source: mainline/uspace/srv/hw/netif/dp8390/dp8390.c@ 202f57b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 202f57b was 7e1f9b7, checked in by Jakub Jermar <jakub@…>, 15 years ago

Merge from lp:~jakub/helenos/net.

  • Property mode set to 100644
File size: 44.8 KB
Line 
1/*
2 * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
3 *
4 * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
5 * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
6 * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
7 * * Any deviations from these conditions require written permission from the copyright holder in advance
8 *
9 *
10 * Disclaimer
11 *
12 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
14 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
18 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
19 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 *
23 * Changes:
24 * 2009 ported to HelenOS, Lukas Mejdrech
25 */
26
27/** @addtogroup dp8390
28 * @{
29 */
30
31/** @file
32 * DP8390 network interface core implementation.
33 */
34
35#include <assert.h>
36#include <byteorder.h>
37#include <errno.h>
38
39#include <netif_local.h>
40#include <net/packet.h>
41#include <packet_client.h>
42
43#include "dp8390_drv.h"
44#include "dp8390_port.h"
45
46/*
47 * dp8390.c
48 *
49 * Created: before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
50 *
51 * Modified Mar 10 1994 by Philip Homburg
52 * Become a generic dp8390 driver.
53 *
54 * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
55 * Added support for 3c503 boards.
56 */
57
58#include "local.h"
59#include "dp8390.h"
60
61/** Queues the outgoing packet.
62 * @param[in] dep The network interface structure.
63 * @param[in] packet The outgoing packet.
64 * @return EOK on success.
65 * @return EINVAL
66 */
67int queue_packet(dpeth_t * dep, packet_t *packet);
68
69/** Reads a memory block byte by byte.
70 * @param[in] port The source address.
71 * @param[out] buf The destination buffer.
72 * @param[in] size The memory block size in bytes.
73 */
74static void outsb(port_t port, void * buf, size_t size);
75
76/** Reads a memory block word by word.
77 * @param[in] port The source address.
78 * @param[out] buf The destination buffer.
79 * @param[in] size The memory block size in bytes.
80 */
81static void outsw(port_t port, void * buf, size_t size);
82
83//static u16_t eth_ign_proto;
84//static char *progname;
85
86/* Configuration */
87/*typedef struct dp_conf
88{
89 port_t dpc_port;
90 int dpc_irq;
91 phys_bytes dpc_mem;
92 char *dpc_envvar;
93} dp_conf_t;
94*/
95//dp_conf_t dp_conf[]= /* Card addresses */
96//{
97 /* I/O port, IRQ, Buffer address, Env. var. */
98/* { 0x280, 3, 0xD0000, "DPETH0" },
99 { 0x300, 5, 0xC8000, "DPETH1" },
100 { 0x380, 10, 0xD8000, "DPETH2" },
101};
102*/
103/* Test if dp_conf has exactly DE_PORT_NR entries. If not then you will see
104 * the error: "array size is negative".
105 */
106//extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
107
108/* Card inits configured out? */
109#if !ENABLE_WDETH
110#define wdeth_probe(dep) (0)
111#endif
112#if !ENABLE_NE2000
113#define ne_probe(dep) (0)
114#endif
115#if !ENABLE_3C503
116#define el2_probe(dep) (0)
117#endif
118
119/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
120 * on writes to the CR register. Additional CR_STAs do not appear to hurt
121 * genuine dp8390s
122 */
123#define CR_EXTRA CR_STA
124
125//#if ENABLE_PCI
126//_PROTOTYPE(static void pci_conf, (void) );
127//#endif
128//_PROTOTYPE(static void do_vwrite, (message *mp, int from_int,
129// int vectored) );
130//_PROTOTYPE(static void do_vwrite_s, (message *mp, int from_int) );
131//_PROTOTYPE(static void do_vread, (message *mp, int vectored) );
132//_PROTOTYPE(static void do_vread_s, (message *mp) );
133//_PROTOTYPE(static void do_init, (message *mp) );
134//_PROTOTYPE(static void do_int, (dpeth_t *dep) );
135//_PROTOTYPE(static void do_getstat, (message *mp) );
136//_PROTOTYPE(static void do_getstat_s, (message *mp) );
137//_PROTOTYPE(static void do_getname, (message *mp) );
138//_PROTOTYPE(static void do_stop, (message *mp) );
139_PROTOTYPE(static void dp_init, (dpeth_t *dep) );
140//_PROTOTYPE(static void dp_confaddr, (dpeth_t *dep) );
141_PROTOTYPE(static void dp_reinit, (dpeth_t *dep) );
142_PROTOTYPE(static void dp_reset, (dpeth_t *dep) );
143//_PROTOTYPE(static void dp_check_ints, (dpeth_t *dep) );
144_PROTOTYPE(static void dp_recv, (dpeth_t *dep) );
145_PROTOTYPE(static void dp_send, (dpeth_t *dep) );
146//_PROTOTYPE(static void dp8390_stop, (void) );
147_PROTOTYPE(static void dp_getblock, (dpeth_t *dep, int page,
148 size_t offset, size_t size, void *dst) );
149_PROTOTYPE(static void dp_pio8_getblock, (dpeth_t *dep, int page,
150 size_t offset, size_t size, void *dst) );
151_PROTOTYPE(static void dp_pio16_getblock, (dpeth_t *dep, int page,
152 size_t offset, size_t size, void *dst) );
153_PROTOTYPE(static int dp_pkt2user, (dpeth_t *dep, int page,
154 int length) );
155//_PROTOTYPE(static int dp_pkt2user_s, (dpeth_t *dep, int page,
156// int length) );
157_PROTOTYPE(static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp,
158 vir_bytes offset, int nic_addr, vir_bytes count) );
159//_PROTOTYPE(static void dp_user2nic_s, (dpeth_t *dep, iovec_dat_s_t *iovp,
160// vir_bytes offset, int nic_addr, vir_bytes count) );
161_PROTOTYPE(static void dp_pio8_user2nic, (dpeth_t *dep,
162 iovec_dat_t *iovp, vir_bytes offset,
163 int nic_addr, vir_bytes count) );
164//_PROTOTYPE(static void dp_pio8_user2nic_s, (dpeth_t *dep,
165// iovec_dat_s_t *iovp, vir_bytes offset,
166// int nic_addr, vir_bytes count) );
167_PROTOTYPE(static void dp_pio16_user2nic, (dpeth_t *dep,
168 iovec_dat_t *iovp, vir_bytes offset,
169 int nic_addr, vir_bytes count) );
170//_PROTOTYPE(static void dp_pio16_user2nic_s, (dpeth_t *dep,
171// iovec_dat_s_t *iovp, vir_bytes offset,
172// int nic_addr, vir_bytes count) );
173_PROTOTYPE(static void dp_nic2user, (dpeth_t *dep, int nic_addr,
174 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
175//_PROTOTYPE(static void dp_nic2user_s, (dpeth_t *dep, int nic_addr,
176// iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
177_PROTOTYPE(static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr,
178 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
179//_PROTOTYPE(static void dp_pio8_nic2user_s, (dpeth_t *dep, int nic_addr,
180// iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
181_PROTOTYPE(static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr,
182 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
183//_PROTOTYPE(static void dp_pio16_nic2user_s, (dpeth_t *dep, int nic_addr,
184// iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
185_PROTOTYPE(static void dp_next_iovec, (iovec_dat_t *iovp) );
186//_PROTOTYPE(static void dp_next_iovec_s, (iovec_dat_s_t *iovp) );
187_PROTOTYPE(static void conf_hw, (dpeth_t *dep) );
188//_PROTOTYPE(static void update_conf, (dpeth_t *dep, dp_conf_t *dcp) );
189_PROTOTYPE(static void map_hw_buffer, (dpeth_t *dep) );
190//_PROTOTYPE(static int calc_iovec_size, (iovec_dat_t *iovp) );
191//_PROTOTYPE(static int calc_iovec_size_s, (iovec_dat_s_t *iovp) );
192_PROTOTYPE(static void reply, (dpeth_t *dep, int err, int may_block) );
193//_PROTOTYPE(static void mess_reply, (message *req, message *reply) );
194_PROTOTYPE(static void get_userdata, (int user_proc,
195 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
196//_PROTOTYPE(static void get_userdata_s, (int user_proc,
197// cp_grant_id_t grant, vir_bytes offset, vir_bytes count,
198// void *loc_addr) );
199//_PROTOTYPE(static void put_userdata, (int user_proc,
200// vir_bytes user_addr, vir_bytes count, void *loc_addr) );
201//_PROTOTYPE(static void put_userdata_s, (int user_proc,
202// cp_grant_id_t grant, size_t count, void *loc_addr) );
203_PROTOTYPE(static void insb, (port_t port, void *buf, size_t size) );
204_PROTOTYPE(static void insw, (port_t port, void *buf, size_t size) );
205//_PROTOTYPE(static void do_vir_insb, (port_t port, int proc,
206// vir_bytes buf, size_t size) );
207//_PROTOTYPE(static void do_vir_insw, (port_t port, int proc,
208// vir_bytes buf, size_t size) );
209//_PROTOTYPE(static void do_vir_outsb, (port_t port, int proc,
210// vir_bytes buf, size_t size) );
211//_PROTOTYPE(static void do_vir_outsw, (port_t port, int proc,
212// vir_bytes buf, size_t size) );
213
214int do_probe(dpeth_t * dep){
215 /* This is the default, try to (re)locate the device. */
216 conf_hw(dep);
217 if (dep->de_mode == DEM_DISABLED)
218 {
219 /* Probe failed, or the device is configured off. */
220 return EXDEV;//ENXIO;
221 }
222 if (dep->de_mode == DEM_ENABLED)
223 dp_init(dep);
224 return EOK;
225}
226
227/*===========================================================================*
228 * dp8390_dump *
229 *===========================================================================*/
230void dp8390_dump(dpeth_t * dep)
231{
232// dpeth_t *dep;
233 int /*i,*/ isr;
234
235// printf("\n");
236// for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
237// {
238#if XXX
239 if (dep->de_mode == DEM_DISABLED)
240 printf("dp8390 port %d is disabled\n", i);
241 else if (dep->de_mode == DEM_SINK)
242 printf("dp8390 port %d is in sink mode\n", i);
243#endif
244
245 if (dep->de_mode != DEM_ENABLED)
246// continue;
247 return;
248
249// printf("dp8390 statistics of port %d:\n", i);
250
251 printf("recvErr :%8ld\t", dep->de_stat.ets_recvErr);
252 printf("sendErr :%8ld\t", dep->de_stat.ets_sendErr);
253 printf("OVW :%8ld\n", dep->de_stat.ets_OVW);
254
255 printf("CRCerr :%8ld\t", dep->de_stat.ets_CRCerr);
256 printf("frameAll :%8ld\t", dep->de_stat.ets_frameAll);
257 printf("missedP :%8ld\n", dep->de_stat.ets_missedP);
258
259 printf("packetR :%8ld\t", dep->de_stat.ets_packetR);
260 printf("packetT :%8ld\t", dep->de_stat.ets_packetT);
261 printf("transDef :%8ld\n", dep->de_stat.ets_transDef);
262
263 printf("collision :%8ld\t", dep->de_stat.ets_collision);
264 printf("transAb :%8ld\t", dep->de_stat.ets_transAb);
265 printf("carrSense :%8ld\n", dep->de_stat.ets_carrSense);
266
267 printf("fifoUnder :%8ld\t", dep->de_stat.ets_fifoUnder);
268 printf("fifoOver :%8ld\t", dep->de_stat.ets_fifoOver);
269 printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
270
271 printf("OWC :%8ld\t", dep->de_stat.ets_OWC);
272
273 isr= inb_reg0(dep, DP_ISR);
274 printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
275 inb_reg0(dep, DP_ISR), dep->de_flags);
276// }
277}
278
279/*===========================================================================*
280 * do_init *
281 *===========================================================================*/
282int do_init(dpeth_t * dep, int mode){
283 if (dep->de_mode == DEM_DISABLED)
284 {
285 // might call do_probe()
286 return EXDEV;
287 }
288
289 if (dep->de_mode == DEM_SINK)
290 {
291// strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
292// dep->de_address.ea_addr[5] = port;
293// dp_confaddr(dep);
294// reply_mess.m_type = DL_CONF_REPLY;
295// reply_mess.m3_i1 = mp->DL_PORT;
296// reply_mess.m3_i2 = DE_PORT_NR;
297// *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
298// mess_reply(mp, &reply_mess);
299// return;
300 return EOK;
301 }
302 assert(dep->de_mode == DEM_ENABLED);
303 assert(dep->de_flags &DEF_ENABLED);
304
305 dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
306
307 if (mode &DL_PROMISC_REQ)
308 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
309 if (mode &DL_MULTI_REQ)
310 dep->de_flags |= DEF_MULTI;
311 if (mode &DL_BROAD_REQ)
312 dep->de_flags |= DEF_BROAD;
313
314// dep->de_client = mp->m_source;
315 dp_reinit(dep);
316
317// reply_mess.m_type = DL_CONF_REPLY;
318// reply_mess.m3_i1 = mp->DL_PORT;
319// reply_mess.m3_i2 = DE_PORT_NR;
320// *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
321
322// mess_reply(mp, &reply_mess);
323 return EOK;
324}
325
326/*===========================================================================*
327 * do_stop *
328 *===========================================================================*/
329void do_stop(dpeth_t * dep){
330 if((dep->de_mode != DEM_SINK) && (dep->de_mode == DEM_ENABLED) && (dep->de_flags &DEF_ENABLED)){
331 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
332 (dep->de_stopf)(dep);
333
334 dep->de_flags = DEF_EMPTY;
335 }
336}
337
338int queue_packet(dpeth_t * dep, packet_t *packet){
339 packet_t *tmp;
340
341 if(dep->packet_count >= MAX_PACKETS){
342 netif_pq_release(packet_get_id(packet));
343 return ELIMIT;
344 }
345
346 tmp = dep->packet_queue;
347 while(pq_next(tmp)){
348 tmp = pq_next(tmp);
349 }
350 if(pq_add(&tmp, packet, 0, 0) != EOK){
351 return EINVAL;
352 }
353 if(! dep->packet_count){
354 dep->packet_queue = packet;
355 }
356 ++ dep->packet_count;
357 return EBUSY;
358}
359
360/*===========================================================================*
361 * based on do_vwrite *
362 *===========================================================================*/
363int do_pwrite(dpeth_t * dep, packet_t *packet, int from_int)
364{
365// int port, count, size;
366 int size;
367 int sendq_head;
368/* dpeth_t *dep;
369
370 port = mp->DL_PORT;
371 count = mp->DL_COUNT;
372 if (port < 0 || port >= DE_PORT_NR)
373 panic("", "dp8390: illegal port", port);
374 dep= &de_table[port];
375 dep->de_client= mp->DL_PROC;
376*/
377 if (dep->de_mode == DEM_SINK)
378 {
379 assert(!from_int);
380// dep->de_flags |= DEF_PACK_SEND;
381 reply(dep, OK, FALSE);
382// return;
383 return EOK;
384 }
385 assert(dep->de_mode == DEM_ENABLED);
386 assert(dep->de_flags &DEF_ENABLED);
387 if(dep->packet_queue && (! from_int)){
388// if (dep->de_flags &DEF_SEND_AVAIL){
389// panic("", "dp8390: send already in progress", NO_NUM);
390 return queue_packet(dep, packet);
391 }
392
393 sendq_head= dep->de_sendq_head;
394// if (dep->de_sendq[sendq_head].sq_filled)
395// {
396// if (from_int)
397// panic("", "dp8390: should not be sending\n", NO_NUM);
398// dep->de_sendmsg= *mp;
399// dep->de_flags |= DEF_SEND_AVAIL;
400// reply(dep, OK, FALSE);
401// return;
402// return queue_packet(dep, packet);
403// }
404// assert(!(dep->de_flags &DEF_PACK_SEND));
405
406/* if (vectored)
407 {
408 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
409 (count > IOVEC_NR ? IOVEC_NR : count) *
410 sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
411 dep->de_write_iovec.iod_iovec_s = count;
412 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
413 dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
414
415 dep->de_tmp_iovec = dep->de_write_iovec;
416 size = calc_iovec_size(&dep->de_tmp_iovec);
417 }
418 else
419 {
420 dep->de_write_iovec.iod_iovec[0].iov_addr =
421 (vir_bytes) mp->DL_ADDR;
422 dep->de_write_iovec.iod_iovec[0].iov_size =
423 mp->DL_COUNT;
424 dep->de_write_iovec.iod_iovec_s = 1;
425 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
426 dep->de_write_iovec.iod_iovec_addr = 0;
427 size= mp->DL_COUNT;
428 }
429*/
430 size = packet_get_data_length(packet);
431 dep->de_write_iovec.iod_iovec[0].iov_addr = (vir_bytes) packet_get_data(packet);
432 dep->de_write_iovec.iod_iovec[0].iov_size = size;
433 dep->de_write_iovec.iod_iovec_s = 1;
434 dep->de_write_iovec.iod_iovec_addr = (uintptr_t) NULL;
435
436 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
437 {
438 panic("", "dp8390: invalid packet size", size);
439 return EINVAL;
440 }
441 (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
442 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
443 size);
444 dep->de_sendq[sendq_head].sq_filled= TRUE;
445 if (dep->de_sendq_tail == sendq_head)
446 {
447 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
448 outb_reg0(dep, DP_TBCR1, size >> 8);
449 outb_reg0(dep, DP_TBCR0, size &0xff);
450 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
451 }
452 else
453 dep->de_sendq[sendq_head].sq_size= size;
454
455 if (++sendq_head == dep->de_sendq_nr)
456 sendq_head= 0;
457 assert(sendq_head < SENDQ_NR);
458 dep->de_sendq_head= sendq_head;
459
460// dep->de_flags |= DEF_PACK_SEND;
461
462 /* If the interrupt handler called, don't send a reply. The reply
463 * will be sent after all interrupts are handled.
464 */
465 if (from_int)
466 return EOK;
467 reply(dep, OK, FALSE);
468
469 assert(dep->de_mode == DEM_ENABLED);
470 assert(dep->de_flags &DEF_ENABLED);
471 return EOK;
472}
473
474/*===========================================================================*
475 * dp_init *
476 *===========================================================================*/
477void dp_init(dep)
478dpeth_t *dep;
479{
480 int dp_rcr_reg;
481 int i;//, r;
482
483 /* General initialization */
484 dep->de_flags = DEF_EMPTY;
485 (*dep->de_initf)(dep);
486
487// dp_confaddr(dep);
488
489 if (debug)
490 {
491 printf("%s: Ethernet address ", dep->de_name);
492 for (i= 0; i < 6; i++)
493 printf("%x%c", dep->de_address.ea_addr[i],
494 i < 5 ? ':' : '\n');
495 }
496
497 /* Map buffer */
498 map_hw_buffer(dep);
499
500 /* Initialization of the dp8390 following the mandatory procedure
501 * in reference manual ("DP8390D/NS32490D NIC Network Interface
502 * Controller", National Semiconductor, July 1995, Page 29).
503 */
504 /* Step 1: */
505 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
506 /* Step 2: */
507 if (dep->de_16bit)
508 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
509 else
510 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
511 /* Step 3: */
512 outb_reg0(dep, DP_RBCR0, 0);
513 outb_reg0(dep, DP_RBCR1, 0);
514 /* Step 4: */
515 dp_rcr_reg = 0;
516 if (dep->de_flags &DEF_PROMISC)
517 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
518 if (dep->de_flags &DEF_BROAD)
519 dp_rcr_reg |= RCR_AB;
520 if (dep->de_flags &DEF_MULTI)
521 dp_rcr_reg |= RCR_AM;
522 outb_reg0(dep, DP_RCR, dp_rcr_reg);
523 /* Step 5: */
524 outb_reg0(dep, DP_TCR, TCR_INTERNAL);
525 /* Step 6: */
526 outb_reg0(dep, DP_BNRY, dep->de_startpage);
527 outb_reg0(dep, DP_PSTART, dep->de_startpage);
528 outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
529 /* Step 7: */
530 outb_reg0(dep, DP_ISR, 0xFF);
531 /* Step 8: */
532 outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
533 IMR_OVWE | IMR_CNTE);
534 /* Step 9: */
535 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
536
537 outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
538 outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
539 outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
540 outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
541 outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
542 outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
543
544 outb_reg1(dep, DP_MAR0, 0xff);
545 outb_reg1(dep, DP_MAR1, 0xff);
546 outb_reg1(dep, DP_MAR2, 0xff);
547 outb_reg1(dep, DP_MAR3, 0xff);
548 outb_reg1(dep, DP_MAR4, 0xff);
549 outb_reg1(dep, DP_MAR5, 0xff);
550 outb_reg1(dep, DP_MAR6, 0xff);
551 outb_reg1(dep, DP_MAR7, 0xff);
552
553 outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
554 /* Step 10: */
555 outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
556 /* Step 11: */
557 outb_reg0(dep, DP_TCR, TCR_NORMAL);
558
559 inb_reg0(dep, DP_CNTR0); /* reset counters by reading */
560 inb_reg0(dep, DP_CNTR1);
561 inb_reg0(dep, DP_CNTR2);
562
563 /* Finish the initialization. */
564 dep->de_flags |= DEF_ENABLED;
565 for (i= 0; i<dep->de_sendq_nr; i++)
566 dep->de_sendq[i].sq_filled= 0;
567 dep->de_sendq_head= 0;
568 dep->de_sendq_tail= 0;
569 if (!dep->de_prog_IO)
570 {
571 dep->de_user2nicf= dp_user2nic;
572// dep->de_user2nicf_s= dp_user2nic_s;
573 dep->de_nic2userf= dp_nic2user;
574// dep->de_nic2userf_s= dp_nic2user_s;
575 dep->de_getblockf= dp_getblock;
576 }
577 else if (dep->de_16bit)
578 {
579 dep->de_user2nicf= dp_pio16_user2nic;
580// dep->de_user2nicf_s= dp_pio16_user2nic_s;
581 dep->de_nic2userf= dp_pio16_nic2user;
582// dep->de_nic2userf_s= dp_pio16_nic2user_s;
583 dep->de_getblockf= dp_pio16_getblock;
584 }
585 else
586 {
587 dep->de_user2nicf= dp_pio8_user2nic;
588// dep->de_user2nicf_s= dp_pio8_user2nic_s;
589 dep->de_nic2userf= dp_pio8_nic2user;
590// dep->de_nic2userf_s= dp_pio8_nic2user_s;
591 dep->de_getblockf= dp_pio8_getblock;
592 }
593
594 /* Set the interrupt handler and policy. Do not automatically
595 * reenable interrupts. Return the IRQ line number on interrupts.
596 */
597/* dep->de_hook = dep->de_irq;
598 r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
599 if (r != OK)
600 panic("DP8390", "sys_irqsetpolicy failed", r);
601
602 r= sys_irqenable(&dep->de_hook);
603 if (r != OK)
604 {
605 panic("DP8390", "unable enable interrupts", r);
606 }
607*/
608}
609
610/*===========================================================================*
611 * dp_reinit *
612 *===========================================================================*/
613static void dp_reinit(dep)
614dpeth_t *dep;
615{
616 int dp_rcr_reg;
617
618 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
619
620 dp_rcr_reg = 0;
621 if (dep->de_flags &DEF_PROMISC)
622 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
623 if (dep->de_flags &DEF_BROAD)
624 dp_rcr_reg |= RCR_AB;
625 if (dep->de_flags &DEF_MULTI)
626 dp_rcr_reg |= RCR_AM;
627 outb_reg0(dep, DP_RCR, dp_rcr_reg);
628}
629
630/*===========================================================================*
631 * dp_reset *
632 *===========================================================================*/
633static void dp_reset(dep)
634dpeth_t *dep;
635{
636 int i;
637
638 /* Stop chip */
639 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
640 outb_reg0(dep, DP_RBCR0, 0);
641 outb_reg0(dep, DP_RBCR1, 0);
642 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++)
643 ; /* Do nothing */
644 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
645 outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
646 outb_reg0(dep, DP_TCR, TCR_NORMAL);
647
648 /* Acknowledge the ISR_RDC (remote dma) interrupt. */
649 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++)
650 ; /* Do nothing */
651 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) &~ISR_RDC);
652
653 /* Reset the transmit ring. If we were transmitting a packet, we
654 * pretend that the packet is processed. Higher layers will
655 * retransmit if the packet wasn't actually sent.
656 */
657 dep->de_sendq_head= dep->de_sendq_tail= 0;
658 for (i= 0; i<dep->de_sendq_nr; i++)
659 dep->de_sendq[i].sq_filled= 0;
660 dp_send(dep);
661 dep->de_flags &= ~DEF_STOPPED;
662}
663
664/*===========================================================================*
665 * dp_check_ints *
666 *===========================================================================*/
667void dp_check_ints(dep, isr)
668dpeth_t *dep;
669int isr;
670{
671 int /*isr,*/ tsr;
672 int size, sendq_tail;
673
674 if (!(dep->de_flags &DEF_ENABLED))
675 panic("", "dp8390: got premature interrupt", NO_NUM);
676
677 for(;;)
678 {
679// isr = inb_reg0(dep, DP_ISR);
680 if (!isr)
681 break;
682 outb_reg0(dep, DP_ISR, isr);
683 if (isr &(ISR_PTX|ISR_TXE))
684 {
685 if (isr &ISR_TXE)
686 {
687#if DEBUG
688 {printf("%s: got send Error\n", dep->de_name);}
689#endif
690 dep->de_stat.ets_sendErr++;
691 }
692 else
693 {
694 tsr = inb_reg0(dep, DP_TSR);
695
696 if (tsr &TSR_PTX) dep->de_stat.ets_packetT++;
697#if 0 /* Reserved in later manuals, should be ignored */
698 if (!(tsr &TSR_DFR))
699 {
700 /* In most (all?) implementations of
701 * the dp8390, this bit is set
702 * when the packet is not deferred
703 */
704 dep->de_stat.ets_transDef++;
705 }
706#endif
707 if (tsr &TSR_COL) dep->de_stat.ets_collision++;
708 if (tsr &TSR_ABT) dep->de_stat.ets_transAb++;
709 if (tsr &TSR_CRS) dep->de_stat.ets_carrSense++;
710 if (tsr &TSR_FU
711 && ++dep->de_stat.ets_fifoUnder <= 10)
712 {
713 printf("%s: fifo underrun\n",
714 dep->de_name);
715 }
716 if (tsr &TSR_CDH
717 && ++dep->de_stat.ets_CDheartbeat <= 10)
718 {
719 printf("%s: CD heart beat failure\n",
720 dep->de_name);
721 }
722 if (tsr &TSR_OWC) dep->de_stat.ets_OWC++;
723 }
724 sendq_tail= dep->de_sendq_tail;
725
726 if (!(dep->de_sendq[sendq_tail].sq_filled))
727 {
728 /* Software bug? */
729 assert(!debug);
730
731 /* Or hardware bug? */
732 printf(
733 "%s: transmit interrupt, but not sending\n",
734 dep->de_name);
735 continue;
736 }
737 dep->de_sendq[sendq_tail].sq_filled= 0;
738 if (++sendq_tail == dep->de_sendq_nr)
739 sendq_tail= 0;
740 dep->de_sendq_tail= sendq_tail;
741 if (dep->de_sendq[sendq_tail].sq_filled)
742 {
743 size= dep->de_sendq[sendq_tail].sq_size;
744 outb_reg0(dep, DP_TPSR,
745 dep->de_sendq[sendq_tail].sq_sendpage);
746 outb_reg0(dep, DP_TBCR1, size >> 8);
747 outb_reg0(dep, DP_TBCR0, size &0xff);
748 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
749 }
750// if (dep->de_flags &DEF_SEND_AVAIL)
751 dp_send(dep);
752 }
753
754 if (isr &ISR_PRX)
755 {
756 /* Only call dp_recv if there is a read request */
757// if (dep->de_flags) &DEF_READING)
758 dp_recv(dep);
759 }
760
761 if (isr &ISR_RXE) dep->de_stat.ets_recvErr++;
762 if (isr &ISR_CNT)
763 {
764 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
765 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
766 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
767 }
768 if (isr &ISR_OVW)
769 {
770 dep->de_stat.ets_OVW++;
771#if 0
772 {printW(); printf(
773 "%s: got overwrite warning\n", dep->de_name);}
774#endif
775/* if (dep->de_flags &DEF_READING)
776 {
777 printf(
778"dp_check_ints: strange: overwrite warning and pending read request\n");
779 dp_recv(dep);
780 }
781*/ }
782 if (isr &ISR_RDC)
783 {
784 /* Nothing to do */
785 }
786 if (isr &ISR_RST)
787 {
788 /* this means we got an interrupt but the ethernet
789 * chip is shutdown. We set the flag DEF_STOPPED,
790 * and continue processing arrived packets. When the
791 * receive buffer is empty, we reset the dp8390.
792 */
793#if 0
794 {printW(); printf(
795 "%s: NIC stopped\n", dep->de_name);}
796#endif
797 dep->de_flags |= DEF_STOPPED;
798 break;
799 }
800 isr = inb_reg0(dep, DP_ISR);
801 }
802// if ((dep->de_flags &(DEF_READING|DEF_STOPPED)) ==
803// (DEF_READING|DEF_STOPPED))
804 if ((dep->de_flags &DEF_STOPPED) == DEF_STOPPED)
805 {
806 /* The chip is stopped, and all arrived packets are
807 * delivered.
808 */
809 dp_reset(dep);
810 }
811}
812
813/*===========================================================================*
814 * dp_recv *
815 *===========================================================================*/
816static void dp_recv(dep)
817dpeth_t *dep;
818{
819 dp_rcvhdr_t header;
820 //unsigned pageno, curr, next;
821 int pageno, curr, next;
822 vir_bytes length;
823 int packet_processed, r;
824 u16_t eth_type;
825
826 packet_processed = FALSE;
827 pageno = inb_reg0(dep, DP_BNRY) + 1;
828 if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
829
830 do
831 {
832 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
833 curr = inb_reg1(dep, DP_CURR);
834 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
835
836 if (curr == pageno) break;
837
838 (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
839 &header);
840 (dep->de_getblockf)(dep, pageno, sizeof(header) +
841 2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
842
843 length = (header.dr_rbcl | (header.dr_rbch << 8)) -
844 sizeof(dp_rcvhdr_t);
845 next = header.dr_next;
846 if (length < ETH_MIN_PACK_SIZE ||
847 length > ETH_MAX_PACK_SIZE_TAGGED)
848 {
849 printf("%s: packet with strange length arrived: %d\n",
850 dep->de_name, (int) length);
851 next= curr;
852 }
853 else if (next < dep->de_startpage || next >= dep->de_stoppage)
854 {
855 printf("%s: strange next page\n", dep->de_name);
856 next= curr;
857 }
858/* else if (eth_type == eth_ign_proto)
859 {
860*/ /* Hack: ignore packets of a given protocol, useful
861 * if you share a net with 80 computers sending
862 * Amoeba FLIP broadcasts. (Protocol 0x8146.)
863 */
864/* static int first= 1;
865 if (first)
866 {
867 first= 0;
868 printf("%s: dropping proto 0x%04x packets\n",
869 dep->de_name,
870 ntohs(eth_ign_proto));
871 }
872 dep->de_stat.ets_packetR++;
873 }
874*/ else if (header.dr_status &RSR_FO)
875 {
876 /* This is very serious, so we issue a warning and
877 * reset the buffers */
878 printf("%s: fifo overrun, resetting receive buffer\n",
879 dep->de_name);
880 dep->de_stat.ets_fifoOver++;
881 next = curr;
882 }
883 else if ((header.dr_status &RSR_PRX) &&
884 (dep->de_flags &DEF_ENABLED))
885 {
886// if (dep->de_safecopy_read)
887// r = dp_pkt2user_s(dep, pageno, length);
888// else
889 r = dp_pkt2user(dep, pageno, length);
890 if (r != OK)
891 return;
892
893 packet_processed = TRUE;
894 dep->de_stat.ets_packetR++;
895 }
896 if (next == dep->de_startpage)
897 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
898 else
899 outb_reg0(dep, DP_BNRY, next - 1);
900
901 pageno = next;
902 }
903 while (!packet_processed);
904}
905
906/*===========================================================================*
907 * dp_send *
908 *===========================================================================*/
909static void dp_send(dep)
910dpeth_t *dep;
911{
912 packet_t *packet;
913
914// if (!(dep->de_flags &DEF_SEND_AVAIL))
915// return;
916
917 if(dep->packet_queue){
918 packet = dep->packet_queue;
919 dep->packet_queue = pq_detach(packet);
920 do_pwrite(dep, packet, TRUE);
921 netif_pq_release(packet_get_id(packet));
922 -- dep->packet_count;
923 }
924// if(! dep->packet_queue){
925// dep->de_flags &= ~DEF_SEND_AVAIL;
926// }
927/* switch(dep->de_sendmsg.m_type)
928 {
929 case DL_WRITE: do_vwrite(&dep->de_sendmsg, TRUE, FALSE); break;
930 case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE); break;
931 case DL_WRITEV_S: do_vwrite_s(&dep->de_sendmsg, TRUE); break;
932 default:
933 panic("", "dp8390: wrong type", dep->de_sendmsg.m_type);
934 break;
935 }
936*/
937}
938
939/*===========================================================================*
940 * dp_getblock *
941 *===========================================================================*/
942static void dp_getblock(dep, page, offset, size, dst)
943dpeth_t *dep;
944int page;
945size_t offset;
946size_t size;
947void *dst;
948{
949// int r;
950
951 offset = page * DP_PAGESIZE + offset;
952
953 memcpy(dst, dep->de_locmem + offset, size);
954}
955
956/*===========================================================================*
957 * dp_pio8_getblock *
958 *===========================================================================*/
959static void dp_pio8_getblock(dep, page, offset, size, dst)
960dpeth_t *dep;
961int page;
962size_t offset;
963size_t size;
964void *dst;
965{
966 offset = page * DP_PAGESIZE + offset;
967 outb_reg0(dep, DP_RBCR0, size &0xFF);
968 outb_reg0(dep, DP_RBCR1, size >> 8);
969 outb_reg0(dep, DP_RSAR0, offset &0xFF);
970 outb_reg0(dep, DP_RSAR1, offset >> 8);
971 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
972
973 insb(dep->de_data_port, dst, size);
974}
975
976/*===========================================================================*
977 * dp_pio16_getblock *
978 *===========================================================================*/
979static void dp_pio16_getblock(dep, page, offset, size, dst)
980dpeth_t *dep;
981int page;
982size_t offset;
983size_t size;
984void *dst;
985{
986 offset = page * DP_PAGESIZE + offset;
987 outb_reg0(dep, DP_RBCR0, size &0xFF);
988 outb_reg0(dep, DP_RBCR1, size >> 8);
989 outb_reg0(dep, DP_RSAR0, offset &0xFF);
990 outb_reg0(dep, DP_RSAR1, offset >> 8);
991 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
992
993 assert (!(size &1));
994 insw(dep->de_data_port, dst, size);
995}
996
997/*===========================================================================*
998 * dp_pkt2user *
999 *===========================================================================*/
1000static int dp_pkt2user(dep, page, length)
1001dpeth_t *dep;
1002int page, length;
1003{
1004 int last, count;
1005 packet_t *packet;
1006
1007// if (!(dep->de_flags &DEF_READING))
1008// return EGENERIC;
1009
1010 packet = netif_packet_get_1(length);
1011 if(! packet){
1012 return ENOMEM;
1013 }
1014 dep->de_read_iovec.iod_iovec[0].iov_addr = (vir_bytes) packet_suffix(packet, length);
1015 dep->de_read_iovec.iod_iovec[0].iov_size = length;
1016 dep->de_read_iovec.iod_iovec_s = 1;
1017 dep->de_read_iovec.iod_iovec_addr = (uintptr_t) NULL;
1018
1019 last = page + (length - 1) / DP_PAGESIZE;
1020 if (last >= dep->de_stoppage)
1021 {
1022 count = (dep->de_stoppage - page) * DP_PAGESIZE -
1023 sizeof(dp_rcvhdr_t);
1024
1025 /* Save read_iovec since we need it twice. */
1026 dep->de_tmp_iovec = dep->de_read_iovec;
1027 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
1028 sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
1029 (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
1030 &dep->de_read_iovec, count, length - count);
1031 }
1032 else
1033 {
1034 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
1035 sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
1036 }
1037
1038 dep->de_read_s = length;
1039 dep->de_flags |= DEF_PACK_RECV;
1040// dep->de_flags &= ~DEF_READING;
1041
1042 if(dep->received_count >= MAX_PACKETS){
1043 netif_pq_release(packet_get_id(packet));
1044 return ELIMIT;
1045 }else{
1046 if(pq_add(&dep->received_queue, packet, 0, 0) == EOK){
1047 ++ dep->received_count;
1048 }else{
1049 netif_pq_release(packet_get_id(packet));
1050 }
1051 }
1052 return OK;
1053}
1054
1055/*===========================================================================*
1056 * dp_user2nic *
1057 *===========================================================================*/
1058static void dp_user2nic(dep, iovp, offset, nic_addr, count)
1059dpeth_t *dep;
1060iovec_dat_t *iovp;
1061vir_bytes offset;
1062int nic_addr;
1063vir_bytes count;
1064{
1065 vir_bytes vir_hw;//, vir_user;
1066 //int bytes, i, r;
1067 int i, r;
1068 vir_bytes bytes;
1069
1070 vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
1071
1072 i= 0;
1073 while (count > 0)
1074 {
1075 if (i >= IOVEC_NR)
1076 {
1077 dp_next_iovec(iovp);
1078 i= 0;
1079 continue;
1080 }
1081 assert(i < iovp->iod_iovec_s);
1082 if (offset >= iovp->iod_iovec[i].iov_size)
1083 {
1084 offset -= iovp->iod_iovec[i].iov_size;
1085 i++;
1086 continue;
1087 }
1088 bytes = iovp->iod_iovec[i].iov_size - offset;
1089 if (bytes > count)
1090 bytes = count;
1091
1092 r= sys_vircopy(iovp->iod_proc_nr, D,
1093 iovp->iod_iovec[i].iov_addr + offset,
1094 SELF, D, vir_hw, bytes);
1095 if (r != OK)
1096 panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
1097
1098 count -= bytes;
1099 vir_hw += bytes;
1100 offset += bytes;
1101 }
1102 assert(count == 0);
1103}
1104
1105/*===========================================================================*
1106 * dp_pio8_user2nic *
1107 *===========================================================================*/
1108static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
1109dpeth_t *dep;
1110iovec_dat_t *iovp;
1111vir_bytes offset;
1112int nic_addr;
1113vir_bytes count;
1114{
1115// phys_bytes phys_user;
1116 int i;
1117 vir_bytes bytes;
1118
1119 outb_reg0(dep, DP_ISR, ISR_RDC);
1120
1121 outb_reg0(dep, DP_RBCR0, count &0xFF);
1122 outb_reg0(dep, DP_RBCR1, count >> 8);
1123 outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
1124 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1125 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
1126
1127 i= 0;
1128 while (count > 0)
1129 {
1130 if (i >= IOVEC_NR)
1131 {
1132 dp_next_iovec(iovp);
1133 i= 0;
1134 continue;
1135 }
1136 assert(i < iovp->iod_iovec_s);
1137 if (offset >= iovp->iod_iovec[i].iov_size)
1138 {
1139 offset -= iovp->iod_iovec[i].iov_size;
1140 i++;
1141 continue;
1142 }
1143 bytes = iovp->iod_iovec[i].iov_size - offset;
1144 if (bytes > count)
1145 bytes = count;
1146
1147 do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
1148 iovp->iod_iovec[i].iov_addr + offset, bytes);
1149 count -= bytes;
1150 offset += bytes;
1151 }
1152 assert(count == 0);
1153
1154 for (i= 0; i<100; i++)
1155 {
1156 if (inb_reg0(dep, DP_ISR) &ISR_RDC)
1157 break;
1158 }
1159 if (i == 100)
1160 {
1161 panic("", "dp8390: remote dma failed to complete", NO_NUM);
1162 }
1163}
1164
1165/*===========================================================================*
1166 * dp_pio16_user2nic *
1167 *===========================================================================*/
1168static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
1169dpeth_t *dep;
1170iovec_dat_t *iovp;
1171vir_bytes offset;
1172int nic_addr;
1173vir_bytes count;
1174{
1175 vir_bytes vir_user;
1176 vir_bytes ecount;
1177 int i, r, user_proc;
1178 vir_bytes bytes;
1179 //u8_t two_bytes[2];
1180 u16_t two_bytes;
1181 int odd_byte;
1182
1183 ecount= (count+1) &~1;
1184 odd_byte= 0;
1185
1186 outb_reg0(dep, DP_ISR, ISR_RDC);
1187 outb_reg0(dep, DP_RBCR0, ecount &0xFF);
1188 outb_reg0(dep, DP_RBCR1, ecount >> 8);
1189 outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
1190 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1191 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
1192
1193 i= 0;
1194 while (count > 0)
1195 {
1196 if (i >= IOVEC_NR)
1197 {
1198 dp_next_iovec(iovp);
1199 i= 0;
1200 continue;
1201 }
1202 assert(i < iovp->iod_iovec_s);
1203 if (offset >= iovp->iod_iovec[i].iov_size)
1204 {
1205 offset -= iovp->iod_iovec[i].iov_size;
1206 i++;
1207 continue;
1208 }
1209 bytes = iovp->iod_iovec[i].iov_size - offset;
1210 if (bytes > count)
1211 bytes = count;
1212
1213 user_proc= iovp->iod_proc_nr;
1214 vir_user= iovp->iod_iovec[i].iov_addr + offset;
1215 if (odd_byte)
1216 {
1217 r= sys_vircopy(user_proc, D, vir_user,
1218 // SELF, D, (vir_bytes)&two_bytes[1], 1);
1219 SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[1]), 1);
1220 if (r != OK)
1221 {
1222 panic("DP8390",
1223 "dp_pio16_user2nic: sys_vircopy failed",
1224 r);
1225 }
1226 //outw(dep->de_data_port, *(u16_t *)two_bytes);
1227 outw(dep->de_data_port, two_bytes);
1228 count--;
1229 offset++;
1230 bytes--;
1231 vir_user++;
1232 odd_byte= 0;
1233 if (!bytes)
1234 continue;
1235 }
1236 ecount= bytes &~1;
1237 if (ecount != 0)
1238 {
1239 do_vir_outsw(dep->de_data_port, user_proc, vir_user,
1240 ecount);
1241 count -= ecount;
1242 offset += ecount;
1243 bytes -= ecount;
1244 vir_user += ecount;
1245 }
1246 if (bytes)
1247 {
1248 assert(bytes == 1);
1249 r= sys_vircopy(user_proc, D, vir_user,
1250 // SELF, D, (vir_bytes)&two_bytes[0], 1);
1251 SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[0]), 1);
1252 if (r != OK)
1253 {
1254 panic("DP8390",
1255 "dp_pio16_user2nic: sys_vircopy failed",
1256 r);
1257 }
1258 count--;
1259 offset++;
1260 bytes--;
1261 vir_user++;
1262 odd_byte= 1;
1263 }
1264 }
1265 assert(count == 0);
1266
1267 if (odd_byte)
1268 //outw(dep->de_data_port, *(u16_t *)two_bytes);
1269 outw(dep->de_data_port, two_bytes);
1270
1271 for (i= 0; i<100; i++)
1272 {
1273 if (inb_reg0(dep, DP_ISR) &ISR_RDC)
1274 break;
1275 }
1276 if (i == 100)
1277 {
1278 panic("", "dp8390: remote dma failed to complete", NO_NUM);
1279 }
1280}
1281
1282/*===========================================================================*
1283 * dp_nic2user *
1284 *===========================================================================*/
1285static void dp_nic2user(dep, nic_addr, iovp, offset, count)
1286dpeth_t *dep;
1287int nic_addr;
1288iovec_dat_t *iovp;
1289vir_bytes offset;
1290vir_bytes count;
1291{
1292 vir_bytes vir_hw;//, vir_user;
1293 vir_bytes bytes;
1294 int i, r;
1295
1296 vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
1297
1298 i= 0;
1299 while (count > 0)
1300 {
1301 if (i >= IOVEC_NR)
1302 {
1303 dp_next_iovec(iovp);
1304 i= 0;
1305 continue;
1306 }
1307 assert(i < iovp->iod_iovec_s);
1308 if (offset >= iovp->iod_iovec[i].iov_size)
1309 {
1310 offset -= iovp->iod_iovec[i].iov_size;
1311 i++;
1312 continue;
1313 }
1314 bytes = iovp->iod_iovec[i].iov_size - offset;
1315 if (bytes > count)
1316 bytes = count;
1317
1318 r= sys_vircopy(SELF, D, vir_hw,
1319 iovp->iod_proc_nr, D,
1320 iovp->iod_iovec[i].iov_addr + offset, bytes);
1321 if (r != OK)
1322 panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
1323
1324 count -= bytes;
1325 vir_hw += bytes;
1326 offset += bytes;
1327 }
1328 assert(count == 0);
1329}
1330
1331/*===========================================================================*
1332 * dp_pio8_nic2user *
1333 *===========================================================================*/
1334static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
1335dpeth_t *dep;
1336int nic_addr;
1337iovec_dat_t *iovp;
1338vir_bytes offset;
1339vir_bytes count;
1340{
1341// phys_bytes phys_user;
1342 int i;
1343 vir_bytes bytes;
1344
1345 outb_reg0(dep, DP_RBCR0, count &0xFF);
1346 outb_reg0(dep, DP_RBCR1, count >> 8);
1347 outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
1348 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1349 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1350
1351 i= 0;
1352 while (count > 0)
1353 {
1354 if (i >= IOVEC_NR)
1355 {
1356 dp_next_iovec(iovp);
1357 i= 0;
1358 continue;
1359 }
1360 assert(i < iovp->iod_iovec_s);
1361 if (offset >= iovp->iod_iovec[i].iov_size)
1362 {
1363 offset -= iovp->iod_iovec[i].iov_size;
1364 i++;
1365 continue;
1366 }
1367 bytes = iovp->iod_iovec[i].iov_size - offset;
1368 if (bytes > count)
1369 bytes = count;
1370
1371 do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
1372 iovp->iod_iovec[i].iov_addr + offset, bytes);
1373 count -= bytes;
1374 offset += bytes;
1375 }
1376 assert(count == 0);
1377}
1378
1379/*===========================================================================*
1380 * dp_pio16_nic2user *
1381 *===========================================================================*/
1382static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
1383dpeth_t *dep;
1384int nic_addr;
1385iovec_dat_t *iovp;
1386vir_bytes offset;
1387vir_bytes count;
1388{
1389 vir_bytes vir_user;
1390 vir_bytes ecount;
1391 int i, r, user_proc;
1392 vir_bytes bytes;
1393 //u8_t two_bytes[2];
1394 u16_t two_bytes;
1395 int odd_byte;
1396
1397 ecount= (count+1) &~1;
1398 odd_byte= 0;
1399
1400 outb_reg0(dep, DP_RBCR0, ecount &0xFF);
1401 outb_reg0(dep, DP_RBCR1, ecount >> 8);
1402 outb_reg0(dep, DP_RSAR0, nic_addr &0xFF);
1403 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1404 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1405
1406 i= 0;
1407 while (count > 0)
1408 {
1409 if (i >= IOVEC_NR)
1410 {
1411 dp_next_iovec(iovp);
1412 i= 0;
1413 continue;
1414 }
1415 assert(i < iovp->iod_iovec_s);
1416 if (offset >= iovp->iod_iovec[i].iov_size)
1417 {
1418 offset -= iovp->iod_iovec[i].iov_size;
1419 i++;
1420 continue;
1421 }
1422 bytes = iovp->iod_iovec[i].iov_size - offset;
1423 if (bytes > count)
1424 bytes = count;
1425
1426 user_proc= iovp->iod_proc_nr;
1427 vir_user= iovp->iod_iovec[i].iov_addr + offset;
1428 if (odd_byte)
1429 {
1430 //r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
1431 r= sys_vircopy(SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[1]),
1432 user_proc, D, vir_user, 1);
1433 if (r != OK)
1434 {
1435 panic("DP8390",
1436 "dp_pio16_nic2user: sys_vircopy failed",
1437 r);
1438 }
1439 count--;
1440 offset++;
1441 bytes--;
1442 vir_user++;
1443 odd_byte= 0;
1444 if (!bytes)
1445 continue;
1446 }
1447 ecount= bytes &~1;
1448 if (ecount != 0)
1449 {
1450 do_vir_insw(dep->de_data_port, user_proc, vir_user,
1451 ecount);
1452 count -= ecount;
1453 offset += ecount;
1454 bytes -= ecount;
1455 vir_user += ecount;
1456 }
1457 if (bytes)
1458 {
1459 assert(bytes == 1);
1460 //*(u16_t *)two_bytes= inw(dep->de_data_port);
1461 two_bytes= inw(dep->de_data_port);
1462 //r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
1463 r= sys_vircopy(SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[0]),
1464 user_proc, D, vir_user, 1);
1465 if (r != OK)
1466 {
1467 panic("DP8390",
1468 "dp_pio16_nic2user: sys_vircopy failed",
1469 r);
1470 }
1471 count--;
1472 offset++;
1473 bytes--;
1474 vir_user++;
1475 odd_byte= 1;
1476 }
1477 }
1478 assert(count == 0);
1479}
1480
1481/*===========================================================================*
1482 * dp_next_iovec *
1483 *===========================================================================*/
1484static void dp_next_iovec(iovp)
1485iovec_dat_t *iovp;
1486{
1487 assert(iovp->iod_iovec_s > IOVEC_NR);
1488
1489 iovp->iod_iovec_s -= IOVEC_NR;
1490
1491 iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
1492
1493 get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
1494 (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
1495 sizeof(iovec_t), iovp->iod_iovec);
1496}
1497
1498/*===========================================================================*
1499 * conf_hw *
1500 *===========================================================================*/
1501static void conf_hw(dep)
1502dpeth_t *dep;
1503{
1504// static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */};
1505
1506// int ifnr;
1507// dp_conf_t *dcp;
1508
1509// dep->de_mode= DEM_DISABLED; /* Superfluous */
1510// ifnr= dep-de_table;
1511
1512// dcp= &dp_conf[ifnr];
1513// update_conf(dep, dcp);
1514// if (dep->de_mode != DEM_ENABLED)
1515// return;
1516 if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
1517 {
1518 printf("%s: No ethernet card found at 0x%x\n",
1519 dep->de_name, dep->de_base_port);
1520 dep->de_mode= DEM_DISABLED;
1521 return;
1522 }
1523
1524/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
1525
1526 dep->de_mode = DEM_ENABLED;
1527
1528 dep->de_flags = DEF_EMPTY;
1529// dep->de_stat = empty_stat;
1530}
1531
1532/*===========================================================================*
1533 * map_hw_buffer *
1534 *===========================================================================*/
1535static void map_hw_buffer(dep)
1536dpeth_t *dep;
1537{
1538// int r;
1539// size_t o, size;
1540// char *buf, *abuf;
1541
1542 if (dep->de_prog_IO)
1543 {
1544#if 0
1545 if(debug){
1546 printf(
1547 "map_hw_buffer: programmed I/O, no need to map buffer\n");
1548 }
1549#endif
1550 dep->de_locmem = (char *)-dep->de_ramsize; /* trap errors */
1551 return;
1552 }else{
1553 printf("map_hw_buffer: no buffer!\n");
1554 }
1555
1556// size = dep->de_ramsize + PAGE_SIZE; /* Add PAGE_SIZE for
1557// * alignment
1558// */
1559// buf= malloc(size);
1560// if (buf == NULL)
1561// panic(__FILE__, "map_hw_buffer: cannot malloc size", size);
1562// o= PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE);
1563// abuf= buf + o;
1564// printf("buf at 0x%x, abuf at 0x%x\n", buf, abuf);
1565
1566// r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)abuf,
1567// dep->de_ramsize, (phys_bytes)dep->de_linmem);
1568// if (r != OK)
1569// panic(__FILE__, "map_hw_buffer: sys_vm_map failed", r);
1570// dep->de_locmem = abuf;
1571}
1572
1573/*===========================================================================*
1574 * reply *
1575 *===========================================================================*/
1576static void reply(dep, err, may_block)
1577dpeth_t *dep;
1578int err;
1579int may_block;
1580{
1581/* message reply;
1582 int status;
1583 int r;
1584
1585 status = 0;
1586 if (dep->de_flags &DEF_PACK_SEND)
1587 status |= DL_PACK_SEND;
1588 if (dep->de_flags &DEF_PACK_RECV)
1589 status |= DL_PACK_RECV;
1590
1591 reply.m_type = DL_TASK_REPLY;
1592 reply.DL_PORT = dep - de_table;
1593 reply.DL_PROC = dep->de_client;
1594 reply.DL_STAT = status | ((u32_t) err << 16);
1595 reply.DL_COUNT = dep->de_read_s;
1596 reply.DL_CLCK = 0; *//* Don't know */
1597/* r= send(dep->de_client, &reply);
1598
1599 if (r == ELOCKED && may_block)
1600 {
1601#if 0
1602 printf("send locked\n");
1603#endif
1604 return;
1605 }
1606
1607 if (r < 0)
1608 panic("", "dp8390: send failed:", r);
1609
1610*/ dep->de_read_s = 0;
1611// dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
1612}
1613
1614/*===========================================================================*
1615 * get_userdata *
1616 *===========================================================================*/
1617static void get_userdata(user_proc, user_addr, count, loc_addr)
1618int user_proc;
1619vir_bytes user_addr;
1620vir_bytes count;
1621void *loc_addr;
1622{
1623 int r;
1624
1625 r= sys_vircopy(user_proc, D, user_addr,
1626 SELF, D, (vir_bytes)loc_addr, count);
1627 if (r != OK)
1628 panic("DP8390", "get_userdata: sys_vircopy failed", r);
1629}
1630
1631static void insb(port_t port, void *buf, size_t size)
1632{
1633 size_t i;
1634
1635 for(i = 0; i < size; ++ i){
1636 *((uint8_t *) buf + i) = inb(port);
1637 }
1638}
1639
1640static void insw(port_t port, void *buf, size_t size)
1641{
1642 size_t i;
1643
1644 for(i = 0; i * 2 < size; ++ i){
1645 *((uint16_t *) buf + i) = inw(port);
1646 }
1647}
1648
1649static void outsb(port_t port, void *buf, size_t size)
1650{
1651 size_t i;
1652
1653 for(i = 0; i < size; ++ i){
1654 outb(port, *((uint8_t *) buf + i));
1655 }
1656}
1657
1658static void outsw(port_t port, void *buf, size_t size)
1659{
1660 size_t i;
1661
1662 for(i = 0; i * 2 < size; ++ i){
1663 outw(port, *((uint16_t *) buf + i));
1664 }
1665}
1666
1667/*
1668 * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
1669 */
1670
1671/** @}
1672 */
Note: See TracBrowser for help on using the repository browser.