|
|
1.1 root 1: /*-
2: * Copyright (c) 1990, 1991 William F. Jolitz.
3: * Copyright (c) 1990 The Regents of the University of California.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by the University of
17: * California, Berkeley and its contributors.
18: * 4. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * if_hp.c,v 1.9 1993/07/13 21:53:06 mycroft Exp
35: */
36:
37: /*
38: * HP LAN Ethernet driver
39: *
40: * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
41: * insight on the ne2000 gained from Robert Clements PC/FTP driver.
42: *
43: * receive bottom end totally rewritten by Curt Mayer, Dec 1992.
44: * no longer loses back to back packets.
45: * note to driver writers: RTFM!
46: *
47: * hooks for packet filter added by Charles Hannum, 29DEC1992.
48: *
49: * Mostly rewritten for HP-labelled EISA controllers by Charles Hannum,
50: * 18JAN1993.
51: */
52:
53: #include "hp.h"
54: #if NHP > 0
55:
56: #include "param.h"
57: #include "systm.h"
58: #include "mbuf.h"
59: #include "buf.h"
60: #include "protosw.h"
61: #include "socket.h"
62: #include "ioctl.h"
63: #include "errno.h"
64: #include "syslog.h"
65:
66: #include "net/if.h"
67: #include "net/netisr.h"
68: #include "net/route.h"
69:
70: #ifdef INET
71: #include "netinet/in.h"
72: #include "netinet/in_systm.h"
73: #include "netinet/in_var.h"
74: #include "netinet/ip.h"
75: #include "netinet/if_ether.h"
76: #endif
77:
78: #ifdef NS
79: #include "netns/ns.h"
80: #include "netns/ns_if.h"
81: #endif
82:
83: #include "bpfilter.h"
84: #if NBPFILTER > 0
85: #include "net/bpf.h"
86: #include "net/bpfdesc.h"
87: #endif
88:
89: #include "machine/cpufunc.h"
90: #include "i386/isa/isa_device.h"
91: #include "i386/isa/if_nereg.h"
92: #include "i386/isa/icu.h"
93:
94: int hpprobe (), hpattach (), hpintr ();
95: int hpstart (), hpinit (), ether_output (), hpioctl ();
96:
97: struct isa_driver hpdriver =
98: {
99: hpprobe, hpattach, "hp",
100: };
101:
102: struct mbuf *hpget ();
103:
104: #define ETHER_MIN_LEN 64
105: #define ETHER_MAX_LEN 1536
106:
107: /*
108: * Ethernet software status per interface.
109: *
110: * Each interface is referenced by a network interface structure,
111: * ns_if, which the routing code uses to locate the interface.
112: * This structure contains the output queue for the interface, its address, ...
113: */
114: struct hp_softc
115: {
116: struct arpcom ns_ac; /* Ethernet common part */
117: #define ns_if ns_ac.ac_if /* network-visible interface */
118: #define ns_addr ns_ac.ac_enaddr /* hardware Ethernet address */
119: int ns_flags;
120: #define DSF_LOCK 1 /* block re-entering enstart */
121: int ns_oactive;
122: int ns_mask;
123: struct prhdr ns_ph; /* hardware header of incoming packet*/
124: u_char ns_pb[2048];
125: u_char ns_txstart; /* transmitter buffer start */
126: u_char ns_rxstart; /* receiver buffer start */
127: u_char ns_rxend; /* receiver buffer end */
128: u_char hp_type; /* HP board type */
129: u_char hp_irq; /* interrupt vector */
130: short ns_port; /* i/o port base */
131: short ns_mode; /* word/byte mode */
132: short ns_rcr;
133: #if NBPFILTER > 0
134: caddr_t ns_bpf;
135: #endif
136: }
137:
138: hp_softc[NHP];
139: #define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN)
140:
141: #define PAT(n) (0xa55a + 37*(n))
142:
143: u_short boarddata[16];
144:
145: #define hp_option (-8)
146: #define hp_data (-4)
147: #define HP_RUN (0x01)
148: #define HP_DATA (0x10)
149:
150: hpprobe (dvp)
151: struct isa_device *dvp;
152: {
153: int val, i, s, sum, pat;
154: register struct hp_softc *ns = &hp_softc[0];
155: register hpc;
156:
157: #ifdef lint
158: hpintr (0);
159: #endif
160:
161: hpc = (ns->ns_port = dvp->id_iobase + 0x10);
162: s = splnet ();
163:
164: ns->hp_irq = ffs(dvp->id_irq) - 1;
165:
166: /* Extract board address */
167: for (i = 0; i < 6; i++)
168: ns->ns_addr[i] = inb (hpc - 0x10 + i);
169: ns->hp_type = inb (hpc - 0x10 + 7);
170:
171: if (ns->ns_addr[0] != 0x08 ||
172: ns->ns_addr[1] != 0x00 ||
173: ns->ns_addr[2] != 0x09) {
174: splx (s);
175: return 0;
176: }
177:
178: /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
179: /* On this board, WTS means 32-bit transfers, which is still
180: experimental. - mycroft, 18JAN93 */
181: #ifdef HP_32BIT
182: ns->ns_mode = DSDC_WTS | DSDC_BMS | DSDC_FT1;
183: #else
184: ns->ns_mode = DSDC_BMS | DSDC_FT1;
185: #endif
186: ns->ns_txstart = 0 * 1024 / DS_PGSIZE;
187: ns->ns_rxend = 32 * 1024 / DS_PGSIZE;
188:
189: ns->ns_rxstart = ns->ns_txstart + (PKTSZ / DS_PGSIZE);
190:
191: outb (hpc + hp_option, HP_RUN);
192:
193: #if 0
194: outb (hpc + ds0_isr, 0xff);
195: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP);
196: DELAY (1000);
197:
198: /* Check cmd reg and fail if not right */
199: if ((i = inb (hpc + ds_cmd)) != (DSCM_NODMA | DSCM_PG0 | DSCM_STOP)) {
200: splx (s);
201: return (0);
202: }
203: #endif
204:
205: outb (hpc + hp_option, 0);
206:
207: splx (s);
208: return (32);
209: }
210:
211: /*
212: * Fetch from onboard ROM/RAM
213: */
214: hpfetch (ns, up, ad, len)
215: struct hp_softc *ns;
216: caddr_t up;
217: {
218: u_char cmd;
219: register hpc = ns->ns_port;
220: int counter = 100000;
221:
222: outb (hpc + hp_option, inb (hpc + hp_option) | HP_DATA);
223:
224: cmd = inb (hpc + ds_cmd);
225: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
226:
227: /* Setup remote dma */
228: outb (hpc + ds0_isr, DSIS_RDC);
229:
230: if (ns->ns_mode & DSDC_WTS)
231: len = (len + 3) & ~3;
232: else
233: len = (len + 1) & ~1;
234:
235: outb (hpc + ds0_rbcr0, len);
236: outb (hpc + ds0_rbcr1, len >> 8);
237: outb (hpc + ds0_rsar0, ad);
238: outb (hpc + ds0_rsar1, ad >> 8);
239:
240: #ifdef HP_DEBUG
241: printf ("hpfetch: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n",
242: len, hpc+hp_data, ad, inb (hpc + hp_option),
243: ns->ns_mode & DSDC_WTS ? 32 : 16);
244: printf ("hpfetch: cmd=0x%02x isr=0x%02x ",
245: inb (hpc + ds_cmd), inb (hpc + ds0_isr));
246: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START);
247: printf ("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n",
248: inb (hpc + ds0_imr), inb (hpc + ds0_rcr), inb (hpc + ds0_tcr),
249: inb (hpc + ds0_dcr));
250: #endif
251:
252: /* Execute & extract from card */
253: outb (hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START);
254:
255: #ifdef HP_32BIT
256: if (ns->ns_mode & DSDC_WTS)
257: len = (caddr_t) insd (hpc + hp_data, up, len >> 2) - up;
258: else
259: #endif
260: len = (caddr_t) insw (hpc + hp_data, up, len >> 1) - up;
261:
262: #ifdef HP_DEBUG
263: printf ("hpfetch: done len=%d\n", len);
264: #endif
265:
266: /* Wait till done, then shutdown feature */
267: while ((inb (hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
268: ;
269: outb (hpc + ds0_isr, DSIS_RDC);
270: outb (hpc + ds_cmd, cmd);
271:
272: outb (hpc + hp_option, inb (hpc + hp_option) & ~HP_DATA);
273: }
274:
275: /*
276: * Put to onboard RAM
277: */
278: hpput (ns, up, ad, len)
279: struct hp_softc *ns;
280: caddr_t up;
281: {
282: u_char cmd;
283: register hpc = ns->ns_port;
284: int counter = 100000;
285:
286: outb (hpc + hp_option, inb (hpc + hp_option) | HP_DATA);
287:
288: cmd = inb (hpc + ds_cmd);
289: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
290:
291: /* Setup for remote dma */
292: outb (hpc + ds0_isr, DSIS_RDC);
293:
294: if (ns->ns_mode & DSDC_WTS)
295: len = (len + 3) & ~3;
296: else
297: len = (len + 1) & ~1;
298:
299: #ifdef HP_DEBUG
300: printf ("hpput: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n",
301: len, hpc+hp_data, ad, inb (hpc + hp_option),
302: ns->ns_mode & DSDC_WTS ? 32 : 16);
303: printf ("hpput: cmd=0x%02x isr=0x%02x ",
304: inb (hpc + ds_cmd), inb (hpc + ds0_isr));
305: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START);
306: printf ("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n",
307: inb (hpc + ds0_imr), inb (hpc + ds0_rcr), inb (hpc + ds0_tcr),
308: inb (hpc + ds0_dcr));
309: {
310: unsigned char *p = (unsigned char *) up;
311: int n = len;
312: printf ("hpput:");
313: while (n--)
314: printf (" %02x", *(p++));
315: printf ("\n");
316: }
317: #endif
318:
319: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
320: outb (hpc + ds0_rbcr0, 0xff);
321: outb (hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START);
322:
323: outb (hpc + ds0_rbcr0, len);
324: outb (hpc + ds0_rbcr1, len >> 8);
325: outb (hpc + ds0_rsar0, ad);
326: outb (hpc + ds0_rsar1, ad >> 8);
327:
328: /* Execute & stuff to card */
329: outb (hpc + ds_cmd, DSCM_RWRITE | DSCM_PG0 | DSCM_START);
330:
331: #ifdef HP_32BIT
332: if (ns->ns_mode & DSDC_WTS)
333: len = (caddr_t) outsd (hpc + hp_data, up, len >> 2) - up;
334: else
335: #endif
336: len = (caddr_t) outsw (hpc + hp_data, up, len >> 1) - up;
337:
338: #ifdef HP_DEBUG
339: printf ("hpput: done len=%d\n", len);
340: #endif
341:
342: /* Wait till done, then shutdown feature */
343: while ((inb (hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
344: ;
345: outb (hpc + ds0_isr, DSIS_RDC);
346: outb (hpc + ds_cmd, cmd);
347:
348: outb (hpc + hp_option, inb (hpc + hp_option) & ~HP_DATA);
349: }
350:
351: /*
352: * Reset of interface.
353: */
354: hpreset (unit, uban)
355: int unit, uban;
356: {
357: register struct hp_softc *ns = &hp_softc[unit];
358: register hpc = ns->ns_port;
359: if (unit >= NHP)
360: return;
361: printf ("hp%d: reset\n", unit);
362: outb (hpc + hp_option, 0);
363: ns->ns_flags &= ~DSF_LOCK;
364: hpinit (unit);
365: }
366:
367: static char *
368: hp_id (type)
369: u_char type;
370: {
371: static struct
372: {
373: u_char type;
374: char *name;
375: }
376: boards[] =
377: { { 0x00, "hp27240" } ,
378: { 0x10, "hp24240" } ,
379: { 0x01, "hp27245" } ,
380: { 0x02, "hp27250" } ,
381: { 0x81, "hp27247" } ,
382: { 0x91, "hp27247r1" } };
383: int n = sizeof (boards) / sizeof (boards[0]);
384:
385: while (n)
386: if (boards[--n].type == type)
387: return boards[n].name;
388:
389: return "UNKNOWN";
390: }
391:
392: /*
393: * Interface exists: make available by filling in network interface
394: * record. System will initialize the interface when it is ready
395: * to accept packets. We get the ethernet address here.
396: */
397: hpattach (dvp)
398: struct isa_device *dvp;
399: {
400: int unit = dvp->id_unit;
401: register struct hp_softc *ns = &hp_softc[unit];
402: register struct ifnet *ifp = &ns->ns_if;
403:
404: ifp->if_unit = unit;
405: ifp->if_name = hpdriver.name;
406: ifp->if_mtu = ETHERMTU;
407: printf ("hp%d: %s %d-bit ethernet address %s\n", unit,
408: hp_id (ns->hp_type), ns->ns_mode & DSDC_WTS ? 32 : 16,
409: ether_sprintf (ns->ns_addr));
410: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
411: ifp->if_init = hpinit;
412: ifp->if_output = ether_output;
413: ifp->if_start = hpstart;
414: ifp->if_ioctl = hpioctl;
415: ifp->if_reset = hpreset;
416: ifp->if_watchdog = 0;
417: if_attach (ifp);
418:
419: #if NBPFILTER > 0
420: bpfattach (&ns->ns_bpf, ifp, DLT_EN10MB,
421: sizeof (struct ether_header));
422: #endif
423: }
424:
425: /*
426: * Initialization of interface; set up initialization block
427: * and transmit/receive descriptor rings.
428: */
429: hpinit (unit)
430: int unit;
431: {
432: register struct hp_softc *ns = &hp_softc[unit];
433: struct ifnet *ifp = &ns->ns_if;
434: int s;
435: int i;
436: char *cp;
437: register hpc = ns->ns_port;
438:
439: if (ifp->if_addrlist == (struct ifaddr *) 0)
440: return;
441: if (ifp->if_flags & IFF_RUNNING)
442: return;
443:
444: s = splnet ();
445:
446: #ifdef HP_DEBUG
447: printf ("hpinit: hp%d at 0x%x irq %d\n", unit, hpc, (int) ns->hp_irq);
448: printf ("hpinit: promiscuous mode %s\n",
449: ns->ns_if.if_flags & IFF_PROMISC ? "on" : "off");
450: #endif
451:
452: ns->ns_rcr = (ns->ns_if.if_flags & IFF_BROADCAST ? DSRC_AB : 0) |
453: (ns->ns_if.if_flags & IFF_PROMISC ? DSRC_PRO : 0);
454: #ifdef HP_LOG_ERRORS
455: ns->ns_rcr |= DSRC_SEP;
456: #endif
457:
458: /* set irq and turn on board */
459: outb (hpc + hp_option, HP_RUN | (ns->hp_irq << 1));
460:
461: /* init regs */
462: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP);
463: outb (hpc + ds0_dcr, 0);
464: outb (hpc + ds0_rbcr0, 0);
465: outb (hpc + ds0_rbcr1, 0);
466: outb (hpc + ds0_rcr, DSRC_MON);
467: outb (hpc + ds0_tpsr, ns->ns_txstart);
468: outb (hpc + ds0_imr, 0);
469: outb (hpc + ds0_tcr, DSTC_LB0);
470: outb (hpc + ds0_pstart, ns->ns_rxstart);
471: outb (hpc + ds0_bnry, ns->ns_rxend-1);
472: outb (hpc + ds0_pstop, ns->ns_rxend);
473: outb (hpc + ds0_isr, 0xff);
474: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG1 | DSCM_STOP);
475: outb (hpc + ds1_curr, ns->ns_rxstart);
476:
477: /* set physical address on ethernet */
478: for (i = 0; i < 6; i++)
479: outb (hpc + ds1_par0 + i, ns->ns_addr[i]);
480:
481: /* clr logical address hash filter for now */
482: for (i = 0; i < 8; i++)
483: outb (hpc + ds1_mar0 + i, 0xff);
484:
485: /* fire it up */
486: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
487: outb (hpc + ds0_dcr, ns->ns_mode);
488: outb (hpc + ds0_rcr, ns->ns_rcr);
489: outb (hpc + ds0_tcr, 0);
490: outb (hpc + ds0_imr, 0xff);
491:
492: ns->ns_if.if_flags |= IFF_RUNNING;
493: ns->ns_flags &= ~DSF_LOCK;
494: ns->ns_oactive = 0;
495: ns->ns_mask = ~0;
496: hpstart (ifp);
497:
498: #ifdef HP_DEBUG
499: printf ("hpinit: done\n", unit, hpc);
500: #endif
501:
502: splx (s);
503: }
504:
505: /*
506: * Setup output on interface.
507: * Get another datagram to send off of the interface queue,
508: * and map it to the interface before starting the output.
509: * called only at splnet or interrupt level.
510: */
511: hpstart (ifp)
512: struct ifnet *ifp;
513: {
514: register struct hp_softc *ns = &hp_softc[ifp->if_unit];
515: struct mbuf *m0, *m;
516: int buffer;
517: int len = 0, i, total, t;
518: register hpc = ns->ns_port;
519:
520: /*
521: * The DS8390 has only one transmit buffer, if it is busy we
522: * must wait until the transmit interrupt completes.
523: */
524: if (ns->ns_flags & DSF_LOCK)
525: return;
526:
527: if (inb (hpc + ds_cmd) & DSCM_TRANS)
528: return;
529:
530: if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)
531: return;
532:
533: IF_DEQUEUE (&ns->ns_if.if_snd, m);
534:
535: if (m == 0)
536: return;
537:
538: /*
539: * Copy the mbuf chain into the transmit buffer
540: */
541:
542: ns->ns_flags |= DSF_LOCK; /* prevent entering hpstart */
543: buffer = ns->ns_txstart * DS_PGSIZE;
544: len = i = 0;
545: t = 0;
546: for (m0 = m; m != 0; m = m->m_next)
547: t += m->m_len;
548:
549: m = m0;
550: total = t;
551:
552: #ifdef HP_DEBUG
553: printf ("hpstart: len=%d\n", total);
554: #endif
555:
556: #if NBPFILTER > 0
557: if (ns->ns_bpf)
558: bpf_mtap (ns->ns_bpf, m);
559: #endif
560:
561: for (m0 = m; m != 0;)
562: {
563: if (m->m_len & 1 && t > m->m_len)
564: {
565: m->m_len -= 1;
566: hpput (ns, mtod (m, caddr_t), buffer, m->m_len);
567: t -= m->m_len;
568: buffer += m->m_len;
569: m->m_data += m->m_len;
570: m->m_len = 1;
571: m = m_pullup (m, 2);
572: }
573: else
574: {
575: hpput (ns, mtod (m, caddr_t), buffer, m->m_len);
576: t -= m->m_len;
577: buffer += m->m_len;
578: MFREE (m, m0);
579: m = m0;
580: }
581: }
582:
583: /*
584: * Init transmit length registers, and set transmit start flag.
585: */
586:
587: len = total;
588: if (len < ETHER_MIN_LEN)
589: len = ETHER_MIN_LEN;
590: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
591: outb (hpc + ds0_tbcr0, len & 0xff);
592: outb (hpc + ds0_tbcr1, (len >> 8) & 0xff);
593: outb (hpc + ds0_tpsr, ns->ns_txstart);
594: outb (hpc + ds_cmd, DSCM_TRANS | DSCM_NODMA | DSCM_PG0 | DSCM_START);
595:
596: #ifdef HP_DEBUG
597: printf ("hpstart: done\n", hpc);
598: #endif
599: }
600:
601: /*
602: * Controller interrupt.
603: */
604: hpintr (unit)
605: {
606: register struct hp_softc *ns = &hp_softc[unit];
607: u_char cmd, isr;
608: register hpc = ns->ns_port;
609: u_char err;
610:
611: /* Save cmd, clear interrupt */
612: cmd = inb (hpc + ds_cmd);
613: loop:
614: isr = inb (hpc + ds0_isr);
615: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
616: outb (hpc + ds0_isr, isr);
617:
618: /* Receiver error */
619: if (isr & DSIS_RXE)
620: {
621: /* need to read these registers to clear status */
622: err = inb (hpc + ds0_rsr);
623: (void) inb (hpc + 0xD);
624: (void) inb (hpc + 0xE);
625: (void) inb (hpc + 0xF);
626: ns->ns_if.if_ierrors++;
627: #ifdef HP_LOG_ERRORS
628: isr |= DSIS_RX;
629: #endif
630: }
631:
632: /* We received something */
633: if (isr & DSIS_RX)
634: {
635: u_char bnry;
636: u_char curr;
637: u_short addr;
638: int len;
639: int i;
640: unsigned char c;
641:
642: while (1)
643: {
644: outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
645: bnry = inb (hpc + ds0_bnry);
646: outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1);
647: curr = inb (hpc + ds1_curr);
648:
649: #ifdef HP_DEBUG
650: printf ("hpintr: receive isr=0x%02x bnry=0x%02x curr=0x%02x\n",
651: isr, bnry, curr);
652: #endif
653:
654: if (++bnry >= ns->ns_rxend)
655: bnry = ns->ns_rxstart;
656:
657: /* if ring empty, done! */
658: if (bnry == curr)
659: break;
660:
661: addr = bnry * DS_PGSIZE;
662:
663: outb (hpc + hp_option, inb (hpc + hp_option) | HP_DATA);
664:
665: #if 0
666: /* send packet with auto packet release */
667: outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
668: outb (hpc + ds0_rbcr1, 0x0f);
669: outb (hpc + ds0_dcr, ns->ns_mode | DSDC_AR);
670: outb (hpc + ds_cmd, DSCM_SENDP | DSCM_PG0 | DSCM_START);
671: #endif
672:
673: /* get length */
674: hpfetch (ns, (caddr_t) &ns->ns_ph, addr, sizeof ns->ns_ph);
675: addr += sizeof ns->ns_ph;
676:
677: #ifdef HP_DEBUG
678: printf ("hpintr: sendp packet hdr: %x %x %x %x\n",
679: ns->ns_ph.pr_status,
680: ns->ns_ph.pr_nxtpg,
681: ns->ns_ph.pr_sz0,
682: ns->ns_ph.pr_sz1);
683: #endif
684:
685: #ifdef HP_LOG_ERRORS
686: if (ns->ns_ph.pr_status & (DSRS_CRC|DSRS_FO|DSRS_DFR))
687: {
688: /* Get packet header */
689: if (len > 14)
690: len = 14;
691: hpfetch (ns, (caddr_t) (ns->ns_pb), addr, len);
692:
693: /* move boundary up */
694: bnry = ns->ns_ph.pr_nxtpg;
695: if (--bnry < ns->ns_rxstart)
696: bnry = ns->ns_rxend-1;
697: outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
698: outb (hpc + ds0_bnry, bnry);
699:
700: printf ("hp%d: receive error status=0x%02x\n", unit,
701: ns->ns_ph.pr_status);
702: printf ("hp%d: packet header:", unit);
703: {
704: int n;
705: for (n = 0; n < len; n++)
706: printf (" %02x", ns->ns_pb[n]);
707: }
708: printf ("\n");
709:
710: continue;
711: }
712: #endif
713:
714: ns->ns_if.if_ipackets++;
715: len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1 << 8);
716: if (len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)
717: {
718: printf ("hpintr: bnry %x curr %x\n", bnry, curr);
719: printf ("hpintr: packet hdr: %x %x %x %x\n",
720: ns->ns_ph.pr_status,
721: ns->ns_ph.pr_nxtpg,
722: ns->ns_ph.pr_sz0,
723: ns->ns_ph.pr_sz1);
724: printf ("isr = 0x%x reg_isr=0x%x\n",
725: isr, inb (hpc + ds0_isr));
726: outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
727: bnry = inb (hpc + ds0_bnry);
728: outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1);
729: curr = inb (hpc + ds1_curr);
730: printf ("hpintr: new bnry %x curr %x\n", bnry, curr);
731: printf ("hpintr: bad len %d\n-hanging-\n",
732: len);
733: while (1);
734: }
735:
736: /* read packet */
737: hpfetch (ns, (caddr_t) (ns->ns_pb), addr, len);
738:
739: /* move boundary up */
740: bnry = ns->ns_ph.pr_nxtpg;
741: if (--bnry < ns->ns_rxstart)
742: bnry = ns->ns_rxend-1;
743: outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
744: outb (hpc + ds0_bnry, bnry);
745:
746: #ifdef HP_DEBUG
747: printf ("hpintr: receive done bnry=0x%02x\n", bnry);
748: #endif
749:
750: outb (hpc + hp_option, inb (hpc + hp_option) & ~HP_DATA);
751:
752: /* adjust for ether header and checksum */
753: len -= sizeof (struct ether_header) + sizeof (long);
754:
755: /* process packet */
756: hpread (ns, (caddr_t) (ns->ns_pb), len);
757: }
758: }
759:
760: /* Transmit error */
761: if (isr & DSIS_TXE)
762: {
763: ns->ns_flags &= ~DSF_LOCK;
764: /* Need to read these registers to clear status */
765: ns->ns_if.if_collisions += inb (hpc + ds0_tbcr0);
766: ns->ns_if.if_oerrors++;
767: }
768:
769: /* Packet Transmitted */
770: if (isr & DSIS_TX)
771: {
772: ns->ns_flags &= ~DSF_LOCK;
773: ++ns->ns_if.if_opackets;
774: ns->ns_if.if_collisions += inb (hpc + ds0_tbcr0);
775: }
776:
777: /* Receiver ovverun? */
778: if (isr & DSIS_ROVRN)
779: {
780: log (LOG_ERR, "hp%d: error: isr %x\n", ns - hp_softc, isr
781: /*, DSIS_BITS*/ );
782: outb (hpc + ds0_rbcr0, 0);
783: outb (hpc + ds0_rbcr1, 0);
784: outb (hpc + ds0_tcr, DSTC_LB0);
785: outb (hpc + ds0_rcr, DSRC_MON);
786: outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA);
787: outb (hpc + ds0_rcr, ns->ns_rcr);
788: outb (hpc + ds0_tcr, 0);
789: }
790:
791: /* Any more to send? */
792: outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
793: hpstart (&ns->ns_if);
794: outb (hpc + ds_cmd, cmd);
795: outb (hpc + ds0_imr, 0xff);
796:
797: /* Still more to do? */
798: isr = inb (hpc + ds0_isr);
799: if (isr)
800: goto loop;
801: }
802:
803: /*
804: * Pass a packet to the higher levels.
805: * We deal with the trailer protocol here.
806: */
807: hpread (ns, buf, len)
808: register struct hp_softc *ns;
809: char *buf;
810: int len;
811: {
812: register struct ether_header *eh;
813: struct mbuf *m;
814: int off, resid;
815: register struct ifqueue *inq;
816:
817: /*
818: * Deal with trailer protocol: if type is trailer type
819: * get true type from first 16-bit word past data.
820: * Remember that type was trailer by setting off.
821: */
822: eh = (struct ether_header *) buf;
823: eh->ether_type = ntohs ((u_short) eh->ether_type);
824: #define hpdataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
825: if (eh->ether_type >= ETHERTYPE_TRAIL &&
826: eh->ether_type < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER)
827: {
828: off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
829: if (off >= ETHERMTU)
830: return; /* sanity */
831: eh->ether_type = ntohs (*hpdataaddr (eh, off, u_short *));
832: resid = ntohs (*(hpdataaddr (eh, off + 2, u_short *)));
833: if (off + resid > len)
834: return; /* sanity */
835: len = off + resid;
836: }
837: else
838: off = 0;
839:
840: if (len == 0)
841: return;
842:
843: #if NBPFILTER > 0
844: if (ns->ns_bpf)
845: bpf_tap (ns->ns_bpf, buf, len + sizeof (struct ether_header));
846: #endif
847:
848: if ((ns->ns_if.if_flags & IFF_PROMISC)
849: && bcmp (eh->ether_dhost, ns->ns_addr,
850: sizeof (eh->ether_dhost)) != 0
851: && bcmp (eh->ether_dhost, etherbroadcastaddr,
852: sizeof (eh->ether_dhost)) != 0)
853: return;
854:
855: /*
856: * Pull packet off interface. Off is nonzero if packet
857: * has trailing header; hpget will then force this header
858: * information to be at the front, but we still have to drop
859: * the type and length which are at the front of any trailer data.
860: */
861: m = hpget (buf, len, off, &ns->ns_if);
862: if (m == 0)
863: return;
864:
865: ether_input (&ns->ns_if, eh, m);
866: }
867:
868: /*
869: * Supporting routines
870: */
871:
872: /*
873: * Pull read data off a interface.
874: * Len is length of data, with local net header stripped.
875: * Off is non-zero if a trailer protocol was used, and
876: * gives the offset of the trailer information.
877: * We copy the trailer information and then all the normal
878: * data into mbufs. When full cluster sized units are present
879: * we copy into clusters.
880: */
881: struct mbuf *
882: hpget (buf, totlen, off0, ifp)
883: caddr_t buf;
884: int totlen, off0;
885: struct ifnet *ifp;
886: {
887: struct mbuf *top, **mp, *m, *p;
888: int off = off0, len;
889: register caddr_t cp = buf;
890: char *epkt;
891:
892: buf += sizeof (struct ether_header);
893: cp = buf;
894: epkt = cp + totlen;
895:
896:
897: if (off)
898: {
899: cp += off + 2 * sizeof (u_short);
900: totlen -= 2 * sizeof (u_short);
901: }
902:
903: MGETHDR (m, M_DONTWAIT, MT_DATA);
904: if (m == 0)
905: return (0);
906: m->m_pkthdr.rcvif = ifp;
907: m->m_pkthdr.len = totlen;
908: m->m_len = MHLEN;
909:
910: top = 0;
911: mp = ⊤
912: while (totlen > 0)
913: {
914: if (top)
915: {
916: MGET (m, M_DONTWAIT, MT_DATA);
917: if (m == 0)
918: {
919: m_freem (top);
920: return (0);
921: }
922: m->m_len = MLEN;
923: }
924: len = min (totlen, epkt - cp);
925: if (len >= MINCLSIZE)
926: {
927: MCLGET (m, M_DONTWAIT);
928: if (m->m_flags & M_EXT)
929: m->m_len = len = min (len, MCLBYTES);
930: else
931: len = m->m_len;
932: }
933: else
934: {
935: /*
936: * Place initial small packet/header at end of mbuf.
937: */
938: if (len < m->m_len)
939: {
940: if (top == 0 && len + max_linkhdr <= m->m_len)
941: m->m_data += max_linkhdr;
942: m->m_len = len;
943: }
944: else
945: len = m->m_len;
946: }
947: bcopy (cp, mtod (m, caddr_t), (unsigned) len);
948: cp += len;
949: *mp = m;
950: mp = &m->m_next;
951: totlen -= len;
952: if (cp == epkt)
953: cp = buf;
954: }
955: return (top);
956: }
957:
958: /*
959: * Process an ioctl request.
960: */
961: hpioctl (ifp, cmd, data)
962: register struct ifnet *ifp;
963: int cmd;
964: caddr_t data;
965: {
966: register struct ifaddr *ifa = (struct ifaddr *) data;
967: struct hp_softc *ns = &hp_softc[ifp->if_unit];
968: struct ifreq *ifr = (struct ifreq *) data;
969: int s = splnet (), error = 0;
970:
971:
972: switch (cmd)
973: {
974:
975: case SIOCSIFADDR:
976: ifp->if_flags |= IFF_UP;
977:
978: switch (ifa->ifa_addr->sa_family)
979: {
980: #ifdef INET
981: case AF_INET:
982: hpinit (ifp->if_unit);/* before arpwhohas */
983: ((struct arpcom *) ifp)->ac_ipaddr =
984: IA_SIN (ifa)->sin_addr;
985: arpwhohas ((struct arpcom *) ifp, &IA_SIN (ifa)->sin_addr);
986: break;
987: #endif
988: #ifdef NS
989: case AF_NS:
990: {
991: register struct ns_addr *ina = &(IA_SNS (ifa)->sns_addr);
992:
993: if (ns_nullhost (*ina))
994: ina->x_host = *(union ns_host *) (ns->ns_addr);
995: else
996: {
997: /*
998: * The manual says we can't change the address
999: * while the receiver is armed,
1000: * so reset everything
1001: */
1002: ifp->if_flags &= ~IFF_RUNNING;
1003: bcopy ((caddr_t) ina->x_host.c_host,
1004: (caddr_t) ns->ns_addr, sizeof (ns->ns_addr));
1005: }
1006: hpinit (ifp->if_unit); /* does hp_setaddr() */
1007: break;
1008: }
1009: #endif
1010: default:
1011: hpinit (ifp->if_unit);
1012: break;
1013: }
1014: break;
1015:
1016: case SIOCSIFFLAGS:
1017: #ifdef HP_DEBUG
1018: printf ("hp: setting flags, up: %s, running: %s\n",
1019: ifp->if_flags & IFF_UP ? "yes" : "no",
1020: ifp->if_flags & IFF_RUNNING ? "yes" : "no");
1021: #endif
1022: if ((ifp->if_flags & IFF_UP) == 0 &&
1023: ifp->if_flags & IFF_RUNNING)
1024: {
1025: ifp->if_flags &= ~IFF_RUNNING;
1026: outb (ns->ns_port + ds_cmd, DSCM_STOP | DSCM_NODMA);
1027: }
1028: else if (ifp->if_flags & IFF_UP &&
1029: (ifp->if_flags & IFF_RUNNING) == 0)
1030: hpinit (ifp->if_unit);
1031: break;
1032:
1033: #ifdef notdef
1034: case SIOCGHWADDR:
1035: bcopy ((caddr_t) ns->ns_addr, (caddr_t) & ifr->ifr_data,
1036: sizeof (ns->ns_addr));
1037: break;
1038: #endif
1039:
1040: default:
1041: error = EINVAL;
1042: }
1043: splx (s);
1044: return (error);
1045: }
1046:
1047: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.