]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/isa/if_zp.c
This commit was generated by cvs2svn to compensate for changes in r53142,
[FreeBSD/FreeBSD.git] / 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 David 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$
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 #include "opt_lint.h"
108 #ifdef COMPILING_LINT
109 static char const zpdummy[] = "code to use the includes of card.h and pcic.h";
110 #else
111 #error "Dedicated PCMCIA drivers and generic PCMCIA support can't be mixed"
112 #endif
113 #endif
114
115 #include "zp.h"
116
117 #include "opt_inet.h"
118 #include "opt_ipx.h"
119
120 #include <sys/param.h>
121 #if defined(__FreeBSD__)
122 #include <sys/systm.h>
123 #include <sys/conf.h>
124 #endif
125 #include <sys/mbuf.h>
126 #include <sys/socket.h>
127 #include <sys/sockio.h>
128 #include <sys/syslog.h>
129
130 #include <net/ethernet.h>
131 #include <net/if.h>
132
133 #include <netinet/in.h>
134 #include <netinet/if_ether.h>
135
136 #include <net/bpf.h>
137
138 #include <machine/clock.h>
139 #include <machine/md_var.h>
140
141 #include <i386/isa/isa_device.h>
142 #include <i386/isa/if_zpreg.h>
143 #include <i386/isa/pcic.h>
144
145 #include "apm.h"
146 #if NAPM > 0
147 #include <machine/apm_bios.h>
148 #endif                          /* NAPM > 0 */
149
150
151 /*****************************************************************************
152  *                       Driver for Ethernet Adapter                         *
153  *****************************************************************************/
154 /*
155  * zp_softc: per line info and status
156  */
157 static struct zp_softc {
158         struct arpcom arpcom;   /* Ethernet common part          */
159 #define MAX_MBS  8              /* # of mbufs we keep around     */
160         struct mbuf *mb[MAX_MBS];       /* spare mbuf storage.           */
161         int     next_mb;        /* Which mbuf to use next.       */
162         int     last_mb;        /* Last mbuf.                    */
163         int     ep_io_addr;     /* i/o bus address               */
164         char    ep_connectors;  /* Connectors on this card.      */
165         int     tx_start_thresh;/* Current TX_start_thresh.      */
166         char    bus32bit;       /* 32bit access possible         */
167         u_short if_port;
168         u_char  last_alive;     /* information for reconfiguration */
169         u_char  last_up;        /* information for reconfiguration */
170         int     slot;           /* PCMCIA slot */
171         struct  callout_handle ch; /* Callout handle for timeouts  */
172         int     buffill_pending;
173 #if NAPM >              0
174         struct apmhook s_hook;  /* reconfiguration support */
175         struct apmhook r_hook;  /* reconfiguration support */
176 #endif                          /* NAPM > 0 */
177 }       zp_softc[NZP];
178
179 static int zpprobe __P((struct isa_device *));
180 static int zpattach __P((struct isa_device *));
181 static int zp_suspend __P((void *visa_dev));
182 static int zp_resume __P((void *visa_dev));
183 static int zpioctl __P((struct ifnet * ifp, u_long, caddr_t));
184 static u_short read_eeprom_data __P((int, int));
185
186 static void zpinit __P((int));
187 static ointhand2_t zpintr;
188 static void zpmbuffill __P((void *));
189 static void zpmbufempty __P((struct zp_softc *));
190 static void zpread __P((struct zp_softc *));
191 static void zpreset __P((int));
192 static void zpstart __P((struct ifnet *));
193 static void zpstop __P((int));
194 static void zpwatchdog __P((struct ifnet *));
195
196 struct isa_driver zpdriver = {
197         zpprobe,
198         zpattach,
199         "zp"
200 };
201 #define CARD_INFO  "3Com Corporation~3C589"
202
203 static unsigned char card_info[256];
204
205 /*
206  * scan the card information structure looking for the version/product info
207  * tuple.  when we find it, compare it to the string we are looking for.
208  * return 1 if we find it, 0 otherwise.
209  */
210
211 static int
212 zp_check_cis(unsigned char *scratch)
213 {
214         int     i, j, k;
215
216         card_info[0] = '\0';
217         i = 0;
218         while (scratch[i] != 0xff && i < 1024) {
219                 unsigned char link = scratch[i + 2];
220
221                 if (scratch[i] == 0x15) {
222                         /* level 1 version/product info copy to card_info,
223                          * translating '\0' to '~' */
224                         k = 0;
225                         for (j = i + 8; scratch[j] != 0xff; j += 2)
226                                 card_info[k++] = scratch[j] == '\0' ? '~' : scratch[j];
227                         card_info[k++] = '\0';
228                         return (bcmp(card_info, CARD_INFO, sizeof(CARD_INFO) - 1) == 0);
229                 }
230                 i += 4 + 2 * link;
231         }
232         return 0;
233 }
234 /*
235  * Probe each slot looking for an IBM Credit Card Adapter for Ethernet
236  * For each card that we find, map its card information structure
237  * into system memory at 'scratch' and see whether it's one of ours.
238  * Return the slot number if we find a card, or -1 otherwise.
239  *
240  * Side effects:
241  * + On success, leaves CIS mapped into memory at 'scratch';
242  *   caller must free it.
243  * + On success, leaves ethernet address in enet_addr.
244  * + Leaves product/vendor id of last card probed in 'card_info'
245  */
246
247 static int     prev_slot = 0;
248
249 static int
250 zp_find_adapter(unsigned char *scratch, int reconfig)
251 {
252         int     slot;
253
254         for (slot = prev_slot; slot < MAXSLOT; ++slot) {
255                 /* see if there's a PCMCIA controller here Intel PCMCIA
256                  * controllers use 0x82 and 0x83 IBM clone chips use 0x88 and
257                  * 0x89, apparently */
258                 /* IBM ThinkPad230Cs use 0x84. */
259                 unsigned char idbyte = pcic_getb(slot, PCIC_ID_REV);
260
261                 if (idbyte != 0x82 && idbyte != 0x83 &&
262                     idbyte != 0x84 &&   /* for IBM ThinkPad 230Cs */
263                     idbyte != 0x88 && idbyte != 0x89) {
264                         continue;
265                 }
266                 if ((pcic_getb(slot, PCIC_STATUS) & PCIC_CD) != PCIC_CD) {
267                         if (!reconfig) {
268                                 printf("zp: slot %d: no card in slot\n", slot);
269                         } else {
270                                 log(LOG_NOTICE, "zp: slot %d: no card in slot\n", slot);
271                         }
272                         /* no card in slot */
273                         continue;
274                 }
275                 pcic_power_on(slot);
276                 pcic_reset(slot);
277                 DELAY(50000);
278                 /* map the card's attribute memory and examine its card
279                  * information structure tuples for something we recognize. */
280                 pcic_map_memory(slot, 0, kvtop(scratch), 0L,
281                     0xFFFL, ATTRIBUTE, 1);
282
283                 if ((zp_check_cis(scratch)) > 0) {
284                         /* found it */
285                         if (!reconfig) {
286                                 printf("zp: found card in slot %d\n", slot);
287                         } else {
288                                 log(LOG_NOTICE, "zp: found card in slot %d\n", slot);
289                         }
290                         prev_slot = (prev_slot == MAXSLOT - 1) ? 0 : prev_slot + 1;
291
292                         return slot;
293                 } else {
294                         if (!reconfig) {
295                                 printf("zp: pcmcia slot %d: %s\n", slot, card_info);
296                         } else {
297                                 log(LOG_NOTICE, "zp: pcmcia slot %d: %s\n", slot, card_info);
298                         }
299                 }
300                 pcic_unmap_memory(slot, 0);
301         }
302         prev_slot = 0;
303         return -1;
304 }
305
306
307 /*
308  * macros to handle casting unsigned long to (char *) so we can
309  * read/write into physical memory space.
310  */
311
312 #define PEEK(addr) (*((unsigned char *)(addr)))
313 #define POKE(addr,val) do { PEEK(addr) = (val); } while (0)
314
315 /*
316  * Determine if the device is present
317  *
318  *   on entry:
319  *      a pointer to an isa_device struct
320  *   on exit:
321  *      NULL if device not found
322  *      or # of i/o addresses used (if found)
323  */
324 static int
325 zpprobe(struct isa_device * isa_dev)
326 {
327         struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
328         int     slot;
329         u_short k;
330         int     re_init_flag;
331
332         if ((slot = zp_find_adapter(isa_dev->id_maddr, isa_dev->id_reconfig)) < 0)
333                 return 0;
334
335         /* okay, we found a card, so set it up */
336         /* Inhibit 16 bit memory delay. POINTETH.SYS apparently does this, for
337          * what reason I don't know. */
338         pcic_putb(slot, PCIC_CDGC,
339             pcic_getb(slot, PCIC_CDGC) | PCIC_16_DL_INH);
340         /* things to map (1) card's EEPROM is already mapped by the
341          * find_adapter routine but we still need to get the card's ethernet
342          * address. after that we unmap that part of attribute memory. (2)
343          * card configuration registers need to be mapped in so we can set the
344          * configuration and socket # registers. (3) shared memory packet
345          * buffer (4) i/o ports (5) IRQ */
346 #ifdef  notdef
347         /* Sigh.  Location of the ethernet address isn't documented in [1]. It
348          * was derived by doing a hex dump of all of attribute memory and
349          * looking for the IBM vendor prefix. */
350         enet_addr[0] = PEEK(isa_dev->id_maddr + 0xff0);
351         enet_addr[1] = PEEK(isa_dev->id_maddr + 0xff2);
352         enet_addr[2] = PEEK(isa_dev->id_maddr + 0xff4);
353         enet_addr[3] = PEEK(isa_dev->id_maddr + 0xff6);
354         enet_addr[4] = PEEK(isa_dev->id_maddr + 0xff8);
355         enet_addr[5] = PEEK(isa_dev->id_maddr + 0xffa);
356 #endif
357         re_init_flag = 0;
358 re_init:
359         /* (2) map card configuration registers.  these are offset in card
360          * memory space by 0x20000.  normally we could get this offset from
361          * the card information structure, but I'm too lazy and am not quite
362          * sure if I understand the CIS anyway.
363          * 
364          * XXX IF YOU'RE TRYING TO PORT THIS DRIVER FOR A DIFFERENT PCMCIA CARD,
365          * the most likely thing to change is the constant 0x20000 in the next
366          * statement.  Oh yes, also change the card id string that we probe
367          * for. */
368         pcic_map_memory(slot, 0, kvtop(isa_dev->id_maddr), 0x10000, 8L,
369             ATTRIBUTE, 1);
370 #if OLD_3C589B_CARDS
371         POKE(isa_dev->id_maddr, 0x80);  /* reset the card (how long?) */
372         DELAY(40000);
373 #endif
374         /* Set the configuration index.  According to [1], the adapter won't
375          * respond to any i/o signals until we do this; it uses the Memory
376          * Only interface (whatever that is; it's not documented). Also turn
377          * on "level" (not pulse) interrupts.
378          * 
379          * XXX probably should init the socket and copy register also, so that we
380          * can deal with multiple instances of the same card. */
381         POKE(isa_dev->id_maddr, 0x41);
382         pcic_unmap_memory(slot, 0);
383
384         /* (4) map i/o ports.
385          * 
386          * XXX is it possible that the config file leaves this unspecified, in
387          * which case we have to pick one?
388          * 
389          * At least one PCMCIA device driver I'v seen maps a block of 32
390          * consecutive i/o ports as two windows of 16 ports each. Maybe some
391          * other pcic chips are restricted to 16-port windows; the 82365SL
392          * doesn't seem to have that problem.  But since we have an extra
393          * window anyway... */
394         pcic_map_io(slot, 0, isa_dev->id_iobase, 16, 2);
395
396         /* (5) configure the card for the desired interrupt
397          * 
398          * XXX is it possible that the config file leaves this unspecified? */
399         pcic_map_irq(slot, ffs(isa_dev->id_irq) - 1);
400
401         /* tell the PCIC that this is an I/O card (not memory) */
402         pcic_putb(slot, PCIC_INT_GEN,
403             pcic_getb(slot, PCIC_INT_GEN) | PCIC_CARDTYPE);
404
405         sc->ep_io_addr = isa_dev->id_iobase;
406         GO_WINDOW(0);
407         k = read_eeprom_data(BASE, EEPROM_ADDR_CFG);    /* get addr cfg */
408         sc->if_port = k >> 14;
409         k = (k & 0x1f) * 0x10 + 0x200;  /* decode base addr. */
410         if (k != (u_short) isa_dev->id_iobase) {
411                 if (!re_init_flag) {
412                         re_init_flag++;
413                         goto re_init;
414                 }
415                 return (0);
416         }
417         k = read_eeprom_data(BASE, EEPROM_RESOURCE_CFG);
418
419         k >>= 12;
420
421         if (isa_dev->id_irq != (1 << ((k == 2) ? 9 : k)))
422                 return (0);
423
424         outb(BASE, ACTIVATE_ADAPTER_TO_CONFIG);
425
426
427         /* information for reconfiguration */
428         sc->last_alive = 0;
429         sc->last_up = 0;
430         sc->slot = slot;
431
432         return (0x10);          /* 16 bytes of I/O space used. */
433 }
434 #if NAPM > 0
435 static int
436 zp_suspend(visa_dev)
437         void   *visa_dev;
438 {
439 #if 0
440         struct isa_device *isa_dev = visa_dev;
441         struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
442
443         pcic_power_off(sc->slot);
444 #endif
445         return 0;
446 }
447
448 static int
449 zp_resume(visa_dev)
450         void   *visa_dev;
451 {
452         struct isa_device *isa_dev = visa_dev;
453
454         prev_slot = 0;
455         reconfig_isadev(isa_dev, &net_imask);
456         return 0;
457 }
458 #endif                          /* NAPM > 0 */
459
460
461 /*
462  * Install interface into kernel networking data structures
463  */
464
465 static int
466 zpattach(isa_dev)
467         struct isa_device *isa_dev;
468 {
469         struct zp_softc *sc = &zp_softc[isa_dev->id_unit];
470         struct ifnet *ifp = &sc->arpcom.ac_if;
471         u_short i;
472         int     pl;
473
474         isa_dev->id_ointr = zpintr;
475
476         /* PCMCIA card can be offlined. Reconfiguration is required */
477         if (isa_dev->id_reconfig) {
478                 if (!isa_dev->id_alive && sc->last_alive) {
479                         pl = splimp();
480                         sc->last_up = (ifp->if_flags & IFF_UP);
481                         if_down(ifp);
482                         splx(pl);
483                         sc->last_alive = 0;
484                 }
485                 if (isa_dev->id_alive && !sc->last_alive) {
486                         zpreset(isa_dev->id_unit);
487                         if (sc->last_up) {
488                                 pl = splimp();
489                                 if_up(ifp);
490                                 splx(pl);
491                         }
492                         sc->last_alive = 1;
493                 }
494                 return 1;
495         } else {
496                 sc->last_alive = 1;
497         }
498
499
500         sc->ep_io_addr = isa_dev->id_iobase;
501         printf("zp%d: ", isa_dev->id_unit);
502
503         sc->buffill_pending = 0;
504         callout_handle_init(&sc->ch);
505
506         sc->ep_connectors = 0;
507
508         i = inw(isa_dev->id_iobase + EP_W0_CONFIG_CTRL);
509
510         if (i & IS_AUI) {
511                 printf("aui");
512                 sc->ep_connectors |= AUI;
513         }
514         if (i & IS_BNC) {
515                 if (sc->ep_connectors)
516                         printf("/");
517                 printf("bnc");
518                 sc->ep_connectors |= BNC;
519         }
520         if (i & IS_UTP) {
521                 if (sc->ep_connectors)
522                         printf("/");
523                 printf("utp");
524                 sc->ep_connectors |= UTP;
525         }
526         if (!sc->ep_connectors)
527                 printf("no connectors!");
528
529         GO_WINDOW(0);
530         {
531                 short   tmp_addr[3];
532                 int     j;
533                 for (j = 0; j < 3; j++) {
534                         tmp_addr[j] = htons(read_eeprom_data(BASE, j));
535                 }
536                 bcopy(tmp_addr, sc->arpcom.ac_enaddr, 6);
537         }
538
539         printf(" address %6D\n", sc->arpcom.ac_enaddr, ":");
540
541         sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
542         ifp->if_softc = sc;
543         ifp->if_mtu = ETHERMTU;
544         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
545         ifp->if_unit = isa_dev->id_unit;
546         ifp->if_name = "zp";
547         ifp->if_output = ether_output;
548         ifp->if_start = zpstart;
549         ifp->if_ioctl = zpioctl;
550         ifp->if_watchdog = zpwatchdog;
551         /* Select connector according to board setting. */
552         ifp->if_flags |= IFF_LINK0;
553
554         if_attach(ifp);
555         ether_ifattach(ifp);
556
557         bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
558 #if NAPM > 0
559         sc->s_hook.ah_fun = zp_suspend;
560         sc->s_hook.ah_arg = (void *) isa_dev;
561         sc->s_hook.ah_name = "3Com PCMCIA Etherlink III 3C589";
562         sc->s_hook.ah_order = APM_MID_ORDER;
563         apm_hook_establish(APM_HOOK_SUSPEND, &sc->s_hook);
564         sc->r_hook.ah_fun = zp_resume;
565         sc->r_hook.ah_arg = (void *) isa_dev;
566         sc->r_hook.ah_name = "3Com PCMCIA Etherlink III 3C589";
567         sc->r_hook.ah_order = APM_MID_ORDER;
568         apm_hook_establish(APM_HOOK_RESUME, &sc->r_hook);
569 #endif                          /* NAPM > 0 */
570         return 1;
571 }
572 /*
573  * The order in here seems important. Otherwise we may not receive
574  * interrupts. ?!
575  */
576 static void
577 zpinit(unit)
578         int     unit;
579 {
580         register struct zp_softc *sc = &zp_softc[unit];
581         register struct ifnet *ifp = &sc->arpcom.ac_if;
582         int     s, i;
583
584         if (TAILQ_EMPTY(&ifp->if_addrhead)) /* XXX unlikely */
585                 return;
586
587         s = splimp();
588         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
589
590         GO_WINDOW(0);
591
592         /* Disable the card */
593         outw(BASE + EP_W0_CONFIG_CTRL, 0);
594
595         /* Enable the card */
596         outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
597
598         GO_WINDOW(2);
599
600         /* Reload the ether_addr. */
601         for (i = 0; i < 6; i++)
602                 outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
603
604         outw(BASE + EP_COMMAND, RX_RESET);
605         outw(BASE + EP_COMMAND, TX_RESET);
606
607         /* Window 1 is operating window */
608         GO_WINDOW(1);
609         for (i = 0; i < 31; i++)
610                 inb(BASE + EP_W1_TX_STATUS);
611
612         /* get rid of stray intr's */
613         outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
614
615         outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
616             S_TX_COMPLETE | S_TX_AVAIL);
617         outw(BASE + EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
618             S_TX_COMPLETE | S_TX_AVAIL);
619
620 #ifndef IFF_MULTICAST
621 #define IFF_MULTICAST   0x10000
622 #endif
623
624         outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
625             ((sc->arpcom.ac_if.if_flags & IFF_MULTICAST) ? FIL_GROUP : 0) |
626             FIL_BRDCST |
627             ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) ? FIL_ALL : 0));
628         /* you can `ifconfig (link0|-link0) ep0' to get the following
629          * behaviour: -link0    disable AUI/UTP. enable BNC. link0 disable
630          * BNC. enable AUI. if the card has a UTP connector, that is enabled
631          * too. not sure, but it seems you have to be careful to not plug
632          * things into both AUI & UTP. */
633
634         if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) {
635                 GO_WINDOW(0);
636                 /* set the xcvr */
637                 outw(BASE + EP_W0_ADDRESS_CFG, 3 << 14);
638                 GO_WINDOW(2);
639                 outw(BASE + EP_COMMAND, START_TRANSCEIVER);
640                 GO_WINDOW(1);
641         }
642 #if defined(__NetBSD__) || defined(__FreeBSD__)
643         if ((ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & UTP)) {
644 #else
645         if ((ifp->if_flags & IFF_ALTPHYS) && (sc->ep_connectors & UTP)) {
646 #endif
647                 GO_WINDOW(4);
648                 outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
649                 GO_WINDOW(1);
650         }
651         outw(BASE + EP_COMMAND, RX_ENABLE);
652         outw(BASE + EP_COMMAND, TX_ENABLE);
653
654         ifp->if_flags |= IFF_RUNNING;
655         ifp->if_flags &= ~IFF_OACTIVE;  /* just in case */
656         sc->tx_start_thresh = 20;       /* probably a good starting point. */
657         /* Store up a bunch of mbuf's for use later. (MAX_MBS). First we free
658          * up any that we had in case we're being called from intr or
659          * somewhere else. */
660         sc->last_mb = 0;
661         sc->next_mb = 0;
662         if (sc->buffill_pending != 0) {
663                 untimeout(zpmbuffill, sc, sc->ch);
664                 sc->buffill_pending = 0;
665         }
666         zpmbuffill(sc);
667         zpstart(ifp);
668         splx(s);
669 }
670
671 static const char padmap[] = {0, 3, 2, 1};
672 static void
673 zpstart(ifp)
674         struct ifnet *ifp;
675 {
676         register struct zp_softc *sc = ifp->if_softc;
677         struct mbuf *m, *top;
678
679         int     s, len, pad;
680
681         s = splimp();
682
683         if (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) {
684                 splx(s);
685                 return;
686         }
687 startagain:
688
689         /* Sneak a peek at the next packet */
690         m = sc->arpcom.ac_if.if_snd.ifq_head;
691         if (m == 0) {
692                 splx(s);
693                 return;
694         }
695         for (len = 0, top = m; m; m = m->m_next)
696                 len += m->m_len;
697
698         pad = padmap[len & 3];
699
700         /* The 3c509 automatically pads short packets to minimum ethernet
701          * length, but we drop packets that are too large. Perhaps we should
702          * truncate them instead? */
703         if (len + pad > ETHER_MAX_LEN) {
704                 /* packet is obviously too large: toss it */
705                 ++sc->arpcom.ac_if.if_oerrors;
706                 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
707                 m_freem(m);
708                 goto readcheck;
709         }
710         if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
711                 /* no room in FIFO */
712                 outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
713                 sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
714                 splx(s);
715
716                 return;
717         }
718         IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
719
720         if (m == 0) {           /* not really needed */
721                 splx(s);
722                 return;
723         }
724         outw(BASE + EP_COMMAND, SET_TX_START_THRESH |
725             (len / 4 + sc->tx_start_thresh));
726
727         outw(BASE + EP_W1_TX_PIO_WR_1, len);
728         outw(BASE + EP_W1_TX_PIO_WR_1, 0xffff); /* Second dword meaningless */
729
730         for (top = m; m != 0; m = m->m_next) {
731                 if (sc->bus32bit) {
732                         outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
733                             m->m_len / 4);
734                         if (m->m_len & 3)
735                                 outsb(BASE + EP_W1_TX_PIO_WR_1,
736                                     mtod(m, caddr_t) + (m->m_len & (~3)),
737                                     m->m_len & 3);
738                 } else {
739                         outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 2);
740                         if (m->m_len & 1)
741                                 outb(BASE + EP_W1_TX_PIO_WR_1,
742                                     *(mtod(m, caddr_t) + m->m_len - 1));
743                 }
744         }
745         while (pad--)
746                 outb(BASE + EP_W1_TX_PIO_WR_1, 0);      /* Padding */
747
748         if (sc->arpcom.ac_if.if_bpf) {
749                 bpf_mtap(&sc->arpcom.ac_if, top);
750         }
751
752         m_freem(top);
753         ++sc->arpcom.ac_if.if_opackets;
754         /* Is another packet coming in? We don't want to overflow the tiny RX
755          * fifo. */
756 readcheck:
757         if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
758                 splx(s);
759                 return;
760         }
761         goto startagain;
762 }
763 static void
764 zpintr(unit)
765         int     unit;
766 {
767         int     status, i;
768         register struct zp_softc *sc = &zp_softc[unit];
769
770         struct ifnet *ifp = &sc->arpcom.ac_if;
771
772
773         status = 0;
774 checkintr:
775         status = inw(BASE + EP_STATUS) &
776             (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE | S_CARD_FAILURE);
777 checkintr2:
778         if (status == 0) {
779                 /* No interrupts. */
780                 outw(BASE + EP_COMMAND, C_INTR_LATCH);
781
782                 status = inw(BASE + EP_STATUS) &
783                     (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE |
784                         S_CARD_FAILURE);
785                 if (status)
786                         goto checkintr2;
787
788                 return;
789         }
790         /* important that we do this first. */
791         outw(BASE + EP_COMMAND, ACK_INTR | status);
792
793         if (status & S_TX_AVAIL) {
794                 status &= ~S_TX_AVAIL;
795                 inw(BASE + EP_W1_FREE_TX);
796                 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
797                 zpstart(&sc->arpcom.ac_if);
798
799         }
800         if (status & S_RX_COMPLETE) {
801                 status &= ~S_RX_COMPLETE;
802                 zpread(sc);
803         }
804         if (status & S_CARD_FAILURE) {
805                 printf("zp%d: reset (status: %x)\n", unit, status);
806                 outw(BASE + EP_COMMAND, C_INTR_LATCH);
807                 zpinit(unit);
808                 return;
809         }
810         if (status & S_TX_COMPLETE) {
811                 status &= ~S_TX_COMPLETE;
812                 /* We need to read TX_STATUS until we get a 0 status in order
813                  * to turn off the interrupt flag. */
814                 while ((i = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
815                         outw(BASE + EP_W1_TX_STATUS, 0x0);
816                         if (i & (TXS_MAX_COLLISION | TXS_JABBER | TXS_UNDERRUN)) {
817                                 if (i & TXS_MAX_COLLISION)
818                                         ++sc->arpcom.ac_if.if_collisions;
819                                 if (i & (TXS_JABBER | TXS_UNDERRUN)) {
820                                         outw(BASE + EP_COMMAND, TX_RESET);
821                                         if (i & TXS_UNDERRUN) {
822                                                 if (sc->tx_start_thresh < ETHER_MAX_LEN) {
823                                                         sc->tx_start_thresh += 20;
824                                                         outw(BASE + EP_COMMAND,
825                                                             SET_TX_START_THRESH |
826                                                             sc->tx_start_thresh);
827                                                 }
828                                         }
829                                 }
830                                 outw(BASE + EP_COMMAND, TX_ENABLE);
831                                 ++sc->arpcom.ac_if.if_oerrors;
832                         }
833                 }
834                 zpstart(ifp);
835         }
836         goto checkintr;
837 }
838
839 static void
840 zpread(sc)
841         register struct zp_softc *sc;
842 {
843         struct ether_header *eh;
844         struct mbuf *mcur, *m, *m0, *top;
845         int     totlen, lenthisone;
846         int     save_totlen;
847         int     off;
848
849
850         totlen = inw(BASE + EP_W1_RX_STATUS);
851         off = 0;
852         top = 0;
853
854         if (totlen & ERR_RX) {
855                 ++sc->arpcom.ac_if.if_ierrors;
856                 goto out;
857         }
858         save_totlen = totlen &= RX_BYTES_MASK;  /* Lower 11 bits = RX bytes. */
859
860         m = sc->mb[sc->next_mb];
861         sc->mb[sc->next_mb] = 0;
862
863         if (m == 0) {
864                 MGETHDR(m, M_DONTWAIT, MT_DATA);
865                 if (m == 0)
866                         goto out;
867         } else {
868                 /* Convert one of our saved mbuf's */
869                 sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
870                 m->m_data = m->m_pktdat;
871                 m->m_flags = M_PKTHDR;
872         }
873
874         top = m0 = m;           /* We assign top so we can "goto out" */
875 #define EROUND  ((sizeof(struct ether_header) + 3) & ~3)
876 #define EOFF    (EROUND - sizeof(struct ether_header))
877         m0->m_data += EOFF;
878         /* Read what should be the header. */
879         insw(BASE + EP_W1_RX_PIO_RD_1,
880             mtod(m0, caddr_t), sizeof(struct ether_header) / 2);
881         m->m_len = sizeof(struct ether_header);
882         totlen -= sizeof(struct ether_header);
883         /* mostly deal with trailer here.  (untested) We do this in a couple
884          * of parts.  First we check for a trailer, if we have one we convert
885          * the mbuf back to a regular mbuf and set the offset and subtract
886          * sizeof(struct ether_header) from the pktlen. After we've read the
887          * packet off the interface (all except for the trailer header, we
888          * then get a header mbuf, read the trailer into it, and fix up the
889          * mbuf pointer chain. */
890         eh = mtod(m, struct ether_header *);
891         while (totlen > 0) {
892                 lenthisone = min(totlen, M_TRAILINGSPACE(m));
893                 if (lenthisone == 0) {  /* no room in this one */
894                         mcur = m;
895                         m = sc->mb[sc->next_mb];
896                         sc->mb[sc->next_mb] = 0;
897                         if (!m) {
898                                 MGET(m, M_DONTWAIT, MT_DATA);
899                                 if (m == 0)
900                                         goto out;
901                         } else if (sc->buffill_pending == 0) {
902                                 sc->ch = timeout(zpmbuffill, sc, 0);
903                                 sc->buffill_pending = 1;
904                                 sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
905                         }
906                         if (totlen >= MINCLSIZE)
907                                 MCLGET(m, M_DONTWAIT);
908                         m->m_len = 0;
909                         mcur->m_next = m;
910                         lenthisone = min(totlen, M_TRAILINGSPACE(m));
911                 }
912                 if (sc->bus32bit) {
913                         insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
914                             lenthisone / 4);
915                         m->m_len += (lenthisone & ~3);
916                         if (lenthisone & 3)
917                                 insb(BASE + EP_W1_RX_PIO_RD_1,
918                                     mtod(m, caddr_t) + m->m_len,
919                                     lenthisone & 3);
920                         m->m_len += (lenthisone & 3);
921                 } else {
922                         insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
923                             lenthisone / 2);
924                         m->m_len += lenthisone;
925                         if (lenthisone & 1)
926                                 *(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
927                 }
928                 totlen -= lenthisone;
929         }
930         if (off) {
931                 top = sc->mb[sc->next_mb];
932                 sc->mb[sc->next_mb] = 0;
933                 if (top == 0) {
934                         MGETHDR(m, M_DONTWAIT, MT_DATA);
935                         if (top == 0) {
936                                 top = m0;
937                                 goto out;
938                         }
939                 } else {
940                         /* Convert one of our saved mbuf's */
941                         sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
942                         top->m_data = top->m_pktdat;
943                         top->m_flags = M_PKTHDR;
944                 }
945                 insw(BASE + EP_W1_RX_PIO_RD_1, mtod(top, caddr_t),
946                     sizeof(struct ether_header));
947                 top->m_next = m0;
948                 top->m_len = sizeof(struct ether_header);
949                 /* XXX Accomodate for type and len from beginning of trailer */
950                 top->m_pkthdr.len = save_totlen - (2 * sizeof(u_short));
951         } else {
952                 top = m0;
953                 top->m_pkthdr.len = save_totlen;
954         }
955
956         top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
957         outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
958         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
959         ++sc->arpcom.ac_if.if_ipackets;
960         if (sc->arpcom.ac_if.if_bpf) {
961                 bpf_mtap(&sc->arpcom.ac_if, top);
962
963                 /* Note that the interface cannot be in promiscuous mode if
964                  * there are no BPF listeners.  And if we are in promiscuous
965                  * mode, we have to check if this packet is really ours. */
966                 if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
967                     (eh->ether_dhost[0] & 1) == 0 &&
968                     bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
969                         sizeof(eh->ether_dhost)) != 0 &&
970                     bcmp(eh->ether_dhost, etherbroadcastaddr,
971                         sizeof(eh->ether_dhost)) != 0) {
972                         m_freem(top);
973                         return;
974                 }
975         }
976         m_adj(top, sizeof(struct ether_header));
977         ether_input(&sc->arpcom.ac_if, eh, top);
978         return;
979
980 out:    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
981         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
982         if (top)
983                 m_freem(top);
984
985 }
986
987
988 /*
989  * Look familiar?
990  */
991 static int
992 zpioctl(ifp, cmd, data)
993         register struct ifnet *ifp;
994         u_long  cmd;
995         caddr_t data;
996 {
997         struct zp_softc *sc = ifp->if_softc;
998         int     error = 0;
999
1000
1001         switch (cmd) {
1002         case SIOCSIFADDR:
1003         case SIOCGIFADDR:
1004         case SIOCSIFMTU:
1005                 error = ether_ioctl(ifp, cmd, data);
1006                 break;
1007
1008         case SIOCSIFFLAGS:
1009                 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
1010                         ifp->if_flags &= ~IFF_RUNNING;
1011                         zpstop(ifp->if_unit);
1012                         zpmbufempty(sc);
1013                         break;
1014                 }
1015                 zpinit(ifp->if_unit);
1016                 break;
1017         default:
1018                 error = EINVAL;
1019         }
1020         return (error);
1021 }
1022
1023 static void
1024 zpreset(unit)
1025         int     unit;
1026 {
1027         int     s = splimp();
1028
1029         zpstop(unit);
1030         zpinit(unit);
1031         splx(s);
1032 }
1033
1034 static void
1035 zpwatchdog(ifp)
1036         struct ifnet *ifp;
1037 {
1038         log(LOG_ERR, "zp%d: watchdog\n", ifp->if_unit);
1039         ifp->if_oerrors++;
1040         zpreset(ifp->if_unit);
1041 }
1042
1043 static void
1044 zpstop(unit)
1045         int     unit;
1046 {
1047         struct zp_softc *sc = &zp_softc[unit];
1048
1049         outw(BASE + EP_COMMAND, RX_DISABLE);
1050         outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1051         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1052         outw(BASE + EP_COMMAND, TX_DISABLE);
1053         outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
1054         outw(BASE + EP_COMMAND, RX_RESET);
1055         outw(BASE + EP_COMMAND, TX_RESET);
1056         outw(BASE + EP_COMMAND, C_INTR_LATCH);
1057         outw(BASE + EP_COMMAND, SET_RD_0_MASK);
1058         outw(BASE + EP_COMMAND, SET_INTR_MASK);
1059         outw(BASE + EP_COMMAND, SET_RX_FILTER);
1060 }
1061
1062
1063
1064 static  u_short
1065 read_eeprom_data(id_port, offset)
1066         int     id_port;
1067         int     offset;
1068 {
1069
1070         outb(id_port + 10, 0x80 + offset);
1071         DELAY(1000);
1072         return inw(id_port + 12);
1073 }
1074
1075
1076
1077
1078 static void
1079 zpmbuffill(sp)
1080         void   *sp;
1081 {
1082         struct zp_softc *sc = (struct zp_softc *) sp;
1083         int     s, i;
1084
1085         s = splimp();
1086         i = sc->last_mb;
1087         do {
1088                 if (sc->mb[i] == NULL)
1089                         MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
1090                 if (sc->mb[i] == NULL)
1091                         break;
1092                 i = (i + 1) % MAX_MBS;
1093         } while (i != sc->next_mb);
1094         sc->buffill_pending = 0;
1095         sc->last_mb = i;
1096         splx(s);
1097 }
1098
1099 static void
1100 zpmbufempty(sc)
1101         struct zp_softc *sc;
1102 {
1103         int     s, i;
1104
1105         s = splimp();
1106         for (i = 0; i < MAX_MBS; i++) {
1107                 if (sc->mb[i]) {
1108                         m_freem(sc->mb[i]);
1109                         sc->mb[i] = NULL;
1110                 }
1111         }
1112         sc->last_mb = sc->next_mb = 0;
1113         if (sc->buffill_pending != 0) {
1114                 untimeout(zpmbuffill, sc, sc->ch);
1115                 sc->buffill_pending = 0;
1116         }
1117         splx(s);
1118 }