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

Cache object: 5e474e7cb739a8ce26cd03d64f1dd2db


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