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