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