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