The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/if_rdp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright 1998, Joerg Wunsch
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD: releng/5.1/sys/i386/isa/if_rdp.c 111926 2003-03-05 19:24:24Z peter $
   28  */
   29 
   30 /*
   31  * Device driver for RealTek RTL 8002 (`REDP') based pocket-ethernet
   32  * adapters, hooked up to a printer port.  `rdp' is a shorthand for
   33  * REDP since some tools like netstat work best if the interface name
   34  * has no more than three letters.
   35  *
   36  * Driver configuration flags so far:
   37  *   flags 0x1 -- assume 74S288 EEPROM (default 94C46)
   38  *   flags 0x2 -- use `slow' mode (mode 3 of the packet driver, default 0)
   39  *
   40  * Maybe this driver will some day also work with the successor, RTL
   41  * 8012 (`AREDP'), which is unfortunately not fully register-
   42  * compatible with the 8002.  The 8012 offers support for faster
   43  * transfer modi like bidirectional SPP and EPP, 64 K x 4 buffer
   44  * memory as opposed to 16 K x 4 for the 8002, a multicast filter, and
   45  * a builtin multiplexer that allows chaining a printer behind the
   46  * ethernet adapter.
   47  *
   48  * About the only documentation i've been able to find about the RTL
   49  * 8002 was the packet driver source code at ftp.realtek.com.tw, so
   50  * this driver is somewhat based on the way the packet driver handles
   51  * the chip.  The exact author of the packet driver is unknown, the
   52  * only name that i could find in the source was someone called Chiu,
   53  * supposedly an employee of RealTek.  So credits to them for that
   54  * piece of code which has proven valuable to me.
   55  *
   56  * Later on, Leo kuo <leo@realtek.com.tw> has been very helpful to me
   57  * by sending me a readable (PDF) file documenting the RTL 8012, which
   58  * helped me to also understand the 8002, as well as by providing me
   59  * with the source code of the 8012 packet driver that i haven't been
   60  * able to find on the FTP site.  A big Thanks! goes here to RealTek
   61  * for this kind of service.
   62  */
   63 
   64 #include "rdp.h"
   65 
   66 #include <sys/param.h>
   67 #include <sys/systm.h>
   68 #include <sys/kernel.h>
   69 #include <sys/sockio.h>
   70 #include <sys/mbuf.h>
   71 #include <sys/socket.h>
   72 #include <sys/syslog.h>
   73 #include <sys/bus.h>
   74 
   75 #include <net/ethernet.h>
   76 #include <net/if.h>
   77 #include <net/if_arp.h>
   78 #include <net/if_dl.h>
   79 #include <net/if_mib.h>
   80 
   81 #ifdef INET
   82 #include <netinet/in.h>
   83 #include <netinet/if_ether.h>
   84 #endif
   85 
   86 #include <net/bpf.h>
   87 
   88 #include <machine/md_var.h>
   89 
   90 #include <i386/isa/isa_device.h>
   91 #include <i386/isa/icu.h>
   92 #include <i386/isa/if_rdpreg.h>
   93 #include <i386/isa/intr_machdep.h>
   94 
   95 #ifndef COMPAT_OLDISA
   96 #error "The rdp device requires the old isa compatibility shims"
   97 #endif
   98 
   99 #define IOCTL_CMD_T u_long
  100 
  101 /*
  102  * Debug levels (ORed together):
  103  *  != 0 - general (bad packets etc.)
  104  *  2 - debug EEPROM IO
  105  *  4 - debug interrupt status
  106  */
  107 #undef DEBUG
  108 #define DEBUG 0
  109 
  110 /*
  111  * rdp_softc: per interface info and status
  112  */
  113 struct rdp_softc {
  114         struct arpcom arpcom;   /*
  115                                  * Ethernet common, always goes first so
  116                                  * a rdp_softc * can be cast into an
  117                                  * arpcom * or into an ifnet *.
  118                                  */
  119 
  120         /*
  121          * local stuff, somewhat sorted by memory alignment class
  122          */
  123         u_short baseaddr;       /* IO port address */
  124         u_short txsize;         /* tx size for next (buffered) packet,
  125                                  * there's only one additional packet
  126                                  * we can buffer, thus a single variable
  127                                  * ought to be enough */
  128         int txbusy;             /* tx is transmitting */
  129         int txbuffered;         /* # of packets in tx buffer */
  130         int slow;               /* use lpt_control to send data */
  131         u_char irqenbit;        /* mirror of current Ctrl_IRQEN */
  132         /*
  133          * type of parameter EEPROM; device flags 0x1 selects 74S288
  134          */
  135         enum {
  136                 EEPROM_93C46, EEPROM_74S288 /* or 82S123 */
  137         } eeprom;
  138 };
  139 
  140 static struct rdp_softc rdp_softc[NRDP];
  141 
  142 /*
  143  * Since there's no fixed location in the EEPROM about where to find
  144  * the ethernet hardware address, we drop a table of valid OUIs here,
  145  * and search through the EEPROM until we find a possible valid
  146  * Ethernet address.  Only the first 16 bits of all possible OUIs are
  147  * recorded in the table (as obtained from
  148  * http://standards.ieee.org/regauth/oui/oui.txt).
  149  */
  150 
  151 static u_short allowed_ouis[] = {
  152         0x0000, 0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007,
  153         0x0008, 0x0010, 0x001C, 0x0020, 0x0040, 0x0050, 0x0060,
  154         0x0070, 0x0080, 0x0090, 0x009D, 0x00A0, 0x00AA, 0x00BB,
  155         0x00C0, 0x00CF, 0x00DD, 0x00E0, 0x00E6, 0x0207, 0x021C,
  156         0x0260, 0x0270, 0x029D, 0x02AA, 0x02BB, 0x02C0, 0x02CF,
  157         0x02E6, 0x040A, 0x04E0, 0x0800, 0x08BB, 0x1000, 0x1100,
  158         0x8000, 0xAA00
  159 };
  160 
  161 /*
  162  * ISA bus support.
  163  */
  164 static int rdp_probe(struct isa_device *);
  165 static int rdp_attach(struct isa_device *);
  166 
  167 /*
  168  * Required entry points.
  169  */
  170 static void rdp_init(void *);
  171 static int rdp_ioctl(struct ifnet *, IOCTL_CMD_T, caddr_t);
  172 static void rdp_start(struct ifnet *);
  173 static void rdp_reset(struct ifnet *);
  174 static void rdp_watchdog(struct ifnet *);
  175 static void rdpintr(int);
  176 
  177 /*
  178  * REDP private functions.
  179  */
  180 
  181 static void rdp_stop(struct rdp_softc *);
  182 static void rdp_rint(struct rdp_softc *);
  183 static void rdp_get_packet(struct rdp_softc *, unsigned);
  184 static u_short rdp_write_mbufs(struct rdp_softc *, struct mbuf *);
  185 static int rdp_gethwaddr_93c46(struct rdp_softc *, u_char *);
  186 static void rdp_gethwaddr_74s288(struct rdp_softc *, u_char *);
  187 static void rdp_93c46_cmd(struct rdp_softc *, u_short, unsigned);
  188 static u_short rdp_93c46_read(struct rdp_softc *);
  189 
  190 struct isa_driver rdpdriver = {
  191         INTR_TYPE_NET,
  192         rdp_probe,
  193         rdp_attach,
  194         "rdp",
  195         1                       /* we wanna get a chance before lptN */
  196 };
  197 COMPAT_ISA_DRIVER(rdp, rdpdriver);
  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_start = rdp_start;
  601                 ifp->if_ioctl = rdp_ioctl;
  602                 ifp->if_watchdog = rdp_watchdog;
  603                 ifp->if_init = rdp_init;
  604                 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  605                 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
  606 
  607                 /*
  608                  * Attach the interface
  609                  */
  610                 ether_ifattach(ifp, sc->arpcom.ac_enaddr);
  611         }
  612 
  613         /*
  614          * Print additional info when attached
  615          */
  616         if_printf(ifp, "RealTek RTL%s pocket ethernet, EEPROM %s, %s mode\n",
  617                "8002",          /* hook for 8012 */
  618                sc->eeprom == EEPROM_93C46? "93C46": "74S288",
  619                sc->slow? "slow": "fast");
  620         if_printf(ifp, "address %6D\n", sc->arpcom.ac_enaddr, ":");
  621 
  622         return 1;
  623 }
  624 
  625 /*
  626  * Reset interface.
  627  */
  628 static void
  629 rdp_reset(struct ifnet *ifp)
  630 {
  631         struct rdp_softc *sc = ifp->if_softc;
  632         int s;
  633 
  634         s = splimp();
  635 
  636         /*
  637          * Stop interface and re-initialize.
  638          */
  639         rdp_stop(sc);
  640         rdp_init(sc);
  641 
  642         (void) splx(s);
  643 }
  644 
  645 /*
  646  * Take interface offline.
  647  */
  648 static void
  649 rdp_stop(struct rdp_softc *sc)
  650 {
  651 
  652         sc->txbusy = sc->txbusy = 0;
  653 
  654         /* disable printer interface interrupts */
  655         sc->irqenbit = 0;
  656         outb(sc->baseaddr + lpt_control, Ctrl_SelData);
  657         outb(sc->baseaddr + lpt_data, 0xff);
  658 
  659         /* reset the RTL 8002 */
  660         WrNib(sc, CMR1 + HNib, MkHi(CMR1_RST));
  661         DELAY(100);
  662 }
  663 
  664 /*
  665  * Device timeout/watchdog routine. Entered if the device neglects to
  666  * generate an interrupt after a transmit has been started on it.
  667  */
  668 static void
  669 rdp_watchdog(struct ifnet *ifp)
  670 {
  671 
  672         log(LOG_ERR, "rdp%d: device timeout\n", ifp->if_unit);
  673         ifp->if_oerrors++;
  674 
  675         rdp_reset(ifp);
  676 }
  677 
  678 /*
  679  * Initialize device.
  680  */
  681 static void
  682 rdp_init(void *xsc)
  683 {
  684         struct rdp_softc *sc = xsc;
  685         struct ifnet *ifp = &sc->arpcom.ac_if;
  686         int i, s;
  687         u_char reg;
  688 
  689         /* address not known */
  690         if (TAILQ_EMPTY(&ifp->if_addrhead))
  691                 return;
  692 
  693         s = splimp();
  694 
  695         ifp->if_timer = 0;
  696 
  697         /* program ethernet ID into the chip */
  698         for (i = 0, reg = IDR0; i < 6; i++, reg++)
  699                 WrByte(sc, reg, sc->arpcom.ac_enaddr[i]);
  700 
  701         /* set accept mode */
  702         WrNib(sc, CMR2 + HNib,
  703               MkHi((ifp->if_flags & IFF_PROMISC)? CMR2_AM_ALL: CMR2_AM_PB));
  704 
  705         /* enable tx and rx */
  706         WrNib(sc, CMR1 + HNib, MkHi(CMR1_TE | CMR1_RE));
  707 
  708         /* allow interrupts to happen */
  709         WrNib(sc, CMR2, CMR2_IRQOUT | CMR2_IRQINV);
  710         WrNib(sc, IMR, ISR_TOK | ISR_TER | ISR_ROK | ISR_RER);
  711         WrNib(sc, IMR + HNib, MkHi(ISR_RBER));
  712 
  713         /* allow IRQs to pass the parallel interface */
  714         sc->irqenbit = Ctrl_IRQEN;
  715         outb(sc->baseaddr + lpt_control, sc->irqenbit + Ctrl_SelData);
  716 
  717         /* clear all flags */
  718         sc->txbusy = sc->txbuffered = 0;
  719 
  720         /*
  721          * Set 'running' flag, and clear output active flag.
  722          */
  723         ifp->if_flags |= IFF_RUNNING;
  724         ifp->if_flags &= ~IFF_OACTIVE;
  725 
  726         /*
  727          * ...and attempt to start output
  728          */
  729         rdp_start(ifp);
  730 
  731         (void) splx(s);
  732 }
  733 
  734 /*
  735  * Start output on interface.
  736  * We make two assumptions here:
  737  *  1) that the current priority is set to splimp _before_ this code
  738  *     is called *and* is returned to the appropriate priority after
  739  *     return
  740  *  2) that the IFF_OACTIVE flag is checked before this code is called
  741  *     (i.e. that the output part of the interface is idle)
  742  */
  743 static void
  744 rdp_start(struct ifnet *ifp)
  745 {
  746         struct rdp_softc *sc = ifp->if_softc;
  747         struct mbuf *m;
  748         int len;
  749 
  750 outloop:
  751 
  752         /*
  753          * See if there is room to put another packet in the buffer.
  754          */
  755         if (sc->txbuffered) {
  756                 /*
  757                  * No room. Indicate this to the outside world and exit.
  758                  */
  759                 ifp->if_flags |= IFF_OACTIVE;
  760                 return;
  761         }
  762         IF_DEQUEUE(&ifp->if_snd, m);
  763         if (m == 0) {
  764                 /*
  765                  * We are using the !OACTIVE flag to indicate to the outside
  766                  * world that we can accept an additional packet rather than
  767                  * that the transmitter is _actually_ active. Indeed, the
  768                  * transmitter may be active, but if we haven't filled all the
  769                  * buffers with data then we still want to accept more.
  770                  */
  771                 ifp->if_flags &= ~IFF_OACTIVE;
  772                 return;
  773         }
  774 
  775         /*
  776          * Copy the mbuf chain into the transmit buffer
  777          */
  778 
  779         len = rdp_write_mbufs(sc, m);
  780         if (len == 0)
  781                 goto outloop;
  782 
  783         /* ensure minimal valid ethernet length */
  784         len = max(len, (ETHER_MIN_LEN-ETHER_CRC_LEN));
  785 
  786         /*
  787          * Actually start the transceiver.  Set a timeout in case the
  788          * Tx interrupt never arrives.
  789          */
  790         if (!sc->txbusy) {
  791                 WrNib(sc, TBCR1, len >> 8);
  792                 WrByte(sc, TBCR0, len & 0xff);
  793                 WrNib(sc, CMR1, CMR1_TRA);
  794                 sc->txbusy = 1;
  795                 ifp->if_timer = 2;
  796         } else {
  797                 sc->txbuffered = 1;
  798                 sc->txsize = len;
  799         }
  800 
  801         /*
  802          * Tap off here if there is a bpf listener.
  803          */
  804         BPF_MTAP(ifp, m);
  805 
  806         m_freem(m);
  807 
  808         /*
  809          * Loop back to the top to possibly buffer more packets
  810          */
  811         goto outloop;
  812 }
  813 
  814 /*
  815  * Process an ioctl request.
  816  */
  817 static int
  818 rdp_ioctl(struct ifnet *ifp, IOCTL_CMD_T command, caddr_t data)
  819 {
  820         struct rdp_softc *sc = ifp->if_softc;
  821         int s, error = 0;
  822 
  823         s = splimp();
  824 
  825         switch (command) {
  826 
  827         case SIOCSIFFLAGS:
  828                 /*
  829                  * If the interface is marked up and stopped, then start it.
  830                  * If it is marked down and running, then stop it.
  831                  */
  832                 if (ifp->if_flags & IFF_UP) {
  833                         if ((ifp->if_flags & IFF_RUNNING) == 0)
  834                                 rdp_init(sc);
  835                 } else {
  836                         if (ifp->if_flags & IFF_RUNNING) {
  837                                 rdp_stop(sc);
  838                                 ifp->if_flags &= ~IFF_RUNNING;
  839                         }
  840                 }
  841 
  842                 /*
  843                  * Promiscuous flag may have changed, propagage this
  844                  * to the NIC.
  845                  */
  846                 if (ifp->if_flags & IFF_UP)
  847                         WrNib(sc, CMR2 + HNib,
  848                               MkHi((ifp->if_flags & IFF_PROMISC)?
  849                                    CMR2_AM_ALL: CMR2_AM_PB));
  850 
  851                 break;
  852 
  853         case SIOCADDMULTI:
  854         case SIOCDELMULTI:
  855                 /*
  856                  * Multicast list has changed; we don't support it.
  857                  */
  858                 error = ENOTTY;
  859                 break;
  860 
  861         default:
  862                 error = ether_ioctl(ifp, command, data);
  863                 break;
  864         }
  865         (void) splx(s);
  866         return (error);
  867 }
  868 
  869 /*
  870  * External interrupt service routine.
  871  */
  872 static void 
  873 rdpintr(int unit)
  874 {
  875         struct rdp_softc *sc = rdp_softc + unit;
  876         struct ifnet *ifp = (struct ifnet *)sc;
  877         u_char isr, tsr, rsr, colls;
  878 
  879         /* disable interrupts, so SD3 can be routed to the pin */
  880         sc->irqenbit = 0;
  881         outb(sc->baseaddr + lpt_control, Ctrl_SelData);
  882         WrNib(sc, CMR2, CMR2_IRQINV);
  883         /*
  884          * loop until there are no more new interrupts
  885          */
  886         for (;;) {
  887                 isr = RdNib(sc, ISR);
  888                 isr |= RdNib(sc, ISR + HNib) << 4;
  889                 RdEnd(sc, ISR + HNib);
  890 
  891                 if (isr == 0)
  892                         break;
  893 #if DEBUG & 4
  894                 printf("rdp%d: ISR = %#x\n", unit, isr);
  895 #endif
  896 
  897                 /*
  898                  * Clear the pending interrupt bits.
  899                  */
  900                 WrNib(sc, ISR, isr & 0x0f);
  901                 if (isr & 0xf0)
  902                         WrNib(sc, ISR + HNib, MkHi(isr));
  903 
  904                 /*
  905                  * Handle transmitter interrupts.
  906                  */
  907                 if (isr & (ISR_TOK | ISR_TER)) {
  908                         tsr = RdNib(sc, TSR);
  909                         RdEnd(sc, TSR);
  910 #if DEBUG & 4
  911                         if (isr & ISR_TER)
  912                                 printf("rdp%d: tsr %#x\n", unit, tsr);
  913 #endif
  914                         if (tsr & TSR_TABT)
  915                                 ifp->if_oerrors++;
  916                         else
  917                                 /*
  918                                  * Update total number of successfully
  919                                  * transmitted packets.
  920                                  */
  921                                 ifp->if_opackets++;
  922 
  923                         if (tsr & TSR_COL) {
  924                                 colls = RdNib(sc, COLR);
  925                                 RdEnd(sc, COLR);
  926                                 ifp->if_collisions += colls;
  927                         }
  928 
  929                         /*
  930                          * reset tx busy and output active flags
  931                          */
  932                         sc->txbusy = 0;
  933                         ifp->if_flags &= ~IFF_OACTIVE;
  934 
  935                         /*
  936                          * If we had already queued up another packet,
  937                          * start sending it now.
  938                          */
  939                         if (sc->txbuffered) {
  940                                 WrNib(sc, TBCR1, sc->txsize >> 8);
  941                                 WrByte(sc, TBCR0, sc->txsize & 0xff);
  942                                 WrNib(sc, CMR1, CMR1_TRA);
  943                                 sc->txbusy = 1;
  944                                 sc->txbuffered = 0;
  945                                 ifp->if_timer = 2;
  946                         } else {
  947                                 /*
  948                                  * clear watchdog timer
  949                                  */
  950                                 ifp->if_timer = 0;
  951                         }
  952                         
  953                 }
  954 
  955                 /*
  956                  * Handle receiver interrupts
  957                  */
  958                 if (isr & (ISR_ROK | ISR_RER | ISR_RBER)) {
  959                         rsr = RdNib(sc, RSR);
  960                         rsr |= RdNib(sc, RSR + HNib) << 4;
  961                         RdEnd(sc, RSR + HNib);
  962 #if DEBUG & 4
  963                         if (isr & (ISR_RER | ISR_RBER))
  964                                 printf("rdp%d: rsr %#x\n", unit, rsr);
  965 #endif
  966 
  967                         if (rsr & (RSR_PUN | RSR_POV)) {
  968                                 printf("rdp%d: rsr %#x, resetting\n",
  969                                        unit, rsr);
  970                                 rdp_reset(ifp);
  971                                 break;
  972                         }
  973 
  974                         if (rsr & RSR_BUFO)
  975                                 /*
  976                                  * CRC and FA errors are recorded in
  977                                  * rdp_rint() on a per-packet basis
  978                                  */
  979                                 ifp->if_ierrors++;
  980                         if (isr & (ISR_ROK | ISR_RER))
  981                                 rdp_rint(sc);
  982                 }
  983 
  984                 /*
  985                  * If it looks like the transmitter can take more data,
  986                  * attempt to start output on the interface. This is done
  987                  * after handling the receiver to give the receiver priority.
  988                  */
  989                 if ((ifp->if_flags & IFF_OACTIVE) == 0)
  990                         rdp_start(ifp);
  991 
  992         }
  993         /* re-enable interrupts */
  994         WrNib(sc, CMR2, CMR2_IRQOUT | CMR2_IRQINV);
  995         sc->irqenbit = Ctrl_IRQEN;
  996         outb(sc->baseaddr + lpt_control, Ctrl_SelData + sc->irqenbit);
  997 }
  998 
  999 /*
 1000  * Ethernet interface receiver interrupt.
 1001  */
 1002 static void
 1003 rdp_rint(struct rdp_softc *sc)
 1004 {
 1005         struct ifnet *ifp = &sc->arpcom.ac_if;
 1006         struct rdphdr rh;
 1007         u_short len;
 1008         size_t i;
 1009         u_char *packet_ptr, b, status;
 1010         int excessive_bad_pkts = 0;
 1011 
 1012         /*
 1013          * Fetch the packets from the NIC's buffer.
 1014          */
 1015         for (;;) {
 1016                 b = RdNib(sc, CMR1);
 1017                 RdEnd(sc, CMR1);
 1018 
 1019                 if (b & CMR1_BUFE)
 1020                         /* no more packets */
 1021                         break;
 1022 
 1023                 /* first, obtain the buffer header */
 1024                 
 1025                 outb(sc->baseaddr + lpt_data, MAR + EOC); /* prepare addr */
 1026                 outb(sc->baseaddr + lpt_control, Ctrl_LNibRead);
 1027                 outb(sc->baseaddr + lpt_data, MAR + RdAddr + HNib);
 1028 
 1029                 packet_ptr = (u_char *)&rh;
 1030                 if (sc->slow)
 1031                         for (i = 0; i < sizeof rh; i++, packet_ptr++)
 1032                                 *packet_ptr = RdByteA2(sc);
 1033                 else
 1034                         for (i = 0; i < sizeof rh; i++, packet_ptr++)
 1035                                 *packet_ptr = RdByteA1(sc);
 1036 
 1037                 RdEnd(sc, MAR + HNib);
 1038                 outb(sc->baseaddr + lpt_control, Ctrl_SelData);
 1039 
 1040                 len = rh.pktlen - ETHER_CRC_LEN;
 1041                 status = rh.status;
 1042 
 1043                 if ((status & (RSR_ROK | RSR_CRC | RSR_FA)) != RSR_ROK ||
 1044                     len > (ETHER_MAX_LEN - ETHER_CRC_LEN) ||
 1045                     len < (ETHER_MIN_LEN - ETHER_CRC_LEN) ||
 1046                     len > MCLBYTES) {
 1047 #if DEBUG
 1048                         if_printf(ifp, "bad packet in buffer, "
 1049                                "len %d, status %#x\n",
 1050                                (int)len, (int)status);
 1051 #endif
 1052                         ifp->if_ierrors++;
 1053                         /* rx jump packet */
 1054                         WrNib(sc, CMR1, CMR1_RDPAC);
 1055                         if (++excessive_bad_pkts > 5) {
 1056                                 /*
 1057                                  * the chip seems to be stuck, we are
 1058                                  * probably seeing the same bad packet
 1059                                  * over and over again
 1060                                  */
 1061 #if DEBUG
 1062                                 if_printf(ifp, "resetting due to an "
 1063                                        "excessive number of bad packets\n");
 1064 #endif
 1065                                 rdp_reset(ifp);
 1066                                 return;
 1067                         }
 1068                         continue;
 1069                 }
 1070 
 1071                 /*
 1072                  * Go get packet.
 1073                  */
 1074                 excessive_bad_pkts = 0;
 1075                 rdp_get_packet(sc, len);
 1076                 ifp->if_ipackets++;
 1077         }
 1078 }
 1079 
 1080 /*
 1081  * Retreive packet from NIC memory and send to the next level up via
 1082  * ether_input().
 1083  */
 1084 static void
 1085 rdp_get_packet(struct rdp_softc *sc, unsigned len)
 1086 {
 1087         struct ifnet *ifp = &sc->arpcom.ac_if;
 1088         struct mbuf *m;
 1089         u_char *packet_ptr;
 1090         size_t s;
 1091 
 1092         /* Allocate a header mbuf */
 1093         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1094         if (m == NULL)
 1095                 return;
 1096         m->m_pkthdr.rcvif = ifp;
 1097         m->m_pkthdr.len = m->m_len = len;
 1098 
 1099         /*
 1100          * We always put the received packet in a single buffer -
 1101          * either with just an mbuf header or in a cluster attached
 1102          * to the header. The +2 is to compensate for the alignment
 1103          * fixup below.
 1104          */
 1105         if ((len + ETHER_ALIGN) > MHLEN) {
 1106                 /* Attach an mbuf cluster */
 1107                 MCLGET(m, M_DONTWAIT);
 1108 
 1109                 /* Insist on getting a cluster */
 1110                 if ((m->m_flags & M_EXT) == 0) {
 1111                         m_freem(m);
 1112                         return;
 1113                 }
 1114         }
 1115 
 1116         /*
 1117          * The +2 is to longword align the start of the real packet.
 1118          * This is important for NFS.
 1119          */
 1120         m->m_data += ETHER_ALIGN;
 1121 
 1122         /*
 1123          * Get packet, including link layer address, from interface.
 1124          */
 1125         outb(sc->baseaddr + lpt_control, Ctrl_LNibRead);
 1126         outb(sc->baseaddr + lpt_data, RdAddr + MAR);
 1127 
 1128         packet_ptr = mtod(m, u_char *);
 1129         if (sc->slow)
 1130                 for (s = 0; s < len; s++, packet_ptr++)
 1131                         *packet_ptr = RdByteA2(sc);
 1132         else
 1133                 for (s = 0; s < len; s++, packet_ptr++)
 1134                         *packet_ptr = RdByteA1(sc);
 1135 
 1136         RdEnd(sc, MAR + HNib);
 1137         outb(sc->baseaddr + lpt_control, Ctrl_SelData);
 1138         WrNib(sc, CMR1, CMR1_RDPAC);
 1139 
 1140         (*ifp->if_input)(ifp, m);
 1141 }
 1142 
 1143 /*
 1144  * Write an mbuf chain to the NIC's tx buffer.
 1145  */
 1146 static u_short
 1147 rdp_write_mbufs(struct rdp_softc *sc, struct mbuf *m)
 1148 {
 1149         u_short total_len;
 1150         struct mbuf *mp;
 1151         u_char *dp, b;
 1152         int i;
 1153 
 1154         /* First, count up the total number of bytes to copy */
 1155         for (total_len = 0, mp = m; mp; mp = mp->m_next)
 1156                 total_len += mp->m_len;
 1157 
 1158         if (total_len == 0)
 1159                 return 0;
 1160 
 1161         outb(sc->baseaddr + lpt_data, MAR | EOC);
 1162 
 1163         /*
 1164          * Transfer the mbuf chain to the NIC memory.
 1165          */
 1166         if (sc->slow) {
 1167                 /* writing the first byte is complicated */
 1168                 outb(sc->baseaddr + lpt_control,
 1169                      Ctrl_LNibRead | sc->irqenbit);
 1170                 outb(sc->baseaddr + lpt_data, MAR | WrAddr);
 1171                 b = *(u_char *)m->m_data;
 1172                 outb(sc->baseaddr + lpt_data, (b & 0x0f) | 0x40);
 1173                 outb(sc->baseaddr + lpt_data, b & 0x0f);
 1174                 outb(sc->baseaddr + lpt_data, b >> 4);
 1175                 outb(sc->baseaddr + lpt_control,
 1176                      Ctrl_HNibRead | sc->irqenbit);
 1177                 /* advance the mbuf pointer */
 1178                 mp = m;
 1179                 m->m_len--;
 1180                 m->m_data++;
 1181                 /* write the remaining bytes */
 1182                 while (m) {
 1183                         for (i = 0, dp = (u_char *)m->m_data;
 1184                              i < m->m_len;
 1185                              i++, dp++)
 1186                                 WrByteALToDRAMA(sc, *dp);
 1187                         m = m->m_next;
 1188                 }
 1189                 /*
 1190                  * restore old mbuf in case we have to hand it off to
 1191                  * BPF again
 1192                  */
 1193                 m = mp;
 1194                 m->m_len++;
 1195                 m->m_data--;
 1196 
 1197                 /* the RTL 8002 requires an even byte-count remote DMA */
 1198                 if (total_len & 1)
 1199                         WrByteALToDRAMA(sc, 0);
 1200         } else {
 1201                 outb(sc->baseaddr + lpt_data, MAR | WrAddr);
 1202                 while (m) {
 1203                         for (i = 0, dp = (u_char *)m->m_data;
 1204                              i < m->m_len;
 1205                              i++, dp++)
 1206                                 WrByteALToDRAM(sc, *dp);
 1207                         m = m->m_next;
 1208                 }
 1209 
 1210                 /* the RTL 8002 requires an even byte-count remote DMA */
 1211                 if (total_len & 1)
 1212                         WrByteALToDRAM(sc, 0);
 1213         }
 1214 
 1215         outb(sc->baseaddr + lpt_data, 0xff);
 1216         outb(sc->baseaddr + lpt_control,
 1217              Ctrl_HNibRead | Ctrl_SelData | sc->irqenbit);
 1218 
 1219         return total_len;
 1220 }
 1221 
 1222 /*
 1223  * Read the designated ethernet hardware address out of a 93C46
 1224  * (serial) EEPROM.
 1225  * Note that the 93C46 uses 16-bit words in big-endian notation.
 1226  */
 1227 static int
 1228 rdp_gethwaddr_93c46(struct rdp_softc *sc, u_char *etheraddr)
 1229 {
 1230         int i, magic;
 1231         size_t j = 0;
 1232         u_short w;
 1233 
 1234         WrNib(sc, CMR2, CMR2_PAGE | CMR2_IRQINV); /* select page 1 */
 1235 
 1236         /*
 1237          * The original RealTek packet driver had the ethernet address
 1238          * starting at EEPROM address 0.  Other vendors seem to have
 1239          * gone `creative' here -- while they didn't do anything else
 1240          * than changing a few strings in the entire driver, compared
 1241          * to the RealTek version, they also moved out the ethernet
 1242          * address to a different location in the EEPROM, so the
 1243          * original RealTek driver won't work correctly with them, and
 1244          * vice versa.  Sounds pretty cool, eh?  $@%&!
 1245          *
 1246          * Anyway, we walk through the EEPROM, until we find some
 1247          * allowable value based upon our table of IEEE OUI assignments.
 1248          */
 1249         for (i = magic = 0; magic < 3 && i < 32; i++) {
 1250                 /* read cmd (+ 6 bit address) */
 1251                 rdp_93c46_cmd(sc, 0x180 + i, 10);
 1252                 w = rdp_93c46_read(sc);
 1253                 switch (magic) {
 1254                 case 0:
 1255                         for (j = 0;
 1256                              j < sizeof allowed_ouis / sizeof(u_short);
 1257                              j++)
 1258                                 if (w == allowed_ouis[j]) {
 1259                                         etheraddr[0] = (w >> 8) & 0xff;
 1260                                         etheraddr[1] = w & 0xff;
 1261                                         magic++;
 1262                                         break;
 1263                                 }
 1264                         break;
 1265 
 1266                 case 1:
 1267                         /*
 1268                          * If the first two bytes have been 00:00, we
 1269                          * discard the match iff the next two bytes
 1270                          * are also 00:00, so we won't get fooled by
 1271                          * an EEPROM that has been filled with zeros.
 1272                          * This in theory would disallow 64 K of legal
 1273                          * addresses assigned to Xerox, but it's
 1274                          * almost certain that those addresses haven't
 1275                          * been used for RTL80[01]2 chips anyway.
 1276                          */
 1277                         if ((etheraddr[0] | etheraddr[1]) == 0 && w == 0) {
 1278                                 magic--;
 1279                                 break;
 1280                         }
 1281 
 1282                         etheraddr[2] = (w >> 8) & 0xff;
 1283                         etheraddr[3] = w & 0xff;
 1284                         magic++;
 1285                         break;
 1286 
 1287                 case 2:
 1288                         etheraddr[4] = (w >> 8) & 0xff;
 1289                         etheraddr[5] = w & 0xff;
 1290                         magic++;
 1291                         break;
 1292                 }
 1293         }
 1294 
 1295         WrNib(sc, CMR2, CMR2_IRQINV);   /* back to page 0 */
 1296 
 1297         return magic == 3;
 1298 }
 1299 
 1300 /*
 1301  * Read the designated ethernet hardware address out of a 74S288
 1302  * EEPROM.
 1303  *
 1304  * This is untested, since i haven't seen any adapter actually using
 1305  * a 74S288.  In the RTL 8012, only the serial EEPROM (94C46) is
 1306  * supported anymore.
 1307  */
 1308 static void
 1309 rdp_gethwaddr_74s288(struct rdp_softc *sc, u_char *etheraddr)
 1310 {
 1311         int i;
 1312         u_char b;
 1313 
 1314         WrNib(sc, CMR2, CMR2_PAGE | CMR2_IRQINV); /* select page 1 */
 1315 
 1316         for (i = 0; i < 6; i++) {
 1317                 WrNib(sc, PCMR, i & 0x0f); /* lower 4 bit of addr */
 1318                 WrNib(sc, PCMR + HNib, HNib + 4); /* upper 2 bit addr + /CS */
 1319                 WrNib(sc, PCMR + HNib, HNib); /* latch data now */
 1320                 b = RdNib(sc, PDR) & 0x0f;
 1321                 b |= (RdNib(sc, PDR + HNib) & 0x0f) << 4;
 1322                 etheraddr[i] = b;
 1323         }
 1324 
 1325         RdEnd(sc, PDR + HNib);
 1326         WrNib(sc, CMR2, CMR2_IRQINV);   /* reselect page 0 */
 1327 }
 1328 
 1329 /*
 1330  * Send nbits of data (starting with MSB) out to the 93c46 as a
 1331  * command.  Assumes register page 1 has already been selected.
 1332  */
 1333 static void
 1334 rdp_93c46_cmd(struct rdp_softc *sc, u_short data, unsigned nbits)
 1335 {
 1336         u_short mask = 1 << (nbits - 1);
 1337         unsigned i;
 1338         u_char b;
 1339 
 1340 #if DEBUG & 2
 1341         printf("rdp_93c46_cmd(): ");
 1342 #endif
 1343         for (i = 0; i < nbits; i++, mask >>= 1) {
 1344                 b = HNib + PCMR_SK + PCMR_CS;
 1345                 if (data & mask)
 1346                         b += PCMR_DO;
 1347 #if DEBUG & 2
 1348                 printf("%d", b & 1);
 1349 #endif
 1350                 WrNib(sc, PCMR + HNib, b);
 1351                 DELAY(1);
 1352                 WrNib(sc, PCMR + HNib, b & ~PCMR_SK);
 1353                 DELAY(1);
 1354         }
 1355 #if DEBUG & 2
 1356         printf("\n");
 1357 #endif
 1358 }
 1359 
 1360 /*
 1361  * Read one word of data from the 93c46.  Actually, we have to read
 1362  * 17 bits, and discard the very first bit.  Assumes register page 1
 1363  * to be selected as well.
 1364  */
 1365 static u_short
 1366 rdp_93c46_read(struct rdp_softc *sc)
 1367 {
 1368         u_short data = 0;
 1369         u_char b;
 1370         int i;
 1371 
 1372 #if DEBUG & 2
 1373         printf("rdp_93c46_read(): ");
 1374 #endif
 1375         for (i = 0; i < 17; i++) {
 1376                 WrNib(sc, PCMR + HNib, PCMR_SK + PCMR_CS + HNib);
 1377                 DELAY(1);
 1378                 WrNib(sc, PCMR + HNib, PCMR_CS + HNib);
 1379                 DELAY(1);
 1380                 b = RdNib(sc, PDR);
 1381                 data <<= 1;
 1382                 if (b & 1)
 1383                         data |= 1;
 1384 #if DEBUG & 2
 1385                 printf("%d", b & 1);
 1386 #endif
 1387                 RdEnd(sc, PDR);
 1388                 DELAY(1);
 1389         }
 1390 
 1391 #if DEBUG & 2
 1392         printf("\n");
 1393 #endif
 1394         /* end of cycle */
 1395         WrNib(sc, PCMR + HNib, PCMR_SK + HNib);
 1396         DELAY(1);
 1397 
 1398         return data;
 1399 }

Cache object: 2d92b6d4877749f560ba0805d7fceddb


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