if_netdock_nubus.c revision 1.1 1 /* $NetBSD: if_netdock_nubus.c,v 1.1 2002/06/19 01:54:28 itojun Exp $ */
2
3 /*
4 * Copyright (C) 2000,2002 Daishi Kato <daishi (at) axlight.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Daishi Kato
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Asante NetDock (for Duo series) driver
35 * the chip inside is not known
36 */
37
38 /*
39 * The author would like to thank Takeo Kuwata <tkuwata (at) mac.com> for
40 * his help in stabilizing this driver.
41 */
42
43 /***********************/
44
45 #include <sys/param.h>
46 #include <sys/device.h>
47 #include <sys/socket.h>
48 #include <sys/systm.h>
49 #include <sys/mbuf.h>
50 #include <sys/ioctl.h>
51
52 #include <net/if.h>
53 #include <net/if_dl.h>
54 #include <net/if_ether.h>
55
56 #include "opt_inet.h"
57 #ifdef INET
58 #include <netinet/in.h>
59 #include <netinet/if_inarp.h>
60 #endif
61
62 #include "bpfilter.h"
63 #if NBPFILTER > 0
64 #include <net/bpf.h>
65 #endif
66
67 #include <machine/bus.h>
68 #include <machine/viareg.h>
69 #include <mac68k/nubus/nubus.h>
70
71 /***********************/
72
73 #define NETDOCK_DEBUG
74
75 #define NETDOCK_NUBUS_CATEGORY 0x0020
76 #define NETDOCK_NUBUS_TYPE 0x0003
77 #define NETDOCK_NUBUS_DRSW 0x0103
78 #define NETDOCK_NUBUS_DRHW 0x0100
79
80 #define ETHERMICRODOCK_NUBUS_CATEGORY 0x0020
81 #define ETHERMICRODOCK_NUBUS_TYPE 0x0003
82 #define ETHERMICRODOCK_NUBUS_DRSW 0x0102
83 #define ETHERMICRODOCK_NUBUS_DRHW 0x0100
84
85 #define REG_ISR 0x000c
86 #define REG_000E 0x000e
87 #define REG_0000 0x0000
88 #define REG_0002 0x0002
89 #define REG_0004 0x0004
90 #define REG_0006 0x0006
91 #define REG_DATA 0x0008
92 #define REG_EFD00 0xefd00
93
94 #define ISR_ALL 0x3300
95 #define ISR_TX 0x0200
96 #define ISR_RX 0x0100
97 #define ISR_READY 0x0800
98 #define ISR_BIT_0C 0x1000
99 #define ISR_BIT_0D 0x2000
100 #define ISR_MASK 0x0033
101 #define ISR_BIT_03 0x0008
102
103 #define REG_0002_BIT_04 0x0010
104 #define REG_0000_BIT_08 0x0100
105 #define REG_0004_BIT_0F 0x8000
106 #define REG_0004_BIT_07 0x0080
107 #define REG_DATA_BIT_02 0x0004
108 #define REG_DATA_BIT_03 0x0008
109 #define REG_DATA_BIT_04 0x0010
110 #define REG_DATA_BIT_05 0x0020
111 #define REG_DATA_BIT_08 0x0100
112 #define REG_DATA_BIT_07 0x0080
113 #define REG_DATA_BIT_0F 0x8000
114
115 /***********************/
116
117 typedef struct netdock_softc {
118 struct device sc_dev;
119 struct ethercom sc_ethercom;
120 #define sc_if sc_ethercom.ec_if
121
122 bus_space_tag_t sc_regt;
123 bus_space_handle_t sc_regh;
124
125 u_int8_t sc_enaddr[ETHER_ADDR_LEN];
126
127 } netdock_softc_t;
128
129 /***********************/
130
131 static int netdock_nubus_match __P((struct device *, struct cfdata *,
132 void*));
133 static void netdock_nubus_attach __P((struct device *, struct device *,
134 void *));
135 static int netdock_nb_get_enaddr __P((bus_space_tag_t, bus_space_handle_t,
136 struct nubus_attach_args *, u_int8_t *));
137 #ifdef NETDOCK_DEBUG_DRIVER
138 static void netdock_print_driver __P((bus_space_tag_t, bus_space_handle_t,
139 struct nubus_attach_args *));
140 #endif
141
142 int netdock_setup __P((struct netdock_softc *, u_int8_t *));
143 void netdock_intr __P((void *));
144
145 static void netdock_watchdog __P((struct ifnet *));
146 static int netdock_init __P((struct netdock_softc *));
147 static int netdock_stop __P((struct netdock_softc *));
148 static int netdock_ioctl __P((struct ifnet *, u_long, caddr_t));
149 static void netdock_start __P((struct ifnet *));
150 static void netdock_reset __P((struct netdock_softc *));
151 static void netdock_txint __P((struct netdock_softc *));
152 static void netdock_rxint __P((struct netdock_softc *));
153
154 static u_int netdock_put __P((struct netdock_softc *, struct mbuf *));
155 static int netdock_read __P((struct netdock_softc *, int));
156 static struct mbuf *netdock_get __P((struct netdock_softc *, int));
157
158 /***********************/
159
160 #define NIC_GET_1(sc, o) (bus_space_read_1((sc)->sc_regt, \
161 (sc)->sc_regh, (o)))
162 #define NIC_PUT_1(sc, o, val) (bus_space_write_1((sc)->sc_regt, \
163 (sc)->sc_regh, (o), (val)))
164 #define NIC_GET_2(sc, o) (bus_space_read_2((sc)->sc_regt, \
165 (sc)->sc_regh, (o)))
166 #define NIC_PUT_2(sc, o, val) (bus_space_write_2((sc)->sc_regt, \
167 (sc)->sc_regh, (o), (val)))
168 #define NIC_GET_4(sc, o) (bus_space_read_4((sc)->sc_regt, \
169 (sc)->sc_regh, (o)))
170 #define NIC_PUT_4(sc, o, val) (bus_space_write_4((sc)->sc_regt, \
171 (sc)->sc_regh, (o), (val)))
172
173 #define NIC_BSET(sc, o, b) \
174 __asm__ __volatile("bset %0,%1" : : "di" ((u_short)(b)), \
175 "g" (*(u_int8_t *)((sc)->sc_regh.base + (o))))
176 #define NIC_BCLR(sc, o, b) \
177 __asm__ __volatile("bclr %0,%1" : : "di" ((u_short)(b)), \
178 "g" (*(u_int8_t *)((sc)->sc_regh.base + (o))))
179 #define NIC_ANDW(sc, o, b) \
180 __asm__ __volatile("andw %0,%1" : : "di" ((u_short)(b)), \
181 "g" (*(u_int8_t *)((sc)->sc_regh.base + (o))))
182 #define NIC_ORW(sc, o, b) \
183 __asm__ __volatile("orw %0,%1" : : "di" ((u_short)(b)), \
184 "g" (*(u_int8_t *)((sc)->sc_regh.base + (o))))
185
186
187 /***********************/
188
189 struct cfattach netdock_nubus_ca = {
190 sizeof(struct netdock_softc), netdock_nubus_match, netdock_nubus_attach
191 };
192
193 /***********************/
194
195 static int
196 netdock_nubus_match(parent, cf, aux)
197 struct device *parent;
198 struct cfdata *cf;
199 void *aux;
200 {
201 struct nubus_attach_args *na = (struct nubus_attach_args *)aux;
202 bus_space_handle_t bsh;
203 int rv;
204
205 if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot),
206 NBMEMSIZE, 0, &bsh))
207 return (0);
208
209 rv = 0;
210
211 if (na->category == NETDOCK_NUBUS_CATEGORY &&
212 na->type == NETDOCK_NUBUS_TYPE &&
213 na->drsw == NETDOCK_NUBUS_DRSW) {
214 /* assuming this IS Asante NetDock */
215 rv = 1;
216 }
217
218 if (na->category == ETHERMICRODOCK_NUBUS_CATEGORY &&
219 na->type == ETHERMICRODOCK_NUBUS_TYPE &&
220 na->drsw == ETHERMICRODOCK_NUBUS_DRSW) {
221 /* assuming this IS Newer EtherMicroDock */
222 rv = 1;
223 }
224
225 bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
226
227 return rv;
228 }
229
230 static void
231 netdock_nubus_attach(parent, self, aux)
232 struct device *parent, *self;
233 void *aux;
234 {
235 struct netdock_softc *sc = (struct netdock_softc *)self;
236 struct nubus_attach_args *na = (struct nubus_attach_args *)aux;
237 bus_space_tag_t bst;
238 bus_space_handle_t bsh;
239 u_int8_t enaddr[ETHER_ADDR_LEN];
240 char *cardtype;
241
242 bst = na->na_tag;
243 if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 0, &bsh)) {
244 printf(": failed to map memory space.\n");
245 return;
246 }
247
248 sc->sc_regt = bst;
249 cardtype = nubus_get_card_name(bst, bsh, na->fmt);
250
251 #ifdef NETDOCK_DEBUG_DRIVER
252 netdock_print_driver(bst, bsh, na);
253 #endif
254
255 if (netdock_nb_get_enaddr(bst, bsh, na, enaddr)) {
256 printf(": can't find MAC address.\n");
257 bus_space_unmap(bst, bsh, NBMEMSIZE);
258 return;
259 }
260
261 if (bus_space_subregion(bst, bsh, 0xe00300, 0xf0000, &sc->sc_regh)) {
262 printf(": failed to map register space.\n");
263 bus_space_unmap(bst, bsh, NBMEMSIZE);
264 return;
265 }
266
267 printf(": %s\n", cardtype);
268
269 if (netdock_setup(sc, enaddr)) {
270 bus_space_unmap(bst, bsh, NBMEMSIZE);
271 return;
272 }
273
274 add_nubus_intr(na->slot, netdock_intr, (void *)sc);
275
276 return;
277 }
278
279 static int
280 netdock_nb_get_enaddr(bst, bsh, na, ep)
281 bus_space_tag_t bst;
282 bus_space_handle_t bsh;
283 struct nubus_attach_args *na;
284 u_int8_t *ep;
285 {
286 nubus_dir dir;
287 nubus_dirent dirent;
288
289 /*
290 * these hardwired resource IDs are only for NetDock
291 */
292 nubus_get_main_dir(na->fmt, &dir);
293 if (nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x81, &dirent) <= 0)
294 return 1;
295 nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir);
296 if (nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x80, &dirent) <= 0)
297 return 1;
298 if (nubus_get_ind_data(bst, bsh, na->fmt, &dirent,
299 ep, ETHER_ADDR_LEN) <= 0)
300 return 1;
301
302 return 0;
303 }
304
305 #ifdef NETDOCK_DEBUG_DRIVER
306 static void
307 netdock_print_driver(bst, bsh, na)
308 bus_space_tag_t bst;
309 bus_space_handle_t bsh;
310 struct nubus_attach_args *na;
311 {
312 #define HEADSIZE (8+4)
313 #define CODESIZE (6759-4)
314 unsigned char mydata[HEADSIZE + CODESIZE];
315 nubus_dir dir;
316 nubus_dirent dirent;
317 int i, rv;
318
319 nubus_get_main_dir(na->fmt, &dir);
320 rv = nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x81, &dirent);
321 if (rv <= 0) {
322 printf(": can't find sResource.\n");
323 return;
324 }
325 nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir);
326 if (nubus_find_rsrc(bst, bsh, na->fmt, &dir, NUBUS_RSRC_DRVRDIR,
327 &dirent) <= 0) {
328 printf(": can't find sResource.\n");
329 return;
330 }
331 if (nubus_get_ind_data(bst, bsh, na->fmt,
332 &dirent, mydata, HEADSIZE+CODESIZE) <= 0) {
333 printf(": can't find indirect data.\n");
334 return;
335 }
336 printf("\n########## begin driver dir");
337 for (i = 0; i < HEADSIZE; i++) {
338 if (i % 16 == 0)
339 printf("\n%02x:",i);
340 printf(" %02x", mydata[i]);
341 }
342 printf("\n########## begin driver code");
343 for (i = 0; i < CODESIZE; i++) {
344 if (i % 16 == 0)
345 printf("\n%02x:",i);
346 printf(" %02x", mydata[i + HEADSIZE]);
347 }
348 #if 0
349 printf("\n########## begin driver code (partial)\n");
350 #define PARTSIZE 256
351 #define OFFSET 0x1568
352 for (i = OFFSET; i < OFFSET + PARTSIZE; i++) {
353 if ((i - OFFSET) % 16 == 0)
354 printf("\n%02x:",i);
355 printf(" %02x", mydata[i + HEADSIZE]);
356 }
357 #endif
358 printf("\n########## end\n");
359 }
360 #endif
361
362
363 int
364 netdock_setup(sc, lladdr)
365 struct netdock_softc *sc;
366 u_int8_t *lladdr;
367 {
368 struct ifnet *ifp = &sc->sc_if;
369
370 bcopy(lladdr, sc->sc_enaddr, ETHER_ADDR_LEN);
371 printf("%s: Ethernet address %s\n",
372 sc->sc_dev.dv_xname, ether_sprintf(lladdr));
373
374 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
375 ifp->if_softc = sc;
376 ifp->if_ioctl = netdock_ioctl;
377 ifp->if_start = netdock_start;
378 ifp->if_flags =
379 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
380 ifp->if_watchdog = netdock_watchdog;
381
382 if_attach(ifp);
383 ether_ifattach(ifp, lladdr);
384
385 return (0);
386 }
387
388 static int
389 netdock_ioctl(ifp, cmd, data)
390 struct ifnet *ifp;
391 u_long cmd;
392 caddr_t data;
393 {
394 struct ifaddr *ifa;
395 struct ifreq *ifr;
396 struct netdock_softc *sc = ifp->if_softc;
397 int s = splnet();
398 int err = 0;
399 int temp;
400
401 switch (cmd) {
402 case SIOCSIFADDR:
403 ifa = (struct ifaddr *)data;
404 ifp->if_flags |= IFF_UP;
405 switch (ifa->ifa_addr->sa_family) {
406 #ifdef INET
407 case AF_INET:
408 (void)netdock_init(sc);
409 arp_ifinit(ifp, ifa);
410 break;
411 #endif
412 default:
413 (void)netdock_init(sc);
414 break;
415 }
416 break;
417
418 case SIOCSIFFLAGS:
419 if ((ifp->if_flags & IFF_UP) == 0 &&
420 (ifp->if_flags & IFF_RUNNING) != 0) {
421 netdock_stop(sc);
422 ifp->if_flags &= ~IFF_RUNNING;
423 } else if ((ifp->if_flags & IFF_UP) != 0 &&
424 (ifp->if_flags & IFF_RUNNING) == 0) {
425 (void)netdock_init(sc);
426 } else {
427 temp = ifp->if_flags & IFF_UP;
428 netdock_reset(sc);
429 ifp->if_flags |= temp;
430 netdock_start(ifp);
431 }
432 break;
433
434 case SIOCADDMULTI:
435 case SIOCDELMULTI:
436 ifr = (struct ifreq *)data;
437 if (cmd == SIOCADDMULTI)
438 err = ether_addmulti(ifr, &sc->sc_ethercom);
439 else
440 err = ether_delmulti(ifr, &sc->sc_ethercom);
441
442 if (err == ENETRESET) {
443 temp = ifp->if_flags & IFF_UP;
444 netdock_reset(sc);
445 ifp->if_flags |= temp;
446 err = 0;
447 }
448 break;
449 default:
450 err = EINVAL;
451 break;
452 }
453 splx(s);
454 return (err);
455 }
456
457 static void
458 netdock_start(ifp)
459 struct ifnet *ifp;
460 {
461 struct netdock_softc *sc = ifp->if_softc;
462 struct mbuf *m;
463
464 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
465 return;
466
467 while (1) {
468 IF_DEQUEUE(&ifp->if_snd, m);
469 if (m == 0)
470 return;
471
472 if ((m->m_flags & M_PKTHDR) == 0)
473 panic("%s: netdock_start: no header mbuf",
474 sc->sc_dev.dv_xname);
475
476 #if NBPFILTER > 0
477 if (ifp->if_bpf)
478 bpf_mtap(ifp->if_bpf, m);
479 #endif
480
481 if ((netdock_put(sc, m)) == 0) {
482 IF_PREPEND(&ifp->if_snd, m);
483 return;
484 }
485
486 ifp->if_opackets++;
487 }
488
489 }
490
491 static void
492 netdock_reset(sc)
493 struct netdock_softc *sc;
494 {
495
496 netdock_stop(sc);
497 netdock_init(sc);
498 }
499
500 static int
501 netdock_init(sc)
502 struct netdock_softc *sc;
503 {
504 int s;
505 int saveisr;
506 int savetmp;
507
508 if (sc->sc_if.if_flags & IFF_RUNNING)
509 return (0);
510
511 s = splnet();
512
513 /* 0606 */
514 NIC_PUT_2(sc, REG_000E, 0x0200);
515 NIC_PUT_2(sc, REG_ISR , 0);
516 NIC_PUT_2(sc, REG_000E, 0);
517
518 NIC_PUT_2(sc, REG_0000, 0x8104);
519 NIC_PUT_2(sc, REG_0004, 0x0043);
520 NIC_PUT_2(sc, REG_000E, 0x0100);
521 NIC_PUT_2(sc, REG_0002, 0x6618);
522 NIC_PUT_2(sc, REG_0000, 0x8010);
523
524 NIC_PUT_1(sc, REG_0004 + 0, sc->sc_enaddr[0]);
525 NIC_PUT_1(sc, REG_0004 + 1, sc->sc_enaddr[1]);
526 NIC_PUT_1(sc, REG_0004 + 2, sc->sc_enaddr[2]);
527 NIC_PUT_1(sc, REG_0004 + 3, sc->sc_enaddr[3]);
528 NIC_PUT_1(sc, REG_0004 + 4, sc->sc_enaddr[4]);
529 NIC_PUT_1(sc, REG_0004 + 5, sc->sc_enaddr[5]);
530
531 NIC_PUT_2(sc, REG_ISR , 0x2008);
532 NIC_PUT_2(sc, REG_000E, 0x0200);
533 NIC_PUT_2(sc, REG_0000, 0x4000);
534 NIC_PUT_2(sc, REG_ISR, ISR_MASK);
535
536
537 /* 1320 */
538 saveisr = NIC_GET_2(sc, REG_ISR);
539 NIC_PUT_2(sc, REG_ISR , 0);
540 savetmp = NIC_GET_2(sc, REG_000E);
541 NIC_PUT_2(sc, REG_000E, 0x0100);
542 NIC_ANDW(sc, REG_ISR, ~ISR_BIT_03);
543 NIC_PUT_2(sc, REG_000E, savetmp);
544
545 /* 1382 */
546 savetmp = NIC_GET_2(sc, REG_000E);
547 NIC_PUT_2(sc, REG_000E, 0x0100);
548 NIC_ORW(sc, REG_ISR, ISR_BIT_03);
549 NIC_PUT_2(sc, REG_000E, savetmp);
550 NIC_PUT_2(sc, REG_ISR , saveisr);
551
552
553 sc->sc_if.if_flags |= IFF_RUNNING;
554 sc->sc_if.if_flags &= ~IFF_OACTIVE;
555
556 splx(s);
557 return (0);
558 }
559
560 static int
561 netdock_stop(sc)
562 struct netdock_softc *sc;
563 {
564 int s = splnet();
565
566 sc->sc_if.if_timer = 0;
567 sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP);
568
569 splx(s);
570 return (0);
571 }
572
573 static void
574 netdock_watchdog(ifp)
575 struct ifnet *ifp;
576 {
577 struct netdock_softc *sc = ifp->if_softc;
578 int tmp;
579
580 printf("netdock_watchdog: resetting chip\n");
581 tmp = ifp->if_flags & IFF_UP;
582 netdock_reset(sc);
583 ifp->if_flags |= tmp;
584 }
585
586 static u_int
587 netdock_put(sc, m0)
588 struct netdock_softc *sc;
589 struct mbuf *m0;
590 {
591 struct mbuf *m;
592 u_int totlen = 0;
593 u_int tmplen;
594 int isr;
595 int timeout;
596 int tmp;
597 u_int i;
598
599 for (m = m0; m; m = m->m_next)
600 totlen += m->m_len;
601
602 if (totlen >= ETHER_MAX_LEN)
603 panic("%s: netdock_put: packet overflow", sc->sc_dev.dv_xname);
604
605 totlen += 6;
606 tmplen = totlen;
607 tmplen &= 0xff00;
608 tmplen |= 0x2000;
609 NIC_PUT_2(sc, REG_0000, tmplen);
610
611 timeout = 0x3000;
612 while ((((isr = NIC_GET_2(sc, REG_ISR)) & ISR_READY) == 0) &&
613 timeout--) {
614 if (isr & ISR_TX)
615 netdock_txint(sc);
616 }
617 if (timeout == 0)
618 return (0);
619
620 tmp = NIC_GET_2(sc, REG_0002);
621 tmp <<= 8;
622 NIC_PUT_2(sc, REG_0002, tmp);
623 NIC_PUT_2(sc, REG_0006, 0x240);
624 NIC_GET_2(sc, REG_ISR);
625 tmplen = ((totlen << 8) & 0xfe00) | ((totlen >> 8) & 0x00ff);
626 NIC_PUT_2(sc, REG_DATA, tmplen);
627
628 for (m = m0; m; m = m->m_next) {
629 u_char *data = mtod(m, u_char *);
630 int len = m->m_len;
631 int len4 = len >> 2;
632 u_int32_t *data4 = (u_int32_t *)data;
633 for (i = 0; i < len4; i++)
634 NIC_PUT_4(sc, REG_DATA, data4[i]);
635 for (i = len4 << 2; i < len; i++)
636 NIC_PUT_1(sc, REG_DATA, data[i]);
637 }
638
639 if (totlen & 0x01)
640 NIC_PUT_2(sc, REG_DATA, 0x2020);
641 else
642 NIC_PUT_2(sc, REG_DATA, 0);
643
644 NIC_PUT_2(sc, REG_0000, 0xc000);
645
646 m_freem(m0);
647 /* sc->sc_if.if_timer = 5; */
648 return (totlen);
649 }
650
651 void
652 netdock_intr(arg)
653 void *arg;
654 {
655 struct netdock_softc *sc = (struct netdock_softc *)arg;
656 int isr;
657 int tmp;
658
659 NIC_PUT_2(sc, REG_ISR, 0);
660 while ((isr = (NIC_GET_2(sc, REG_ISR) & ISR_ALL)) != 0) {
661 if (isr & ISR_TX)
662 netdock_txint(sc);
663
664 if (isr & ISR_RX)
665 netdock_rxint(sc);
666
667 if (isr & (ISR_BIT_0C | ISR_BIT_0D)) {
668 if (isr & ISR_BIT_0C) {
669 NIC_PUT_2(sc, REG_000E, 0);
670 NIC_BSET(sc, REG_0004, 0x08);
671 NIC_PUT_2(sc, REG_000E, 0x0200);
672 }
673 if (isr & ISR_BIT_0D) {
674 NIC_PUT_2(sc, REG_000E, 0);
675 tmp = NIC_GET_2(sc, REG_0002);
676 if (tmp & REG_0002_BIT_04)
677 NIC_GET_2(sc, REG_0006);
678 tmp = NIC_GET_2(sc, REG_0000);
679 if (tmp & REG_0000_BIT_08)
680 NIC_BSET(sc, REG_0000, 0x08);
681 NIC_PUT_2(sc, REG_000E, 0x0200);
682 }
683 NIC_PUT_2(sc, REG_ISR, isr);
684 }
685 }
686 NIC_PUT_2(sc, REG_ISR, ISR_MASK);
687 }
688
689 static void
690 netdock_txint(sc)
691 struct netdock_softc *sc;
692 {
693 struct ifnet *ifp = &sc->sc_if;
694 int savereg0002;
695 int reg0004;
696 int regdata;
697
698 ifp->if_flags &= ~IFF_OACTIVE;
699 ifp->if_timer = 0;
700
701 savereg0002 = NIC_GET_2(sc, REG_0002);
702
703 while (((reg0004 = NIC_GET_2(sc, REG_0004)) & REG_0004_BIT_0F) == 0) {
704 NIC_PUT_2(sc, REG_0002, reg0004);
705 NIC_PUT_2(sc, REG_0006, 0x0060);
706 NIC_GET_2(sc, REG_ISR);
707 regdata = NIC_GET_2(sc, REG_DATA);
708 if ((regdata & REG_DATA_BIT_08) == 0) {
709 /* ifp->if_collisions++; */
710 if (regdata & REG_DATA_BIT_07)
711 /* ifp->if_oerrors++; */
712 NIC_PUT_2(sc, REG_000E, 0);
713 NIC_ORW(sc, REG_0000, 0x0100);
714 NIC_PUT_2(sc, REG_000E, 0x0200);
715 }
716 NIC_GET_2(sc ,REG_DATA);
717
718 if (regdata & REG_DATA_BIT_0F)
719 NIC_GET_4(sc, REG_EFD00);
720 NIC_PUT_2(sc, REG_0000, 0xa000);
721 NIC_PUT_2(sc, REG_ISR, ISR_TX);
722 }
723
724 NIC_PUT_2(sc, REG_0002, savereg0002);
725 NIC_PUT_2(sc, REG_000E, 0);
726 NIC_GET_2(sc, REG_0006);
727 NIC_PUT_2(sc, REG_000E, 0x0200);
728 NIC_PUT_2(sc, REG_0006, 0);
729 }
730
731 static void
732 netdock_rxint(sc)
733 struct netdock_softc *sc;
734 {
735 struct ifnet *ifp = &sc->sc_if;
736 int regdata1;
737 int regdata2;
738 u_int len;
739 int timeout;
740
741 while ((NIC_GET_2(sc, REG_0004) & REG_0004_BIT_07) == 0) {
742 NIC_GET_2(sc, REG_ISR);
743 NIC_PUT_2(sc, REG_0006, 0x00e0);
744 NIC_GET_2(sc, REG_ISR);
745 regdata1 = NIC_GET_2(sc, REG_DATA);
746 regdata2 = NIC_GET_2(sc, REG_DATA);
747 len = ((regdata2 << 8) & 0x0700) | ((regdata2 >> 8) & 0x00ff);
748
749 #if 0
750 printf("netdock_rxint: r1=0x%04x, r2=0x%04x, len=%d\n",
751 regdata1, regdata2, len);
752 #endif
753
754 if ((regdata1 & REG_DATA_BIT_04) == 0)
755 len -= 2;
756
757 if ((regdata1 & 0x00ac) == 0) {
758 if (netdock_read(sc, len))
759 ifp->if_ipackets++;
760 else
761 ifp->if_ierrors++;
762 } else {
763 ifp->if_ierrors++;
764
765 if (regdata1 & REG_DATA_BIT_02)
766 NIC_GET_4(sc, REG_EFD00);
767 if (regdata1 & REG_DATA_BIT_03)
768 ;
769 if (regdata1 & REG_DATA_BIT_05)
770 NIC_GET_4(sc, REG_EFD00);
771 if (regdata1 & REG_DATA_BIT_07)
772 ;
773 }
774
775 timeout = 0x14;
776 while ((NIC_GET_2(sc, REG_0000) & REG_0000_BIT_08) && timeout--)
777 ;
778 if (timeout == 0)
779 ;
780
781 NIC_PUT_2(sc, REG_0000, 0x8000);
782 }
783 NIC_PUT_2(sc, REG_0006, 0);
784 }
785
786 static int
787 netdock_read(sc, len)
788 struct netdock_softc *sc;
789 int len;
790 {
791 struct ifnet *ifp = &sc->sc_if;
792 struct mbuf *m;
793
794 m = netdock_get(sc, len);
795 if (m == 0)
796 return (0);
797
798 /* the data comes with frame checksum and ethernet header */
799 m->m_flags |= M_HASFCS;
800
801 #if NBPFILTER > 0
802 if (ifp->if_bpf)
803 bpf_mtap(ifp->if_bpf, m);
804 #endif
805
806 (*ifp->if_input)(ifp, m);
807
808 return (1);
809 }
810
811 static struct mbuf *
812 netdock_get(sc, datalen)
813 struct netdock_softc *sc;
814 int datalen;
815 {
816 struct mbuf *m, *top, **mp;
817 u_char *data;
818 int i;
819 int len;
820 int len4;
821 u_int32_t *data4;
822
823 MGETHDR(m, M_DONTWAIT, MT_DATA);
824 if (m == NULL)
825 return (NULL);
826 m->m_pkthdr.rcvif = &sc->sc_if;
827 m->m_pkthdr.len = datalen;
828 len = MHLEN;
829 top = NULL;
830 mp = ⊤
831
832 while (datalen > 0) {
833 if (top) {
834 MGET(m, M_DONTWAIT, MT_DATA);
835 if (m == 0) {
836 m_freem(top);
837 return (NULL);
838 }
839 len = MLEN;
840 }
841 if (datalen >= MINCLSIZE) {
842 MCLGET(m, M_DONTWAIT);
843 if ((m->m_flags & M_EXT) == 0) {
844 if (top)
845 m_freem(top);
846 return (NULL);
847 }
848 len = MCLBYTES;
849 }
850
851 if (mp == &top) {
852 caddr_t newdata = (caddr_t)
853 ALIGN(m->m_data + sizeof(struct ether_header)) -
854 sizeof(struct ether_header);
855 len -= newdata - m->m_data;
856 m->m_data = newdata;
857 }
858
859 m->m_len = len = min(datalen, len);
860
861 data = mtod(m, u_char *);
862 len4 = len >> 2;
863 data4 = (u_int32_t *)data;
864 for (i = 0; i < len4; i++)
865 data4[i] = NIC_GET_4(sc, REG_DATA);
866 for (i = len4 << 2; i < len; i++)
867 data[i] = NIC_GET_1(sc, REG_DATA);
868
869 datalen -= len;
870 *mp = m;
871 mp = &m->m_next;
872 }
873
874 return (top);
875 }
876