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/ie/if_ie_isa.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  * Copyright (c) 2003 Matthew N. Dodd
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * Portions: 
   27  * Copyright (c) 1992, 1993, University of Vermont and State
   28  *  Agricultural College.
   29  * Copyright (c) 1992, 1993, Garrett A. Wollman.
   30  * Copyright (c) 1990, 1991, William F. Jolitz
   31  * Copyright (c) 1990, The Regents of the University of California
   32  * Copyright (c) 1993, 1994, Charles M. Hannum
   33  * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
   34  * Copyright (c) 1997, Aaron C. Smith
   35  *
   36  * See if_ie.c for applicable license.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD: releng/9.2/sys/dev/ie/if_ie_isa.c 181134 2008-08-01 21:33:07Z jhb $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/socket.h>
   46 
   47 #include <sys/module.h>
   48 #include <sys/bus.h>
   49 
   50 #include <machine/bus.h>
   51 #include <machine/resource.h>
   52 #include <sys/rman.h>
   53 
   54 #include <machine/md_var.h>
   55 
   56 #include <net/if.h>
   57 #include <net/if_arp.h>
   58 #include <net/if_media.h>
   59 
   60 #include <isa/isavar.h>
   61 #include <isa/pnpvar.h>
   62 
   63 #include <i386/isa/elink.h>
   64 
   65 #include <dev/ic/i82586.h>
   66 #include <dev/ie/if_ie507.h>
   67 #include <dev/ie/if_iee16.h>
   68 #include <dev/ie/if_iereg.h>
   69 #include <dev/ie/if_ievar.h>
   70 
   71 static int              ie_modevent             (module_t, int, void *);
   72 
   73 static void             ie_isa_3C507_identify   (driver_t *, device_t);
   74 static int              ie_isa_3C507_probe      (device_t);
   75 static int              ie_isa_3C507_attach     (device_t);
   76 static int              ie_3C507_port_check     (u_int32_t);
   77 
   78 static void             ie_isa_ee16_identify    (driver_t *, device_t);
   79 static int              ie_isa_ee16_probe       (device_t);
   80 static int              ie_isa_ee16_attach      (device_t);
   81 static int              ie_isa_ee16_shutdown    (device_t);
   82 static int              ie_ee16_port_check      (u_int32_t port);
   83 static u_int16_t        ie_ee16_hw_read_eeprom  (u_int32_t port, int loc);
   84 
   85 static int              ie_isa_sl_probe         (device_t);
   86 static int              ie_isa_sl_attach        (device_t);
   87 static enum ie_hardware ie_isa_sl_get_hard_type (u_int32_t);
   88 
   89 /*
   90  * 3Com 3C507 Etherlink 16
   91  */
   92 #define IE_3C507_IOBASE_LOW     0x200
   93 #define IE_3C507_IOBASE_HIGH    0x3e0
   94 #define IE_3C507_IOSIZE         16
   95 
   96 #define IE_3C507_IRQ_MASK       0x0f
   97 
   98 #define IE_3C507_MADDR_HIGH     0x20
   99 #define IE_3C507_MADDR_MASK     0x1c
  100 #define IE_3C507_MADDR_BASE     0xc0000
  101 #define IE_3C507_MADDR_SHIFT    12
  102 
  103 #define IE_3C507_MSIZE_MASK     3
  104 #define IE_3C507_MSIZE_SHIFT    14
  105 
  106 static void
  107 ie_isa_3C507_identify (driver_t *driver, device_t parent)
  108 {
  109         char *          desc = "3Com 3C507 Etherlink 16";
  110         device_t        child;
  111         u_int32_t       port, maddr, msize;
  112         u_int8_t        irq, data;
  113         int             error;
  114 
  115         /* Reset and put card in CONFIG state without changing address. */
  116         elink_reset();
  117         elink_idseq(ELINK_507_POLY);
  118         elink_idseq(ELINK_507_POLY);
  119         outb(ELINK_ID_PORT, 0xff);
  120 
  121         for (port = IE_3C507_IOBASE_LOW;
  122              port <= IE_3C507_IOBASE_HIGH;
  123              port += IE_3C507_IOSIZE) {
  124 
  125                 if (ie_3C507_port_check(port)) {
  126 #ifdef DEBUG 
  127                         if (bootverbose) {
  128                                 device_printf(parent,
  129                                         "(if_ie) (3C507) not found at port %#x\n",
  130                                         port);
  131                         }
  132 #endif
  133                         continue;
  134                 }
  135 
  136                 outb(port + IE507_CTRL, EL_CTRL_NRST);
  137 
  138                 data = inb(port + IE507_IRQ);
  139                 irq = data & IE_3C507_IRQ_MASK;
  140 
  141                 data = inb(port + IE507_MADDR);
  142 
  143                 if (data & IE_3C507_MADDR_HIGH) {
  144                         if (bootverbose) {
  145                                 device_printf(parent,
  146                                         "(if_ie) can't map 3C507 RAM in high memory\n");
  147                         }
  148                         continue;
  149                 }
  150 
  151                 maddr = IE_3C507_MADDR_BASE +
  152                         ((data & IE_3C507_MADDR_MASK)
  153                         << IE_3C507_MADDR_SHIFT);
  154                 msize = ((data & IE_3C507_MSIZE_MASK) + 1)
  155                         << IE_3C507_MSIZE_SHIFT;
  156 
  157                 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1);
  158                 device_set_desc_copy(child, desc);
  159                 device_set_driver(child, driver);
  160 
  161                 error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
  162                 if (error) {
  163                         device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n",
  164                                         irq);
  165                         error = device_delete_child(parent, child);
  166                         continue;
  167                 }
  168 
  169                 error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_3C507_IOSIZE);
  170                 if (error) {
  171                         device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n",
  172                                         port, port+IE_3C507_IOSIZE);
  173                         error = device_delete_child(parent, child);
  174                         continue;
  175                 }
  176 
  177                 error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize);
  178                 if (error) {
  179                         device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n",
  180                                         maddr, maddr+msize);
  181                         error = device_delete_child(parent, child);
  182                         continue;
  183                 }
  184 
  185                 if (bootverbose) {
  186                         device_printf(parent,
  187                                 "(if_ie) <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n",
  188                                 desc,
  189                                 port, (port + IE_3C507_IOSIZE) - 1,
  190                                 irq,
  191                                 (u_long)maddr, (u_long)(maddr + msize) - 1,
  192                                 (msize / 1024));
  193                 }
  194         }
  195 
  196         /* go to RUN state */
  197         outb(ELINK_ID_PORT, 0x00);
  198         elink_idseq(ELINK_507_POLY);
  199         outb(ELINK_ID_PORT, 0x00);
  200 
  201         return;
  202 }
  203 
  204 static int
  205 ie_isa_3C507_probe (device_t dev)
  206 {
  207         u_int32_t       iobase;
  208 
  209         /* No ISA-PnP support */
  210         if (isa_get_vendorid(dev)) {
  211                 return (ENXIO);
  212         }
  213 
  214         /* No ISA-HINT support */
  215         if (!device_get_desc(dev)) {
  216                 return (EBUSY);
  217         }
  218 
  219         /* Have we at least an ioport? */
  220         if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) {
  221                 return (ENXIO);
  222         }
  223 
  224         /* Is this thing really a 3c507? */
  225         if (ie_3C507_port_check(iobase)) {
  226                 return (ENXIO);
  227         }
  228 
  229         return (0);
  230 }
  231 
  232 static int
  233 ie_isa_3C507_attach (device_t dev)
  234 {
  235         struct ie_softc *       sc;
  236         int                     error;
  237 
  238         sc = device_get_softc(dev);
  239 
  240         sc->io_rid = 0;
  241         sc->irq_rid = 0;
  242         sc->mem_rid = 0;
  243 
  244         error = ie_alloc_resources(dev);
  245         if (error) {
  246                 goto bad;
  247         }
  248 
  249         sc->bus_use = 0;
  250         sc->ie_reset_586 = el_reset_586;
  251         sc->ie_chan_attn = el_chan_attn;
  252         sc->hard_type = IE_3C507;
  253         sc->hard_vers = 0;
  254 
  255         outb(PORT(sc) + IE507_CTRL, EL_CTRL_NORMAL);
  256 
  257         if (!check_ie_present(sc)) {
  258                 error = ENXIO;
  259                 goto bad;
  260         }
  261 
  262         sl_read_ether(sc, sc->enaddr);
  263 
  264         /* Clear the interrupt latch just in case. */
  265         outb(PORT(sc) + IE507_ICTRL, 1);
  266 
  267         error = ie_attach(dev);
  268         if (error) {
  269                 device_printf(dev, "ie_attach() failed.\n");
  270                 goto bad;
  271         }
  272 
  273         return (0);
  274 bad:
  275         ie_release_resources(dev);
  276 
  277         return (error);
  278 }
  279 
  280 /*
  281  * If a 3c507 is present, return 0
  282  * else, return 1.
  283  */
  284 static int
  285 ie_3C507_port_check (u_int32_t port)
  286 {
  287         u_char *        signature = "*3COM*";
  288         int             i;
  289 
  290         for (i = 0; i < 6; i++)
  291                 if (inb(port + i) != signature[i])
  292                         return (ENXIO);
  293 
  294         return (0);
  295 }
  296 
  297 /*
  298  * Intel EtherExpress 16
  299  */
  300 #define IE_EE16_ID_PORT                 0x0f
  301 #define IE_EE16_ID                      0xbaba
  302 #define IE_EE16_EEPROM_CONFIG1          0x00
  303 #define IE_EE16_EEPROM_IRQ_MASK         0xe000
  304 #define IE_EE16_EEPROM_IRQ_SHIFT        13
  305 #define IE_EE16_EEPROM_MEMCFG           0x06
  306 #define IE_EE16_IOSIZE                  16
  307 
  308 /*
  309  * TODO:
  310  *              Test for 8/16 bit mode.
  311  *              Test for invalid mem sizes.
  312  */
  313 static void
  314 ie_isa_ee16_identify (driver_t *driver, device_t parent)
  315 {
  316         char *          desc = "Intel EtherExpress 16";
  317         device_t        child;
  318         u_int16_t       ports[] = {
  319                                 0x300, 0x310, 0x320, 0x330,
  320                                 0x340, 0x350, 0x360, 0x370,
  321                                 0x200, 0x210, 0x220, 0x230,
  322                                 0x240, 0x250, 0x260, 0x270,
  323                                 0
  324                         };
  325         u_int16_t       irqs[] = { 0, 0x09, 0x03, 0x04, 0x05, 0x0a, 0x0b, 0 };
  326         u_int32_t       port, maddr, msize;
  327         u_int8_t        irq;
  328         u_int16_t       data;
  329         int             i, error;
  330 
  331         for (i = 0; ports[i]; i++) {
  332                 port = ports[i];
  333 
  334                 if (ie_ee16_port_check(port)) {
  335 #ifdef DEBUG
  336                         if (bootverbose) {
  337                                 device_printf(parent,
  338                                         "if_ie: (EE16) not found at port %#x\n",
  339                                         port);
  340                         }
  341 #endif
  342                         continue;
  343                 }
  344 
  345                 /* reset any ee16 at the current iobase */
  346                 outb(port + IEE16_ECTRL, IEE16_RESET_ASIC);
  347                 outb(port + IEE16_ECTRL, 0);
  348                 DELAY(240);
  349 
  350                 data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_CONFIG1);
  351                 irq = irqs[((data & IE_EE16_EEPROM_IRQ_MASK)
  352                            >> IE_EE16_EEPROM_IRQ_SHIFT)];
  353 
  354                 data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_MEMCFG);
  355                 maddr = 0xc0000 + ((ffs(data & 0x00ff) - 1) * 0x4000);
  356                 msize = (fls((data & 0x00ff) >> (ffs(data & 0x00ff) - 1)))
  357                         * 0x4000;
  358 
  359                 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1);
  360                 device_set_desc_copy(child, desc);
  361                 device_set_driver(child, driver);
  362 
  363                 error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
  364                 if (error) {
  365                         device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n",
  366                                         irq);
  367                         error = device_delete_child(parent, child);
  368                         continue;
  369                 }
  370 
  371                 error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_EE16_IOSIZE);
  372                 if (error) {
  373                         device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n",
  374                                         port, port+IE_EE16_IOSIZE);
  375                         error = device_delete_child(parent, child);
  376                         continue;
  377                 }
  378 
  379                 error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize);
  380                 if (error) {
  381                         device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n",
  382                                         maddr, maddr+msize);
  383                         error = device_delete_child(parent, child);
  384                         continue;
  385                 }
  386 
  387                 if (bootverbose) {
  388                         device_printf(parent,
  389                                 "if_ie: <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n",
  390                                 desc,
  391                                 port, (port + IE_EE16_IOSIZE) - 1,
  392                                 irq,
  393                                 (u_long)maddr, (u_long)(maddr + msize) - 1,
  394                                 (msize / 1024));
  395                 }
  396         }
  397 
  398         return;
  399 }
  400 
  401 static int
  402 ie_isa_ee16_probe (device_t dev)
  403 {
  404         u_int32_t       iobase;
  405 
  406         /* No ISA-PnP support */
  407         if (isa_get_vendorid(dev))
  408                 return (ENXIO);
  409 
  410         /* No ISA-HINT support */
  411         if (!device_get_desc(dev))
  412                 return (EBUSY);
  413 
  414         /* Have we at least an ioport? */
  415         if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
  416                 return (ENXIO);
  417 
  418         /* Is this really an EE16? */
  419         if (ie_ee16_port_check(iobase))
  420                 return (ENXIO);
  421 
  422         return (0);
  423 }
  424 
  425 static int
  426 ie_isa_ee16_attach (device_t dev)
  427 {
  428         struct ie_softc *       sc;
  429         int                     i, error;
  430         u_int16_t               checksum;
  431         u_short                 eaddrtemp, pg, adjust, decode, edecode;
  432         u_char                  bart_config;
  433         
  434         sc = device_get_softc(dev);
  435 
  436         sc->io_rid = 0;
  437         sc->irq_rid = 0;
  438         sc->mem_rid = 0;
  439 
  440         error = ie_alloc_resources(dev);
  441         if (error) {
  442                 goto bad;
  443         }
  444 
  445         sc->bus_use = 0;
  446         sc->ie_reset_586 = ee16_reset_586;
  447         sc->ie_chan_attn = ee16_chan_attn;
  448         sc->hard_type = IE_EE16;
  449         sc->hard_vers = 0;
  450         sc->iomem = 0;
  451 
  452         /* reset any ee16 at the current iobase */
  453         outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_ASIC);
  454         outb(PORT(sc) + IEE16_ECTRL, 0);
  455         DELAY(240);
  456 
  457         /* Is this really an EE16? */
  458         if (ie_ee16_port_check(PORT(sc))) {
  459                 device_printf(dev, "ie_ee16_port_check() failed\n");
  460                 error = ENXIO;
  461                 goto bad;
  462         }
  463 
  464         /* need to put the 586 in RESET while we access the eeprom. */
  465         outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_586);
  466 
  467         /* read the eeprom and checksum it, should == IE_E16_ID */
  468         checksum = 0;
  469         for (i = 0; i < 0x40; i++)
  470                 checksum += ie_ee16_hw_read_eeprom(PORT(sc), i);
  471 
  472         if (checksum != IE_EE16_ID) {
  473                 device_printf(dev, "invalid eeprom checksum: %x\n", checksum);
  474                 error = ENXIO;
  475                 goto bad;
  476         }
  477 
  478         if ((kvtop(sc->iomembot) < 0xC0000) ||
  479              (kvtop(sc->iomembot) + sc->iosize > 0xF0000)) {
  480                 device_printf(sc->dev, "mapped memory location %p out of range\n",
  481                         (void *)sc->iomembot);
  482                 error = ENXIO;
  483                 goto bad;
  484         }
  485 
  486         pg = ((kvtop(sc->iomembot)) & 0x3C000) >> 14;
  487         adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
  488         decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
  489         edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
  490 
  491         /* ZZZ This should be checked against eeprom location 6, low byte */
  492         outb(PORT(sc) + IEE16_MEMDEC, decode & 0xFF);
  493         /* ZZZ This should be checked against eeprom location 1, low byte */
  494         outb(PORT(sc) + IEE16_MCTRL, adjust);
  495         /* ZZZ Now if I could find this one I would have it made */
  496         outb(PORT(sc) + IEE16_MPCTRL, (~decode & 0xFF));
  497         /* ZZZ I think this is location 6, high byte */
  498         outb(PORT(sc) + IEE16_MECTRL, edecode); /* XXX disable Exxx */
  499 
  500 #if 0
  501         (void) kvtop(sc->iomembot);
  502 #endif
  503 
  504         /*
  505          * first prime the stupid bart DRAM controller so that it works,
  506          * then zero out all of memory.
  507          */
  508         bzero(sc->iomembot, 32);
  509         bzero(sc->iomembot, sc->iosize);
  510 
  511         /* Get the encoded interrupt number from the EEPROM */
  512         sc->irq_encoded = ie_ee16_hw_read_eeprom(PORT(sc),
  513                                                  IE_EE16_EEPROM_CONFIG1);
  514         sc->irq_encoded = (sc->irq_encoded & IE_EE16_EEPROM_IRQ_MASK) >>
  515                            IE_EE16_EEPROM_IRQ_SHIFT;
  516 
  517         /*
  518          * Get the hardware ethernet address from the EEPROM and save it in
  519          * the softc for use by the 586 setup code.
  520          */
  521         eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_HIGH);
  522         sc->enaddr[1] = eaddrtemp & 0xFF;
  523         sc->enaddr[0] = eaddrtemp >> 8;
  524         eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_MID);
  525         sc->enaddr[3] = eaddrtemp & 0xFF;
  526         sc->enaddr[2] = eaddrtemp >> 8;
  527         eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_LOW);
  528         sc->enaddr[5] = eaddrtemp & 0xFF;
  529         sc->enaddr[4] = eaddrtemp >> 8;
  530 
  531         /* disable the board interrupts */
  532         outb(PORT(sc) + IEE16_IRQ, sc->irq_encoded);
  533 
  534         /* enable loopback to keep bad packets off the wire */
  535         bart_config = inb(PORT(sc) + IEE16_CONFIG);
  536         bart_config |= IEE16_BART_LOOPBACK;
  537         bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */
  538         outb(PORT(sc) + IEE16_CONFIG, bart_config);
  539         bart_config = inb(PORT(sc) + IEE16_CONFIG);
  540 
  541         /* take the board out of reset state */
  542         outb(PORT(sc) + IEE16_ECTRL, 0);
  543         DELAY(100);
  544 
  545         if (!check_ie_present(sc)) {
  546                 device_printf(dev, "check_ie_present() returned false.\n");
  547                 error = ENXIO;
  548                 goto bad;
  549         }
  550 
  551         error = ie_attach(dev);
  552         if (error) {
  553                 device_printf(dev, "ie_attach() failed.\n");
  554                 goto bad;
  555         }
  556 
  557         return (0);
  558 bad:
  559         ie_release_resources(dev);
  560 
  561         return (error);
  562 }
  563 
  564 static int
  565 ie_isa_ee16_shutdown(device_t dev)
  566 {
  567         struct ie_softc *       sc;
  568 
  569         sc = device_get_softc(dev);
  570         IE_LOCK(sc);
  571         ee16_shutdown(sc);
  572         IE_UNLOCK(sc);
  573 
  574         return (0);
  575 }
  576 
  577 /*
  578  * If an EE16 is present, return 0
  579  * else, return 1.
  580  */
  581 static int
  582 ie_ee16_port_check (u_int32_t port)
  583 {
  584         int             i;
  585         u_int16_t       board_id;
  586         u_int8_t        data;
  587 
  588         board_id = 0;
  589         for (i = 0; i < 4; i++) {
  590                 data = inb(port + IE_EE16_ID_PORT);
  591                 board_id |= ((data >> 4) << ((data & 0x03) << 2));
  592         }
  593 
  594         if (board_id != IE_EE16_ID)
  595                 return (1);
  596 
  597         return (0);
  598 }
  599 
  600 static void
  601 ie_ee16_hw_eeprom_clock (u_int32_t port, int state)
  602 {
  603         u_int8_t        ectrl;
  604 
  605         ectrl = inb(port + IEE16_ECTRL);
  606         ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
  607 
  608         if (state) {
  609                 ectrl |= IEE16_ECTRL_EESK;
  610         }
  611         outb(port + IEE16_ECTRL, ectrl);
  612         DELAY(9);               /* EESK must be stable for 8.38 uSec */
  613 }
  614 
  615 static void
  616 ie_ee16_hw_eeprom_out (u_int32_t port, u_int16_t edata, int count)
  617 {
  618         u_int8_t        ectrl;
  619         int             i;
  620 
  621         ectrl = inb(port + IEE16_ECTRL);
  622         ectrl &= ~IEE16_RESET_ASIC;
  623 
  624         for (i = count - 1; i >= 0; i--) {
  625                 ectrl &= ~IEE16_ECTRL_EEDI;
  626                 if (edata & (1 << i)) {
  627                         ectrl |= IEE16_ECTRL_EEDI;
  628                 }
  629                 outb(port + IEE16_ECTRL, ectrl);
  630                 DELAY(1);       /* eeprom data must be setup for 0.4 uSec */
  631                 ie_ee16_hw_eeprom_clock(port, 1);
  632                 ie_ee16_hw_eeprom_clock(port, 0);
  633         }
  634         ectrl &= ~IEE16_ECTRL_EEDI;
  635         outb(port + IEE16_ECTRL, ectrl);
  636         DELAY(1);               /* eeprom data must be held for 0.4 uSec */
  637 
  638         return;
  639 }
  640 
  641 static u_int16_t
  642 ie_ee16_hw_eeprom_in (u_int32_t port)
  643 {
  644         u_int8_t        ectrl;
  645         u_int16_t       edata;
  646         int             i;
  647 
  648         ectrl = inb(port + IEE16_ECTRL);
  649         ectrl &= ~IEE16_RESET_ASIC;
  650 
  651         for (edata = 0, i = 0; i < 16; i++) {
  652                 edata = edata << 1;
  653                 ie_ee16_hw_eeprom_clock(port, 1);
  654                 ectrl = inb(port + IEE16_ECTRL);
  655                 if (ectrl & IEE16_ECTRL_EEDO) {
  656                         edata |= 1;
  657                 }
  658                 ie_ee16_hw_eeprom_clock(port, 0);
  659         }
  660         return (edata);
  661 }
  662 
  663 static u_int16_t
  664 ie_ee16_hw_read_eeprom (u_int32_t port, int loc)
  665 {
  666         u_int8_t        ectrl;
  667         u_int16_t       edata;
  668 
  669         ectrl = inb(port + IEE16_ECTRL);
  670         ectrl &= IEE16_ECTRL_MASK;
  671         ectrl |= IEE16_ECTRL_EECS;
  672         outb(port + IEE16_ECTRL, ectrl);
  673 
  674         ie_ee16_hw_eeprom_out(port, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
  675         ie_ee16_hw_eeprom_out(port, loc, IEE16_EEPROM_ADDR_SIZE);
  676         edata = ie_ee16_hw_eeprom_in(port);
  677 
  678         ectrl = inb(port + IEE16_ECTRL);
  679         ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
  680         outb(port + IEE16_ECTRL, ectrl);
  681 
  682         ie_ee16_hw_eeprom_clock(port, 1);
  683         ie_ee16_hw_eeprom_clock(port, 0);
  684 
  685         return (edata);
  686 }
  687 
  688 /*
  689  * AT&T StarLan/
  690  */
  691 
  692 static int
  693 ie_isa_sl_probe (device_t dev)
  694 {
  695         u_int32_t       iobase;
  696 
  697         /* No ISA-PnP support */
  698         if (isa_get_vendorid(dev))
  699                 return (ENXIO);
  700 
  701         /* ISA-HINT support only! */
  702         if (device_get_desc(dev))
  703                 return (EBUSY);
  704 
  705         /* Have we at least an ioport? */
  706         if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
  707                 return (ENXIO);
  708 
  709         /* Is this really an SL board? */
  710         if (ie_isa_sl_get_hard_type(iobase) == IE_NONE)
  711                 return (ENXIO);
  712 
  713         return (ENXIO);
  714 }
  715 
  716 static int
  717 ie_isa_sl_attach (device_t dev)
  718 {
  719         struct ie_softc *       sc;
  720         int                     error;
  721 
  722         sc = device_get_softc(dev);
  723 
  724         sc->io_rid = 0;
  725         sc->irq_rid = 0;
  726         sc->mem_rid = 0;
  727 
  728         error = ie_alloc_resources(dev);
  729         if (error) {
  730                 goto bad;
  731         }
  732 
  733         /* Is this really an SL board? */
  734         if ((sc->hard_type = ie_isa_sl_get_hard_type(PORT(sc))) == IE_NONE) {
  735                 error = ENXIO;
  736                 goto bad;
  737         }
  738 
  739         sc->hard_vers = SL_REV(inb(PORT(sc) + IEATT_REVISION));
  740         if (sc->hard_type == IE_NI5210) {
  741                 sc->bus_use = 1;
  742         } else {
  743                 sc->bus_use = 0;
  744         }
  745 
  746         sc->ie_reset_586 = sl_reset_586;
  747         sc->ie_chan_attn = sl_chan_attn;
  748 
  749         if (!check_ie_present(sc)) {
  750                 error = ENXIO;
  751                 goto bad;
  752         }
  753 
  754         switch (sc->hard_type) {
  755                 case IE_EN100:
  756                 case IE_STARLAN10:
  757                 case IE_SLFIBER:
  758                 case IE_NI5210:
  759                         sl_read_ether(sc, sc->enaddr);
  760                         break;
  761                 default:
  762                         if (bootverbose)
  763                                 device_printf(sc->dev, "unknown AT&T board type code %d\n", sc->hard_type);
  764                         error = ENXIO;
  765                         goto bad;
  766                         break;
  767         }
  768 
  769         error = ie_attach(dev);
  770         if (error) {
  771                 device_printf(dev, "ie_attach() failed.\n");
  772                 goto bad;
  773         }
  774 
  775         return (0);
  776 bad:
  777         ie_release_resources(dev);
  778 
  779         return (error);
  780 }
  781 
  782 static enum ie_hardware
  783 ie_isa_sl_get_hard_type (u_int32_t port)
  784 {
  785         u_char                  c;
  786         enum ie_hardware        retval;
  787 
  788         c = inb(port + IEATT_REVISION);
  789         switch (SL_BOARD(c)) {
  790                 case SL1_BOARD:
  791                         if (inb(port + IEATT_ATTRIB) != NI5210_BOARD)
  792                                 retval = IE_NONE;
  793                         retval = IE_NI5210;
  794                         break;
  795                 case SL10_BOARD:
  796                         retval = IE_STARLAN10;
  797                         break;
  798                 case EN100_BOARD:
  799                         retval = IE_EN100;
  800                         break;
  801                 case SLFIBER_BOARD:
  802                         retval = IE_SLFIBER;
  803                         break;
  804                 default:
  805                         retval = IE_NONE;
  806         }
  807         return (retval);
  808 }
  809 
  810 static devclass_t ie_devclass;
  811 
  812 static device_method_t ie_isa_3C507_methods[] = {
  813         DEVMETHOD(device_identify,      ie_isa_3C507_identify),
  814         DEVMETHOD(device_probe,         ie_isa_3C507_probe),
  815         DEVMETHOD(device_attach,        ie_isa_3C507_attach),
  816         DEVMETHOD(device_detach,        ie_detach),
  817         { 0, 0 }
  818 };
  819 
  820 static driver_t ie_isa_3C507_driver = {
  821         "ie",
  822         ie_isa_3C507_methods,
  823         sizeof(struct ie_softc), 
  824 };
  825 
  826 DRIVER_MODULE(ie_3C507, isa, ie_isa_3C507_driver, ie_devclass, ie_modevent, 0);
  827 MODULE_DEPEND(ie_3C507, elink, 1, 1, 1);
  828 
  829 static device_method_t ie_isa_ee16_methods[] = {
  830         DEVMETHOD(device_identify,      ie_isa_ee16_identify),
  831         DEVMETHOD(device_probe,         ie_isa_ee16_probe),
  832         DEVMETHOD(device_attach,        ie_isa_ee16_attach),
  833         DEVMETHOD(device_shutdown,      ie_isa_ee16_shutdown),
  834         DEVMETHOD(device_detach,        ie_detach),
  835         { 0, 0 }
  836 };
  837 
  838 static driver_t ie_isa_ee16_driver = {
  839         "ie",
  840         ie_isa_ee16_methods,
  841         sizeof(struct ie_softc), 
  842 };
  843 
  844 DRIVER_MODULE(ie, isa, ie_isa_ee16_driver, ie_devclass, ie_modevent, 0);
  845 
  846 static device_method_t ie_isa_sl_methods[] = {
  847         DEVMETHOD(device_probe,         ie_isa_sl_probe),
  848         DEVMETHOD(device_attach,        ie_isa_sl_attach),
  849         DEVMETHOD(device_detach,        ie_detach),
  850         { 0, 0 }
  851 };
  852 
  853 static driver_t ie_isa_sl_driver = {
  854         "ie",
  855         ie_isa_sl_methods,
  856         sizeof(struct ie_softc), 
  857 };
  858 
  859 DRIVER_MODULE(ie_SL, isa, ie_isa_sl_driver, ie_devclass, ie_modevent, 0);
  860 
  861 static int
  862 ie_modevent (mod, what, arg)
  863         module_t        mod;
  864         int             what;
  865         void *          arg;
  866 {
  867         device_t *      devs;
  868         int             count;
  869         int             i;
  870 
  871         switch (what) {
  872         case MOD_LOAD:
  873                 break;
  874         case MOD_UNLOAD:
  875                 devclass_get_devices(ie_devclass, &devs, &count);
  876                 for (i = 0; i < count; i++)
  877                         device_delete_child(device_get_parent(devs[i]), devs[i]);
  878                 break;
  879         default:
  880                 break;
  881         };
  882 
  883         return (0);
  884 }

Cache object: 1f8a4e48cdf319dd496fa4d2db46f52b


[ 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.