3 ** File: 8390.c May 02, 2000
5 ** Author: Giovanni Falzoni <gfalzoni@inwind.it>
7 ** This file contains an ethernet device driver for NICs
8 ** equipped with the National Semiconductor NS 8390 chip.
9 ** It has to be associated with the board specific driver.
10 ** Rewritten from Minix 2.0.0 ethernet driver dp8390.c
11 ** to extract the NS 8390 common functions.
17 #include <minix/com.h>
19 #include <net/gen/ether.h>
20 #include <net/gen/eth_io.h>
23 #if (ENABLE_DP8390 == 1)
25 #define PIO16 0 /* NOTE: pio 16 functions missing */
30 #define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \
31 sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\
32 (dstProc),D,(vir_bytes)(dstOffs),length)
35 #define sys_user2nic_s(srcProc,grant,dstOffs,length) \
36 sys_safecopyfrom((srcProc),(grant),0, \
37 (vir_bytes)(dstOffs),length,dep->de_memsegm)
40 static char RdmaErrMsg
[] = "remote dma failed to complete";
43 ** Name: void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset);
44 ** Function: Sets the board for reading/writing.
46 static void ns_rw_setup(dpeth_t
*dep
, int mode
, int size
, u16_t offset
)
49 if (mode
== CR_DM_RW
) outb_reg0(dep
, DP_ISR
, ISR_RDC
);
50 outb_reg0(dep
, DP_RBCR0
, size
& 0xFF);
51 outb_reg0(dep
, DP_RBCR1
, (size
>> 8) & 0xFF);
52 outb_reg0(dep
, DP_RSAR0
, offset
& 0xFF);
53 outb_reg0(dep
, DP_RSAR1
, (offset
>> 8) & 0xFF);
54 mode
|= (CR_PS_P0
| CR_STA
);
55 outb_reg0(dep
, DP_CR
, mode
);
60 ** Name: void ns_start_xmit(dpeth_t *dep, int size, int pageno);
61 ** Function: Sets the board for for transmitting and fires it.
63 static void ns_start_xmit(dpeth_t
* dep
, int size
, int pageno
)
66 outb_reg0(dep
, DP_TPSR
, pageno
);
67 outb_reg0(dep
, DP_TBCR1
, size
>> 8);
68 outb_reg0(dep
, DP_TBCR0
, size
& 0xFF);
69 outb_reg0(dep
, DP_CR
, CR_NO_DMA
| CR_STA
| CR_TXP
); /* Fires transmission */
74 ** Name: void mem_getblock(dpeth_t *dep, u16_t offset,
75 ** int size, void *dst)
76 ** Function: Reads a block of packet from board (shared memory).
78 static void mem_getblock(dpeth_t
*dep
, u16_t offset
, int size
, void *dst
)
80 panic(__FILE__
, "mem_getblock: not converted to safecopies", NO_NUM
);
82 sys_nic2mem(dep
->de_linmem
+ offset
, SELF
, dst
, size
);
88 ** Name: void mem_nic2user(dpeth_t *dep, int pageno, int pktsize);
89 ** Function: Copies a packet from board to user area (shared memory).
91 static void mem_nic2user(dpeth_t
* dep
, int pageno
, int pktsize
)
94 iovec_dat_s_t
*iovp
= &dep
->de_read_iovec
;
97 panic(__FILE__
, "mem_nic2user: not converted to safecopies", NO_NUM
);
100 /* Computes shared memory address (skipping receive header) */
101 offset
= pageno
* DP_PAGESIZE
+ sizeof(dp_rcvhdr_t
);
103 do { /* Reads chuncks of packet into user area */
105 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of a chunck */
106 if (bytes
> pktsize
) bytes
= pktsize
;
108 /* Reads from board to user area */
109 if ((offset
+ bytes
) > (dep
->de_stoppage
* DP_PAGESIZE
)) {
111 /* Circular buffer wrap-around */
112 bytes
= dep
->de_stoppage
* DP_PAGESIZE
- offset
;
113 sys_nic2mem_s(dep
->de_linmem
+ offset
, iovp
->iod_proc_nr
,
114 iovp
->iod_iovec
[ix
].iov_grant
, bytes
);
117 bytes
= iovp
->iod_iovec
[ix
].iov_size
- bytes
;
118 if (bytes
> pktsize
) bytes
= pktsize
;
119 offset
= dep
->de_startpage
* DP_PAGESIZE
;
121 sys_nic2mem_s(dep
->de_linmem
+ offset
, iovp
->iod_proc_nr
,
122 iovp
->iod_iovec
[ix
].iov_grant
, bytes
);
125 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
129 /* Till packet done */
130 } while ((pktsize
-= bytes
) > 0);
136 ** Name: void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
137 ** Function: Copies a packet from user area to board (shared memory).
139 static void mem_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
141 phys_bytes offset
, phys_user
;
142 iovec_dat_s_t
*iovp
= &dep
->de_write_iovec
;
145 panic(__FILE__
, "mem_user2nic: not converted to safecopies", NO_NUM
);
148 /* Computes shared memory address */
149 offset
= pageno
* DP_PAGESIZE
;
151 do { /* Reads chuncks of packet from user area */
153 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of chunck */
154 if (bytes
> pktsize
) bytes
= pktsize
;
156 /* Reads from user area to board (shared memory) */
157 sys_user2nic_s(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
158 dep
->de_linmem
+ offset
, bytes
);
161 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
165 /* Till packet done */
166 } while ((pktsize
-= bytes
) > 0);
172 ** Name: void pio_getblock(dpeth_t *dep, u16_t offset,
173 ** int size, void *dst)
174 ** Function: Reads a block of packet from board (Prog. I/O).
176 static void pio_getblock(dpeth_t
*dep
, u16_t offset
, int size
, void *dst
)
179 /* Sets up board for reading */
180 ns_rw_setup(dep
, CR_DM_RR
, size
, offset
);
183 insb(dep
->de_data_port
, SELF
, dst
, size
);
185 if (dep
->de_16bit
== TRUE
) {
186 insw(dep
->de_data_port
, dst
, size
);
188 insb(dep
->de_data_port
, dst
, size
);
195 ** Name: void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
196 ** Function: Copies a packet from board to user area (Prog. I/O).
198 static void pio_nic2user(dpeth_t
*dep
, int pageno
, int pktsize
)
200 iovec_dat_s_t
*iovp
= &dep
->de_read_iovec
;
201 unsigned offset
, iov_offset
; int r
, bytes
, ix
= 0;
203 /* Computes memory address (skipping receive header) */
204 offset
= pageno
* DP_PAGESIZE
+ sizeof(dp_rcvhdr_t
);
205 /* Sets up board for reading */
206 ns_rw_setup(dep
, CR_DM_RR
, ((offset
+ pktsize
) > (dep
->de_stoppage
* DP_PAGESIZE
)) ?
207 (dep
->de_stoppage
* DP_PAGESIZE
) - offset
: pktsize
, offset
);
210 do { /* Reads chuncks of packet into user area */
212 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of a chunck */
213 if (bytes
> pktsize
) bytes
= pktsize
;
215 if ((offset
+ bytes
) > (dep
->de_stoppage
* DP_PAGESIZE
)) {
217 /* Circular buffer wrap-around */
218 bytes
= dep
->de_stoppage
* DP_PAGESIZE
- offset
;
219 r
= sys_safe_insb(dep
->de_data_port
, iovp
->iod_proc_nr
,
220 iovp
->iod_iovec
[ix
].iov_grant
, iov_offset
, bytes
);
223 panic(__FILE__
, "pio_nic2user: sys_safe_insb failed",
228 bytes
= iovp
->iod_iovec
[ix
].iov_size
- bytes
;
229 if (bytes
> pktsize
) bytes
= pktsize
;
230 offset
= dep
->de_startpage
* DP_PAGESIZE
;
231 ns_rw_setup(dep
, CR_DM_RR
, pktsize
, offset
);
233 r
= sys_safe_insb(dep
->de_data_port
, iovp
->iod_proc_nr
,
234 iovp
->iod_iovec
[ix
].iov_grant
, iov_offset
, bytes
);
236 panic(__FILE__
, "pio_nic2user: sys_safe_insb failed", r
);
239 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
244 /* Till packet done */
245 } while ((pktsize
-= bytes
) > 0);
250 ** Name: void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
251 ** Function: Copies a packet from user area to board (Prog. I/O).
253 static void pio_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
255 iovec_dat_s_t
*iovp
= &dep
->de_write_iovec
;
256 int r
, bytes
, ix
= 0;
258 /* Sets up board for writing */
259 ns_rw_setup(dep
, CR_DM_RW
, pktsize
, pageno
* DP_PAGESIZE
);
261 do { /* Reads chuncks of packet from user area */
263 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of chunck */
264 if (bytes
> pktsize
) bytes
= pktsize
;
265 r
= sys_safe_outsb(dep
->de_data_port
, iovp
->iod_proc_nr
,
266 iovp
->iod_iovec
[ix
].iov_grant
, 0, bytes
);
268 panic(__FILE__
, "pio_user2nic: sys_safe_outsb failed", r
);
270 if (++ix
>= IOVEC_NR
) { /* Next buffer of I/O vector */
274 /* Till packet done */
275 } while ((pktsize
-= bytes
) > 0);
277 for (ix
= 0; ix
< 100; ix
+= 1) {
278 if (inb_reg0(dep
, DP_ISR
) & ISR_RDC
) break;
281 panic(dep
->de_name
, RdmaErrMsg
, NO_NUM
);
287 ** Name: void ns_stats(dpeth_t * dep)
288 ** Function: Updates counters reading from device
290 static void ns_stats(dpeth_t
* dep
)
293 dep
->de_stat
.ets_CRCerr
+= inb_reg0(dep
, DP_CNTR0
);
294 dep
->de_stat
.ets_recvErr
+= inb_reg0(dep
, DP_CNTR1
);
295 dep
->de_stat
.ets_fifoOver
+= inb_reg0(dep
, DP_CNTR2
);
300 ** Name: void ns_dodump(dpeth_t * dep)
301 ** Function: Displays statistics (a request from F5 key).
303 static void ns_dodump(dpeth_t
* dep
)
306 ns_stats(dep
); /* Forces reading fo counters from board */
311 ** Name: void ns_reinit(dpeth_t *dep)
312 ** Function: Updates receiver configuration.
314 static void ns_reinit(dpeth_t
* dep
)
318 if (dep
->de_flags
& DEF_PROMISC
) dp_reg
|= RCR_AB
| RCR_PRO
| RCR_AM
;
319 if (dep
->de_flags
& DEF_BROAD
) dp_reg
|= RCR_AB
;
320 if (dep
->de_flags
& DEF_MULTI
) dp_reg
|= RCR_AM
;
321 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
322 outb_reg0(dep
, DP_RCR
, dp_reg
);
327 ** Name: void ns_send(dpeth_t * dep, int from_int, int size)
328 ** Function: Transfers packet to device and starts sending.
330 static void ns_send(dpeth_t
* dep
, int from_int
, int size
)
334 if (queue
= dep
->de_sendq_head
, dep
->de_sendq
[queue
].sq_filled
) {
335 if (from_int
) panic(dep
->de_name
, "should not be sending ", NO_NUM
);
336 dep
->de_send_s
= size
;
339 (dep
->de_user2nicf
) (dep
, dep
->de_sendq
[queue
].sq_sendpage
, size
);
340 dep
->bytes_Tx
+= (long) size
;
341 dep
->de_sendq
[queue
].sq_filled
= TRUE
;
342 dep
->de_flags
|= (DEF_XMIT_BUSY
| DEF_ACK_SEND
);
343 if (dep
->de_sendq_tail
== queue
) { /* there it goes.. */
344 ns_start_xmit(dep
, size
, dep
->de_sendq
[queue
].sq_sendpage
);
346 dep
->de_sendq
[queue
].sq_size
= size
;
348 if (++queue
== dep
->de_sendq_nr
) queue
= 0;
349 dep
->de_sendq_head
= queue
;
350 dep
->de_flags
&= NOT(DEF_SENDING
);
356 ** Name: void ns_reset(dpeth_t *dep)
357 ** Function: Resets device.
359 static void ns_reset(dpeth_t
* dep
)
364 outb_reg0(dep
, DP_CR
, CR_STP
| CR_NO_DMA
);
365 outb_reg0(dep
, DP_RBCR0
, 0);
366 outb_reg0(dep
, DP_RBCR1
, 0);
367 for (ix
= 0; ix
< 0x1000 && ((inb_reg0(dep
, DP_ISR
) & ISR_RST
) == 0); ix
+= 1)
369 outb_reg0(dep
, DP_TCR
, TCR_1EXTERNAL
| TCR_OFST
);
370 outb_reg0(dep
, DP_CR
, CR_STA
| CR_NO_DMA
);
371 outb_reg0(dep
, DP_TCR
, TCR_NORMAL
| TCR_OFST
);
373 /* Acknowledge the ISR_RDC (remote dma) interrupt. */
374 for (ix
= 0; ix
< 0x1000 && ((inb_reg0(dep
, DP_ISR
) & ISR_RDC
) == 0); ix
+= 1)
376 outb_reg0(dep
, DP_ISR
, inb_reg0(dep
, DP_ISR
) & NOT(ISR_RDC
));
378 /* Reset the transmit ring. If we were transmitting a packet, we
379 * pretend that the packet is processed. Higher layers will
380 * retransmit if the packet wasn't actually sent. */
381 dep
->de_sendq_head
= dep
->de_sendq_tail
= 0;
382 for (ix
= 0; ix
< dep
->de_sendq_nr
; ix
++)
383 dep
->de_sendq
[ix
].sq_filled
= FALSE
;
384 ns_send(dep
, TRUE
, dep
->de_send_s
);
389 ** Name: void ns_recv(dpeth_t *dep, int fromint, int size)
390 ** Function: Gets a packet from device
392 static void ns_recv(dpeth_t
*dep
, int fromint
, int size
)
396 unsigned pageno
, curr
, next
;
398 int packet_processed
= FALSE
;
403 pageno
= inb_reg0(dep
, DP_BNRY
) + 1;
404 if (pageno
== dep
->de_stoppage
) pageno
= dep
->de_startpage
;
408 outb_reg0(dep
, DP_CR
, CR_PS_P1
);
409 curr
= inb_reg1(dep
, DP_CURR
);
410 outb_reg0(dep
, DP_CR
, CR_PS_P0
| CR_NO_DMA
| CR_STA
);
412 if (curr
== pageno
) break;
414 (dep
->de_getblockf
) (dep
, pageno
* DP_PAGESIZE
, sizeof(header
), &header
);
416 (dep
->de_getblockf
) (dep
, pageno
* DP_PAGESIZE
+ sizeof(header
) + 2 * sizeof(ether_addr_t
), sizeof(eth_type
), ð_type
);
418 length
= (header
.dr_rbcl
| (header
.dr_rbch
<< 8)) - sizeof(dp_rcvhdr_t
);
419 next
= header
.dr_next
;
421 if (length
< ETH_MIN_PACK_SIZE
|| length
> ETH_MAX_PACK_SIZE
) {
422 printf("%s: packet with strange length arrived: %d\n", dep
->de_name
, length
);
423 dep
->de_stat
.ets_recvErr
+= 1;
426 } else if (next
< dep
->de_startpage
|| next
>= dep
->de_stoppage
) {
427 printf("%s: strange next page\n", dep
->de_name
);
428 dep
->de_stat
.ets_recvErr
+= 1;
432 } else if (eth_type
== eth_ign_proto
) {
433 /* Hack: ignore packets of a given protocol */
434 static int first
= TRUE
;
437 printf("%s: dropping proto %04x packet\n", dep
->de_name
, ntohs(eth_ign_proto
));
441 } else if (header
.dr_status
& RSR_FO
) {
442 /* This is very serious, issue a warning and reset buffers */
443 printf("%s: fifo overrun, resetting receive buffer\n", dep
->de_name
);
444 dep
->de_stat
.ets_fifoOver
+= 1;
447 } else if ((header
.dr_status
& RSR_PRX
) && (dep
->de_flags
& DEF_ENABLED
)) {
449 if (!(dep
->de_flags
& DEF_READING
)) break;
451 (dep
->de_nic2userf
) (dep
, pageno
, length
);
452 dep
->de_read_s
= length
;
453 dep
->de_flags
|= DEF_ACK_RECV
;
454 dep
->de_flags
&= NOT(DEF_READING
);
455 packet_processed
= TRUE
;
457 dep
->bytes_Rx
+= (long) length
;
458 dep
->de_stat
.ets_packetR
+= 1;
459 outb_reg0(dep
, DP_BNRY
, (next
== dep
->de_startpage
? dep
->de_stoppage
: next
) - 1);
462 } while (!packet_processed
);
464 if ((dep
->de_flags
& (DEF_READING
| DEF_STOPPED
)) == (DEF_READING
| DEF_STOPPED
))
465 /* The chip is stopped, and all arrived packets delivered */
466 (*dep
->de_resetf
) (dep
);
467 dep
->de_flags
&= NOT(DEF_STOPPED
);
473 ** Name: void ns_interrupt(dpeth_t * dep)
474 ** Function: Handles interrupt.
476 static void ns_interrupt(dpeth_t
* dep
)
481 while ((isr
= inb_reg0(dep
, DP_ISR
)) != 0) {
483 outb_reg0(dep
, DP_ISR
, isr
);
484 if (isr
& (ISR_PTX
| ISR_TXE
)) {
486 tsr
= inb_reg0(dep
, DP_TSR
);
488 dep
->de_stat
.ets_packetT
++;
490 if (tsr
& TSR_COL
) dep
->de_stat
.ets_collision
++;
491 if (tsr
& (TSR_ABT
| TSR_FU
)) {
492 dep
->de_stat
.ets_fifoUnder
++;
494 if ((isr
& ISR_TXE
) || (tsr
& (TSR_CRS
| TSR_CDH
| TSR_OWC
))) {
495 printf("%s: got send Error (0x%02X)\n", dep
->de_name
, tsr
);
496 dep
->de_stat
.ets_sendErr
++;
498 queue
= dep
->de_sendq_tail
;
500 if (!(dep
->de_sendq
[queue
].sq_filled
)) { /* Hardware bug? */
501 printf("%s: transmit interrupt, but not sending\n", dep
->de_name
);
504 dep
->de_sendq
[queue
].sq_filled
= FALSE
;
505 if (++queue
== dep
->de_sendq_nr
) queue
= 0;
506 dep
->de_sendq_tail
= queue
;
507 if (dep
->de_sendq
[queue
].sq_filled
) {
508 ns_start_xmit(dep
, dep
->de_sendq
[queue
].sq_size
,
509 dep
->de_sendq
[queue
].sq_sendpage
);
511 if (dep
->de_flags
& DEF_SENDING
) {
512 ns_send(dep
, TRUE
, dep
->de_send_s
);
516 ns_recv(dep
, TRUE
, 0);
519 printf("%s: got recv Error (0x%04X)\n", dep
->de_name
, inb_reg0(dep
, DP_RSR
));
520 dep
->de_stat
.ets_recvErr
++;
523 dep
->de_stat
.ets_CRCerr
+= inb_reg0(dep
, DP_CNTR0
);
524 dep
->de_stat
.ets_recvErr
+= inb_reg0(dep
, DP_CNTR1
);
525 dep
->de_stat
.ets_fifoOver
+= inb_reg0(dep
, DP_CNTR2
);
528 printf("%s: got overwrite warning\n", dep
->de_name
);
534 /* This means we got an interrupt but the ethernet
535 * chip is shutdown. We set the flag DEF_STOPPED, and
536 * continue processing arrived packets. When the
537 * receive buffer is empty, we reset the dp8390. */
538 printf("%s: network interface stopped\n", dep
->de_name
);
539 dep
->de_flags
|= DEF_STOPPED
;
543 if ((dep
->de_flags
& (DEF_READING
| DEF_STOPPED
)) == (DEF_READING
| DEF_STOPPED
)) {
545 /* The chip is stopped, and all arrived packets delivered */
547 dep
->de_flags
&= NOT(DEF_STOPPED
);
553 ** Name: void ns_init(dpeth_t *dep)
554 ** Function: Initializes the NS 8390
556 void ns_init(dpeth_t
* dep
)
561 /* NS8390 initialization (as recommended in National Semiconductor specs) */
562 outb_reg0(dep
, DP_CR
, CR_PS_P0
| CR_STP
| CR_NO_DMA
); /* 0x21 */
564 outb_reg0(dep
, DP_DCR
, (DCR_BYTEWIDE
| DCR_LTLENDIAN
| DCR_8BYTES
| DCR_BMS
));
566 outb_reg0(dep
, DP_DCR
, (((dep
->de_16bit
) ? DCR_WORDWIDE
: DCR_BYTEWIDE
) |
567 DCR_LTLENDIAN
| DCR_8BYTES
| DCR_BMS
));
569 outb_reg0(dep
, DP_RBCR0
, 0);
570 outb_reg0(dep
, DP_RBCR1
, 0);
571 outb_reg0(dep
, DP_RCR
, RCR_MON
); /* Sets Monitor mode */
572 outb_reg0(dep
, DP_TCR
, TCR_INTERNAL
); /* Sets Loopback mode 1 */
573 outb_reg0(dep
, DP_PSTART
, dep
->de_startpage
);
574 outb_reg0(dep
, DP_PSTOP
, dep
->de_stoppage
);
575 outb_reg0(dep
, DP_BNRY
, dep
->de_stoppage
- 1);
576 outb_reg0(dep
, DP_ISR
, 0xFF); /* Clears Interrupt Status Register */
577 outb_reg0(dep
, DP_IMR
, 0); /* Clears Interrupt Mask Register */
579 /* Copies station address in page 1 registers */
580 outb_reg0(dep
, DP_CR
, CR_PS_P1
| CR_NO_DMA
); /* Selects Page 1 */
581 for (ix
= 0; ix
< SA_ADDR_LEN
; ix
+= 1) /* Initializes address */
582 outb_reg1(dep
, DP_PAR0
+ ix
, dep
->de_address
.ea_addr
[ix
]);
583 for (ix
= DP_MAR0
; ix
<= DP_MAR7
; ix
+= 1) /* Initializes address */
584 outb_reg1(dep
, ix
, 0xFF);
586 outb_reg1(dep
, DP_CURR
, dep
->de_startpage
);
587 outb_reg1(dep
, DP_CR
, CR_PS_P0
| CR_NO_DMA
); /* Selects Page 0 */
589 inb_reg0(dep
, DP_CNTR0
); /* Resets counters by reading them */
590 inb_reg0(dep
, DP_CNTR1
);
591 inb_reg0(dep
, DP_CNTR2
);
593 dp_reg
= IMR_PRXE
| IMR_PTXE
| IMR_RXEE
| IMR_TXEE
| IMR_OVWE
| IMR_CNTE
;
594 outb_reg0(dep
, DP_ISR
, 0xFF); /* Clears Interrupt Status Register */
595 outb_reg0(dep
, DP_IMR
, dp_reg
); /* Sets Interrupt Mask register */
598 if (dep
->de_flags
& DEF_PROMISC
) dp_reg
|= RCR_AB
| RCR_PRO
| RCR_AM
;
599 if (dep
->de_flags
& DEF_BROAD
) dp_reg
|= RCR_AB
;
600 if (dep
->de_flags
& DEF_MULTI
) dp_reg
|= RCR_AM
;
601 outb_reg0(dep
, DP_RCR
, dp_reg
); /* Sets receive as requested */
602 outb_reg0(dep
, DP_TCR
, TCR_NORMAL
); /* Sets transmitter */
604 outb_reg0(dep
, DP_CR
, CR_STA
| CR_NO_DMA
); /* Starts board */
606 /* Initializes the send queue. */
607 for (ix
= 0; ix
< dep
->de_sendq_nr
; ix
+= 1)
608 dep
->de_sendq
[ix
].sq_filled
= 0;
609 dep
->de_sendq_head
= dep
->de_sendq_tail
= 0;
611 /* Device specific functions */
612 if (!dep
->de_prog_IO
) {
613 dep
->de_user2nicf
= mem_user2nic
;
614 dep
->de_nic2userf
= mem_nic2user
;
615 dep
->de_getblockf
= mem_getblock
;
618 dep
->de_user2nicf
= pio_user2nic
;
619 dep
->de_nic2userf
= pio_nic2user
;
620 dep
->de_getblockf
= pio_getblock
;
622 #error Missing I/O functions for pio 16 bits
625 dep
->de_recvf
= ns_recv
;
626 dep
->de_sendf
= ns_send
;
627 dep
->de_flagsf
= ns_reinit
;
628 dep
->de_resetf
= ns_reset
;
629 dep
->de_getstatsf
= ns_stats
;
630 dep
->de_dumpstatsf
= ns_dodump
;
631 dep
->de_interruptf
= ns_interrupt
;
639 ** Name: void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize)
640 ** Function: Copies a packet from user area to board (Prog. I/O, 16bits).
642 static void dp_pio16_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
645 phys_bytes phys_user
, phys_2bytes
= vir2phys(two_bytes
);
646 vir_bytes ecount
= (pktsize
+ 1) & NOT(0x0001);
647 int bytes
, ix
= 0, odd_byte
= 0;
648 iovec_dat_t
*iovp
= &dep
->de_write_iovec
;
650 outb_reg0(dep
, DP_ISR
, ISR_RDC
);
651 dp_read_setup(dep
, ecount
, pageno
* DP_PAGESIZE
);
654 bytes
= iovp
->iod_iovec
[ix
].iov_size
;
655 if (bytes
> pktsize
) bytes
= pktsize
;
657 phys_user
= numap(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_addr
, bytes
);
658 if (!phys_user
) panic(dep
->de_name
, UmapErrMsg
, NO_NUM
);
661 phys_copy(phys_user
, phys_2bytes
+ 1, (phys_bytes
) 1);
662 out_word(dep
->de_data_port
, *(u16_t
*)two_bytes
);
667 if (!bytes
) continue;
669 ecount
= bytes
& NOT(0x0001);
671 phys_outsw(dep
->de_data_port
, phys_user
, ecount
);
677 phys_copy(phys_user
, phys_2bytes
, (phys_bytes
) 1);
683 if (++ix
>= IOVEC_NR
) { /* Next buffer of I/O vector */
690 if (odd_byte
) out_word(dep
->de_data_port
, *(u16_t
*) two_bytes
);
691 for (ix
= 0; ix
< 100; ix
++) {
692 if (inb_reg0(dep
, DP_ISR
) & ISR_RDC
) break;
695 panic(dep
->de_name
, RdmaErrMsg
, NO_NUM
);
701 ** Name: void dp_pio16_nic2user(dpeth_t *dep, int pageno, int pktsize)
702 ** Function: Copies a packet from board to user area (Prog. I/O, 16bits).
704 static void dp_pio16_nic2user(dpeth_t
* dep
, int nic_addr
, int count
)
706 phys_bytes phys_user
;
710 phys_bytes phys_2bytes
;
713 ecount
= (count
+ 1) & ~1;
714 phys_2bytes
= vir2phys(two_bytes
);
717 dp_read_setup(dep
, ecount
, nic_addr
);
726 bytes
= iovp
->iod_iovec
[i
].iov_size
;
727 if (bytes
> count
) bytes
= count
;
729 phys_user
= numap(iovp
->iod_proc_nr
,
730 iovp
->iod_iovec
[i
].iov_addr
, bytes
);
731 if (!phys_user
) panic(dep
->de_name
, UmapErrMsg
, NO_NUM
);
733 phys_copy(phys_2bytes
+ 1, phys_user
, (phys_bytes
) 1);
738 if (!bytes
) continue;
742 phys_insw(dep
->de_data_port
, phys_user
, ecount
);
748 *(u16_t
*) two_bytes
= in_word(dep
->de_data_port
);
749 phys_copy(phys_2bytes
, phys_user
, (phys_bytes
) 1);
759 #endif /* PIO16 == 1 */
761 #endif /* ENABLE_DP8390 */