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/i386/isa/if_rdp.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 1998, Joerg Wunsch
    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 unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD: releng/5.0/sys/i386/isa/if_rdp.c 106939 2002-11-15 00:00:15Z sam $
   28  */
   29 
   30 /*
   31  * Device driver for RealTek RTL 8002 (`REDP') based pocket-ethernet
   32  * adapters, hooked up to a printer port.  `rdp' is a shorthand for
   33  * REDP since some tools like netstat work best if the interface name
   34  * has no more than three letters.
   35  *
   36  * Driver configuration flags so far:
   37  *   flags 0x1 -- assume 74S288 EEPROM (default 94C46)
   38  *   flags 0x2 -- use `slow' mode (mode 3 of the packet driver, default 0)
   39  *
   40  * Maybe this driver will some day also work with the successor, RTL
   41  * 8012 (`AREDP'), which is unfortunately not fully register-
   42  * compatible with the 8002.  The 8012 offers support for faster
   43  * transfer modi like bidirectional SPP and EPP, 64 K x 4 buffer
   44  * memory as opposed to 16 K x 4 for the 8002, a multicast filter, and
   45  * a builtin multiplexer that allows chaining a printer behind the
   46  * ethernet adapter.
   47  *
   48  * About the only documentation i've been able to find about the RTL
   49  * 8002 was the packet driver source code at ftp.realtek.com.tw, so
   50  * this driver is somewhat based on the way the packet driver handles
   51  * the chip.  The exact author of the packet driver is unknown, the
   52  * only name that i could find in the source was someone called Chiu,
   53  * supposedly an employee of RealTek.  So credits to them for that
   54  * piece of code which has proven valuable to me.
   55  *
   56  * Later on, Leo kuo <leo@realtek.com.tw> has been very helpful to me
   57  * by sending me a readable (PDF) file documenting the RTL 8012, which
   58  * helped me to also understand the 8002, as well as by providing me
   59  * with the source code of the 8012 packet driver that i haven't been
   60  * able to find on the FTP site.  A big Thanks! goes here to RealTek
   61  * for this kind of service.
   62  */
   63 
   64 #include "rdp.h"
   65 
   66 #include <sys/param.h>
   67 #include <sys/systm.h>
   68 #include <sys/kernel.h>
   69 #include <sys/sockio.h>
   70 #include <sys/mbuf.h>
   71 #include <sys/socket.h>
   72 #include <sys/syslog.h>
   73 #include <sys/bus.h>
   74 
   75 #include <net/ethernet.h>
   76 #include <net/if.h>
   77 #include <net/if_arp.h>
   78 #include <net/if_dl.h>
   79 #include <net/if_mib.h>
   80 
   81 #ifdef INET
   82 #include <netinet/in.h>
   83 #include <netinet/if_ether.h>
   84 #endif
   85 
   86 #ifdef NS
   87 #include <netns/ns.h>
   88 #include <netns/ns_if.h>
   89 #endif
   90 
   91 #include <net/bpf.h>
   92 
   93 #include <machine/md_var.h>
   94 
   95 #include <i386/isa/isa_device.h>
   96 #include <i386/isa/icu.h>
   97 #include <i386/isa/if_rdpreg.h>
   98 #include <i386/isa/intr_machdep.h>
   99 
  100 #ifndef COMPAT_OLDISA
  101 #error "The rdp device requires the old isa compatibility shims"
  102 #endif
  103 
  104 #define IOCTL_CMD_T u_long
  105 
  106 /*
  107  * Debug levels (ORed together):
  108  *  != 0 - general (bad packets etc.)
  109  *  2 - debug EEPROM IO
  110  *  4 - debug interrupt status
  111  */
  112 #undef DEBUG
  113 #define DEBUG 0
  114 
  115 /*
  116  * rdp_softc: per interface info and status
  117  */
  118 struct rdp_softc {
  119         struct arpcom arpcom;   /*
  120                                  * Ethernet common, always goes first so
  121                                  * a rdp_softc * can be cast into an
  122                                  * arpcom * or into an ifnet *.
  123                                  */
  124 
  125         /*
  126          * local stuff, somewhat sorted by memory alignment class
  127          */
  128         u_short baseaddr;       /* IO port address */
  129         u_short txsize;         /* tx size for next (buffered) packet,
  130                                  * there's only one additional packet
  131                                  * we can buffer, thus a single variable
  132                                  * ought to be enough */
  133         int txbusy;             /* tx is transmitting */
  134         int txbuffered;         /* # of packets in tx buffer */
  135         int slow;               /* use lpt_control to send data */
  136         u_char irqenbit;        /* mirror of current Ctrl_IRQEN */
  137         /*
  138          * type of parameter EEPROM; device flags 0x1 selects 74S288
  139          */
  140         enum {
  141                 EEPROM_93C46, EEPROM_74S288 /* or 82S123 */
  142         } eeprom;
  143 };
  144 
  145 static struct rdp_softc rdp_softc[NRDP];
  146 
  147 /*
  148  * Since there's no fixed location in the EEPROM about where to find
  149  * the ethernet hardware address, we drop a table of valid OUIs here,
  150  * and search through the EEPROM until we find a possible valid
  151  * Ethernet address.  Only the first 16 bits of all possible OUIs are
  152  * recorded in the table (as obtained from
  153  * http://standards.ieee.org/regauth/oui/oui.txt).
  154  */
  155 
  156 static u_short allowed_ouis[] = {
  157         0x0000, 0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007,
  158         0x0008, 0x0010, 0x001C, 0x0020, 0x0040, 0x0050, 0x0060,
  159         0x0070, 0x0080, 0x0090, 0x009D, 0x00A0, 0x00AA, 0x00BB,
  160         0x00C0, 0x00CF, 0x00DD, 0x00E0, 0x00E6, 0x0207, 0x021C,
  161         0x0260, 0x0270, 0x029D, 0x02AA, 0x02BB, 0x02C0, 0x02CF,
  162         0x02E6, 0x040A, 0x04E0, 0x0800, 0x08BB, 0x1000, 0x1100,
  163         0x8000, 0xAA00
  164 };
  165 
  166 /*
  167  * ISA bus support.
  168  */
  169 static int rdp_probe(struct isa_device *);
  170 static int rdp_attach(struct isa_device *);
  171 
  172 /*
  173  * Required entry points.
  174  */
  175 static void rdp_init(void *);
  176 static int rdp_ioctl(struct ifnet *, IOCTL_CMD_T, caddr_t);
  177 static void rdp_start(struct ifnet *);
  178 static void rdp_reset(struct ifnet *);
  179 static void rdp_watchdog(struct ifnet *);
  180 static void rdpintr(int);
  181 
  182 /*
  183  * REDP private functions.
  184  */
  185 
  186 static void rdp_stop(struct rdp_softc *);
  187 static void rdp_rint(struct rdp_softc *);
  188 static void rdp_get_packet(struct rdp_softc *, unsigned);
  189 static u_short rdp_write_mbufs(struct rdp_softc *, struct mbuf *);
  190 static int rdp_gethwaddr_93c46(struct rdp_softc *, u_char *);
  191 static void rdp_gethwaddr_74s288(struct rdp_softc *, u_char *);
  192 static void rdp_93c46_cmd(struct rdp_softc *, u_short, unsigned);
  193 static u_short rdp_93c46_read(struct rdp_softc *);
  194 
  195 struct isa_driver rdpdriver = {
  196         INTR_TYPE_NET,
  197         rdp_probe,
  198         rdp_attach,
  199         "rdp",
  200         1                       /* we wanna get a chance before lptN */
  201 };
  202 COMPAT_ISA_DRIVER(rdp, rdpdriver);
  203 
  204 /*
  205  * REDP-specific functions.
  206  *
  207  * They are inlined, thus go first in this file.  Together with gcc's
  208  * usual optimization, these functions probably come close to the
  209  * packet driver's hand-optimized code. ;-)
  210  *
  211  * Comments are partially obtained from the packet driver as well.
  212  * Some of the function names contain register names which don't make
  213  * much sense for us, but i've kept them for easier reference in
  214  * comparision to the packet driver.
  215  *
  216  * Some of the functions are currently not used by the driver; it's
  217  * not quite clear whether we ever need them at all.  They are
  218  * supposedly even slower than what is currently implemented as `slow'
  219  * mode.  Right now, `fast' (default) mode is what the packet driver
  220  * calls mode 0, slow mode is mode 3 (writing through lpt_control,
  221  * reading twice).
  222  *
  223  * We should autoprobe the modi, as opposed to making them dependent
  224  * on a kernel configuration flag.
  225  */
  226 
  227 /*
  228  * read a nibble from rreg; end-of-data cmd is not issued;
  229  * used for general register read.
  230  *
  231  * Unlike the packet driver's version, i'm shifting the result
  232  * by 3 here (as opposed to within the caller's code) for clarity.
  233  *  -- Joerg
  234  */
  235 static __inline u_char
  236 RdNib(struct rdp_softc *sc, u_char rreg)
  237 {
  238 
  239         outb(sc->baseaddr + lpt_data, EOC + rreg);
  240         outb(sc->baseaddr + lpt_data, RdAddr + rreg); /* write addr */
  241         (void)inb(sc->baseaddr + lpt_status);
  242         return (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f;
  243 }
  244 
  245 #if 0
  246 /*
  247  * read a byte from MAR register through lpt_data; the low nibble is
  248  * read prior to the high one; end-of-read command is not issued; used
  249  * for remote DMA in mode 4 + 5
  250  */
  251 static __inline u_char
  252 RdByte(struct rdp_softc *sc)
  253 {
  254         u_char hinib, lonib;
  255 
  256         outb(sc->baseaddr + lpt_data, RdAddr + MAR); /* cmd for low nibble */
  257         lonib = (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f;
  258         outb(sc->baseaddr + lpt_data, RdAddr + MAR + HNib);
  259         hinib = (inb(sc->baseaddr + lpt_status) << 1) & 0xf0;
  260         return hinib + lonib;
  261 }
  262 
  263 
  264 /*
  265  * read a byte from MAR register through lpt_data; the low nibble is
  266  * read prior to the high one; end-of-read command is not issued; used
  267  * for remote DMA in mode 6 + 7
  268  */
  269 static __inline u_char
  270 RdByte1(struct rdp_softc *sc)
  271 {
  272         u_char hinib, lonib;
  273 
  274         outb(sc->baseaddr + lpt_data, RdAddr + MAR); /* cmd for low nibble */
  275         (void)inb(sc->baseaddr + lpt_status);
  276         lonib = (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f;
  277         outb(sc->baseaddr + lpt_data, RdAddr + MAR + HNib);
  278         (void)inb(sc->baseaddr + lpt_status);
  279         hinib = (inb(sc->baseaddr + lpt_status) << 1) & 0xf0;
  280         return hinib + lonib;
  281 }
  282 #endif
  283 
  284 
  285 /*
  286  * read a byte from MAR register through lpt_control; the low nibble is
  287  * read prior to the high one; end-of-read command is not issued; used
  288  * for remote DMA in mode 0 + 1
  289  */
  290 static __inline u_char
  291 RdByteA1(struct rdp_softc *sc)
  292 {
  293         u_char hinib, lonib;
  294 
  295         outb(sc->baseaddr + lpt_control, Ctrl_LNibRead);
  296         lonib = (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f;
  297         outb(sc->baseaddr + lpt_control, Ctrl_HNibRead);
  298         hinib = (inb(sc->baseaddr + lpt_status) << 1) & 0xf0;
  299         return hinib + lonib;
  300 }
  301 
  302 
  303 /*
  304  * read a byte from MAR register through lpt_control; the low nibble is
  305  * read prior to the high one; end-of-read command is not issued; used
  306  * for remote DMA in mode 2 + 3
  307  */
  308 static __inline u_char
  309 RdByteA2(struct rdp_softc *sc)
  310 {
  311         u_char hinib, lonib;
  312 
  313         outb(sc->baseaddr + lpt_control, Ctrl_LNibRead);
  314         (void)inb(sc->baseaddr + lpt_status);
  315         lonib = (inb(sc->baseaddr + lpt_status) >> 3) & 0x0f;
  316         outb(sc->baseaddr + lpt_control, Ctrl_HNibRead);
  317         (void)inb(sc->baseaddr + lpt_status);
  318         hinib = (inb(sc->baseaddr + lpt_status) << 1) & 0xf0;
  319         return hinib + lonib;
  320 }
  321 
  322 /*
  323  * End-of-read cmd
  324  */
  325 static __inline void
  326 RdEnd(struct rdp_softc *sc, u_char rreg)
  327 {
  328 
  329         outb(sc->baseaddr + lpt_data, EOC + rreg);
  330 }
  331 
  332 /*
  333  * Write a nibble to a register; end-of-write is issued.
  334  * Used for general register write.
  335  */
  336 static __inline void
  337 WrNib(struct rdp_softc *sc, u_char wreg, u_char wdata)
  338 {
  339 
  340         /* prepare and write address */
  341         outb(sc->baseaddr + lpt_data, EOC + wreg);
  342         outb(sc->baseaddr + lpt_data, WrAddr + wreg);
  343         outb(sc->baseaddr + lpt_data, WrAddr + wreg);
  344         /* prepare and write data */
  345         outb(sc->baseaddr + lpt_data, WrAddr + wdata);
  346         outb(sc->baseaddr + lpt_data, wdata);
  347         outb(sc->baseaddr + lpt_data, wdata);
  348         /* end-of-write */
  349         outb(sc->baseaddr + lpt_data, EOC + wdata);
  350 }
  351 
  352 /*
  353  * Write a byte to a register; end-of-write is issued.
  354  * Used for general register write.
  355  */
  356 static __inline void
  357 WrByte(struct rdp_softc *sc, u_char wreg, u_char wdata)
  358 {
  359 
  360         /* prepare and write address */
  361         outb(sc->baseaddr + lpt_data, EOC + wreg);
  362         outb(sc->baseaddr + lpt_data, WrAddr + wreg);
  363         outb(sc->baseaddr + lpt_data, WrAddr + wreg);
  364         /* prepare and write low nibble */
  365         outb(sc->baseaddr + lpt_data, WrAddr + (wdata & 0x0F));
  366         outb(sc->baseaddr + lpt_data, (wdata & 0x0F));
  367         outb(sc->baseaddr + lpt_data, (wdata & 0x0F));
  368         /* prepare and write high nibble */
  369         wdata >>= 4;
  370         outb(sc->baseaddr + lpt_data, wdata);
  371         outb(sc->baseaddr + lpt_data, wdata + HNib);
  372         outb(sc->baseaddr + lpt_data, wdata + HNib);
  373         /* end-of-write */
  374         outb(sc->baseaddr + lpt_data, EOC + wdata + HNib);
  375 }
  376 
  377 /*
  378  * Write the byte to DRAM via lpt_data;
  379  * used for remote DMA write in mode 0 / 2 / 4
  380  */
  381 static __inline void
  382 WrByteALToDRAM(struct rdp_softc *sc, u_char val)
  383 {
  384 
  385         outb(sc->baseaddr + lpt_data, val & 0x0F);
  386         outb(sc->baseaddr + lpt_data, MkHi(val));
  387 }
  388 
  389 /*
  390  * Write the byte to DRAM via lpt_control;
  391  * used for remote DMA write in mode 1 / 3 / 5
  392  */
  393 static __inline void
  394 WrByteALToDRAMA(struct rdp_softc *sc, u_char val)
  395 {
  396 
  397         outb(sc->baseaddr + lpt_data, val & 0x0F);
  398         outb(sc->baseaddr + lpt_control, Ctrl_LNibRead | sc->irqenbit);
  399         outb(sc->baseaddr + lpt_data, val >> 4);
  400         outb(sc->baseaddr + lpt_control, Ctrl_HNibRead | sc->irqenbit);
  401 }
  402 
  403 #if 0 /* they could be used for the RAM test */
  404 /*
  405  * Write the u_short to DRAM via lpt_data;
  406  * used for remote DMA write in mode 0 / 2 / 4
  407  */
  408 static __inline void
  409 WrWordbxToDRAM(struct rdp_softc *sc, u_short val)
  410 {
  411 
  412         outb(sc->baseaddr + lpt_data, val & 0x0F);
  413         val >>= 4;
  414         outb(sc->baseaddr + lpt_data, (val & 0x0F) + HNib);
  415         val >>= 4;
  416         outb(sc->baseaddr + lpt_data, val & 0x0F);
  417         val >>= 4;
  418         outb(sc->baseaddr + lpt_data, val + HNib);
  419 }
  420 
  421 
  422 /*
  423  * Write the u_short to DRAM via lpt_control;
  424  * used for remote DMA write in mode 1 / 3 / 5
  425  */
  426 static __inline void
  427 WrWordbxToDRAMA(struct rdp_softc *sc, u_short val)
  428 {
  429 
  430         outb(sc->baseaddr + lpt_data, val & 0x0F);
  431         outb(sc->baseaddr + lpt_control, Ctrl_LNibRead | sc->irqenbit);
  432         val >>= 4;
  433         outb(sc->baseaddr + lpt_data, (val & 0x0F) + HNib);
  434         outb(sc->baseaddr + lpt_control, Ctrl_HNibRead | sc->irqenbit);
  435         val >>= 4;
  436         outb(sc->baseaddr + lpt_data, val & 0x0F);
  437         outb(sc->baseaddr + lpt_control, Ctrl_LNibRead | sc->irqenbit);
  438         val >>= 4;
  439         outb(sc->baseaddr + lpt_data, val + HNib);
  440         outb(sc->baseaddr + lpt_control, Ctrl_HNibRead | sc->irqenbit);
  441 }
  442 #endif
  443 
  444 
  445 /*
  446  * Determine if the device is present
  447  *
  448  *   on entry:
  449  *      a pointer to an isa_device struct
  450  *   on exit:
  451  *      0 if device not found
  452  *      or # of i/o addresses used (if found)
  453  */
  454 static int
  455 rdp_probe(struct isa_device *isa_dev)
  456 {
  457         int unit = isa_dev->id_unit;
  458         struct rdp_softc *sc = &rdp_softc[unit];
  459         u_char b1, b2;
  460         intrmask_t irqmap[3];
  461         u_char sval[3];
  462 
  463         if (unit < 0 || unit >= NRDP)
  464                 return 0;
  465 
  466         sc->baseaddr = isa_dev->id_iobase;
  467         if (isa_dev->id_flags & 1)
  468                 sc->eeprom = EEPROM_74S288;
  469         /* else defaults to 93C46 */
  470         if (isa_dev->id_flags & 2)
  471                 sc->slow = 1;
  472 
  473         /* let R/WB = A/DB = CSB = high to be ready for next r/w cycle */
  474         outb(sc->baseaddr + lpt_data, 0xFF);
  475         /* DIR = 0 for write mode, IRQEN=0, SLCT=INIT=AUTOFEED=STB=high */
  476         outb(sc->baseaddr + lpt_control, Ctrl_SelData);
  477         /* software reset */
  478         WrNib(sc, CMR1 + HNib, MkHi(CMR1_RST));
  479         DELAY(2000);
  480         /* is EPLC alive? */
  481         b1 = RdNib(sc, CMR1);
  482         RdEnd(sc, CMR1);
  483         b2 = RdNib(sc, CMR2) & 0x0f;
  484         b2 |= RdNib(sc, CMR2 + HNib) << 4;
  485         RdEnd(sc, CMR2 + HNib);
  486         /*
  487          * After the reset, we expect CMR1 & 7 to be 1 (rx buffer empty),
  488          * and CMR2 & 0xf7 to be 0x20 (receive mode set to physical and
  489          * broadcasts).
  490          */
  491         if (bootverbose)
  492                 printf("rdp%d: CMR1 = %#x, CMR2 = %#x\n", unit, b1, b2);
  493 
  494         if ((b1 & (CMR1_BUFE | CMR1_IRQ | CMR1_TRA)) != CMR1_BUFE
  495             || (b2 & ~CMR2_IRQINV) != CMR2_AM_PB)
  496                 return 0;
  497 
  498         /*
  499          * We have found something that could be a RTL 80[01]2, now
  500          * see whether we can generate an interrupt.
  501          */
  502         disable_intr();
  503 
  504         /*
  505          * Test whether our configured IRQ is working.
  506          *
  507          * Set to no acception mode + IRQout, then enable RxE + TxE,
  508          * then cause RBER (by advancing the read pointer although
  509          * the read buffer is empty) to generate an interrupt.
  510          */
  511         WrByte(sc, CMR2, CMR2_IRQOUT);
  512         WrNib(sc, CMR1 + HNib, MkHi(CMR1_TE | CMR1_RE));
  513         WrNib(sc, CMR1, CMR1_RDPAC);
  514         DELAY(1000);
  515 
  516         irqmap[0] = isa_irq_pending();
  517         sval[0] = inb(sc->baseaddr + lpt_status);
  518 
  519         /* allow IRQs to pass the parallel interface */
  520         outb(sc->baseaddr + lpt_control, Ctrl_IRQEN + Ctrl_SelData);
  521         DELAY(1000);
  522         /* generate interrupt */
  523         WrNib(sc, IMR + HNib, MkHi(ISR_RBER));
  524         DELAY(1000);
  525 
  526         irqmap[1] = isa_irq_pending();
  527         sval[1] = inb(sc->baseaddr + lpt_status);
  528 
  529         /* de-assert and disable IRQ */
  530         WrNib(sc, IMR + HNib, MkHi(0));
  531         (void)inb(sc->baseaddr + lpt_status); /* might be necessary to
  532                                                  clear IRQ */
  533         DELAY(1000);
  534         irqmap[2] = isa_irq_pending();
  535         sval[2] = inb(sc->baseaddr + lpt_status);
  536 
  537         WrNib(sc, CMR1 + HNib, MkHi(0));
  538         outb(sc->baseaddr + lpt_control, Ctrl_SelData);
  539         WrNib(sc, CMR2, CMR2_IRQINV);
  540 
  541         enable_intr();
  542 
  543         if (bootverbose)
  544                 printf("rdp%d: irq maps / lpt status "
  545                        "%#x/%#x - %#x/%#x - %#x/%#x (id_irq %#x)\n",
  546                        unit, irqmap[0], sval[0], irqmap[1], sval[1],
  547                        irqmap[2], sval[2], isa_dev->id_irq);
  548 
  549         if ((irqmap[1] & isa_dev->id_irq) == 0) {
  550                 printf("rdp%d: configured IRQ (%d) cannot be asserted "
  551                        "by device",
  552                        unit, ffs(isa_dev->id_irq) - 1);
  553                 if (irqmap[1])
  554                         printf(" (probable IRQ: %d)", ffs(irqmap[1]) - 1);
  555                 printf("\n");
  556                 return 0;
  557         }
  558 
  559         /*
  560          * XXX should do RAMtest here
  561          */
  562 
  563         switch (sc->eeprom) {
  564         case EEPROM_93C46:
  565                 if (rdp_gethwaddr_93c46(sc, sc->arpcom.ac_enaddr) == 0) {
  566                         printf("rdp%d: failed to find a valid hardware "
  567                                "address in EEPROM\n",
  568                                unit);
  569                         return 0;
  570                 }
  571                 break;
  572 
  573         case EEPROM_74S288:
  574                 rdp_gethwaddr_74s288(sc, sc->arpcom.ac_enaddr);
  575                 break;
  576         }
  577 
  578         return lpt_control + 1;
  579 }
  580 
  581 /*
  582  * Install interface into kernel networking data structures
  583  */
  584 static int
  585 rdp_attach(struct isa_device *isa_dev)
  586 {
  587         int unit = isa_dev->id_unit;
  588         struct rdp_softc *sc = &rdp_softc[unit];
  589         struct ifnet *ifp = &sc->arpcom.ac_if;
  590 
  591         isa_dev->id_ointr = rdpintr;
  592 
  593         /*
  594          * Reset interface
  595          */
  596         rdp_stop(sc);
  597 
  598         if (!ifp->if_name) {
  599                 /*
  600                  * Initialize ifnet structure
  601                  */
  602                 ifp->if_softc = sc;
  603                 ifp->if_unit = unit;
  604                 ifp->if_name = "rdp";
  605                 ifp->if_start = rdp_start;
  606                 ifp->if_ioctl = rdp_ioctl;
  607                 ifp->if_watchdog = rdp_watchdog;
  608                 ifp->if_init = rdp_init;
  609                 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  610                 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
  611 
  612                 /*
  613                  * Attach the interface
  614                  */
  615                 ether_ifattach(ifp, sc->arpcom.ac_enaddr);
  616         }
  617 
  618         /*
  619          * Print additional info when attached
  620          */
  621         if_printf(ifp, "RealTek RTL%s pocket ethernet, EEPROM %s, %s mode\n",
  622                "8002",          /* hook for 8012 */
  623                sc->eeprom == EEPROM_93C46? "93C46": "74S288",
  624                sc->slow? "slow": "fast");
  625         if_printf(ifp, "address %6D\n", sc->arpcom.ac_enaddr, ":");
  626 
  627         return 1;
  628 }
  629 
  630 /*
  631  * Reset interface.
  632  */
  633 static void
  634 rdp_reset(struct ifnet *ifp)
  635 {
  636         struct rdp_softc *sc = ifp->if_softc;
  637         int s;
  638 
  639         s = splimp();
  640 
  641         /*
  642          * Stop interface and re-initialize.
  643          */
  644         rdp_stop(sc);
  645         rdp_init(sc);
  646 
  647         (void) splx(s);
  648 }
  649 
  650 /*
  651  * Take interface offline.
  652  */
  653 static void
  654 rdp_stop(struct rdp_softc *sc)
  655 {
  656 
  657         sc->txbusy = sc->txbusy = 0;
  658 
  659         /* disable printer interface interrupts */
  660         sc->irqenbit = 0;
  661         outb(sc->baseaddr + lpt_control, Ctrl_SelData);
  662         outb(sc->baseaddr + lpt_data, 0xff);
  663 
  664         /* reset the RTL 8002 */
  665         WrNib(sc, CMR1 + HNib, MkHi(CMR1_RST));
  666         DELAY(100);
  667 }
  668 
  669 /*
  670  * Device timeout/watchdog routine. Entered if the device neglects to
  671  * generate an interrupt after a transmit has been started on it.
  672  */
  673 static void
  674 rdp_watchdog(struct ifnet *ifp)
  675 {
  676 
  677         log(LOG_ERR, "rdp%d: device timeout\n", ifp->if_unit);
  678         ifp->if_oerrors++;
  679 
  680         rdp_reset(ifp);
  681 }
  682 
  683 /*
  684  * Initialize device.
  685  */
  686 static void
  687 rdp_init(void *xsc)
  688 {
  689         struct rdp_softc *sc = xsc;
  690         struct ifnet *ifp = &sc->arpcom.ac_if;
  691         int i, s;
  692         u_char reg;
  693 
  694         /* address not known */
  695         if (TAILQ_EMPTY(&ifp->if_addrhead))
  696                 return;
  697 
  698         s = splimp();
  699 
  700         ifp->if_timer = 0;
  701 
  702         /* program ethernet ID into the chip */
  703         for (i = 0, reg = IDR0; i < 6; i++, reg++)
  704                 WrByte(sc, reg, sc->arpcom.ac_enaddr[i]);
  705 
  706         /* set accept mode */
  707         WrNib(sc, CMR2 + HNib,
  708               MkHi((ifp->if_flags & IFF_PROMISC)? CMR2_AM_ALL: CMR2_AM_PB));
  709 
  710         /* enable tx and rx */
  711         WrNib(sc, CMR1 + HNib, MkHi(CMR1_TE | CMR1_RE));
  712 
  713         /* allow interrupts to happen */
  714         WrNib(sc, CMR2, CMR2_IRQOUT | CMR2_IRQINV);
  715         WrNib(sc, IMR, ISR_TOK | ISR_TER | ISR_ROK | ISR_RER);
  716         WrNib(sc, IMR + HNib, MkHi(ISR_RBER));
  717 
  718         /* allow IRQs to pass the parallel interface */
  719         sc->irqenbit = Ctrl_IRQEN;
  720         outb(sc->baseaddr + lpt_control, sc->irqenbit + Ctrl_SelData);
  721 
  722         /* clear all flags */
  723         sc->txbusy = sc->txbuffered = 0;
  724 
  725         /*
  726          * Set 'running' flag, and clear output active flag.
  727          */
  728         ifp->if_flags |= IFF_RUNNING;
  729         ifp->if_flags &= ~IFF_OACTIVE;
  730 
  731         /*
  732          * ...and attempt to start output
  733          */
  734         rdp_start(ifp);
  735 
  736         (void) splx(s);
  737 }
  738 
  739 /*
  740  * Start output on interface.
  741  * We make two assumptions here:
  742  *  1) that the current priority is set to splimp _before_ this code
  743  *     is called *and* is returned to the appropriate priority after
  744  *     return
  745  *  2) that the IFF_OACTIVE flag is checked before this code is called
  746  *     (i.e. that the output part of the interface is idle)
  747  */
  748 static void
  749 rdp_start(struct ifnet *ifp)
  750 {
  751         struct rdp_softc *sc = ifp->if_softc;
  752         struct mbuf *m;
  753         int len;
  754 
  755 outloop:
  756 
  757         /*
  758          * See if there is room to put another packet in the buffer.
  759          */
  760         if (sc->txbuffered) {
  761                 /*
  762                  * No room. Indicate this to the outside world and exit.
  763                  */
  764                 ifp->if_flags |= IFF_OACTIVE;
  765                 return;
  766         }
  767         IF_DEQUEUE(&ifp->if_snd, m);
  768         if (m == 0) {
  769                 /*
  770                  * We are using the !OACTIVE flag to indicate to the outside
  771                  * world that we can accept an additional packet rather than
  772                  * that the transmitter is _actually_ active. Indeed, the
  773                  * transmitter may be active, but if we haven't filled all the
  774                  * buffers with data then we still want to accept more.
  775                  */
  776                 ifp->if_flags &= ~IFF_OACTIVE;
  777                 return;
  778         }
  779 
  780         /*
  781          * Copy the mbuf chain into the transmit buffer
  782          */
  783 
  784         len = rdp_write_mbufs(sc, m);
  785         if (len == 0)
  786                 goto outloop;
  787 
  788         /* ensure minimal valid ethernet length */
  789         len = max(len, (ETHER_MIN_LEN-ETHER_CRC_LEN));
  790 
  791         /*
  792          * Actually start the transceiver.  Set a timeout in case the
  793          * Tx interrupt never arrives.
  794          */
  795         if (!sc->txbusy) {
  796                 WrNib(sc, TBCR1, len >> 8);
  797                 WrByte(sc, TBCR0, len & 0xff);
  798                 WrNib(sc, CMR1, CMR1_TRA);
  799                 sc->txbusy = 1;
  800                 ifp->if_timer = 2;
  801         } else {
  802                 sc->txbuffered = 1;
  803                 sc->txsize = len;
  804         }
  805 
  806         /*
  807          * Tap off here if there is a bpf listener.
  808          */
  809         BPF_MTAP(ifp, m);
  810 
  811         m_freem(m);
  812 
  813         /*
  814          * Loop back to the top to possibly buffer more packets
  815          */
  816         goto outloop;
  817 }
  818 
  819 /*
  820  * Process an ioctl request.
  821  */
  822 static int
  823 rdp_ioctl(struct ifnet *ifp, IOCTL_CMD_T command, caddr_t data)
  824 {
  825         struct rdp_softc *sc = ifp->if_softc;
  826         int s, error = 0;
  827 
  828         s = splimp();
  829 
  830         switch (command) {
  831 
  832         case SIOCSIFFLAGS:
  833                 /*
  834                  * If the interface is marked up and stopped, then start it.
  835                  * If it is marked down and running, then stop it.
  836                  */
  837                 if (ifp->if_flags & IFF_UP) {
  838                         if ((ifp->if_flags & IFF_RUNNING) == 0)
  839                                 rdp_init(sc);
  840                 } else {
  841                         if (ifp->if_flags & IFF_RUNNING) {
  842                                 rdp_stop(sc);
  843                                 ifp->if_flags &= ~IFF_RUNNING;
  844                         }
  845                 }
  846 
  847                 /*
  848                  * Promiscuous flag may have changed, propagage this
  849                  * to the NIC.
  850                  */
  851                 if (ifp->if_flags & IFF_UP)
  852                         WrNib(sc, CMR2 + HNib,
  853                               MkHi((ifp->if_flags & IFF_PROMISC)?
  854                                    CMR2_AM_ALL: CMR2_AM_PB));
  855 
  856                 break;
  857 
  858         case SIOCADDMULTI:
  859         case SIOCDELMULTI:
  860                 /*
  861                  * Multicast list has changed; we don't support it.
  862                  */
  863                 error = ENOTTY;
  864                 break;
  865 
  866         default:
  867                 error = ether_ioctl(ifp, command, data);
  868                 break;
  869         }
  870         (void) splx(s);
  871         return (error);
  872 }
  873 
  874 /*
  875  * External interrupt service routine.
  876  */
  877 static void 
  878 rdpintr(int unit)
  879 {
  880         struct rdp_softc *sc = rdp_softc + unit;
  881         struct ifnet *ifp = (struct ifnet *)sc;
  882         u_char isr, tsr, rsr, colls;
  883 
  884         /* disable interrupts, so SD3 can be routed to the pin */
  885         sc->irqenbit = 0;
  886         outb(sc->baseaddr + lpt_control, Ctrl_SelData);
  887         WrNib(sc, CMR2, CMR2_IRQINV);
  888         /*
  889          * loop until there are no more new interrupts
  890          */
  891         for (;;) {
  892                 isr = RdNib(sc, ISR);
  893                 isr |= RdNib(sc, ISR + HNib) << 4;
  894                 RdEnd(sc, ISR + HNib);
  895 
  896                 if (isr == 0)
  897                         break;
  898 #if DEBUG & 4
  899                 printf("rdp%d: ISR = %#x\n", unit, isr);
  900 #endif
  901 
  902                 /*
  903                  * Clear the pending interrupt bits.
  904                  */
  905                 WrNib(sc, ISR, isr & 0x0f);
  906                 if (isr & 0xf0)
  907                         WrNib(sc, ISR + HNib, MkHi(isr));
  908 
  909                 /*
  910                  * Handle transmitter interrupts.
  911                  */
  912                 if (isr & (ISR_TOK | ISR_TER)) {
  913                         tsr = RdNib(sc, TSR);
  914                         RdEnd(sc, TSR);
  915 #if DEBUG & 4
  916                         if (isr & ISR_TER)
  917                                 printf("rdp%d: tsr %#x\n", unit, tsr);
  918 #endif
  919                         if (tsr & TSR_TABT)
  920                                 ifp->if_oerrors++;
  921                         else
  922                                 /*
  923                                  * Update total number of successfully
  924                                  * transmitted packets.
  925                                  */
  926                                 ifp->if_opackets++;
  927 
  928                         if (tsr & TSR_COL) {
  929                                 colls = RdNib(sc, COLR);
  930                                 RdEnd(sc, COLR);
  931                                 ifp->if_collisions += colls;
  932                         }
  933 
  934                         /*
  935                          * reset tx busy and output active flags
  936                          */
  937                         sc->txbusy = 0;
  938                         ifp->if_flags &= ~IFF_OACTIVE;
  939 
  940                         /*
  941                          * If we had already queued up another packet,
  942                          * start sending it now.
  943                          */
  944                         if (sc->txbuffered) {
  945                                 WrNib(sc, TBCR1, sc->txsize >> 8);
  946                                 WrByte(sc, TBCR0, sc->txsize & 0xff);
  947                                 WrNib(sc, CMR1, CMR1_TRA);
  948                                 sc->txbusy = 1;
  949                                 sc->txbuffered = 0;
  950                                 ifp->if_timer = 2;
  951                         } else {
  952                                 /*
  953                                  * clear watchdog timer
  954                                  */
  955                                 ifp->if_timer = 0;
  956                         }
  957                         
  958                 }
  959 
  960                 /*
  961                  * Handle receiver interrupts
  962                  */
  963                 if (isr & (ISR_ROK | ISR_RER | ISR_RBER)) {
  964                         rsr = RdNib(sc, RSR);
  965                         rsr |= RdNib(sc, RSR + HNib) << 4;
  966                         RdEnd(sc, RSR + HNib);
  967 #if DEBUG & 4
  968                         if (isr & (ISR_RER | ISR_RBER))
  969                                 printf("rdp%d: rsr %#x\n", unit, rsr);
  970 #endif
  971 
  972                         if (rsr & (RSR_PUN | RSR_POV)) {
  973                                 printf("rdp%d: rsr %#x, resetting\n",
  974                                        unit, rsr);
  975                                 rdp_reset(ifp);
  976                                 break;
  977                         }
  978 
  979                         if (rsr & RSR_BUFO)
  980                                 /*
  981                                  * CRC and FA errors are recorded in
  982                                  * rdp_rint() on a per-packet basis
  983                                  */
  984                                 ifp->if_ierrors++;
  985                         if (isr & (ISR_ROK | ISR_RER))
  986                                 rdp_rint(sc);
  987                 }
  988 
  989                 /*
  990                  * If it looks like the transmitter can take more data,
  991                  * attempt to start output on the interface. This is done
  992                  * after handling the receiver to give the receiver priority.
  993                  */
  994                 if ((ifp->if_flags & IFF_OACTIVE) == 0)
  995                         rdp_start(ifp);
  996 
  997         }
  998         /* re-enable interrupts */
  999         WrNib(sc, CMR2, CMR2_IRQOUT | CMR2_IRQINV);
 1000         sc->irqenbit = Ctrl_IRQEN;
 1001         outb(sc->baseaddr + lpt_control, Ctrl_SelData + sc->irqenbit);
 1002 }
 1003 
 1004 /*
 1005  * Ethernet interface receiver interrupt.
 1006  */
 1007 static void
 1008 rdp_rint(struct rdp_softc *sc)
 1009 {
 1010         struct ifnet *ifp = &sc->arpcom.ac_if;
 1011         struct rdphdr rh;
 1012         u_short len;
 1013         size_t i;
 1014         u_char *packet_ptr, b, status;
 1015         int excessive_bad_pkts = 0;
 1016 
 1017         /*
 1018          * Fetch the packets from the NIC's buffer.
 1019          */
 1020         for (;;) {
 1021                 b = RdNib(sc, CMR1);
 1022                 RdEnd(sc, CMR1);
 1023 
 1024                 if (b & CMR1_BUFE)
 1025                         /* no more packets */
 1026                         break;
 1027 
 1028                 /* first, obtain the buffer header */
 1029                 
 1030                 outb(sc->baseaddr + lpt_data, MAR + EOC); /* prepare addr */
 1031                 outb(sc->baseaddr + lpt_control, Ctrl_LNibRead);
 1032                 outb(sc->baseaddr + lpt_data, MAR + RdAddr + HNib);
 1033 
 1034                 packet_ptr = (u_char *)&rh;
 1035                 if (sc->slow)
 1036                         for (i = 0; i < sizeof rh; i++, packet_ptr++)
 1037                                 *packet_ptr = RdByteA2(sc);
 1038                 else
 1039                         for (i = 0; i < sizeof rh; i++, packet_ptr++)
 1040                                 *packet_ptr = RdByteA1(sc);
 1041 
 1042                 RdEnd(sc, MAR + HNib);
 1043                 outb(sc->baseaddr + lpt_control, Ctrl_SelData);
 1044 
 1045                 len = rh.pktlen - ETHER_CRC_LEN;
 1046                 status = rh.status;
 1047 
 1048                 if ((status & (RSR_ROK | RSR_CRC | RSR_FA)) != RSR_ROK ||
 1049                     len > (ETHER_MAX_LEN - ETHER_CRC_LEN) ||
 1050                     len < (ETHER_MIN_LEN - ETHER_CRC_LEN) ||
 1051                     len > MCLBYTES) {
 1052 #if DEBUG
 1053                         if_printf(ifp, "bad packet in buffer, "
 1054                                "len %d, status %#x\n",
 1055                                (int)len, (int)status);
 1056 #endif
 1057                         ifp->if_ierrors++;
 1058                         /* rx jump packet */
 1059                         WrNib(sc, CMR1, CMR1_RDPAC);
 1060                         if (++excessive_bad_pkts > 5) {
 1061                                 /*
 1062                                  * the chip seems to be stuck, we are
 1063                                  * probably seeing the same bad packet
 1064                                  * over and over again
 1065                                  */
 1066 #if DEBUG
 1067                                 if_printf(ifp, "resetting due to an "
 1068                                        "excessive number of bad packets\n");
 1069 #endif
 1070                                 rdp_reset(ifp);
 1071                                 return;
 1072                         }
 1073                         continue;
 1074                 }
 1075 
 1076                 /*
 1077                  * Go get packet.
 1078                  */
 1079                 excessive_bad_pkts = 0;
 1080                 rdp_get_packet(sc, len);
 1081                 ifp->if_ipackets++;
 1082         }
 1083 }
 1084 
 1085 /*
 1086  * Retreive packet from NIC memory and send to the next level up via
 1087  * ether_input().
 1088  */
 1089 static void
 1090 rdp_get_packet(struct rdp_softc *sc, unsigned len)
 1091 {
 1092         struct ifnet *ifp = &sc->arpcom.ac_if;
 1093         struct mbuf *m;
 1094         u_char *packet_ptr;
 1095         size_t s;
 1096 
 1097         /* Allocate a header mbuf */
 1098         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1099         if (m == NULL)
 1100                 return;
 1101         m->m_pkthdr.rcvif = ifp;
 1102         m->m_pkthdr.len = m->m_len = len;
 1103 
 1104         /*
 1105          * We always put the received packet in a single buffer -
 1106          * either with just an mbuf header or in a cluster attached
 1107          * to the header. The +2 is to compensate for the alignment
 1108          * fixup below.
 1109          */
 1110         if ((len + ETHER_ALIGN) > MHLEN) {
 1111                 /* Attach an mbuf cluster */
 1112                 MCLGET(m, M_DONTWAIT);
 1113 
 1114                 /* Insist on getting a cluster */
 1115                 if ((m->m_flags & M_EXT) == 0) {
 1116                         m_freem(m);
 1117                         return;
 1118                 }
 1119         }
 1120 
 1121         /*
 1122          * The +2 is to longword align the start of the real packet.
 1123          * This is important for NFS.
 1124          */
 1125         m->m_data += ETHER_ALIGN;
 1126 
 1127         /*
 1128          * Get packet, including link layer address, from interface.
 1129          */
 1130         outb(sc->baseaddr + lpt_control, Ctrl_LNibRead);
 1131         outb(sc->baseaddr + lpt_data, RdAddr + MAR);
 1132 
 1133         packet_ptr = mtod(m, u_char *);
 1134         if (sc->slow)
 1135                 for (s = 0; s < len; s++, packet_ptr++)
 1136                         *packet_ptr = RdByteA2(sc);
 1137         else
 1138                 for (s = 0; s < len; s++, packet_ptr++)
 1139                         *packet_ptr = RdByteA1(sc);
 1140 
 1141         RdEnd(sc, MAR + HNib);
 1142         outb(sc->baseaddr + lpt_control, Ctrl_SelData);
 1143         WrNib(sc, CMR1, CMR1_RDPAC);
 1144 
 1145         (*ifp->if_input)(ifp, m);
 1146 }
 1147 
 1148 /*
 1149  * Write an mbuf chain to the NIC's tx buffer.
 1150  */
 1151 static u_short
 1152 rdp_write_mbufs(struct rdp_softc *sc, struct mbuf *m)
 1153 {
 1154         u_short total_len;
 1155         struct mbuf *mp;
 1156         u_char *dp, b;
 1157         int i;
 1158 
 1159         /* First, count up the total number of bytes to copy */
 1160         for (total_len = 0, mp = m; mp; mp = mp->m_next)
 1161                 total_len += mp->m_len;
 1162 
 1163         if (total_len == 0)
 1164                 return 0;
 1165 
 1166         outb(sc->baseaddr + lpt_data, MAR | EOC);
 1167 
 1168         /*
 1169          * Transfer the mbuf chain to the NIC memory.
 1170          */
 1171         if (sc->slow) {
 1172                 /* writing the first byte is complicated */
 1173                 outb(sc->baseaddr + lpt_control,
 1174                      Ctrl_LNibRead | sc->irqenbit);
 1175                 outb(sc->baseaddr + lpt_data, MAR | WrAddr);
 1176                 b = *(u_char *)m->m_data;
 1177                 outb(sc->baseaddr + lpt_data, (b & 0x0f) | 0x40);
 1178                 outb(sc->baseaddr + lpt_data, b & 0x0f);
 1179                 outb(sc->baseaddr + lpt_data, b >> 4);
 1180                 outb(sc->baseaddr + lpt_control,
 1181                      Ctrl_HNibRead | sc->irqenbit);
 1182                 /* advance the mbuf pointer */
 1183                 mp = m;
 1184                 m->m_len--;
 1185                 m->m_data++;
 1186                 /* write the remaining bytes */
 1187                 while (m) {
 1188                         for (i = 0, dp = (u_char *)m->m_data;
 1189                              i < m->m_len;
 1190                              i++, dp++)
 1191                                 WrByteALToDRAMA(sc, *dp);
 1192                         m = m->m_next;
 1193                 }
 1194                 /*
 1195                  * restore old mbuf in case we have to hand it off to
 1196                  * BPF again
 1197                  */
 1198                 m = mp;
 1199                 m->m_len++;
 1200                 m->m_data--;
 1201 
 1202                 /* the RTL 8002 requires an even byte-count remote DMA */
 1203                 if (total_len & 1)
 1204                         WrByteALToDRAMA(sc, 0);
 1205         } else {
 1206                 outb(sc->baseaddr + lpt_data, MAR | WrAddr);
 1207                 while (m) {
 1208                         for (i = 0, dp = (u_char *)m->m_data;
 1209                              i < m->m_len;
 1210                              i++, dp++)
 1211                                 WrByteALToDRAM(sc, *dp);
 1212                         m = m->m_next;
 1213                 }
 1214 
 1215                 /* the RTL 8002 requires an even byte-count remote DMA */
 1216                 if (total_len & 1)
 1217                         WrByteALToDRAM(sc, 0);
 1218         }
 1219 
 1220         outb(sc->baseaddr + lpt_data, 0xff);
 1221         outb(sc->baseaddr + lpt_control,
 1222              Ctrl_HNibRead | Ctrl_SelData | sc->irqenbit);
 1223 
 1224         return total_len;
 1225 }
 1226 
 1227 /*
 1228  * Read the designated ethernet hardware address out of a 93C46
 1229  * (serial) EEPROM.
 1230  * Note that the 93C46 uses 16-bit words in big-endian notation.
 1231  */
 1232 static int
 1233 rdp_gethwaddr_93c46(struct rdp_softc *sc, u_char *etheraddr)
 1234 {
 1235         int i, magic;
 1236         size_t j = 0;
 1237         u_short w;
 1238 
 1239         WrNib(sc, CMR2, CMR2_PAGE | CMR2_IRQINV); /* select page 1 */
 1240 
 1241         /*
 1242          * The original RealTek packet driver had the ethernet address
 1243          * starting at EEPROM address 0.  Other vendors seem to have
 1244          * gone `creative' here -- while they didn't do anything else
 1245          * than changing a few strings in the entire driver, compared
 1246          * to the RealTek version, they also moved out the ethernet
 1247          * address to a different location in the EEPROM, so the
 1248          * original RealTek driver won't work correctly with them, and
 1249          * vice versa.  Sounds pretty cool, eh?  $@%&!
 1250          *
 1251          * Anyway, we walk through the EEPROM, until we find some
 1252          * allowable value based upon our table of IEEE OUI assignments.
 1253          */
 1254         for (i = magic = 0; magic < 3 && i < 32; i++) {
 1255                 /* read cmd (+ 6 bit address) */
 1256                 rdp_93c46_cmd(sc, 0x180 + i, 10);
 1257                 w = rdp_93c46_read(sc);
 1258                 switch (magic) {
 1259                 case 0:
 1260                         for (j = 0;
 1261                              j < sizeof allowed_ouis / sizeof(u_short);
 1262                              j++)
 1263                                 if (w == allowed_ouis[j]) {
 1264                                         etheraddr[0] = (w >> 8) & 0xff;
 1265                                         etheraddr[1] = w & 0xff;
 1266                                         magic++;
 1267                                         break;
 1268                                 }
 1269                         break;
 1270 
 1271                 case 1:
 1272                         /*
 1273                          * If the first two bytes have been 00:00, we
 1274                          * discard the match iff the next two bytes
 1275                          * are also 00:00, so we won't get fooled by
 1276                          * an EEPROM that has been filled with zeros.
 1277                          * This in theory would disallow 64 K of legal
 1278                          * addresses assigned to Xerox, but it's
 1279                          * almost certain that those addresses haven't
 1280                          * been used for RTL80[01]2 chips anyway.
 1281                          */
 1282                         if ((etheraddr[0] | etheraddr[1]) == 0 && w == 0) {
 1283                                 magic--;
 1284                                 break;
 1285                         }
 1286 
 1287                         etheraddr[2] = (w >> 8) & 0xff;
 1288                         etheraddr[3] = w & 0xff;
 1289                         magic++;
 1290                         break;
 1291 
 1292                 case 2:
 1293                         etheraddr[4] = (w >> 8) & 0xff;
 1294                         etheraddr[5] = w & 0xff;
 1295                         magic++;
 1296                         break;
 1297                 }
 1298         }
 1299 
 1300         WrNib(sc, CMR2, CMR2_IRQINV);   /* back to page 0 */
 1301 
 1302         return magic == 3;
 1303 }
 1304 
 1305 /*
 1306  * Read the designated ethernet hardware address out of a 74S288
 1307  * EEPROM.
 1308  *
 1309  * This is untested, since i haven't seen any adapter actually using
 1310  * a 74S288.  In the RTL 8012, only the serial EEPROM (94C46) is
 1311  * supported anymore.
 1312  */
 1313 static void
 1314 rdp_gethwaddr_74s288(struct rdp_softc *sc, u_char *etheraddr)
 1315 {
 1316         int i;
 1317         u_char b;
 1318 
 1319         WrNib(sc, CMR2, CMR2_PAGE | CMR2_IRQINV); /* select page 1 */
 1320 
 1321         for (i = 0; i < 6; i++) {
 1322                 WrNib(sc, PCMR, i & 0x0f); /* lower 4 bit of addr */
 1323                 WrNib(sc, PCMR + HNib, HNib + 4); /* upper 2 bit addr + /CS */
 1324                 WrNib(sc, PCMR + HNib, HNib); /* latch data now */
 1325                 b = RdNib(sc, PDR) & 0x0f;
 1326                 b |= (RdNib(sc, PDR + HNib) & 0x0f) << 4;
 1327                 etheraddr[i] = b;
 1328         }
 1329 
 1330         RdEnd(sc, PDR + HNib);
 1331         WrNib(sc, CMR2, CMR2_IRQINV);   /* reselect page 0 */
 1332 }
 1333 
 1334 /*
 1335  * Send nbits of data (starting with MSB) out to the 93c46 as a
 1336  * command.  Assumes register page 1 has already been selected.
 1337  */
 1338 static void
 1339 rdp_93c46_cmd(struct rdp_softc *sc, u_short data, unsigned nbits)
 1340 {
 1341         u_short mask = 1 << (nbits - 1);
 1342         unsigned i;
 1343         u_char b;
 1344 
 1345 #if DEBUG & 2
 1346         printf("rdp_93c46_cmd(): ");
 1347 #endif
 1348         for (i = 0; i < nbits; i++, mask >>= 1) {
 1349                 b = HNib + PCMR_SK + PCMR_CS;
 1350                 if (data & mask)
 1351                         b += PCMR_DO;
 1352 #if DEBUG & 2
 1353                 printf("%d", b & 1);
 1354 #endif
 1355                 WrNib(sc, PCMR + HNib, b);
 1356                 DELAY(1);
 1357                 WrNib(sc, PCMR + HNib, b & ~PCMR_SK);
 1358                 DELAY(1);
 1359         }
 1360 #if DEBUG & 2
 1361         printf("\n");
 1362 #endif
 1363 }
 1364 
 1365 /*
 1366  * Read one word of data from the 93c46.  Actually, we have to read
 1367  * 17 bits, and discard the very first bit.  Assumes register page 1
 1368  * to be selected as well.
 1369  */
 1370 static u_short
 1371 rdp_93c46_read(struct rdp_softc *sc)
 1372 {
 1373         u_short data = 0;
 1374         u_char b;
 1375         int i;
 1376 
 1377 #if DEBUG & 2
 1378         printf("rdp_93c46_read(): ");
 1379 #endif
 1380         for (i = 0; i < 17; i++) {
 1381                 WrNib(sc, PCMR + HNib, PCMR_SK + PCMR_CS + HNib);
 1382                 DELAY(1);
 1383                 WrNib(sc, PCMR + HNib, PCMR_CS + HNib);
 1384                 DELAY(1);
 1385                 b = RdNib(sc, PDR);
 1386                 data <<= 1;
 1387                 if (b & 1)
 1388                         data |= 1;
 1389 #if DEBUG & 2
 1390                 printf("%d", b & 1);
 1391 #endif
 1392                 RdEnd(sc, PDR);
 1393                 DELAY(1);
 1394         }
 1395 
 1396 #if DEBUG & 2
 1397         printf("\n");
 1398 #endif
 1399         /* end of cycle */
 1400         WrNib(sc, PCMR + HNib, PCMR_SK + HNib);
 1401         DELAY(1);
 1402 
 1403         return data;
 1404 }

Cache object: b21b35a3fb46c92157027ea98af06eff


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