source: mainline/uspace/srv/hw/netif/dp8390/dp8390.c@ 6fc0edd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6fc0edd was 6fc0edd, checked in by Martin Decky <martin@…>, 14 years ago

more robust interrupt processing

  • Property mode set to 100644
File size: 32.0 KB
Line 
1/** @addtogroup dp8390
2 * @{
3 */
4
5/** @file
6 * DP8390 network interface core implementation.
7 */
8
9#include <assert.h>
10#include <byteorder.h>
11#include <errno.h>
12#include <netif_local.h>
13#include <net/packet.h>
14#include <packet_client.h>
15#include "dp8390_drv.h"
16#include "dp8390_port.h"
17#include "dp8390.h"
18#include "ne2000.h"
19
20/** Queues the outgoing packet.
21 * @param[in] dep The network interface structure.
22 * @param[in] packet The outgoing packet.
23 * @return EOK on success.
24 * @return EINVAL
25 */
26int queue_packet(dpeth_t * dep, packet_t *packet);
27
28/** Reads a memory block byte by byte.
29 * @param[in] port The source address.
30 * @param[out] buf The destination buffer.
31 * @param[in] size The memory block size in bytes.
32 */
33static void outsb(port_t port, void * buf, size_t size);
34
35/** Reads a memory block word by word.
36 * @param[in] port The source address.
37 * @param[out] buf The destination buffer.
38 * @param[in] size The memory block size in bytes.
39 */
40static void outsw(port_t port, void * buf, size_t size);
41
42/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
43 * on writes to the CR register. Additional CR_STAs do not appear to hurt
44 * genuine dp8390s
45 */
46#define CR_EXTRA CR_STA
47
48static void dp_init(dpeth_t *dep);
49static void dp_reinit(dpeth_t *dep);
50static void dp_reset(dpeth_t *dep);
51static void dp_recv(dpeth_t *dep);
52static void dp_send(dpeth_t *dep);
53static void dp_pio8_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst);
54static void dp_pio16_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst);
55static int dp_pkt2user(dpeth_t *dep, int page, int length);
56static void dp_pio8_user2nic(dpeth_t *dep, iovec_dat_t *iovp, vir_bytes offset, int nic_addr, vir_bytes count);
57static void dp_pio16_user2nic(dpeth_t *dep, iovec_dat_t *iovp, vir_bytes offset, int nic_addr, vir_bytes count);
58static void dp_pio8_nic2user(dpeth_t *dep, int nic_addr, iovec_dat_t *iovp, vir_bytes offset, vir_bytes count);
59static void dp_pio16_nic2user(dpeth_t *dep, int nic_addr, iovec_dat_t *iovp, vir_bytes offset, vir_bytes count);
60static void dp_next_iovec(iovec_dat_t *iovp);
61static void conf_hw(dpeth_t *dep);
62static void reply(dpeth_t *dep, int err, int may_block);
63static void get_userdata(int user_proc, vir_bytes user_addr, vir_bytes count, void *loc_addr);
64static void insb(port_t port, void *buf, size_t size);
65static void insw(port_t port, void *buf, size_t size);
66
67int do_probe(dpeth_t *dep)
68{
69 /* This is the default, try to (re)locate the device. */
70 conf_hw(dep);
71 if (dep->de_mode == DEM_DISABLED)
72 /* Probe failed, or the device is configured off. */
73 return EXDEV;
74
75 if (dep->de_mode == DEM_ENABLED)
76 dp_init(dep);
77
78 return EOK;
79}
80
81void dp8390_dump(dpeth_t *dep)
82{
83// dpeth_t *dep;
84 int /*i,*/ isr;
85
86// printf("\n");
87// for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
88// {
89#if XXX
90 if (dep->de_mode == DEM_DISABLED)
91 printf("dp8390 port %d is disabled\n", i);
92 else if (dep->de_mode == DEM_SINK)
93 printf("dp8390 port %d is in sink mode\n", i);
94#endif
95
96 if (dep->de_mode != DEM_ENABLED)
97// continue;
98 return;
99
100// printf("dp8390 statistics of port %d:\n", i);
101
102 printf("recvErr :%8ld\t", dep->de_stat.ets_recvErr);
103 printf("sendErr :%8ld\t", dep->de_stat.ets_sendErr);
104 printf("OVW :%8ld\n", dep->de_stat.ets_OVW);
105
106 printf("CRCerr :%8ld\t", dep->de_stat.ets_CRCerr);
107 printf("frameAll :%8ld\t", dep->de_stat.ets_frameAll);
108 printf("missedP :%8ld\n", dep->de_stat.ets_missedP);
109
110 printf("packetR :%8ld\t", dep->de_stat.ets_packetR);
111 printf("packetT :%8ld\t", dep->de_stat.ets_packetT);
112 printf("transDef :%8ld\n", dep->de_stat.ets_transDef);
113
114 printf("collision :%8ld\t", dep->de_stat.ets_collision);
115 printf("transAb :%8ld\t", dep->de_stat.ets_transAb);
116 printf("carrSense :%8ld\n", dep->de_stat.ets_carrSense);
117
118 printf("fifoUnder :%8ld\t", dep->de_stat.ets_fifoUnder);
119 printf("fifoOver :%8ld\t", dep->de_stat.ets_fifoOver);
120 printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
121
122 printf("OWC :%8ld\t", dep->de_stat.ets_OWC);
123
124 isr= inb_reg0(dep, DP_ISR);
125 printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
126 inb_reg0(dep, DP_ISR), dep->de_flags);
127// }
128}
129
130int do_init(dpeth_t *dep, int mode)
131{
132 if (dep->de_mode == DEM_DISABLED)
133 // might call do_probe()
134 return EXDEV;
135
136 if (dep->de_mode == DEM_SINK) {
137// strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
138// dep->de_address.ea_addr[5] = port;
139// reply_mess.m_type = DL_CONF_REPLY;
140// reply_mess.m3_i1 = mp->DL_PORT;
141// reply_mess.m3_i2 = DE_PORT_NR;
142// *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
143// mess_reply(mp, &reply_mess);
144// return;
145 return EOK;
146 }
147
148 assert(dep->de_mode == DEM_ENABLED);
149 assert(dep->de_flags & DEF_ENABLED);
150
151 dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
152
153 if (mode &DL_PROMISC_REQ)
154 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
155
156 if (mode &DL_MULTI_REQ)
157 dep->de_flags |= DEF_MULTI;
158
159 if (mode &DL_BROAD_REQ)
160 dep->de_flags |= DEF_BROAD;
161
162// dep->de_client = mp->m_source;
163 dp_reinit(dep);
164
165// reply_mess.m_type = DL_CONF_REPLY;
166// reply_mess.m3_i1 = mp->DL_PORT;
167// reply_mess.m3_i2 = DE_PORT_NR;
168// *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
169
170// mess_reply(mp, &reply_mess);
171 return EOK;
172}
173
174void do_stop(dpeth_t *dep)
175{
176 if ((dep->de_mode != DEM_SINK)
177 && (dep->de_mode == DEM_ENABLED)
178 && (dep->de_flags & DEF_ENABLED)) {
179 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
180 (dep->de_stopf)(dep);
181 dep->de_flags = DEF_EMPTY;
182 }
183}
184
185int queue_packet(dpeth_t *dep, packet_t *packet)
186{
187 packet_t *tmp;
188
189 if (dep->packet_count >= MAX_PACKETS) {
190 netif_pq_release(packet_get_id(packet));
191 return ELIMIT;
192 }
193
194 tmp = dep->packet_queue;
195 while (pq_next(tmp))
196 tmp = pq_next(tmp);
197
198 if (pq_add(&tmp, packet, 0, 0) != EOK)
199 return EINVAL;
200
201 if (!dep->packet_count)
202 dep->packet_queue = packet;
203
204 ++dep->packet_count;
205 return EBUSY;
206}
207
208int do_pwrite(dpeth_t *dep, packet_t *packet, int from_int)
209{
210// int port, count, size;
211 int size;
212 int sendq_head;
213/* dpeth_t *dep;
214
215 port = mp->DL_PORT;
216 count = mp->DL_COUNT;
217 if (port < 0 || port >= DE_PORT_NR)
218 fprintf(stderr, "dp8390: illegal port\n");
219 dep= &de_table[port];
220 dep->de_client= mp->DL_PROC;
221*/
222 if (dep->de_mode == DEM_SINK) {
223 assert(!from_int);
224// dep->de_flags |= DEF_PACK_SEND;
225 reply(dep, EOK, false);
226// return;
227 return EOK;
228 }
229
230 assert(dep->de_mode == DEM_ENABLED);
231 assert(dep->de_flags &DEF_ENABLED);
232
233 if ((dep->packet_queue) && (!from_int)) {
234// if (dep->de_flags &DEF_SEND_AVAIL){
235// fprintf(stderr, "dp8390: send already in progress\n");
236 return queue_packet(dep, packet);
237 }
238
239 sendq_head= dep->de_sendq_head;
240// if (dep->de_sendq[sendq_head].sq_filled) {
241// if (from_int)
242// fprintf(stderr, "dp8390: should not be sending\n");
243// dep->de_sendmsg= *mp;
244// dep->de_flags |= DEF_SEND_AVAIL;
245// reply(dep, EOK, false);
246// return;
247// return queue_packet(dep, packet);
248// }
249// assert(!(dep->de_flags &DEF_PACK_SEND));
250
251/* if (vectored) {
252 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
253 (count > IOVEC_NR ? IOVEC_NR : count) *
254 sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
255 dep->de_write_iovec.iod_iovec_s = count;
256 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
257 dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
258
259 dep->de_tmp_iovec = dep->de_write_iovec;
260 size = calc_iovec_size(&dep->de_tmp_iovec);
261 } else {
262 dep->de_write_iovec.iod_iovec[0].iov_addr =
263 (vir_bytes) mp->DL_ADDR;
264 dep->de_write_iovec.iod_iovec[0].iov_size =
265 mp->DL_COUNT;
266 dep->de_write_iovec.iod_iovec_s = 1;
267 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
268 dep->de_write_iovec.iod_iovec_addr = 0;
269 size= mp->DL_COUNT;
270 }
271*/
272 size = packet_get_data_length(packet);
273 dep->de_write_iovec.iod_iovec[0].iov_addr = (vir_bytes) packet_get_data(packet);
274 dep->de_write_iovec.iod_iovec[0].iov_size = size;
275 dep->de_write_iovec.iod_iovec_s = 1;
276 dep->de_write_iovec.iod_iovec_addr = (uintptr_t) NULL;
277
278 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) {
279 fprintf(stderr, "dp8390: invalid packet size\n");
280 return EINVAL;
281 }
282
283 (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
284 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
285 size);
286 dep->de_sendq[sendq_head].sq_filled= true;
287 if (dep->de_sendq_tail == sendq_head) {
288 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
289 outb_reg0(dep, DP_TBCR1, size >> 8);
290 outb_reg0(dep, DP_TBCR0, size & 0xff);
291 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA); /* there it goes.. */
292 } else
293 dep->de_sendq[sendq_head].sq_size = size;
294
295 if (++sendq_head == dep->de_sendq_nr)
296 sendq_head= 0;
297
298 assert(sendq_head < SENDQ_NR);
299 dep->de_sendq_head = sendq_head;
300
301// dep->de_flags |= DEF_PACK_SEND;
302
303 /*
304 * If the interrupt handler called, don't send a reply. The reply
305 * will be sent after all interrupts are handled.
306 */
307 if (from_int)
308 return EOK;
309
310 reply(dep, EOK, false);
311
312 assert(dep->de_mode == DEM_ENABLED);
313 assert(dep->de_flags & DEF_ENABLED);
314
315 return EOK;
316}
317
318void dp_init(dpeth_t *dep)
319{
320 int dp_rcr_reg;
321 int i;
322
323 /* General initialization */
324 dep->de_flags = DEF_EMPTY;
325 (*dep->de_initf)(dep);
326
327 printf("%s: Ethernet address ", dep->de_name);
328 for (i = 0; i < 6; i++)
329 printf("%x%c", dep->de_address.ea_addr[i], i < 5 ? ':' : '\n');
330
331 /*
332 * Initialization of the dp8390 following the mandatory procedure
333 * in reference manual ("DP8390D/NS32490D NIC Network Interface
334 * Controller", National Semiconductor, July 1995, Page 29).
335 */
336
337 /* Step 1: */
338 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
339
340 /* Step 2: */
341 if (dep->de_16bit)
342 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
343 else
344 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
345
346 /* Step 3: */
347 outb_reg0(dep, DP_RBCR0, 0);
348 outb_reg0(dep, DP_RBCR1, 0);
349
350 /* Step 4: */
351 dp_rcr_reg = 0;
352
353 if (dep->de_flags & DEF_PROMISC)
354 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
355
356 if (dep->de_flags & DEF_BROAD)
357 dp_rcr_reg |= RCR_AB;
358
359 if (dep->de_flags & DEF_MULTI)
360 dp_rcr_reg |= RCR_AM;
361
362 outb_reg0(dep, DP_RCR, dp_rcr_reg);
363
364 /* Step 5: */
365 outb_reg0(dep, DP_TCR, TCR_INTERNAL);
366
367 /* Step 6: */
368 outb_reg0(dep, DP_BNRY, dep->de_startpage);
369 outb_reg0(dep, DP_PSTART, dep->de_startpage);
370 outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
371
372 /* Step 7: */
373 outb_reg0(dep, DP_ISR, 0xFF);
374
375 /* Step 8: */
376 outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
377 IMR_OVWE | IMR_CNTE);
378
379 /* Step 9: */
380 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
381
382 outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
383 outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
384 outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
385 outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
386 outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
387 outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
388
389 outb_reg1(dep, DP_MAR0, 0xff);
390 outb_reg1(dep, DP_MAR1, 0xff);
391 outb_reg1(dep, DP_MAR2, 0xff);
392 outb_reg1(dep, DP_MAR3, 0xff);
393 outb_reg1(dep, DP_MAR4, 0xff);
394 outb_reg1(dep, DP_MAR5, 0xff);
395 outb_reg1(dep, DP_MAR6, 0xff);
396 outb_reg1(dep, DP_MAR7, 0xff);
397
398 outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
399
400 /* Step 10: */
401 outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
402
403 /* Step 11: */
404 outb_reg0(dep, DP_TCR, TCR_NORMAL);
405
406 inb_reg0(dep, DP_CNTR0); /* Reset counters by reading */
407 inb_reg0(dep, DP_CNTR1);
408 inb_reg0(dep, DP_CNTR2);
409
410 /* Finish the initialization. */
411 dep->de_flags |= DEF_ENABLED;
412 for (i = 0; i < dep->de_sendq_nr; i++)
413 dep->de_sendq[i].sq_filled= 0;
414
415 dep->de_sendq_head = 0;
416 dep->de_sendq_tail = 0;
417
418 if (dep->de_16bit) {
419 dep->de_user2nicf= dp_pio16_user2nic;
420 dep->de_nic2userf= dp_pio16_nic2user;
421 dep->de_getblockf= dp_pio16_getblock;
422 } else {
423 dep->de_user2nicf= dp_pio8_user2nic;
424 dep->de_nic2userf= dp_pio8_nic2user;
425 dep->de_getblockf= dp_pio8_getblock;
426 }
427}
428
429static void dp_reinit(dep)
430dpeth_t *dep;
431{
432 int dp_rcr_reg;
433
434 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
435
436 dp_rcr_reg = 0;
437 if (dep->de_flags &DEF_PROMISC)
438 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
439 if (dep->de_flags &DEF_BROAD)
440 dp_rcr_reg |= RCR_AB;
441 if (dep->de_flags &DEF_MULTI)
442 dp_rcr_reg |= RCR_AM;
443 outb_reg0(dep, DP_RCR, dp_rcr_reg);
444}
445
446/*===========================================================================*
447 * dp_reset *
448 *===========================================================================*/
449static void dp_reset(dep)
450dpeth_t *dep;
451{
452 int i;
453
454 /* Stop chip */
455 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
456 outb_reg0(dep, DP_RBCR0, 0);
457 outb_reg0(dep, DP_RBCR1, 0);
458 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++)
459 ; /* Do nothing */
460 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
461 outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
462 outb_reg0(dep, DP_TCR, TCR_NORMAL);
463
464 /* Acknowledge the ISR_RDC (remote dma) interrupt. */
465 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++)
466 ; /* Do nothing */
467 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) &~ISR_RDC);
468
469 /* Reset the transmit ring. If we were transmitting a packet, we
470 * pretend that the packet is processed. Higher layers will
471 * retransmit if the packet wasn't actually sent.
472 */
473 dep->de_sendq_head= dep->de_sendq_tail= 0;
474 for (i= 0; i<dep->de_sendq_nr; i++)
475 dep->de_sendq[i].sq_filled= 0;
476 dp_send(dep);
477 dep->de_flags &= ~DEF_STOPPED;
478}
479
480void dp_check_ints(dpeth_t *dep, int isr)
481{
482 int tsr;
483 int size, sendq_tail;
484
485 if (!(dep->de_flags & DEF_ENABLED))
486 fprintf(stderr, "dp8390: got premature interrupt\n");
487
488 for (; isr; isr = inb_reg0(dep, DP_ISR)) {
489 outb_reg0(dep, DP_ISR, isr);
490
491 if (isr & (ISR_PTX | ISR_TXE)) {
492 if (isr & ISR_TXE)
493 dep->de_stat.ets_sendErr++;
494 else {
495 tsr = inb_reg0(dep, DP_TSR);
496
497 if (tsr & TSR_PTX)
498 dep->de_stat.ets_packetT++;
499
500 if (tsr & TSR_COL)
501 dep->de_stat.ets_collision++;
502
503 if (tsr & TSR_ABT)
504 dep->de_stat.ets_transAb++;
505
506 if (tsr & TSR_CRS)
507 dep->de_stat.ets_carrSense++;
508
509 if ((tsr & TSR_FU) && (++dep->de_stat.ets_fifoUnder <= 10))
510 printf("%s: fifo underrun\n", dep->de_name);
511
512 if ((tsr & TSR_CDH) && (++dep->de_stat.ets_CDheartbeat <= 10))
513 printf("%s: CD heart beat failure\n", dep->de_name);
514
515 if (tsr & TSR_OWC)
516 dep->de_stat.ets_OWC++;
517 }
518
519 sendq_tail = dep->de_sendq_tail;
520
521 if (!(dep->de_sendq[sendq_tail].sq_filled)) {
522 /* Or hardware bug? */
523 printf("%s: transmit interrupt, but not sending\n", dep->de_name);
524 continue;
525 }
526
527 dep->de_sendq[sendq_tail].sq_filled = 0;
528
529 if (++sendq_tail == dep->de_sendq_nr)
530 sendq_tail = 0;
531
532 dep->de_sendq_tail = sendq_tail;
533
534 if (dep->de_sendq[sendq_tail].sq_filled) {
535 size = dep->de_sendq[sendq_tail].sq_size;
536 outb_reg0(dep, DP_TPSR,
537 dep->de_sendq[sendq_tail].sq_sendpage);
538 outb_reg0(dep, DP_TBCR1, size >> 8);
539 outb_reg0(dep, DP_TBCR0, size & 0xff);
540 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
541 }
542
543// if (dep->de_flags &DEF_SEND_AVAIL)
544 dp_send(dep);
545 }
546
547 if (isr & ISR_PRX) {
548 /* Only call dp_recv if there is a read request */
549// if (dep->de_flags) &DEF_READING)
550 dp_recv(dep);
551 }
552
553 if (isr & ISR_RXE)
554 dep->de_stat.ets_recvErr++;
555
556 if (isr & ISR_CNT) {
557 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
558 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
559 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
560 }
561
562 if (isr & ISR_OVW) {
563 dep->de_stat.ets_OVW++;
564/* if (dep->de_flags & DEF_READING) {
565 printf("dp_check_ints: strange: overwrite warning and pending read request\n");
566 dp_recv(dep);
567 }
568*/ }
569
570 if (isr & ISR_RDC) {
571 /* Nothing to do */
572 }
573
574 if (isr & ISR_RST) {
575 /*
576 * This means we got an interrupt but the ethernet
577 * chip is shutdown. We set the flag DEF_STOPPED,
578 * and continue processing arrived packets. When the
579 * receive buffer is empty, we reset the dp8390.
580 */
581 dep->de_flags |= DEF_STOPPED;
582 break;
583 }
584 }
585
586// if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED))
587 if ((dep->de_flags & DEF_STOPPED) == DEF_STOPPED) {
588 /*
589 * The chip is stopped, and all arrived packets
590 * are delivered.
591 */
592 dp_reset(dep);
593 }
594}
595
596static void dp_recv(dpeth_t *dep)
597{
598 dp_rcvhdr_t header;
599 //unsigned pageno, curr, next;
600 int pageno, curr, next;
601 vir_bytes length;
602 int packet_processed, r;
603 uint16_t eth_type;
604
605 packet_processed = false;
606 pageno = inb_reg0(dep, DP_BNRY) + 1;
607 if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
608
609 do
610 {
611 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
612 curr = inb_reg1(dep, DP_CURR);
613 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
614
615 if (curr == pageno) break;
616
617 (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
618 &header);
619 (dep->de_getblockf)(dep, pageno, sizeof(header) +
620 2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
621
622 length = (header.dr_rbcl | (header.dr_rbch << 8)) -
623 sizeof(dp_rcvhdr_t);
624 next = header.dr_next;
625 if (length < ETH_MIN_PACK_SIZE ||
626 length > ETH_MAX_PACK_SIZE_TAGGED)
627 {
628 printf("%s: packet with strange length arrived: %d\n",
629 dep->de_name, (int) length);
630 next= curr;
631 }
632 else if (next < dep->de_startpage || next >= dep->de_stoppage)
633 {
634 printf("%s: strange next page\n", dep->de_name);
635 next= curr;
636 }
637/* else if (eth_type == eth_ign_proto)
638 {
639*/ /* Hack: ignore packets of a given protocol, useful
640 * if you share a net with 80 computers sending
641 * Amoeba FLIP broadcasts. (Protocol 0x8146.)
642 */
643/* static int first= 1;
644 if (first)
645 {
646 first= 0;
647 printf("%s: dropping proto 0x%04x packets\n",
648 dep->de_name,
649 ntohs(eth_ign_proto));
650 }
651 dep->de_stat.ets_packetR++;
652 }
653*/ else if (header.dr_status &RSR_FO)
654 {
655 /* This is very serious, so we issue a warning and
656 * reset the buffers */
657 printf("%s: fifo overrun, resetting receive buffer\n",
658 dep->de_name);
659 dep->de_stat.ets_fifoOver++;
660 next = curr;
661 }
662 else if ((header.dr_status &RSR_PRX) &&
663 (dep->de_flags &DEF_ENABLED))
664 {
665// if (dep->de_safecopy_read)
666// r = dp_pkt2user_s(dep, pageno, length);
667// else
668 r = dp_pkt2user(dep, pageno, length);
669 if (r != EOK)
670 return;
671
672 packet_processed = true;
673 dep->de_stat.ets_packetR++;
674 }
675 if (next == dep->de_startpage)
676 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
677 else
678 outb_reg0(dep, DP_BNRY, next - 1);
679
680 pageno = next;
681 }
682 while (!packet_processed);
683}
684
685/*===========================================================================*
686 * dp_send *
687 *===========================================================================*/
688static void dp_send(dep)
689dpeth_t *dep;
690{
691 packet_t *packet;
692
693// if (!(dep->de_flags &DEF_SEND_AVAIL))
694// return;
695
696 if(dep->packet_queue){
697 packet = dep->packet_queue;
698 dep->packet_queue = pq_detach(packet);
699 do_pwrite(dep, packet, true);
700 netif_pq_release(packet_get_id(packet));
701 -- dep->packet_count;
702 }
703// if(! dep->packet_queue){
704// dep->de_flags &= ~DEF_SEND_AVAIL;
705// }
706/* switch(dep->de_sendmsg.m_type)
707 {
708 case DL_WRITE: do_vwrite(&dep->de_sendmsg, true, false); break;
709 case DL_WRITEV: do_vwrite(&dep->de_sendmsg, true, true); break;
710 case DL_WRITEV_S: do_vwrite_s(&dep->de_sendmsg, true); break;
711 default:
712 fprintf(stderr, "dp8390: wrong type\n");
713 break;
714 }
715*/
716}
717
718/*===========================================================================*
719 * dp_pio8_getblock *
720 *===========================================================================*/
721static void dp_pio8_getblock(dep, page, offset, size, dst)
722dpeth_t *dep;
723int page;
724size_t offset;
725size_t size;
726void *dst;
727{
728 offset = page * DP_PAGESIZE + offset;
729 outb_reg0(dep, DP_RBCR0, size &0xFF);
730 outb_reg0(dep, DP_RBCR1, size >> 8);
731 outb_reg0(dep, DP_RSAR0, offset &0xFF);
732 outb_reg0(dep, DP_RSAR1, offset >> 8);
733 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
734
735 insb(dep->de_data_port, dst, size);
736}
737
738/*===========================================================================*
739 * dp_pio16_getblock *
740 *===========================================================================*/
741static void dp_pio16_getblock(dep, page, offset, size, dst)
742dpeth_t *dep;
743int page;
744size_t offset;
745size_t size;
746void *dst;
747{
748 offset = page * DP_PAGESIZE + offset;
749 outb_reg0(dep, DP_RBCR0, size &0xFF);
750 outb_reg0(dep, DP_RBCR1, size >> 8);
751 outb_reg0(dep, DP_RSAR0, offset &0xFF);
752 outb_reg0(dep, DP_RSAR1, offset >> 8);
753 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
754
755 assert (!(size &1));
756 insw(dep->de_data_port, dst, size);
757}
758
759/*===========================================================================*
760 * dp_pkt2user *
761 *===========================================================================*/
762static int dp_pkt2user(dep, page, length)
763dpeth_t *dep;
764int page, length;
765{
766 int last, count;
767 packet_t *packet;
768
769// if (!(dep->de_flags &DEF_READING))
770// return EGENERIC;
771
772 packet = netif_packet_get_1(length);
773 if(! packet){
774 return ENOMEM;
775 }
776 dep->de_read_iovec.iod_iovec[0].iov_addr = (vir_bytes) packet_suffix(packet, length);
777 dep->de_read_iovec.iod_iovec[0].iov_size = length;
778 dep->de_read_iovec.iod_iovec_s = 1;
779 dep->de_read_iovec.iod_iovec_addr = (uintptr_t) NULL;
780
781 last = page + (length - 1) / DP_PAGESIZE;
782 if (last >= dep->de_stoppage)
783 {
784 count = (dep->de_stoppage - page) * DP_PAGESIZE -
785 sizeof(dp_rcvhdr_t);
786
787 /* Save read_iovec since we need it twice. */
788 dep->de_tmp_iovec = dep->de_read_iovec;
789 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
790 sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
791 (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
792 &dep->de_read_iovec, count, length - count);
793 }
794 else
795 {
796 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
797 sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
798 }
799
800 dep->de_read_s = length;
801 dep->de_flags |= DEF_PACK_RECV;
802// dep->de_flags &= ~DEF_READING;
803
804 if(dep->received_count >= MAX_PACKETS){
805 netif_pq_release(packet_get_id(packet));
806 return ELIMIT;
807 }else{
808 if(pq_add(&dep->received_queue, packet, 0, 0) == EOK){
809 ++ dep->received_count;
810 }else{
811 netif_pq_release(packet_get_id(packet));
812 }
813 }
814 return EOK;
815}
816
817/*===========================================================================*
818 * dp_pio8_user2nic *
819 *===========================================================================*/
820static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
821dpeth_t *dep;
822iovec_dat_t *iovp;
823vir_bytes offset;
824int nic_addr;
825vir_bytes count;
826{
827// phys_bytes phys_user;
828 int i;
829 vir_bytes bytes;
830
831 outb_reg0(dep, DP_ISR, ISR_RDC);
832
833 outb_reg0(dep, DP_RBCR0, count &0xFF);
834 outb_reg0(dep, DP_RBCR1, count >> 8);
835 outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
836 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
837 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
838
839 i= 0;
840 while (count > 0)
841 {
842 if (i >= IOVEC_NR)
843 {
844 dp_next_iovec(iovp);
845 i= 0;
846 continue;
847 }
848 assert(i < iovp->iod_iovec_s);
849 if (offset >= iovp->iod_iovec[i].iov_size)
850 {
851 offset -= iovp->iod_iovec[i].iov_size;
852 i++;
853 continue;
854 }
855 bytes = iovp->iod_iovec[i].iov_size - offset;
856 if (bytes > count)
857 bytes = count;
858
859 do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
860 iovp->iod_iovec[i].iov_addr + offset, bytes);
861 count -= bytes;
862 offset += bytes;
863 }
864 assert(count == 0);
865
866 for (i= 0; i<100; i++)
867 {
868 if (inb_reg0(dep, DP_ISR) &ISR_RDC)
869 break;
870 }
871 if (i == 100)
872 fprintf(stderr, "dp8390: remote dma failed to complete\n");
873}
874
875/*===========================================================================*
876 * dp_pio16_user2nic *
877 *===========================================================================*/
878static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
879dpeth_t *dep;
880iovec_dat_t *iovp;
881vir_bytes offset;
882int nic_addr;
883vir_bytes count;
884{
885 vir_bytes vir_user;
886 vir_bytes ecount;
887 int i, r, user_proc;
888 vir_bytes bytes;
889 //uint8_t two_bytes[2];
890 uint16_t two_bytes;
891 int odd_byte;
892
893 ecount= (count+1) &~1;
894 odd_byte= 0;
895
896 outb_reg0(dep, DP_ISR, ISR_RDC);
897 outb_reg0(dep, DP_RBCR0, ecount &0xFF);
898 outb_reg0(dep, DP_RBCR1, ecount >> 8);
899 outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
900 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
901 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
902
903 i= 0;
904 while (count > 0)
905 {
906 if (i >= IOVEC_NR)
907 {
908 dp_next_iovec(iovp);
909 i= 0;
910 continue;
911 }
912 assert(i < iovp->iod_iovec_s);
913 if (offset >= iovp->iod_iovec[i].iov_size)
914 {
915 offset -= iovp->iod_iovec[i].iov_size;
916 i++;
917 continue;
918 }
919 bytes = iovp->iod_iovec[i].iov_size - offset;
920 if (bytes > count)
921 bytes = count;
922
923 user_proc= iovp->iod_proc_nr;
924 vir_user= iovp->iod_iovec[i].iov_addr + offset;
925 if (odd_byte)
926 {
927 r= sys_vircopy(user_proc, D, vir_user,
928 // SELF, D, (vir_bytes)&two_bytes[1], 1);
929 SELF, D, (vir_bytes)&(((uint8_t *)&two_bytes)[1]), 1);
930 if (r != EOK)
931 fprintf(stderr, "DP8390: dp_pio16_user2nic: sys_vircopy failed\n");
932
933 //outw(dep->de_data_port, *(uint16_t *)two_bytes);
934 outw(dep->de_data_port, two_bytes);
935 count--;
936 offset++;
937 bytes--;
938 vir_user++;
939 odd_byte= 0;
940 if (!bytes)
941 continue;
942 }
943 ecount= bytes &~1;
944 if (ecount != 0)
945 {
946 do_vir_outsw(dep->de_data_port, user_proc, vir_user,
947 ecount);
948 count -= ecount;
949 offset += ecount;
950 bytes -= ecount;
951 vir_user += ecount;
952 }
953 if (bytes)
954 {
955 assert(bytes == 1);
956 r= sys_vircopy(user_proc, D, vir_user,
957 // SELF, D, (vir_bytes)&two_bytes[0], 1);
958 SELF, D, (vir_bytes)&(((uint8_t *)&two_bytes)[0]), 1);
959 if (r != EOK)
960 fprintf(stderr, "DP8390: dp_pio16_user2nic: sys_vircopy failed\n");
961
962 count--;
963 offset++;
964 bytes--;
965 vir_user++;
966 odd_byte= 1;
967 }
968 }
969 assert(count == 0);
970
971 if (odd_byte)
972 //outw(dep->de_data_port, *(uint16_t *)two_bytes);
973 outw(dep->de_data_port, two_bytes);
974
975 for (i= 0; i<100; i++)
976 {
977 if (inb_reg0(dep, DP_ISR) &ISR_RDC)
978 break;
979 }
980 if (i == 100)
981 fprintf(stderr, "dp8390: remote dma failed to complete\n");
982}
983
984/*===========================================================================*
985 * dp_pio8_nic2user *
986 *===========================================================================*/
987static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
988dpeth_t *dep;
989int nic_addr;
990iovec_dat_t *iovp;
991vir_bytes offset;
992vir_bytes count;
993{
994// phys_bytes phys_user;
995 int i;
996 vir_bytes bytes;
997
998 outb_reg0(dep, DP_RBCR0, count &0xFF);
999 outb_reg0(dep, DP_RBCR1, count >> 8);
1000 outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
1001 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1002 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1003
1004 i= 0;
1005 while (count > 0)
1006 {
1007 if (i >= IOVEC_NR)
1008 {
1009 dp_next_iovec(iovp);
1010 i= 0;
1011 continue;
1012 }
1013 assert(i < iovp->iod_iovec_s);
1014 if (offset >= iovp->iod_iovec[i].iov_size)
1015 {
1016 offset -= iovp->iod_iovec[i].iov_size;
1017 i++;
1018 continue;
1019 }
1020 bytes = iovp->iod_iovec[i].iov_size - offset;
1021 if (bytes > count)
1022 bytes = count;
1023
1024 do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
1025 iovp->iod_iovec[i].iov_addr + offset, bytes);
1026 count -= bytes;
1027 offset += bytes;
1028 }
1029 assert(count == 0);
1030}
1031
1032/*===========================================================================*
1033 * dp_pio16_nic2user *
1034 *===========================================================================*/
1035static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
1036dpeth_t *dep;
1037int nic_addr;
1038iovec_dat_t *iovp;
1039vir_bytes offset;
1040vir_bytes count;
1041{
1042 vir_bytes vir_user;
1043 vir_bytes ecount;
1044 int i, r, user_proc;
1045 vir_bytes bytes;
1046 //uint8_t two_bytes[2];
1047 uint16_t two_bytes;
1048 int odd_byte;
1049
1050 ecount= (count+1) &~1;
1051 odd_byte= 0;
1052
1053 outb_reg0(dep, DP_RBCR0, ecount &0xFF);
1054 outb_reg0(dep, DP_RBCR1, ecount >> 8);
1055 outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
1056 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1057 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1058
1059 i= 0;
1060 while (count > 0)
1061 {
1062 if (i >= IOVEC_NR)
1063 {
1064 dp_next_iovec(iovp);
1065 i= 0;
1066 continue;
1067 }
1068 assert(i < iovp->iod_iovec_s);
1069 if (offset >= iovp->iod_iovec[i].iov_size)
1070 {
1071 offset -= iovp->iod_iovec[i].iov_size;
1072 i++;
1073 continue;
1074 }
1075 bytes = iovp->iod_iovec[i].iov_size - offset;
1076 if (bytes > count)
1077 bytes = count;
1078
1079 user_proc= iovp->iod_proc_nr;
1080 vir_user= iovp->iod_iovec[i].iov_addr + offset;
1081 if (odd_byte)
1082 {
1083 //r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
1084 r= sys_vircopy(SELF, D, (vir_bytes)&(((uint8_t *)&two_bytes)[1]),
1085 user_proc, D, vir_user, 1);
1086 if (r != EOK)
1087 fprintf(stderr, "DP8390: dp_pio16_nic2user: sys_vircopy failed\n");
1088
1089 count--;
1090 offset++;
1091 bytes--;
1092 vir_user++;
1093 odd_byte= 0;
1094 if (!bytes)
1095 continue;
1096 }
1097 ecount= bytes &~1;
1098 if (ecount != 0)
1099 {
1100 do_vir_insw(dep->de_data_port, user_proc, vir_user,
1101 ecount);
1102 count -= ecount;
1103 offset += ecount;
1104 bytes -= ecount;
1105 vir_user += ecount;
1106 }
1107 if (bytes)
1108 {
1109 assert(bytes == 1);
1110 //*(uint16_t *)two_bytes= inw(dep->de_data_port);
1111 two_bytes= inw(dep->de_data_port);
1112 //r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
1113 r= sys_vircopy(SELF, D, (vir_bytes)&(((uint8_t *)&two_bytes)[0]),
1114 user_proc, D, vir_user, 1);
1115 if (r != EOK)
1116 fprintf(stderr, "DP8390: dp_pio16_nic2user: sys_vircopy failed\n");
1117
1118 count--;
1119 offset++;
1120 bytes--;
1121 vir_user++;
1122 odd_byte= 1;
1123 }
1124 }
1125 assert(count == 0);
1126}
1127
1128/*===========================================================================*
1129 * dp_next_iovec *
1130 *===========================================================================*/
1131static void dp_next_iovec(iovp)
1132iovec_dat_t *iovp;
1133{
1134 assert(iovp->iod_iovec_s > IOVEC_NR);
1135
1136 iovp->iod_iovec_s -= IOVEC_NR;
1137
1138 iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
1139
1140 get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
1141 (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
1142 sizeof(iovec_t), iovp->iod_iovec);
1143}
1144
1145/*===========================================================================*
1146 * conf_hw *
1147 *===========================================================================*/
1148static void conf_hw(dep)
1149dpeth_t *dep;
1150{
1151// static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */};
1152
1153// int ifnr;
1154// dp_conf_t *dcp;
1155
1156// dep->de_mode= DEM_DISABLED; /* Superfluous */
1157// ifnr= dep-de_table;
1158
1159// dcp= &dp_conf[ifnr];
1160// update_conf(dep, dcp);
1161// if (dep->de_mode != DEM_ENABLED)
1162// return;
1163 if (!ne_probe(dep)) {
1164 printf("%s: No ethernet card found at %#lx\n",
1165 dep->de_name, dep->de_base_port);
1166 dep->de_mode= DEM_DISABLED;
1167 return;
1168 }
1169
1170/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
1171
1172 dep->de_mode = DEM_ENABLED;
1173
1174 dep->de_flags = DEF_EMPTY;
1175// dep->de_stat = empty_stat;
1176}
1177
1178/*===========================================================================*
1179 * reply *
1180 *===========================================================================*/
1181static void reply(dep, err, may_block)
1182dpeth_t *dep;
1183int err;
1184int may_block;
1185{
1186/* message reply;
1187 int status;
1188 int r;
1189
1190 status = 0;
1191 if (dep->de_flags &DEF_PACK_SEND)
1192 status |= DL_PACK_SEND;
1193 if (dep->de_flags &DEF_PACK_RECV)
1194 status |= DL_PACK_RECV;
1195
1196 reply.m_type = DL_TASK_REPLY;
1197 reply.DL_PORT = dep - de_table;
1198 reply.DL_PROC = dep->de_client;
1199 reply.DL_STAT = status | ((u32_t) err << 16);
1200 reply.DL_COUNT = dep->de_read_s;
1201 reply.DL_CLCK = 0; *//* Don't know */
1202/* r= send(dep->de_client, &reply);
1203
1204 if (r == ELOCKED && may_block)
1205 {
1206#if 0
1207 printf("send locked\n");
1208#endif
1209 return;
1210 }
1211
1212 if (r < 0)
1213 fprintf(stderr, "dp8390: send failed\n");
1214
1215*/ dep->de_read_s = 0;
1216// dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
1217}
1218
1219/*===========================================================================*
1220 * get_userdata *
1221 *===========================================================================*/
1222static void get_userdata(user_proc, user_addr, count, loc_addr)
1223int user_proc;
1224vir_bytes user_addr;
1225vir_bytes count;
1226void *loc_addr;
1227{
1228 int r;
1229
1230 r= sys_vircopy(user_proc, D, user_addr,
1231 SELF, D, (vir_bytes)loc_addr, count);
1232 if (r != EOK)
1233 fprintf(stderr, "DP8390: get_userdata: sys_vircopy failed\n");
1234}
1235
1236static void insb(port_t port, void *buf, size_t size)
1237{
1238 size_t i;
1239
1240 for(i = 0; i < size; ++ i){
1241 *((uint8_t *) buf + i) = inb(port);
1242 }
1243}
1244
1245static void insw(port_t port, void *buf, size_t size)
1246{
1247 size_t i;
1248
1249 for(i = 0; i * 2 < size; ++ i){
1250 *((uint16_t *) buf + i) = inw(port);
1251 }
1252}
1253
1254static void outsb(port_t port, void *buf, size_t size)
1255{
1256 size_t i;
1257
1258 for(i = 0; i < size; ++ i){
1259 outb(port, *((uint8_t *) buf + i));
1260 }
1261}
1262
1263static void outsw(port_t port, void *buf, size_t size)
1264{
1265 size_t i;
1266
1267 for(i = 0; i * 2 < size; ++ i){
1268 outw(port, *((uint16_t *) buf + i));
1269 }
1270}
1271
1272/** @}
1273 */
Note: See TracBrowser for help on using the repository browser.