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/isa/if_le_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 /*      $OpenBSD: if_le_isa.c,v 1.23 2022/04/06 18:59:28 naddy Exp $    */
    2 /*      $NetBSD: if_le_isa.c,v 1.2 1996/05/12 23:52:56 mycroft Exp $    */
    3 
    4 /*-
    5  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
    6  * Copyright (c) 1992, 1993
    7  *      The Regents of the University of California.  All rights reserved.
    8  *
    9  * This code is derived from software contributed to Berkeley by
   10  * Ralph Campbell and Rick Macklem.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)if_le.c     8.2 (Berkeley) 11/16/93
   37  */
   38 
   39 #include "bpfilter.h"
   40 #include "isadma.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/syslog.h>
   46 #include <sys/socket.h>
   47 #include <sys/device.h>
   48 
   49 #include <net/if.h>
   50 #include <net/if_media.h>
   51 
   52 #include <netinet/in.h>
   53 #include <netinet/if_ether.h>
   54 
   55 #include <machine/cpu.h>
   56 #include <machine/intr.h>
   57 
   58 #include <dev/isa/isareg.h>
   59 #include <dev/isa/isavar.h>
   60 #include <dev/isa/isadmavar.h>
   61 
   62 #include <dev/ic/lancereg.h>
   63 #include <dev/ic/lancevar.h>
   64 #include <dev/ic/am7990reg.h>
   65 #include <dev/ic/am7990var.h>
   66 
   67 #include <dev/isa/if_levar.h>
   68 
   69 static char *card_type[] =
   70     { "unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA" };
   71 
   72 int     le_isa_probe(struct device *, void *, void *);
   73 void    le_isa_attach(struct device *, struct device *, void *);
   74 
   75 const struct cfattach le_isa_ca = {
   76         sizeof(struct le_softc), le_isa_probe, le_isa_attach
   77 };
   78 
   79 int     depca_isa_probe(struct le_softc *, struct isa_attach_args *);
   80 int     ne2100_isa_probe(struct le_softc *, struct isa_attach_args *);
   81 int     bicc_isa_probe(struct le_softc *, struct isa_attach_args *);
   82 int     lance_isa_probe(struct lance_softc *);
   83 
   84 int
   85 le_isa_probe(struct device *parent, void *match, void *aux)
   86 {
   87         struct le_softc *lesc = match;
   88         struct isa_attach_args *ia = aux;
   89         u_int8_t bogusether[ETHER_ADDR_LEN] = { 255, 255, 255, 255, 255, 255 };
   90 
   91 #if NISADMA == 0
   92         if (ia->ia_drq != DRQUNK) {
   93                 printf("cannot support dma lance devices\n");
   94                 return 0;
   95         }
   96 #endif
   97 
   98         if (bicc_isa_probe(lesc, ia) == 0 && ne2100_isa_probe(lesc, ia) == 0 &&
   99             depca_isa_probe(lesc, ia) == 0)
  100                 return (0);
  101 
  102         if (bcmp(lesc->sc_am7990.lsc.sc_arpcom.ac_enaddr, bogusether,
  103             sizeof(bogusether)) == 0)
  104                 return (0);
  105 
  106         return (1);
  107 }
  108 
  109 int
  110 depca_isa_probe(struct le_softc *lesc, struct isa_attach_args *ia)
  111 {
  112         struct lance_softc *sc = &lesc->sc_am7990.lsc;
  113         bus_space_tag_t iot = lesc->sc_iot;
  114         bus_space_handle_t ioh = lesc->sc_ioh;
  115         int iosize = 16;
  116         int port;
  117 
  118 #if 0
  119         u_long sum, rom_sum;
  120         u_char x;
  121 #endif
  122         int i;
  123 
  124         if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh))
  125                 return (0);
  126         lesc->sc_iot = iot;
  127         lesc->sc_ioh = ioh;
  128         lesc->sc_rap = DEPCA_RAP;
  129         lesc->sc_rdp = DEPCA_RDP;
  130         lesc->sc_card = DEPCA;
  131 
  132         if (lance_isa_probe(sc) == 0) {
  133                 bus_space_unmap(iot, ioh, iosize);
  134                 return 0;
  135         }
  136 
  137         bus_space_write_1(iot, ioh, DEPCA_CSR, DEPCA_CSR_DUM);
  138 
  139         /*
  140          * Extract the physical MAC address from the ROM.
  141          *
  142          * The address PROM is 32 bytes wide, and we access it through
  143          * a single I/O port.  On each read, it rotates to the next
  144          * position.  We find the ethernet address by looking for a
  145          * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff,
  146          * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the
  147          * ethernet address and a checksum).
  148          *
  149          * It appears that the PROM can be at one of two locations, so
  150          * we just try both.
  151          */
  152         port = DEPCA_ADP;
  153         for (i = 0; i < 32; i++)
  154                 if (bus_space_read_1(iot, ioh, port) == 0xff &&
  155                     bus_space_read_1(iot, ioh, port) == 0x00 &&
  156                     bus_space_read_1(iot, ioh, port) == 0x55 &&
  157                     bus_space_read_1(iot, ioh, port) == 0xaa &&
  158                     bus_space_read_1(iot, ioh, port) == 0xff &&
  159                     bus_space_read_1(iot, ioh, port) == 0x00 &&
  160                     bus_space_read_1(iot, ioh, port) == 0x55 &&
  161                     bus_space_read_1(iot, ioh, port) == 0xaa)
  162                         goto found;
  163         port = DEPCA_ADP + 1;
  164         for (i = 0; i < 32; i++)
  165                 if (bus_space_read_1(iot, ioh, port) == 0xff &&
  166                     bus_space_read_1(iot, ioh, port) == 0x00 &&
  167                     bus_space_read_1(iot, ioh, port) == 0x55 &&
  168                     bus_space_read_1(iot, ioh, port) == 0xaa &&
  169                     bus_space_read_1(iot, ioh, port) == 0xff &&
  170                     bus_space_read_1(iot, ioh, port) == 0x00 &&
  171                     bus_space_read_1(iot, ioh, port) == 0x55 &&
  172                     bus_space_read_1(iot, ioh, port) == 0xaa)
  173                         goto found;
  174         printf("%s: address not found\n", sc->sc_dev.dv_xname);
  175         return 0;
  176 
  177 found:
  178         for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
  179                 sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, port);
  180 
  181 #if 0
  182         sum =
  183             (sc->sc_arpcom.ac_enaddr[0] <<  2) +
  184             (sc->sc_arpcom.ac_enaddr[1] << 10) +
  185             (sc->sc_arpcom.ac_enaddr[2] <<  1) +
  186             (sc->sc_arpcom.ac_enaddr[3] <<  9) +
  187             (sc->sc_arpcom.ac_enaddr[4] <<  0) +
  188             (sc->sc_arpcom.ac_enaddr[5] <<  8);
  189         sum = (sum & 0xffff) + (sum >> 16);
  190         sum = (sum & 0xffff) + (sum >> 16);
  191 
  192         rom_sum = bus_space_read_1(iot, ioh, port);
  193         rom_sum |= bus_space_read_1(iot, ioh, port << 8);
  194 
  195         if (sum != rom_sum) {
  196                 printf("%s: checksum mismatch; calculated %04x != read %04x",
  197                     sc->sc_dev.dv_xname, sum, rom_sum);
  198                 bus_space_unmap(iot, ioh, iosize);
  199                 return 0;
  200         }
  201 #endif
  202 
  203         bus_space_write_1(iot, ioh, DEPCA_CSR, DEPCA_CSR_NORMAL);
  204 
  205         ia->ia_iosize = iosize;
  206         ia->ia_drq = DRQUNK;
  207         bus_space_unmap(iot, ioh, ia->ia_iosize);
  208         return 1;
  209 }
  210 
  211 int
  212 ne2100_isa_probe(struct le_softc *lesc, struct isa_attach_args *ia)
  213 {
  214         struct lance_softc *sc = &lesc->sc_am7990.lsc;
  215         bus_space_tag_t iot = lesc->sc_iot;
  216         bus_space_handle_t ioh = lesc->sc_ioh;
  217         int iosize = 24;
  218         int i;
  219 
  220         if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh))
  221                 return (0);
  222         lesc->sc_iot = iot;
  223         lesc->sc_ioh = ioh;
  224         lesc->sc_rap = NE2100_RAP;
  225         lesc->sc_rdp = NE2100_RDP;
  226         lesc->sc_card = NE2100;
  227 
  228         if (lance_isa_probe(sc) == 0) {
  229                 bus_space_unmap(iot, ioh, iosize);
  230                 return 0;
  231         }
  232 
  233         /*
  234          * Extract the physical MAC address from the ROM.
  235          */
  236         for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
  237                 sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, i);
  238 
  239         ia->ia_iosize = iosize;
  240         bus_space_unmap(iot, ioh, ia->ia_iosize);
  241         return 1;
  242 }
  243 
  244 int
  245 bicc_isa_probe(struct le_softc *lesc, struct isa_attach_args *ia)
  246 {
  247         struct lance_softc *sc = &lesc->sc_am7990.lsc;
  248         bus_space_handle_t ioh;
  249         bus_space_tag_t iot = ia->ia_iot;
  250         int iosize = 16;
  251         int i;
  252 
  253         if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh))
  254                 return (0);
  255         lesc->sc_iot = iot;
  256         lesc->sc_ioh = ioh;
  257         lesc->sc_rap = BICC_RAP;
  258         lesc->sc_rdp = BICC_RDP;
  259         lesc->sc_card = BICC;
  260 
  261         if (lance_isa_probe(sc) == 0) {
  262                 bus_space_unmap(iot, ioh, iosize);
  263                 return 0;
  264         }
  265 
  266         /*
  267          * Extract the physical MAC address from the ROM.
  268          */
  269         for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
  270                 sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, i * 2);
  271 
  272         ia->ia_iosize = iosize;
  273         bus_space_unmap(iot, ioh, ia->ia_iosize);
  274         return 1;
  275 }
  276 
  277 /*
  278  * Determine which chip is present on the card.
  279  */
  280 int
  281 lance_isa_probe(struct lance_softc *sc)
  282 {
  283 
  284         /* Stop the LANCE chip and put it in a known state. */
  285         le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP);
  286         delay(100);
  287 
  288         if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP)
  289                 return 0;
  290 
  291         le_isa_wrcsr(sc, LE_CSR3, sc->sc_conf3);
  292         return 1;
  293 }
  294 
  295 void
  296 le_isa_attach(struct device *parent, struct device *self,
  297     void *aux)
  298 {
  299         struct le_softc *lesc = (void *)self;
  300         struct lance_softc *sc = &lesc->sc_am7990.lsc;
  301         struct isa_attach_args *ia = aux;
  302         bus_space_tag_t iot = ia->ia_iot;
  303         bus_space_handle_t ioh;
  304 
  305         if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
  306                 panic("%s: can't map I/O-ports", sc->sc_dev.dv_xname);
  307         lesc->sc_iot = iot;
  308         lesc->sc_ioh = ioh;
  309 
  310         printf(": %s Ethernet\n", card_type[lesc->sc_card]);
  311 
  312         if (lesc->sc_card == DEPCA) {
  313                 u_char *mem, val;
  314                 int i;
  315 
  316                 mem = sc->sc_mem = ISA_HOLE_VADDR(ia->ia_maddr);
  317 
  318                 val = 0xff;
  319                 for (;;) {
  320                         for (i = 0; i < ia->ia_msize; i++)
  321                                 mem[i] = val;
  322                         for (i = 0; i < ia->ia_msize; i++)
  323                                 if (mem[i] != val) {
  324                                         printf("%s: failed to clear memory\n",
  325                                             sc->sc_dev.dv_xname);
  326                                         return;
  327                                 }
  328                         if (val == 0x00)
  329                                 break;
  330                         val -= 0x55;
  331                 }
  332 
  333                 sc->sc_conf3 = LE_C3_ACON;
  334                 sc->sc_addr = 0;
  335                 sc->sc_memsize = ia->ia_msize;
  336         } else {
  337                 sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT);
  338                 if (sc->sc_mem == 0) {
  339                         printf("%s: couldn't allocate memory for card\n",
  340                             sc->sc_dev.dv_xname);
  341                         return;
  342                 }
  343 
  344                 sc->sc_conf3 = 0;
  345                 sc->sc_addr = kvtop(sc->sc_mem);
  346                 sc->sc_memsize = 16384;
  347         }
  348 
  349         sc->sc_copytodesc = lance_copytobuf_contig;
  350         sc->sc_copyfromdesc = lance_copyfrombuf_contig;
  351         sc->sc_copytobuf = lance_copytobuf_contig;
  352         sc->sc_copyfrombuf = lance_copyfrombuf_contig;
  353         sc->sc_zerobuf = lance_zerobuf_contig;
  354 
  355         sc->sc_rdcsr = le_isa_rdcsr;
  356         sc->sc_wrcsr = le_isa_wrcsr;
  357         sc->sc_hwreset = NULL;
  358         sc->sc_hwinit = NULL;
  359 
  360         printf("%s", sc->sc_dev.dv_xname);
  361         am7990_config(&lesc->sc_am7990);
  362 
  363 #if NISADMA > 0
  364         if (ia->ia_drq != DRQUNK)
  365                 isadma_cascade(ia->ia_drq);
  366 #endif
  367 
  368         lesc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  369             IPL_NET, le_isa_intredge, sc, sc->sc_dev.dv_xname);
  370 }

Cache object: 88bdf11728c8a9b2b8795c68e8da5b28


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