home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser-CD 2000 January / LCD_01_2000.iso / pd / 308 / uart_040 / pc16550.c < prev    next >
C/C++ Source or Header  |  1999-08-22  |  50KB  |  2,568 lines

  1. /*
  2.  * Filename:     
  3.  * Version:      
  4.  * Author:       Frank Naumann
  5.  * Started:      1999-07-28
  6.  * Last Updated: 1999-08-06
  7.  * Target O/S:   TOS/MiNT
  8.  * Description:  
  9.  * 
  10.  * Note:         Please send suggestions, patches or bug reports to me
  11.  *               or the MiNT mailing list <mint@fishpool.com>.
  12.  * 
  13.  * Copying:      Copyright 1999 Frank Naumann <fnaumann@cs.uni-magdeburg.de>
  14.  *               Portions copyright 1998, 1999 Rainer Mannigel, Michael Schwingen.
  15.  * 
  16.  * This program is free software; you can redistribute it and/or modify
  17.  * it under the terms of the GNU General Public License as published by
  18.  * the Free Software Foundation; either version 2, or (at your option)
  19.  * any later version.
  20.  * 
  21.  * This program is distributed in the hope that it will be useful,
  22.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  * GNU General Public License for more details.
  25.  * 
  26.  * You should have received a copy of the GNU General Public License
  27.  * along with this program; if not, write to the Free Software
  28.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  * 
  30.  * 
  31.  * changes since last version:
  32.  * 
  33.  * 1999-08-21:    (v0.40)
  34.  * 
  35.  * - new: added MiNT version and Milan check
  36.  * - new: added tty tread & twrite functions, ttys work now
  37.  * - new: added automatic tty install (init, open)
  38.  * - new: check & evaluate file sharing modes (open, close)
  39.  * - new: wake up sleeping process on close
  40.  * - fix: wrong return value in read & write for N_DELAY
  41.  * 
  42.  * 1999-08-14:    (v0.30b)
  43.  * 
  44.  * - new: optimized read data interrupt routine
  45.  * - new: return EWOULDBLOCK in read & write if N_DELAY is set
  46.  * 
  47.  * 1999-08-09:    (v0.20b)
  48.  * 
  49.  * - inital revision
  50.  * 
  51.  * 
  52.  * known bugs:
  53.  * 
  54.  * 
  55.  * todo:
  56.  * 
  57.  * 
  58.  * 
  59.  * UART BIOS and XBIOS Routinen for Milan.
  60.  * Rainer Mannigel, Michael Schwingen
  61.  * 
  62.  * We now support lots (currently 10) of UARTs, and interrupt sharing
  63.  * between them. We install one interrupt handler for each physical
  64.  * interrupt line that belongs to one or more UARTs, and that gets the
  65.  * pointer to the first UART's iovar in its corresponding intr_iovar. The
  66.  * iovars are chained together by the next field, so the interrupt handler
  67.  * services one UART at a time as long as there are events left to be
  68.  * handled and then goes on to the next UART.
  69.  * 
  70.  * Due to the braindamaged design using Bconmap() to access more than one
  71.  * serial port, we do not get a useable device number in the BIOS calls
  72.  * (Bconin/out/stat/ostat), which means that we have to provide one entry
  73.  * point for each of these routines (and for Rsconf, which gets no device
  74.  * numbger at all) for every port we want to handle - this is why there is a 
  75.  * statical limit - these routines are in stubs.s
  76.  */
  77.  
  78. /* FreeMiNT header */
  79. # include <atarierr.h>
  80. # include <default.h>
  81. # include <dcntl.h>
  82. # include <file.h>
  83. # include <fstring.h>
  84.  
  85. # include <osbind.h>
  86.  
  87. # include "kernel.h"
  88. # include "rsvf.h"
  89. # include "pc16550.h"
  90.  
  91.  
  92. /*
  93.  * version
  94.  */
  95.  
  96. # define VER_MAJOR    0
  97. # define VER_MINOR    40
  98. # define VER_STATUS    
  99.  
  100.  
  101. /*
  102.  * debugging stuff
  103.  */
  104.  
  105. # if 0
  106. # define DEV_DEBUG    1
  107. # endif
  108.  
  109. # if 0
  110. # define INT_DEBUG    1
  111. # endif
  112.  
  113.  
  114. /*
  115.  * default settings
  116.  */
  117.  
  118. # define RSVF_BASENAME    "serial"
  119. # define RSVF_OFFSETT    1
  120.  
  121. # define TTY_BASENAME    "tty"
  122. # define TTY_OFFSETT    'c'
  123.  
  124.  
  125. # define IOBUFSIZE    4096
  126.  
  127. # define MAX_PORTS    10
  128. # define MAX_INTS     5    /* 2 onboard + 3 ISA cards */
  129.  
  130.  
  131. /*
  132.  * messages
  133.  */
  134.  
  135. # define MSG_VERSION    str (VER_MAJOR) "." str (VER_MINOR) str (VER_STATUS) 
  136. # define MSG_BUILDDATE    __DATE__
  137.  
  138. # define MSG_BOOT    \
  139.     "\033p Milan UART serial driver version " MSG_VERSION " \033q\r\n"
  140.  
  141. # define MSG_GREET    \
  142.     "╜ 1998, 1999 by Rainer Mannigel, Michael Schwingen.\r\n" \
  143.     "╜ " MSG_BUILDDATE " by Frank Naumann <fnaumann@cs.uni-magdeburg.de>.\r\n\r\n"
  144.  
  145. # define MSG_MINT    \
  146.     "\033pMiNT to old!\033q\r\n"
  147.  
  148. # define MSG_MILAN    \
  149.     "\033pThis driver require a Milan!\033q\r\n"
  150.  
  151. # define MSG_FAILURE    \
  152.     "\7\r\nSorry, driver NOT installed - initialization failed!\r\n\r\n"
  153.  
  154.  
  155. /****************************************************************************/
  156. /* BEGIN kernel interface */
  157.  
  158. struct kerinfo *kernel;
  159.  
  160. /* END kernel interface */
  161. /****************************************************************************/
  162.  
  163. /****************************************************************************/
  164. /* BEGIN definition part */
  165.  
  166. typedef struct iorec IOREC;
  167. struct iorec
  168. {
  169.     uchar    *buffer;    /* buffer location pointer */
  170.         ushort    size;        /* maximum size of this buffer */
  171.     volatile ushort head;    /* offset to next byte to be taken
  172.                  * from this buffer */
  173.     volatile ushort tail;    /* offset to next location available
  174.                      * to insert a new byte */
  175.     ushort    low_water;    /* amount of space in buffer before a "xon"
  176.                  * may be sent to restore normal use of
  177.                  * buffer */
  178.     ushort    high_water;    /* amount of space used in buffer that
  179.                  * trigger's the sending of a "xoff" signal
  180.                  * to the host */
  181.     ushort    res;        /* alignment */
  182. };
  183.  
  184. typedef struct iovar IOVAR;
  185. struct iovar
  186. {
  187.     UART    *regs;        /* UART register base address */
  188.     IOVAR    *next;        /* for Interrupt-Sharing */
  189.     
  190.     IOREC    input;        /* input buffer */
  191.     IOREC    output;        /* output buffer */
  192.     
  193.     ushort    rxoff;        /* flag: receiver stopped (buffer full) */
  194.     ushort    txoff;        /* flag: transmitter stopped */
  195.     
  196.     ushort    hsk_mode;    /* handshake mode */
  197. # define SHAKE_XON_OFF        0x1
  198. # define SHAKE_RTS_CTS        0x2
  199.     
  200.     uchar    sendnow;    /* one byte of control data, bypasses buffer */
  201.     uchar    res1;        /* alignment */
  202.     
  203.     long    baudrate;    /* current baud rate value */
  204.     long    baudbase;    /* crystal frequency / 16 */
  205.     
  206.     ushort    intr;        /* intr number */
  207.     ushort    lockpid;    /* */
  208.     
  209.     FILEPTR    *open;        /* */
  210.     TTY    tty;        /* */
  211. };
  212.  
  213.  
  214. # define XON        0x11
  215. # define XOFF        0x13
  216.  
  217.  
  218. # if 0
  219. void int_autoprobe_start(void);
  220. int  int_autoprobe_end(void);
  221. void set_int_levelmode(uchar int_nr);
  222. # endif
  223.  
  224.  
  225. /*
  226.  * inline assembler primitives
  227.  */
  228. FASTFN ushort    spl7        (void);
  229. FASTFN void    spl        (ushort old_sr);
  230.  
  231. FASTFN void    rts_on        (UART *regs);
  232. FASTFN void    rts_off        (UART *regs);
  233. FASTFN void    dtr_on        (UART *regs);
  234. FASTFN void    dtr_off        (UART *regs);
  235. FASTFN void    brk_on        (UART *regs);
  236. FASTFN void    brk_off        (UART *regs);
  237. FASTFN void    txint_on    (UART *regs);
  238. FASTFN void    txint_off    (UART *regs);
  239.  
  240.  
  241. /*
  242.  * initialization
  243.  */
  244. FASTFN int    detect_uart    (UART *regs, ulong *baudbase);
  245. FASTFN int    init_uart    (IOVAR **iovar, ushort base, int intr, long baudbase);
  246. FASTFN void    init_pc16550    (void);
  247. DEVDRV *    _cdecl init    (struct kerinfo *k);
  248.  
  249.  
  250. /*
  251.  * buffer manipulation
  252.  */
  253. FASTFN int    iorec_empty    (IOREC *iorec);
  254. FASTFN int    iorec_full    (IOREC *iorec);
  255. FASTFN uchar    iorec_get    (IOREC *iorec);
  256. FASTFN int    iorec_put    (IOREC *iorec, uchar data);
  257. FASTFN long    iorec_used    (IOREC *iorec);
  258. FASTFN long    iorec_free    (IOREC *iorec);
  259.  
  260.  
  261. /*
  262.  * start/stop primitives
  263.  */
  264. static void    stop_receiver    (IOVAR *iovar, UART *regs);
  265. static void    start_receiver    (IOVAR *iovar, UART *regs);
  266. FASTFN void    stop_transmitter (IOVAR *iovar);
  267. FASTFN void    start_transmitter (IOVAR *iovar);
  268.  
  269.  
  270. /*
  271.  * interrupt handling
  272.  */
  273. FASTFN void    pc16550_read_x    (IOVAR *iovar, UART *regs);
  274. FASTFN void    pc16550_read_o    (IOVAR *iovar, UART *regs);
  275. FASTFN void    pc16550_read    (IOVAR *iovar, UART *regs);
  276. FASTFN void    pc16550_write    (IOVAR *iovar, UART *regs);
  277. FASTFN void    pc16550_ctsint    (IOVAR *iovar, uchar msr);
  278. static void    pc16550_int    (void);
  279.  
  280.        void    pc16550_intx    (void);
  281.        void    pc16550_int0    (void);
  282.        void    pc16550_int1    (void);
  283.        void    pc16550_int2    (void);
  284.        void    pc16550_int3    (void);
  285.        void    pc16550_int4    (void);
  286.  
  287.  
  288. /*
  289.  * device driver
  290.  */
  291. static long _cdecl    uart_open    (FILEPTR *f);
  292. static long _cdecl    uart_writeb    (FILEPTR *f, const char *buf, long bytes);
  293. static long _cdecl    uart_readb    (FILEPTR *f, char *buf, long bytes);
  294. static long _cdecl    uart_twrite    (FILEPTR *f, const char *buf, long bytes);
  295. static long _cdecl    uart_tread    (FILEPTR *f, char *buf, long bytes);
  296. static long _cdecl    uart_lseek    (FILEPTR *f, long where, int whence);
  297. static long _cdecl    uart_ioctl    (FILEPTR *f, int mode, void *buf);
  298. static long _cdecl    uart_datime    (FILEPTR *f, ushort *timeptr, int rwflag);
  299. static long _cdecl    uart_close    (FILEPTR *f, int pid);
  300. static long _cdecl    uart_select    (FILEPTR *f, long proc, int mode);
  301. static void _cdecl    uart_unselect    (FILEPTR *f, long proc, int mode);
  302.  
  303. static DEVDRV raw_devtab =
  304. {
  305.     uart_open,
  306.     uart_writeb, uart_readb, uart_lseek, uart_ioctl, uart_datime,
  307.     uart_close,
  308.     uart_select, uart_unselect,
  309. };
  310.  
  311. static DEVDRV tty_devtab =
  312. {
  313.     uart_open,
  314.     uart_twrite, uart_tread, uart_lseek, uart_ioctl, uart_datime,
  315.     uart_close,
  316.     uart_select, uart_unselect,
  317.     uart_writeb, uart_readb
  318. };
  319.  
  320.  
  321. /*
  322.  * debugging stuff
  323.  */
  324.  
  325. # ifdef DEV_DEBUG
  326. #  define DEBUG(x)    KERNEL_DEBUG x
  327. #  define TRACE(x)    KERNEL_TRACE x
  328. #  define ALERT(x)    KERNEL_ALERT x
  329. # else
  330. #  define DEBUG(x)
  331. #  define TRACE(x)
  332. #  define ALERT(x)    KERNEL_ALERT x
  333. # endif
  334.  
  335. # ifdef INT_DEBUG
  336. #  define DEBUG_I(x)    KERNEL_DEBUG x
  337. #  define TRACE_I(x)    KERNEL_TRACE x
  338. #  define ALERT_I(x)    KERNEL_ALERT x
  339. # else
  340. #  define DEBUG_I(x)
  341. #  define TRACE_I(x)
  342. #  define ALERT_I(x)    KERNEL_ALERT x
  343. # endif
  344.  
  345. /* END definition part */
  346. /****************************************************************************/
  347.  
  348. /****************************************************************************/
  349. /* BEGIN global data definition & access implementation */
  350.  
  351. /*
  352.  * global data structures
  353.  */
  354.  
  355. static IOVAR *pc16550_iovar [MAX_PORTS * 2];
  356.  
  357. # define IOVARS(nr)        (pc16550_iovar [nr])
  358. # define IOVAR_TTY_OFFSET    (MAX_PORTS)
  359. # define IOVAR_MAX        (MAX_PORTS * 2 - 1)
  360.  
  361.  
  362. /*
  363.  * interrupt data structures
  364.  */
  365.  
  366. /* ptr to first UART struct for each interrupt handler
  367.  */
  368. static IOVAR *intr_iovar [MAX_INTS];
  369.  
  370. /* ptr to interrupt handler routine, used for Setexc
  371.  */
  372. static void (*intr_handler [MAX_INTS])(void) =
  373. {
  374.     pc16550_int0,
  375.     pc16550_int1,
  376.     pc16550_int2,
  377.     pc16550_int3,
  378.     pc16550_int4
  379. };
  380.  
  381. /* END global data & access implementation */
  382. /****************************************************************************/
  383.  
  384. /****************************************************************************/
  385. /* BEGIN inline assembler primitives */
  386.  
  387. FASTFN ushort
  388. spl7 (void)
  389. {
  390.     ushort old_sr;
  391.     
  392.     __asm__ volatile
  393.     (
  394.         "move.w %%sr,%0;"
  395.         "ori #0x0700,%%sr"
  396.         : "=d" (old_sr)            /* output register */
  397.         :                 /* input registers */
  398.         : "cc"                /* clobbered */
  399.     );
  400.     
  401.     return old_sr;
  402. }
  403.  
  404. FASTFN void
  405. spl (ushort old_sr)
  406. {
  407.     __asm__ volatile
  408.     (
  409.         "move.w %0,%%sr"
  410.         :                 /* output register */
  411.         : "d" (old_sr)            /* input registers */
  412.         : "cc"                /* clobbered */
  413.     );
  414. }
  415.  
  416.  
  417.  
  418. FASTFN void
  419. rts_on (UART *regs)
  420. {
  421. # if 0
  422.     ushort sr = spl7 ();
  423.     regs->mcr |= RTSO;
  424.     spl (sr);
  425. # else
  426.     asm volatile
  427.     (
  428.         "bset.b #1,4(%0)"     /* set RTSO in MCR */
  429.         :
  430.         : "a" (regs)
  431.         : "cc"
  432.     );
  433. # endif
  434.     DEBUG_I (("PC16550 RTS on"));
  435. }
  436.  
  437. FASTFN void
  438. rts_off (UART *regs)
  439. {
  440. # if 0
  441.     ushort sr = spl7 ();
  442.     regs->mcr &= ~RTSO;
  443.     spl (sr);
  444. # else
  445.     asm volatile
  446.     (
  447.         "bclr.b #1,4(%0)"     /* delete RTSO in MCR */
  448.         :
  449.         : "a" (regs)
  450.         : "cc"
  451.     );
  452. # endif  
  453.     DEBUG_I (("PC16550 RTS off"));
  454. }
  455.  
  456.  
  457. FASTFN void
  458. dtr_on (UART *regs)
  459. {
  460.     DEBUG_I (("PC16550 DTR on"));
  461. # if 0
  462.     regs->mcr |= DTRO;
  463. # else
  464.     asm volatile
  465.     (
  466.         "bset.b #0,4(%0)"     /* set DTRO in MCR */
  467.         :
  468.         : "a" (regs)
  469.         : "cc"
  470.     );
  471. # endif
  472. }
  473.  
  474. FASTFN void
  475. dtr_off (UART *regs)
  476. {
  477.     DEBUG_I (("PC16550 DTR off"));
  478. # if 0
  479.     regs->mcr |= DTRO;
  480. # else
  481.     asm volatile
  482.     (
  483.         "bclr.b #0,4(%0)"     /* delete DTRO in MCR */
  484.         :
  485.         : "a" (regs)
  486.         : "cc"
  487.     );
  488. # endif
  489. }
  490.  
  491.  
  492. FASTFN void
  493. brk_on (UART *regs)
  494. {
  495.     DEBUG_I (("PC16550 BRK on"));
  496.     regs->lcr |= SBRK;
  497. }
  498.  
  499. FASTFN void
  500. brk_off (UART *regs)
  501. {
  502.     DEBUG_I (("PC16550 BRK off"));
  503.     regs->lcr &= ~SBRK;
  504. }
  505.  
  506.  
  507. FASTFN void
  508. txint_on (UART *regs)
  509. {
  510.     DEBUG_I (("PC16550 TXINT on"));
  511. # if 0
  512.     regs->ier |= TXLDL_IE;
  513. # else
  514.     asm volatile
  515.     (
  516.         "bset.b #1,1(%0)"     /* set TXLDL_IE in IER */
  517.         :
  518.         : "a" (regs)
  519.         : "cc"
  520.     );
  521. # endif
  522. }
  523.  
  524. FASTFN void
  525. txint_off (UART *regs)
  526. {
  527.     DEBUG_I (("PC16550 TXINT off"));
  528. # if 0
  529.     regs->ier &= ~TXLDL_IE;
  530. # else
  531.     asm volatile
  532.     (
  533.         "bclr.b #1,1(%0)"     /* delete TXLDL_IE in IER */
  534.         :
  535.         : "a" (regs)
  536.         : "cc"
  537.     );
  538. # endif
  539. }
  540.  
  541. /* END inline assembler primitives */
  542. /****************************************************************************/
  543.  
  544. /****************************************************************************/
  545. /* BEGIN initialization */
  546.  
  547. /*
  548.  * Autodetect a UART.
  549.  * 
  550.  * This routine first does some sanity checks to be sure that there is a
  551.  * UART at the diven address. It then enables the interrupt and toggles the
  552.  * IER to generate an interrupt, to autodetect the interrupt line. The
  553.  * interrupt driver is disabled after this, which means that multiple UARTs
  554.  * using the same interrupt will be detected OK even if the hardware does
  555.  * not support sharing the interrupt line once all UARTs are enabled later.
  556.  * The last thing is to measure the BRG crystal by transmitting some
  557.  * characters (in loopback mode) with disabled FIFOs and measuring the time
  558.  * needed by using MFP timer A.
  559.  * 
  560.  * We time sending 18 characters (or 180 bits) at the highest possible speed
  561.  * (BRG divide by 1, or 115200 bps at 1.8432MHz). At a MFP clock of
  562.  * 2.4576MHz and a :16 prescaler, this gives the following counted values:
  563.  * 
  564.  * Crystal (MHz)   count    BRG=1 rate
  565.  * 1.8432          240      115200
  566.  * 3.6864          120      230400
  567.  * 7.3728           60      460800
  568.  * 
  569.  * 4.0             111      250000 (for MIDI cards)
  570.  * 6.0              74      375000 (for MIDI cards)
  571.  * 
  572.  */
  573.  
  574. /* only in one place used -> FASTFN
  575.  */
  576. FASTFN int
  577. detect_uart (UART *regs, ulong *baudbase)
  578. {
  579.     ulong rate = 115200;
  580.     int intr = 0;
  581.     int i;
  582.     
  583.     
  584.     *baudbase = 0L;
  585.     
  586.     /* read LSR */ 
  587.     (void) regs->lsr;
  588.     /* now LSR may not be $FF! */
  589.     if (regs->lsr == 0xff)
  590.         return 0;
  591.     
  592.     regs->scr = 0x55;
  593.     if (regs->scr != 0x55)
  594.         return 0;
  595.     
  596.     regs->scr = 0xAA;
  597.     if (regs->scr != 0xAA)
  598.         return 0;
  599.     
  600.     /* set DLAB */
  601.     regs->lcr = 0x83;
  602.     
  603.     /* set baudrate */
  604.     regs->dlm = (115200 / rate) >> 8;
  605.     regs->dll = (115200 / rate) & 0xFF;
  606.     
  607.     /* 8N1 */
  608.     regs->lcr = 0x03;
  609.     regs->ier = 0;
  610.     
  611.     /* Reset FIFOs */
  612.     regs->fcr = RXFR | TXFR;
  613.     /* Disable FIFOs */
  614.     regs->fcr = 0;
  615.     
  616.     /* enable loopback */
  617.     regs->mcr = LOOP;
  618.     
  619.     /* check loopback */
  620.     if ((regs->msr & 0xf0) != 0)
  621.         return 0;
  622.     
  623.     /* enable loopback */
  624.     regs->mcr = LOOP | 0x0f;
  625.     
  626.     /* check loopback */
  627.     if ((regs->msr & 0xf0) != 0xf0)
  628.         return 0;
  629.     
  630. # if 0
  631.     int_autoprobe_start ();
  632.     
  633.     regs->mcr = GI_EN;
  634.     
  635.     /* this will create enough INTs */
  636.     regs->ier = 0x00;
  637.     regs->ier = 0x0f;
  638.     regs->ier = 0x00;
  639.     regs->ier = 0x0f;
  640.     
  641.     /* short delay */
  642.     for (i = 255; i >= 0; i--)
  643.         (void) regs->rbr;
  644.     
  645.     regs->ier = 0;
  646.     regs->mcr = 0;
  647.     
  648.     intr = int_autoprobe_end ();
  649. # else
  650.     if ((UART *) (0x03f8L + 0xc0000000L) == regs)
  651.     {
  652.         /* builtin port 1 */
  653.         intr = 4;
  654.     }
  655.     else if ((UART *) (0x02f8L + 0xc0000000L) == regs)
  656.     {
  657.         /* builtin port 2 */
  658.         intr = 3;
  659.     }
  660.     else
  661.     {
  662.         /* no detection available yet */
  663.         intr = 0;
  664.     }
  665. # endif
  666.     
  667.     if (intr > 0)
  668.     {
  669. # if 0
  670.         *baudbase = 115200L;
  671. # else
  672. /*        volatile uchar *tcdr = (volatile uchar *) 0xffffc103L + 17 * 4; */
  673.         volatile uchar *tadr = (volatile uchar *) 0xffffc103L + 15 * 4;
  674.         volatile uchar *tacr = (volatile uchar *) 0xffffc103L + 12 * 4;
  675.         
  676.         ushort sr;
  677.         short time;
  678.         
  679.         
  680.         sr = spl7 ();
  681.         
  682.         /* enable loopback */
  683.         regs->mcr = LOOP; 
  684.         
  685.         *tacr = 0;
  686.         *tadr = 0xff;
  687.         while (*tadr != 0xff)
  688.             ;
  689.         
  690.         for (i = 0; i < 19; i++)
  691.         {
  692.             /* send 1 char */
  693.             regs->thr = 0x00;
  694.             
  695.             /* wait until done */
  696.             while ((regs->lsr & TXDE) == 0)
  697.                 ;
  698.             
  699.             if (i == 0)
  700.                 *tacr = 3;
  701.         }
  702.         
  703.         /* stop timer */
  704.         *tacr = 0;
  705.         time = 255 - *tadr;
  706.         
  707.         /* get Rx data */
  708.         while ((regs->lsr & RXDA))
  709.             (void) regs->rbr;
  710.         
  711.         /* disable loopback */
  712.         regs->mcr = GI_EN;
  713.         (void) regs->iir;
  714.         (void) regs->msr;
  715.         
  716.         spl (sr);
  717.         
  718.         
  719.         if      (time > 230 && time <= 250)    *baudbase = 115200L;
  720.         else if (time > 115 && time <= 125)    *baudbase = 230400L;
  721.         else if (time >  55 && time <=  65)    *baudbase = 460800L;
  722.         else if (time > 105 && time <= 115)    *baudbase = 250000L;
  723.         else if (time >  70 && time <=  80)    *baudbase = 375000L;
  724. # endif
  725.         
  726.         DEBUG (("detect_clock: t = %d, baudbase = %lu", time, *baudbase));
  727.     }
  728.     
  729.     /* Reset FIFOs */
  730.     regs->fcr = FIFO_EN | RXFR | TXFR;
  731.     regs->fcr = FIFO_EN | RXFTH_8;
  732.     
  733.     if ((regs->iir & 0xc0) != 0xc0)
  734.     {
  735.         DEBUG (("no 16550A at %lx, INT %i", regs, intr));
  736.         return 0;
  737.     }
  738.     
  739.     DEBUG (("detected 16550A at %lx, INT %i", regs, intr));
  740.     return intr;
  741. }
  742.  
  743. /* only in one place used -> FASTFN
  744.  */
  745. FASTFN int
  746. init_uart (IOVAR **iovar, ushort base, int intr, long baudbase)
  747. {
  748.     char *buffer;
  749.     
  750.     *iovar = kmalloc (sizeof (**iovar));
  751.     if (!*iovar)
  752.         goto error;
  753.     
  754.     bzero (*iovar, sizeof (**iovar));
  755.     
  756.     buffer = kmalloc (2 * IOBUFSIZE);
  757.     if (!buffer)
  758.         goto error;
  759.     
  760.     (*iovar)->input.buffer = buffer;
  761.     (*iovar)->output.buffer = buffer + IOBUFSIZE;
  762.     
  763.     (*iovar)->input.size = (*iovar)->output.size = IOBUFSIZE;
  764.     (*iovar)->input.low_water = (*iovar)->output.low_water = 1 * (IOBUFSIZE / 4);
  765.     (*iovar)->input.high_water = (*iovar)->output.high_water = 3 * (IOBUFSIZE / 4);
  766.     
  767.     (*iovar)->regs = (UART *) (0xC0000000L | base);
  768.     (*iovar)->intr = intr;
  769.     (*iovar)->baudbase = baudbase;
  770.     
  771.     {
  772.         UART *regs = (*iovar)->regs;
  773.         long div;
  774.         
  775.         regs->ier = 0;
  776.         
  777.         (*iovar)->baudrate = 9600;
  778.         div = (*iovar)->baudbase / 9600;
  779.         
  780.         regs->lcr |= BNKSE;
  781.         regs->dll = (div     ) & 0xFF;
  782.         regs->dlm = (div >> 8) & 0xFF;
  783.         regs->lcr &= ~BNKSE;
  784.         
  785.         /* Reset FIFOs */
  786.         regs->fcr = FIFO_EN | RXFR | TXFR;
  787.         /* Enable FIFOs, set Rcv Threshold */
  788.         regs->fcr = FIFO_EN | RXFTH_8;
  789.         
  790.         regs->lcr = 3;    /* 8bit char, 1 stopbit, no parity */
  791.         
  792.         (*iovar)->rxoff = 0;            /* receiver on */
  793.         (*iovar)->txoff = 1;            /* transmitter off */
  794.         (*iovar)->hsk_mode = SHAKE_RTS_CTS;    /* RTS/CTS */
  795.         
  796.         rts_on (regs);    
  797.         dtr_on (regs);
  798.         
  799.         regs->ier = RXHDL_IE | LS_IE | MS_IE;
  800.         regs->mcr |= (GI_EN | RTSO);
  801.     }
  802.     
  803.     return 1;
  804.     
  805. error:
  806.     if (*iovar)
  807.         kfree (*iovar);
  808.     
  809.     ALERT (("uart.xdd: kmalloc(%li, %li) fail, out of memory?", sizeof (**iovar), IOBUFSIZE));
  810.     return 0;
  811. }
  812.     
  813. /* only in one place used -> FASTFN
  814.  */
  815. FASTFN void
  816. init_pc16550 (void)
  817. {
  818. # define NUM_BASES 12
  819.     ushort bases[NUM_BASES] =
  820.     {
  821.         0x03f8L, 0x02f8L,            /* on-board SERIAL1 + SERIAL2 */
  822.         0x03e8L, 0x02e8L,
  823.         0x02a0L, 0x02a8L, 0x02b0, 0x02b8,    /* first AST fourport */
  824.         0x01a0L, 0x01a8L, 0x01b0, 0x01b8    /* second AST fourport */ 
  825.     };
  826.     ulong baudbase[NUM_BASES];
  827.     uchar intr[NUM_BASES];
  828.     
  829.     static int did_init;
  830.     
  831.     int i, j;
  832.     ushort sr;
  833.     
  834.     int current_iovar = 0;
  835.     int intr_num = 0;
  836.     
  837.     
  838.     if (!did_init)
  839.     {
  840.         for (i = 0; i < NUM_BASES; i++)
  841.             intr[i] = detect_uart ((UART *) (bases[i] + 0xc0000000L), &baudbase[i]);
  842.         
  843.         did_init = 1;
  844.     }
  845.     
  846.     DEBUG (("UARTS found:"));
  847.     
  848.     sr = spl7 ();
  849.     for (i = 0; i < NUM_BASES; i++)
  850.     {
  851.         if (intr[i] && baudbase[i] && current_iovar < MAX_PORTS)
  852.         {
  853.             DEBUG (("base %x, intr %i, baudbase %lu", bases[i], intr[i], baudbase[i]));
  854.             
  855.             if (init_uart (&(IOVARS (current_iovar)), bases[i], intr[i], baudbase[i]))
  856.                 current_iovar++;
  857.         }
  858.     }
  859.     
  860.     /* install interrupt handlers
  861.      * chain iovars into a linked list per shared interrupt
  862.      */
  863.     for (i = 0; i < current_iovar; i++)
  864.     {
  865.         int chain_int = 0;
  866.         
  867.         DEBUG (("installing INT for UART %d:",i));
  868.         
  869.         for (j = 0; j < i; j++)
  870.             if (IOVARS (i)->intr == IOVARS (j)->intr)
  871.                 chain_int = j;
  872.         
  873.         if (chain_int)
  874.         {
  875.             DEBUG (("chaining iovar %d to iovar %d", i, chain_int));
  876.             
  877.             IOVARS (chain_int)->next = IOVARS (i);
  878.             /* set_int_levelmode (IOVARS (i)->intr); */
  879.         }
  880.         else if (intr_num < MAX_INTS)
  881.         {
  882.             void *old;
  883.             
  884.             DEBUG (("allocating new int handler %d to iovar %d, INT %d", intr_num, i, IOVARS (i)->intr));
  885.             
  886.             intr_iovar[intr_num] = IOVARS (i);
  887.             old = Setexc (80 + IOVARS (i)->intr, intr_handler[intr_num]);
  888.             DEBUG (("old int handler = %lx", old));
  889.             
  890.             intr_num++;
  891.         }
  892.         else
  893.             DEBUG (("ERROR: no free int handler for UART using int %d", IOVARS (i)->intr));
  894.     }
  895.     
  896.     spl (sr);
  897. }
  898.  
  899. DEVDRV * _cdecl
  900. init (struct kerinfo *k)
  901. {
  902.     RSVF *rsvfptr;
  903.     RSVF *rsvf;
  904.     char *ptr;
  905.     long mch;
  906.     int initialized;
  907.     int i;
  908.     
  909.     struct dev_descr raw_dev_descriptor =
  910.     {
  911.         &raw_devtab,
  912.         0,        /* dinfo -> fc.aux */
  913.         0,        /* flags */
  914.         NULL,        /* struct tty * */
  915.         0,        /* drvsize */
  916.         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
  917.         { 0, 0 }
  918.     };
  919.     
  920.     struct dev_descr tty_dev_descriptor =
  921.     {
  922.         &tty_devtab,
  923.         0,        /* dinfo -> fc.aux */
  924.         O_TTY,        /* flags */
  925.         NULL,        /* struct tty * */
  926.         44,        /* drvsize */
  927.         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
  928.         { 0, 0 }
  929.     };
  930.     
  931.     
  932.     kernel = k;
  933.     
  934.     c_conws (MSG_BOOT);
  935.     c_conws (MSG_GREET);
  936.     
  937.     DEBUG (("%s: enter init", __FILE__));
  938.     
  939.     if ((MINT_MAJOR == 0)
  940.         || ((MINT_MAJOR == 1) && (MINT_MINOR < 15)))
  941.     {
  942.         c_conws (MSG_MINT);
  943.         goto failure;
  944.     }
  945.     
  946. # define SSYS_GETCOOKIE    8
  947. # define COOKIE__MCH    0x5f4d4348L
  948. # define MILAN_C    0x00040000L
  949.     if ((s_system (SSYS_GETCOOKIE, COOKIE__MCH, &mch) != 0)
  950.         || (mch != MILAN_C))
  951.     {
  952.         c_conws (MSG_MILAN);
  953.         goto failure;
  954.     }
  955.     
  956.     /* temporary until MiNT will do this */
  957. # define RSVF_BUF 1024L
  958.     rsvf = rsvfptr = (RSVF *) m_xalloc (RSVF_BUF, 0x40);
  959.     if (!rsvf)
  960.     {
  961.         DEBUG (("%s: m_xalloc fail!", __FILE__));
  962.         goto failure;
  963.     }
  964.     
  965.     bzero (rsvf, RSVF_BUF);
  966.     
  967.     ptr = (char *) rsvf;
  968.     ptr += 512;
  969.     
  970.     init_pc16550 ();
  971.     initialized = 1;
  972.     
  973.     for (i = 0; i < MAX_PORTS && IOVARS (i); i++)
  974.     {
  975.         char name [64];
  976.         
  977.         
  978.         ksprintf (name, "u:\\dev\\%s%i", RSVF_BASENAME, i + RSVF_OFFSETT);
  979.         
  980.         raw_dev_descriptor.dinfo = i;
  981.         raw_dev_descriptor.tty = &(IOVARS (i)->tty);
  982.         if (d_cntl (DEV_INSTALL, name, &raw_dev_descriptor) >= 0)
  983.         {
  984.             DEBUG (("%s: %s installed", __FILE__, name));
  985.             
  986.             rsvfptr->data = ptr;
  987.             rsvfptr->type = RSVF_PORT | RSVF_GEMDOS | RSVF_BIOS;
  988.             rsvfptr->bdev = 7 + i;
  989.             
  990.             ksprintf (rsvfptr->data, "%s%i", RSVF_BASENAME, i + RSVF_OFFSETT);
  991.             
  992.             DEBUG (("uart: installed %s on %i", rsvfptr->data, 7 + i));
  993.             
  994.             ptr += ((strlen (rsvfptr->data) + 1) + 3) & ~3;
  995.             rsvfptr++;
  996.         }
  997.         
  998.         
  999.         ksprintf (name, "u:\\dev\\%s%c", TTY_BASENAME, (char) (i + TTY_OFFSETT));
  1000.         
  1001.         tty_dev_descriptor.dinfo = i + IOVAR_TTY_OFFSET;
  1002.         tty_dev_descriptor.tty = &(IOVARS (i)->tty);
  1003.         if (d_cntl (DEV_INSTALL, name, &tty_dev_descriptor) >= 0)
  1004.         {
  1005.             DEBUG (("%s: %s installed", __FILE__, name));
  1006.             
  1007.             IOVARS (i + IOVAR_TTY_OFFSET) = IOVARS (i);
  1008.         }
  1009.     }
  1010.     
  1011.     if (initialized)
  1012.     {
  1013. # define COOKIE_RSVF    0x52535646L
  1014. # define SSYS_SETCOOKIE    9
  1015.         s_system (SSYS_SETCOOKIE, COOKIE_RSVF, rsvf);
  1016.         
  1017.         return (DEVDRV *) 1;
  1018.     }
  1019.     
  1020. failure:
  1021. # if 0
  1022.     if (rsvf)
  1023.         m_free (rsvf);
  1024. # endif
  1025.     
  1026.     c_conws (MSG_FAILURE);
  1027.     return NULL;
  1028. }
  1029.  
  1030. /* END initialization */
  1031. /****************************************************************************/
  1032.  
  1033. /****************************************************************************/
  1034. /* BEGIN buffer manipulation */
  1035.  
  1036. /* helper function */
  1037. FASTFN ushort
  1038. inc_ptr (ushort ptr, ushort size)
  1039. {
  1040.     if (++ptr >= size)
  1041.         ptr = 0;
  1042.     
  1043.     return ptr;
  1044. }
  1045.  
  1046. FASTFN int
  1047. iorec_empty (IOREC *iorec)
  1048. {
  1049.     return (iorec->head == iorec->tail);
  1050. }
  1051.  
  1052. FASTFN int
  1053. iorec_full (IOREC *iorec)
  1054. {
  1055.     return (iorec->head == inc_ptr (iorec->tail, iorec->size));
  1056. }
  1057.  
  1058. FASTFN uchar
  1059. iorec_get (IOREC *iorec)
  1060. {
  1061.     register ushort i = inc_ptr (iorec->head, iorec->size);
  1062.     register uchar data;
  1063.     
  1064.     data = iorec->buffer[i];
  1065.     iorec->head = i;
  1066.     
  1067.     return data;
  1068. }
  1069.  
  1070. FASTFN int
  1071. iorec_put (IOREC *iorec, uchar data)
  1072. {
  1073.     register ushort i = inc_ptr (iorec->tail, iorec->size);
  1074.     
  1075.     if (i == iorec->head)
  1076.     {
  1077.         /* buffer full */
  1078.         return 0;
  1079.     }
  1080.     
  1081.     iorec->buffer[i] = data;
  1082.     iorec->tail = i;
  1083.     
  1084.     return 1;
  1085. }
  1086.  
  1087. FASTFN long
  1088. iorec_used (IOREC *iorec)
  1089. {
  1090.     register long tmp;
  1091.     
  1092.     tmp = iorec->tail;
  1093.     tmp -= iorec->head;
  1094.     
  1095.     if (tmp < 0)
  1096.         tmp += iorec->size;
  1097.     
  1098.     return tmp;
  1099. }
  1100.  
  1101. FASTFN long
  1102. iorec_free (IOREC *iorec)
  1103. {
  1104.     register long tmp;
  1105.     
  1106.     tmp = iorec->head;
  1107.     tmp -= iorec->tail;
  1108.     
  1109.     if (tmp <= 0)
  1110.         tmp += iorec->size;
  1111.     
  1112.     return tmp;
  1113. }
  1114.  
  1115. /* END buffer manipulation */
  1116. /****************************************************************************/
  1117.  
  1118. /****************************************************************************/
  1119. /* BEGIN start/stop primitives */
  1120.  
  1121. static void
  1122. stop_receiver (IOVAR *iovar, UART *regs)
  1123. {
  1124.     if (!iovar->rxoff)
  1125.     {
  1126.         /* set stop flag */
  1127.         iovar->rxoff = 1;
  1128.         
  1129.         DEBUG_I (("uart: stop receiver"));
  1130.         
  1131.         if (iovar->hsk_mode & SHAKE_XON_OFF)
  1132.         {
  1133.             /* send XOFF */
  1134.             iovar->sendnow = XOFF;
  1135.             
  1136.             /* enable interrupt */
  1137.             txint_on (regs);
  1138.         }
  1139.         
  1140.         if (iovar->hsk_mode & SHAKE_RTS_CTS)
  1141.         {
  1142.             /* set rts off */
  1143.             rts_off (regs);
  1144.         }
  1145.     }
  1146. }
  1147.  
  1148. static void
  1149. start_receiver (IOVAR *iovar, UART *regs)
  1150. {
  1151.     if (iovar->rxoff)
  1152.     {
  1153.         /* clear stop flag */
  1154.         iovar->rxoff = 0;
  1155.         
  1156.         DEBUG_I (("uart: start receiver"));
  1157.         
  1158.         if (iovar->hsk_mode & SHAKE_RTS_CTS)
  1159.         {
  1160.             /* set rts on */
  1161.             rts_on (regs);
  1162.         }
  1163.         
  1164.         if (iovar->hsk_mode & SHAKE_XON_OFF)
  1165.         {
  1166.             /* send XON */
  1167.             iovar->sendnow = XON;
  1168.             
  1169.             /* enable interrupt */
  1170.             txint_on (regs);
  1171.         }
  1172.     }
  1173. }
  1174.  
  1175. FASTFN void
  1176. stop_transmitter (IOVAR *iovar)
  1177. {
  1178.     /* set stop flag */
  1179.     iovar->txoff = 1;
  1180.     
  1181.     DEBUG_I (("uart: transmitter stoped"));
  1182. }
  1183.  
  1184. FASTFN void
  1185. start_transmitter (IOVAR *iovar)
  1186. {
  1187.     DEBUG_I (("uart: transmitter started"));
  1188.     
  1189.     /* clear stop flag */
  1190.     iovar->txoff = 0;
  1191.     
  1192.     /* enable interrupt */
  1193.     txint_on (iovar->regs);
  1194. }
  1195.  
  1196. /* END start/stop primitives */
  1197. /****************************************************************************/
  1198.  
  1199. /****************************************************************************/
  1200. /* BEGIN interrupt handling */
  1201.  
  1202. /*
  1203.  * pc16550_read(): uart receive buffer full.
  1204.  * Holt Zeichen vom UART und schreibt es in den Puffer.
  1205.  * XON/XOFF- oder RTS/CTS-Mode wird beachtet.
  1206.  * 
  1207.  * only called from pc16550_int
  1208.  */
  1209.  
  1210. FASTFN void
  1211. pc16550_read_x (IOVAR *iovar, UART *regs)
  1212. {
  1213.     while (regs->lsr & RXDA)
  1214.     {
  1215.         register uchar data = regs->rbr;
  1216.         
  1217.         if (data == XOFF)
  1218.         {
  1219.             /* receiver can't accept more data */
  1220.             
  1221.             stop_transmitter (iovar);
  1222.         }
  1223.         else if (data == XON)
  1224.         {
  1225.             /* receiver ready now */
  1226.             
  1227.             start_transmitter (iovar);
  1228.         }
  1229.         else
  1230.         {
  1231.             DEBUG_I (("rcv: put data %d in buffer", data));
  1232.             
  1233.             if (!iorec_put (&iovar->input, data))
  1234.             {
  1235.                 DEBUG_I (("rcvint: buffer full!"));
  1236.             }
  1237.         }
  1238.     }
  1239. }
  1240.  
  1241. FASTFN void
  1242. pc16550_read_o (IOVAR *iovar, UART *regs)
  1243. {
  1244.     while (regs->lsr & RXDA)
  1245.     {
  1246.         register uchar data = regs->rbr;
  1247.         
  1248.         DEBUG_I (("rcv: put data %d in buffer", data));
  1249.         
  1250.         if (!iorec_put (&iovar->input, data))
  1251.         {
  1252.             DEBUG_I (("rcvint: buffer full!"));
  1253.         }
  1254.     }
  1255. }
  1256.  
  1257. FASTFN void
  1258. pc16550_read (IOVAR *iovar, UART *regs)
  1259. {
  1260.     if (iovar->hsk_mode & SHAKE_XON_OFF)    pc16550_read_x (iovar, regs);
  1261.     else                    pc16550_read_o (iovar, regs);
  1262.     
  1263.     if (iovar->hsk_mode == 0 || iovar->rxoff)
  1264.     {
  1265.         /* no handshake or already off */
  1266.         return;
  1267.     }
  1268.     
  1269.     /* in handshake mode test the free space
  1270.      */
  1271.     if (iorec_used (&iovar->input) > iovar->input.high_water)
  1272.         stop_receiver (iovar, regs);
  1273. }
  1274.  
  1275. /*
  1276.  * pc16550_write(): 
  1277.  * 
  1278.  * only called from pc16550_int
  1279.  */
  1280. FASTFN void
  1281. pc16550_write (IOVAR *iovar, UART *regs)
  1282. {
  1283.     register int count = 16;
  1284.     
  1285.     if (iovar->sendnow)
  1286.     {
  1287.         /* control byte
  1288.          */
  1289.         
  1290.         DEBUG_I (("pc16550_write: send control %i", iovar->sendnow));
  1291.         
  1292.         regs->thr = iovar->sendnow;
  1293.         iovar->sendnow = 0;
  1294.         
  1295.         count--;
  1296.     }
  1297.     
  1298.     /* real data
  1299.      */
  1300.     
  1301.     /* is somebody ready to receive data? */
  1302.     if (iovar->hsk_mode && iovar->txoff)
  1303.     {
  1304.         DEBUG_I (("pc16550_write: sender disabled - INT turned off, ier=$%x", regs->ier));
  1305.         
  1306.         /* disable interrupt */
  1307.         txint_off (regs);
  1308.     }
  1309.     else
  1310.     {
  1311.         while (count--)
  1312.         {
  1313.             if (iorec_empty (&iovar->output))
  1314.             {
  1315.                 DEBUG_I (("pc16550_write: buffer empty - INT turned off, ier=$%x", regs->ier));
  1316.                 
  1317.                 /* disable interrupt */
  1318.                 txint_off (regs);
  1319.                 
  1320.                 break;
  1321.             }
  1322.             
  1323.             /* send character from buffer */
  1324.             regs->thr = iorec_get (&iovar->output);
  1325.         }
  1326.     }
  1327. }
  1328.  
  1329. /*
  1330.  * pc16550_ctsint(): CTS-Interruptroutine.
  1331.  * 
  1332.  * only called from pc16550_int
  1333.  */
  1334. FASTFN void
  1335. pc16550_ctsint (IOVAR *iovar, uchar msr)
  1336. {
  1337.     if (iovar->hsk_mode & SHAKE_RTS_CTS)
  1338.     {
  1339.         DEBUG_I (("ctsint: (RTS/CTS active)"));
  1340.         
  1341.         if (msr & CTSI)
  1342.             /* CTS is on */
  1343.             start_transmitter (iovar);
  1344.         else
  1345.             /* CTS is off */
  1346.             stop_transmitter (iovar);
  1347.     }
  1348. }
  1349.  
  1350. /*
  1351.  * Der eigentliche Interrupthandler. Wird vom Assemblerteil aufgerufen.
  1352.  * HACK: Der IOVAR-Zeiger wird in A0 uebergeben!
  1353.  */
  1354. static void
  1355. pc16550_int (void)
  1356. {
  1357.     IOVAR *iovar;
  1358.     UART *regs;
  1359.     ushort sr;
  1360.     uchar event;
  1361.     
  1362.     asm volatile
  1363.     (
  1364.         "move.l %%a0,%0"
  1365.         : "=da" (iovar)        /* output register */
  1366.         :             /* input registers */
  1367.         : "cc"            /* clobbered */
  1368.     );
  1369.     
  1370. next_uart:
  1371.     
  1372.     regs = iovar->regs;
  1373.     DEBUG_I (("pc16550_int: handling UART at %lx", regs));
  1374.     
  1375.     sr = spl7 ();
  1376.     
  1377.     while (!((event = (regs->iir & 0x0f)) & 1))
  1378.     {
  1379.         /* Int pending */
  1380.         
  1381.         DEBUG_I (("pc16550_int: event %d ", event));
  1382.         
  1383.         switch (event)
  1384.         {
  1385.             case 6:        /* Highest priority */
  1386.             {
  1387.                 /* Parity error, framing error, data overrun
  1388.                  * or break event
  1389.                  */
  1390.                 if (regs->lsr & OE)
  1391.                     pc16550_read (iovar, regs);
  1392.                 else
  1393.                     (void) regs->rbr;
  1394.                 
  1395.                 break;
  1396.             }
  1397.             case 4:
  1398.             {
  1399.                 /* Receive Buffer Register (RBR) full, or
  1400.                  * reception FIFO level equal to or above
  1401.                  * treshold
  1402.                  */
  1403.             }
  1404.             case 12:
  1405.             {
  1406.                 /* At least one character is in the reception
  1407.                  * FIFO, and no character has been input to or
  1408.                  * read from the reception FIFO for four
  1409.                  * character times
  1410.                  */
  1411.                 pc16550_read (iovar, regs);
  1412.                 
  1413.                 break;
  1414.             }
  1415.             case 2:
  1416.             {
  1417.                 /* Transmitter Data Register Empty
  1418.                  */
  1419.                 pc16550_write (iovar, regs);
  1420.                 
  1421.                 break;
  1422.             }
  1423.             case 0:
  1424.             {
  1425.                 /* Any transition on /CTS, /DSR or /DCD or a low to
  1426.                  * high transition on /RI
  1427.                  */
  1428.                 register uchar msr = regs->msr;
  1429.                 
  1430.                 if (msr & DCTS)
  1431.                     pc16550_ctsint (iovar, msr);
  1432.                 
  1433.                 /* (msr & DDSR)
  1434.                     ; */
  1435.                 
  1436.                 /* (msr & TERI)
  1437.                     ; */
  1438.                 
  1439.                 /* (msr & DDCD)
  1440.                     ; */
  1441.                 
  1442.                 DEBUG_I (("pc16550_int: E0: %d", msr));
  1443.                 break;
  1444.             }
  1445.             default:
  1446.             {
  1447.                 /* unknown event
  1448.                  */
  1449.                 
  1450.                 (void) regs->lsr;
  1451.                 (void) regs->msr;
  1452.                 
  1453.                 DEBUG_I (("pc16550_int: unknown event, ignored"));
  1454.                 break;
  1455.             }
  1456.         }
  1457.     }
  1458.     
  1459.     spl (sr);
  1460.     
  1461.     iovar = iovar->next;
  1462.     if (iovar)
  1463.     {
  1464.         DEBUG_I (("pc16550_int: continuing on next IOVAR!"));
  1465.         goto next_uart;
  1466.     }
  1467.     
  1468.     DEBUG_I (("PC16550_int: exit"));
  1469. }
  1470.  
  1471. /* Interrupt-Routinen fuer PC16550 - rufen die eigentlichen C-Routinen auf
  1472.  */
  1473. void
  1474. pc16550_intx (void)
  1475. {
  1476.     (void) pc16550_int;    /* tell the compiler that we need it */
  1477.     
  1478.     asm volatile
  1479.     (
  1480.         "_pc16550_int0:
  1481.          movem.l %%a0-%%a2/%%d0-%%d2,-(%%sp)
  1482.          move.l  _intr_iovar,%%a0
  1483.          bsr     _pc16550_int
  1484.          movem.l (%%sp)+,%%a0-%%a2/%%d0-%%d2
  1485.          rte"
  1486.         :             /* output register */
  1487.         :              /* input registers */
  1488.                      /* clobbered */
  1489.     );
  1490.     
  1491.     asm volatile
  1492.     (
  1493.         "_pc16550_int1:
  1494.          movem.l %%a0-%%a2/%%d0-%%d2,-(%%sp)
  1495.          move.l  _intr_iovar+4,%%a0
  1496.          bsr     _pc16550_int
  1497.          movem.l (%%sp)+,%%a0-%%a2/%%d0-%%d2
  1498.          rte"
  1499.         :             /* output register */
  1500.         :              /* input registers */
  1501.                      /* clobbered */
  1502.     );
  1503.     
  1504.     asm volatile
  1505.     (
  1506.         "_pc16550_int2:
  1507.          movem.l %%a0-%%a2/%%d0-%%d2,-(%%sp)
  1508.          move.l  _intr_iovar+8,%%a0
  1509.          bsr     _pc16550_int
  1510.          movem.l (%%sp)+,%%a0-%%a2/%%d0-%%d2
  1511.          rte"
  1512.         :             /* output register */
  1513.         :              /* input registers */
  1514.                      /* clobbered */
  1515.     );
  1516.     
  1517.     asm volatile
  1518.     (
  1519.         "_pc16550_int3:
  1520.          movem.l %%a0-%%a2/%%d0-%%d2,-(%%sp)
  1521.          move.l  _intr_iovar+12,%%a0
  1522.          bsr     _pc16550_int
  1523.          movem.l (%%sp)+,%%a0-%%a2/%%d0-%%d2
  1524.          rte"
  1525.         :             /* output register */
  1526.         :              /* input registers */
  1527.                      /* clobbered */
  1528.     );
  1529.     
  1530.     asm volatile
  1531.     (
  1532.         "_pc16550_int4:
  1533.          movem.l %%a0-%%a2/%%d0-%%d2,-(%%sp)
  1534.          move.l  _intr_iovar+16,%%a0
  1535.          bsr     _pc16550_int
  1536.          movem.l (%%sp)+,%%a0-%%a2/%%d0-%%d2
  1537.          rte"
  1538.         :             /* output register */
  1539.         :              /* input registers */
  1540.                      /* clobbered */
  1541.     );
  1542. }
  1543.  
  1544. /* END interrupt handling */
  1545. /****************************************************************************/
  1546.  
  1547. /****************************************************************************/
  1548. /* BEGIN  */
  1549.  
  1550. static void _cdecl
  1551. check_select (void)
  1552. {
  1553.     int flag = 0;
  1554.     int i;
  1555.     
  1556.     for (i = 0; IOVARS (i); i++)
  1557.     {
  1558.         IOVAR *iovar = IOVARS (i);
  1559.         
  1560.         if (iovar->tty.rsel)
  1561.         {
  1562.             if (!iorec_empty (&iovar->input))
  1563.                 wakeselect (iovar->tty.rsel);
  1564.             else
  1565.                 flag = 1;
  1566.         }
  1567.         
  1568.         if (iovar->tty.wsel)
  1569.         {
  1570.             if (iorec_free (&iovar->output))
  1571.                 wakeselect (iovar->tty.wsel);
  1572.             else
  1573.                 flag = 1;
  1574.         }
  1575.     }
  1576.     
  1577.     if (flag)
  1578.         addroottimeout (1000L, check_select, 0);
  1579. }
  1580.  
  1581. /* END  */
  1582. /****************************************************************************/
  1583.  
  1584. /****************************************************************************/
  1585. /* BEGIN device driver routines */
  1586.  
  1587. static long _cdecl
  1588. uart_open (FILEPTR *f)
  1589. {
  1590.     ushort dev = f->fc.aux;
  1591.     IOVAR *iovar;
  1592.     
  1593.     DEBUG (("uart_open [%i]: enter (%lx)", f->fc.aux, f->flags));
  1594.     
  1595.     if (dev > IOVAR_MAX)
  1596.         return EACCDN;
  1597.     
  1598.     iovar = IOVARS (dev);
  1599.     
  1600.     if (iovar->open && denyshare (iovar->open, f))
  1601.     {
  1602.         DEBUG (("uart_open: file sharing denied"));
  1603.         return EACCDN;
  1604.     }
  1605.     
  1606.     f->pos = 0;
  1607.     f->next = iovar->open;
  1608.     iovar->open = f;
  1609.     
  1610.     if (dev >= IOVAR_TTY_OFFSET)
  1611.         f->flags |= O_TTY;
  1612.     
  1613.     return E_OK;
  1614. }
  1615.  
  1616. static long _cdecl
  1617. uart_writeb (FILEPTR *f, const char *buf, long bytes)
  1618. {
  1619.     IOVAR *iovar = IOVARS (f->fc.aux);
  1620.     IOREC *iorec = &iovar->output;
  1621.     long done = 0;
  1622.     
  1623.     DEBUG (("uart_writeb [%i]: enter (%lx, %ld)", f->fc.aux, buf, bytes));
  1624.     for (;;)
  1625.     {
  1626.         /* copy as much as possible */
  1627.         while ((bytes > 0) && iorec_put (iorec, *buf))
  1628.         {
  1629.             DEBUG (("%x - %c", (int) *buf, *buf));
  1630.             
  1631.             buf++; done++;
  1632.             bytes--;
  1633.         }
  1634.         
  1635.         /* start transfer - interrupt controlled */
  1636.         start_transmitter (iovar);
  1637.         
  1638.         if (f->flags & O_NDELAY)
  1639.         {
  1640.             if (!done)
  1641.                 done = EWOULDBLOCK;
  1642.             
  1643.             break;
  1644.         }
  1645.         
  1646.         if (!bytes)
  1647.             break;
  1648.         
  1649.         /* sleep until there is enough room in the buffer
  1650.          * to continue
  1651.          */
  1652.         while (iorec_used (iorec) > iorec->high_water)
  1653.             sleep (READY_Q, 0L);
  1654.     }
  1655.     
  1656.     if (done > 0)
  1657.     {
  1658.         struct bios_file *b = (struct bios_file *) f->fc.index;
  1659.         
  1660.         b->xattr.atime = timestamp;
  1661.         b->xattr.adate = datestamp;
  1662.     }
  1663.     
  1664.     DEBUG (("uart_writeb: leave (%ld)", done));
  1665.     return done;
  1666. }
  1667.  
  1668. static long _cdecl
  1669. uart_readb (FILEPTR *f, char *buf, long bytes)
  1670. {
  1671.     IOVAR *iovar = IOVARS (f->fc.aux);
  1672.     IOREC *iorec = &iovar->input;
  1673.     long done = 0;
  1674.     
  1675.     DEBUG (("uart_readb [%i]: enter (%lx, %ld)", f->fc.aux, buf, bytes));
  1676.     for (;;)
  1677.     {
  1678.         /* copy as much as possible */
  1679.         while ((bytes > 0) && !iorec_empty (iorec))
  1680.         {
  1681.             *buf = iorec_get (iorec);
  1682.             DEBUG (("%x - %c", (int) *buf, *buf));
  1683.             
  1684.             buf++; done++;
  1685.             bytes--;
  1686.         }
  1687.         
  1688.         if (iorec_used (iorec) < iorec->low_water)
  1689.             /* start receiver */
  1690.             start_receiver (iovar, iovar->regs);
  1691.         
  1692.         if (f->flags & O_NDELAY)
  1693.         {
  1694.             if (!done)
  1695.                 done = EWOULDBLOCK;
  1696.             
  1697.             break;
  1698.         }
  1699.         
  1700.         if (!bytes)
  1701.             break;
  1702.         
  1703.         /* sleep until we received enough data or the buffer
  1704.          * become to full
  1705.          */
  1706.         {
  1707.             long i;
  1708.             
  1709.             i = iorec_used (iorec);
  1710.             while ((i < bytes) && (i < iorec->high_water))
  1711.             {
  1712.                 sleep (READY_Q, 0L);
  1713.                 i = iorec_used (iorec);
  1714.             }
  1715.         }
  1716.     }
  1717.     
  1718.     if (done > 0)
  1719.     {
  1720.         struct bios_file *b = (struct bios_file *) f->fc.index;
  1721.         
  1722.         b->xattr.atime = timestamp;
  1723.         b->xattr.adate = datestamp;
  1724.     }
  1725.     
  1726.     DEBUG (("uart_readb: leave (%ld)", done));
  1727.     return done;
  1728. }
  1729.  
  1730. /*
  1731.  * Note: when a BIOS device is a terminal (i.e. has the O_TTY flag
  1732.  * set), bios_read and bios_write will only ever be called indirectly, via
  1733.  * tty_read and tty_write. That's why we can afford to play a bit fast and
  1734.  * loose with the pointers ("buf" is really going to point to a long) and
  1735.  * why we know that "bytes" is divisible by 4.
  1736.  */
  1737.  
  1738. static long _cdecl
  1739. uart_twrite (FILEPTR *f, const char *buf, long bytes)
  1740. {
  1741.     IOVAR *iovar = IOVARS (f->fc.aux);
  1742.     IOREC *iorec = &iovar->output;
  1743.     long done = 0;
  1744.     const long *r = (const long *) buf;
  1745.     
  1746.     DEBUG (("uart_twrite [%i]: enter (%lx, %ld)", f->fc.aux, buf, bytes));
  1747.     for (;;)
  1748.     {
  1749.         /* copy as much as possible */
  1750.         while ((bytes > 0) && iorec_put (iorec, (char) *r))
  1751.         {
  1752.             DEBUG (("%lx - %c", *r, (char) *r));
  1753.             
  1754.             r++; done += 4;
  1755.             bytes -= 4;
  1756.         }
  1757.         
  1758.         /* start transfer - interrupt controlled */
  1759.         start_transmitter (iovar);
  1760.         
  1761.         if (f->flags & O_NDELAY)
  1762.         {
  1763.             if (!done)
  1764.                 done = EWOULDBLOCK;
  1765.             
  1766.             break;
  1767.         }
  1768.         
  1769.         if (!bytes)
  1770.             break;
  1771.         
  1772.         /* sleep until there is enough room in the buffer
  1773.          * to continue
  1774.          */
  1775.         while (iorec_used (iorec) > iorec->high_water)
  1776.             sleep (READY_Q, 0L);
  1777.     }
  1778.     
  1779.     if (done > 0)
  1780.     {
  1781.         struct bios_file *b = (struct bios_file *) f->fc.index;
  1782.         
  1783.         b->xattr.atime = timestamp;
  1784.         b->xattr.adate = datestamp;
  1785.     }
  1786.     
  1787.     DEBUG (("uart_twrite: leave (%ld)", done));
  1788.     return done;
  1789. }
  1790.  
  1791. static long _cdecl
  1792. uart_tread (FILEPTR *f, char *buf, long bytes)
  1793. {
  1794.     IOVAR *iovar = IOVARS (f->fc.aux);
  1795.     IOREC *iorec = &iovar->input;
  1796.     long done = 0;
  1797.     long *r = (long *) buf;
  1798.     
  1799.     DEBUG (("uart_tread [%i]: enter (%lx, %ld)", f->fc.aux, buf, bytes));
  1800.     for (;;)
  1801.     {
  1802.         /* copy as much as possible */
  1803.         while ((bytes > 0) && !iorec_empty (iorec))
  1804.         {
  1805.             *r = (long) iorec_get (iorec);
  1806.             DEBUG (("%lx - %c", *r, (char) *r));
  1807.             
  1808.             r++; done += 4;
  1809.             bytes -= 4;
  1810.         }
  1811.         
  1812.         if (iorec_used (iorec) < iorec->low_water)
  1813.             /* start receiver */
  1814.             start_receiver (iovar, iovar->regs);
  1815.         
  1816.         if (f->flags & O_NDELAY)
  1817.         {
  1818.             if (!done)
  1819.                 done = EWOULDBLOCK;
  1820.             
  1821.             break;
  1822.         }
  1823.         
  1824.         if (!bytes)
  1825.             break;
  1826.         
  1827.         /* sleep until we received enough data or the buffer
  1828.          * become to full
  1829.          */
  1830.         {
  1831.             long i;
  1832.             
  1833.             i = iorec_used (iorec);
  1834.             while ((i < bytes) && (i < iorec->high_water))
  1835.             {
  1836.                 sleep (READY_Q, 0L);
  1837.                 i = iorec_used (iorec);
  1838.             }
  1839.         }
  1840.     }
  1841.     
  1842.     if (done > 0)
  1843.     {
  1844.         struct bios_file *b = (struct bios_file *) f->fc.index;
  1845.         
  1846.         b->xattr.atime = timestamp;
  1847.         b->xattr.adate = datestamp;
  1848.     }
  1849.     
  1850.     DEBUG (("uart_tread: leave (%ld)", done));
  1851.     return done;
  1852. }
  1853.  
  1854. static long _cdecl
  1855. uart_lseek (FILEPTR *f, long where, int whence)
  1856. {
  1857.     DEBUG (("uart_lseek [%i]: enter (%ld, %d)", f->fc.aux, where, whence));
  1858.     
  1859.     /* (terminal) devices are always at position 0 */
  1860.     return 0;
  1861. }
  1862.  
  1863. static long _cdecl
  1864. uart_ioctl (FILEPTR *f, int mode, void *buf)
  1865. {
  1866.     IOVAR *iovar = IOVARS (f->fc.aux);
  1867.     long r = E_OK;
  1868.     
  1869.     DEBUG (("uart_ioctl [%i]: (%x, (%c %i), %lx)", f->fc.aux, mode, (char) (mode >> 8), (mode & 0xff), buf));
  1870.     
  1871.     switch (mode)
  1872.     {
  1873.         case FIONREAD:
  1874.         {
  1875.             *(long *) buf = iorec_used (&iovar->input);
  1876.             break;
  1877.         }
  1878.         case FIONWRITE:
  1879.         {
  1880.             long bytes;
  1881.             
  1882.             bytes = iorec_free (&iovar->output);
  1883.             bytes -= 2;
  1884.             if (bytes < 0)
  1885.                 bytes = 0;
  1886.             
  1887.             *(long *) buf = bytes;
  1888.             break;
  1889.         }
  1890.         case FIOEXCEPT:        /* anywhere documented? */
  1891.         {
  1892.             *(long *) buf = 0;
  1893.             break;
  1894.         }
  1895.         case TIOCFLUSH:
  1896.         {
  1897.             int flushtype;
  1898.             
  1899.             /* HSMODEM put the value itself in arg
  1900.              * MiNT use arg as a pointer to the value
  1901.              * 
  1902.              * if opened as terminal we assume MiNT convention
  1903.              * otherwise HSMODEM convention
  1904.              */
  1905.             if (f->fc.aux >= IOVAR_TTY_OFFSET)
  1906.                 flushtype = *(int *) buf;
  1907.             else
  1908.                 flushtype = (int) ((long) buf);
  1909.             
  1910.             if (flushtype <= 0)
  1911.             {
  1912.                 r = EINVFN;
  1913.                 break;
  1914.             }
  1915.             
  1916.             if (flushtype & 1)
  1917.             {
  1918.                 IOREC *iorec = &(iovar->input);
  1919.                 ushort sr;
  1920.                 
  1921.                 sr = spl7 ();
  1922.                 iorec->head = iorec->tail = 0;
  1923.                 spl (sr);
  1924.             }
  1925.             
  1926.             if (flushtype & 2)
  1927.             {
  1928.                 IOREC *iorec = &(iovar->output);
  1929.                 ushort sr;
  1930.                 
  1931.                 sr = spl7 ();
  1932.                 iorec->head = iorec->tail = 0;
  1933.                 spl (sr);
  1934.             }
  1935.             
  1936.             break;
  1937.         }
  1938.         case TIOCSTOP:        /* HSMODEM */
  1939.         {
  1940.             if (iovar->hsk_mode)
  1941.                 stop_receiver (iovar, iovar->regs);
  1942.             
  1943.             break;
  1944.         }
  1945.         case TIOCSTART:        /* HSMODEM */
  1946.         {
  1947.             start_receiver (iovar, iovar->regs);
  1948.             break;
  1949.         }
  1950.         case TIOCIBAUD:
  1951.         case TIOCOBAUD:
  1952.         {
  1953.             long speed = *(long *) buf;
  1954.             
  1955.             DEBUG (("uart_ioctl(TIOCIBAUD) to %li", speed));
  1956.             
  1957.             if (speed == -1)
  1958.             {
  1959.                 /* current baudrate */
  1960.                 
  1961.                 *(long *) buf = iovar->baudrate;
  1962.                 break;
  1963.             }
  1964.             else if (speed == 0)
  1965.             {
  1966.                 /* clear dtr */
  1967.                 
  1968.                 dtr_off (iovar->regs);
  1969.                 break;
  1970.             }
  1971.             else
  1972.             {
  1973.                 /* set baudrate to speed, enable dtr */
  1974.                 
  1975.                 static const long table [] =
  1976.                 {
  1977.                     300, 600,
  1978.                     1200, 1800, 2400, 3600, 4800, 9600,
  1979.                     14400, 19200, 28800, 38400, 57600,
  1980.                     115200, 230400, 460800,
  1981.                     0
  1982.                 };
  1983.                 
  1984.                 long baudrate;
  1985.                 long div;
  1986.                 
  1987.                 div = iovar->baudbase / speed;
  1988.                 
  1989.                 if (div < 1)
  1990.                     div = 1;
  1991.                 if (div > 65534)
  1992.                     div = 65534;
  1993.                 
  1994.                 baudrate = iovar->baudbase / div;
  1995.                 
  1996.                 if ((baudrate != speed) || (iovar->baudbase % div))
  1997.                 {
  1998. # if 0
  1999.                     if (baudrate > speed)
  2000.                     {
  2001.                         div++;
  2002.                         baudrate = iovar->baudbase / div;
  2003.                     }
  2004.                     
  2005.                     if (baudrate < 9600)
  2006.                         baudrate = 9600;
  2007. # else
  2008.                     if (speed > iovar->baudbase)
  2009.                     {
  2010.                         baudrate = iovar->baudbase;
  2011.                     }
  2012.                     else
  2013.                     {
  2014.                         int i;
  2015.                         
  2016.                         baudrate = table [0];
  2017.                         
  2018.                         for (i = 0; table [i] != 0; i++)
  2019.                         {
  2020.                             if (speed > table [i] && speed <= iovar->baudbase)
  2021.                                 baudrate = table [i];
  2022.                         }
  2023.                     }
  2024. # endif
  2025.                     
  2026.                     *(long *) buf = baudrate;
  2027.                     DEBUG (("uart_ioctl(TIOCIBAUD) error -> %li", baudrate));
  2028.                     
  2029.                     r = ERANGE;
  2030.                     break;
  2031.                 }
  2032.                 
  2033.                 if (baudrate != iovar->baudrate)
  2034.                 {
  2035.                     UART *regs = iovar->regs;
  2036.                     ushort sr;
  2037.                     uchar old_ier;
  2038.                     
  2039.                     sr = spl7 ();
  2040.                     
  2041.                     /* save old interrupts */
  2042.                     old_ier = regs->ier;
  2043.                     
  2044.                     /* and lock */ 
  2045.                     regs->ier = 0;
  2046.                     
  2047.                     old_ier |= (LS_IE | MS_IE);
  2048.                     
  2049.                     /* set new daudrate
  2050.                      */
  2051.                     iovar->baudrate = baudrate;
  2052.                     div = iovar->baudbase / baudrate;
  2053.                     
  2054.                     regs->lcr |= BNKSE;
  2055.                     regs->dll = (div) & 0xFF;
  2056.                     regs->dlm = (div >> 8) & 0xFF;
  2057.                     regs->lcr &= ~BNKSE;
  2058.                     
  2059.                     /* Reset FIFOs */
  2060.                     regs->fcr = FIFO_EN | RXFR | TXFR;
  2061.                     /* Enable FIFOs, set Rcv Threshold */
  2062.                     regs->fcr = FIFO_EN | RXFTH_8;
  2063.                     
  2064.                     /* freeup new interrupts */ 
  2065.                     regs->ier = old_ier;
  2066.                     regs->mcr |= (GI_EN | RTSO);
  2067.                     
  2068.                     spl (sr);
  2069.                 }
  2070.                 
  2071.                 /* always enable dtr */
  2072.                 dtr_on (iovar->regs);
  2073.             }
  2074.             
  2075.             break;
  2076.         }
  2077.         case TIOCCBRK:
  2078.         {
  2079.             brk_off (iovar->regs);
  2080.             break;
  2081.         }
  2082.         case TIOCSBRK:
  2083.         {
  2084.             brk_on (iovar->regs);
  2085.             break;
  2086.         }
  2087.         case TIOCGFLAGS:
  2088.         {
  2089.             ushort flags = 0;
  2090.             uchar lcr = iovar->regs->lcr;
  2091.             
  2092.             switch (lcr & WLS)
  2093.             {
  2094.                 case 0: flags |= TF_5BIT; break;
  2095.                 case 1: flags |= TF_6BIT; break;
  2096.                 case 2: flags |= TF_7BIT; break;
  2097.                 case 3: flags |= TF_8BIT; break;
  2098.             }
  2099.             
  2100.             if (lcr & STB)    flags |= TF_2STOP;
  2101.             else        flags |= TF_1STOP;
  2102.             
  2103.             if (lcr & PEN)
  2104.             {
  2105.                 if (lcr & EPS)    flags |= T_EVENP;
  2106.                 else        flags |= T_ODDP;
  2107.             }
  2108.             
  2109.             if (iovar->hsk_mode & SHAKE_XON_OFF)
  2110.                 flags |= T_TANDEM;
  2111.             
  2112.             if (iovar->hsk_mode & SHAKE_RTS_CTS)
  2113.                 flags |= T_RTSCTS;
  2114.             
  2115.             *(ushort *) buf = flags;
  2116.             break;
  2117.         }
  2118.         case TIOCSFLAGS:
  2119.         {
  2120.             ushort flags = *(ushort *) buf;
  2121.             ushort lcr = iovar->regs->lcr;
  2122.             
  2123.             lcr &= ~WLS;
  2124.             switch (flags & TF_CHARBITS)
  2125.             {
  2126.                 case TF_5BIT:    lcr |= 0;        break;
  2127.                 case TF_6BIT:    lcr |= 1;        break;
  2128.                 case TF_7BIT:    lcr |= 2;        break;
  2129.                 case TF_8BIT:    lcr |= 3;        break;
  2130.                 default:    goto err_erange;    break;
  2131.             }
  2132.             
  2133.             switch (flags & TF_STOPBITS)
  2134.             {
  2135.                 case TF_1STOP:    lcr &= ~STB;        break;
  2136.                 case TF_15STOP:    goto err_erange;    break;
  2137.                 case TF_2STOP:    lcr |= STB;        break;
  2138.                 default:    goto err_erange;    break;
  2139.             }
  2140.             
  2141.             if (flags & (T_EVENP | T_ODDP))
  2142.             {
  2143.                 if ((flags & (T_EVENP | T_ODDP)) == (T_EVENP | T_ODDP))
  2144.                     goto err_erange;
  2145.                 
  2146.                 /* enable parity */
  2147.                 lcr |= PEN;
  2148.                 
  2149.                 /* set even/odd parity */
  2150.                 if (flags & T_EVENP)    lcr |= EPS;
  2151.                 else            lcr &= ~EPS;
  2152.             }
  2153.             else
  2154.             {
  2155.                 /* disable parity */
  2156.                 lcr &= ~PEN;
  2157.                 
  2158.                 /* even/odd bit ignored in this case */
  2159.             }
  2160.             
  2161.             if (flags & T_TANDEM)    iovar->hsk_mode |= SHAKE_XON_OFF;
  2162.             else            iovar->hsk_mode &= ~SHAKE_XON_OFF;
  2163.             
  2164.             if (flags & T_RTSCTS)    iovar->hsk_mode |= SHAKE_RTS_CTS;
  2165.             else            iovar->hsk_mode &= ~SHAKE_RTS_CTS;
  2166.             
  2167.             /* setup in register */
  2168.             iovar->regs->lcr = lcr;
  2169.             
  2170.             break;
  2171.         }
  2172.         case TIONOTSEND:
  2173.         case TIOCOUTQ:
  2174.         {
  2175.             *(long *) buf = iorec_used (&iovar->output);
  2176.             break;
  2177.         }
  2178.         case TIOCSFLAGSB:    /* anywhere documented? */
  2179.         {
  2180.             r = EINVFN;
  2181.             break;
  2182.         }
  2183.         case TIOCGVMIN:
  2184.         {
  2185.             struct tty *tty = (struct tty *) f->devinfo;
  2186.             ushort *v = buf;
  2187.             
  2188.             v [0] = tty->vmin;
  2189.             v [1] = tty->vtime;
  2190.             
  2191.             break;
  2192.         }
  2193.         case TIOCSVMIN:
  2194.         {
  2195.             struct tty *tty = (struct tty *) f->devinfo;
  2196.             ushort *v = buf;
  2197.             
  2198.             if (v [0] > iovar->input.size / 2)
  2199.                 v [0] = iovar->input.size / 2;
  2200.             
  2201.             tty->vmin = v [0];
  2202.             tty->vtime = v [1];
  2203.             
  2204.             /* t->vticks = 0; */
  2205.             
  2206.             break;
  2207.         }
  2208.         case TIOCWONLINE:
  2209.         {
  2210. # if 0
  2211.             struct tty *tty = (struct tty *) f->devinfo;
  2212.             
  2213.             while (tty->state & TS_BLIND)
  2214.                 sleep (IO_Q, (long) &tty->state);
  2215. # else
  2216.             r = EINVFN;
  2217. # endif
  2218.             break;
  2219.         }
  2220.         case TIOCBUFFER:    /* HSMODEM special */
  2221.         {
  2222.             long *ptr = (long *) buf;
  2223.             
  2224.             /* input buffer size */
  2225.             if (*ptr == -1)    *ptr = iovar->input.size;
  2226.             else        *ptr = -1;
  2227.             
  2228.             ptr++;
  2229.             
  2230.             /* input low watermark */
  2231.             if (*ptr == -1)    *ptr = iovar->input.low_water;
  2232.             else        *ptr = -1;
  2233.             
  2234.             ptr++;
  2235.             
  2236.             /* input high watermark */
  2237.             if (*ptr == -1)    *ptr = iovar->input.high_water;
  2238.             else        *ptr = -1;
  2239.             
  2240.             ptr++;
  2241.             
  2242.             /* output buffer size */
  2243.             if (*ptr == -1)    *ptr = iovar->output.size;
  2244.             else        *ptr = -1;
  2245.             
  2246.             break;
  2247.         }
  2248.         case TIOCCTLMAP:    /* HSMODEM */
  2249.         {
  2250.             long *ptr = (long *) buf;
  2251.             
  2252.             ptr [0] = 0
  2253.             /*    | TIOCMH_LE */
  2254.                 | TIOCMH_DTR
  2255.                 | TIOCMH_RTS
  2256.                 | TIOCMH_CTS
  2257.                 | TIOCMH_CD
  2258.                 | TIOCMH_RI
  2259.                 | TIOCMH_DSR
  2260.             /*    | TIOCMH_LEI */
  2261.             /*    | TIOCMH_TXD */
  2262.             /*    | TIOCMH_RXD */
  2263.                 | TIOCMH_BRK
  2264.             /*    | TIOCMH_TER */
  2265.             /*    | TIOCMH_RER */
  2266.                 | TIOCMH_TBE
  2267.                 | TIOCMH_RBF
  2268.                 ;
  2269.             
  2270.             ptr [1] = 0;    /* will be never supported */
  2271.             ptr [2] = 0;    /* will be never supported */
  2272.             ptr [3] = 0;    /* reserved */
  2273.             ptr [4] = 0;    /* reserved */
  2274.             ptr [5] = 0;    /* reserved */
  2275.             
  2276.             break;
  2277.         }
  2278.         case TIOCCTLGET:    /* HSMODEM */
  2279.         {
  2280.             /* register long mask = *(long *) buf; */
  2281.             register long val = 0;
  2282.             register char reg;
  2283.             
  2284.             /* TIOCMH_LE */
  2285.             
  2286.             /* mcr */
  2287.             reg = iovar->regs->mcr;
  2288.             if (reg & DTRO) val |= TIOCMH_DTR;
  2289.             if (reg & RTSO) val |= TIOCMH_RTS;
  2290.             
  2291.             /* msr */
  2292.             reg = iovar->regs->msr;
  2293.             if (reg & CTSI) val |= TIOCMH_CTS;
  2294.             if (reg & RII ) val |= TIOCMH_RI;
  2295.             if (reg & DCDI) val |= TIOCMH_CD;
  2296.             if (reg & DSRI) val |= TIOCMH_DSR;
  2297.             
  2298.             /* TIOCMH_LEI */
  2299.             /* TIOCMH_TXD */
  2300.             /* TIOCMH_RXD */
  2301.             
  2302.             /* lsr */
  2303.             reg = iovar->regs->lsr;
  2304.             if (reg & BRK ) val |= TIOCMH_BRK;
  2305.             /* TIOCMH_TER */
  2306.             /* TIOCMH_RER */
  2307.             if (reg & TXDE) val |= TIOCMH_TBE;
  2308.             if (reg & RXDA) val |= TIOCMH_RBF;
  2309.             
  2310.             *(long *) buf = val;
  2311.             break;
  2312.         }
  2313.         case TIOCCTLSET:    /* HSMODEM */
  2314.         {
  2315.             long *arg = (long *) buf;
  2316.             
  2317.             register long mask = *arg++;
  2318.             register long val = *arg;
  2319.             
  2320.             if (mask & (TIOCMH_DTR | TIOCMH_RTS))
  2321.             {
  2322.                 /* mcr    */
  2323.                 register char reg_val = iovar->regs->mcr;
  2324.                 
  2325.                 if (mask & TIOCMH_DTR)
  2326.                 {
  2327.                     if (val & TIOCMH_DTR)    reg_val |= DTRO;
  2328.                     else            reg_val &= ~DTRO;
  2329.                 }
  2330.                 
  2331.                 if (mask & TIOCMH_RTS)
  2332.                 {
  2333.                     if (val & TIOCMH_RTS)    reg_val |= RTSO;
  2334.                     else            reg_val &= ~RTSO;
  2335.                 }
  2336.                 
  2337.                 iovar->regs->mcr = reg_val;
  2338.             }
  2339.             
  2340.             break;
  2341.         }
  2342.         case TIOCERROR:        /* HSMODEM */
  2343.         {
  2344.             r = ERANGE;
  2345.             break;
  2346.         }
  2347.         case TIOCCDTR:
  2348.         {
  2349.             dtr_off (iovar->regs);
  2350.             break;
  2351.         }
  2352.         case TIOCSDTR:
  2353.         {
  2354.             dtr_on (iovar->regs);
  2355.             break;
  2356.         }
  2357.         
  2358.         case F_SETLK:
  2359.         case F_SETLKW:
  2360.         {
  2361.             struct flock *lck = (struct flock *) buf;
  2362.             int cpid = p_getpid ();
  2363.             
  2364.             while (iovar->lockpid && iovar->lockpid != cpid)
  2365.             {
  2366.                 if (mode == F_SETLKW && lck->l_type != F_UNLCK)
  2367.                     sleep (IO_Q, (long) iovar);
  2368.                 else
  2369.                     return ELOCKED;
  2370.             }
  2371.             
  2372.             if (lck->l_type == F_UNLCK)
  2373.             {
  2374.                 if (!(f->flags & O_LOCK))
  2375.                 {
  2376.                     DEBUG (("uart_ioctl: wrong file descriptor for UNLCK"));
  2377.                     return ENSLOCK;
  2378.                 }
  2379.                 
  2380.                 if (iovar->lockpid != cpid)
  2381.                     return ENSLOCK;
  2382.                 
  2383.                 iovar->lockpid = 0;
  2384.                 f->flags &= ~O_LOCK;
  2385.                 
  2386.                 /* wake anyone waiting for this lock */
  2387.                 wake (IO_Q, (long) iovar);
  2388.             }
  2389.             else
  2390.             {
  2391.                 iovar->lockpid = cpid;
  2392.                 f->flags |= O_LOCK;
  2393.             }
  2394.             
  2395.             break;
  2396.         }
  2397.         case F_GETLK:
  2398.         {
  2399.             struct flock *lck = (struct flock *) buf;
  2400.             
  2401.             if (iovar->lockpid)
  2402.             {
  2403.                 lck->l_type = F_WRLCK;
  2404.                 lck->l_start = lck->l_len = 0;
  2405.                 lck->l_pid = iovar->lockpid;
  2406.             }
  2407.             else
  2408.             {
  2409.                 lck->l_type = F_UNLCK;
  2410.             }
  2411.             
  2412.             break;
  2413.         }
  2414.         
  2415.         default:
  2416.         {
  2417.             /* Fcntl will automatically call tty_ioctl to handle
  2418.              * terminal calls that we didn't deal with
  2419.              */
  2420.             r = EINVFN;
  2421.             break;
  2422.         }
  2423.     }
  2424.     
  2425.     goto out;
  2426.     
  2427. err_erange:
  2428.     r = ERANGE;
  2429.     
  2430. out:
  2431.     DEBUG (("uart_ioctl: return %li", r));
  2432.     return r;
  2433. }
  2434.  
  2435. static long _cdecl
  2436. uart_datime (FILEPTR *f, ushort *timeptr, int rwflag)
  2437. {
  2438.     DEBUG (("uart_datime [%i]: enter (%i)", f->fc.aux, rwflag));
  2439.     
  2440.     if (rwflag)
  2441.         return EACCDN;
  2442.     
  2443.     *timeptr++ = timestamp;
  2444.     *timeptr = datestamp;
  2445.     
  2446.     return E_OK;
  2447. }
  2448.  
  2449. static long _cdecl
  2450. uart_close (FILEPTR *f, int pid)
  2451. {
  2452.     IOVAR *iovar = IOVARS (f->fc.aux);
  2453.     
  2454.     DEBUG (("uart_close [%i]: enter", f->fc.aux));
  2455.     
  2456.     if (iovar->lockpid == pid)
  2457.     {
  2458.         /* wake anyone waiting for this lock */
  2459.         wake (IO_Q, (long) iovar);
  2460.     }
  2461.     
  2462.     if (f->links <= 0)
  2463.     {
  2464.         register FILEPTR **temp;
  2465.         register long flag = 1;
  2466.         
  2467.         /* remove the FILEPTR from the linked list */
  2468.         temp = &iovar->open;
  2469.         while (*temp)
  2470.         {
  2471.             if (*temp == f)
  2472.             {
  2473.                 *temp = f->next;
  2474.                 f->next = NULL;
  2475.                 flag = 0;
  2476.                 
  2477.                 break;
  2478.             }
  2479.             
  2480.             temp = &(*temp)->next;
  2481.         }
  2482.         
  2483.         if (flag)
  2484.         {
  2485.             ALERT (("uart_close: remove open FILEPTR fail!", f->fc.aux));
  2486.         }
  2487.     }
  2488.     
  2489.     DEBUG (("uart_close: leave ok"));
  2490.     return E_OK;
  2491. }
  2492.  
  2493. static long _cdecl
  2494. uart_select (FILEPTR *f, long proc, int mode)
  2495. {
  2496.     IOVAR *iovar = IOVARS (f->fc.aux);
  2497.     struct tty *tty = (struct tty *) f->devinfo;
  2498.     
  2499.     DEBUG (("uart_select [%i]: enter (%li, %i, %lx)", f->fc.aux, proc, mode, tty));
  2500.     
  2501.     if (mode == O_RDONLY)
  2502.     {
  2503.         if (!iorec_empty (&iovar->input))
  2504.         {
  2505.             TRACE (("uart_select: data present for device %lx", iovar));
  2506.             return 1;
  2507.         }
  2508.         
  2509.         if (tty)
  2510.         {
  2511.             /* avoid collisions with other processes
  2512.              */
  2513.             
  2514.             if (tty->rsel)
  2515.                 /* collision */
  2516.                 return 2;
  2517.             
  2518.             tty->rsel = proc;
  2519.         }
  2520.         
  2521.         return 0;
  2522.     }
  2523.     else if (mode == O_WRONLY)
  2524.     {
  2525.         if ((!tty || !(tty->state & (TS_BLIND | TS_HOLD))) && !iorec_empty (&iovar->output))
  2526.         {
  2527.             TRACE (("uart_select: ready to output on %lx", iovar));
  2528.             return 1;
  2529.         }
  2530.         
  2531.         if (tty)
  2532.         {
  2533.             /* avoid collisions with other processes
  2534.              */
  2535.             
  2536.             if (tty->wsel)
  2537.                 /* collision */
  2538.                 return 2;
  2539.             
  2540.             tty->wsel = proc;
  2541.         }
  2542.         
  2543.         return 0;
  2544.     }
  2545.     
  2546.     /* default -- we don't know this mode, return 0 */
  2547.     return 0;
  2548. }
  2549.  
  2550. static void _cdecl
  2551. uart_unselect (FILEPTR *f, long proc, int mode)
  2552. {
  2553.     struct tty *tty = (struct tty *) f->devinfo;
  2554.     
  2555.     DEBUG (("uart_unselect [%i]: enter (%li, %i, %lx)", f->fc.aux, proc, mode, tty));
  2556.     
  2557.     if (tty)
  2558.     {
  2559.         if (mode == O_RDONLY && tty->rsel == proc)
  2560.             tty->rsel = 0;
  2561.         else if (mode == O_WRONLY && tty->wsel == proc)
  2562.             tty->wsel = 0;
  2563.     }
  2564. }
  2565.  
  2566. /* END device driver routines */
  2567. /****************************************************************************/
  2568.