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

Cache object: c5f0a7663687550f497c9765a85639f7


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