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.
14 #include <minix/drivers.h>
15 #include <minix/com.h>
16 #include <net/gen/ether.h>
17 #include <net/gen/eth_io.h>
20 #if (ENABLE_DP8390 == 1)
22 #define PIO16 0 /* NOTE: pio 16 functions missing */
27 #define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \
28 sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\
29 (dstProc),D,(vir_bytes)(dstOffs),length)
32 #define sys_user2nic_s(srcProc,grant,dstOffs,length) \
33 sys_safecopyfrom((srcProc),(grant),0, \
34 (vir_bytes)(dstOffs),length,dep->de_memsegm)
37 static char RdmaErrMsg
[] = "remote dma failed to complete";
40 ** Name: void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset);
41 ** Function: Sets the board for reading/writing.
43 static void ns_rw_setup(const dpeth_t
*dep
, int mode
, int size
, u16_t offset
)
46 if (mode
== CR_DM_RW
) outb_reg0(dep
, DP_ISR
, ISR_RDC
);
47 outb_reg0(dep
, DP_RBCR0
, size
& 0xFF);
48 outb_reg0(dep
, DP_RBCR1
, (size
>> 8) & 0xFF);
49 outb_reg0(dep
, DP_RSAR0
, offset
& 0xFF);
50 outb_reg0(dep
, DP_RSAR1
, (offset
>> 8) & 0xFF);
51 mode
|= (CR_PS_P0
| CR_STA
);
52 outb_reg0(dep
, DP_CR
, mode
);
57 ** Name: void ns_start_xmit(dpeth_t *dep, int size, int pageno);
58 ** Function: Sets the board for for transmitting and fires it.
60 static void ns_start_xmit(const dpeth_t
* dep
, int size
, int pageno
)
63 outb_reg0(dep
, DP_TPSR
, pageno
);
64 outb_reg0(dep
, DP_TBCR1
, size
>> 8);
65 outb_reg0(dep
, DP_TBCR0
, size
& 0xFF);
66 outb_reg0(dep
, DP_CR
, CR_NO_DMA
| CR_STA
| CR_TXP
); /* Fires transmission */
71 ** Name: void mem_getblock(dpeth_t *dep, u16_t offset,
72 ** int size, void *dst)
73 ** Function: Reads a block of packet from board (shared memory).
75 static void mem_getblock(dpeth_t
*dep
, u16_t offset
, int size
, void *dst
)
77 panic("mem_getblock: not converted to safecopies");
79 sys_nic2mem(dep
->de_linmem
+ offset
, SELF
, dst
, size
);
85 ** Name: void mem_nic2user(dpeth_t *dep, int pageno, int pktsize);
86 ** Function: Copies a packet from board to user area (shared memory).
88 static void mem_nic2user(dpeth_t
* dep
, int pageno
, int pktsize
)
90 panic("mem_nic2user: not converted to safecopies");
93 iovec_dat_s_t
*iovp
= &dep
->de_read_iovec
;
97 /* Computes shared memory address (skipping receive header) */
98 offset
= pageno
* DP_PAGESIZE
+ sizeof(dp_rcvhdr_t
);
100 do { /* Reads chuncks of packet into user area */
102 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of a chunck */
103 if (bytes
> pktsize
) bytes
= pktsize
;
105 /* Reads from board to user area */
106 if ((offset
+ bytes
) > (dep
->de_stoppage
* DP_PAGESIZE
)) {
108 /* Circular buffer wrap-around */
109 bytes
= dep
->de_stoppage
* DP_PAGESIZE
- offset
;
110 sys_nic2mem_s(dep
->de_linmem
+ offset
, iovp
->iod_proc_nr
,
111 iovp
->iod_iovec
[ix
].iov_grant
, bytes
);
114 bytes
= iovp
->iod_iovec
[ix
].iov_size
- bytes
;
115 if (bytes
> pktsize
) bytes
= pktsize
;
116 offset
= dep
->de_startpage
* DP_PAGESIZE
;
118 sys_nic2mem_s(dep
->de_linmem
+ offset
, iovp
->iod_proc_nr
,
119 iovp
->iod_iovec
[ix
].iov_grant
, bytes
);
122 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
126 /* Till packet done */
127 } while ((pktsize
-= bytes
) > 0);
133 ** Name: void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
134 ** Function: Copies a packet from user area to board (shared memory).
136 static void mem_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
139 panic("mem_user2nic: not converted to safecopies");
141 phys_bytes offset
, phys_user
;
142 iovec_dat_s_t
*iovp
= &dep
->de_write_iovec
;
145 /* Computes shared memory address */
146 offset
= pageno
* DP_PAGESIZE
;
148 do { /* Reads chuncks of packet from user area */
150 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of chunck */
151 if (bytes
> pktsize
) bytes
= pktsize
;
153 /* Reads from user area to board (shared memory) */
154 sys_user2nic_s(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
155 dep
->de_linmem
+ offset
, bytes
);
158 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
162 /* Till packet done */
163 } while ((pktsize
-= bytes
) > 0);
169 ** Name: void pio_getblock(dpeth_t *dep, u16_t offset,
170 ** int size, void *dst)
171 ** Function: Reads a block of packet from board (Prog. I/O).
173 static void pio_getblock(dpeth_t
*dep
, u16_t offset
, int size
, void *dst
)
176 /* Sets up board for reading */
177 ns_rw_setup(dep
, CR_DM_RR
, size
, offset
);
180 insb(dep
->de_data_port
, SELF
, dst
, size
);
182 if (dep
->de_16bit
== TRUE
) {
183 insw(dep
->de_data_port
, dst
, size
);
185 insb(dep
->de_data_port
, dst
, size
);
192 ** Name: void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
193 ** Function: Copies a packet from board to user area (Prog. I/O).
195 static void pio_nic2user(dpeth_t
*dep
, int pageno
, int pktsize
)
197 iovec_dat_s_t
*iovp
= &dep
->de_read_iovec
;
198 unsigned offset
, iov_offset
; int r
, bytes
, ix
= 0;
200 /* Computes memory address (skipping receive header) */
201 offset
= pageno
* DP_PAGESIZE
+ sizeof(dp_rcvhdr_t
);
202 /* Sets up board for reading */
203 ns_rw_setup(dep
, CR_DM_RR
, ((offset
+ pktsize
) > (dep
->de_stoppage
* DP_PAGESIZE
)) ?
204 (dep
->de_stoppage
* DP_PAGESIZE
) - offset
: pktsize
, offset
);
207 do { /* Reads chuncks of packet into user area */
209 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of a chunck */
210 if (bytes
> pktsize
) bytes
= pktsize
;
212 if ((offset
+ bytes
) > (dep
->de_stoppage
* DP_PAGESIZE
)) {
214 /* Circular buffer wrap-around */
215 bytes
= dep
->de_stoppage
* DP_PAGESIZE
- offset
;
216 r
= sys_safe_insb(dep
->de_data_port
, iovp
->iod_proc_nr
,
217 iovp
->iod_iovec
[ix
].iov_grant
, iov_offset
, bytes
);
219 panic("pio_nic2user: sys_safe_insb failed: %d", r
);
223 bytes
= iovp
->iod_iovec
[ix
].iov_size
- bytes
;
224 if (bytes
> pktsize
) bytes
= pktsize
;
225 offset
= dep
->de_startpage
* DP_PAGESIZE
;
226 ns_rw_setup(dep
, CR_DM_RR
, pktsize
, offset
);
228 r
= sys_safe_insb(dep
->de_data_port
, iovp
->iod_proc_nr
,
229 iovp
->iod_iovec
[ix
].iov_grant
, iov_offset
, bytes
);
231 panic("pio_nic2user: sys_safe_insb failed: %d", r
);
234 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
239 /* Till packet done */
240 } while ((pktsize
-= bytes
) > 0);
245 ** Name: void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
246 ** Function: Copies a packet from user area to board (Prog. I/O).
248 static void pio_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
250 iovec_dat_s_t
*iovp
= &dep
->de_write_iovec
;
251 int r
, bytes
, ix
= 0;
253 /* Sets up board for writing */
254 ns_rw_setup(dep
, CR_DM_RW
, pktsize
, pageno
* DP_PAGESIZE
);
256 do { /* Reads chuncks of packet from user area */
258 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of chunck */
259 if (bytes
> pktsize
) bytes
= pktsize
;
260 r
= sys_safe_outsb(dep
->de_data_port
, iovp
->iod_proc_nr
,
261 iovp
->iod_iovec
[ix
].iov_grant
, 0, bytes
);
263 panic("pio_user2nic: sys_safe_outsb failed: %d", r
);
265 if (++ix
>= IOVEC_NR
) { /* Next buffer of I/O vector */
269 /* Till packet done */
270 } while ((pktsize
-= bytes
) > 0);
272 for (ix
= 0; ix
< 100; ix
+= 1) {
273 if (inb_reg0(dep
, DP_ISR
) & ISR_RDC
) break;
282 ** Name: void ns_stats(dpeth_t * dep)
283 ** Function: Updates counters reading from device
285 static void ns_stats(dpeth_t
* dep
)
288 dep
->de_stat
.ets_CRCerr
+= inb_reg0(dep
, DP_CNTR0
);
289 dep
->de_stat
.ets_recvErr
+= inb_reg0(dep
, DP_CNTR1
);
290 dep
->de_stat
.ets_fifoOver
+= inb_reg0(dep
, DP_CNTR2
);
295 ** Name: void ns_dodump(dpeth_t * dep)
296 ** Function: Displays statistics (a request from F5 key).
298 static void ns_dodump(dpeth_t
* dep
)
301 ns_stats(dep
); /* Forces reading fo counters from board */
306 ** Name: void ns_reinit(dpeth_t *dep)
307 ** Function: Updates receiver configuration.
309 static void ns_reinit(dpeth_t
* dep
)
313 if (dep
->de_flags
& DEF_PROMISC
) dp_reg
|= RCR_AB
| RCR_PRO
| RCR_AM
;
314 if (dep
->de_flags
& DEF_BROAD
) dp_reg
|= RCR_AB
;
315 if (dep
->de_flags
& DEF_MULTI
) dp_reg
|= RCR_AM
;
316 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
317 outb_reg0(dep
, DP_RCR
, dp_reg
);
322 ** Name: void ns_send(dpeth_t * dep, int from_int, int size)
323 ** Function: Transfers packet to device and starts sending.
325 static void ns_send(dpeth_t
* dep
, int from_int
, int size
)
329 if (queue
= dep
->de_sendq_head
, dep
->de_sendq
[queue
].sq_filled
) {
330 if (from_int
) panic("should not be sending ");
331 dep
->de_send_s
= size
;
334 (dep
->de_user2nicf
) (dep
, dep
->de_sendq
[queue
].sq_sendpage
, size
);
335 dep
->bytes_Tx
+= (long) size
;
336 dep
->de_sendq
[queue
].sq_filled
= TRUE
;
337 dep
->de_flags
|= (DEF_XMIT_BUSY
| DEF_ACK_SEND
);
338 if (dep
->de_sendq_tail
== queue
) { /* there it goes.. */
339 ns_start_xmit(dep
, size
, dep
->de_sendq
[queue
].sq_sendpage
);
341 dep
->de_sendq
[queue
].sq_size
= size
;
343 if (++queue
== dep
->de_sendq_nr
) queue
= 0;
344 dep
->de_sendq_head
= queue
;
345 dep
->de_flags
&= NOT(DEF_SENDING
);
351 ** Name: void ns_reset(dpeth_t *dep)
352 ** Function: Resets device.
354 static void ns_reset(dpeth_t
* dep
)
359 outb_reg0(dep
, DP_CR
, CR_STP
| CR_NO_DMA
);
360 outb_reg0(dep
, DP_RBCR0
, 0);
361 outb_reg0(dep
, DP_RBCR1
, 0);
362 for (ix
= 0; ix
< 0x1000 && ((inb_reg0(dep
, DP_ISR
) & ISR_RST
) == 0); ix
+= 1)
364 outb_reg0(dep
, DP_TCR
, TCR_1EXTERNAL
| TCR_OFST
);
365 outb_reg0(dep
, DP_CR
, CR_STA
| CR_NO_DMA
);
366 outb_reg0(dep
, DP_TCR
, TCR_NORMAL
| TCR_OFST
);
368 /* Acknowledge the ISR_RDC (remote dma) interrupt. */
369 for (ix
= 0; ix
< 0x1000 && ((inb_reg0(dep
, DP_ISR
) & ISR_RDC
) == 0); ix
+= 1)
371 outb_reg0(dep
, DP_ISR
, inb_reg0(dep
, DP_ISR
) & NOT(ISR_RDC
));
373 /* Reset the transmit ring. If we were transmitting a packet, we
374 * pretend that the packet is processed. Higher layers will
375 * retransmit if the packet wasn't actually sent. */
376 dep
->de_sendq_head
= dep
->de_sendq_tail
= 0;
377 for (ix
= 0; ix
< dep
->de_sendq_nr
; ix
++)
378 dep
->de_sendq
[ix
].sq_filled
= FALSE
;
379 ns_send(dep
, TRUE
, dep
->de_send_s
);
384 ** Name: void ns_recv(dpeth_t *dep, int fromint, int size)
385 ** Function: Gets a packet from device
387 static void ns_recv(dpeth_t
*dep
, int fromint
, int size
)
390 unsigned pageno
, curr
, next
;
392 int packet_processed
= FALSE
;
397 pageno
= inb_reg0(dep
, DP_BNRY
) + 1;
398 if (pageno
== dep
->de_stoppage
) pageno
= dep
->de_startpage
;
402 outb_reg0(dep
, DP_CR
, CR_PS_P1
);
403 curr
= inb_reg1(dep
, DP_CURR
);
404 outb_reg0(dep
, DP_CR
, CR_PS_P0
| CR_NO_DMA
| CR_STA
);
406 if (curr
== pageno
) break;
408 (dep
->de_getblockf
) (dep
, pageno
* DP_PAGESIZE
, sizeof(header
), &header
);
410 (dep
->de_getblockf
) (dep
, pageno
* DP_PAGESIZE
+ sizeof(header
) + 2 * sizeof(ether_addr_t
), sizeof(eth_type
), ð_type
);
412 length
= (header
.dr_rbcl
| (header
.dr_rbch
<< 8)) - sizeof(dp_rcvhdr_t
);
413 next
= header
.dr_next
;
415 if (length
< ETH_MIN_PACK_SIZE
|| length
> ETH_MAX_PACK_SIZE
) {
416 printf("%s: packet with strange length arrived: %ld\n",
417 dep
->de_name
, length
);
418 dep
->de_stat
.ets_recvErr
+= 1;
421 } else if (next
< dep
->de_startpage
|| next
>= dep
->de_stoppage
) {
422 printf("%s: strange next page\n", dep
->de_name
);
423 dep
->de_stat
.ets_recvErr
+= 1;
427 } else if (eth_type
== eth_ign_proto
) {
428 /* Hack: ignore packets of a given protocol */
429 static int first
= TRUE
;
432 printf("%s: dropping proto %04x packet\n", dep
->de_name
, ntohs(eth_ign_proto
));
436 } else if (header
.dr_status
& RSR_FO
) {
437 /* This is very serious, issue a warning and reset buffers */
438 printf("%s: fifo overrun, resetting receive buffer\n", dep
->de_name
);
439 dep
->de_stat
.ets_fifoOver
+= 1;
442 } else if ((header
.dr_status
& RSR_PRX
) && (dep
->de_flags
& DEF_ENABLED
)) {
444 if (!(dep
->de_flags
& DEF_READING
)) break;
446 (dep
->de_nic2userf
) (dep
, pageno
, length
);
447 dep
->de_read_s
= length
;
448 dep
->de_flags
|= DEF_ACK_RECV
;
449 dep
->de_flags
&= NOT(DEF_READING
);
450 packet_processed
= TRUE
;
452 dep
->bytes_Rx
+= (long) length
;
453 dep
->de_stat
.ets_packetR
+= 1;
454 outb_reg0(dep
, DP_BNRY
, (next
== dep
->de_startpage
? dep
->de_stoppage
: next
) - 1);
457 } while (!packet_processed
);
459 if ((dep
->de_flags
& (DEF_READING
| DEF_STOPPED
)) == (DEF_READING
| DEF_STOPPED
))
460 /* The chip is stopped, and all arrived packets delivered */
461 (*dep
->de_resetf
) (dep
);
462 dep
->de_flags
&= NOT(DEF_STOPPED
);
468 ** Name: void ns_interrupt(dpeth_t * dep)
469 ** Function: Handles interrupt.
471 static void ns_interrupt(dpeth_t
* dep
)
476 while ((isr
= inb_reg0(dep
, DP_ISR
)) != 0) {
478 outb_reg0(dep
, DP_ISR
, isr
);
479 if (isr
& (ISR_PTX
| ISR_TXE
)) {
481 tsr
= inb_reg0(dep
, DP_TSR
);
483 dep
->de_stat
.ets_packetT
++;
485 if (tsr
& TSR_COL
) dep
->de_stat
.ets_collision
++;
486 if (tsr
& (TSR_ABT
| TSR_FU
)) {
487 dep
->de_stat
.ets_fifoUnder
++;
489 if ((isr
& ISR_TXE
) || (tsr
& (TSR_CRS
| TSR_CDH
| TSR_OWC
))) {
490 printf("%s: got send Error (0x%02X)\n", dep
->de_name
, tsr
);
491 dep
->de_stat
.ets_sendErr
++;
493 queue
= dep
->de_sendq_tail
;
495 if (!(dep
->de_sendq
[queue
].sq_filled
)) { /* Hardware bug? */
496 printf("%s: transmit interrupt, but not sending\n", dep
->de_name
);
499 dep
->de_sendq
[queue
].sq_filled
= FALSE
;
500 if (++queue
== dep
->de_sendq_nr
) queue
= 0;
501 dep
->de_sendq_tail
= queue
;
502 if (dep
->de_sendq
[queue
].sq_filled
) {
503 ns_start_xmit(dep
, dep
->de_sendq
[queue
].sq_size
,
504 dep
->de_sendq
[queue
].sq_sendpage
);
506 if (dep
->de_flags
& DEF_SENDING
) {
507 ns_send(dep
, TRUE
, dep
->de_send_s
);
511 ns_recv(dep
, TRUE
, 0);
514 printf("%s: got recv Error (0x%04X)\n", dep
->de_name
, inb_reg0(dep
, DP_RSR
));
515 dep
->de_stat
.ets_recvErr
++;
518 dep
->de_stat
.ets_CRCerr
+= inb_reg0(dep
, DP_CNTR0
);
519 dep
->de_stat
.ets_recvErr
+= inb_reg0(dep
, DP_CNTR1
);
520 dep
->de_stat
.ets_fifoOver
+= inb_reg0(dep
, DP_CNTR2
);
523 printf("%s: got overwrite warning\n", dep
->de_name
);
529 /* This means we got an interrupt but the ethernet
530 * chip is shutdown. We set the flag DEF_STOPPED, and
531 * continue processing arrived packets. When the
532 * receive buffer is empty, we reset the dp8390. */
533 printf("%s: network interface stopped\n", dep
->de_name
);
534 dep
->de_flags
|= DEF_STOPPED
;
538 if ((dep
->de_flags
& (DEF_READING
| DEF_STOPPED
)) == (DEF_READING
| DEF_STOPPED
)) {
540 /* The chip is stopped, and all arrived packets delivered */
542 dep
->de_flags
&= NOT(DEF_STOPPED
);
548 ** Name: void ns_init(dpeth_t *dep)
549 ** Function: Initializes the NS 8390
551 void ns_init(dpeth_t
* dep
)
556 /* NS8390 initialization (as recommended in National Semiconductor specs) */
557 outb_reg0(dep
, DP_CR
, CR_PS_P0
| CR_STP
| CR_NO_DMA
); /* 0x21 */
559 outb_reg0(dep
, DP_DCR
, (DCR_BYTEWIDE
| DCR_LTLENDIAN
| DCR_8BYTES
| DCR_BMS
));
561 outb_reg0(dep
, DP_DCR
, (((dep
->de_16bit
) ? DCR_WORDWIDE
: DCR_BYTEWIDE
) |
562 DCR_LTLENDIAN
| DCR_8BYTES
| DCR_BMS
));
564 outb_reg0(dep
, DP_RBCR0
, 0);
565 outb_reg0(dep
, DP_RBCR1
, 0);
566 outb_reg0(dep
, DP_RCR
, RCR_MON
); /* Sets Monitor mode */
567 outb_reg0(dep
, DP_TCR
, TCR_INTERNAL
); /* Sets Loopback mode 1 */
568 outb_reg0(dep
, DP_PSTART
, dep
->de_startpage
);
569 outb_reg0(dep
, DP_PSTOP
, dep
->de_stoppage
);
570 outb_reg0(dep
, DP_BNRY
, dep
->de_stoppage
- 1);
571 outb_reg0(dep
, DP_ISR
, 0xFF); /* Clears Interrupt Status Register */
572 outb_reg0(dep
, DP_IMR
, 0); /* Clears Interrupt Mask Register */
574 /* Copies station address in page 1 registers */
575 outb_reg0(dep
, DP_CR
, CR_PS_P1
| CR_NO_DMA
); /* Selects Page 1 */
576 for (ix
= 0; ix
< SA_ADDR_LEN
; ix
+= 1) /* Initializes address */
577 outb_reg1(dep
, DP_PAR0
+ ix
, dep
->de_address
.ea_addr
[ix
]);
578 for (ix
= DP_MAR0
; ix
<= DP_MAR7
; ix
+= 1) /* Initializes address */
579 outb_reg1(dep
, ix
, 0xFF);
581 outb_reg1(dep
, DP_CURR
, dep
->de_startpage
);
582 outb_reg1(dep
, DP_CR
, CR_PS_P0
| CR_NO_DMA
); /* Selects Page 0 */
584 inb_reg0(dep
, DP_CNTR0
); /* Resets counters by reading them */
585 inb_reg0(dep
, DP_CNTR1
);
586 inb_reg0(dep
, DP_CNTR2
);
588 dp_reg
= IMR_PRXE
| IMR_PTXE
| IMR_RXEE
| IMR_TXEE
| IMR_OVWE
| IMR_CNTE
;
589 outb_reg0(dep
, DP_ISR
, 0xFF); /* Clears Interrupt Status Register */
590 outb_reg0(dep
, DP_IMR
, dp_reg
); /* Sets Interrupt Mask register */
593 if (dep
->de_flags
& DEF_PROMISC
) dp_reg
|= RCR_AB
| RCR_PRO
| RCR_AM
;
594 if (dep
->de_flags
& DEF_BROAD
) dp_reg
|= RCR_AB
;
595 if (dep
->de_flags
& DEF_MULTI
) dp_reg
|= RCR_AM
;
596 outb_reg0(dep
, DP_RCR
, dp_reg
); /* Sets receive as requested */
597 outb_reg0(dep
, DP_TCR
, TCR_NORMAL
); /* Sets transmitter */
599 outb_reg0(dep
, DP_CR
, CR_STA
| CR_NO_DMA
); /* Starts board */
601 /* Initializes the send queue. */
602 for (ix
= 0; ix
< dep
->de_sendq_nr
; ix
+= 1)
603 dep
->de_sendq
[ix
].sq_filled
= 0;
604 dep
->de_sendq_head
= dep
->de_sendq_tail
= 0;
606 /* Device specific functions */
607 if (!dep
->de_prog_IO
) {
608 dep
->de_user2nicf
= mem_user2nic
;
609 dep
->de_nic2userf
= mem_nic2user
;
610 dep
->de_getblockf
= mem_getblock
;
613 dep
->de_user2nicf
= pio_user2nic
;
614 dep
->de_nic2userf
= pio_nic2user
;
615 dep
->de_getblockf
= pio_getblock
;
617 #error Missing I/O functions for pio 16 bits
620 dep
->de_recvf
= ns_recv
;
621 dep
->de_sendf
= ns_send
;
622 dep
->de_flagsf
= ns_reinit
;
623 dep
->de_resetf
= ns_reset
;
624 dep
->de_getstatsf
= ns_stats
;
625 dep
->de_dumpstatsf
= ns_dodump
;
626 dep
->de_interruptf
= ns_interrupt
;
634 ** Name: void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize)
635 ** Function: Copies a packet from user area to board (Prog. I/O, 16bits).
637 static void dp_pio16_user2nic(dpeth_t
*dep
, int pageno
, int pktsize
)
640 phys_bytes phys_user
, phys_2bytes
= vir2phys(two_bytes
);
641 vir_bytes ecount
= (pktsize
+ 1) & NOT(0x0001);
642 int bytes
, ix
= 0, odd_byte
= 0;
643 iovec_dat_t
*iovp
= &dep
->de_write_iovec
;
645 outb_reg0(dep
, DP_ISR
, ISR_RDC
);
646 dp_read_setup(dep
, ecount
, pageno
* DP_PAGESIZE
);
649 bytes
= iovp
->iod_iovec
[ix
].iov_size
;
650 if (bytes
> pktsize
) bytes
= pktsize
;
652 phys_user
= numap(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_addr
, bytes
);
653 if (!phys_user
) panic(UmapErrMsg
);
656 phys_copy(phys_user
, phys_2bytes
+ 1, (phys_bytes
) 1);
657 out_word(dep
->de_data_port
, *(u16_t
*)two_bytes
);
662 if (!bytes
) continue;
664 ecount
= bytes
& NOT(0x0001);
666 phys_outsw(dep
->de_data_port
, phys_user
, ecount
);
672 phys_copy(phys_user
, phys_2bytes
, (phys_bytes
) 1);
678 if (++ix
>= IOVEC_NR
) { /* Next buffer of I/O vector */
685 if (odd_byte
) out_word(dep
->de_data_port
, *(u16_t
*) two_bytes
);
686 for (ix
= 0; ix
< 100; ix
++) {
687 if (inb_reg0(dep
, DP_ISR
) & ISR_RDC
) break;
696 ** Name: void dp_pio16_nic2user(dpeth_t *dep, int pageno, int pktsize)
697 ** Function: Copies a packet from board to user area (Prog. I/O, 16bits).
699 static void dp_pio16_nic2user(dpeth_t
* dep
, int nic_addr
, int count
)
701 phys_bytes phys_user
;
705 phys_bytes phys_2bytes
;
708 ecount
= (count
+ 1) & ~1;
709 phys_2bytes
= vir2phys(two_bytes
);
712 dp_read_setup(dep
, ecount
, nic_addr
);
721 bytes
= iovp
->iod_iovec
[i
].iov_size
;
722 if (bytes
> count
) bytes
= count
;
724 phys_user
= numap(iovp
->iod_proc_nr
,
725 iovp
->iod_iovec
[i
].iov_addr
, bytes
);
726 if (!phys_user
) panic(UmapErrMsg
);
728 phys_copy(phys_2bytes
+ 1, phys_user
, (phys_bytes
) 1);
733 if (!bytes
) continue;
737 phys_insw(dep
->de_data_port
, phys_user
, ecount
);
743 *(u16_t
*) two_bytes
= in_word(dep
->de_data_port
);
744 phys_copy(phys_2bytes
, phys_user
, (phys_bytes
) 1);
754 #endif /* PIO16 == 1 */
756 #endif /* ENABLE_DP8390 */