📄 lance.c
字号:
message mess; int i; for (i= 0; i<EC_PORT_NR_MAX; i++) { if (ec_table[i].mode != EC_ENABLED) continue; mess.m_type= DL_STOP; mess.DL_PORT= i; do_stop(&mess); } /*printf("LANCE driver stopped.\n");*/ sys_exit( 0 );}/*===========================================================================* * do_init * *===========================================================================*/static void do_init(mp)message *mp;{ int port; ether_card_t *ec; message reply_mess;pci_init(); port = mp->DL_PORT; if (port < 0 || port >= EC_PORT_NR_MAX) { reply_mess.m_type= DL_INIT_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; } ec= &ec_table[port]; strcpy(ec->port_name, "eth_card#0"); ec->port_name[9] += port; if (ec->mode == EC_DISABLED) { /* This is the default, try to (re)locate the device. */ /* only try to enable if memory is correct for DMA */ if ( CORRECT_DMA_MEM() ) { conf_hw(ec); } else { report( "LANCE", "DMA denied because address out of range", NO_NUM ); } if (ec->mode == EC_DISABLED) { /* Probe failed, or the device is configured off. */ reply_mess.m_type= DL_INIT_REPLY; reply_mess.m3_i1= ENXIO; mess_reply(mp, &reply_mess); return; } if (ec->mode == EC_ENABLED) ec_init(ec); } if (ec->mode == EC_SINK) { ec->mac_address.ea_addr[0] = ec->mac_address.ea_addr[1] = ec->mac_address.ea_addr[2] = ec->mac_address.ea_addr[3] = ec->mac_address.ea_addr[4] = ec->mac_address.ea_addr[5] = 0; ec_confaddr(ec); reply_mess.m_type = DL_INIT_REPLY; reply_mess.m3_i1 = mp->DL_PORT; reply_mess.m3_i2 = EC_PORT_NR_MAX; *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address; mess_reply(mp, &reply_mess); return; } assert(ec->mode == EC_ENABLED); assert(ec->flags & ECF_ENABLED); ec->flags &= ~(ECF_PROMISC | ECF_MULTI | ECF_BROAD); if (mp->DL_MODE & DL_PROMISC_REQ) ec->flags |= ECF_PROMISC | ECF_MULTI | ECF_BROAD; if (mp->DL_MODE & DL_MULTI_REQ) ec->flags |= ECF_MULTI; if (mp->DL_MODE & DL_BROAD_REQ) ec->flags |= ECF_BROAD; ec->client = mp->m_source; ec_reinit(ec); reply_mess.m_type = DL_INIT_REPLY; reply_mess.m3_i1 = mp->DL_PORT; reply_mess.m3_i2 = EC_PORT_NR_MAX; *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address; mess_reply(mp, &reply_mess);}/*===========================================================================* * do_int * *===========================================================================*/static void do_int(ec)ether_card_t *ec;{ if (ec->flags & (ECF_PACK_SEND | ECF_PACK_RECV)) reply(ec, OK, TRUE);}#if 0/*===========================================================================* * ec_handler * *===========================================================================*/static int ec_handler(hook)irq_hook_t *hook;{ /* LANCE interrupt, send message and reenable interrupts. */#if 0 printf(">> ec_handler(): \n");#endif structof(ether_card_t, ec_hook, hook)->ec_int_pending= 1; notify(eth_tasknr); return 0;}#endif/*===========================================================================* * conf_hw * *===========================================================================*/static void conf_hw(ec)ether_card_t *ec;{ static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ }; int ifnr; ec_conf_t *ecp; ec->mode= EC_DISABLED; /* Superfluous */ ifnr= ec-ec_table; ecp= &ec_conf[ifnr]; update_conf(ec, ecp); if (ec->mode != EC_ENABLED) return; if (!lance_probe(ec)) { printf("%s: No ethernet card found on PCI-BIOS info.\n", ec->port_name); ec->mode= EC_DISABLED; return; } /* Allocate a memory segment, programmed I/O should set the * memory segment (linmem) to zero. */ if (ec->ec_linmem != 0) { assert( 0 ); /*phys2seg(&ec->ec_memseg, &ec->ec_memoff, ec->ec_linmem);*/ }/* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000; ec->flags = ECF_EMPTY; ec->eth_stat = empty_stat;}/*===========================================================================* * update_conf * *===========================================================================*/static void update_conf(ec, ecp)ether_card_t *ec;ec_conf_t *ecp;{ long v; static char ec_fmt[] = "x:d:x:x"; /* Get the default settings and modify them from the environment. */ ec->mode= EC_SINK; v= ecp->ec_port; switch (env_parse(ecp->ec_envvar, ec_fmt, 0, &v, 0x0000L, 0xFFFFL)) { case EP_OFF: ec->mode= EC_DISABLED; break; case EP_ON: case EP_SET: ec->mode= EC_ENABLED; /* Might become disabled if * all probes fail */ break; } ec->ec_port= v; v= ecp->ec_irq | DEI_DEFAULT; (void) env_parse(ecp->ec_envvar, ec_fmt, 1, &v, 0L, (long) NR_IRQ_VECTORS - 1); ec->ec_irq= v; v= ecp->ec_mem; (void) env_parse(ecp->ec_envvar, ec_fmt, 2, &v, 0L, 0xFFFFFL); ec->ec_linmem= v; v= 0; (void) env_parse(ecp->ec_envvar, ec_fmt, 3, &v, 0x2000L, 0x8000L); ec->ec_ramsize= v;}/*===========================================================================* * ec_init * *===========================================================================*/static void ec_init(ec)ether_card_t *ec;{ int i, r; /* General initialization */ ec->flags = ECF_EMPTY; /*disable_irq(ec->ec_irq);*/ lance_init_card(ec); /* Get mac_address, etc ...*/ ec_confaddr(ec);#if VERBOSE printf("%s: Ethernet address ", ec->port_name); for (i= 0; i < 6; i++) printf("%x%c", ec->mac_address.ea_addr[i], i < 5 ? ':' : '\n');#endif /* Finish the initialization */ ec->flags |= ECF_ENABLED; /* Set the interrupt handler */ /*put_irq_handler(&ec->ec_hook, ec->ec_irq, ec_handler);*/ ec->ec_hook = ec->ec_irq; if ((r=sys_irqsetpolicy(ec->ec_irq, 0, &ec->ec_hook)) != OK) printf("lance: error, couldn't set IRQ policy: %d\n", r);/* enable_irq(ec->ec_irq); *//* enter_kdebug(">> ec_init():"); */ return;}/*===========================================================================* * reply * *===========================================================================*/static void reply(ec, err, may_block)ether_card_t *ec;int err;int may_block;{ message reply; int status,r; clock_t now; status = 0; if (ec->flags & ECF_PACK_SEND) status |= DL_PACK_SEND; if (ec->flags & ECF_PACK_RECV) status |= DL_PACK_RECV; reply.m_type = DL_TASK_REPLY; reply.DL_PORT = ec - ec_table; reply.DL_PROC = ec->client; reply.DL_STAT = status | ((u32_t) err << 16); reply.DL_COUNT = ec->read_s;#if 1 if ((r=getuptime(&now)) != OK) panic("lance", "getuptime() failed:", r); reply.DL_CLCK = now; #else reply.DL_CLCK = 0;#endif r = send(ec->client, &reply);#if 1 if (r == ELOCKED && may_block) {/* enter_kdebug(">> lance_task: ELOCKED!"); */ return; }#endif if (r < 0) panic( "lance", "send failed:", r); ec->read_s = 0; ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV);}/*===========================================================================* * mess_reply * *===========================================================================*/static void mess_reply(req, reply_mess)message *req;message *reply_mess;{ if (send(req->m_source, reply_mess) != OK) panic( "lance", "unable to mess_reply", NO_NUM);}/*===========================================================================* * ec_confaddr * *===========================================================================*/static void ec_confaddr(ec)ether_card_t *ec;{ int i; char eakey[16]; static char eafmt[]= "x:x:x:x:x:x"; long v; /* User defined ethernet address? */ strcpy(eakey, ec_conf[ec-ec_table].ec_envvar); strcat(eakey, "_EA"); for (i= 0; i < 6; i++) { v= ec->mac_address.ea_addr[i]; if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET) break; ec->mac_address.ea_addr[i]= v; } if (i != 0 && i != 6) { /* It's all or nothing; force a panic. */ (void) env_parse(eakey, "?", 0, &v, 0L, 0L); }}/*===========================================================================* * ec_reinit * *===========================================================================*/static void ec_reinit(ec)ether_card_t *ec;{ int i; unsigned short ioaddr = ec->ec_port; out_word(ioaddr+LANCE_ADDR, 0x0); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ /* purge Tx-ring */ tx_slot_nr = cur_tx_slot_nr = 0; for (i=0; i<TX_RING_SIZE; i++) { lp->tx_ring[i].u.base = 0; isstored[i]=0; } /* re-init Rx-ring */ rx_slot_nr = 0; for (i=0; i<RX_RING_SIZE; i++) { lp->rx_ring[i].buf_length = -ETH_FRAME_LEN; lp->rx_ring[i].u.addr[3] |= 0x80; } /* Set 'Receive Mode' */ if (ec->flags & ECF_PROMISC) { out_word(ioaddr+LANCE_ADDR, 0xf); out_word(ioaddr+LANCE_DATA, 0x8000); } else { if (ec->flags & (ECF_BROAD | ECF_MULTI)) { out_word(ioaddr+LANCE_ADDR, 0xf); out_word(ioaddr+LANCE_DATA, 0x0000); } else { out_word(ioaddr+LANCE_ADDR, 0xf); out_word(ioaddr+LANCE_DATA, 0x4000); } } out_word(ioaddr+LANCE_ADDR, 0x0); (void)in_word(ioaddr+LANCE_ADDR); out_word(ioaddr+LANCE_DATA, 0x142); /* start && enable interrupt */ return;}/*===========================================================================* * ec_check_ints * *===========================================================================*/static void ec_check_ints(ec)ether_card_t *ec;{ int must_restart=0; int check,status; int isr=0x0000; unsigned short ioaddr = ec->ec_port; if (!(ec->flags & ECF_ENABLED)) panic( "lance", "got premature interrupt", NO_NUM); for (;;) {#if 0 printf("ETH: Reading ISR...");#endif out_word(ioaddr+LANCE_ADDR, 0x00); isr=in_word(ioaddr+LANCE_DATA); if (isr & 0x8600) out_word( ioaddr+LANCE_DATA, isr & ~0x004f); out_word(ioaddr+LANCE_DATA, 0x7940);#if 0 printf("ISR=0x%x...",in_word(ioaddr+LANCE_DATA));#endif#define ISR_WINT 0x0200#define ISR_RINT 0x0400#define ISR_RERR 0x1000#define ISR_WERR 0x4000#define ISR_ERR 0x8000#define ISR_RST 0x0000 if ((isr & (ISR_WINT|ISR_RINT|ISR_RERR|ISR_WERR|ISR_ERR)) == 0x0000) {#if 0 printf("OK\n");#endif break; } if (isr & ISR_RERR) {#if 0 printf("RERR\n");#endif ec->eth_stat.ets_recvErr++; } if ((isr & ISR_WERR) || (isr & ISR_WINT)) { if (isr & ISR_WERR) {#if 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -