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