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. */
6 * Copyright (c) 1990 The Regents of the University of California.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
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
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
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,
82 #include <sys/cdefs.h>
83 __KERNEL_RCSID(0, "$NetBSD: if_hp.c,v 1.47 2009/03/14 21:04:20 dsl Exp $");
91 #include <sys/param.h>
92 #include <sys/systm.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>
105 #include <net/if_ether.h>
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>
116 #include "bpfilter.h"
118 #include <sys/select.h>
120 #include <net/bpfdesc.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, ...
148 struct ethercom ns_ec
; /* Ethernet common part */
149 #define ns_if ns_ac.ac_if /* network-visible interface */
151 #define DSF_LOCK 1 /* block re-entering enstart */
154 struct prhdr ns_ph
; /* hardware header of incoming packet */
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 */
167 u_int8_t ns_addrp
[ETHER_ADDR_LEN
]; /* hardware Ethernet address */
170 rndsource_element_t rnd_source
;
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)
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];
195 hpc
= (ns
->ns_port
= dvp
->id_iobase
+ 0x10);
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) {
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 */
215 ns
->ns_mode
= DSDC_WTS
| DSDC_BMS
| DSDC_FT1
;
217 ns
->ns_mode
= DSDC_BMS
| DSDC_FT1
;
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
);
227 outb(hpc
+ ds0_isr
, 0xff);
228 outb(hpc
+ ds_cmd
, DSCM_NODMA
| DSCM_PG0
| DSCM_STOP
);
231 /* Check cmd reg and fail if not right */
232 if ((i
= inb(hpc
+ ds_cmd
)) != (DSCM_NODMA
| DSCM_PG0
| DSCM_STOP
)) {
238 outb(hpc
+ hp_option
, 0);
244 * Fetch from onboard ROM/RAM
246 hpfetch(struct hp_softc
*ns
, void *up
, int ad
, int len
)
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;
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);
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
),
282 /* Execute & extract from card */
283 outb(hpc
+ ds_cmd
, DSCM_RREAD
| DSCM_PG0
| DSCM_START
);
286 if (ns
->ns_mode
& DSDC_WTS
)
287 len
= (void *) insd(hpc
+ hp_data
, up
, len
>> 2) - up
;
290 len
= (void *) insw(hpc
+ hp_data
, up
, len
>> 1) - up
;
293 printf("hpfetch: done len=%d\n", len
);
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
);
306 hpput(struct hp_softc
*ns
, void *up
, int ad
, int len
)
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;
323 len
= (len
+ 1) & ~1;
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
),
336 unsigned char *p
= (unsigned char *) up
;
340 printf(" %02x", *(p
++));
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
);
358 if (ns
->ns_mode
& DSDC_WTS
)
359 len
= (void *) outsd(hpc
+ hp_data
, up
, len
>> 2) - up
;
362 len
= (void *) outsw(hpc
+ hp_data
, up
, len
>> 1) - up
;
365 printf("hpput: done len=%d\n", len
);
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
;
384 printf("hp%d: reset\n", unit
);
385 outb(hpc
+ hp_option
, 0);
386 ns
->ns_flags
&= ~DSF_LOCK
;
411 int n
= sizeof(boards
) / sizeof(boards
[0]);
414 if (boards
[--n
].type
== type
)
415 return boards
[n
].name
;
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
;
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
);
446 bpfattach(&ns
->ns_bpf
, ifp
, DLT_EN10MB
,
447 sizeof(struct ether_header
));
451 rnd_attach_source(&ns
->rnd_source
, device_xname(&ns
->sc_dev
),
457 * Initialization of interface; set up initialization block
458 * and transmit/receive descriptor rings.
462 struct hp_softc
*ns
= &hp_softc
[unit
];
463 struct ifnet
*ifp
= &ns
->ns_if
;
467 int hpc
= ns
->ns_port
;
469 if (IFADDR_EMPTY(ifp
))
471 if (ifp
->if_flags
& IFF_RUNNING
)
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");
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);
485 ns
->ns_rcr
|= DSRC_SEP
;
488 /* set irq and turn on board */
489 outb(hpc
+ hp_option
, HP_RUN
| (ns
->hp_irq
<< 1));
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);
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
;
529 printf("hpinit: done\n", unit
, hpc
);
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
];
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
)
555 if (inb(hpc
+ ds_cmd
) & DSCM_TRANS
)
558 if ((ns
->ns_if
.if_flags
& IFF_RUNNING
) == 0)
561 IFQ_DEQUEUE(&ns
->ns_if
.if_snd
, m
);
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
;
573 total
= len
= m
->m_pkthdr
.len
;
576 printf("hpstart: len=%d\n", len
);
581 bpf_mtap(ns
->ns_bpf
, m
);
584 for (m0
= m
; m
!= 0;) {
585 if (m
->m_len
& 1 && t
> m
->m_len
) {
587 hpput(ns
, mtod(m
, void *), buffer
, m
->m_len
);
590 m
->m_data
+= m
->m_len
;
594 hpput(ns
, mtod(m
, void *), buffer
, m
->m_len
);
603 * Init transmit length registers, and set transmit start flag.
606 if (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
);
616 printf("hpstart: done\n", hpc
);
620 * Controller interrupt.
624 struct hp_softc
*ns
= &hp_softc
[unit
];
626 int hpc
= ns
->ns_port
;
629 /* Save cmd, clear interrupt */
630 cmd
= inb(hpc
+ ds_cmd
);
632 isr
= inb(hpc
+ ds0_isr
);
633 outb(hpc
+ ds_cmd
, DSCM_NODMA
| DSCM_PG0
| DSCM_START
);
634 outb(hpc
+ ds0_isr
, isr
);
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
++;
648 /* We received something */
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
);
664 printf("hpintr: receive isr=0x%02x bnry=0x%02x curr=0x%02x\n",
668 if (++bnry
>= ns
->ns_rxend
)
669 bnry
= ns
->ns_rxstart
;
671 /* if ring empty, done! */
675 addr
= bnry
* DS_PGSIZE
;
677 outb(hpc
+ hp_option
, inb(hpc
+ hp_option
) | HP_DATA
);
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
);
688 hpfetch(ns
, (void *) & ns
->ns_ph
, addr
, sizeof ns
->ns_ph
);
689 addr
+= sizeof ns
->ns_ph
;
692 printf("hpintr: sendp packet hdr: %x %x %x %x\n",
700 if (ns
->ns_ph
.pr_status
& (DSRS_CRC
| DSRS_FO
| DSRS_DFR
)) {
701 /* Get packet header */
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
);
718 for (n
= 0; n
< len
; n
++)
719 printf(" %02x", ns
->ns_pb
[n
]);
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",
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",
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
);
758 printf("hpintr: receive done bnry=0x%02x\n", bnry
);
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);
767 hpread(ns
, (void *) (ns
->ns_pb
), len
);
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 */
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
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
);
798 outb(hpc
+ ds_cmd
, cmd
);
799 outb(hpc
+ ds0_imr
, 0xff);
803 rnd_add_uint32(&sc
->rnd_source
, isr
);
806 /* Still more to do? */
807 isr
= inb(hpc
+ ds0_isr
);
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
;
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;
836 eh
->ether_type
= *hpdataaddr(eh
, off
, u_short
*);
837 resid
= ntohs(*(hpdataaddr(eh
, off
+ 2, u_short
*)));
838 if (off
+ resid
> len
)
849 bpf_tap(ns
->ns_bpf
, buf
, len
+ sizeof(struct ether_header
));
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)
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
);
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.
885 hpget(void *buf
, int totlen
, int off0
, struct ifnet
*ifp
)
887 struct mbuf
*top
, **mp
, *m
, *p
;
892 buf
+= sizeof(struct ether_header
);
898 cp
+= off
+ 2 * sizeof(u_short
);
899 totlen
-= 2 * sizeof(u_short
);
901 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
904 m
->m_pkthdr
.rcvif
= ifp
;
905 m
->m_pkthdr
.len
= totlen
;
912 MGET(m
, M_DONTWAIT
, MT_DATA
);
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
);
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
;
937 memcpy(mtod(m
, void *), cp
, (unsigned) len
);
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;
961 ifp
->if_flags
|= IFF_UP
;
963 hpinit(ifp
->if_unit
);
964 switch (ifa
->ifa_addr
->sa_family
) {
967 ((struct arpcom
*) ifp
)->ac_ipaddr
=
968 IA_SIN(ifa
)->sin_addr
;
969 arpwhohas((struct arpcom
*) ifp
, &IA_SIN(ifa
)->sin_addr
);
978 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
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");
985 /* XXX re-use ether_ioctl() */
986 switch (ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) {
988 ifp
->if_flags
&= ~IFF_RUNNING
;
989 outb(ns
->ns_port
+ ds_cmd
, DSCM_STOP
| DSCM_NODMA
);
992 hpinit(ifp
->if_unit
);
1001 memcpy((void *) & ifr
->ifr_data
, (void *) ns
->ns_addrp
,
1002 sizeof(ns
->ns_addrp
));
1007 error
= ether_ioctl(ifp
, cmd
, data
);