ldivmod, uldivmod: fix qdivrem calls
[minix.git] / drivers / dpeth / 8390.c
blob43f81dedaf7f3543d35681152751749c2939c5e2
1 #include <assert.h>
2 /*
3 ** File: 8390.c May 02, 2000
4 **
5 ** Author: Giovanni Falzoni <gfalzoni@inwind.it>
6 **
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>
18 #include "dp.h"
20 #if (ENABLE_DP8390 == 1)
22 #define PIO16 0 /* NOTE: pio 16 functions missing */
24 #include "8390.h"
26 #if 0
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)
30 #endif
31 #if 0
32 #define sys_user2nic_s(srcProc,grant,dstOffs,length) \
33 sys_safecopyfrom((srcProc),(grant),0, \
34 (vir_bytes)(dstOffs),length,dep->de_memsegm)
35 #endif
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);
53 return;
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 */
67 return;
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");
78 #if 0
79 sys_nic2mem(dep->de_linmem + offset, SELF, dst, size);
80 return;
81 #endif
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");
91 #if 0
92 phys_bytes offset;
93 iovec_dat_s_t *iovp = &dep->de_read_iovec;
94 int bytes, ix = 0;
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);
112 pktsize -= bytes;
113 phys_user += 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);
120 offset += bytes;
122 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
123 dp_next_iovec(iovp);
124 ix = 0;
126 /* Till packet done */
127 } while ((pktsize -= bytes) > 0);
128 return;
129 #endif
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)
138 #if 1
139 panic("mem_user2nic: not converted to safecopies");
140 #else
141 phys_bytes offset, phys_user;
142 iovec_dat_s_t *iovp = &dep->de_write_iovec;
143 int bytes, ix = 0;
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);
156 offset += bytes;
158 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
159 dp_next_iovec(iovp);
160 ix = 0;
162 /* Till packet done */
163 } while ((pktsize -= bytes) > 0);
164 return;
165 #endif
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);
179 #if PIO16 == 0
180 insb(dep->de_data_port, SELF, dst, size);
181 #else
182 if (dep->de_16bit == TRUE) {
183 insw(dep->de_data_port, dst, size);
184 } else {
185 insb(dep->de_data_port, dst, size);
187 #endif
188 return;
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);
206 iov_offset= 0;
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);
218 if (r != OK) {
219 panic("pio_nic2user: sys_safe_insb failed: %d", r);
221 pktsize -= bytes;
222 iov_offset += bytes;
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);
230 if (r != OK)
231 panic("pio_nic2user: sys_safe_insb failed: %d", r);
232 offset += bytes;
234 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
235 dp_next_iovec(iovp);
236 ix = 0;
238 iov_offset= 0;
239 /* Till packet done */
240 } while ((pktsize -= bytes) > 0);
241 return;
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);
262 if (r != OK)
263 panic("pio_user2nic: sys_safe_outsb failed: %d", r);
265 if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */
266 dp_next_iovec(iovp);
267 ix = 0;
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;
275 if (ix == 100) {
276 panic(RdmaErrMsg);
278 return;
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);
291 return;
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 */
302 return;
306 ** Name: void ns_reinit(dpeth_t *dep)
307 ** Function: Updates receiver configuration.
309 static void ns_reinit(dpeth_t * dep)
311 int dp_reg = 0;
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);
318 return;
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)
327 int queue;
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;
332 return;
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);
340 } else
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);
347 return;
351 ** Name: void ns_reset(dpeth_t *dep)
352 ** Function: Resets device.
354 static void ns_reset(dpeth_t * dep)
356 int ix;
358 /* Stop chip */
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)
363 /* Do nothing */ ;
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)
370 /* Do nothing */ ;
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);
380 return;
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)
389 dp_rcvhdr_t header;
390 unsigned pageno, curr, next;
391 vir_bytes length;
392 int packet_processed = FALSE;
393 #ifdef ETH_IGN_PROTO
394 u16_t eth_type;
395 #endif
397 pageno = inb_reg0(dep, DP_BNRY) + 1;
398 if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
400 do {
401 /* */
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);
409 #ifdef ETH_IGN_PROTO
410 (dep->de_getblockf) (dep, pageno * DP_PAGESIZE + sizeof(header) + 2 * sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
411 #endif
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;
419 next = curr;
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;
424 next = curr;
426 #ifdef ETH_IGN_PROTO
427 } else if (eth_type == eth_ign_proto) {
428 /* Hack: ignore packets of a given protocol */
429 static int first = TRUE;
430 if (first) {
431 first = FALSE;
432 printf("%s: dropping proto %04x packet\n", dep->de_name, ntohs(eth_ign_proto));
434 next = curr;
435 #endif
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;
440 next = curr;
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);
455 pageno = next;
457 } while (!packet_processed);
458 #if 0
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);
463 #endif
464 return;
468 ** Name: void ns_interrupt(dpeth_t * dep)
469 ** Function: Handles interrupt.
471 static void ns_interrupt(dpeth_t * dep)
473 int isr, tsr;
474 int queue;
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);
482 if (tsr & TSR_PTX) {
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);
497 continue;
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);
510 if (isr & ISR_PRX) {
511 ns_recv(dep, TRUE, 0);
513 if (isr & ISR_RXE) {
514 printf("%s: got recv Error (0x%04X)\n", dep->de_name, inb_reg0(dep, DP_RSR));
515 dep->de_stat.ets_recvErr++;
517 if (isr & ISR_CNT) {
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);
522 if (isr & ISR_OVW) {
523 printf("%s: got overwrite warning\n", dep->de_name);
525 if (isr & ISR_RDC) {
526 /* Nothing to do */
528 if (isr & ISR_RST) {
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;
535 break;
538 if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED)) {
540 /* The chip is stopped, and all arrived packets delivered */
541 ns_reset(dep);
542 dep->de_flags &= NOT(DEF_STOPPED);
544 return;
548 ** Name: void ns_init(dpeth_t *dep)
549 ** Function: Initializes the NS 8390
551 void ns_init(dpeth_t * dep)
553 int dp_reg;
554 int ix;
556 /* NS8390 initialization (as recommended in National Semiconductor specs) */
557 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_NO_DMA); /* 0x21 */
558 #if PIO16 == 0
559 outb_reg0(dep, DP_DCR, (DCR_BYTEWIDE | DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS));
560 #else
561 outb_reg0(dep, DP_DCR, (((dep->de_16bit) ? DCR_WORDWIDE : DCR_BYTEWIDE) |
562 DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS));
563 #endif
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 */
592 dp_reg = 0;
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;
611 } else {
612 #if PIO16 == 0
613 dep->de_user2nicf = pio_user2nic;
614 dep->de_nic2userf = pio_nic2user;
615 dep->de_getblockf = pio_getblock;
616 #else
617 #error Missing I/O functions for pio 16 bits
618 #endif
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;
628 return; /* Done */
631 #if PIO16 == 1
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)
639 u8_t two_bytes[2];
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);
648 do {
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);
655 if (odd_byte) {
656 phys_copy(phys_user, phys_2bytes + 1, (phys_bytes) 1);
657 out_word(dep->de_data_port, *(u16_t *)two_bytes);
658 pktsize--;
659 bytes--;
660 phys_user++;
661 odd_byte = 0;
662 if (!bytes) continue;
664 ecount = bytes & NOT(0x0001);
665 if (ecount != 0) {
666 phys_outsw(dep->de_data_port, phys_user, ecount);
667 pktsize -= ecount;
668 bytes -= ecount;
669 phys_user += ecount;
671 if (bytes) {
672 phys_copy(phys_user, phys_2bytes, (phys_bytes) 1);
673 pktsize--;
674 bytes--;
675 phys_user++;
676 odd_byte = 1;
678 if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */
679 dp_next_iovec(iovp);
680 ix = 0;
683 } while (bytes > 0);
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;
689 if (ix == 100) {
690 panic(RdmaErrMsg);
692 return;
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;
702 vir_bytes ecount;
703 int bytes, i;
704 u8_t two_bytes[2];
705 phys_bytes phys_2bytes;
706 int odd_byte;
708 ecount = (count + 1) & ~1;
709 phys_2bytes = vir2phys(two_bytes);
710 odd_byte = 0;
712 dp_read_setup(dep, ecount, nic_addr);
714 i = 0;
715 while (count > 0) {
716 if (i >= IOVEC_NR) {
717 dp_next_iovec(iovp);
718 i = 0;
719 continue;
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);
727 if (odd_byte) {
728 phys_copy(phys_2bytes + 1, phys_user, (phys_bytes) 1);
729 count--;
730 bytes--;
731 phys_user++;
732 odd_byte = 0;
733 if (!bytes) continue;
735 ecount = bytes & ~1;
736 if (ecount != 0) {
737 phys_insw(dep->de_data_port, phys_user, ecount);
738 count -= ecount;
739 bytes -= ecount;
740 phys_user += ecount;
742 if (bytes) {
743 *(u16_t *) two_bytes = in_word(dep->de_data_port);
744 phys_copy(phys_2bytes, phys_user, (phys_bytes) 1);
745 count--;
746 bytes--;
747 phys_user++;
748 odd_byte = 1;
751 return;
754 #endif /* PIO16 == 1 */
756 #endif /* ENABLE_DP8390 */
758 /** end 8390.c **/