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