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>
18 #include <net/gen/ether.h>
19 #include <net/gen/eth_io.h>
22 #if (ENABLE_DP8390 == 1)
24 #define PIO16 0 /* NOTE: pio 16 functions missing */
29 #define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \
30 sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\
31 (dstProc),D,(vir_bytes)(dstOffs),length)
34 #define sys_user2nic_s(srcProc,grant,dstOffs,length) \
35 sys_safecopyfrom((srcProc),(grant),0, \
36 (vir_bytes)(dstOffs),length,dep->de_memsegm)
39 static char RdmaErrMsg
[] = "remote dma failed to complete";
42 ** Name: void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset);
43 ** Function: Sets the board for reading/writing.
45 static void ns_rw_setup(dpeth_t
*dep
, int mode
, int size
, u16_t offset
)
48 if (mode
== CR_DM_RW
) outb_reg0(dep
, DP_ISR
, ISR_RDC
);
49 outb_reg0(dep
, DP_RBCR0
, size
& 0xFF);
50 outb_reg0(dep
, DP_RBCR1
, (size
>> 8) & 0xFF);
51 outb_reg0(dep
, DP_RSAR0
, offset
& 0xFF);
52 outb_reg0(dep
, DP_RSAR1
, (offset
>> 8) & 0xFF);
53 mode
|= (CR_PS_P0
| CR_STA
);
54 outb_reg0(dep
, DP_CR
, mode
);
59 ** Name: void ns_start_xmit(dpeth_t *dep, int size, int pageno);
60 ** Function: Sets the board for for transmitting and fires it.
62 static void ns_start_xmit(dpeth_t
* dep
, int size
, int pageno
)
65 outb_reg0(dep
, DP_TPSR
, pageno
);
66 outb_reg0(dep
, DP_TBCR1
, size
>> 8);
67 outb_reg0(dep
, DP_TBCR0
, size
& 0xFF);
68 outb_reg0(dep
, DP_CR
, CR_NO_DMA
| CR_STA
| CR_TXP
); /* Fires transmission */
73 ** Name: void mem_getblock(dpeth_t *dep, u16_t offset,
74 ** int size, void *dst)
75 ** Function: Reads a block of packet from board (shared memory).
77 static void mem_getblock(dpeth_t
*dep
, u16_t offset
, int size
, void *dst
)
79 panic("mem_getblock: not converted to safecopies");
81 sys_nic2mem(dep
->de_linmem
+ offset
, SELF
, dst
, size
);
87 ** Name: void mem_nic2user(dpeth_t *dep, int pageno, int pktsize);
88 ** Function: Copies a packet from board to user area (shared memory).
90 static void mem_nic2user(dpeth_t
* dep
, int pageno
, int pktsize
)
93 iovec_dat_s_t
*iovp
= &dep
->de_read_iovec
;
96 panic("mem_nic2user: not converted to safecopies");
99 /* Computes shared memory address (skipping receive header) */
100 offset
= pageno
* DP_PAGESIZE
+ sizeof(dp_rcvhdr_t
);
102 do { /* Reads chuncks of packet into user area */
104 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of a chunck */
105 if (bytes
> pktsize
) bytes
= pktsize
;
107 /* Reads from board to user area */
108 if ((offset
+ bytes
) > (dep
->de_stoppage
* DP_PAGESIZE
)) {
110 /* Circular buffer wrap-around */
111 bytes
= dep
->de_stoppage
* DP_PAGESIZE
- offset
;
112 sys_nic2mem_s(dep
->de_linmem
+ offset
, iovp
->iod_proc_nr
,
113 iovp
->iod_iovec
[ix
].iov_grant
, bytes
);
116 bytes
= iovp
->iod_iovec
[ix
].iov_size
- bytes
;
117 if (bytes
> pktsize
) bytes
= pktsize
;
118 offset
= dep
->de_startpage
* DP_PAGESIZE
;
120 sys_nic2mem_s(dep
->de_linmem
+ offset
, iovp
->iod_proc_nr
,
121 iovp
->iod_iovec
[ix
].iov_grant
, bytes
);
124 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
128 /* Till packet done */
129 } while ((pktsize
-= bytes
) > 0);
135 ** Name: void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
136 ** Function: Copies a packet from user area to board (shared memory).
138 static void mem_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
140 phys_bytes offset
, phys_user
;
141 iovec_dat_s_t
*iovp
= &dep
->de_write_iovec
;
144 panic("mem_user2nic: not converted to safecopies");
147 /* Computes shared memory address */
148 offset
= pageno
* DP_PAGESIZE
;
150 do { /* Reads chuncks of packet from user area */
152 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of chunck */
153 if (bytes
> pktsize
) bytes
= pktsize
;
155 /* Reads from user area to board (shared memory) */
156 sys_user2nic_s(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
157 dep
->de_linmem
+ offset
, bytes
);
160 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
164 /* Till packet done */
165 } while ((pktsize
-= bytes
) > 0);
171 ** Name: void pio_getblock(dpeth_t *dep, u16_t offset,
172 ** int size, void *dst)
173 ** Function: Reads a block of packet from board (Prog. I/O).
175 static void pio_getblock(dpeth_t
*dep
, u16_t offset
, int size
, void *dst
)
178 /* Sets up board for reading */
179 ns_rw_setup(dep
, CR_DM_RR
, size
, offset
);
182 insb(dep
->de_data_port
, SELF
, dst
, size
);
184 if (dep
->de_16bit
== TRUE
) {
185 insw(dep
->de_data_port
, dst
, size
);
187 insb(dep
->de_data_port
, dst
, size
);
194 ** Name: void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
195 ** Function: Copies a packet from board to user area (Prog. I/O).
197 static void pio_nic2user(dpeth_t
*dep
, int pageno
, int pktsize
)
199 iovec_dat_s_t
*iovp
= &dep
->de_read_iovec
;
200 unsigned offset
, iov_offset
; int r
, bytes
, ix
= 0;
202 /* Computes memory address (skipping receive header) */
203 offset
= pageno
* DP_PAGESIZE
+ sizeof(dp_rcvhdr_t
);
204 /* Sets up board for reading */
205 ns_rw_setup(dep
, CR_DM_RR
, ((offset
+ pktsize
) > (dep
->de_stoppage
* DP_PAGESIZE
)) ?
206 (dep
->de_stoppage
* DP_PAGESIZE
) - offset
: pktsize
, offset
);
209 do { /* Reads chuncks of packet into user area */
211 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of a chunck */
212 if (bytes
> pktsize
) bytes
= pktsize
;
214 if ((offset
+ bytes
) > (dep
->de_stoppage
* DP_PAGESIZE
)) {
216 /* Circular buffer wrap-around */
217 bytes
= dep
->de_stoppage
* DP_PAGESIZE
- offset
;
218 r
= sys_safe_insb(dep
->de_data_port
, iovp
->iod_proc_nr
,
219 iovp
->iod_iovec
[ix
].iov_grant
, iov_offset
, bytes
);
221 panic("pio_nic2user: sys_safe_insb failed: %d", r
);
225 bytes
= iovp
->iod_iovec
[ix
].iov_size
- bytes
;
226 if (bytes
> pktsize
) bytes
= pktsize
;
227 offset
= dep
->de_startpage
* DP_PAGESIZE
;
228 ns_rw_setup(dep
, CR_DM_RR
, pktsize
, offset
);
230 r
= sys_safe_insb(dep
->de_data_port
, iovp
->iod_proc_nr
,
231 iovp
->iod_iovec
[ix
].iov_grant
, iov_offset
, bytes
);
233 panic("pio_nic2user: sys_safe_insb failed: %d", r
);
236 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
241 /* Till packet done */
242 } while ((pktsize
-= bytes
) > 0);
247 ** Name: void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
248 ** Function: Copies a packet from user area to board (Prog. I/O).
250 static void pio_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
252 iovec_dat_s_t
*iovp
= &dep
->de_write_iovec
;
253 int r
, bytes
, ix
= 0;
255 /* Sets up board for writing */
256 ns_rw_setup(dep
, CR_DM_RW
, pktsize
, pageno
* DP_PAGESIZE
);
258 do { /* Reads chuncks of packet from user area */
260 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of chunck */
261 if (bytes
> pktsize
) bytes
= pktsize
;
262 r
= sys_safe_outsb(dep
->de_data_port
, iovp
->iod_proc_nr
,
263 iovp
->iod_iovec
[ix
].iov_grant
, 0, bytes
);
265 panic("pio_user2nic: sys_safe_outsb failed: %d", r
);
267 if (++ix
>= IOVEC_NR
) { /* Next buffer of I/O vector */
271 /* Till packet done */
272 } while ((pktsize
-= bytes
) > 0);
274 for (ix
= 0; ix
< 100; ix
+= 1) {
275 if (inb_reg0(dep
, DP_ISR
) & ISR_RDC
) break;
284 ** Name: void ns_stats(dpeth_t * dep)
285 ** Function: Updates counters reading from device
287 static void ns_stats(dpeth_t
* dep
)
290 dep
->de_stat
.ets_CRCerr
+= inb_reg0(dep
, DP_CNTR0
);
291 dep
->de_stat
.ets_recvErr
+= inb_reg0(dep
, DP_CNTR1
);
292 dep
->de_stat
.ets_fifoOver
+= inb_reg0(dep
, DP_CNTR2
);
297 ** Name: void ns_dodump(dpeth_t * dep)
298 ** Function: Displays statistics (a request from F5 key).
300 static void ns_dodump(dpeth_t
* dep
)
303 ns_stats(dep
); /* Forces reading fo counters from board */
308 ** Name: void ns_reinit(dpeth_t *dep)
309 ** Function: Updates receiver configuration.
311 static void ns_reinit(dpeth_t
* dep
)
315 if (dep
->de_flags
& DEF_PROMISC
) dp_reg
|= RCR_AB
| RCR_PRO
| RCR_AM
;
316 if (dep
->de_flags
& DEF_BROAD
) dp_reg
|= RCR_AB
;
317 if (dep
->de_flags
& DEF_MULTI
) dp_reg
|= RCR_AM
;
318 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
319 outb_reg0(dep
, DP_RCR
, dp_reg
);
324 ** Name: void ns_send(dpeth_t * dep, int from_int, int size)
325 ** Function: Transfers packet to device and starts sending.
327 static void ns_send(dpeth_t
* dep
, int from_int
, int size
)
331 if (queue
= dep
->de_sendq_head
, dep
->de_sendq
[queue
].sq_filled
) {
332 if (from_int
) panic("should not be sending ");
333 dep
->de_send_s
= size
;
336 (dep
->de_user2nicf
) (dep
, dep
->de_sendq
[queue
].sq_sendpage
, size
);
337 dep
->bytes_Tx
+= (long) size
;
338 dep
->de_sendq
[queue
].sq_filled
= TRUE
;
339 dep
->de_flags
|= (DEF_XMIT_BUSY
| DEF_ACK_SEND
);
340 if (dep
->de_sendq_tail
== queue
) { /* there it goes.. */
341 ns_start_xmit(dep
, size
, dep
->de_sendq
[queue
].sq_sendpage
);
343 dep
->de_sendq
[queue
].sq_size
= size
;
345 if (++queue
== dep
->de_sendq_nr
) queue
= 0;
346 dep
->de_sendq_head
= queue
;
347 dep
->de_flags
&= NOT(DEF_SENDING
);
353 ** Name: void ns_reset(dpeth_t *dep)
354 ** Function: Resets device.
356 static void ns_reset(dpeth_t
* dep
)
361 outb_reg0(dep
, DP_CR
, CR_STP
| CR_NO_DMA
);
362 outb_reg0(dep
, DP_RBCR0
, 0);
363 outb_reg0(dep
, DP_RBCR1
, 0);
364 for (ix
= 0; ix
< 0x1000 && ((inb_reg0(dep
, DP_ISR
) & ISR_RST
) == 0); ix
+= 1)
366 outb_reg0(dep
, DP_TCR
, TCR_1EXTERNAL
| TCR_OFST
);
367 outb_reg0(dep
, DP_CR
, CR_STA
| CR_NO_DMA
);
368 outb_reg0(dep
, DP_TCR
, TCR_NORMAL
| TCR_OFST
);
370 /* Acknowledge the ISR_RDC (remote dma) interrupt. */
371 for (ix
= 0; ix
< 0x1000 && ((inb_reg0(dep
, DP_ISR
) & ISR_RDC
) == 0); ix
+= 1)
373 outb_reg0(dep
, DP_ISR
, inb_reg0(dep
, DP_ISR
) & NOT(ISR_RDC
));
375 /* Reset the transmit ring. If we were transmitting a packet, we
376 * pretend that the packet is processed. Higher layers will
377 * retransmit if the packet wasn't actually sent. */
378 dep
->de_sendq_head
= dep
->de_sendq_tail
= 0;
379 for (ix
= 0; ix
< dep
->de_sendq_nr
; ix
++)
380 dep
->de_sendq
[ix
].sq_filled
= FALSE
;
381 ns_send(dep
, TRUE
, dep
->de_send_s
);
386 ** Name: void ns_recv(dpeth_t *dep, int fromint, int size)
387 ** Function: Gets a packet from device
389 static void ns_recv(dpeth_t
*dep
, int fromint
, int size
)
393 unsigned pageno
, curr
, next
;
395 int packet_processed
= FALSE
;
400 pageno
= inb_reg0(dep
, DP_BNRY
) + 1;
401 if (pageno
== dep
->de_stoppage
) pageno
= dep
->de_startpage
;
405 outb_reg0(dep
, DP_CR
, CR_PS_P1
);
406 curr
= inb_reg1(dep
, DP_CURR
);
407 outb_reg0(dep
, DP_CR
, CR_PS_P0
| CR_NO_DMA
| CR_STA
);
409 if (curr
== pageno
) break;
411 (dep
->de_getblockf
) (dep
, pageno
* DP_PAGESIZE
, sizeof(header
), &header
);
413 (dep
->de_getblockf
) (dep
, pageno
* DP_PAGESIZE
+ sizeof(header
) + 2 * sizeof(ether_addr_t
), sizeof(eth_type
), ð_type
);
415 length
= (header
.dr_rbcl
| (header
.dr_rbch
<< 8)) - sizeof(dp_rcvhdr_t
);
416 next
= header
.dr_next
;
418 if (length
< ETH_MIN_PACK_SIZE
|| length
> ETH_MAX_PACK_SIZE
) {
419 printf("%s: packet with strange length arrived: %d\n", dep
->de_name
, length
);
420 dep
->de_stat
.ets_recvErr
+= 1;
423 } else if (next
< dep
->de_startpage
|| next
>= dep
->de_stoppage
) {
424 printf("%s: strange next page\n", dep
->de_name
);
425 dep
->de_stat
.ets_recvErr
+= 1;
429 } else if (eth_type
== eth_ign_proto
) {
430 /* Hack: ignore packets of a given protocol */
431 static int first
= TRUE
;
434 printf("%s: dropping proto %04x packet\n", dep
->de_name
, ntohs(eth_ign_proto
));
438 } else if (header
.dr_status
& RSR_FO
) {
439 /* This is very serious, issue a warning and reset buffers */
440 printf("%s: fifo overrun, resetting receive buffer\n", dep
->de_name
);
441 dep
->de_stat
.ets_fifoOver
+= 1;
444 } else if ((header
.dr_status
& RSR_PRX
) && (dep
->de_flags
& DEF_ENABLED
)) {
446 if (!(dep
->de_flags
& DEF_READING
)) break;
448 (dep
->de_nic2userf
) (dep
, pageno
, length
);
449 dep
->de_read_s
= length
;
450 dep
->de_flags
|= DEF_ACK_RECV
;
451 dep
->de_flags
&= NOT(DEF_READING
);
452 packet_processed
= TRUE
;
454 dep
->bytes_Rx
+= (long) length
;
455 dep
->de_stat
.ets_packetR
+= 1;
456 outb_reg0(dep
, DP_BNRY
, (next
== dep
->de_startpage
? dep
->de_stoppage
: next
) - 1);
459 } while (!packet_processed
);
461 if ((dep
->de_flags
& (DEF_READING
| DEF_STOPPED
)) == (DEF_READING
| DEF_STOPPED
))
462 /* The chip is stopped, and all arrived packets delivered */
463 (*dep
->de_resetf
) (dep
);
464 dep
->de_flags
&= NOT(DEF_STOPPED
);
470 ** Name: void ns_interrupt(dpeth_t * dep)
471 ** Function: Handles interrupt.
473 static void ns_interrupt(dpeth_t
* dep
)
478 while ((isr
= inb_reg0(dep
, DP_ISR
)) != 0) {
480 outb_reg0(dep
, DP_ISR
, isr
);
481 if (isr
& (ISR_PTX
| ISR_TXE
)) {
483 tsr
= inb_reg0(dep
, DP_TSR
);
485 dep
->de_stat
.ets_packetT
++;
487 if (tsr
& TSR_COL
) dep
->de_stat
.ets_collision
++;
488 if (tsr
& (TSR_ABT
| TSR_FU
)) {
489 dep
->de_stat
.ets_fifoUnder
++;
491 if ((isr
& ISR_TXE
) || (tsr
& (TSR_CRS
| TSR_CDH
| TSR_OWC
))) {
492 printf("%s: got send Error (0x%02X)\n", dep
->de_name
, tsr
);
493 dep
->de_stat
.ets_sendErr
++;
495 queue
= dep
->de_sendq_tail
;
497 if (!(dep
->de_sendq
[queue
].sq_filled
)) { /* Hardware bug? */
498 printf("%s: transmit interrupt, but not sending\n", dep
->de_name
);
501 dep
->de_sendq
[queue
].sq_filled
= FALSE
;
502 if (++queue
== dep
->de_sendq_nr
) queue
= 0;
503 dep
->de_sendq_tail
= queue
;
504 if (dep
->de_sendq
[queue
].sq_filled
) {
505 ns_start_xmit(dep
, dep
->de_sendq
[queue
].sq_size
,
506 dep
->de_sendq
[queue
].sq_sendpage
);
508 if (dep
->de_flags
& DEF_SENDING
) {
509 ns_send(dep
, TRUE
, dep
->de_send_s
);
513 ns_recv(dep
, TRUE
, 0);
516 printf("%s: got recv Error (0x%04X)\n", dep
->de_name
, inb_reg0(dep
, DP_RSR
));
517 dep
->de_stat
.ets_recvErr
++;
520 dep
->de_stat
.ets_CRCerr
+= inb_reg0(dep
, DP_CNTR0
);
521 dep
->de_stat
.ets_recvErr
+= inb_reg0(dep
, DP_CNTR1
);
522 dep
->de_stat
.ets_fifoOver
+= inb_reg0(dep
, DP_CNTR2
);
525 printf("%s: got overwrite warning\n", dep
->de_name
);
531 /* This means we got an interrupt but the ethernet
532 * chip is shutdown. We set the flag DEF_STOPPED, and
533 * continue processing arrived packets. When the
534 * receive buffer is empty, we reset the dp8390. */
535 printf("%s: network interface stopped\n", dep
->de_name
);
536 dep
->de_flags
|= DEF_STOPPED
;
540 if ((dep
->de_flags
& (DEF_READING
| DEF_STOPPED
)) == (DEF_READING
| DEF_STOPPED
)) {
542 /* The chip is stopped, and all arrived packets delivered */
544 dep
->de_flags
&= NOT(DEF_STOPPED
);
550 ** Name: void ns_init(dpeth_t *dep)
551 ** Function: Initializes the NS 8390
553 void ns_init(dpeth_t
* dep
)
558 /* NS8390 initialization (as recommended in National Semiconductor specs) */
559 outb_reg0(dep
, DP_CR
, CR_PS_P0
| CR_STP
| CR_NO_DMA
); /* 0x21 */
561 outb_reg0(dep
, DP_DCR
, (DCR_BYTEWIDE
| DCR_LTLENDIAN
| DCR_8BYTES
| DCR_BMS
));
563 outb_reg0(dep
, DP_DCR
, (((dep
->de_16bit
) ? DCR_WORDWIDE
: DCR_BYTEWIDE
) |
564 DCR_LTLENDIAN
| DCR_8BYTES
| DCR_BMS
));
566 outb_reg0(dep
, DP_RBCR0
, 0);
567 outb_reg0(dep
, DP_RBCR1
, 0);
568 outb_reg0(dep
, DP_RCR
, RCR_MON
); /* Sets Monitor mode */
569 outb_reg0(dep
, DP_TCR
, TCR_INTERNAL
); /* Sets Loopback mode 1 */
570 outb_reg0(dep
, DP_PSTART
, dep
->de_startpage
);
571 outb_reg0(dep
, DP_PSTOP
, dep
->de_stoppage
);
572 outb_reg0(dep
, DP_BNRY
, dep
->de_stoppage
- 1);
573 outb_reg0(dep
, DP_ISR
, 0xFF); /* Clears Interrupt Status Register */
574 outb_reg0(dep
, DP_IMR
, 0); /* Clears Interrupt Mask Register */
576 /* Copies station address in page 1 registers */
577 outb_reg0(dep
, DP_CR
, CR_PS_P1
| CR_NO_DMA
); /* Selects Page 1 */
578 for (ix
= 0; ix
< SA_ADDR_LEN
; ix
+= 1) /* Initializes address */
579 outb_reg1(dep
, DP_PAR0
+ ix
, dep
->de_address
.ea_addr
[ix
]);
580 for (ix
= DP_MAR0
; ix
<= DP_MAR7
; ix
+= 1) /* Initializes address */
581 outb_reg1(dep
, ix
, 0xFF);
583 outb_reg1(dep
, DP_CURR
, dep
->de_startpage
);
584 outb_reg1(dep
, DP_CR
, CR_PS_P0
| CR_NO_DMA
); /* Selects Page 0 */
586 inb_reg0(dep
, DP_CNTR0
); /* Resets counters by reading them */
587 inb_reg0(dep
, DP_CNTR1
);
588 inb_reg0(dep
, DP_CNTR2
);
590 dp_reg
= IMR_PRXE
| IMR_PTXE
| IMR_RXEE
| IMR_TXEE
| IMR_OVWE
| IMR_CNTE
;
591 outb_reg0(dep
, DP_ISR
, 0xFF); /* Clears Interrupt Status Register */
592 outb_reg0(dep
, DP_IMR
, dp_reg
); /* Sets Interrupt Mask register */
595 if (dep
->de_flags
& DEF_PROMISC
) dp_reg
|= RCR_AB
| RCR_PRO
| RCR_AM
;
596 if (dep
->de_flags
& DEF_BROAD
) dp_reg
|= RCR_AB
;
597 if (dep
->de_flags
& DEF_MULTI
) dp_reg
|= RCR_AM
;
598 outb_reg0(dep
, DP_RCR
, dp_reg
); /* Sets receive as requested */
599 outb_reg0(dep
, DP_TCR
, TCR_NORMAL
); /* Sets transmitter */
601 outb_reg0(dep
, DP_CR
, CR_STA
| CR_NO_DMA
); /* Starts board */
603 /* Initializes the send queue. */
604 for (ix
= 0; ix
< dep
->de_sendq_nr
; ix
+= 1)
605 dep
->de_sendq
[ix
].sq_filled
= 0;
606 dep
->de_sendq_head
= dep
->de_sendq_tail
= 0;
608 /* Device specific functions */
609 if (!dep
->de_prog_IO
) {
610 dep
->de_user2nicf
= mem_user2nic
;
611 dep
->de_nic2userf
= mem_nic2user
;
612 dep
->de_getblockf
= mem_getblock
;
615 dep
->de_user2nicf
= pio_user2nic
;
616 dep
->de_nic2userf
= pio_nic2user
;
617 dep
->de_getblockf
= pio_getblock
;
619 #error Missing I/O functions for pio 16 bits
622 dep
->de_recvf
= ns_recv
;
623 dep
->de_sendf
= ns_send
;
624 dep
->de_flagsf
= ns_reinit
;
625 dep
->de_resetf
= ns_reset
;
626 dep
->de_getstatsf
= ns_stats
;
627 dep
->de_dumpstatsf
= ns_dodump
;
628 dep
->de_interruptf
= ns_interrupt
;
636 ** Name: void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize)
637 ** Function: Copies a packet from user area to board (Prog. I/O, 16bits).
639 static void dp_pio16_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
642 phys_bytes phys_user
, phys_2bytes
= vir2phys(two_bytes
);
643 vir_bytes ecount
= (pktsize
+ 1) & NOT(0x0001);
644 int bytes
, ix
= 0, odd_byte
= 0;
645 iovec_dat_t
*iovp
= &dep
->de_write_iovec
;
647 outb_reg0(dep
, DP_ISR
, ISR_RDC
);
648 dp_read_setup(dep
, ecount
, pageno
* DP_PAGESIZE
);
651 bytes
= iovp
->iod_iovec
[ix
].iov_size
;
652 if (bytes
> pktsize
) bytes
= pktsize
;
654 phys_user
= numap(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_addr
, bytes
);
655 if (!phys_user
) panic(UmapErrMsg
);
658 phys_copy(phys_user
, phys_2bytes
+ 1, (phys_bytes
) 1);
659 out_word(dep
->de_data_port
, *(u16_t
*)two_bytes
);
664 if (!bytes
) continue;
666 ecount
= bytes
& NOT(0x0001);
668 phys_outsw(dep
->de_data_port
, phys_user
, ecount
);
674 phys_copy(phys_user
, phys_2bytes
, (phys_bytes
) 1);
680 if (++ix
>= IOVEC_NR
) { /* Next buffer of I/O vector */
687 if (odd_byte
) out_word(dep
->de_data_port
, *(u16_t
*) two_bytes
);
688 for (ix
= 0; ix
< 100; ix
++) {
689 if (inb_reg0(dep
, DP_ISR
) & ISR_RDC
) break;
698 ** Name: void dp_pio16_nic2user(dpeth_t *dep, int pageno, int pktsize)
699 ** Function: Copies a packet from board to user area (Prog. I/O, 16bits).
701 static void dp_pio16_nic2user(dpeth_t
* dep
, int nic_addr
, int count
)
703 phys_bytes phys_user
;
707 phys_bytes phys_2bytes
;
710 ecount
= (count
+ 1) & ~1;
711 phys_2bytes
= vir2phys(two_bytes
);
714 dp_read_setup(dep
, ecount
, nic_addr
);
723 bytes
= iovp
->iod_iovec
[i
].iov_size
;
724 if (bytes
> count
) bytes
= count
;
726 phys_user
= numap(iovp
->iod_proc_nr
,
727 iovp
->iod_iovec
[i
].iov_addr
, bytes
);
728 if (!phys_user
) panic(UmapErrMsg
);
730 phys_copy(phys_2bytes
+ 1, phys_user
, (phys_bytes
) 1);
735 if (!bytes
) continue;
739 phys_insw(dep
->de_data_port
, phys_user
, ecount
);
745 *(u16_t
*) two_bytes
= in_word(dep
->de_data_port
);
746 phys_copy(phys_2bytes
, phys_user
, (phys_bytes
) 1);
756 #endif /* PIO16 == 1 */
758 #endif /* ENABLE_DP8390 */