The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sx/sx_util.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Device driver for Specialix I/O8+ multiport serial card.
    3  *
    4  * Copyright 2003 Frank Mayhar <frank@exit.com>
    5  *
    6  * Derived from the "si" driver by Peter Wemm <peter@netplex.com.au>, using
    7  * lots of information from the Linux "specialix" driver by Roger Wolff
    8  * <R.E.Wolff@BitWizard.nl> and from the Intel CD1865 "Intelligent Eight-
    9  * Channel Communications Controller" datasheet.  Roger was also nice
   10  * enough to answer numerous questions about stuff specific to the I/O8+
   11  * not covered by the CD1865 datasheet.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notices, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notices, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
   23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
   25  * NO EVENT SHALL THE AUTHORS BE LIABLE.
   26  *
   27  * $FreeBSD: releng/5.3/sys/dev/sx/sx_util.c 128133 2004-04-11 19:32:20Z imp $
   28  */
   29 
   30 #include "opt_debug_sx.h"
   31 
   32 /* Utility and support routines for the Specialix I/O8+ driver. */
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/bus.h>
   37 #include <sys/tty.h>
   38 #include <machine/resource.h>   
   39 #include <machine/bus.h>
   40 #include <machine/clock.h>
   41 #include <sys/rman.h>
   42 
   43 #include <dev/sx/cd1865.h>
   44 #include <dev/sx/sxvar.h>
   45 #include <dev/sx/sx.h>
   46 #include <dev/sx/sx_util.h>
   47 
   48 /*
   49  * sx_probe_io8()
   50  *      Probe the board to verify that it is a Specialix I/O8+.
   51  *
   52  * Description:
   53  *      This is called by sx_pci_attach() (and possibly in the future by
   54  *      sx_isa_attach()) to verify that the card we're attaching to is
   55  *      indeed a Specialix I/O8+.  To do this, we check for the Prescaler
   56  *      Period Register of the CD1865 chip and for the Specialix signature
   57  *      on the DSR input line of each channel.  These lines, along with the
   58  *      RTS output lines, are wired down in hardware.
   59  */
   60 int
   61 sx_probe_io8(
   62         device_t dev)
   63 {
   64         struct sx_softc *sc;
   65         unsigned char val1, val2;
   66         int i;
   67 
   68         sc = device_get_softc(dev);
   69         /*
   70          * Try to write the Prescaler Period Register, then read it back,
   71          * twice.  If this fails, it's not an I/O8+.
   72          */
   73         sx_cd1865_out(sc, CD1865_PPRL, 0x5a);
   74         DELAY(1);
   75         val1 = sx_cd1865_in(sc, CD1865_PPRL);
   76 
   77         sx_cd1865_out(sc, CD1865_PPRL, 0xa5);
   78         DELAY(1);
   79         val2 = sx_cd1865_in(sc, CD1865_PPRL);
   80 
   81         if ((val1 != 0x5a) || (val2 != 0xa5))
   82                 return(1);
   83 
   84         /*
   85          * Check the lines that Specialix uses as board identification.
   86          * These are the DSR input and the RTS output, which are wired
   87          * down.
   88          */
   89         val1 = 0;
   90         for (i = 0; i < 8; i++) {
   91                 sx_cd1865_out(sc, CD1865_CAR, i);       /* Select channel.    */
   92                 if (sx_cd1865_in(sc, CD1865_MSVR) & CD1865_MSVR_DSR) /* Set?  */
   93                         val1 |= 1 << i;                 /* OR it in.          */
   94         }
   95 #ifdef notdef
   96         val2 = 0;
   97         for (i = 0; i < 8; i++) {
   98                 sx_cd1865_out(sc, CD1865_CAR, i);       /* Select channel.    */
   99                 if (sx_cd1865_in(sc, CD1865_MSVR) & CD1865_MSVR_RTS) /* Set?  */
  100                         val2 |= 1 << i;                 /* OR it in.          */
  101         }
  102         /*
  103          * They managed to switch the bit order between the docs and
  104          * the IO8+ card. The new PCI card now conforms to old docs.
  105          * They changed the PCI docs to reflect the situation on the
  106          * old card.
  107          */
  108         val2 = (bp->flags & SX_BOARD_IS_PCI) ? 0x4d : 0xb2;
  109 #endif /* notdef */
  110         if (val1 != 0x4d) {
  111                 if (bootverbose)
  112                         device_printf(dev,
  113                                       "Specialix I/O8+ ID 0x4d not found (0x%02x).\n",
  114                                       val1);
  115                 return(1);
  116         }
  117         return(0);              /* Probed successfully.                       */
  118 }
  119 
  120 /*
  121  * sx_init_CD1865()
  122  *      Hard-reset and initialize the I/O8+ CD1865 processor.
  123  *
  124  * Description:
  125  *      This routine does a hard reset of the CD1865 chip and waits for it
  126  *      to complete.  (The reset should complete after 500us; we wait 1ms
  127  *      and fail if we time out.)  We then initialize the CD1865 processor.
  128  */
  129 int
  130 sx_init_cd1865(
  131         struct sx_softc *sc,
  132         int unit)
  133 {
  134         int s;
  135         unsigned int to;
  136 
  137         s = spltty();
  138         disable_intr();
  139         sx_cd1865_out(sc, CD1865_GSVR, 0x00); /* Clear the GSVR.              */
  140         sx_cd1865_wait_CCR(sc, 0);      /* Wait for the CCR to clear.         */
  141         sx_cd1865_out(sc, CD1865_CCR, CD1865_CCR_HARDRESET); /* Reset CD1865. */
  142         enable_intr();
  143         to = SX_GSVR_TIMEOUT/5;
  144         while (to-- > 0) {
  145                 if (sx_cd1865_in(sc, CD1865_GSVR) == 0xff)
  146                         break;
  147                 DELAY(5);
  148         }
  149         if (to == 0) {
  150                 splx(s);
  151                 printf("sx%d:  Timeout waiting for reset.\n", unit);
  152                 return(EIO);
  153         }
  154         /*
  155          * The high five bits of the Global Interrupt Vector Register is
  156          * used to identify daisy-chained CD1865 chips.  The I/O8+ isn't
  157          * daisy chained, but we have to initialize the field anyway.
  158          */
  159         sx_cd1865_out(sc, CD1865_GIVR, SX_CD1865_ID);
  160         /* Clear the Global Interrupting Channel register. */
  161         sx_cd1865_out(sc, CD1865_GICR, 0);
  162         /*
  163          * Set the Service Match Registers to the appropriate values.  See
  164          * the cd1865.h include file for more information.
  165          */
  166         sx_cd1865_out(sc, CD1865_MSMR, CD1865_ACK_MINT); /* Modem.            */
  167         sx_cd1865_out(sc, CD1865_TSMR, CD1865_ACK_TINT); /* Transmit.         */
  168         sx_cd1865_out(sc, CD1865_RSMR, CD1865_ACK_RINT); /* Receive.          */
  169         /*
  170          * Set RegAckEn in the Service Request Configuration Register;
  171          * we'll be acknowledging service requests in software, not
  172          * hardware.
  173          */
  174         sx_cd1865_bis(sc, CD1865_SRCR, CD1865_SRCR_REGACKEN);
  175         /*
  176          * Set the CD1865 timer tick rate.  The value here is the processor
  177          * clock rate (in MHz) divided by the rate in ticks per second.  See
  178          * commentary in sx.h.
  179          */
  180         sx_cd1865_out(sc, CD1865_PPRH, SX_CD1865_PRESCALE >> 8);
  181         sx_cd1865_out(sc, CD1865_PPRL, SX_CD1865_PRESCALE & 0xff);
  182 
  183         splx(s);
  184         return(0);
  185 }
  186 
  187 #ifdef notyet
  188 /*
  189  * Set the IRQ using the RTS lines that run to the PAL on the board....
  190  *
  191  * This is a placeholder for ISA support, if that's ever implemented.  This
  192  * should _only_ be called from sx_isa_attach().
  193  */
  194 int
  195 sx_set_irq(
  196         struct sx_softc *sc,
  197         int unit,
  198         int irq)
  199 {
  200         register int virq;
  201         register int i, j;
  202 
  203         switch (irq) {
  204         /* In the same order as in the docs... */
  205                 case 15:
  206                         virq = 0;
  207                         break;
  208                 case 12:
  209                         virq = 1;
  210                         break;
  211                 case 11:
  212                         virq = 2;
  213                         break;
  214                 case 9:
  215                         virq = 3;
  216                         break;
  217                 default:
  218                         printf("sx%d:  Illegal irq %d.\n", unit, irq);
  219                         return(0);
  220         }
  221         for (i = 0; i < 2; i++) {
  222                 sx_cd1865_out(sc, CD1865_CAR, i); /* Select channel.          */
  223                 j =  ((virq >> i) & 0x1) ? MSVR_RTS : 0;
  224                 sx_cd1865_out(sc, CD1865_MSVRTS, j);
  225         }
  226         return(1);
  227 }
  228 
  229 #endif /* notyet */
  230 
  231 /*
  232  * sx_int_port()
  233  *      Determine the port that interrupted us.
  234  *
  235  * Description:
  236  *      This routine checks the Global Interrupting Channel Register (GICR)
  237  *      to find the port that caused an interrupt.  It returns a pointer to
  238  *      the sx_port structure of the interrupting port, or NULL if there was
  239  *      none.
  240  *
  241  * XXX - check type/validity of interrupt?
  242  */
  243 struct sx_port *
  244 sx_int_port(
  245         struct sx_softc *sc,
  246         int unit)
  247 {
  248         unsigned char chan;
  249         struct sx_port *pp;
  250         
  251         chan = (sx_cd1865_in(sc, CD1865_GSCR2|SX_EI) & CD1865_GICR_CHAN_MASK)
  252                                                       >> CD1865_GICR_CHAN_SHIFT;
  253         DPRINT((NULL, DBG_INTR, "Intr chan %d\n", chan));
  254         if (chan < CD1865_NUMCHAN) {
  255                 pp = sc->sc_ports + (int)chan;
  256                 return(pp);
  257         }
  258         printf("sx%d: False interrupt on port %d.\n", unit, chan);
  259         return(NULL);
  260 }

Cache object: fb48933ed23bdbf0f5e9ab60d4a9c27e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.