home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / System / MorphOS / Developer / emulexamples / device / serial / serial.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-02  |  29.2 KB  |  1,222 lines

  1. /*
  2.  *  serial.c
  3.  *
  4.  *  Adaptation of Iain Barclay's New8N1 for MorphOS.
  5.  *
  6.  *  Copyright 2000 by E. Lesueur.
  7.  */
  8.  
  9. #define EMUL_NOQUICKMODE    1
  10. #define DEVICES_SERIAL_H_OBSOLETE
  11. #include <exec/lists.h>
  12. #include <exec/memory.h>
  13. #include <exec/execbase.h>
  14. #include <exec/io.h>
  15. #include <exec/ports.h>
  16. #include <exec/errors.h>
  17. #include <exec/resident.h>
  18. #include <exec/initializers.h>
  19. #include <intuition/preferences.h>
  20. #include <devices/timer.h>
  21. #include <devices/serial.h>
  22. #include <hardware/cia.h>
  23. #include <hardware/adkbits.h>
  24. #include <hardware/intbits.h>
  25. #include <hardware/custom.h>
  26. #include <resources/misc.h>
  27. #include <proto/exec.h>
  28. #include <proto/intuition.h>
  29. #include <proto/misc.h>
  30.  
  31.  
  32. #if 0
  33.     void dprintf(const char *,...);
  34. #   define KPRINTF(l,x) do { if (l >= 4) { dprintf("Line %ld: ", __LINE__); dprintf x;} } while(0)
  35.     int tbes;
  36.     int written_chars;
  37.     int caused_tbes;
  38. #   define DB(x)    x
  39. #else
  40. #   define KPRINTF(l,x) ((void)0)
  41. #   define DB(x)
  42. #endif
  43.  
  44. #define ciaa (*(volatile struct CIA *)0xbfe001)
  45. #define ciab (*(volatile struct CIA *)0xbfd000)
  46. #define custom (*(volatile struct Custom *)0xdff000)
  47.  
  48. /*#define NEWCODE  1*/
  49. #define SETDSR   0
  50. #define NCOMM    0
  51. #define NEGCHECK 1
  52. #define EOFCODE  1
  53.  
  54. #ifndef DEVNAME
  55. #   define DEVNAME             "serial.device"
  56. #endif
  57. #define VERSION             43
  58. #define REVISION            6
  59. #define VERSION_STR         "43"
  60. #define REVISION_STR        "6"
  61. #define DATE                "22.7.2000"
  62.  
  63. #define PRTMASK (CIAF_PRTRPOUT | CIAF_PRTRBUSY)
  64. #define STR(x)  #x
  65.  
  66. struct MyDevice {
  67.     struct Library      vb_Library;
  68.     UWORD               vb_Pad;
  69.     ULONG               vb_SaveDDRA;
  70.     ULONG               vb_SavePRA;
  71.     APTR                vb_OldLevel1;
  72.     APTR                vb_OldLevel5;
  73.     BPTR                vb_SegList;
  74.     ULONG               vb_DefBaud;
  75.     ULONG               vb_DefRBufLen;
  76.     UBYTE              *vb_CurRBuf;
  77.     ULONG               vb_CurRBufLen;
  78.     ULONG               vb_CurBaud;
  79.     ULONG               vb_SerFlags;
  80.     ULONG               vb_Initialized;
  81.     struct Interrupt   *vb_oldRBFInt;
  82.     struct Interrupt   *vb_oldTBEInt;
  83.     /*struct timerequest *timerReq;*/
  84. };
  85.  
  86. static void timerRtn(void);
  87.  
  88. static const struct EmulLibEntry _gate_timer = {
  89.     TRAP_LIB, 0, timerRtn
  90. };
  91. static struct Interrupt timerInterrupt = {
  92.     {NULL, NULL, NT_INTERRUPT, 0, DEVNAME },
  93.     NULL,
  94.     (APTR)&_gate_timer
  95. };
  96. static struct MsgPort timerPort = {
  97.     {NULL, NULL, NT_MSGPORT, 0, NULL},
  98.     PA_SOFTINT, 0, (APTR)&timerInterrupt,
  99.     {(APTR)&timerPort.mp_MsgList.lh_Tail, NULL, (APTR)&timerPort.mp_MsgList}
  100. };
  101. static struct timerequest timerReq = {
  102.     {{{NULL, NULL, NT_MESSAGE, 0, NULL},
  103.     &timerPort, sizeof(timerReq)}, NULL, NULL,
  104.     TR_ADDREQUEST, 0, 0},
  105.     {0, 0}
  106. };
  107.  
  108. static volatile BOOL Overrun;
  109. static BOOL Handshake;
  110. static volatile int disableRead = -1;
  111.  
  112. static UBYTE *i_BufPtr;
  113. static UBYTE *i_BufIn;
  114. static UBYTE *i_BufOut;
  115. static UBYTE *i_BufEnd;
  116. static volatile LONG  i_InCnt;
  117. static volatile LONG  i_Thresh;
  118.  
  119. static struct IOExtSer *cr_IOReq;
  120. static UBYTE *cr_OutPtr;
  121. static LONG cr_Length;
  122. static struct MinList readQ = {
  123.     (APTR)&readQ.mlh_Tail, NULL, (APTR)&readQ
  124. };
  125.  
  126. static struct IOExtSer *cw_IOReq;
  127. static UBYTE *cw_Buffer;
  128. static LONG cw_Length;
  129. static struct MinList writeQ = {
  130.     (APTR)&writeQ.mlh_Tail, NULL, (APTR)&writeQ
  131. };
  132.  
  133. struct ExecBase *SysBase;
  134. struct Node *MiscBase;
  135. struct IntuitionBase *IntuitionBase;
  136.  
  137.  
  138. static struct MyDevice *devInit(struct MyDevice *base,
  139.                 BPTR seglist,
  140.                 struct ExecBase *sysbase);
  141. static struct MyDevice *devOpen(void);
  142. static BPTR devExpunge(void);
  143. static BPTR devClose(void);
  144. static void devBeginIO(void);
  145. static void devAbortIO(void);
  146.  
  147. static void freeBuf(struct MyDevice *base);
  148. static ULONG cmdClear(struct MyDevice *base);
  149. static ULONG cmdInvalid(struct IOExtSer *ioreq);
  150. static ULONG internalReset(struct MyDevice *base, ULONG buflen, ULONG baud);
  151. static ULONG cmdReset(struct MyDevice *base, struct IOExtSer *ioreq);
  152. static void internalFlush(struct MinList *queue);
  153. static ULONG cmdFlush(struct IOExtSer *ioreq);
  154. static ULONG cmdRead(struct IOExtSer *ioreq);
  155. static void queueWrite(struct IOExtSer *ioreq);
  156. static ULONG cmdWrite(struct IOExtSer *ioreq);
  157. static ULONG sdcmdBreak(struct IOExtSer *ioreq);
  158. static ULONG sdcmdQuery(struct IOExtSer *ioreq);
  159. static ULONG sdcmdSetParams(struct MyDevice *base, struct IOExtSer *ioreq);
  160. static void timerRtn(void);
  161. static ULONG copyData(struct IOExtSer *ioreq);
  162. static void level1(void);
  163. static void level2(void);
  164. static void level5(void);
  165.  
  166. static int devReserved(void) {
  167.     return 0;
  168. }
  169.  
  170. static const ULONG FuncTable[] = {
  171.     FUNCARRAY_32BIT_NATIVE,
  172.     (ULONG)devOpen,
  173.     (ULONG)devClose,
  174.     (ULONG)devExpunge,
  175.     (ULONG)devReserved,
  176.     (ULONG)devBeginIO,
  177.     (ULONG)devAbortIO,
  178.     ~0
  179. };
  180.  
  181. const struct {
  182.     ULONG  LibSize;
  183.     const void  *FuncTable;
  184.     const void  *DataTable;
  185.     void (*InitFunc)(void);
  186. } init = {
  187.     sizeof(struct MyDevice),
  188.     FuncTable,
  189.     NULL,
  190.     (void (*)())devInit
  191. };
  192.  
  193. const struct Resident ROMTag = {
  194.     RTC_MATCHWORD,
  195.     (APTR)&ROMTag,
  196.     (APTR)(&ROMTag + 1),
  197.     RTF_PPC | RTF_AUTOINIT,
  198.     VERSION,
  199.     NT_DEVICE,
  200.     0,
  201.     DEVNAME,
  202.     DEVNAME " " VERSION_STR "." REVISION_STR " (" DATE ")\r\n",
  203.     (APTR)&init
  204. };
  205.  
  206. const char vers[] = "$VER: " DEVNAME " " VERSION_STR "." REVISION_STR " (" DATE ")";
  207.  
  208. ULONG __amigappc__ = 1;
  209.  
  210. static const struct EmulLibEntry _gate_level2 = {
  211.     TRAP_LIBSRNR, 0, (void (*)())level2
  212. };
  213.  
  214. static struct Interrupt VBInterrupt = {
  215.     {NULL, NULL, NT_INTERRUPT, 0, DEVNAME },
  216.     &readQ,
  217.     (APTR)&_gate_level2
  218. };
  219.  
  220. static const struct EmulLibEntry _gate_level5 = {
  221.     TRAP_LIBNR, 0, (void (*)())level5
  222. };
  223.  
  224. static struct Interrupt RBFInterrupt = {
  225.     {NULL, NULL, NT_INTERRUPT, 0, DEVNAME },
  226.     NULL,
  227.     (APTR)&_gate_level5
  228. };
  229.  
  230. static const struct EmulLibEntry _gate_level1 = {
  231.     TRAP_LIBNR, 0, (void (*)())level1
  232. };
  233.  
  234. static struct Interrupt TBEInterrupt = {
  235.     {NULL, NULL, NT_INTERRUPT, 0, DEVNAME },
  236.     NULL,
  237.     (APTR)&_gate_level1
  238. };
  239.  
  240.  
  241. static struct MyDevice *devInit(struct MyDevice *base,
  242.                 BPTR seglist,
  243.                 struct ExecBase *sysbase) {
  244.     KPRINTF(10, ("devInit(%lx, %lx, %lx)\n", base, seglist, sysbase));
  245.     SysBase = sysbase;
  246.     base->vb_SegList = seglist;
  247.     base->vb_Initialized = 0;
  248.     base->vb_CurRBuf = NULL;
  249.     base->vb_CurRBufLen = 0;
  250.     KPRINTF(10, ("openCnt = %ld\n", base->vb_Library.lib_OpenCnt));
  251.     return base;
  252. }
  253.  
  254.  
  255. static int allocResource(struct MyDevice *base, int bits) {
  256.     UBYTE *user;
  257.     if (user = AllocMiscResource(bits, (UBYTE *)DEVNAME)) {
  258.     struct Device *dev = (APTR)FindName(&SysBase->DeviceList, user);
  259.     if (dev) {
  260.         RemDevice(dev);
  261.         user = AllocMiscResource(bits, DEVNAME);
  262.     }
  263.     }
  264.     return user == NULL;
  265. }
  266.  
  267.  
  268.  
  269. static struct MyDevice *devOpen(void) {
  270.     long unit = REG_D0;
  271.     struct IOExtSer *ioreq = (APTR)REG_A1;
  272.     struct MyDevice *base = (APTR)REG_A6;
  273.     LONG err;
  274.     struct MyDevice *ret = NULL;
  275.  
  276.     KPRINTF(10, ("devOpen(%lx, %lx)\n", ioreq, base));
  277.  
  278.     ++base->vb_Library.lib_OpenCnt;
  279.     base->vb_Library.lib_Flags &= ~LIBF_DELEXP;
  280.  
  281.     KPRINTF(10, ("openCnt = %ld\n", base->vb_Library.lib_OpenCnt));
  282.  
  283.     if (ioreq->IOSer.io_Message.mn_Length < sizeof(struct IOExtSer)) {
  284.     err = IOERR_BADLENGTH;
  285.     KPRINTF(20, ("Bad length\n"));
  286.     goto end;
  287.     }
  288.  
  289.     if (unit != 0) {
  290.     err = IOERR_OPENFAIL;
  291.     KPRINTF(20, ("Bad unit\n"));
  292.     goto end;
  293.     }
  294.  
  295.     if (base->vb_Library.lib_OpenCnt == 1) {
  296.  
  297.     base->vb_SerFlags = ioreq->io_SerFlags;
  298.  
  299.     if (!base->vb_Initialized) {
  300.  
  301.         KPRINTF(5, ("Initialization\n"));
  302.  
  303.         MiscBase = OpenResource("misc.resource");
  304.         if (allocResource(base, MR_SERIALPORT)) {
  305.         if (allocResource(base, MR_SERIALBITS)) {
  306.             struct Preferences prefs;
  307.             struct Preferences *prf;
  308.  
  309.             if (IntuitionBase = (APTR)OpenLibrary("intuition.library", 0)) {
  310.             static const int baudTable[] = {
  311.                 112, 300, 1200, 2400, 4800, 9600, 19200,
  312.                 31250, 38400, 57600, 62400, 64800,
  313.                 76800, 115200
  314.             };
  315.  
  316.             prf = GetPrefs(&prefs, sizeof(prefs));
  317.  
  318.             base->vb_DefBaud = baudTable[prf->BaudRate];
  319. //#if NEWCODE
  320.             base->vb_DefRBufLen = 512 << (prf->SerStopBuf & SBUFSIZE_BITS);
  321. /*#else
  322.             base->vb_DefRBufLen = ((prf->SerStopBuf & SBUFSIZE_BITS) + 8) << 2;
  323. #endif*/
  324.             CloseLibrary((APTR)IntuitionBase);
  325.             } else {
  326.             base->vb_DefRBufLen = 4096;
  327.             base->vb_DefBaud = 9600;
  328.             }
  329.  
  330.             KPRINTF(10, ("baud = %ld, buflen = %ld\n", base->vb_DefBaud, base->vb_DefRBufLen));
  331.  
  332.             if (err = internalReset(base, base->vb_DefRBufLen, base->vb_DefBaud)) {
  333.             FreeMiscResource(MR_SERIALBITS);
  334.             FreeMiscResource(MR_SERIALPORT);
  335.             KPRINTF(20, ("BufErr \n"));
  336.             goto end;
  337.             } else if (OpenDevice("timer.device", UNIT_VBLANK, &timerReq, 0)) {
  338.             FreeMiscResource(MR_SERIALBITS);
  339.             FreeMiscResource(MR_SERIALPORT);
  340.             err = SerErr_DevBusy;
  341.             KPRINTF(20, ("No timer\n"));
  342.             goto end;
  343.             }
  344.  
  345.             Disable();
  346.  
  347.             base->vb_SaveDDRA = ciab.ciaddra;
  348.             base->vb_SavePRA = ciab.ciapra;
  349.             ciab.ciaddra = (base->vb_SaveDDRA & PRTMASK) | CIAF_COMDTR | CIAF_COMRTS;
  350.             ciab.ciapra = base->vb_SavePRA & (PRTMASK | CIAF_COMDSR | CIAF_COMDSR);
  351.  
  352.             AddIntServer(INTB_PORTS, &VBInterrupt);
  353.             base->vb_oldRBFInt = SetIntVector(INTB_RBF, &RBFInterrupt);
  354.             base->vb_oldTBEInt = SetIntVector(INTB_TBE, &TBEInterrupt);
  355.  
  356.             custom.intreq = INTF_RBF | INTF_TBE;
  357.             custom.intena = INTF_SETCLR | INTF_RBF | INTF_TBE;
  358.             ++base->vb_Initialized;
  359.  
  360.             Enable();
  361.             KPRINTF(5, ("Interrupt handlers installed\n"));
  362.  
  363.         } else {
  364.             err = IOERR_OPENFAIL;
  365.             KPRINTF(20, ("No serial bits\n"));
  366.             goto end;
  367.         }
  368.         } else {
  369.         err = IOERR_OPENFAIL;
  370.         KPRINTF(20, ("No serial port\n"));
  371.         goto end;
  372.         }
  373.     }
  374.     } else if (!(base->vb_SerFlags & SERB_SHARED) || !(base->vb_SerFlags & SERB_SHARED)) {
  375.     err = SerErr_DevBusy;
  376.     KPRINTF(20, ("Busy\n"));
  377.     goto end;
  378.     }
  379.  
  380.     Handshake = (ioreq->io_SerFlags & SERF_7WIRE) != 0;
  381.  
  382.     ioreq->io_ReadLen = 8;
  383.     ioreq->io_WriteLen = 8;
  384.     ioreq->io_StopBits = 1;
  385.     ioreq->io_SerFlags = (ioreq->io_SerFlags | SERF_XDISABLED | SERF_RAD_BOOGIE |
  386.               SERF_QUEUEDBRK /*| SERF_7WIRE*/) &
  387.             ~(SERF_PARTY_ODD | SERF_PARTY_ON);
  388.     ioreq->io_Baud = base->vb_CurBaud;
  389.     ioreq->io_RBufLen = base->vb_CurRBufLen;
  390.     base->vb_Library.lib_Flags &= ~LIBF_DELEXP;
  391.     err = 0;
  392.     ret = base;
  393.     ++base->vb_Library.lib_OpenCnt;
  394.   end:
  395.     --base->vb_Library.lib_OpenCnt;
  396.     KPRINTF(10, ("returned: %lx, %ld\n", ret, err));
  397.     ioreq->IOSer.io_Error = err;
  398.     return ret;
  399. }
  400.  
  401.  
  402. static BPTR internalExpunge(struct MyDevice *base) {
  403.     BPTR ret = 0;
  404.  
  405.     KPRINTF(5, ("internalExpunge(%lx)\n", base));
  406.  
  407.     base->vb_Library.lib_Flags |= LIBF_DELEXP;
  408.     if (base->vb_Library.lib_OpenCnt == 0) {
  409.     ret = base->vb_SegList;
  410.     Remove(&base->vb_Library.lib_Node);
  411.     FreeMem((char *)base - base->vb_Library.lib_NegSize,
  412.         base->vb_Library.lib_NegSize + base->vb_Library.lib_PosSize);
  413.     }
  414.  
  415.     return ret;
  416. }
  417.  
  418. static BPTR devExpunge(void) {
  419.     struct MyDevice *base = (APTR)REG_A6;
  420.     return internalExpunge(base);
  421. }
  422.  
  423. static BPTR devClose(void) {
  424.     struct IOExtSer *ioreq = (APTR)REG_A1;
  425.     struct MyDevice *base = (APTR)REG_A6;
  426.     BPTR ret = 0;
  427.  
  428.     KPRINTF(10, ("devClose(%lx, %lx)\n", ioreq, base));
  429.     KPRINTF(4, ("%ld TBEs, %ld chars written, %ld caused TBE\n", tbes, written_chars, caused_tbes));
  430.  
  431.     ioreq->IOSer.io_Device = (APTR)-1;
  432.     if (--base->vb_Library.lib_OpenCnt == 0) {
  433.  
  434.     KPRINTF(5, ("Freeing resources.\n"));
  435.  
  436.     Disable();
  437.  
  438.     custom.intena = INTF_RBF | INTF_TBE;
  439.     custom.intreq = INTF_RBF | INTF_TBE;
  440.     SetIntVector(INTB_RBF, base->vb_oldRBFInt);
  441.     SetIntVector(INTB_TBE, base->vb_oldTBEInt);
  442.     RemIntServer(INTB_PORTS, &VBInterrupt);
  443.  
  444.     freeBuf(base);
  445.  
  446.     ciab.ciaddra |= ~PRTMASK;
  447.     ciab.ciapra = (ciab.ciapra & PRTMASK) | (base->vb_SavePRA & ~PRTMASK);
  448.     ciab.ciaddra = (ciab.ciaddra & PRTMASK) | (base->vb_SaveDDRA & ~PRTMASK);
  449.  
  450.     CloseDevice(&timerReq);
  451.  
  452.     FreeMiscResource(MR_SERIALBITS);
  453.     FreeMiscResource(MR_SERIALPORT);
  454.  
  455.     Enable();
  456.  
  457.     --base->vb_Initialized;
  458.  
  459.     base->vb_SerFlags = 0;
  460.     if (base->vb_Library.lib_Flags & LIBF_DELEXP) {
  461.         ret = internalExpunge(base);
  462.     }
  463.     }
  464.     KPRINTF(10, ("lib_OpenCnt = %ld\n", base->vb_Library.lib_OpenCnt));
  465.  
  466.     return ret;
  467. }
  468.  
  469.  
  470. /* Reset the buffer and baud rate */
  471.  
  472. static ULONG internalReset(struct MyDevice *base, ULONG buflen, ULONG baud) {
  473.     ULONG ret = 0;
  474.  
  475.     KPRINTF(5, ("internalReset(%lx, %ld, %ld)\n", base, buflen, baud));
  476.  
  477.     Disable();
  478.  
  479.     if (base->vb_CurBaud != baud) {
  480.     base->vb_CurBaud = baud;
  481.     custom.serper = (SysBase->PowerSupplyFrequency == 50 ? 24772416 : 25000000) / (baud * 7);
  482.     }
  483.  
  484.     if (buflen <= baud / 4)
  485.     buflen = 65536;
  486.  
  487.     if (base->vb_CurRBufLen != buflen) {
  488.     UBYTE *p = AllocMem(buflen, MEMF_PUBLIC|MEMF_FAST);
  489.  
  490.     KPRINTF(5, ("buffer = %lx\n", p));
  491.  
  492.     if (p) {
  493.         freeBuf(base);
  494.         base->vb_CurRBuf = p;
  495.         base->vb_CurRBufLen = buflen;
  496.         cmdClear(base);
  497.     } else
  498.         ret = SerErr_BufErr;
  499.     }
  500.  
  501.     Enable();
  502.  
  503.     return ret;
  504. }
  505.  
  506.  
  507.  
  508. static void internalAbortIO(struct MyDevice *base, struct IOExtSer *ioreq) {
  509.     int abort = FALSE;
  510.  
  511.     KPRINTF(8, ("AbortIO(%lx, %lx)\n", base, ioreq));
  512.  
  513.     Disable();
  514.  
  515.     if (ioreq->IOSer.io_Flags & IOSERF_QUEUED) {
  516.     KPRINTF(7, ("Removing from queue\n"));
  517.     Remove(&ioreq->IOSer.io_Message.mn_Node);
  518.     abort = TRUE;
  519.     } else if (ioreq->IOSer.io_Flags & IOSERF_ACTIVE) {
  520.     switch(ioreq->IOSer.io_Command) {
  521.       case CMD_READ:
  522.         KPRINTF(7, ("Aborting active read: %lx.\n", cw_IOReq));
  523.         cr_IOReq = NULL;
  524.         abort = TRUE;
  525.         break;
  526.  
  527.       case CMD_WRITE:
  528.       case SDCMD_BREAK:
  529.         KPRINTF(7, ("Aborting active write: %lx, %ld\n", cw_IOReq, cw_Length));
  530.         cw_Length = 0;
  531.         cw_IOReq = NULL;
  532.         ioreq->IOSer.io_Actual = cw_Buffer - (UBYTE *)ioreq->IOSer.io_Data;
  533.         custom.intreq = INTF_SETCLR | INTF_TBE;
  534.         abort = TRUE;
  535.         break;
  536.  
  537.     }
  538.     }
  539.  
  540.     if (abort) {
  541.     ioreq->IOSer.io_Error = IOERR_ABORTED;
  542.     ioreq->IOSer.io_Flags = (ioreq->IOSer.io_Flags | IOSERF_ABORT) &
  543.                    ~(IOSERF_QUEUED | IOSERF_ACTIVE);
  544.     if (!(ioreq->IOSer.io_Flags & IOF_QUICK)) {
  545.         KPRINTF(7, ("Replying \n"));
  546.         ReplyMsg(&ioreq->IOSer.io_Message);
  547.     }
  548.     }
  549.  
  550.     Enable();
  551. }
  552.  
  553. static void devAbortIO(void) {
  554.     struct IOExtSer *ioreq = (APTR)REG_A1;
  555.     struct MyDevice *base = (APTR)REG_A6;
  556.     internalAbortIO(base, ioreq);
  557. }
  558.  
  559.  
  560. /* Free internal buffer */
  561.  
  562. static void freeBuf(struct MyDevice *base) {
  563.     if (base->vb_CurRBuf) {
  564.     FreeMem(base->vb_CurRBuf, base->vb_CurRBufLen);
  565.     base->vb_CurRBuf = NULL;
  566.     base->vb_CurRBufLen = 0;
  567.     }
  568. }
  569.  
  570.  
  571. /* Reset the serial read buffer */
  572.  
  573. static ULONG cmdClear(struct MyDevice *base) {
  574.     KPRINTF(8, ("CMD_CLEAR\n"));
  575.     Disable();
  576.     i_BufPtr = base->vb_CurRBuf;
  577.     i_BufIn = base->vb_CurRBuf;
  578.     i_BufOut = base->vb_CurRBuf;
  579.     i_BufEnd = base->vb_CurRBuf + base->vb_CurRBufLen;
  580.     i_InCnt = 0;
  581.     i_Thresh = base->vb_CurRBufLen - (base->vb_CurBaud >> 4);
  582.     Enable();
  583.     return 0;
  584. }
  585.  
  586.  
  587. static ULONG cmdInvalid(struct IOExtSer *ioreq) {
  588.     KPRINTF(20, ("CMD_INVALID\n"));
  589.     ioreq->IOSer.io_Error = IOERR_NOCMD;
  590.     return 0;
  591. }
  592.  
  593. static ULONG cmdReset(struct MyDevice *base, struct IOExtSer *ioreq) {
  594.     KPRINTF(10, ("CMD_RESET\n"));
  595.     cmdFlush(ioreq);
  596.  
  597.     Disable();
  598.  
  599.     if (cr_IOReq)
  600.     internalAbortIO(base, cr_IOReq);
  601.  
  602.     if (cw_IOReq)
  603.     internalAbortIO(base, cw_IOReq);
  604.  
  605.     ioreq->io_ReadLen = 8;
  606.     ioreq->io_WriteLen = 8;
  607.     ioreq->io_StopBits = 1;
  608.     ioreq->io_Baud = base->vb_DefBaud;
  609.     ioreq->io_RBufLen = base->vb_DefRBufLen;
  610.  
  611.     ioreq->IOSer.io_Error = internalReset(base, base->vb_DefRBufLen, base->vb_DefBaud);
  612.  
  613.     Enable();
  614.     return 0;
  615. }
  616.  
  617. static void internalFlush(struct MinList *queue) {
  618.     struct IOExtSer *ioreq;
  619.     struct IOExtSer *next;
  620.  
  621.     Disable();
  622.     ioreq = (struct IOExtSer *)queue->mlh_Head;
  623.     queue->mlh_Head = (APTR)&queue->mlh_Tail;
  624.     queue->mlh_Tail = NULL;
  625.     queue->mlh_TailPred = (APTR)queue;
  626.     Enable();
  627.  
  628.     while (next = (struct IOExtSer *)ioreq->IOSer.io_Message.mn_Node.ln_Succ) {
  629.     ioreq->IOSer.io_Flags &= ~IOSERF_QUEUED;
  630.     ioreq->IOSer.io_Error = IOERR_ABORTED;
  631.     ReplyMsg(&ioreq->IOSer.io_Message);
  632.     ioreq = next;
  633.     }
  634. }
  635.  
  636. static ULONG cmdFlush(struct IOExtSer *ioreq) {
  637.     KPRINTF(8, ("CMD_FLUSH\n"));
  638.     internalFlush(&readQ);
  639.     internalFlush(&writeQ);
  640.     return 0;
  641. }
  642.  
  643.  
  644. static ULONG cmdRead(struct IOExtSer *ioreq) {
  645.     ULONG ret;
  646.  
  647.     KPRINTF(3, ("CMD_READ(%lx, %ld%s) inCnt = %ld\n", ioreq, ioreq->IOSer.io_Length, ioreq->io_SerFlags & SERF_EOFMODE ? ", EOFMODE" : "", i_InCnt));
  648.  
  649.     ioreq->IOSer.io_Actual = 0;
  650.  
  651.     if (ret = ioreq->IOSer.io_Length) {
  652.  
  653.     /* This can be used to circumvent a bug in NComm 3.0 which
  654.      * references the buffer even when there was nothing read.
  655.      */
  656. #if NCOMM
  657.     *(UBYTE *)ioreq->IOSer.io_Data = 0;
  658. #endif
  659.  
  660.     /* The disable counter works just like exec's TDNestCnt field.  It's
  661.      * initialized to -1.  After incrementing, if it is 0, then we
  662.      * can attempt to process this request immediately.  If it's > 0,
  663.      * then we're already disabled and we must queue this request.
  664.      */
  665.     Disable();
  666.     ++disableRead; /* not atomic on PPC */
  667.     Enable();
  668.  
  669.     if (disableRead <= 0) {
  670.  
  671.         /* If we're already processing a request, this one has to wait
  672.          * until that one is done, so go queue it.
  673.          */
  674.         if (!cr_IOReq) {
  675.  
  676.         /* If we don't have enough bytes to satisfy this request then go
  677.          * queue it.
  678.          */
  679.         if (i_InCnt >= ioreq->IOSer.io_Length) {
  680.  
  681.             /* Setup fields and go copy the data */
  682.             cr_OutPtr = ioreq->IOSer.io_Data;
  683.             cr_Length = ioreq->IOSer.io_Length;
  684.             copyData(ioreq);
  685.  
  686.             Disable();
  687.             --disableRead;
  688.             Enable();
  689.             return 0;
  690.         }
  691.  
  692.         }
  693.     }
  694.  
  695.     /* Just set flags and queue.  The read interrupt will handle it. */
  696.     ioreq->IOSer.io_Flags |= IOSERF_QUEUED;
  697.     Disable();
  698.     AddTail((struct List *)&readQ, &ioreq->IOSer.io_Message.mn_Node);
  699.     --disableRead;
  700.     Enable();
  701.     }
  702.  
  703.     return ret;
  704. }
  705.  
  706.  
  707. static void queueWrite(struct IOExtSer *ioreq) {
  708.  
  709.     KPRINTF(2, ("queueWrite(%lx)\n", ioreq));
  710.  
  711.     Disable();
  712.  
  713.     ioreq->IOSer.io_Flags |= IOSERF_QUEUED;
  714.  
  715.     /* Add request to end of queue. */
  716.     AddTail((struct List *)&writeQ, &ioreq->IOSer.io_Message.mn_Node);
  717.  
  718.     /* If we have an active request, don't force interrupt. */
  719.     if (!cw_IOReq) {
  720.     KPRINTF(1, ("causing TBE interrupt. Intenar = %lx\n", custom.intenar));
  721.     custom.intreq = INTF_SETCLR | INTF_TBE;
  722.     DB(++caused_tbes;)
  723.     } else
  724.     KPRINTF(4, ("Already a pending write: %lx, %ld\n", cw_IOReq, cw_Length));
  725.  
  726.     Enable();
  727.  
  728. }
  729.  
  730. static ULONG cmdWrite(struct IOExtSer *ioreq) {
  731.     ULONG ret = 0;
  732.  
  733.     KPRINTF(4, ("CMD_WRITE(%lx, %ld)\n", ioreq, ioreq->IOSer.io_Length));
  734.  
  735.     ioreq->IOSer.io_Actual = 0;
  736.  
  737.     if (ioreq->IOSer.io_Length) {
  738.  
  739. #if EOFCODE
  740.     if (ioreq->IOSer.io_Flags & SERF_EOFMODE) {
  741.         ioreq->IOSer.io_Error = SerErr_InvParam;
  742.         return 0;
  743.     }
  744. #endif
  745.  
  746. #if NEGCHECK
  747.     if (ioreq->IOSer.io_Length == -1)
  748.         ioreq->IOSer.io_Length = strlen(ioreq->IOSer.io_Data);
  749. #endif
  750.  
  751.     queueWrite(ioreq);
  752.     ret = 1;
  753.     }
  754.  
  755.     return ret;
  756. }
  757.  
  758.  
  759. static ULONG sdcmdBreak(struct IOExtSer *ioreq) {
  760.     KPRINTF(4, ("SDCMD_BREAK\n"));
  761.     queueWrite(ioreq);
  762.     return 1;
  763. }
  764.  
  765.  
  766. static ULONG sdcmdQuery(struct IOExtSer *ioreq) {
  767.     KPRINTF(2, ("SDCMD_QUERY\n"));
  768.     Disable();
  769.     ioreq->io_Status = ciab.ciapra & (~PRTMASK & 0xff);
  770. #if SETDSR
  771.     ioreq->io_Status &= ~CIAF_COMDSR;
  772. #endif
  773.     ioreq->IOSer.io_Actual = i_InCnt;
  774.     Enable();
  775.     KPRINTF(2, ("status = %lx, actual = %ld\n", ioreq->io_Status, ioreq->IOSer.io_Actual));
  776.     return 0;
  777. }
  778.  
  779.  
  780. static ULONG sdcmdSetParams(struct MyDevice *base, struct IOExtSer *ioreq) {
  781.     ULONG err = 0;
  782.  
  783.     KPRINTF(8, ("SDCMD_SETPARAMS: CtlChar = %08lx, ExtFlags = %08lx, SerFlags = %02lx\n"
  784.          "\t\tTermArray = %08lx %08lx\n",
  785.          ioreq->io_CtlChar, ioreq->io_ExtFlags, ioreq->io_SerFlags,
  786.          ioreq->io_TermArray.TermArray0, ioreq->io_TermArray.TermArray1));
  787.  
  788.     /* Validate the read, write, and stop bit lengths. */
  789.  
  790.     if (ioreq->io_ReadLen == 8 &&
  791.     ioreq->io_WriteLen == 8 &&
  792.     ioreq->io_StopBits == 1) {
  793.  
  794.     /*  Get and validate the baud rate. */
  795.  
  796.     int baud = ioreq->io_Baud;
  797.  
  798.     if (!baud) {
  799.         baud = base->vb_CurBaud;
  800.         if (!baud)
  801.         baud = base->vb_DefBaud;
  802.     }
  803.  
  804.     if (baud >= 110 && baud <= 292000) {
  805.  
  806.         /* Get and validate the buffer length. */
  807.  
  808.         int rlen = ioreq->io_RBufLen;
  809.  
  810.         if (!rlen) {
  811.         rlen = base->vb_CurRBufLen;
  812.         if (!rlen)
  813.             rlen = base->vb_DefRBufLen;
  814.         }
  815.  
  816.         err = internalReset(base, rlen, baud);
  817.  
  818.         /* If the 7wire bit is not on, we will only use 3-wire protocol */
  819.  
  820.         Handshake = (ioreq->io_SerFlags & SERF_7WIRE) != 0;
  821.  
  822.     } else
  823.         err = SerErr_InvParam;
  824.  
  825.     } else
  826.     err = SerErr_InvParam;
  827.  
  828.     KPRINTF(8, ("err = %d\n", err));
  829.  
  830.     return err;
  831. }
  832.  
  833.  
  834. static void devBeginIO(void) {
  835.     struct IOExtSer *ioreq = (APTR)REG_A1;
  836.     struct MyDevice *base = (APTR)REG_A6;
  837.     ULONG ret = 0;
  838.  
  839.     KPRINTF(1, ("BeginIO(%lx, %lx, %ld)\n", base, ioreq, ioreq->IOSer.io_Command));
  840.  
  841.     ioreq->IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  842.     ioreq->IOSer.io_Error = 0;
  843.     ioreq->IOSer.io_Flags &= ~(IOSERF_QUEUED|IOSERF_ACTIVE);
  844.  
  845.     switch(ioreq->IOSer.io_Command) {
  846.       case CMD_INVALID:
  847.       case CMD_UPDATE:
  848.       case CMD_STOP:
  849.       case CMD_START:
  850.     ret = cmdInvalid(ioreq);
  851.     break;
  852.  
  853.       case CMD_RESET:
  854.     ret = cmdReset(base, ioreq);
  855.     break;
  856.  
  857.       case CMD_READ:
  858.     ret = cmdRead(ioreq);
  859.     break;
  860.  
  861.       case CMD_WRITE:
  862.     ret = cmdWrite(ioreq);
  863.     break;
  864.  
  865.       case CMD_CLEAR:
  866.     ret = cmdClear(base);
  867.     break;
  868.  
  869.       case CMD_FLUSH:
  870.     ret = cmdFlush(ioreq);
  871.     break;
  872.  
  873.       case SDCMD_QUERY:
  874.     ret = sdcmdQuery(ioreq);
  875.     break;
  876.  
  877.       case SDCMD_BREAK:
  878.     ret = sdcmdBreak(ioreq);
  879.     break;
  880.  
  881.       case SDCMD_SETPARAMS:
  882.     ret = sdcmdSetParams(base, ioreq);
  883.     break;
  884.  
  885.       default:
  886.     ioreq->IOSer.io_Error = IOERR_NOCMD;
  887.     break;
  888.     }
  889.  
  890.     if (ret)
  891.     ioreq->IOSer.io_Flags &= ~IOF_QUICK;
  892.     else if (!(ioreq->IOSer.io_Flags & IOF_QUICK))
  893.     ReplyMsg(&ioreq->IOSer.io_Message);
  894. }
  895.  
  896.  
  897. /* Checks CTS status and if clear generates a TBE interrupt or
  898.  * requeues the timer request.
  899.  *
  900.  * Entered from Exec using the MsgPort callback.
  901.  */
  902. static void timerRtn(void) {
  903.  
  904.     KPRINTF(4, ("Time request returned\n"));
  905.  
  906.     Remove(&timerReq.tr_node.io_Message.mn_Node);
  907.  
  908.     /* If we were breaking, reset adkcon. */
  909.     if (custom.adkconr & ADKF_UARTBRK)
  910.     custom.adkcon = ADKF_UARTBRK;
  911.  
  912.     if (Handshake && ciab.ciapra & CIAF_COMCTS) {
  913.     KPRINTF(4, ("Sending time request\n"));
  914.     timerReq.tr_time.tv_micro = 1000;
  915.     SendIO(&timerReq.tr_node);
  916.     } else {
  917.     custom.intreq = INTF_SETCLR | INTF_TBE;
  918.     DB(++caused_tbes;)
  919.     }
  920. }
  921.  
  922.  
  923.  
  924. static ULONG copyData(struct IOExtSer *ioreq) {
  925.     UBYTE *from = i_BufOut;
  926.     LONG inCnt = i_InCnt;
  927.     UBYTE *to = cr_OutPtr;
  928.     LONG length = cr_Length;
  929.     ULONG ret = 0;
  930.     int k;
  931.  
  932.     KPRINTF(2, ("copyData(%ld, %ld)\n", inCnt, length));
  933.  
  934.     /* If we don't have enough bytes to satisfy the request,
  935.      * set the length to the number of bytes we do have.
  936.      */
  937.     if (length > inCnt)
  938.     length = inCnt;
  939.  
  940.     do {
  941.     inCnt = length;
  942.  
  943.     /* If the copy will extend past the end of the buffer, we can
  944.      * only copy the number of bytes to the end this go around.
  945.      */
  946.     if (inCnt > i_BufEnd - from)
  947.         inCnt = i_BufEnd - from;
  948.  
  949. #if EOFCODE
  950.     if (ioreq->io_SerFlags & SERF_EOFMODE) {
  951.         ULONG t0 = ioreq->io_TermArray.TermArray0;
  952.         ULONG t1 = ioreq->io_TermArray.TermArray1;
  953.  
  954.         for (k = 1; k <= inCnt; ++k) {
  955.         ULONG c = *from++;
  956.         ULONG t;
  957.  
  958. /*{static int cnt=0; if(++cnt<=1000)KPRINTF(0, ("copy %04lx: '%lc'\n", c,
  959.                        c >= ' ' && c < 0x7f ? c : '.'));}*/
  960.         *to++ = c;
  961.  
  962.         t = t0 >> 24;
  963.         if (c < t) {
  964.             t = (UBYTE)(t0 >> 16);
  965.             if (c < t) {
  966.             t = (UBYTE)(t0 >> 8);
  967.             if (c < t) {
  968.                 t = (UBYTE)t0;
  969.                 if (c < t) {
  970.                 t = t1 >> 24;
  971.                 if (c < t) {
  972.                     t = (UBYTE)(t1 >> 16);
  973.                     if (c < t) {
  974.                     t = (UBYTE)(t1 >> 8);
  975.                     if (c < t) {
  976.                         t = (UBYTE)t0;
  977.                     }
  978.                     }
  979.                 }
  980.                 }
  981.             }
  982.             }
  983.         }
  984.         if (c == t) {
  985.             KPRINTF(1, ("Got break char.\n"));
  986.             length = k;
  987.             cr_Length = 0;
  988.             break;
  989.         }
  990.         }
  991.  
  992.         length -= k;
  993.  
  994.     } else
  995. #endif
  996.            {
  997.  
  998.         for (k = inCnt; --k >= 0; ) {
  999. /*{static int cnt=0; if(++cnt<=1000)KPRINTF(0, ("copy %04lx: '%lc'\n", *from,
  1000.                      (UBYTE)*from >= ' ' && (UBYTE)*from < 0x7f ? (UBYTE)*from : '.'));}*/
  1001.         *to++ = *from++;
  1002.         }
  1003.  
  1004.         /* If the following calculation results in a value greater than
  1005.          * zero, then we have a buffer wrap and need to process the
  1006.          * remaining bytes at the beginning of the buffer.
  1007.          */
  1008.  
  1009.         length -= inCnt;
  1010.     }
  1011.  
  1012.     if (length > 0)
  1013.         from = i_BufPtr;
  1014.  
  1015.     } while (length > 0);
  1016.  
  1017.     length = to - cr_OutPtr;
  1018.     cr_OutPtr = to;
  1019.  
  1020.     /* Update output ptr and I/O request */
  1021.     i_BufOut = from;
  1022.     ioreq->IOSer.io_Actual += length;
  1023.  
  1024.     Disable();
  1025.     /* Update number of bytes left in the buffer. */
  1026.     i_InCnt -= length;
  1027.  
  1028.     /* If the threshold becomes positive here, then, if requested,
  1029.      * tell the other end that it's okay to start sending more data.
  1030.      */
  1031.  
  1032.     i_Thresh += length;
  1033.     if (i_Thresh >= 0 && Handshake) {
  1034.     if (i_Thresh - length < 0)
  1035.         KPRINTF(4, ("Clearing RTS\n"));
  1036.     ciab.ciapra &= ~CIAF_COMRTS;
  1037.     }
  1038.  
  1039.     /* Set error if we've had any overruns. */
  1040.     if (Overrun) {
  1041.     Overrun = FALSE;
  1042.     ioreq->IOSer.io_Error = SerErr_LineErr;
  1043.     }
  1044.     Enable();
  1045.  
  1046.     /* Calc number of bytes left to copy.  If the result is greater
  1047.      * than zero, then we have more to copy so return an incomplete
  1048.      * status.
  1049.      */
  1050.  
  1051.     cr_Length -= length;
  1052.     if (cr_Length <= 0) {
  1053.     /* We've completed the I/O request either by copying the requested
  1054.      * of bytes or by finding an EOFMODE character, so return a "reply"
  1055.      * status.
  1056.      */
  1057.      ret = 1;
  1058.     }
  1059.  
  1060.     KPRINTF(2, ("io_Actual = %ld, io_Error = %ld\n", ioreq->IOSer.io_Actual, ioreq->IOSer.io_Error));
  1061.     return ret;
  1062. }
  1063.  
  1064.  
  1065. static void level1(void) {
  1066.  
  1067.     DB(++tbes;)
  1068.  
  1069.     /* Clear the interrupt */
  1070.     custom.intreq = INTF_TBE;
  1071.  
  1072.     /* If we're not handshaking, bypass it. */
  1073.     if (!Handshake || !(ciab.ciapra & CIAF_COMCTS)) {
  1074.       start:
  1075.     --cw_Length;
  1076.     if (cw_Length < 0) {
  1077.         /* Write request completed */
  1078.  
  1079.         if (cw_IOReq) {
  1080.         /* Reply it and setup for next */
  1081.         KPRINTF(4, ("Replying CMD_WRITE %lx\n", cw_IOReq));
  1082.         cw_IOReq->IOSer.io_Flags &= ~IOSERF_ACTIVE;
  1083.         cw_IOReq->IOSer.io_Error = 0;
  1084.         ReplyMsg(&cw_IOReq->IOSer.io_Message);
  1085.         }
  1086.  
  1087.         if (writeQ.mlh_Head->mln_Succ) {
  1088.  
  1089.         struct IOExtSer *ioreq = (struct IOExtSer *)writeQ.mlh_Head;
  1090.  
  1091.         Remove(&ioreq->IOSer.io_Message.mn_Node);
  1092.  
  1093.         KPRINTF(1, ("Start %lx transmition\n", ioreq));
  1094.  
  1095.         if (ioreq->IOSer.io_Command == SDCMD_BREAK) {
  1096.  
  1097.             KPRINTF(1, ("Sending break\n"));
  1098.             cw_IOReq = ioreq;
  1099.             cw_Length = 0;
  1100.             ioreq->IOSer.io_Flags = (ioreq->IOSer.io_Flags & ~IOSERF_QUEUED) | IOSERF_ACTIVE;
  1101.             custom.adkcon = ADKF_SETCLR | ADKF_UARTBRK;
  1102.             timerReq.tr_time.tv_micro = ioreq->io_BrkTime;
  1103.             KPRINTF(4, ("Sending time request\n"));
  1104.             SendIO(&timerReq.tr_node);
  1105.  
  1106.         } else {
  1107.             KPRINTF(1, ("write len = %ld\n", ioreq->IOSer.io_Length));
  1108.             /* Check for absolute length */
  1109.             cw_IOReq = ioreq;
  1110.             cw_Buffer = ioreq->IOSer.io_Data;
  1111.             cw_Length = ioreq->IOSer.io_Length;
  1112.             ioreq->IOSer.io_Actual = ioreq->IOSer.io_Length;
  1113.             ioreq->IOSer.io_Flags = (ioreq->IOSer.io_Flags & ~IOSERF_QUEUED) | IOSERF_ACTIVE;
  1114.             goto start;
  1115.         }
  1116.  
  1117.         } else {
  1118.         /* There aren't anymore requests, so clear and exit */
  1119.         cw_Length = 0;
  1120.         cw_IOReq = NULL;
  1121.         KPRINTF(4, ("Transmission finished.\n"));
  1122.         }
  1123.  
  1124.     } else {
  1125.         /* Currently processing a request. */
  1126. /*{ static int cnt=0; if(++cnt<=1000)KPRINTF(0, ("write '%lc' %lx\n", *cw_Buffer >= ' ' && *cw_Buffer < 0x7f ? *cw_Buffer : '.', *cw_Buffer));}*/
  1127.         custom.serdat = *cw_Buffer++ | (1 << 8); /* next byte + stop bit */
  1128.         DB(++written_chars;)
  1129.     }
  1130.     } else {
  1131.     /* Queue a timer request to recheck CTS status */
  1132.     timerReq.tr_time.tv_micro = 1000;
  1133.     KPRINTF(4, ("Sending time request\n"));
  1134.     SendIO(&timerReq.tr_node);
  1135.     }
  1136. }
  1137.  
  1138.  
  1139. static void level2(void) {
  1140.     struct List *rqueue = (APTR)REG_A1;
  1141.  
  1142.     /* If there's nothing in the buffer, there's no point in going
  1143.      * any further.
  1144.      */
  1145.     if (i_InCnt) {
  1146.  
  1147.     /* If we've been "disabled" then get out. */
  1148.  
  1149.     if (disableRead < 0) {
  1150.         struct IOExtSer *ioreq;
  1151.  
  1152.         /* If we have an active request, try to fulfill it. */
  1153.  
  1154.         if (!cr_IOReq && rqueue->lh_Head->ln_Succ) {
  1155.         struct IOExtSer *ioreq = (struct IOExtSer *)rqueue->lh_Head;
  1156.  
  1157.         KPRINTF(1, ("Start filling read request\n"));
  1158.  
  1159.         /* Remove the node from the list */
  1160.         Remove(&ioreq->IOSer.io_Message.mn_Node);
  1161.  
  1162.         /* Setup fields for processing a read request */
  1163.         cr_IOReq = ioreq;
  1164.         cr_OutPtr = ioreq->IOSer.io_Data;
  1165.         cr_Length = ioreq->IOSer.io_Length;
  1166.         ioreq->IOSer.io_Flags = (ioreq->IOSer.io_Flags & ~IOSERF_QUEUED) | IOSERF_ACTIVE;
  1167.         }
  1168.  
  1169.         if (ioreq = cr_IOReq) {
  1170.         /* Process an active I/O request */
  1171.         if (cr_Length > 0) {
  1172.             if (copyData(ioreq)) {
  1173.             cr_IOReq = NULL;
  1174.             ioreq->IOSer.io_Flags &= ~IOSERF_ACTIVE;
  1175.             KPRINTF(3, ("Replying CMD_READ %lx\n", ioreq));
  1176.             ReplyMsg(&ioreq->IOSer.io_Message);
  1177.             }
  1178.         }
  1179.         }
  1180.     }
  1181.     }
  1182.  
  1183.     REG_SR |= 4; /* Set Z flag */
  1184. }
  1185.  
  1186.  
  1187. static void level5(void) {
  1188.  
  1189.     UWORD dat = custom.serdatr;
  1190.  
  1191.     /* If we've missed some data, set overrun flag. */
  1192.     if ((WORD)dat < 0) {
  1193.     KPRINTF(20, ("****** Overrun !\n"));
  1194.     Overrun = TRUE;
  1195.     }
  1196.  
  1197.     /* Clear the interrupt. */
  1198.     custom.intreq = INTF_RBF;
  1199.  
  1200.     *i_BufIn++ = (UBYTE)dat;
  1201.     ++i_InCnt;
  1202.  
  1203. /*{static int cnt=0; if(++cnt<=1000)KPRINTF(0, ("read %04lx: '%c'\n", dat,
  1204.                      (UBYTE)dat >= ' ' && (UBYTE)dat < 0x7f ? (UBYTE)dat : '.'));}*/
  1205.  
  1206.     /* If we hit physical end of buffer, wrap to the start. */
  1207.     if (i_BufIn == i_BufEnd)
  1208.     i_BufIn = i_BufPtr;
  1209.  
  1210.     --i_Thresh;
  1211.  
  1212.     if (i_Thresh == 0) {
  1213.     /* Hit buffer threshold, so tell other end not to send any more data. */
  1214.     if (Handshake) {
  1215.         KPRINTF(4, ("Setting RTS\n"));
  1216.         ciab.ciapra |= CIAF_COMRTS;
  1217.     }
  1218.     }
  1219. }
  1220.  
  1221.  
  1222.