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