From: Arun Thomas Date: Wed, 22 Jul 2009 12:36:19 +0000 (+0000) Subject: Lance cleanup X-Git-Tag: v3.1.5~208 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=b8eedfee6b2919b89a8c44f6b8777ad7c650506c;p=minix.git Lance cleanup --- diff --git a/drivers/lance/lance.c b/drivers/lance/lance.c index 70ae86837..4919f725b 100644 --- a/drivers/lance/lance.c +++ b/drivers/lance/lance.c @@ -6,29 +6,19 @@ * * The valid messages and their parameters are: * - * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT + * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT * |------------+----------+---------+----------+---------+---------+---------| - * | HARDINT | | | | | | | + * | HARDINT | | | | | | | * |------------|----------|---------|----------|---------|---------|---------| - * | DL_WRITE | port nr | proc nr | count | mode | address | | + * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant | * |------------|----------|---------|----------|---------|---------|---------| - * | DL_WRITEV | port nr | proc nr | count | mode | address | | + * | DL_READV_S | port nr | proc nr | count | | | grant | * |------------|----------|---------|----------|---------|---------|---------| - * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant | + * | DL_CONF | port nr | proc nr | | mode | address | | * |------------|----------|---------|----------|---------|---------|---------| - * | DL_READ | port nr | proc nr | count | | address | | + * |DL_GETSTAT_S| port nr | proc nr | | | | grant | * |------------|----------|---------|----------|---------|---------|---------| - * | DL_READV | port nr | proc nr | count | | address | | - * |------------|----------|---------|----------|---------|---------|---------| - * | DL_READV_S | port nr | proc nr | count | | | grant | - * |------------|----------|---------|----------|---------|---------|---------| - * | DL_CONF | port nr | proc nr | | mode | address | | - * |------------|----------|---------|----------|---------|---------|---------| - * | DL_GETSTAT | port nr | proc nr | | | address | | - * |------------|----------|---------|----------|---------|---------|---------| - * |DL_GETSTAT_S| port nr | proc nr | | | | grant | - * |------------|----------|---------|----------|---------|---------|---------| - * | DL_STOP | port_nr | | | | | | + * | DL_STOP | port_nr | | | | | | * |------------|----------|---------|----------|---------|---------|---------| * * The messages sent are: @@ -47,7 +37,8 @@ * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami */ -#define VERBOSE 0 +#define VERBOSE 0 /* Verbose debugging output */ +#define LANCE_FKEY 0 /* Use function key to dump Lance stats */ #include "../drivers.h" @@ -59,38 +50,12 @@ #include #include +#include #include "lance.h" -/*#include "proc.h"*/ #include -/* new I/O functions in Minix 3 */ -#define out_byte( x, y ) sys_outb( x, y ) -#define out_word( x, y ) sys_outw( x, y ) - -static U8_t in_byte(U16_t port) -{ - unsigned long value; - int s; - if ((s=sys_inb(port, &value)) != OK) - printf( "lance: warning, sys_inb failed: %d\n", s ); - return (U8_t) value; -} - -static U16_t in_word( U16_t port) -{ - unsigned long value; - int s; - if ((s=sys_inw(port, &value)) != OK) - printf( "lance: warning, sys_inw failed: %d\n", s ); - return (U16_t) value; -} -/* -#define in_byte( x ) inb( x ) -#define in_word( x ) inw( x ) -*/ - static ether_card_t ec_table[EC_PORT_NR_MAX]; static int eth_tasknr= ANY; static u16_t eth_ign_proto; @@ -98,41 +63,32 @@ static u16_t eth_ign_proto; /* Configuration */ typedef struct ec_conf { - port_t ec_port; - int ec_irq; - phys_bytes ec_mem; - char *ec_envvar; + port_t ec_port; + int ec_irq; + phys_bytes ec_mem; + char *ec_envvar; } ec_conf_t; /* We hardly use these. Just "LANCE0=on/off" "LANCE1=on/off" mean. */ ec_conf_t ec_conf[]= /* Card addresses */ { - /* I/O port, IRQ, Buffer address, Env. var, Buf selector. */ - { 0x1000, 9, 0x00000, "LANCE0" }, - { 0xD000, 15, 0x00000, "LANCE1" }, + /* I/O port, IRQ, Buffer address, Env. var, Buf selector. */ + { 0x1000, 9, 0x00000, "LANCE0" }, + { 0xD000, 15, 0x00000, "LANCE1" }, }; /* Actually, we use PCI-BIOS info. */ PRIVATE struct pcitab { - u16_t vid; - u16_t did; - int checkclass; + u16_t vid; + u16_t did; + int checkclass; } pcitab[]= { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0 }, /* AMD LANCE */ + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0 }, /* AMD LANCE */ - { 0x0000, 0x0000, 0 } -}; -/* -struct pci_device pci_dev_list[] = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, - "AMD Lance/PCI", 0, 0, 0, 0, 0, 0}, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, - "AMD Lance/PCI", 0, 0, 0, 0, 0, 0}, - {0, 0, NULL, 0, 0, 0, 0, 0, 0} + { 0x0000, 0x0000, 0 } }; -*/ /* General */ _PROTOTYPE( static void do_init, (message *mp) ); @@ -141,68 +97,67 @@ _PROTOTYPE( static void ec_confaddr, (ether_card_t *ec) ); _PROTOTYPE( static void ec_reinit, (ether_card_t *ec) ); _PROTOTYPE( static void ec_check_ints, (ether_card_t *ec) ); _PROTOTYPE( static void conf_hw, (ether_card_t *ec) ); -/*_PROTOTYPE( static int ec_handler, (irq_hook_t *hook) );*/ _PROTOTYPE( static void update_conf, (ether_card_t *ec, ec_conf_t *ecp) ); _PROTOTYPE( static void mess_reply, (message *req, message *reply) ); _PROTOTYPE( static void do_int, (ether_card_t *ec) ); _PROTOTYPE( static void reply, - (ether_card_t *ec, int err, int may_block) ); + (ether_card_t *ec, int err, int may_block) ); _PROTOTYPE( static void ec_reset, (ether_card_t *ec) ); _PROTOTYPE( static void ec_send, (ether_card_t *ec) ); _PROTOTYPE( static void ec_recv, (ether_card_t *ec) ); _PROTOTYPE( static void do_vwrite_s, - (message *mp, int from_int) ); -_PROTOTYPE( static void do_vread_s, (message *mp) ); -_PROTOTYPE( static void get_userdata_s, - (int user_proc, cp_grant_id_t grant, vir_bytes offset, - vir_bytes count, void *loc_addr) ); -_PROTOTYPE( static void ec_user2nic, - (ether_card_t *dep, iovec_dat_t *iovp, - vir_bytes offset, int nic_addr, - vir_bytes count) ); + (message *mp, int from_int) ); +_PROTOTYPE( static void do_vread_s, (message *mp) ); +_PROTOTYPE( static void ec_user2nic, + (ether_card_t *dep, iovec_dat_t *iovp, + vir_bytes offset, int nic_addr, + vir_bytes count) ); _PROTOTYPE( static void ec_nic2user, - (ether_card_t *ec, int nic_addr, - iovec_dat_t *iovp, vir_bytes offset, - vir_bytes count) ); + (ether_card_t *ec, int nic_addr, + iovec_dat_t *iovp, vir_bytes offset, + vir_bytes count) ); _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) ); _PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp) ); _PROTOTYPE( static void do_getstat_s, (message *mp) ); -_PROTOTYPE( static void put_userdata_s, - (int user_proc, cp_grant_id_t grant, - void *loc_addr, vir_bytes count) ); _PROTOTYPE( static void do_stop, (message *mp) ); _PROTOTYPE( static void do_getname, (message *mp) ); -_PROTOTYPE( static void lance_dump, (void) ); -_PROTOTYPE( static void lance_stop, (void) ); -_PROTOTYPE( static void getAddressing, (int devind, ether_card_t *ec) ); +_PROTOTYPE( static void lance_dump, (void) ); +_PROTOTYPE( static void lance_stop, (void) ); +_PROTOTYPE( static void getAddressing, (int devind, ether_card_t *ec) ); /* probe+init LANCE cards */ _PROTOTYPE( static int lance_probe, (ether_card_t *ec) ); _PROTOTYPE( static void lance_init_card, (ether_card_t *ec) ); +/* Accesses Lance Control and Status Registers */ +_PROTOTYPE( static u8_t in_byte, (port_t port) ); +_PROTOTYPE( static u16_t in_word, (port_t port) ); +_PROTOTYPE( static void out_byte, (port_t port, u8_t value) ); +_PROTOTYPE( static void out_word, (port_t port, u16_t value) ); +_PROTOTYPE( static u16_t read_csr, (port_t ioaddr, u16_t csrno) ); +_PROTOTYPE( static void write_csr, (port_t ioaddr, u16_t csrno, u16_t value)); + /* --- LANCE --- */ /* General */ #define Address unsigned long - -/* Minix 3 */ #define virt_to_bus(x) (vir2phys((unsigned long)x)) unsigned long vir2phys( unsigned long x ) { - int r; - unsigned long value; - - if ( (r=sys_umap( SELF, VM_D, x, 4, &value )) != OK ) { - printf("lance: umap of 0x%lx failed\n",x ); - panic( "lance", "sys_umap failed", r ); - } - - return value; + int r; + unsigned long value; + + if ( (r=sys_umap( SELF, VM_D, x, 4, &value )) != OK ) { + printf("lance: umap of 0x%lx failed\n",x ); + panic( "lance", "sys_umap failed", r ); + } + + return value; } /* DMA limitations */ -#define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */ +#define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */ #define CORRECT_DMA_MEM() ( (virt_to_bus(lance_buf + sizeof(struct lance_interface)) & ~DMA_ADDR_MASK) == 0 ) @@ -215,28 +170,28 @@ unsigned long vir2phys( unsigned long x ) static const struct lance_chip_type { - int id_number; - const char *name; - int flags; + int id_number; + const char *name; + int flags; } chip_table[] = { - {0x0000, "LANCE 7990", /* Ancient lance chip. */ - LANCE_MUST_PAD + LANCE_MUST_UNRESET}, - {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */ - LANCE_ENABLE_AUTOSELECT}, - {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */ - LANCE_ENABLE_AUTOSELECT}, - {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */ - LANCE_ENABLE_AUTOSELECT}, - {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */ - LANCE_ENABLE_AUTOSELECT}, - {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */ - LANCE_ENABLE_AUTOSELECT}, - {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */ - LANCE_ENABLE_AUTOSELECT}, - {0x2626, "PCnet/HomePNA 79C978", - LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE}, - {0x0, "PCnet (unknown)", - LANCE_ENABLE_AUTOSELECT}, + {0x0000, "LANCE 7990", /* Ancient lance chip. */ + LANCE_MUST_PAD + LANCE_MUST_UNRESET}, + {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */ + LANCE_ENABLE_AUTOSELECT}, + {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */ + LANCE_ENABLE_AUTOSELECT}, + {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */ + LANCE_ENABLE_AUTOSELECT}, + {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */ + LANCE_ENABLE_AUTOSELECT}, + {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */ + LANCE_ENABLE_AUTOSELECT}, + {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */ + LANCE_ENABLE_AUTOSELECT}, + {0x2626, "PCnet/HomePNA 79C978", + LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE}, + {0x0, "PCnet (unknown)", + LANCE_ENABLE_AUTOSELECT}, }; /* ############## for LANCE device ############## */ @@ -261,40 +216,40 @@ static const struct lance_chip_type /* for lance_interface */ struct lance_init_block { - unsigned short mode; - unsigned char phys_addr[6]; - unsigned long filter[2]; - Address rx_ring; - Address tx_ring; + unsigned short mode; + unsigned char phys_addr[6]; + unsigned long filter[2]; + Address rx_ring; + Address tx_ring; }; struct lance_rx_head { - union { - Address base; - unsigned char addr[4]; - } u; - short buf_length; /* 2s complement */ - short msg_length; + union { + Address base; + unsigned char addr[4]; + } u; + short buf_length; /* 2s complement */ + short msg_length; }; struct lance_tx_head { - union { - Address base; - unsigned char addr[4]; - } u; - short buf_length; /* 2s complement */ - short misc; + union { + Address base; + unsigned char addr[4]; + } u; + short buf_length; /* 2s complement */ + short misc; }; struct lance_interface { - struct lance_init_block init_block; - struct lance_rx_head rx_ring[RX_RING_SIZE]; - struct lance_tx_head tx_ring[TX_RING_SIZE]; - unsigned char rbuf[RX_RING_SIZE][ETH_FRAME_LEN]; - unsigned char tbuf[TX_RING_SIZE][ETH_FRAME_LEN]; + struct lance_init_block init_block; + struct lance_rx_head rx_ring[RX_RING_SIZE]; + struct lance_tx_head tx_ring[TX_RING_SIZE]; + unsigned char rbuf[RX_RING_SIZE][ETH_FRAME_LEN]; + unsigned char tbuf[TX_RING_SIZE][ETH_FRAME_LEN]; }; /* =============== global variables =============== */ @@ -310,123 +265,133 @@ static char *progname; phys_bytes lance_buf_phys; /*===========================================================================* - * lance_task * + * main * *===========================================================================*/ void main( int argc, char **argv ) { - message m; - int i,irq,r, tasknr; - ether_card_t *ec; - long v; - int fkeys, sfkeys; - (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); - - env_setargs( argc, argv ); - - fkeys = sfkeys = 0; bit_set( sfkeys, 7 ); - -#if 0 - if ( (r = fkey_map(&fkeys, &sfkeys)) != OK ) - printf( "Error registering key\n" ); + message m; + int i,irq,r; + u32_t tasknr; + ether_card_t *ec; + long v; +#if LANCE_FKEY + int fkeys, sfkeys; #endif - - if((eth_tasknr=getprocnr()) < 0) - panic("lance","couldn't get own proc nr", i); - v= 0; - (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL); - eth_ign_proto= htons((u16_t) v); + (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); - /* Try to notify inet that we are present (again) */ - r = _pm_findproc("inet", &tasknr); - if (r == OK) - notify(tasknr); + env_setargs( argc, argv ); - while (TRUE) - { +#if LANCE_FKEY + fkeys = sfkeys = 0; + bit_set( sfkeys, 7 ); + if ( (r = fkey_map(&fkeys, &sfkeys)) != OK ) + printf("Warning: lance couldn't observe Shift+F7 key: %d\n",r); +#endif + + v= 0; + (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL); + eth_ign_proto= htons((u16_t) v); + + /* Try to notify inet that we are present (again) */ + r= ds_retrieve_u32("inet", &tasknr); + if (r == OK) + notify(tasknr); + else if (r != ESRCH) + printf("lance: ds_retrieve_u32 failed for 'inet': %d\n", r); + + while (TRUE) + { for (i=0;iec_irq != 0) - sys_irqenable(&ec->ec_hook); - } - + { + ec= &ec_table[i]; + if (ec->ec_irq != 0) + sys_irqenable(&ec->ec_hook); + } + if ((r= receive(ANY, &m)) != OK) - panic( "lance", "receive failed", r); - + panic( "lance", "receive failed", r); + for (i=0;iec_irq != 0) - sys_irqdisable(&ec->ec_hook); - } - -/*printf( "." );*/ - - switch (m.m_type){ - case DEV_PING: notify(m.m_source); continue; - case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break; - case DL_READV_S: do_vread_s(&m); break; - case DL_CONF: do_init(&m); break; - case DL_GETSTAT_S: do_getstat_s(&m); break; - case DL_STOP: do_stop(&m); break; - case DL_GETNAME: do_getname(&m); break; - case FKEY_PRESSED: lance_dump(); break; - /*case HARD_STOP: lance_stop(); break;*/ + { + ec= &ec_table[i]; + if (ec->ec_irq != 0) + sys_irqdisable(&ec->ec_hook); + } + switch (m.m_type) + { + case DEV_PING: + notify(m.m_source); + continue; + case DL_WRITEV_S: + do_vwrite_s(&m, FALSE); + break; + case DL_READV_S: + do_vread_s(&m); + break; + case DL_CONF: + do_init(&m); + break; + case DL_GETSTAT_S: + do_getstat_s(&m); + break; + case DL_STOP: + do_stop(&m); + break; + case DL_GETNAME: + do_getname(&m); + break; + case FKEY_PRESSED: + lance_dump(); + break; case SYS_SIG: { - sigset_t set = m.NOTIFY_ARG; - if ( sigismember( &set, SIGKSTOP ) ) - lance_stop(); + sigset_t set = m.NOTIFY_ARG; + if ( sigismember( &set, SIGKSTOP ) ) + lance_stop(); } - break; + break; case HARD_INT: - for (i=0;imode != EC_ENABLED) - continue; - - /* - printf( "#.\n" ); - */ - - irq=ec->ec_irq; - /*if (ec->ec_int_pending)*/ - { - ec->ec_int_pending = 0; - ec_check_ints(ec); - do_int(ec); - } - } - break; + continue; + { + ec->ec_int_pending = 0; + ec_check_ints(ec); + do_int(ec); + } + } + break; case PROC_EVENT: - break; + /* ignore event */ + break; default: - panic( "lance", "illegal message", m.m_type); + panic( "lance", "illegal message", m.m_type); } - } + } } /*===========================================================================* - * lance_dump * + * lance_dump * *===========================================================================*/ static void lance_dump() { - ether_card_t *ec; - int i, isr; - unsigned short ioaddr; + ether_card_t *ec; + int i, isr, csr; + unsigned short ioaddr; - printf("\n"); - for (i= 0, ec = &ec_table[0]; imode == EC_DISABLED) - printf("lance port %d is disabled\n", i); + printf("lance port %d is disabled\n", i); else if (ec->mode == EC_SINK) - printf("lance port %d is in sink mode\n", i); + printf("lance port %d is in sink mode\n", i); if (ec->mode != EC_ENABLED) - continue; + continue; printf("lance statistics of port %d:\n", i); @@ -453,35 +418,48 @@ static void lance_dump() printf("OWC :%8ld\t", ec->eth_stat.ets_OWC); ioaddr = ec->ec_port; - out_word(ioaddr+LANCE_ADDR, 0x00); - isr=in_word(ioaddr+LANCE_DATA); - printf("isr = 0x%x + 0x%x, flags = 0x%x\n", isr, - in_word(ioaddr+LANCE_DATA), ec->flags); + isr = read_csr(ioaddr, LANCE_CSR0); + printf("isr = 0x%x, flags = 0x%x\n", isr, + ec->flags); + + printf("irq = %d\tioadr = 0x%x\n", ec->ec_irq, ec->ec_port); + + csr = read_csr(ioaddr, LANCE_CSR0); + printf("CSR0: 0x%x\n", csr); + csr = read_csr(ioaddr, LANCE_CSR3); + printf("CSR3: 0x%x\n", csr); + csr = read_csr(ioaddr, LANCE_CSR4); + printf("CSR4: 0x%x\n", csr); + csr = read_csr(ioaddr, LANCE_CSR5); + printf("CSR5: 0x%x\n", csr); + csr = read_csr(ioaddr, LANCE_CSR15); + printf("CSR15: 0x%x\n", csr); - printf("irq = %d\tioadr = %d\n", ec->ec_irq, ec->ec_port); - } + } } /*===========================================================================* - * lance_stop * + * lance_stop * *===========================================================================*/ static void lance_stop() { - message mess; - int i; + message mess; + int i; - for (i= 0; iDL_PORT; - if (port < 0 || port >= EC_PORT_NR_MAX) - { + port = mp->DL_PORT; + if (port < 0 || port >= EC_PORT_NR_MAX) + { reply_mess.m_type= DL_CONF_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) - { + } + + 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 ( 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_CONF_REPLY; - reply_mess.m3_i1= ENXIO; - mess_reply(mp, &reply_mess); - return; - } + { + /* Probe failed, or the device is configured off. */ + reply_mess.m_type= DL_CONF_REPLY; + reply_mess.m3_i1= ENXIO; + mess_reply(mp, &reply_mess); + return; + } if (ec->mode == EC_ENABLED) - ec_init(ec); - } + ec_init(ec); + } - if (ec->mode == EC_SINK) - { + 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->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_CONF_REPLY; reply_mess.m3_i1 = mp->DL_PORT; @@ -553,32 +533,32 @@ pci_init(); *(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; - if (first_time) - { - first_time = 0; - ec_reinit(ec); - } - - reply_mess.m_type = DL_CONF_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); + } + 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; + if (first_time) + { + first_time = 0; + ec_reinit(ec); + } + + reply_mess.m_type = DL_CONF_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); } @@ -588,29 +568,10 @@ pci_init(); static void do_int(ec) ether_card_t *ec; { - if (ec->flags & (ECF_PACK_SEND | ECF_PACK_RECV)) - reply(ec, OK, TRUE); + 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 * @@ -618,31 +579,31 @@ irq_hook_t *hook; static void conf_hw(ec) ether_card_t *ec; { - static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ }; + static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ }; - int ifnr; - ec_conf_t *ecp; + int ifnr; + ec_conf_t *ecp; - ec->mode= EC_DISABLED; /* Superfluous */ - ifnr= ec-ec_table; + ec->mode= EC_DISABLED; /* Superfluous */ + ifnr= ec-ec_table; - ecp= &ec_conf[ifnr]; - update_conf(ec, ecp); - if (ec->mode != EC_ENABLED) - return; + ecp= &ec_conf[ifnr]; + update_conf(ec, ecp); + if (ec->mode != EC_ENABLED) + return; - if (!lance_probe(ec)) - { + if (!lance_probe(ec)) + { printf("%s: No ethernet card found on PCI-BIOS info.\n", - ec->port_name); + ec->port_name); ec->mode= EC_DISABLED; return; - } + } -/* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000; + /* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000; - ec->flags = ECF_EMPTY; - ec->eth_stat = empty_stat; + ec->flags = ECF_EMPTY; + ec->eth_stat = empty_stat; } @@ -653,38 +614,39 @@ 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: - default: - ec->mode= EC_ENABLED; /* Might become disabled if - * all probes fail */ - break; - } + 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: + default: + ec->mode= EC_ENABLED; /* Might become disabled if + * all probes fail */ + break; + } - ec->ec_port= v; + 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_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= 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; + v= 0; + (void) env_parse(ecp->ec_envvar, ec_fmt, 3, &v, 0x2000L, 0x8000L); + ec->ec_ramsize= v; } @@ -694,36 +656,30 @@ ec_conf_t *ecp; static void ec_init(ec) ether_card_t *ec; { - int i, r; + int i, r; - /* General initialization */ - ec->flags = ECF_EMPTY; - /*disable_irq(ec->ec_irq);*/ - lance_init_card(ec); /* Get mac_address, etc ...*/ + /* General initialization */ + ec->flags = ECF_EMPTY; + lance_init_card(ec); /* Get mac_address, etc ...*/ - ec_confaddr(ec); + 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'); + 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); + /* Finish the initialization */ + ec->flags |= ECF_ENABLED; -/* enable_irq(ec->ec_irq); */ + /* Set the interrupt 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); -/* enter_kdebug(">> ec_init():"); */ - - return; + return; } @@ -735,42 +691,36 @@ 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!"); */ + 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 ((r=getuptime(&now)) != OK) + panic("lance", "getuptime() failed:", r); + reply.DL_CLCK = now; + + r = send(ec->client, &reply); + if (r == ELOCKED && may_block) + { return; - } -#endif - if (r < 0) - panic( "lance", "send failed:", r); + } + if (r < 0) + panic( "lance", "send failed:", r); - ec->read_s = 0; - ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV); + ec->read_s = 0; + ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV); } @@ -781,8 +731,8 @@ 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); + if (send(req->m_source, reply_mess) != OK) + panic( "lance", "unable to mess_reply", NO_NUM); } @@ -792,28 +742,28 @@ message *reply_mess; 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; + 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"); + /* User defined ethernet address? */ + strcpy(eakey, ec_conf[ec-ec_table].ec_envvar); + strcat(eakey, "_EA"); - for (i= 0; i < 6; i++) - { + 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; + break; ec->mac_address.ea_addr[i]= v; - } + } - if (i != 0 && i != 6) - { + if (i != 0 && i != 6) + { /* It's all or nothing; force a panic. */ (void) env_parse(eakey, "?", 0, &v, 0L, 0L); - } + } } @@ -823,53 +773,50 @@ ether_card_t *ec; 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; itx_ring[i].u.base = 0; - isstored[i]=0; - } - - /* re-init Rx-ring */ - rx_slot_nr = 0; - for (i=0; iec_port; + + /* stop */ + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP); + + /* purge Tx-ring */ + tx_slot_nr = cur_tx_slot_nr = 0; + for (i=0; itx_ring[i].u.base = 0; + isstored[i]=0; + } + + /* re-init Rx-ring */ + rx_slot_nr = 0; + for (i=0; irx_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 - { + } + + /* Set 'Receive Mode' */ + if (ec->flags & ECF_PROMISC) + { + write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_PROM); + } + else + { if (ec->flags & (ECF_BROAD | ECF_MULTI)) - { - out_word(ioaddr+LANCE_ADDR, 0xf); - out_word(ioaddr+LANCE_DATA, 0x0000); - } + { + write_csr(ioaddr, LANCE_CSR15, 0x0000); + } else - { - out_word(ioaddr+LANCE_ADDR, 0xf); - out_word(ioaddr+LANCE_DATA, 0x4000); - } - } + { + write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_DRCVBC); + } + } - out_word(ioaddr+LANCE_ADDR, 0x0); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, 0x142); /* start && enable interrupt */ + /* start && enable interrupt */ + write_csr(ioaddr, LANCE_CSR0, + LANCE_CSR0_IDON|LANCE_CSR0_IENA|LANCE_CSR0_STRT); - return; + return; } /*===========================================================================* @@ -878,156 +825,156 @@ ether_card_t *ec; 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; + 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); + 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)); + for (;;) + { +#if VERBOSE + printf("ETH: Reading ISR..."); #endif -#define ISR_WINT 0x0200 -#define ISR_RINT 0x0400 -#define ISR_RERR 0x1000 -#define ISR_WERR 0x4000 -#define ISR_ERR 0x8000 + isr = read_csr(ioaddr, LANCE_CSR0); + if (isr & (LANCE_CSR0_ERR|LANCE_CSR0_RINT|LANCE_CSR0_TINT)) { + write_csr(ioaddr, LANCE_CSR0, + isr & ~(LANCE_CSR0_IENA|LANCE_CSR0_TDMD|LANCE_CSR0_STOP + |LANCE_CSR0_STRT|LANCE_CSR0_INIT) ); + } + write_csr(ioaddr, LANCE_CSR0, + LANCE_CSR0_BABL|LANCE_CSR0_CERR|LANCE_CSR0_MISS|LANCE_CSR0_MERR + |LANCE_CSR0_IDON|LANCE_CSR0_IENA); + #define ISR_RST 0x0000 - if ((isr & (ISR_WINT|ISR_RINT|ISR_RERR|ISR_WERR|ISR_ERR)) == 0x0000) - { -#if 0 - printf("OK\n"); + if ((isr & (LANCE_CSR0_TINT|LANCE_CSR0_RINT|LANCE_CSR0_MISS + |LANCE_CSR0_BABL|LANCE_CSR0_ERR)) == 0x0000) + { +#if VERBOSE + printf("OK\n"); #endif - break; - } + 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 - printf("WERR\n"); + if (isr & LANCE_CSR0_MISS) + { +#if VERBOSE + printf("RX Missed Frame\n"); #endif - ec->eth_stat.ets_sendErr++; - } - if (isr & ISR_WINT) - { -#if 0 - printf("WINT\n"); + ec->eth_stat.ets_recvErr++; + } + if ((isr & LANCE_CSR0_BABL) || (isr & LANCE_CSR0_TINT)) + { + if (isr & LANCE_CSR0_BABL) + { +#if VERBOSE + printf("TX Timeout\n"); #endif - /* status check: restart if needed. */ - status = lp->tx_ring[cur_tx_slot_nr].u.base; - - /* ??? */ - if (status & 0x40000000) - { - status = lp->tx_ring[cur_tx_slot_nr].misc; - ec->eth_stat.ets_sendErr++; - if (status & 0x0400) - ec->eth_stat.ets_transAb++; - if (status & 0x0800) - ec->eth_stat.ets_carrSense++; - if (status & 0x1000) - ec->eth_stat.ets_OWC++; - if (status & 0x4000) - { - ec->eth_stat.ets_fifoUnder++; - must_restart=1; - } - } - else - { - if (status & 0x18000000) - ec->eth_stat.ets_collision++; - ec->eth_stat.ets_packetT++; - } - } - /* transmit a packet on the next slot if it exists. */ - check = 0; - if (isstored[cur_tx_slot_nr]==1) - { - /* free the tx-slot just transmitted */ - isstored[cur_tx_slot_nr]=0; - cur_tx_slot_nr = (++cur_tx_slot_nr) & TX_RING_MOD_MASK; - - /* next tx-slot is ready? */ - if (isstored[cur_tx_slot_nr]==1) - check=1; - else - check=0; - } - else - { - panic( "lance", "got premature WINT...", NO_NUM); - } - if (check==1) - { - lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83; - out_word(ioaddr+LANCE_ADDR, 0x0000); - out_word(ioaddr+LANCE_DATA, 0x0048); - } - else - if (check==-1) - continue; - /* we set a buffered message in the slot if it exists. */ - /* and transmit it, if needed. */ - if (ec->flags & ECF_SEND_AVAIL) - ec_send(ec); - } - if (isr & ISR_RINT) - { -#if 0 - printf("RINT\n"); + ec->eth_stat.ets_sendErr++; + } + if (isr & LANCE_CSR0_TINT) + { +#if VERBOSE + printf("TX INT\n"); #endif - ec_recv(ec); - } + /* status check: restart if needed. */ + status = lp->tx_ring[cur_tx_slot_nr].u.base; - if (isr & ISR_RST) - { - ec->flags = ECF_STOPPED; - break; - } + /* ??? */ + if (status & 0x40000000) + { + status = lp->tx_ring[cur_tx_slot_nr].misc; + ec->eth_stat.ets_sendErr++; + if (status & 0x0400) + ec->eth_stat.ets_transAb++; + if (status & 0x0800) + ec->eth_stat.ets_carrSense++; + if (status & 0x1000) + ec->eth_stat.ets_OWC++; + if (status & 0x4000) + { + ec->eth_stat.ets_fifoUnder++; + must_restart=1; + } + } + else + { + if (status & 0x18000000) + ec->eth_stat.ets_collision++; + ec->eth_stat.ets_packetT++; + } + } + /* transmit a packet on the next slot if it exists. */ + check = 0; + if (isstored[cur_tx_slot_nr]==1) + { + /* free the tx-slot just transmitted */ + isstored[cur_tx_slot_nr]=0; + cur_tx_slot_nr = (++cur_tx_slot_nr) & TX_RING_MOD_MASK; + + /* next tx-slot is ready? */ + if (isstored[cur_tx_slot_nr]==1) + check=1; + else + check=0; + } + else + { + panic( "lance", "got premature TX INT...", NO_NUM); + } + if (check==1) + { + lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83; + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_IENA|LANCE_CSR0_TDMD); + } + else + if (check==-1) + continue; + /* we set a buffered message in the slot if it exists. */ + /* and transmit it, if needed. */ + if (ec->flags & ECF_SEND_AVAIL) + ec_send(ec); + } + if (isr & LANCE_CSR0_RINT) + { +#if VERBOSE + printf("RX INT\n"); +#endif + ec_recv(ec); + } - /* ??? cf. lance driver on linux */ - if (must_restart == 1) - { -#if 0 - printf("ETH: restarting...\n"); + if (isr & ISR_RST) + { + ec->flags = ECF_STOPPED; +#if VERBOSE + printf("ISR_RST\n"); #endif - out_word(ioaddr+LANCE_ADDR, 0x0); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ - out_word(ioaddr+LANCE_DATA, 0x2); /* start */ - } + break; } - - if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED)) + + /* ??? cf. lance driver on linux */ + if (must_restart == 1) { -#if 0 - printf("ETH: resetting...\n"); +#if VERBOSE + printf("ETH: restarting...\n"); #endif - ec_reset(ec); + /* stop */ + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP); + /* start */ + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STRT); } + } + + if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED)) + { +#if VERBOSE + printf("ETH: resetting...\n"); +#endif + ec_reset(ec); + } } /*===========================================================================* @@ -1036,33 +983,34 @@ ether_card_t *ec; static void ec_reset(ec) ether_card_t *ec; { - /* Stop/start the chip, and clear all RX,TX-slots */ - unsigned short ioaddr = ec->ec_port; - int i; - - out_word(ioaddr+LANCE_ADDR, 0x0); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ - out_word(ioaddr+LANCE_DATA, 0x2); /* start */ - - /* purge Tx-ring */ - tx_slot_nr = cur_tx_slot_nr = 0; - for (i=0; itx_ring[i].u.base = 0; - isstored[i]=0; - } - - /* re-init Rx-ring */ - rx_slot_nr = 0; - for (i=0; iec_port; + int i; + + /* stop */ + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP); + /* start */ + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STRT); + + /* purge Tx-ring */ + tx_slot_nr = cur_tx_slot_nr = 0; + for (i=0; itx_ring[i].u.base = 0; + isstored[i]=0; + } + + /* re-init Rx-ring */ + rx_slot_nr = 0; + for (i=0; irx_ring[i].buf_length = -ETH_FRAME_LEN; lp->rx_ring[i].u.addr[3] |= 0x80; - } + } - /* store a buffered message on the slot if exists */ - ec_send(ec); - ec->flags &= ~ECF_STOPPED; + /* store a buffered message on the slot if exists */ + ec_send(ec); + ec->flags &= ~ECF_STOPPED; } /*===========================================================================* @@ -1071,19 +1019,19 @@ ether_card_t *ec; static void ec_send(ec) ether_card_t *ec; { - /* from ec_check_ints() or ec_reset(). */ - /* this function proccesses the buffered message. (slot/transmit) */ - if (!(ec->flags & ECF_SEND_AVAIL)) - return; + /* from ec_check_ints() or ec_reset(). */ + /* this function proccesses the buffered message. (slot/transmit) */ + if (!(ec->flags & ECF_SEND_AVAIL)) + return; - ec->flags &= ~ECF_SEND_AVAIL; - switch(ec->sendmsg.m_type) - { - case DL_WRITEV_S: do_vwrite_s(&ec->sendmsg, TRUE); break; - default: + ec->flags &= ~ECF_SEND_AVAIL; + switch(ec->sendmsg.m_type) + { + case DL_WRITEV_S: do_vwrite_s(&ec->sendmsg, TRUE); break; + default: panic( "lance", "wrong type:", ec->sendmsg.m_type); break; - } + } } /*===========================================================================* @@ -1092,32 +1040,36 @@ ether_card_t *ec; static void do_vread_s(mp) message *mp; { - int port, count, size; - ether_card_t *ec; - - port = mp->DL_PORT; - count = mp->DL_COUNT; - ec= &ec_table[port]; - ec->client= mp->DL_PROC; - - get_userdata_s(mp->DL_PROC, (vir_bytes) mp->DL_GRANT, 0, - (count > IOVEC_NR ? IOVEC_NR : count) * - sizeof(iovec_s_t), ec->read_iovec.iod_iovec); - ec->read_iovec.iod_iovec_s = count; - ec->read_iovec.iod_proc_nr = mp->DL_PROC; - ec->read_iovec.iod_grant = (vir_bytes) mp->DL_GRANT; - ec->read_iovec.iod_iovec_offset = 0; - - ec->tmp_iovec = ec->read_iovec; - size= calc_iovec_size(&ec->tmp_iovec); - - ec->flags |= ECF_READING; - - ec_recv(ec); - - if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED)) - ec_reset(ec); - reply(ec, OK, FALSE); + int port, count, size, r; + ether_card_t *ec; + + port = mp->DL_PORT; + count = mp->DL_COUNT; + ec= &ec_table[port]; + ec->client= mp->DL_PROC; + + r = sys_safecopyfrom(mp->DL_PROC, mp->DL_GRANT, 0, + (vir_bytes)ec->read_iovec.iod_iovec, + (count > IOVEC_NR ? IOVEC_NR : count) * + sizeof(iovec_s_t), D); + if (r != OK) + panic(__FILE__, + "do_vread_s: sys_safecopyfrom failed: %d\n", r); + ec->read_iovec.iod_iovec_s = count; + ec->read_iovec.iod_proc_nr = mp->DL_PROC; + ec->read_iovec.iod_grant = (vir_bytes) mp->DL_GRANT; + ec->read_iovec.iod_iovec_offset = 0; + + ec->tmp_iovec = ec->read_iovec; + size= calc_iovec_size(&ec->tmp_iovec); + + ec->flags |= ECF_READING; + + ec_recv(ec); + + if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED)) + ec_reset(ec); + reply(ec, OK, FALSE); } /*===========================================================================* @@ -1126,67 +1078,68 @@ message *mp; static void ec_recv(ec) ether_card_t *ec; { - vir_bytes length; - int packet_processed; - int status; - unsigned short ioaddr = ec->ec_port; - - if ((ec->flags & ECF_READING)==0) - return; - if (!(ec->flags & ECF_ENABLED)) - return; - - /* we check all the received slots until find a properly received packet */ - packet_processed = FALSE; - while (!packet_processed) - { + vir_bytes length; + int packet_processed; + int status; + unsigned short ioaddr = ec->ec_port; + + if ((ec->flags & ECF_READING)==0) + return; + if (!(ec->flags & ECF_ENABLED)) + return; + + /* we check all the received slots until find a properly received packet */ + packet_processed = FALSE; + while (!packet_processed) + { status = lp->rx_ring[rx_slot_nr].u.base >> 24; if ( (status & 0x80) == 0x00 ) - { - status = lp->rx_ring[rx_slot_nr].u.base >> 24; - - /* ??? */ - if (status != 0x03) - { - if (status & 0x01) - ec->eth_stat.ets_recvErr++; - if (status & 0x04) - ec->eth_stat.ets_fifoOver++; - if (status & 0x08) - ec->eth_stat.ets_CRCerr++; - if (status & 0x10) - ec->eth_stat.ets_OVW++; - if (status & 0x20) - ec->eth_stat.ets_frameAll++; - length = 0; - } - else - { - ec->eth_stat.ets_packetR++; - length = lp->rx_ring[rx_slot_nr].msg_length; - } - if (length > 0) - { - ec_nic2user(ec, (int)(lp->rbuf[rx_slot_nr]), - &ec->read_iovec, 0, length); + { + status = lp->rx_ring[rx_slot_nr].u.base >> 24; + + /* ??? */ + if (status != 0x03) + { + if (status & 0x01) + ec->eth_stat.ets_recvErr++; + if (status & 0x04) + ec->eth_stat.ets_fifoOver++; + if (status & 0x08) + ec->eth_stat.ets_CRCerr++; + if (status & 0x10) + ec->eth_stat.ets_OVW++; + if (status & 0x20) + ec->eth_stat.ets_frameAll++; + length = 0; + } + else + { + ec->eth_stat.ets_packetR++; + length = lp->rx_ring[rx_slot_nr].msg_length; + } + if (length > 0) + { + ec_nic2user(ec, (int)(lp->rbuf[rx_slot_nr]), + &ec->read_iovec, 0, length); - ec->read_s = length; - ec->flags |= ECF_PACK_RECV; - ec->flags &= ~ECF_READING; - packet_processed = TRUE; - } - /* set up this slot again, and we move to the next slot */ - lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN; - lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80; - - out_word(ioaddr+LANCE_ADDR, 0x00); - out_word(ioaddr+LANCE_DATA, 0x7940); - - rx_slot_nr = (++rx_slot_nr) & RX_RING_MOD_MASK; - } + ec->read_s = length; + ec->flags |= ECF_PACK_RECV; + ec->flags &= ~ECF_READING; + packet_processed = TRUE; + } + /* set up this slot again, and we move to the next slot */ + lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN; + lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80; + + write_csr(ioaddr, LANCE_CSR0, + LANCE_CSR0_BABL|LANCE_CSR0_CERR|LANCE_CSR0_MISS + |LANCE_CSR0_MERR|LANCE_CSR0_IDON|LANCE_CSR0_IENA); + + rx_slot_nr = (++rx_slot_nr) & RX_RING_MOD_MASK; + } else - break; - } + break; + } } /*===========================================================================* @@ -1196,87 +1149,72 @@ static void do_vwrite_s(mp, from_int) message *mp; int from_int; { - int port, count, check; - ether_card_t *ec; - unsigned short ioaddr; + int port, count, check, r; + ether_card_t *ec; + unsigned short ioaddr; - port = mp->DL_PORT; - count = mp->DL_COUNT; - ec = &ec_table[port]; - ec->client= mp->DL_PROC; + port = mp->DL_PORT; + count = mp->DL_COUNT; + ec = &ec_table[port]; + ec->client= mp->DL_PROC; - if (isstored[tx_slot_nr]==1) - { + if (isstored[tx_slot_nr]==1) + { /* all slots are used, so this message is buffered */ ec->sendmsg= *mp; ec->flags |= ECF_SEND_AVAIL; reply(ec, OK, FALSE); return; - } - - /* convert the message to write_iovec */ - get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0, - (count > IOVEC_NR ? IOVEC_NR : count) * - sizeof(iovec_s_t), ec->write_iovec.iod_iovec); - - ec->write_iovec.iod_iovec_s = count; - ec->write_iovec.iod_proc_nr = mp->DL_PROC; - ec->write_iovec.iod_grant = mp->DL_GRANT; - ec->write_iovec.iod_iovec_offset = 0; - - ec->tmp_iovec = ec->write_iovec; - ec->write_s = calc_iovec_size(&ec->tmp_iovec); - - /* copy write_iovec to the slot on DMA address */ - ec_user2nic(ec, &ec->write_iovec, 0, - (int)(lp->tbuf[tx_slot_nr]), ec->write_s); - /* set-up for transmitting, and transmit it if needed. */ - lp->tx_ring[tx_slot_nr].buf_length = -ec->write_s; - lp->tx_ring[tx_slot_nr].misc = 0x0; - lp->tx_ring[tx_slot_nr].u.base - = virt_to_bus(lp->tbuf[tx_slot_nr]) & 0xffffff; - isstored[tx_slot_nr]=1; - if (cur_tx_slot_nr == tx_slot_nr) - check=1; - else - check=0; - tx_slot_nr = (++tx_slot_nr) & TX_RING_MOD_MASK; - - if (check == 1) - { + } + + /* convert the message to write_iovec */ + r = sys_safecopyfrom(mp->DL_PROC, mp->DL_GRANT, 0, + (vir_bytes)ec->write_iovec.iod_iovec, + (count > IOVEC_NR ? IOVEC_NR : count) * + sizeof(iovec_s_t), D); + if (r != OK) + panic(__FILE__, + "do_vwrite_s: sys_safecopyfrom failed: %d\n", r); + + ec->write_iovec.iod_iovec_s = count; + ec->write_iovec.iod_proc_nr = mp->DL_PROC; + ec->write_iovec.iod_grant = mp->DL_GRANT; + ec->write_iovec.iod_iovec_offset = 0; + + ec->tmp_iovec = ec->write_iovec; + ec->write_s = calc_iovec_size(&ec->tmp_iovec); + + /* copy write_iovec to the slot on DMA address */ + ec_user2nic(ec, &ec->write_iovec, 0, + (int)(lp->tbuf[tx_slot_nr]), ec->write_s); + /* set-up for transmitting, and transmit it if needed. */ + lp->tx_ring[tx_slot_nr].buf_length = -ec->write_s; + lp->tx_ring[tx_slot_nr].misc = 0x0; + lp->tx_ring[tx_slot_nr].u.base + = virt_to_bus(lp->tbuf[tx_slot_nr]) & 0xffffff; + isstored[tx_slot_nr]=1; + if (cur_tx_slot_nr == tx_slot_nr) + check=1; + else + check=0; + tx_slot_nr = (++tx_slot_nr) & TX_RING_MOD_MASK; + + if (check == 1) + { ioaddr = ec->ec_port; lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83; - out_word(ioaddr+LANCE_ADDR, 0x0000); - out_word(ioaddr+LANCE_DATA, 0x0048); - } + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_IENA|LANCE_CSR0_TDMD); + } - ec->flags |= ECF_PACK_SEND; + ec->flags |= ECF_PACK_SEND; - /* reply by calling do_int() if this function is called from interrupt. */ - if (from_int) - return; - reply(ec, OK, FALSE); + /* reply by calling do_int() if this function is called from interrupt. */ + if (from_int) + return; + reply(ec, OK, FALSE); } -/*===========================================================================* - * get_userdata_s * - *===========================================================================*/ -static void get_userdata_s(user_proc, grant, offset, count, loc_addr) -int user_proc; -cp_grant_id_t grant; -vir_bytes offset; -vir_bytes count; -void *loc_addr; -{ - int cps; - cps = sys_safecopyfrom(user_proc, grant, offset, - (vir_bytes)loc_addr, count, D); - if (cps != OK) - panic(__FILE__, - "get_userdata_s: sys_safecopyfrom failed: %d\n", cps); -} - /*===========================================================================* * ec_user2nic * *===========================================================================*/ @@ -1287,36 +1225,36 @@ vir_bytes offset; int nic_addr; vir_bytes count; { - int bytes, i, r; + int bytes, i, r; - i= 0; - while (count > 0) - { + i= 0; + while (count > 0) + { if (i >= IOVEC_NR) - { - ec_next_iovec(iovp); - i= 0; - continue; - } + { + ec_next_iovec(iovp); + i= 0; + continue; + } if (offset >= iovp->iod_iovec[i].iov_size) - { - offset -= iovp->iod_iovec[i].iov_size; - i++; - continue; - } + { + offset -= iovp->iod_iovec[i].iov_size; + i++; + continue; + } bytes = iovp->iod_iovec[i].iov_size - offset; if (bytes > count) - bytes = count; + bytes = count; if ( (r=sys_safecopyfrom(iovp->iod_proc_nr, - iovp->iod_iovec[i].iov_grant, offset, - nic_addr, bytes, D )) != OK ) - panic( __FILE__, "ec_user2nic: sys_safecopyfrom failed", r ); - + iovp->iod_iovec[i].iov_grant, offset, + nic_addr, bytes, D )) != OK ) + panic( __FILE__, "ec_user2nic: sys_safecopyfrom failed", r ); + count -= bytes; nic_addr += bytes; offset += bytes; - } + } } /*===========================================================================* @@ -1329,34 +1267,34 @@ iovec_dat_t *iovp; vir_bytes offset; vir_bytes count; { - int bytes, i, r; + int bytes, i, r; - i= 0; - while (count > 0) - { + i= 0; + while (count > 0) + { if (i >= IOVEC_NR) - { - ec_next_iovec(iovp); - i= 0; - continue; - } + { + ec_next_iovec(iovp); + i= 0; + continue; + } if (offset >= iovp->iod_iovec[i].iov_size) - { - offset -= iovp->iod_iovec[i].iov_size; - i++; - continue; - } + { + offset -= iovp->iod_iovec[i].iov_size; + i++; + continue; + } bytes = iovp->iod_iovec[i].iov_size - offset; if (bytes > count) - bytes = count; + bytes = count; if ( (r=sys_safecopyto( iovp->iod_proc_nr, iovp->iod_iovec[i].iov_grant, - offset, nic_addr, bytes, D )) != OK ) - panic( __FILE__, "ec_nic2user: sys_safecopyto failed: ", r ); + offset, nic_addr, bytes, D )) != OK ) + panic( __FILE__, "ec_nic2user: sys_safecopyto failed: ", r ); count -= bytes; nic_addr += bytes; offset += bytes; - } + } } @@ -1366,39 +1304,45 @@ vir_bytes count; static int calc_iovec_size(iovp) iovec_dat_t *iovp; { - int size,i; + int size,i; - size = i = 0; + size = i = 0; - while (i < iovp->iod_iovec_s) - { + while (i < iovp->iod_iovec_s) + { if (i >= IOVEC_NR) - { - ec_next_iovec(iovp); - i= 0; - continue; - } + { + ec_next_iovec(iovp); + i= 0; + continue; + } size += iovp->iod_iovec[i].iov_size; i++; - } + } - return size; + return size; } /*===========================================================================* - * ec_next_iovec * + * ec_next_iovec * *===========================================================================*/ static void ec_next_iovec(iovp) iovec_dat_t *iovp; { - iovp->iod_iovec_s -= IOVEC_NR; - iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_s_t); - - get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, - iovp->iod_iovec_offset, - (iovp->iod_iovec_s > IOVEC_NR ? - IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_s_t), - iovp->iod_iovec); + int r; + + iovp->iod_iovec_s -= IOVEC_NR; + iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_s_t); + + r = sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_grant, + iovp->iod_iovec_offset, + (vir_bytes)iovp->iod_iovec, + (iovp->iod_iovec_s > IOVEC_NR ? + IOVEC_NR : iovp->iod_iovec_s) * + sizeof(iovec_s_t), D); + if (r != OK) + panic(__FILE__, + "ec_next_iovec: sys_safecopyfrom failed: %d\n", r); } @@ -1408,42 +1352,29 @@ iovec_dat_t *iovp; static void do_getstat_s(mp) message *mp; { - int r, port; - ether_card_t *ec; + int r, port; + ether_card_t *ec; - port = mp->DL_PORT; - if (port < 0 || port >= EC_PORT_NR_MAX) - panic( "lance", "illegal port", port); + port = mp->DL_PORT; + if (port < 0 || port >= EC_PORT_NR_MAX) + panic( "lance", "illegal port", port); - ec= &ec_table[port]; - ec->client= mp->DL_PROC; + ec= &ec_table[port]; + ec->client= mp->DL_PROC; - put_userdata_s(mp->DL_PROC, mp->DL_GRANT, - &ec->eth_stat, sizeof(ec->eth_stat)); + r = sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0, + (vir_bytes)&ec->eth_stat, sizeof(ec->eth_stat), D); - mp->m_type= DL_STAT_REPLY; - mp->DL_PORT= port; - mp->DL_STAT= OK; - r= send(mp->m_source, mp); - if (r != OK) - panic(__FILE__, "do_getstat_s: send failed: %d\n", r); -} + if (r != OK) + panic(__FILE__, + "do_getstat_s: sys_safecopyto failed: %d\n", r); -/*===========================================================================* - * put_userdata_s * - *===========================================================================*/ -static void put_userdata_s(user_proc, grant, loc_addr, count) -int user_proc; -cp_grant_id_t grant; -void *loc_addr; -vir_bytes count; -{ - int cps; - cps = sys_safecopyto(user_proc, grant, 0, - (vir_bytes) loc_addr, count, D); - if (cps != OK) - panic(__FILE__, - "put_userdata_s: sys_safecopyto failed: %d\n", cps); + mp->m_type= DL_STAT_REPLY; + mp->DL_PORT= port; + mp->DL_STAT= OK; + r= send(mp->m_source, mp); + if (r != OK) + panic(__FILE__, "do_getstat_s: send failed: %d\n", r); } /*===========================================================================* @@ -1452,342 +1383,379 @@ vir_bytes count; static void do_stop(mp) message *mp; { - int port; - ether_card_t *ec; - unsigned short ioaddr; + int port; + ether_card_t *ec; + unsigned short ioaddr; - port = mp->DL_PORT; - if (port < 0 || port >= EC_PORT_NR_MAX) - panic( "lance", "illegal port", port); - ec = &ec_table[port]; + port = mp->DL_PORT; + if (port < 0 || port >= EC_PORT_NR_MAX) + panic( "lance", "illegal port", port); + ec = &ec_table[port]; - if (!(ec->flags & ECF_ENABLED)) - return; + if (!(ec->flags & ECF_ENABLED)) + return; - ioaddr = ec->ec_port; + ioaddr = ec->ec_port; - out_word(ioaddr+LANCE_ADDR, 0x0); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ - out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* reset */ + /* stop */ + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP); - ec->flags = ECF_EMPTY; + /* Reset */ + in_word(ioaddr+LANCE_RESET); + + ec->flags = ECF_EMPTY; } +/*===========================================================================* + * getAddressing * + *===========================================================================*/ static void getAddressing(devind, ec) int devind; ether_card_t *ec; { - unsigned int membase, ioaddr; - int reg, irq; - - for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) - { - ioaddr = pci_attr_r32(devind, reg); - - if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 - || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0) - continue; - /* Strip the I/O address out of the returned value */ - ioaddr &= PCI_BASE_ADDRESS_IO_MASK; - /* Get the memory base address */ - membase = pci_attr_r32(devind, PCI_BASE_ADDRESS_1); - /* KK: Get the IRQ number */ - irq = pci_attr_r8(devind, PCI_INTERRUPT_PIN); - if (irq) - irq = pci_attr_r8(devind, PCI_INTERRUPT_LINE); - /* Get the ROM base address */ - /*pci_attr_r32(devind, PCI_ROM_ADDRESS, &romaddr); - romaddr >>= 10;*/ - /* Take the first one or the one that matches in boot ROM address */ - /*if (pci_ioaddr == 0 - || romaddr == ((unsigned long) rom.rom_segment << 4)) {*/ - ec->ec_linmem = membase; - ec->ec_port = ioaddr; - ec->ec_irq = irq; - /*}*/ - } + unsigned int membase, ioaddr; + int reg, irq; + + for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) + { + ioaddr = pci_attr_r32(devind, reg); + + if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 + || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0) + continue; + /* Strip the I/O address out of the returned value */ + ioaddr &= PCI_BASE_ADDRESS_IO_MASK; + /* Get the memory base address */ + membase = pci_attr_r32(devind, PCI_BASE_ADDRESS_1); + /* KK: Get the IRQ number */ + irq = pci_attr_r8(devind, PCI_INTERRUPT_PIN); + if (irq) + irq = pci_attr_r8(devind, PCI_INTERRUPT_LINE); + + ec->ec_linmem = membase; + ec->ec_port = ioaddr; + ec->ec_irq = irq; + } } /*===========================================================================* - * lance_probe * + * lance_probe * *===========================================================================*/ static int lance_probe(ec) ether_card_t *ec; { - unsigned short pci_cmd, attached = 0; - unsigned short ioaddr; - int lance_version, chip_version; - int devind, just_one, i, r; - - u16_t vid, did; - u32_t bar; - u8_t ilr; - char *dname; - - if ((ec->ec_pcibus | ec->ec_pcidev | ec->ec_pcifunc) != 0) - { - /* Look for specific PCI device */ - r= pci_find_dev(ec->ec_pcibus, ec->ec_pcidev, - ec->ec_pcifunc, &devind); - if (r == 0) - { - printf("%s: no PCI found at %d.%d.%d\n", - ec->port_name, ec->ec_pcibus, - ec->ec_pcidev, ec->ec_pcifunc); - return 0; - } - pci_ids(devind, &vid, &did); - just_one= TRUE; - } - else - { - r= pci_first_dev(&devind, &vid, &did); - if (r == 0) - return 0; - just_one= FALSE; - } - - for(;;) - { - for (i= 0; pcitab[i].vid != 0; i++) - { - if (pcitab[i].vid != vid) - continue; - if (pcitab[i].did != did) - continue; - if (pcitab[i].checkclass) - { - panic("lance", - "class check not implemented", NO_NUM); - } - break; - } - if (pcitab[i].vid != 0) - break; - - if (just_one) - { - printf( - "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n", - ec->port_name, vid, did, - ec->ec_pcibus, - ec->ec_pcidev, ec->ec_pcifunc); - return 0; - } - - r= pci_next_dev(&devind, &vid, &did); - if (!r) - return 0; - } - - dname= pci_dev_name(vid, did); - if (!dname) - dname= "unknown device"; - - /* - printf("%s: ", ec->port_name); - printf("%s ", dname); - printf("(%x/", vid); - printf("%x) ", did); - printf("at %s\n", pci_slot_name(devind)); - */ - pci_reserve(devind); - -/* for (i = 0; pci_dev_list[i].vendor != 0; i++) { - if (pci_dev_list[i].suffix == 1) + unsigned short pci_cmd, attached = 0; + unsigned short ioaddr; + int lance_version, chip_version; + int devind, just_one, i, r; + + u16_t vid, did; + u32_t bar; + u8_t ilr; + char *dname; + + if ((ec->ec_pcibus | ec->ec_pcidev | ec->ec_pcifunc) != 0) + { + /* Look for specific PCI device */ + r= pci_find_dev(ec->ec_pcibus, ec->ec_pcidev, + ec->ec_pcifunc, &devind); + if (r == 0) + { + printf("%s: no PCI found at %d.%d.%d\n", + ec->port_name, ec->ec_pcibus, + ec->ec_pcidev, ec->ec_pcifunc); + return 0; + } + pci_ids(devind, &vid, &did); + just_one= TRUE; + } + else + { + r= pci_first_dev(&devind, &vid, &did); + if (r == 0) + return 0; + just_one= FALSE; + } + + for(;;) + { + for (i= 0; pcitab[i].vid != 0; i++) + { + if (pcitab[i].vid != vid) + continue; + if (pcitab[i].did != did) + continue; + if (pcitab[i].checkclass) + { + panic("lance", + "class check not implemented", NO_NUM); + } + break; + } + if (pcitab[i].vid != 0) + break; + + if (just_one) { - ec->ec_port = pci_dev_list[i].ioaddr; - ec->ec_irq = pci_dev_list[i].irq; - ec->ec_linmem = pci_dev_list[i].membase; - ec->ec_bus = pci_dev_list[i].bus; - ec->ec_dev = pci_dev_list[i].devfn; - ec->ec_fnc = - pci_dev_list[i].suffix = -1; - attached = 1; - break; + printf( + "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n", + ec->port_name, vid, did, + ec->ec_pcibus, + ec->ec_pcidev, ec->ec_pcifunc); + return 0; } - } - if (attached == 0) - return 0; -*/ - getAddressing(devind, ec); - - /* ===== Bus Master ? ===== */ - /*pcibios_read_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, &pci_cmd);*/ - pci_cmd = pci_attr_r32(devind, PCI_CR); - if (!(pci_cmd & PCI_COMMAND_MASTER)) { - pci_cmd |= PCI_COMMAND_MASTER; - /*pcibios_write_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, pci_cmd);*/ - pci_attr_w32(devind, PCI_CR, pci_cmd); - } - - /* ===== Probe Details ===== */ - ioaddr = ec->ec_port; - - out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* Reset */ - out_word(ioaddr+LANCE_ADDR, 0x0); /* Sw to win 0 */ - if (in_word(ioaddr+LANCE_DATA) != 0x4) - { + + r= pci_next_dev(&devind, &vid, &did); + if (!r) + return 0; + } + + dname= pci_dev_name(vid, did); + if (!dname) + dname= "unknown device"; + + pci_reserve(devind); + + getAddressing(devind, ec); + + + /* ===== Bus Master ? ===== */ + pci_cmd = pci_attr_r32(devind, PCI_CR); + if (!(pci_cmd & PCI_COMMAND_MASTER)) { + pci_cmd |= PCI_COMMAND_MASTER; + pci_attr_w32(devind, PCI_CR, pci_cmd); + } + + /* ===== Probe Details ===== */ + ioaddr = ec->ec_port; + + /* Reset */ + in_word(ioaddr+LANCE_RESET); + + if (read_csr(ioaddr, LANCE_CSR0) != LANCE_CSR0_STOP) + { ec->mode=EC_DISABLED; - } - /* Probe Chip Version */ - out_word(ioaddr+LANCE_ADDR, 88); /* Get the version of the chip */ - if (in_word(ioaddr+LANCE_ADDR) != 88) - lance_version = 0; - else - { - chip_version = in_word(ioaddr+LANCE_DATA); - out_word(ioaddr+LANCE_ADDR, 89); - chip_version |= in_word(ioaddr+LANCE_DATA) << 16; + } + + /* Probe Chip Version */ + out_word(ioaddr+LANCE_ADDR, 88); /* Get the version of the chip */ + if (in_word(ioaddr+LANCE_ADDR) != 88) + lance_version = 0; + else + { + chip_version = read_csr(ioaddr, LANCE_CSR88); + chip_version |= read_csr(ioaddr, LANCE_CSR89) << 16; + if ((chip_version & 0xfff) != 0x3) - { - ec->mode=EC_DISABLED; - } + { + ec->mode=EC_DISABLED; + } chip_version = (chip_version >> 12) & 0xffff; for (lance_version = 1; chip_table[lance_version].id_number != 0; ++lance_version) - if (chip_table[lance_version].id_number == chip_version) - break; - } - -#if 0 - printf("%s: %s at %X:%d\n", - ec->port_name, chip_table[lance_version].name, - ec->ec_port, ec->ec_irq); + if (chip_table[lance_version].id_number == chip_version) + break; + } + +#if VERBOSE + printf("%s: %s at %X:%d\n", + ec->port_name, chip_table[lance_version].name, + ec->ec_port, ec->ec_irq); #endif - return lance_version; + return lance_version; } /*===========================================================================* - * do_getname * + * do_getname * *===========================================================================*/ static void do_getname(mp) message *mp; { - int r; - - strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME)); - mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0'; - mp->m_type= DL_NAME_REPLY; - r= send(mp->m_source, mp); - if (r != OK) - panic("LANCE", "do_getname: send failed", r); + int r; + + strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME)); + mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0'; + mp->m_type= DL_NAME_REPLY; + r= send(mp->m_source, mp); + if (r != OK) + panic("LANCE", "do_getname: send failed", r); } /*===========================================================================* - * lance_init_card * + * lance_init_card * *===========================================================================*/ static void lance_init_card(ec) ether_card_t *ec; { - int i; - Address l = lance_buf; - unsigned short ioaddr = ec->ec_port; - - /* ============= setup init_block(cf. lance_probe1) ================ */ - /* make sure data structure is 8-byte aligned and below 16MB (for DMA) */ - - lp = (struct lance_interface *)l; - lp->init_block.mode = 0x3; /* disable Rx and Tx */ - lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0; - /* using multiple Rx/Tx buffer */ - lp->init_block.rx_ring - = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS; - lp->init_block.tx_ring - = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS; - - l = virt_to_bus(&lp->init_block); - out_word(ioaddr+LANCE_ADDR, 0x1); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, (unsigned short)l); - out_word(ioaddr+LANCE_ADDR, 0x2); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, (unsigned short)(l >> 16)); - out_word(ioaddr+LANCE_ADDR, 0x4); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, 0x915); - out_word(ioaddr+LANCE_ADDR, 0x0); - (void)in_word(ioaddr+LANCE_ADDR); - - /* ============= Get MAC address (cf. lance_probe1) ================ */ - for (i = 0; i < 6; ++i) - ec->mac_address.ea_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i); - - /* ============ (re)start init_block(cf. lance_reset) =============== */ - /* Reset the LANCE */ - (void)in_word(ioaddr+LANCE_RESET); - - /* ----- Re-initialize the LANCE ----- */ - /* Set station address */ - for (i = 0; i < 6; ++i) - lp->init_block.phys_addr[i] = ec->mac_address.ea_addr[i]; - /* Preset the receive ring headers */ - for (i=0; irx_ring[i].buf_length = -ETH_FRAME_LEN; - /* OWN */ - lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff; - /* we set the top byte as the very last thing */ - lp->rx_ring[i].u.addr[3] = 0x80; - } - /* Preset the transmitting ring headers */ - for (i=0; itx_ring[i].u.base = 0; - isstored[i] = 0; - } - lp->init_block.mode = 0x0; /* enable Rx and Tx */ - - l = (Address)virt_to_bus(&lp->init_block); - out_word(ioaddr+LANCE_ADDR, 0x1); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, (short)l); - out_word(ioaddr+LANCE_ADDR, 0x2); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, (short)(l >> 16)); - out_word(ioaddr+LANCE_ADDR, 0x4); - (void)in_word(ioaddr+LANCE_ADDR); - out_word(ioaddr+LANCE_DATA, 0x915); - out_word(ioaddr+LANCE_ADDR, 0x0); - (void)in_word(ioaddr+LANCE_ADDR); - - /* ----- start when init done. ----- */ - out_word(ioaddr+LANCE_DATA, 0x4); /* stop */ - out_word(ioaddr+LANCE_DATA, 0x1); /* init */ - for (i = 10000; i > 0; --i) - if (in_word(ioaddr+LANCE_DATA) & 0x100) - break; - - /* Set 'Multicast Table' */ - for (i=0;i<4;++i) - { - out_word(ioaddr+LANCE_ADDR, 0x8 + i); - out_word(ioaddr+LANCE_DATA, 0xffff); - } - - /* Set 'Receive Mode' */ - if (ec->flags & ECF_PROMISC) - { - out_word(ioaddr+LANCE_ADDR, 0xf); - out_word(ioaddr+LANCE_DATA, 0x8000); - } - else - { + int i; + Address l = (vir_bytes)lance_buf; + unsigned short ioaddr = ec->ec_port; + + /* ============= setup init_block(cf. lance_probe1) ================ */ + /* make sure data structure is 8-byte aligned and below 16MB (for DMA) */ + + lp = (struct lance_interface *)l; + + /* disable Tx and Rx */ + lp->init_block.mode = LANCE_CSR15_DTX|LANCE_CSR15_DRX; + lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0; + /* using multiple Rx/Tx buffer */ + lp->init_block.rx_ring + = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS; + lp->init_block.tx_ring + = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS; + + l = virt_to_bus(&lp->init_block); + write_csr(ioaddr, LANCE_CSR1, (unsigned short)l); + write_csr(ioaddr, LANCE_CSR2, (unsigned short)(l >> 16)); + write_csr(ioaddr, LANCE_CSR4, + LANCE_CSR4_APAD_XMT|LANCE_CSR4_MFCOM|LANCE_CSR4_RCVCCOM + |LANCE_CSR4_TXSTRTM|LANCE_CSR4_JABM); + + /* ============= Get MAC address (cf. lance_probe1) ================ */ + for (i = 0; i < 6; ++i) + ec->mac_address.ea_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i); + + /* ============ (re)start init_block(cf. lance_reset) =============== */ + /* Reset the LANCE */ + (void)in_word(ioaddr+LANCE_RESET); + + /* ----- Re-initialize the LANCE ----- */ + /* Set station address */ + for (i = 0; i < 6; ++i) + lp->init_block.phys_addr[i] = ec->mac_address.ea_addr[i]; + /* Preset the receive ring headers */ + for (i=0; irx_ring[i].buf_length = -ETH_FRAME_LEN; + /* OWN */ + lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff; + /* we set the top byte as the very last thing */ + lp->rx_ring[i].u.addr[3] = 0x80; + } + /* Preset the transmitting ring headers */ + for (i=0; itx_ring[i].u.base = 0; + isstored[i] = 0; + } + /* enable Rx and Tx */ + lp->init_block.mode = 0x0; + + l = (Address)virt_to_bus(&lp->init_block); + write_csr(ioaddr, LANCE_CSR1, (short)l); + write_csr(ioaddr, LANCE_CSR2, (short)(l >> 16)); + write_csr(ioaddr, LANCE_CSR4, + LANCE_CSR4_APAD_XMT|LANCE_CSR4_MFCOM|LANCE_CSR4_RCVCCOM + |LANCE_CSR4_TXSTRTM|LANCE_CSR4_JABM); + + /* ----- start when init done. ----- */ + /* stop */ + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP); + /* init */ + write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_INIT); + /* poll for IDON */ + for (i = 10000; i > 0; --i) + if (read_csr(ioaddr, LANCE_CSR0) & LANCE_CSR0_IDON) + break; + + /* Set 'Multicast Table' */ + for (i=0;i<4;++i) + { + write_csr(ioaddr, LANCE_CSR8 + i, 0xffff); + } + + /* Set 'Receive Mode' */ + if (ec->flags & ECF_PROMISC) + { + write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_PROM); + } + else + { if (ec->flags & (ECF_BROAD | ECF_MULTI)) - { - out_word(ioaddr+LANCE_ADDR, 0xf); - out_word(ioaddr+LANCE_DATA, 0x0000); - } + { + write_csr(ioaddr, LANCE_CSR15, 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 */ + { + write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_DRCVBC); + } + } + + /* start && enable interrupt */ + write_csr(ioaddr, LANCE_CSR0, + LANCE_CSR0_IDON|LANCE_CSR0_IENA|LANCE_CSR0_STRT); + + return; +} + +/*===========================================================================* + * in_byte * + *===========================================================================*/ +static u8_t in_byte(port_t port) +{ + int r; + u32_t value; + + r= sys_inb(port, &value); + if (r != OK) + panic("lance","sys_inb failed", r); + return value; +} + +/*===========================================================================* + * in_word * + *===========================================================================*/ +static u16_t in_word(port_t port) +{ + int r; + u32_t value; + + r= sys_inw(port, &value); + if (r != OK) + panic("lance","sys_inw failed", r); + return value; +} - return; +/*===========================================================================* + * out_byte * + *===========================================================================*/ +static void out_byte(port_t port, u8_t value) +{ + int r; + + r= sys_outb(port, value); + if (r != OK) + panic("lance","sys_outb failed", r); +} + +/*===========================================================================* + * out_word * + *===========================================================================*/ +static void out_word(port_t port, u16_t value) +{ + int r; + + r= sys_outw(port, value); + if (r != OK) + panic("lance","sys_outw failed", r); +} + +/*===========================================================================* + * read_csr * + *===========================================================================*/ +static u16_t read_csr(port_t ioaddr, u16_t csrno) +{ + out_word(ioaddr+LANCE_ADDR, csrno); + return in_word(ioaddr+LANCE_DATA); +} + +/*===========================================================================* + * write_csr * + *===========================================================================*/ +static void write_csr(port_t ioaddr, u16_t csrno, u16_t value) +{ + out_word(ioaddr+LANCE_ADDR, csrno); + out_word(ioaddr+LANCE_DATA, value); } diff --git a/drivers/lance/lance.h b/drivers/lance/lance.h index 8f6d00f96..67117656b 100644 --- a/drivers/lance/lance.h +++ b/drivers/lance/lance.h @@ -1,4 +1,3 @@ -/*#include "kernel.h"*/ #include #include @@ -102,3 +101,115 @@ typedef struct ether_card #define DEI_DEFAULT 0x8000 +/* + * NOTE: Not all the CSRs are defined. Just the ones that were deemed + * necessary or potentially useful. + */ + +/* Control and Status Register Addresses */ +#define LANCE_CSR0 0 /* Controller Status Register */ +#define LANCE_CSR1 1 /* Initialization Block Address (Lower) */ +#define LANCE_CSR2 2 /* Initialization Block Address (Upper) */ +#define LANCE_CSR3 3 /* Interrupt Masks and Deferral Control */ +#define LANCE_CSR4 4 /* Test and Features Control */ +#define LANCE_CSR5 5 /* Extended Control and Interrupt */ +#define LANCE_CSR8 8 /* Logical Address Filter 0 */ +#define LANCE_CSR9 9 /* Logical Address Filter 1 */ +#define LANCE_CSR10 10 /* Logical Address Filter 2 */ +#define LANCE_CSR11 11 /* Logical Address Filter 3 */ +#define LANCE_CSR15 15 /* Mode */ +#define LANCE_CSR88 88 /* Chip ID Register (Lower) */ +#define LANCE_CSR89 89 /* Chip ID Register (Upper) */ + +/* Control and Status Register 0 (CSR0) */ +#define LANCE_CSR0_ERR 0x8000 /* Error Occurred */ +#define LANCE_CSR0_BABL 0x4000 /* Transmitter Timeout Error */ +#define LANCE_CSR0_CERR 0x2000 /* Collision Error */ +#define LANCE_CSR0_MISS 0x1000 /* Missed Frame */ +#define LANCE_CSR0_MERR 0x0800 /* Memory Error */ +#define LANCE_CSR0_RINT 0x0400 /* Receive Interrupt */ +#define LANCE_CSR0_TINT 0x0200 /* Transmit Interrupt */ +#define LANCE_CSR0_IDON 0x0100 /* Initialization Done */ +#define LANCE_CSR0_INTR 0x0080 /* Interrupt Flag */ +#define LANCE_CSR0_IENA 0x0040 /* Interrupt Enable */ +#define LANCE_CSR0_RXON 0x0020 /* Receive On */ +#define LANCE_CSR0_TXON 0x0010 /* Transmit On */ +#define LANCE_CSR0_TDMD 0x0008 /* Transmit Demand */ +#define LANCE_CSR0_STOP 0x0004 /* Stop */ +#define LANCE_CSR0_STRT 0x0002 /* Start */ +#define LANCE_CSR0_INIT 0x0001 /* Init */ + +/* Control and Status Register 3 (CSR3) */ +/* 0x8000 Reserved */ +#define LANCE_CSR3_BABLM 0x4000 /* Babble Mask */ +/* 0x2000 Reserved */ +#define LANCE_CSR3_MISSM 0x1000 /* Missed Frame Mask */ +#define LANCE_CSR3_MERRM 0x0800 /* Memory Error Mask */ +#define LANCE_CSR3_RINTM 0x0400 /* Receive Interrupt Mask */ +#define LANCE_CSR3_TINTM 0x0200 /* Transmit Interrupt Mask */ +#define LANCE_CSR3_IDONM 0x0100 /* Initialization Done Mask */ +/* 0x0080 Reserved */ +#define LANCE_CSR3_DXSUFLO 0x0040 /* Disable Transmit Stop on Underflow */ +#define LANCE_CSR3_LAPPEN 0x0020 /* Look Ahead Packet Processing Enable */ +#define LANCE_CSR3_DXMT2PD 0x0010 /* Disable Transmit Two Part Deferral */ +#define LANCE_CSR3_EMBA 0x0008 /* Enable Modified Back-off Algorithm */ +#define LANCE_CSR3_BSWP 0x0004 /* Byte Swap */ +/* 0x0002 Reserved + * 0x0001 Reserved */ + +/* Control and Status Register 4 (CSR4) */ +#define LANCE_CSR4_EN124 0x8000 /* Enable CSR124 Access */ +#define LANCE_CSR4_DMAPLUS 0x4000 /* Disable DMA Burst Transfer Counter */ +#define LANCE_CSR4_TIMER 0x2000 /* Enable Bus Activity Timer */ +#define LANCE_CSR4_DPOLL 0x1000 /* Disable Transmit Polling */ +#define LANCE_CSR4_APAD_XMT 0x0800 /* Auto Pad Transmit */ +#define LANCE_CSR4_ASTRP_RCV 0x0400 /* Auto Strip Receive */ +#define LANCE_CSR4_MFCO 0x0200 /* Missed Frame Counter Overflow */ +#define LANCE_CSR4_MFCOM 0x0100 /* Missed Frame Counter Overflow Mask */ +#define LANCE_CSR4_UINTCMD 0x0080 /* User Interrupt Command */ +#define LANCE_CSR4_UINT 0x0040 /* User Interrupt */ +#define LANCE_CSR4_RCVCCO 0x0020 /* Receive Collision Counter Overflow */ +#define LANCE_CSR4_RCVCCOM 0x0010 /* Receive Collision Counter Overflow + * Mask */ +#define LANCE_CSR4_TXSTRT 0x0008 /* Transmit Start */ +#define LANCE_CSR4_TXSTRTM 0x0004 /* Transmit Start Mask */ +#define LANCE_CSR4_JAB 0x0002 /* Jabber Error */ +#define LANCE_CSR4_JABM 0x0001 /* Jabber Error Mask */ + +/* Control and Status Register 5 (CSR5) */ +#define LANCE_CSR5_TOKINTD 0x8000 /* Transmit OK Interrupt Disable */ +#define LANCE_CSR5_LINTEN 0x4000 /* Last Transmit Interrupt Enable */ +/* 0x2000 Reserved + * 0x1000 Reserved */ +#define LANCE_CSR5_SINT 0x0800 /* System Interrupt */ +#define LANCE_CSR5_SINTE 0x0400 /* System Interrupt Enable */ +#define LANCE_CSR5_SLPINT 0x0200 /* Sleep Interrupt */ +#define LANCE_CSR5_SLPINTE 0x0100 /* Sleep Interrupt Enable */ +#define LANCE_CSR5_EXDINT 0x0080 /* Excessive Deferral Interrupt */ +#define LANCE_CSR5_EXDINTE 0x0040 /* Excessive Deferral Interrupt Enable */ +#define LANCE_CSR5_MPPLBA 0x0020 /* Magic Packet Physical Logical Broadcast + * Accept */ +#define LANCE_CSR5_MPINT 0x0010 /* Magic Packet Interrupt */ +#define LANCE_CSR5_MPINTE 0x0008 /* Magic Packet Interrupt Enable */ +#define LANCE_CSR5_MPEN 0x0004 /* Magic Packet Enable */ +#define LANCE_CSR5_MPMODE 0x0002 /* Magic Packet Mode */ +#define LANCE_CSR5_SPND 0x0001 /* Suspend */ + +/* Control and Status Register 15 (CSR15) */ +#define LANCE_CSR15_PROM 0x8000 /* Promiscuous Mode */ +#define LANCE_CSR15_DRCVBC 0x4000 /* Disable Receive Broadcast */ +#define LANCE_CSR15_DRCVPA 0x2000 /* Disable Receive Physical Address */ +#define LANCE_CSR15_DLNKTST 0x1000 /* Disable Link Status */ +#define LANCE_CSR15_DAPC 0x0800 /* Disable Automatic Polarity Correction */ +#define LANCE_CSR15_MENDECL 0x0400 /* MENDEC Loopback Mode */ +#define LANCE_CSR15_LRT 0x0200 /* Low Receive Threshold (T-MAU Mode) */ +#define LANCE_CSR15_TSEL 0x0200 /* Transmit Mode Select (AUI Mode) */ +/* 0x0100 Portsel[1] + * 0x0080 Portsel[0] */ +#define LANCE_CSR15_INTL 0x0040 /* Internal Loopback */ +#define LANCE_CSR15_DRTY 0x0020 /* Disable Retry */ +#define LANCE_CSR15_FCOLL 0x0010 /* Force Collision */ +#define LANCE_CSR15_DXMTFCS 0x0008 /* Disable Transmit CRC (FCS) */ +#define LANCE_CSR15_LOOP 0x0004 /* Loopback Enable */ +#define LANCE_CSR15_DTX 0x0002 /* Disable Transmit */ +#define LANCE_CSR15_DRX 0x0001 /* Disable Receiver */