FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/if_zp.c
1 /*
2 * This code is based on
3 * (1) FreeBSD implementation on ISA/EISA Ethelink III by Herb Peyerl
4 * (2) Linux implementation on PCMCIA Etherlink III by Devid Hinds
5 * (3) FreeBSD implementation on PCMCIA IBM Ethernet Card I/II
6 * by David Greenman
7 * (4) RT-Mach implementation on PCMCIA/ISA/EISA Etherlink III
8 * by Seiji Murata
9 *
10 * Copyright (c) by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
11 * Copyright (c) by Seiji Murata <seiji@mt.cs.keio.ac.jp>
12 */
13 /*
14 * Copyright (c) 1993 Herb Peyerl <hpeyerl@novatel.ca>
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 * From: if_ep.c,v 1.9 1994/01/25 10:46:29 deraadt Exp $
37 * $FreeBSD: src/sys/i386/isa/if_zp.c,v 1.26.2.8 1999/09/05 08:13:01 peter Exp $
38 */
39 /*-
40 * TODO:
41 * [1] integrate into current if_ed.c
42 * [2] parse tuples to find out where to map the shared memory buffer,
43 * and what to write into the configuration register
44 * [3] move pcic-specific code into a separate module.
45 *
46 * Device driver for IBM PCMCIA Credit Card Adapter for Ethernet,
47 * if_ze.c
48 *
49 * Based on the Device driver for National Semiconductor DS8390 ethernet
50 * adapters by David Greenman. Modifications for PCMCIA by Keith Moore.
51 * Adapted for FreeBSD 1.1.5 by Jordan Hubbard.
52 *
53 * Currently supports only the IBM Credit Card Adapter for Ethernet, but
54 * could probably work with other PCMCIA cards also, if it were modified
55 * to get the locations of the PCMCIA configuration option register (COR)
56 * by parsing the configuration tuples, rather than by hard-coding in
57 * the value expected by IBM's card.
58 *
59 * Sources for data on the PCMCIA/IBM CCAE specific portions of the driver:
60 *
61 * [1] _Local Area Network Credit Card Adapters Technical Reference_,
62 * IBM Corp., SC30-3585-00, part # 33G9243.
63 * [2] "pre-alpha" PCMCIA support code for Linux by Barry Jaspan.
64 * [3] Intel 82536SL PC Card Interface Controller Data Sheet, Intel
65 * Order Number 290423-002
66 * [4] National Semiconductor DP83902A ST-NIC (tm) Serial Network
67 * Interface Controller for Twisted Pair data sheet.
68 *
69 *
70 * Copyright (C) 1993, David Greenman. This software may be used, modified,
71 * copied, distributed, and sold, in both source and binary form provided
72 * that the above copyright and these terms are retained. Under no
73 * circumstances is the author responsible for the proper functioning
74 * of this software, nor does the author assume any responsibility
75 * for damages incurred with its use.
76 */
77 /*======================================================================
78
79 A PCMCIA ethernet driver for the 3com 3c589 card.
80
81 Written by David Hinds, dhinds@allegro.stanford.edu
82
83 The network driver code is based on Donald Becker's 3c589 code:
84
85 Written 1994 by Donald Becker.
86 Copyright 1993 United States Government as represented by the
87 Director, National Security Agency. This software may be used and
88 distributed according to the terms of the GNU Public License,
89 incorporated herein by reference.
90 Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
91
92 ======================================================================*/
93 /*
94 * I doubled delay loops in this file because it is not enough for some
95 * laptop machines' PCIC (especially, on my Chaplet ILFA 350 ^^;).
96 * HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
97 */
98 /*
99 * Very small patch for IBM Ethernet PCMCIA Card II and IBM ThinkPad230Cs.
100 * ETO, Toshihisa <eto@osl.fujitsu.co.jp>
101 */
102
103 /* XXX - Don't mix different PCCARD support code */
104 #include "card.h"
105 #include "pcic.h"
106 #if NCARD > 0 || NPCIC > 0
107 #ifndef LINT_PCCARD_HACK
108 #error "Dedicated PCMCIA drivers and generic PCMCIA support can't be mixed"
109 #else
110 #warning "Dedicated PCMCIA drivers and generic PCMCIA support can't be mixed"
111 #endif
112 #endif
113
114 #include "zp.h"
115
116 #include "bpfilter.h"
117
118 #include <sys/param.h>
119 #if defined(__FreeBSD__)
120 #include <sys/systm.h>
121 #include <sys/conf.h>
122 #include <sys/kernel.h>
123 #endif
124 #include <sys/mbuf.h>
125 #include <sys/socket.h>
126 #include <sys/ioctl.h>
127 #include <sys/errno.h>
128 #include <sys/syslog.h>
129
130 #include <net/if.h>
131 #include <net/if_dl.h>
132 #include <net/if_types.h>
133
134 #ifdef INET
135 #include <netinet/in.h>
136 #include <netinet/in_systm.h>
137 #include <netinet/in_var.h>
138 #include <netinet/ip.h>
139 #include <netinet/if_ether.h>
140 #endif
141
142 #ifdef IPX
143 #include <netipx/ipx.h>
144 #include <netipx/ipx_if.h>
145 #endif
146
147 #ifdef NS
148 #include <netns/ns.h>
149 #include <netns/ns_if.h>
150 #endif
151
152 #if NBPFILTER > 0
153 #include <net/bpf.h>
154 #include <net/bpfdesc.h>
155 #endif
156
157 #include <machine/clock.h>
158 #include <machine/md_var.h>
159
160 #include <i386/isa/isa_device.h>
161 #include <i386/isa/if_zpreg.h>
162 #include <i386/isa/pcic.h>
163
164 #include "apm.h"
165 #if NAPM > 0
166 #include <machine/apm_bios.h>
167 #endif /* NAPM > 0 */
168
169
170 /*****************************************************************************
171 * Driver for Ethernet Adapter *
172 *****************************************************************************/
173 /*
174 * zp_softc: per line info and status
175 */
176 static struct zp_softc {
177 struct arpcom arpcom; /* Ethernet common part */
178 #define MAX_MBS 8 /* # of mbufs we keep around */
179 struct mbuf *mb[MAX_MBS]; /* spare mbuf storage. */
180 int next_mb; /* Which mbuf to use next. */
181 int last_mb; /* Last mbuf. */
182 int ep_io_addr; /* i/o bus address */
183 char ep_connectors; /* Connectors on this card. */
184 int tx_start_thresh;/* Current TX_start_thresh. */
185 char bus32bit; /* 32bit access possible */
186 u_short if_port;
187 u_char last_alive; /* information for reconfiguration */
188 u_char last_up; /* information for reconfiguration */
189 int slot; /* PCMCIA slot */
190 #if NAPM > 0
191 struct apmhook s_hook; /* reconfiguration support */
192 struct apmhook r_hook; /* reconfiguration support */
193 #endif /* NAPM > 0 */
194 } zp_softc[NZP];
195
196 static int zpprobe __P((struct isa_device *));
197 static int zpattach __P((struct isa_device *));
198 static int zp_suspend __P((void *visa_dev));
199 static int zp_resume __P((void *visa_dev));
200 static int zpioctl __P((struct ifnet * ifp, int, caddr_t));
201 static u_short read_eeprom_data __P((int, int));
202
203 static void zpinit __P((int));
204 static void zpmbuffill __P((void *));
205 static void zpmbufempty __P((struct zp_softc *));
206 static void zpread __P((struct zp_softc *));
207 static void zpreset __P((int));
208 static void zpstart __P((struct ifnet *));
209 static void zpstop __P((int));
210 static void zpwatchdog __P((struct ifnet *));
211
212 struct isa_driver zpdriver = {
213 zpprobe,
214 zpattach,
215 "zp"
216 };
217 #define CARD_INFO "3Com Corporation~3C589"
218
219 static unsigned char card_info[256];
220
221 /*
222 * scan the card information structure looking for the version/product info
223 * tuple. when we find it, compare it to the string we are looking for.
224 * return 1 if we find it, 0 otherwise.
225 */
226
227 static int
228 zp_check_cis(unsigned char *scratch)
229 {
230 int i, j, k;
231
232 card_info[0] = '\0';
233 i = 0;
234 while (scratch[i] != 0xff && i < 1024) {
235 unsigned char link = scratch[i + 2];
236
237 if (scratch[i] == 0x15) {
238 /* level 1 version/product info copy to card_info,
239 * translating '\0' to '~' */
240 k = 0;
241 for (j = i + 8; scratch[j] != 0xff; j += 2)
242 card_info[k++] = scratch[j] == '\0' ? '~' : scratch[j];
243 card_info[k++] = '\0';
244 return (bcmp(card_info, CARD_INFO, sizeof(CARD_INFO) - 1) == 0);
245 }
246 i += 4 + 2 * link;
247 }
248 return 0;
249 }
250 /*
251 * Probe each slot looking for an IBM Credit Card Adapter for Ethernet
252 * For each card that we find, map its card information structure
253 * into system memory at 'scratch' and see whether it's one of ours.
254 * Return the slot number if we find a card, or -1 otherwise.
255 *
256 * Side effects:
257 * + On success, leaves CIS mapped into memory at 'scratch';
258 * caller must free it.
259 * + On success, leaves ethernet address in enet_addr.
260 * + Leaves product/vendor id of last card probed in 'card_info'
261 */
262
263 static int prev_slot = 0;
264
265 static int
266 zp_find_adapter(unsigned char *scratch, int reconfig)
267 {
268 int slot;
269
270 for (slot = prev_slot; slot < MAXSLOT; ++slot) {
271 /* see if there's a PCMCIA controller here Intel PCMCIA
272 * controllers use 0x82 and 0x83 IBM clone chips use 0x88 and
273 * 0x89, apparently */
274 /* IBM ThinkPad230Cs use 0x84. */
275 unsigned char idbyte = pcic_getb(slot, PCIC_ID_REV);
276
277 if (idbyte != 0x82 && idbyte != 0x83 &&
278 idbyte != 0x84 && /* for IBM ThinkPad 230Cs */
279 idbyte != 0x88 && idbyte != 0x89) {
280 continue;
281 }
282 if ((pcic_getb(slot, PCIC_STATUS) & PCIC_CD) != PCIC_CD) {
283 if (!reconfig) {
284 printf("zp: slot %d: no card in slot\n", slot);
285 } else {
286 log(LOG_NOTICE, "zp: slot %d: no card in slot\n", slot);
287 }
288 /* no card in slot */
289 continue;
290 }
291 pcic_power_on(slot);
292 pcic_reset(slot);
293 DELAY(50000);
294 /* map the card's attribute memory and examine its card
295 * information structure tuples for something we recognize. */
296 pcic_map_memory(slot, 0, kvtop(scratch), 0L,
297 0xFFFL, ATTRIBUTE, 1);
298
299 if ((zp_check_cis(scratch)) > 0) {
300 /* found it */
301 if (!reconfig) {
302 printf("zp: found card in slot %d\n", slot);
303 } else {
304 log(LOG_NOTICE, "zp: found card in slot %d\n", slot);
305 }
306 prev_slot = (prev_slot == MAXSLOT - 1) ? 0 : prev_slot + 1;
307
308 return slot;
309 } else {
310 if (!reconfig) {
311 printf("zp: pcmcia slot %d: %s\n", slot, card_info);
312 } else {
313 log(LOG_NOTICE, "zp: pcmcia slot %d: %s\n", slot, card_info);
314 }
315 }
316 pcic_unmap_memory(slot, 0);
317 }
318 prev_slot = 0;
319 return -1;
320 }
321
322
323 /*
324 * macros to handle casting unsigned long to (char *) so we can
325 * read/write into physical memory space.
326 */
327
328 #define PEEK(addr) (*((unsigned char *)(addr)))
329 #define POKE(addr,val) do { PEEK(addr) = (val); } while (0)
330
331 /*
332 * Determine if the device is present
333 *
334 * on entry:
335 * a pointer to an isa_device struct
336 * on exit:
337 * NULL if device not found
338 * or # of i/o addresses used (if found)
339 */
340 static int
341 zpprobe(struct isa_device * isa_dev)
342 {
343 struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
344 int slot;
345 u_short k;
346 int re_init_flag;
347
348 if ((slot = zp_find_adapter(isa_dev->id_maddr, isa_dev->id_reconfig)) < 0)
349 return 0;
350
351 /* okay, we found a card, so set it up */
352 /* Inhibit 16 bit memory delay. POINTETH.SYS apparently does this, for
353 * what reason I don't know. */
354 pcic_putb(slot, PCIC_CDGC,
355 pcic_getb(slot, PCIC_CDGC) | PCIC_16_DL_INH);
356 /* things to map (1) card's EEPROM is already mapped by the
357 * find_adapter routine but we still need to get the card's ethernet
358 * address. after that we unmap that part of attribute memory. (2)
359 * card configuration registers need to be mapped in so we can set the
360 * configuration and socket # registers. (3) shared memory packet
361 * buffer (4) i/o ports (5) IRQ */
362 #ifdef notdef
363 /* Sigh. Location of the ethernet address isn't documented in [1]. It
364 * was derived by doing a hex dump of all of attribute memory and
365 * looking for the IBM vendor prefix. */
366 enet_addr[0] = PEEK(isa_dev->id_maddr + 0xff0);
367 enet_addr[1] = PEEK(isa_dev->id_maddr + 0xff2);
368 enet_addr[2] = PEEK(isa_dev->id_maddr + 0xff4);
369 enet_addr[3] = PEEK(isa_dev->id_maddr + 0xff6);
370 enet_addr[4] = PEEK(isa_dev->id_maddr + 0xff8);
371 enet_addr[5] = PEEK(isa_dev->id_maddr + 0xffa);
372 #endif
373 re_init_flag = 0;
374 re_init:
375 /* (2) map card configuration registers. these are offset in card
376 * memory space by 0x20000. normally we could get this offset from
377 * the card information structure, but I'm too lazy and am not quite
378 * sure if I understand the CIS anyway.
379 *
380 * XXX IF YOU'RE TRYING TO PORT THIS DRIVER FOR A DIFFERENT PCMCIA CARD,
381 * the most likely thing to change is the constant 0x20000 in the next
382 * statement. Oh yes, also change the card id string that we probe
383 * for. */
384 pcic_map_memory(slot, 0, kvtop(isa_dev->id_maddr), 0x10000, 8L,
385 ATTRIBUTE, 1);
386 #if OLD_3C589B_CARDS
387 POKE(isa_dev->id_maddr, 0x80); /* reset the card (how long?) */
388 DELAY(40000);
389 #endif
390 /* Set the configuration index. According to [1], the adapter won't
391 * respond to any i/o signals until we do this; it uses the Memory
392 * Only interface (whatever that is; it's not documented). Also turn
393 * on "level" (not pulse) interrupts.
394 *
395 * XXX probably should init the socket and copy register also, so that we
396 * can deal with multiple instances of the same card. */
397 POKE(isa_dev->id_maddr, 0x41);
398 pcic_unmap_memory(slot, 0);
399
400 /* (4) map i/o ports.
401 *
402 * XXX is it possible that the config file leaves this unspecified, in
403 * which case we have to pick one?
404 *
405 * At least one PCMCIA device driver I'v seen maps a block of 32
406 * consecutive i/o ports as two windows of 16 ports each. Maybe some
407 * other pcic chips are restricted to 16-port windows; the 82365SL
408 * doesn't seem to have that problem. But since we have an extra
409 * window anyway... */
410 pcic_map_io(slot, 0, isa_dev->id_iobase, 16, 2);
411
412 /* (5) configure the card for the desired interrupt
413 *
414 * XXX is it possible that the config file leaves this unspecified? */
415 pcic_map_irq(slot, ffs(isa_dev->id_irq) - 1);
416
417 /* tell the PCIC that this is an I/O card (not memory) */
418 pcic_putb(slot, PCIC_INT_GEN,
419 pcic_getb(slot, PCIC_INT_GEN) | PCIC_CARDTYPE);
420
421 sc->ep_io_addr = isa_dev->id_iobase;
422 GO_WINDOW(0);
423 k = read_eeprom_data(BASE, EEPROM_ADDR_CFG); /* get addr cfg */
424 sc->if_port = k >> 14;
425 k = (k & 0x1f) * 0x10 + 0x200; /* decode base addr. */
426 if (k != (u_short) isa_dev->id_iobase) {
427 if (!re_init_flag) {
428 re_init_flag++;
429 goto re_init;
430 }
431 return (0);
432 }
433 k = read_eeprom_data(BASE, EEPROM_RESOURCE_CFG);
434
435 k >>= 12;
436
437 if (isa_dev->id_irq != (1 << ((k == 2) ? 9 : k)))
438 return (0);
439
440 outb(BASE, ACTIVATE_ADAPTER_TO_CONFIG);
441
442
443 /* information for reconfiguration */
444 sc->last_alive = 0;
445 sc->last_up = 0;
446 sc->slot = slot;
447
448 return (0x10); /* 16 bytes of I/O space used. */
449 }
450 #if NAPM > 0
451 static int
452 zp_suspend(visa_dev)
453 void *visa_dev;
454 {
455 #if 0
456 struct isa_device *isa_dev = visa_dev;
457 struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
458
459 pcic_power_off(sc->slot);
460 #endif
461 return 0;
462 }
463
464 static int
465 zp_resume(visa_dev)
466 void *visa_dev;
467 {
468 struct isa_device *isa_dev = visa_dev;
469
470 prev_slot = 0;
471 reconfig_isadev(isa_dev, &net_imask);
472 return 0;
473 }
474 #endif /* NAPM > 0 */
475
476
477 /*
478 * Install interface into kernel networking data structures
479 */
480
481 static int
482 zpattach(isa_dev)
483 struct isa_device *isa_dev;
484 {
485 struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
486 struct ifnet *ifp = &sc->arpcom.ac_if;
487 u_short i;
488 int pl;
489
490 /* PCMCIA card can be offlined. Reconfiguration is required */
491 if (isa_dev->id_reconfig) {
492 if (!isa_dev->id_alive && sc->last_alive) {
493 pl = splimp();
494 sc->last_up = (ifp->if_flags & IFF_UP);
495 if_down(ifp);
496 splx(pl);
497 sc->last_alive = 0;
498 }
499 if (isa_dev->id_alive && !sc->last_alive) {
500 zpreset(isa_dev->id_unit);
501 if (sc->last_up) {
502 pl = splimp();
503 if_up(ifp);
504 splx(pl);
505 }
506 sc->last_alive = 1;
507 }
508 return 1;
509 } else {
510 sc->last_alive = 1;
511 }
512
513
514 sc->ep_io_addr = isa_dev->id_iobase;
515 printf("zp%d: ", isa_dev->id_unit);
516
517 sc->ep_connectors = 0;
518
519 i = inw(isa_dev->id_iobase + EP_W0_CONFIG_CTRL);
520
521 if (i & IS_AUI) {
522 printf("aui");
523 sc->ep_connectors |= AUI;
524 }
525 if (i & IS_BNC) {
526 if (sc->ep_connectors)
527 printf("/");
528 printf("bnc");
529 sc->ep_connectors |= BNC;
530 }
531 if (i & IS_UTP) {
532 if (sc->ep_connectors)
533 printf("/");
534 printf("utp");
535 sc->ep_connectors |= UTP;
536 }
537 if (!sc->ep_connectors)
538 printf("no connectors!");
539
540 GO_WINDOW(0);
541 {
542 short tmp_addr[3];
543 int i;
544 for (i = 0; i < 3; i++) {
545 tmp_addr[i] = htons(read_eeprom_data(BASE, i));
546 }
547 bcopy(tmp_addr, sc->arpcom.ac_enaddr, 6);
548 }
549
550 printf(" address %6D\n", sc->arpcom.ac_enaddr, ":");
551
552 ifp->if_softc = sc;
553 ifp->if_mtu = ETHERMTU;
554 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
555 ifp->if_unit = isa_dev->id_unit;
556 ifp->if_name = "zp";
557 ifp->if_output = ether_output;
558 ifp->if_start = zpstart;
559 ifp->if_ioctl = zpioctl;
560 ifp->if_watchdog = zpwatchdog;
561 /* Select connector according to board setting. */
562 ifp->if_flags |= IFF_LINK0;
563
564 if_attach(ifp);
565 ether_ifattach(ifp);
566
567 #if NBPFILTER > 0
568 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
569 #endif
570 #if NAPM > 0
571 sc->s_hook.ah_fun = zp_suspend;
572 sc->s_hook.ah_arg = (void *) isa_dev;
573 sc->s_hook.ah_name = "3Com PCMCIA Etherlink III 3C589";
574 sc->s_hook.ah_order = APM_MID_ORDER;
575 apm_hook_establish(APM_HOOK_SUSPEND, &sc->s_hook);
576 sc->r_hook.ah_fun = zp_resume;
577 sc->r_hook.ah_arg = (void *) isa_dev;
578 sc->r_hook.ah_name = "3Com PCMCIA Etherlink III 3C589";
579 sc->r_hook.ah_order = APM_MID_ORDER;
580 apm_hook_establish(APM_HOOK_RESUME, &sc->r_hook);
581 #endif /* NAPM > 0 */
582 return 1;
583 }
584 /*
585 * The order in here seems important. Otherwise we may not receive
586 * interrupts. ?!
587 */
588 static void
589 zpinit(unit)
590 int unit;
591 {
592 register struct zp_softc *sc = &zp_softc[unit];
593 register struct ifnet *ifp = &sc->arpcom.ac_if;
594 int s, i;
595
596 if (ifp->if_addrlist == (struct ifaddr *) 0)
597 return;
598
599 s = splimp();
600 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
601
602 GO_WINDOW(0);
603
604 /* Disable the card */
605 outw(BASE + EP_W0_CONFIG_CTRL, 0);
606
607 /* Enable the card */
608 outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
609
610 GO_WINDOW(2);
611
612 /* Reload the ether_addr. */
613 for (i = 0; i < 6; i++)
614 outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
615
616 outw(BASE + EP_COMMAND, RX_RESET);
617 outw(BASE + EP_COMMAND, TX_RESET);
618
619 /* Window 1 is operating window */
620 GO_WINDOW(1);
621 for (i = 0; i < 31; i++)
622 inb(BASE + EP_W1_TX_STATUS);
623
624 /* get rid of stray intr's */
625 outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
626
627 outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
628 S_TX_COMPLETE | S_TX_AVAIL);
629 outw(BASE + EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
630 S_TX_COMPLETE | S_TX_AVAIL);
631
632 #ifndef IFF_MULTICAST
633 #define IFF_MULTICAST 0x10000
634 #endif
635
636 outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
637 ((sc->arpcom.ac_if.if_flags & IFF_MULTICAST) ? FIL_GROUP : 0) |
638 FIL_BRDCST |
639 ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) ? FIL_ALL : 0));
640 /* you can `ifconfig (link0|-link0) ep0' to get the following
641 * behaviour: -link0 disable AUI/UTP. enable BNC. link0 disable
642 * BNC. enable AUI. if the card has a UTP connector, that is enabled
643 * too. not sure, but it seems you have to be careful to not plug
644 * things into both AUI & UTP. */
645
646 if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) {
647 GO_WINDOW(0);
648 /* set the xcvr */
649 outw(BASE + EP_W0_ADDRESS_CFG, 3 << 14);
650 GO_WINDOW(2);
651 outw(BASE + EP_COMMAND, START_TRANSCEIVER);
652 GO_WINDOW(1);
653 }
654 #if defined(__NetBSD__) || defined(__FreeBSD__)
655 if ((ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & UTP)) {
656 #else
657 if ((ifp->if_flags & IFF_ALTPHYS) && (sc->ep_connectors & UTP)) {
658 #endif
659 GO_WINDOW(4);
660 outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
661 GO_WINDOW(1);
662 }
663 outw(BASE + EP_COMMAND, RX_ENABLE);
664 outw(BASE + EP_COMMAND, TX_ENABLE);
665
666 ifp->if_flags |= IFF_RUNNING;
667 ifp->if_flags &= ~IFF_OACTIVE; /* just in case */
668 sc->tx_start_thresh = 20; /* probably a good starting point. */
669 /* Store up a bunch of mbuf's for use later. (MAX_MBS). First we free
670 * up any that we had in case we're being called from intr or
671 * somewhere else. */
672 sc->last_mb = 0;
673 sc->next_mb = 0;
674 zpmbuffill(sc);
675 zpstart(ifp);
676 splx(s);
677 }
678
679 static const char padmap[] = {0, 3, 2, 1};
680 static void
681 zpstart(ifp)
682 struct ifnet *ifp;
683 {
684 register struct zp_softc *sc = ifp->if_softc;
685 struct mbuf *m, *top;
686
687 int s, len, pad;
688
689 s = splimp();
690
691 if (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) {
692 splx(s);
693 return;
694 }
695 startagain:
696
697 /* Sneak a peek at the next packet */
698 m = sc->arpcom.ac_if.if_snd.ifq_head;
699 if (m == 0) {
700 splx(s);
701 return;
702 }
703 for (len = 0, top = m; m; m = m->m_next)
704 len += m->m_len;
705
706 pad = padmap[len & 3];
707
708 /* The 3c509 automatically pads short packets to minimum ethernet
709 * length, but we drop packets that are too large. Perhaps we should
710 * truncate them instead? */
711 if (len + pad > ETHER_MAX_LEN) {
712 /* packet is obviously too large: toss it */
713 ++sc->arpcom.ac_if.if_oerrors;
714 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
715 m_freem(m);
716 goto readcheck;
717 }
718 if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
719 /* no room in FIFO */
720 outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
721 sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
722 splx(s);
723
724 return;
725 }
726 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
727
728 if (m == 0) { /* not really needed */
729 splx(s);
730 return;
731 }
732 outw(BASE + EP_COMMAND, SET_TX_START_THRESH |
733 (len / 4 + sc->tx_start_thresh));
734
735 outw(BASE + EP_W1_TX_PIO_WR_1, len);
736 outw(BASE + EP_W1_TX_PIO_WR_1, 0xffff); /* Second dword meaningless */
737
738 for (top = m; m != 0; m = m->m_next) {
739 if (sc->bus32bit) {
740 outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
741 m->m_len / 4);
742 if (m->m_len & 3)
743 outsb(BASE + EP_W1_TX_PIO_WR_1,
744 mtod(m, caddr_t) + (m->m_len & (~3)),
745 m->m_len & 3);
746 } else {
747 outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 2);
748 if (m->m_len & 1)
749 outb(BASE + EP_W1_TX_PIO_WR_1,
750 *(mtod(m, caddr_t) + m->m_len - 1));
751 }
752 }
753 while (pad--)
754 outb(BASE + EP_W1_TX_PIO_WR_1, 0); /* Padding */
755
756 #if NBPFILTER > 0
757 if (sc->arpcom.ac_if.if_bpf) {
758 bpf_mtap(&sc->arpcom.ac_if, top);
759 }
760 #endif
761
762 m_freem(top);
763 ++sc->arpcom.ac_if.if_opackets;
764 /* Is another packet coming in? We don't want to overflow the tiny RX
765 * fifo. */
766 readcheck:
767 if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
768 splx(s);
769 return;
770 }
771 goto startagain;
772 }
773 void
774 zpintr(unit)
775 int unit;
776 {
777 int status, i;
778 register struct zp_softc *sc = &zp_softc[unit];
779
780 struct ifnet *ifp = &sc->arpcom.ac_if;
781
782
783 status = 0;
784 checkintr:
785 status = inw(BASE + EP_STATUS) &
786 (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE | S_CARD_FAILURE);
787 checkintr2:
788 if (status == 0) {
789 /* No interrupts. */
790 outw(BASE + EP_COMMAND, C_INTR_LATCH);
791
792 status = inw(BASE + EP_STATUS) &
793 (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE |
794 S_CARD_FAILURE);
795 if (status)
796 goto checkintr2;
797
798 return;
799 }
800 /* important that we do this first. */
801 outw(BASE + EP_COMMAND, ACK_INTR | status);
802
803 if (status & S_TX_AVAIL) {
804 status &= ~S_TX_AVAIL;
805 inw(BASE + EP_W1_FREE_TX);
806 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
807 zpstart(&sc->arpcom.ac_if);
808
809 }
810 if (status & S_RX_COMPLETE) {
811 status &= ~S_RX_COMPLETE;
812 zpread(sc);
813 }
814 if (status & S_CARD_FAILURE) {
815 printf("zp%d: reset (status: %x)\n", unit, status);
816 outw(BASE + EP_COMMAND, C_INTR_LATCH);
817 zpinit(unit);
818 return;
819 }
820 if (status & S_TX_COMPLETE) {
821 status &= ~S_TX_COMPLETE;
822 /* We need to read TX_STATUS until we get a 0 status in order
823 * to turn off the interrupt flag. */
824 while ((i = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
825 outw(BASE + EP_W1_TX_STATUS, 0x0);
826 if (i & (TXS_MAX_COLLISION | TXS_JABBER | TXS_UNDERRUN)) {
827 if (i & TXS_MAX_COLLISION)
828 ++sc->arpcom.ac_if.if_collisions;
829 if (i & (TXS_JABBER | TXS_UNDERRUN)) {
830 outw(BASE + EP_COMMAND, TX_RESET);
831 if (i & TXS_UNDERRUN) {
832 if (sc->tx_start_thresh < ETHER_MAX_LEN) {
833 sc->tx_start_thresh += 20;
834 outw(BASE + EP_COMMAND,
835 SET_TX_START_THRESH |
836 sc->tx_start_thresh);
837 }
838 }
839 }
840 outw(BASE + EP_COMMAND, TX_ENABLE);
841 ++sc->arpcom.ac_if.if_oerrors;
842 }
843 }
844 zpstart(ifp);
845 }
846 goto checkintr;
847 }
848
849 static void
850 zpread(sc)
851 register struct zp_softc *sc;
852 {
853 struct ether_header *eh;
854 struct mbuf *mcur, *m, *m0, *top;
855 int totlen, lenthisone;
856 int save_totlen;
857 int off;
858
859
860 totlen = inw(BASE + EP_W1_RX_STATUS);
861 off = 0;
862 top = 0;
863
864 if (totlen & ERR_RX) {
865 ++sc->arpcom.ac_if.if_ierrors;
866 goto out;
867 }
868 save_totlen = totlen &= RX_BYTES_MASK; /* Lower 11 bits = RX bytes. */
869
870 m = sc->mb[sc->next_mb];
871 sc->mb[sc->next_mb] = 0;
872
873 if (m == 0) {
874 MGETHDR(m, M_DONTWAIT, MT_DATA);
875 if (m == 0)
876 goto out;
877 } else {
878 /* Convert one of our saved mbuf's */
879 sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
880 m->m_data = m->m_pktdat;
881 m->m_flags = M_PKTHDR;
882 }
883
884 top = m0 = m; /* We assign top so we can "goto out" */
885 #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
886 #define EOFF (EROUND - sizeof(struct ether_header))
887 m0->m_data += EOFF;
888 /* Read what should be the header. */
889 insw(BASE + EP_W1_RX_PIO_RD_1,
890 mtod(m0, caddr_t), sizeof(struct ether_header) / 2);
891 m->m_len = sizeof(struct ether_header);
892 totlen -= sizeof(struct ether_header);
893 /* mostly deal with trailer here. (untested) We do this in a couple
894 * of parts. First we check for a trailer, if we have one we convert
895 * the mbuf back to a regular mbuf and set the offset and subtract
896 * sizeof(struct ether_header) from the pktlen. After we've read the
897 * packet off the interface (all except for the trailer header, we
898 * then get a header mbuf, read the trailer into it, and fix up the
899 * mbuf pointer chain. */
900 eh = mtod(m, struct ether_header *);
901 while (totlen > 0) {
902 lenthisone = min(totlen, M_TRAILINGSPACE(m));
903 if (lenthisone == 0) { /* no room in this one */
904 mcur = m;
905 m = sc->mb[sc->next_mb];
906 sc->mb[sc->next_mb] = 0;
907 if (!m) {
908 MGET(m, M_DONTWAIT, MT_DATA);
909 if (m == 0)
910 goto out;
911 } else {
912 timeout(zpmbuffill, sc, 0);
913 sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
914 }
915 if (totlen >= MINCLSIZE)
916 MCLGET(m, M_DONTWAIT);
917 m->m_len = 0;
918 mcur->m_next = m;
919 lenthisone = min(totlen, M_TRAILINGSPACE(m));
920 }
921 if (sc->bus32bit) {
922 insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
923 lenthisone / 4);
924 m->m_len += (lenthisone & ~3);
925 if (lenthisone & 3)
926 insb(BASE + EP_W1_RX_PIO_RD_1,
927 mtod(m, caddr_t) + m->m_len,
928 lenthisone & 3);
929 m->m_len += (lenthisone & 3);
930 } else {
931 insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
932 lenthisone / 2);
933 m->m_len += lenthisone;
934 if (lenthisone & 1)
935 *(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
936 }
937 totlen -= lenthisone;
938 }
939 if (off) {
940 top = sc->mb[sc->next_mb];
941 sc->mb[sc->next_mb] = 0;
942 if (top == 0) {
943 MGETHDR(m, M_DONTWAIT, MT_DATA);
944 if (top == 0) {
945 top = m0;
946 goto out;
947 }
948 } else {
949 /* Convert one of our saved mbuf's */
950 sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
951 top->m_data = top->m_pktdat;
952 top->m_flags = M_PKTHDR;
953 }
954 insw(BASE + EP_W1_RX_PIO_RD_1, mtod(top, caddr_t),
955 sizeof(struct ether_header));
956 top->m_next = m0;
957 top->m_len = sizeof(struct ether_header);
958 /* XXX Accomodate for type and len from beginning of trailer */
959 top->m_pkthdr.len = save_totlen - (2 * sizeof(u_short));
960 } else {
961 top = m0;
962 top->m_pkthdr.len = save_totlen;
963 }
964
965 top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
966 outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
967 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
968 ++sc->arpcom.ac_if.if_ipackets;
969 #if NBPFILTER > 0
970 if (sc->arpcom.ac_if.if_bpf) {
971 bpf_mtap(&sc->arpcom.ac_if, top);
972
973 /* Note that the interface cannot be in promiscuous mode if
974 * there are no BPF listeners. And if we are in promiscuous
975 * mode, we have to check if this packet is really ours. */
976 if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
977 (eh->ether_dhost[0] & 1) == 0 &&
978 bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
979 sizeof(eh->ether_dhost)) != 0 &&
980 bcmp(eh->ether_dhost, etherbroadcastaddr,
981 sizeof(eh->ether_dhost)) != 0) {
982 m_freem(top);
983 return;
984 }
985 }
986 #endif
987 m_adj(top, sizeof(struct ether_header));
988 ether_input(&sc->arpcom.ac_if, eh, top);
989 return;
990
991 out: outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
992 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
993 if (top)
994 m_freem(top);
995
996 }
997
998
999 /*
1000 * Look familiar?
1001 */
1002 static int
1003 zpioctl(ifp, cmd, data)
1004 register struct ifnet *ifp;
1005 int cmd;
1006 caddr_t data;
1007 {
1008 register struct ifaddr *ifa = (struct ifaddr *) data;
1009 struct zp_softc *sc = ifp->if_softc;
1010 int error = 0;
1011
1012
1013 switch (cmd) {
1014 case SIOCSIFADDR:
1015 ifp->if_flags |= IFF_UP;
1016 switch (ifa->ifa_addr->sa_family) {
1017 #ifdef INET
1018 case AF_INET:
1019 zpinit(ifp->if_unit); /* before arpwhohas */
1020 arp_ifinit((struct arpcom *) ifp, ifa);
1021 break;
1022 #endif
1023 #ifdef IPX
1024 case AF_IPX:
1025 {
1026 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
1027
1028 if (ipx_nullhost(*ina))
1029 ina->x_host =
1030 *(union ipx_host *) (sc->arpcom.ac_enaddr);
1031 else {
1032 ifp->if_flags &= ~IFF_RUNNING;
1033 bcopy((caddr_t) ina->x_host.c_host,
1034 (caddr_t) sc->arpcom.ac_enaddr,
1035 sizeof(sc->arpcom.ac_enaddr));
1036 }
1037 zpinit(ifp->if_unit);
1038 break;
1039 }
1040 #endif
1041 #ifdef NS
1042 case AF_NS:
1043 {
1044 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
1045
1046 if (ns_nullhost(*ina))
1047 ina->x_host =
1048 *(union ns_host *) (sc->arpcom.ac_enaddr);
1049 else {
1050 ifp->if_flags &= ~IFF_RUNNING;
1051 bcopy((caddr_t) ina->x_host.c_host,
1052 (caddr_t) sc->arpcom.ac_enaddr,
1053 sizeof(sc->arpcom.ac_enaddr));
1054 }
1055 zpinit(ifp->if_unit);
1056 break;
1057 }
1058 #endif
1059 default:
1060 zpinit(ifp->if_unit);
1061 break;
1062 }
1063 break;
1064 case SIOCSIFFLAGS:
1065 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
1066 ifp->if_flags &= ~IFF_RUNNING;
1067 zpstop(ifp->if_unit);
1068 zpmbufempty(sc);
1069 break;
1070 }
1071 zpinit(ifp->if_unit);
1072 break;
1073 default:
1074 error = EINVAL;
1075 }
1076 return (error);
1077 }
1078
1079 static void
1080 zpreset(unit)
1081 int unit;
1082 {
1083 int s = splimp();
1084
1085 zpstop(unit);
1086 zpinit(unit);
1087 splx(s);
1088 }
1089
1090 static void
1091 zpwatchdog(ifp)
1092 struct ifnet *ifp;
1093 {
1094 log(LOG_ERR, "zp%d: watchdog\n", ifp->if_unit);
1095 ifp->if_oerrors++;
1096 zpreset(ifp->if_unit);
1097 }
1098
1099 static void
1100 zpstop(unit)
1101 int unit;
1102 {
1103 struct zp_softc *sc = &zp_softc[unit];
1104
1105 outw(BASE + EP_COMMAND, RX_DISABLE);
1106 outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1107 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1108 outw(BASE + EP_COMMAND, TX_DISABLE);
1109 outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
1110 outw(BASE + EP_COMMAND, RX_RESET);
1111 outw(BASE + EP_COMMAND, TX_RESET);
1112 outw(BASE + EP_COMMAND, C_INTR_LATCH);
1113 outw(BASE + EP_COMMAND, SET_RD_0_MASK);
1114 outw(BASE + EP_COMMAND, SET_INTR_MASK);
1115 outw(BASE + EP_COMMAND, SET_RX_FILTER);
1116 }
1117
1118
1119
1120 static u_short
1121 read_eeprom_data(id_port, offset)
1122 int id_port;
1123 int offset;
1124 {
1125
1126 outb(id_port + 10, 0x80 + offset);
1127 DELAY(1000);
1128 return inw(id_port + 12);
1129 }
1130
1131
1132
1133
1134 static void
1135 zpmbuffill(sp)
1136 void *sp;
1137 {
1138 struct zp_softc *sc = (struct zp_softc *) sp;
1139 int s, i;
1140
1141 s = splimp();
1142 i = sc->last_mb;
1143 do {
1144 if (sc->mb[i] == NULL)
1145 MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
1146 if (sc->mb[i] == NULL)
1147 break;
1148 i = (i + 1) % MAX_MBS;
1149 } while (i != sc->next_mb);
1150 sc->last_mb = i;
1151 splx(s);
1152 }
1153
1154 static void
1155 zpmbufempty(sc)
1156 struct zp_softc *sc;
1157 {
1158 int s, i;
1159
1160 s = splimp();
1161 for (i = 0; i < MAX_MBS; i++) {
1162 if (sc->mb[i]) {
1163 m_freem(sc->mb[i]);
1164 sc->mb[i] = NULL;
1165 }
1166 }
1167 sc->last_mb = sc->next_mb = 0;
1168 untimeout(zpmbuffill, sc);
1169 splx(s);
1170 }
Cache object: be6e77b1ba49fef0a1a53fe7149178e8
|