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