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