home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / utils / sercli.shr / sercli / src / rcs / serial.c,v < prev   
Encoding:
Text File  |  1993-06-16  |  23.7 KB  |  1,047 lines

  1. head    1.6;
  2. access;
  3. symbols
  4.     sercli_v1_10:1.6
  5.     sercli_v1_9:1.4
  6.     sercli_v1_8:1.4
  7.     sercli_v1_7:1.3
  8.     sercli_v1_6:1.2
  9.     sercli_v1_5:1.1;
  10. locks
  11.     rkr:1.6;
  12. comment    @**  @;
  13.  
  14.  
  15. 1.6
  16. date    93.06.16.23.26.42;    author rkr;    state Exp;
  17. branches;
  18. next    1.5;
  19.  
  20. 1.5
  21. date    93.06.10.16.44.13;    author rkr;    state Exp;
  22. branches;
  23. next    1.4;
  24.  
  25. 1.4
  26. date    91.12.20.09.43.24;    author rkr;    state Exp;
  27. branches;
  28. next    1.3;
  29.  
  30. 1.3
  31. date    91.12.10.02.47.50;    author rkr;    state Exp;
  32. branches;
  33. next    1.2;
  34.  
  35. 1.2
  36. date    91.12.02.10.51.08;    author rkr;    state Exp;
  37. branches;
  38. next    1.1;
  39.  
  40. 1.1
  41. date    91.11.28.08.25.04;    author rkr;    state Exp;
  42. branches;
  43. next    ;
  44.  
  45.  
  46. desc
  47. @sercli is a program to permit shell-like interface to the serial port,
  48. while also permitting easy config- and run-time-control over the way the
  49. serial port (or even _which_ serial port) is used.
  50.  
  51. @
  52.  
  53.  
  54. 1.6
  55. log
  56. @Added per-file copyright notice, as suggested by GPL.
  57. @
  58. text
  59. @/*
  60. **  $Source: WB_2.1:homes/rkr/prog/sercli/src/RCS/serial.c,v $
  61. **  $Author: rkr $
  62. **  $Revision: 1.5 $
  63. **  $Locker:  $
  64. **  $State: Exp $
  65. **  $Date: 1993/06/10 16:44:13 $
  66. **
  67. **  sercli (an Amiga .device <-> FIFO interface tool)
  68. **  Copyright (C) 1993  Richard Rauch
  69. **
  70. **  See /doc/sercli.doc and /COPYING for use and distribution license.
  71. **
  72. */
  73.  
  74. /*
  75. **  ToDo:
  76. **
  77. **  **    Change {SER_BUCKET_SIZE} into a variable that can be set by the
  78. **    main program.  (Perhaps only through a special function, though, so
  79. **    that unreasonably small/large values can be filtered...?)
  80. **
  81. **  **    In write_ser(), read_ser_line(), and their asynch counterparts, I
  82. **    do not set the .io_Flags field...  I believe this to be a mistake,
  83. **    although it's not likely to cause much/any _harm_ at the moment.
  84. **
  85. **    I clear IOF_QUICK, at least, when creating the asynch requests
  86. **    (they are cloned from the possibly-already-used {ser_write_req}
  87. **    request, which could very well have the IOF_QUICK bit set...)
  88. **
  89. **  **    Also, a synchronous read_ser() that is non-line-oriented, which
  90. **    reads up to {n} characters into a {buf} would be appropriate.
  91. **
  92. **  **    Time-outable i/o.
  93. **
  94. **  **    Add error-handling (started; need to add for SafeAbortIO()...pro'ly
  95. **    best done by having SafeAbortIO() return whatever AbortIO()
  96. **    returns, and then using that from this context...)
  97. **
  98. **  **    Get rid of the __stkargs declaration of BeginIO().  There should be
  99. **    a '@@' version of the thing in the .lib (but there isn't, right
  100. **    now).
  101. **
  102. **  **    Some names are still not of the form <verb>_<noun>_<modifier>.    The
  103. **    ones that I have not changed are left as they are because the
  104. **    "correct" form is ambiguous.  Arguably, they are all "correct."
  105. **
  106. **  **    When doing a set_ser_soft(), we should "clone" the param-setting
  107. **    request onto all other requests (the global read/write requests and
  108. **    all the ones dynamically allocated).
  109. **
  110. **    Doing a "ser query" while running seems to suggest that the
  111. **    software is getting confused.
  112. **
  113. */
  114.  
  115.  
  116. /*
  117. **  Some includes...
  118. **
  119. */
  120. #include <exec/types.h>
  121.  
  122. #include <clib/alib_protos.h>
  123. #include <clib/exec_protos.h>
  124.  
  125. #include <stdlib.h>
  126. #include <string.h>
  127.  
  128. #include "ser_supp.h"
  129. #include "misc.h"
  130. #include "sercli-config.h"
  131.  
  132.  
  133. #define SER_BUCKET_SIZE 256
  134.  
  135. /*
  136. **  No '@@' entry point for BeginIO.  (frown)
  137. **
  138. */
  139. __stkargs void BeginIO (struct IORequest *ior);
  140.  
  141.  
  142.  
  143.  
  144. /*
  145. **  Some globals...
  146. **
  147. */
  148. IOExtSer *ser_read_req        = 0;
  149. IOExtSer *ser_write_req     = 0;
  150. IOExtSer *ser_status_req    = 0;    /*** uses read port for now ***/
  151.  
  152. List *ser_bucket_list        = 0;
  153. List *ser_writes_p_list     = 0;    /*** SERial WRITES Pending LIST ***/
  154.  
  155. MsgPort *ser_read_reply_port    = 0;
  156. MsgPort *ser_write_reply_port    = 0;
  157.  
  158. ULONG ser_dev            = 0;    /*** flag ***/
  159. ULONG ser_read_reply_mask    = 0;
  160. ULONG ser_write_reply_mask    = 0;
  161.  
  162.  
  163.  
  164. /*
  165. **  Functions needed to access the above structures...
  166. **
  167. */
  168.  
  169. /*
  170. **  Use atexit() to make sure close_ser() is called by exit() before
  171. **  calling this function, as this function relies on auto-cleanup.
  172. **
  173. **  Non-DICE compilers may have a limit to the number of functions to be
  174. **  called through atexit() (Aztec, for instance, says only 16 are valid in
  175. **  their 5.0a docs).
  176. **
  177. **  For the sake of Lattice/SAS (about which I know little), I have set up
  178. **  ser_test.c to call its own clean_up(), which calls close_ser().
  179. **
  180. **  Besides, since ANSI (K&R2, anyway) doesn't say how many functions can
  181. **  be set with atexit(), it's not clear that DICE/Aztec/SAS would all
  182. **  execute multiple atexit()-set-functions in the same order.
  183. **
  184. */
  185. void open_ser (void)
  186. {
  187.     if (ser_dev)    /*** AM ALREADY OPEN??? ***/
  188.     return ();  /*** do nothing, then.. ***/
  189.  
  190.     if (!(ser_read_reply_port = CreatePort (0, 0) ) )
  191.     exit (10);
  192.     if (!(ser_write_reply_port = CreatePort (0, 0) ) )
  193.     exit (10);
  194.  
  195.     ser_read_reply_mask  = 1 << ser_read_reply_port->mp_SigBit;
  196.     ser_write_reply_mask = 1 << ser_write_reply_port->mp_SigBit;
  197.  
  198.     if (!(ser_read_req  = (IOExtSer *) CreateExtIO (ser_read_reply_port, sizeof (IOExtSer) ) ) )
  199.     exit (10);
  200.     if (!(ser_write_req = (IOExtSer *) CreateExtIO (ser_write_reply_port, sizeof (IOExtSer) ) ) )
  201.     exit (10);
  202.     if (!(ser_status_req  = (IOExtSer *) CreateExtIO (ser_read_reply_port, sizeof (IOExtSer) ) ) )
  203.     exit (10);
  204.  
  205.     /*
  206.     **    Actuallly open the thing...
  207.     **
  208.     */
  209.     {
  210.     ser_status_req->io_SerFlags
  211.         = (ser_xon_xoff ? 0 : SERF_XDISABLED)
  212.         | (ser_exclusive ? 0 : SERF_SHARED)
  213.         | (ser_rad_boogie ? SERF_RAD_BOOGIE : 0)
  214.         | (ser_7wire ? SERF_7WIRE : 0)
  215.         |
  216.         (
  217.         ser_parity ?
  218.         (
  219.             1 == ser_parity
  220.             ? (SERF_PARTY_ODD | SERF_PARTY_ON)
  221.             : (2 == ser_parity ? SERF_PARTY_ON : 0)
  222.         ) : 0
  223.         );
  224.  
  225.     if
  226.     (
  227.         OpenDevice
  228.         (
  229.         ser_device_name,
  230.         ser_device_unit,
  231.         (IORequest *) ser_status_req,
  232.         0
  233.         )
  234.     )
  235.         exit (10);
  236.     ser_dev = 1;
  237.     }
  238.  
  239.     CopyMem (ser_status_req, ser_read_req, sizeof (IOExtSer) );
  240.     ser_read_req->IOSer.io_Message.mn_ReplyPort = ser_read_reply_port;
  241.     CopyMem (ser_status_req, ser_write_req, sizeof (IOExtSer) );
  242.     ser_write_req->IOSer.io_Message.mn_ReplyPort = ser_write_reply_port;
  243.  
  244.     NEW (ser_bucket_list);
  245.     if (!ser_bucket_list)
  246.     exit (10);
  247.     NewList (ser_bucket_list);
  248.  
  249.     NEW (ser_writes_p_list);
  250.     if (!ser_writes_p_list)
  251.     exit (10);
  252.     NewList (ser_writes_p_list);
  253.  
  254.     set_ser_soft ();
  255. }
  256.  
  257.  
  258.  
  259. /*
  260. **  Closes down the serial ports, removes message ports & IORequests, frees
  261. **  memory.
  262. **
  263. **  If you spin of other tasks that could access these structures, you may
  264. **  want to wrap a Forbid()/Permit() pair around this function.  Be warned,
  265. **  however, that some of the cleanup (SafeAbortIO(), particularly) can
  266. **  cause this task to Wait(), thus breaking the Forbid().
  267. **
  268. **  (Semaphores might be more apt than Forbid()/Permit()...)
  269. **
  270. */
  271. void close_ser (void)
  272. {
  273.     SafeAbortIO ( (IORequest *) ser_read_req);
  274.     SafeAbortIO ( (IORequest *) ser_write_req);
  275.     SafeAbortIO ( (IORequest *) ser_status_req);
  276.  
  277.     if (ser_writes_p_list)
  278.     {
  279.     ser_bucket_t *b;
  280.     ser_bucket_keeper_t *sbk;
  281.  
  282.     while (sbk = (ser_bucket_keeper_t *) GetHead (ser_writes_p_list) )
  283.     {
  284.         Remove ( (Node *) sbk);
  285.         b = sbk->sbk_alter_ego;
  286.         SafeAbortIO ( (IORequest *) b);
  287.  
  288.         FREEN (b->b_buf, b->b_size);
  289.         FREE (b);
  290.     }
  291.     FREE (ser_writes_p_list);
  292.     ser_writes_p_list = 0;
  293.     }
  294.  
  295.     if (ser_bucket_list)
  296.     {
  297.     ser_bucket_t *b;
  298.     ser_bucket_keeper_t *sbk;
  299.  
  300.     while (sbk = (ser_bucket_keeper_t *) GetHead (ser_bucket_list) )
  301.     {
  302.         Remove ( (Node *) sbk);
  303.         b = sbk->sbk_alter_ego;
  304.  
  305.         FREEN (b->b_buf, b->b_size);
  306.         FREE (b);
  307.     }
  308.  
  309.     FREE (ser_bucket_list);
  310.     ser_bucket_list = 0;
  311.     }
  312.  
  313.  
  314.     if (ser_dev)
  315.     {
  316.     CloseDevice ( (IORequest *) ser_status_req);
  317.     ser_dev = 0;
  318.     }
  319.  
  320.     if (ser_read_reply_port)
  321.     {
  322.     DeletePort (ser_read_reply_port);
  323.     ser_read_reply_mask  = 0;
  324.     ser_read_reply_port  = 0;
  325.     }
  326.     if (ser_write_reply_port)
  327.     {
  328.     DeletePort (ser_write_reply_port);
  329.     ser_write_reply_mask = 0;
  330.     ser_write_reply_port = 0;
  331.     }
  332.  
  333.     if (ser_status_req)
  334.     {
  335.     DeleteExtIO ( (IORequest *) ser_status_req);
  336.     ser_status_req    = 0;
  337.     }
  338.     if (ser_read_req)
  339.     {
  340.     DeleteExtIO ( (IORequest *) ser_read_req);
  341.     ser_read_req  = 0;
  342.     }
  343.     if (ser_write_req)
  344.     {
  345.     DeleteExtIO ( (IORequest *) ser_write_req);
  346.     ser_write_req = 0;
  347.     }
  348. }
  349.  
  350.  
  351.  
  352. /*
  353. **  The strlen() isn't needed.  The built-in serial.device (and probably
  354. **  all 3rd party .devices for other serial ports) supports a ~0
  355. **  {io_Length} to tell the .device to look for an ASCII nul to signal
  356. **  end-of-buf.
  357. **
  358. **  However, I don't see that it could affect performance much/at all one
  359. **  way or the other...  What I do might even help performance, depending
  360. **  on how the CMD_READ is implemented on the .device.
  361. **
  362. **  And this is more `secure' against changes, since write_ser() is a black
  363. **  box, with a clear entrance and exit.  Any changes to write_ser() will
  364. **  be `inherited' into write_ser_str().
  365. **
  366. */
  367. ULONG write_ser_str (char *str)
  368. {
  369.     return (write_ser (str, strlen (str) ) );
  370. }
  371.  
  372.  
  373.  
  374. /*
  375. **  Writes {len} bytes of {str} to the .device opened with ser_open().
  376. **
  377. **  Returns actual number of bytes written.
  378. **
  379. **  If an error occurs, handle_error() will be called (if the user has not
  380. **  installed an error handler, errors will be ignored).
  381. **
  382. */
  383. ULONG write_ser (char *str, ULONG len)
  384. {
  385.     ser_write_req->IOSer.io_Command = CMD_WRITE;
  386.     ser_write_req->IOSer.io_Length  = len;
  387.     ser_write_req->IOSer.io_Data    = str;
  388.  
  389.     if (DoIO ( (IO_Request *) ser_write_req) )
  390.     handle_error (error_type_serial, ser_write_req);
  391.  
  392.     return (ser_write_req->IOSer.io_Actual);
  393. }
  394.  
  395.  
  396.  
  397. /*
  398. **  Not set:
  399. **  {
  400. **    io_CtlChar,
  401. **    io_RBufLen,
  402. **    io_extFlags,
  403. **    io_BrkTime,
  404. **    io_TermArray,
  405. **    io_status,    // izzis settable at all?
  406. **  }
  407. **
  408. **  Returns {!ser_write_req->IOSer.io_Error} (1 == ERROR, 0 == Safe).
  409. **
  410. */
  411. ULONG set_ser_soft (void)
  412. {
  413.     SafeAbortIO ( (IORequest *) ser_read_req);
  414.     SafeAbortIO ( (IORequest *) ser_write_req);
  415.     SafeAbortIO ( (IORequest *) ser_status_req);
  416.  
  417.     /*
  418.     **    Put this in its own function & re-use for close_ser()...
  419.     **
  420.     */
  421.     if (ser_writes_p_list)
  422.     {
  423.     ser_bucket_t *b;
  424.     ser_bucket_keeper_t *sbk;
  425.  
  426.     while (sbk = (ser_bucket_keeper_t *) GetHead (ser_writes_p_list) )
  427.     {
  428.         Remove ( (Node *) sbk);
  429.         b = sbk->sbk_alter_ego;
  430.         SafeAbortIO ( (IORequest *) b);
  431.  
  432.         AddTail (ser_bucket_list, (Node *) sbk);    /*** ?? ***/
  433.     }
  434.     }
  435.  
  436.     ser_write_req->IOSer.io_Command = SDCMD_SETPARAMS;
  437.     ser_write_req->io_Baud    = ser_bps;
  438.     ser_write_req->io_ReadLen    = ser_read_bits;
  439.     ser_write_req->io_WriteLen    = ser_write_bits;
  440.     ser_write_req->io_StopBits    = ser_stop_bits;
  441.  
  442.     ser_write_req->io_SerFlags
  443.     = (ser_xon_xoff ? 0 : SERF_XDISABLED)
  444.     | (ser_exclusive ? 0 : SERF_SHARED)
  445.     | (ser_rad_boogie ? SERF_RAD_BOOGIE : 0)
  446.     | (ser_7wire ? SERF_7WIRE : 0)
  447.     |
  448.     (
  449.         ser_parity ?
  450.         (
  451.         1 == ser_parity
  452.         ? (SERF_PARTY_ODD | SERF_PARTY_ON)
  453.         : (2 == ser_parity ? SERF_PARTY_ON : 0)
  454.         ) : 0
  455.     );
  456.  
  457.     /*
  458.     **    I don't s'pose it's necessary to "update" any of the other IO
  459.     **    requests...  We'll see, soon enough!  *grin*
  460.     **
  461.     */
  462.     if (DoIO ( (IORequest *) ser_write_req) )
  463.     handle_error (error_type_serial, ser_write_req);
  464.  
  465.     return (!ser_write_req->IOSer.io_Error);
  466. }
  467.  
  468.  
  469.  
  470. /*
  471. **  Get a line of data up to and include '\n' (or {max_len} bytes,
  472. **  whichever happens first).
  473. **
  474. **  A terminating null is alaways applied.
  475. **
  476. **  The {buf} ptr is returned.
  477. **
  478. **  Loosely speaking, this behaves like fgets(), only this works with a
  479. **  serial port.
  480. **
  481. **
  482. **  NOTES:
  483. **    Unlike fgets(), read_ser_line() will always return the {buf},
  484. **    regardless of any IO errors.
  485. **
  486. */
  487. char *read_ser_line (char *buf, ULONG max_len)
  488. {
  489.     int c;
  490.     ULONG len = 0;
  491.  
  492.     if (!max_len)
  493.     return (0);
  494.     do
  495.     {
  496.     ser_read_req->IOSer.io_Command = CMD_READ;
  497.     ser_read_req->IOSer.io_Length  = 1;
  498.     ser_read_req->IOSer.io_Data    = &(buf [len] );
  499.     if (DoIO ( (IORequest *) ser_read_req) )
  500.         handle_error (error_type_serial, ser_read_req);
  501.  
  502.     c = buf [len];
  503.     write_ser (&(buf [len] ), 1);
  504.     ++len;
  505.     }
  506.     while ( (c != '\n') && (len < (max_len - 1) ) );
  507.  
  508.     buf [len] = 0;
  509.     return (buf);
  510. }
  511.  
  512.  
  513.  
  514. /*
  515. **  Initiate an asynch write to the serial port of {size} bytes from {buf}.
  516. **
  517. **  This could actually be made a little more efficient by taking advantage
  518. **  of the fact that everything in our {ser_bucket_list} is a recycled
  519. **  {CMD_WRITE} request for the serial port.
  520. **
  521. **  (For that matter, I could take advantage of the serial port's
  522. **  non-destructive handling of i/o requests elsewhere, as well...)
  523. **
  524. **
  525. **  NOTES:
  526. **  **    If you send enough data through write_ser_asynch(), you could
  527. **    conceivably run out of memory.    write_ser_asynch() would then
  528. **    exit()...
  529. **
  530. **    This should be a clean, graceful behavior (haven't tested this, yet
  531. **    *grin*), but it's not a very robust way to handle memory; a
  532. **    'better' solution would be to wait a while, and reattempt the
  533. **    allocation, and/or give some previous write requests a chance to
  534. **    return..
  535. **
  536. **  **    Put a 'faucet' on the front end of this function if you will be
  537. **    sending long continuous streams of data (esp. if you want to
  538. **    error-check!) or else use the synchronous i/o write_ser(), above.
  539. **    Otherwise, you will end up copying your outbound data into buffers
  540. **    allocated by write_ser_async(); even though you probably won't run
  541. **    out of memory, an XPR (say) would probably then exit having 'sent'
  542. **    the entire file to the serial port, without mishap...  This won't
  543. **    be a problem for protocols like XModem that require continuous
  544. **    re-synching between sender/receiver.
  545. **
  546. **  **    IOF_QUICK is used, so this function may not _really_ be asynch.
  547. **    Depends on the serial.device software/hardware, and the current
  548. **    state of things.
  549. **
  550. **    If this gets to be a problem, a new function can be split off.
  551. **    However, since I (presently) don't need to worry about when a write
  552. **    request completes, this suits me better.
  553. **
  554. **    Use SendIO() if "real" asynch i/o is required.
  555. **
  556. **    Or, perhaps we could signal ourselves, so that if the caller does a
  557. **    Wait(), the effect will be as if our task switched out, the .device
  558. **    satisfied the i/o and returned the message, and we woke up again...
  559. **
  560. */
  561. void write_ser_asynch (char *buf, ULONG size)
  562. {
  563.     ULONG copy_size;
  564.  
  565.     for (;size ; size -= copy_size, buf += copy_size)
  566.     {
  567.     IOExtSer *ior;
  568.     ser_bucket_t *b;
  569.     ser_bucket_keeper_t *sbk;
  570.  
  571.     if (sbk = (ser_bucket_keeper_t *) GetHead (ser_bucket_list) )
  572.     {
  573.         Remove ( (Node *) sbk);
  574.         b = sbk->sbk_alter_ego;
  575.         copy_size = b->b_size;
  576.     }
  577.     else
  578.     {
  579.         NEW (b);
  580.         if (!b)
  581.         {
  582.         exit (10);
  583.         }
  584.         copy_size = b->b_size = SER_BUCKET_SIZE;
  585.         NEWN (b->b_buf, b->b_size);
  586.         if (!b->b_buf)
  587.         {
  588.         FREE (b);
  589.         exit (10);
  590.         }
  591.         b->b_self = b;
  592.         sbk = &(b->b_link);
  593.     }
  594.     ior = &(b->b_ior);
  595.     copy_size = MIN (copy_size, size);
  596.  
  597.     CopyMem (ser_write_req, ior, sizeof (IOExtSer) );
  598.     CopyMem (buf, b->b_buf, copy_size);
  599.  
  600.     /*
  601.     **  Pro'ly not all of these need to be reset (any except {io_Length}
  602.     **  ({io_Data} could be set when the buffer is allocated?)...
  603.     **
  604.     */
  605.     ior->IOSer.io_Flags            = IOF_QUICK;
  606.     ior->IOSer.io_Message.mn_ReplyPort  = ser_write_reply_port;
  607.     ior->IOSer.io_Command            = CMD_WRITE;
  608.     ior->IOSer.io_Length            = copy_size;
  609.     ior->IOSer.io_Data            = b->b_buf;
  610.  
  611.     BeginIO ( (IORequest *) ior);
  612.     if (!(ior->IOSer.io_Flags & IOF_QUICK) )
  613.         AddTail (ser_writes_p_list, (Node *) sbk);
  614.     else
  615.     {
  616.         AddTail (ser_bucket_list, (Node *) sbk);
  617.         ior->IOSer.io_Flags = 0;
  618.     }
  619.     }
  620. }
  621.  
  622.  
  623.  
  624. /*
  625. **  Remove replies to write_ser_asynch(), above, and stash the
  626. **  {ser_bucket_t} buffers in another List.
  627. **
  628. **  Call this when signaled with {ser_write_reply_mask}.
  629. **
  630. **  (Question: Is it worth generalizing to include Read replies, as well?
  631. **  The internal serial.device can only handle one read request at a
  632. **  time...  Keeping it with no args and only one list is simpler.)
  633. **
  634. */
  635. void clear_write_replies (void)
  636. {
  637.     ser_bucket_t *b;
  638.     ser_bucket_keeper_t *sbk;
  639.  
  640.     while (b = (ser_bucket_t *) GetMsg (ser_write_reply_port) )
  641.     {
  642.     if (b->b_ior.IOSer.io_Error)
  643.         handle_error (error_type_serial, &(b->b_ior) );
  644.  
  645.     /*
  646.     **  REDUNDANT???
  647.     **  Remove (&(b->b_link) );
  648.     **
  649.     */
  650.  
  651.     sbk = &(b->b_link);
  652.     Remove (&(sbk->sbk_link) );
  653.  
  654.     AddTail (ser_bucket_list, (Node *) sbk);
  655.     }
  656. }
  657.  
  658.  
  659.  
  660. /*
  661. **  Initiate an asynch read from the serial port of up to {size} bytes,
  662. **  or 1 byte if the serial port is empty.
  663. **
  664. **  Caller must examine IOSer.io_Actual when it eventually comes back in
  665. **  order to determine how many bytes were read.
  666. **
  667. */
  668. void read_ser_asynch (char *buf, ULONG max)
  669. {
  670.     ULONG read_len;
  671.  
  672.     /*
  673.     **    Old stuff????  Why not BeginIO(), below, rather than SendIO()?
  674.     **        (Because the caller may Wait() on a signal mask including that
  675.     **        for this IO operation...  See NOTES for write_ser_async()...)
  676.     **
  677.     **    ser_status_req->IOSer.io_Command = SDCMD_QUERY;
  678.     **    ser_status_req->IOSer.io_Flags     = IOF_QUICK;
  679.     **    BeginIO ( (IORequest *) ser_status_req);
  680.     **
  681.     **    if (!(ser_status_req->IOSer.io_Flags & IOF_QUICK) )
  682.     **        WaitIO ( (IORequest *) ser_status_req);
  683.     **
  684.     */
  685.  
  686.     read_len = ser_chars_pending ();
  687.  
  688.     ser_read_req->IOSer.io_Command = CMD_READ;
  689.     ser_read_req->IOSer.io_Length  = MIN (max, MAX (1, read_len) );
  690.     ser_read_req->IOSer.io_Data    = buf;
  691.     SendIO ( (IORequest *) ser_read_req);
  692. }
  693.  
  694.  
  695.  
  696. /*
  697. **  Find out how many characters are pending for read from the serial
  698. **  device.
  699. **
  700. **  {SDCMD_QUERY} "always succeeds," say autodocs...
  701. **
  702. */
  703. ULONG ser_chars_pending (void)
  704. {
  705.     query_ser ();
  706.     return (ser_status_req->IOSer.io_Actual);
  707. }
  708.  
  709.  
  710.  
  711. /*
  712. **  Query the state of the serial port.  Presently, returns an {IOExtSer *}.
  713. **
  714. */
  715. IOExtSer *query_ser (void)
  716. {
  717.     ser_status_req->IOSer.io_Command = SDCMD_QUERY;
  718.     DoIO ( (IORequest *) ser_status_req);
  719.     return (ser_status_req);
  720. }
  721.  
  722. @
  723.  
  724.  
  725. 1.5
  726. log
  727. @Fixed a little problem w/setting params (confusion over which i/o
  728. request was being used); for that matter, CREATED a new i/o request
  729. (ser_status_request) to handle setting/getting serial status -- it
  730. shares ser_read_req's message port.
  731. @
  732. text
  733. @d2 1
  734. a2 1
  735. **  $Source: WB_2.1:ho/rcs/serial.c,v $
  736. d4 1
  737. a4 1
  738. **  $Revision: 1.4 $
  739. d7 1
  740. a7 1
  741. **  $Date: 1991/12/20 09:43:24 $
  742. d9 5
  743. a25 3
  744. **
  745. **    (????  {io_Flags} is private for Exec and the .device, I think, so
  746. **    should _not_ be set...)
  747. @
  748.  
  749.  
  750. 1.4
  751. log
  752. @*** empty log message ***
  753. @
  754. text
  755. @d2 1
  756. a2 1
  757. **  $Source: Workbench:personal/rkr/prog/sercli/src/rcs/serial.c,v $
  758. d4 2
  759. a5 2
  760. **  $Revision: 1.3 $
  761. **  $Locker: rkr $
  762. d7 1
  763. a7 1
  764. **  $Date: 91/12/10 02:47:50 $
  765. d90 1
  766. d142 2
  767. d150 1
  768. a150 1
  769.     ser_read_req->io_SerFlags
  770. d171 1
  771. a171 1
  772.         (IORequest *) ser_read_req,
  773. d179 3
  774. a181 1
  775.     CopyMem (ser_read_req, ser_write_req, sizeof (IOExtSer) );
  776. d215 1
  777. d256 1
  778. a256 1
  779.     CloseDevice ( (IORequest *) ser_read_req);
  780. d273 5
  781. d355 1
  782. d382 1
  783. a382 1
  784.     ser_read_req->io_SerFlags
  785. d617 3
  786. a619 3
  787.     **    ser_read_req->IOSer.io_Command = SDCMD_QUERY;
  788.     **    ser_read_req->IOSer.io_Flags   = IOF_QUICK;
  789.     **    BeginIO ( (IORequest *) ser_read_req);
  790. d621 2
  791. a622 2
  792.     **    if (!(ser_read_req->IOSer.io_Flags & IOF_QUICK) )
  793.     **        WaitIO ( (IORequest *) ser_read_req);
  794. d646 1
  795. a646 1
  796.     return (ser_read_req->IOSer.io_Actual);
  797. d657 3
  798. a659 3
  799.     ser_read_req->IOSer.io_Command = SDCMD_QUERY;
  800.     DoIO ( (IORequest *) ser_read_req);
  801.     return (ser_read_req);
  802. @
  803.  
  804.  
  805. 1.3
  806. log
  807. @**  Added query_ser().
  808.  
  809. **  write_ser_asynch() used to set {IOF_QUICK}, but did not clear it if it
  810.     was still set after BeginIO().
  811.  
  812.     Also, I was using |= and &= to turn {IOF_QUICK} on & off.  I now just
  813.     use {... = IOF_QUICK} and {... = 0}, respectively.
  814.  
  815.  
  816. @
  817. text
  818. @d4 1
  819. a4 1
  820. **  $Revision: 1.2 $
  821. d7 1
  822. a7 1
  823. **  $Date: 91/12/02 10:51:08 $
  824. @
  825.  
  826.  
  827. 1.2
  828. log
  829. @**  Changed ser_soft_set() to set_ser_soft() (<verb>_<noun>_<modifier>).
  830.  
  831.  
  832. **  Made {ser_bucket_from_list_t} into {ser_bucket_keeper}, which is a
  833.     little more descriptive of what's going on (though not ideal).  Changed
  834.     internal structure member names accordingly.
  835.  
  836.  
  837. **  Change typedef names of Amiga OS structs (in ser_supp.h) back to names
  838.     w/o underscores.
  839.  
  840.  
  841. **  Cause the serial error-handler to do a hex-dump of the data it has been
  842.     passed...
  843.  
  844.  
  845. **  _Use_ the error-handler...
  846.  
  847.  
  848. **  Use IOF_QUICK in write_ser_asynch().  Don't use it in
  849.     read_ser_asynch().
  850.  
  851.     The assumption being that we don't care when (or presently even if)
  852.     output finishes; we only want to be told about input completion.  Note
  853.     that, when QUICK io happens, we should (esp. if done for read events)
  854.     either put the message to our own reply port ourselves...
  855.     Alternatively, but theoretically more troublesome (it takes some
  856.     construing, but is not unimaginable), QUICK write events may be tossed
  857.     into our {ser_bucket_list}, after signalling the Task indicated by the
  858.     io request's message port.
  859. @
  860. text
  861. @d7 1
  862. a7 1
  863. **  $Date: 91/12/02 10:44:44 $
  864. d46 7
  865. d161 1
  866. d533 1
  867. a533 1
  868.     ior->IOSer.io_Flags            |= IOF_QUICK;
  869. d540 4
  870. a543 1
  871.     if (ior->IOSer.io_Flags & IOF_QUICK)
  872. d545 2
  873. a546 2
  874.     else
  875.         AddTail (ser_writes_p_list, (Node *) sbk);
  876. a627 3
  877. **  (Rename to serial_query(), since {ser_read_req} has the results of a
  878. **  {SDCMD_QUERY} command...?)
  879. **
  880. d633 12
  881. d647 1
  882. a647 1
  883.     return (ser_read_req->IOSer.io_Actual);
  884. d649 1
  885. @
  886.  
  887.  
  888. 1.1
  889. log
  890. @Initial revision
  891. @
  892. text
  893. @d2 6
  894. a7 6
  895. **  $Source$
  896. **  $Author$
  897. **  $Revision$
  898. **  $Locker$
  899. **  $State$
  900. **  $Date$
  901. d42 4
  902. d81 2
  903. a82 2
  904. IO_Ext_Ser *ser_read_req    = 0;
  905. IO_Ext_Ser *ser_write_req    = 0;
  906. d87 2
  907. a88 2
  908. Msg_Port *ser_read_reply_port    = 0;
  909. Msg_Port *ser_write_reply_port    = 0;
  910. d130 1
  911. a130 1
  912.     if (!(ser_read_req  = (IO_Ext_Ser *) CreateExtIO (ser_read_reply_port, sizeof (IO_Ext_Ser) ) ) )
  913. d132 1
  914. a132 1
  915.     if (!(ser_write_req = (IO_Ext_Ser *) CreateExtIO (ser_write_reply_port, sizeof (IO_Ext_Ser) ) ) )
  916. d160 1
  917. a160 1
  918.         (IO_Request *) ser_read_req,
  919. d168 1
  920. a168 1
  921.     CopyMem (ser_read_req, ser_write_req, sizeof (IO_Ext_Ser) );
  922. d181 1
  923. a181 1
  924.     ser_soft_set ();
  925. d200 2
  926. a201 2
  927.     SafeAbortIO ( (IO_Request *) ser_read_req);
  928.     SafeAbortIO ( (IO_Request *) ser_write_req);
  929. d206 1
  930. a206 1
  931.     ser_bucket_from_list_t *bfl;
  932. d208 1
  933. a208 1
  934.     while (bfl = (ser_bucket_from_list_t *) GetHead (ser_writes_p_list) )
  935. d210 3
  936. a212 3
  937.         Remove ( (Node *) bfl);
  938.         b = bfl->bfl_alter_ego;
  939.         SafeAbortIO ( (IO_Request *) b);
  940. d224 1
  941. a224 1
  942.     ser_bucket_from_list_t *bfl;
  943. d226 1
  944. a226 1
  945.     while (bfl = (ser_bucket_from_list_t *) GetHead (ser_bucket_list) )
  946. d228 2
  947. a229 2
  948.         Remove ( (Node *) bfl);
  949.         b = bfl->bfl_alter_ego;
  950. d242 1
  951. a242 1
  952.     CloseDevice ( (IO_Request *) ser_read_req);
  953. d261 1
  954. a261 1
  955.     DeleteExtIO ( (IO_Request *) ser_read_req);
  956. d266 1
  957. a266 1
  958.     DeleteExtIO ( (IO_Request *) ser_write_req);
  959. d332 1
  960. a332 1
  961. ULONG ser_soft_set (void)
  962. d334 2
  963. a335 2
  964.     SafeAbortIO ( (IO_Request *) ser_read_req);
  965.     SafeAbortIO ( (IO_Request *) ser_write_req);
  966. d344 1
  967. a344 1
  968.     ser_bucket_from_list_t *bfl;
  969. d346 1
  970. a346 1
  971.     while (bfl = (ser_bucket_from_list_t *) GetHead (ser_writes_p_list) )
  972. d348 3
  973. a350 3
  974.         Remove ( (Node *) bfl);
  975.         b = bfl->bfl_alter_ego;
  976.         SafeAbortIO ( (IO_Request *) b);
  977. d352 1
  978. a352 1
  979.         AddTail (ser_bucket_list, (Node *) bfl);    /*** ?? ***/
  980. d382 1
  981. a382 1
  982.     if (DoIO ( (IO_Request *) ser_write_req) )
  983. d419 1
  984. a419 1
  985.     if (DoIO ( (IO_Request *) ser_read_req) )
  986. d445 2
  987. a446 2
  988. **  NOTE:
  989. **    If you send enough data through write_ser_asynch(), you could
  990. d456 1
  991. a456 1
  992. **    Put a 'faucet' on the front end of this function if you will be
  993. d458 1
  994. a458 1
  995. **    error-check!) or else use the syncrounous i/o write_ser(), above.
  996. d466 14
  997. d487 1
  998. a487 1
  999.     IO_Ext_Ser *ior;
  1000. d489 1
  1001. a489 1
  1002.     ser_bucket_from_list_t *bfl;
  1003. d491 1
  1004. a491 1
  1005.     if (bfl = (ser_bucket_from_list_t *) GetHead (ser_bucket_list) )
  1006. d493 2
  1007. a494 2
  1008.         Remove ( (Node *) bfl);
  1009.         b = bfl->bfl_alter_ego;
  1010. d512 1
  1011. a512 1
  1012.         bfl = &(b->b_link);
  1013. d517 1
  1014. a517 1
  1015.     CopyMem (ser_write_req, ior, sizeof (IO_Ext_Ser) );
  1016. d525 1
  1017. a525 1
  1018.     ior->IOSer.io_Flags            &= ~IOF_QUICK;
  1019. d531 5
  1020. a535 2
  1021.     BeginIO ( (IO_Request *) ior);
  1022.     AddTail (ser_writes_p_list, (Node *) bfl);
  1023. d555 1
  1024. a555 1
  1025.     ser_bucket_from_list_t *bfl;
  1026. d568 2
  1027. a569 2
  1028.     bfl = &(b->b_link);
  1029.     Remove (&(bfl->bfl_link) );
  1030. d571 1
  1031. a571 1
  1032.     AddTail (ser_bucket_list, (Node *) bfl);
  1033. d591 2
  1034. d596 1
  1035. a596 1
  1036.     **    BeginIO ( (IO_Request *) ser_read_req);
  1037. d599 1
  1038. a599 1
  1039.     **        WaitIO ( (IO_Request *) ser_read_req);
  1040. d608 1
  1041. a608 1
  1042.     SendIO ( (IO_Request *) ser_read_req);
  1043. d626 1
  1044. a626 1
  1045.     DoIO ( (IO_Request *) ser_read_req);
  1046. @
  1047.