From: David van Moolenbroek Date: Tue, 2 Dec 2014 14:01:20 +0000 (+0000) Subject: dec21140A: use new libnetdriver X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=refs%2Fchanges%2F16%2F2916%2F1;p=minix.git dec21140A: use new libnetdriver Change-Id: I54be3b770e4d1fd320200c30e9e9073a7c1b405b --- diff --git a/minix/drivers/net/dec21140A/dec21140A.c b/minix/drivers/net/dec21140A/dec21140A.c index 4ab0d5e40..5d9eec3b5 100644 --- a/minix/drivers/net/dec21140A/dec21140A.c +++ b/minix/drivers/net/dec21140A/dec21140A.c @@ -2,7 +2,7 @@ * dec21041.c * * This file contains an ethernet device driver for DEC 21140A - * fast ethernet controllers as emulated by VirtualPC 2007. It is not + * fast ethernet controllers as emulated by VirtualPC 2007. It is not * intended to support the real card, as much more error checking * and testing would be needed. It supports both bridged and NAT mode. * @@ -12,288 +12,105 @@ #include #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include "dec21140A.h" - static u32_t io_inl(u16_t); static void io_outl(u16_t, u32_t); -static void do_conf(const message *); -static void do_get_stat_s(message *); -static void do_interrupt(const dpeth_t *); -static void do_reply(dpeth_t *); -static void do_vread_s(const message *, int); -static void do_watchdog(void *); - -static void de_update_conf(dpeth_t *); -static int de_probe(dpeth_t *, int skip); -static void de_conf_addr(dpeth_t *); -static void de_first_init(dpeth_t *); + +static int do_init(unsigned int, ether_addr_t *); +static void do_stop(void); +static int do_send(struct netdriver_data *, size_t); +static ssize_t do_recv(struct netdriver_data *, size_t); +static void do_stat(eth_stat_t *); +static void do_intr(unsigned int); + +static int de_probe(dpeth_t *, unsigned int skip); +static void de_conf_addr(dpeth_t *, ether_addr_t *); +static void de_init_buf(dpeth_t *); static void de_reset(const dpeth_t *); static void de_hw_conf(const dpeth_t *); static void de_start(const dpeth_t *); -static void de_setup_frame(const dpeth_t *); +static void de_setup_frame(const dpeth_t *, const ether_addr_t *); static u16_t de_read_rom(const dpeth_t *, u8_t, u8_t); -static int de_calc_iov_size(iovec_dat_s_t *); -static void de_next_iov(iovec_dat_s_t *); -static void do_vwrite_s(const message *, int); -static void de_get_userdata_s(int, cp_grant_id_t, vir_bytes, int, void - *); - -/* Error messages */ -static char str_CopyErrMsg[] = "unable to read/write user data"; -static char str_SendErrMsg[] = "send failed"; -static char str_SizeErrMsg[] = "illegal packet size"; -static char str_UmapErrMsg[] = "Unable to sys_umap"; -static char str_BusyErrMsg[] = "Send/Recv failed: busy"; -static char str_StatErrMsg[] = "Unable to send stats"; -static char str_AlignErrMsg[] = "Bad align of buffer/descriptor"; -static char str_DevName[] = "dec21140A:eth#?"; static dpeth_t de_state; static int de_instance; -/* SEF functions and variables. */ -static void sef_local_startup(void); -static int sef_cb_init_fresh(int type, sef_init_info_t *info); +static const struct netdriver de_table = { + .ndr_init = do_init, + .ndr_stop = do_stop, + .ndr_recv = do_recv, + .ndr_send = do_send, + .ndr_stat = do_stat, + .ndr_intr = do_intr +}; -/*===========================================================================* - * main * - *===========================================================================*/ int main(int argc, char *argv[]) { - dpeth_t *dep; - message m; - int ipc_status; - int r; - - /* SEF local startup. */ env_setargs(argc, argv); - sef_local_startup(); - - while (TRUE) - { - if ((r= netdriver_receive(ANY, &m, &ipc_status)) != OK) - panic("netdriver_receive failed: %d", r); - - if(is_ipc_notify(ipc_status)) { - switch(_ENDPOINT_P(m.m_source)) { - case CLOCK: - do_watchdog(&m); - break; - - case HARDWARE: - dep = &de_state; - if (dep->de_mode == DEM_ENABLED) { - do_interrupt(dep); - if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV)) - do_reply(dep); - sys_irqenable(&dep->de_hook); - } - break; - default: - printf("ignoring notify from %d\n", m.m_source); - break; - } - continue; - } - - switch (m.m_type) - { - case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break; - case DL_READV_S: do_vread_s(&m, FALSE); break; - case DL_CONF: do_conf(&m); break; - case DL_GETSTAT_S: do_get_stat_s(&m); break; - - default: - printf("message 0x%x; %d from %d\n", - m.m_type, m.m_type-DL_RQ_BASE, m.m_source); - panic("illegal message: %d", m.m_type); - } - } -} - -/*===========================================================================* - * sef_local_startup * - *===========================================================================*/ -static void sef_local_startup() -{ - /* Register init callbacks. */ - sef_setcb_init_fresh(sef_cb_init_fresh); - sef_setcb_init_lu(sef_cb_init_fresh); - sef_setcb_init_restart(sef_cb_init_fresh); - - /* Register live update callbacks. */ - sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); - sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree); - - /* Register signal callbacks. */ - sef_setcb_signal_handler(sef_cb_signal_handler_term); - - /* Let SEF perform startup. */ - sef_startup(); -} - -/*===========================================================================* - * sef_cb_init_fresh * - *===========================================================================*/ -static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) -{ -/* Initialize the DEC 21140A driver. */ - int fkeys, sfkeys; - long v; - - v = 0; - (void) env_parse("instance", "d", 0, &v, 0, 255); - de_instance = (int) v; - /* Request function key for debug dumps */ - fkeys = sfkeys = 0; - bit_set(sfkeys, DE_FKEY); - if ((fkey_map(&fkeys, &sfkeys)) != OK) - printf("%s: error using Shift+F%d key(%d)\n", str_DevName, DE_FKEY, errno); + netdriver_task(&de_table); - /* Announce we are up! */ - netdriver_announce(); - - return OK; + return 0; } -static void do_get_stat_s(message * mp) +static void de_init_hw(dpeth_t *dep, ether_addr_t *addr) { - int rc; - dpeth_t *dep; - - dep = &de_state; + de_reset(dep); + de_conf_addr(dep, addr); + de_init_buf(dep); - if ((rc = sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant, - 0, (vir_bytes)&dep->de_stat, sizeof(dep->de_stat))) != OK) - panic("%s %d", str_CopyErrMsg, rc); + /* Set the interrupt handler policy. Request interrupts not to be reenabled + * automatically. Return the IRQ line number when an interrupt occurs. + */ + dep->de_hook = dep->de_irq; + sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook); + sys_irqenable(&dep->de_hook); - mp->m_type = DL_STAT_REPLY; - rc = ipc_send(mp->m_source, mp); - if( rc != OK ) - panic("%s %d", str_StatErrMsg, rc); - return; + de_reset(dep); + de_hw_conf(dep); + de_setup_frame(dep, addr); + de_start(dep); } -static void do_conf(const message * mp) +static int do_init(unsigned int instance, ether_addr_t *addr) { - int r; +/* Initialize the DEC 21140A driver. */ dpeth_t *dep; - message reply_mess; dep = &de_state; + memset(dep, 0, sizeof(*dep)); - strncpy(dep->de_name, str_DevName, strlen(str_DevName)); - dep->de_name[strlen(dep->de_name)-1] = '0' + de_instance; + strlcpy(dep->de_name, "dec21140A:?", sizeof(dep->de_name)); + dep->de_name[strlen(dep->de_name)-1] = '0' + instance; - if (dep->de_mode == DEM_DISABLED) { - de_update_conf(dep); - pci_init(); - if (dep->de_mode == DEM_ENABLED && !de_probe(dep, de_instance)) { - printf("%s: warning no ethernet card found at 0x%04X\n", - dep->de_name, dep->de_base_port); - dep->de_mode = DEM_DISABLED; - } - } - - r = OK; + de_instance = instance; - /* 'de_mode' may change if probe routines fail, test again */ - switch (dep->de_mode) { + if (!de_probe(dep, instance)) + return ENXIO; - case DEM_DISABLED: - r = ENXIO; /* Device is OFF or hardware probe failed */ - break; - - case DEM_ENABLED: - if (dep->de_flags == DEF_EMPTY) { - de_first_init(dep); - dep->de_flags |= DEF_ENABLED; - de_reset(dep); - de_hw_conf(dep); - de_setup_frame(dep); - de_start(dep); - } + de_init_hw(dep, addr); - /* TODO CHECK PROMISC AND MULTI */ - dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD); - if (mp->m_net_netdrv_dl_conf.mode & DL_PROMISC_REQ) - dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD; - if (mp->m_net_netdrv_dl_conf.mode & DL_MULTI_REQ) - dep->de_flags |= DEF_MULTI; - if (mp->m_net_netdrv_dl_conf.mode & DL_BROAD_REQ) - dep->de_flags |= DEF_BROAD; - break; - - case DEM_SINK: - DEBUG(printf("%s running in sink mode\n", str_DevName)); - memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t)); - de_conf_addr(dep); - break; - - default: break; - } - - reply_mess.m_type = DL_CONF_REPLY; - reply_mess.m_netdrv_net_dl_conf.stat = r; - if(r == OK){ - memcpy(reply_mess.m_netdrv_net_dl_conf.hw_addr, dep->de_address.ea_addr, - sizeof(reply_mess.m_netdrv_net_dl_conf.hw_addr)); - } - - if (ipc_send(mp->m_source, &reply_mess) != OK) - panic("%s %d", str_SendErrMsg, mp->m_source); - - return; -} - -static void do_reply(dpeth_t * dep) -{ - message reply; - int r, flags = DL_NOFLAGS; - - if (dep->de_flags & DEF_ACK_SEND) flags |= DL_PACK_SEND; - if (dep->de_flags & DEF_ACK_RECV) flags |= DL_PACK_RECV; - - reply.m_type = DL_TASK_REPLY; - reply.m_netdrv_net_dl_task.flags = flags; - reply.m_netdrv_net_dl_task.count = dep->de_read_s; - - r = ipc_send(dep->de_client, &reply); - - if(r < 0) - panic("%s %d", str_SendErrMsg, r); - - dep->de_read_s = 0; - dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV); - return; + return OK; } -static void do_watchdog(void *UNUSED(message)) +static void do_stat(eth_stat_t *stat) { - /* nothing here yet */ - return; + memcpy(stat, &de_state.de_stat, sizeof(*stat)); } -static int de_probe(dpeth_t *dep, int skip) +static int de_probe(dpeth_t *dep, unsigned int skip) { - int i, r, devind; - u16_t vid, did, temp16; + int r, devind; + u16_t vid, did; DEBUG(printf("PROBING...")); - + + pci_init(); + r= pci_first_dev(&devind, &vid, &did); if (r == 0) return FALSE; @@ -314,40 +131,22 @@ static int de_probe(dpeth_t *dep, int skip) panic("de_probe: base address invalid: %d", dep->de_base_port); DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n", - dep->de_name, (unsigned long)dep->de_base_port, + dep->de_name, (unsigned long)dep->de_base_port, dep->de_irq)); dep->de_type = pci_attr_r8(devind, PCI_REV); /* device validation. We support only the DEC21140A */ if(dep->de_type != DEC_21140A){ - dep->de_type = DE_TYPE_UNKNOWN; - printf("%s: unsupported device\n", str_DevName); + printf("%s: unsupported card type %x\n", dep->de_name, dep->de_type); return FALSE; } - de_reset(dep); - - DEBUG(printf("Reading SROM...\n")); - - for(i=0;i<(1<srom[i*2] = temp16 & 0xFF; - dep->srom[i*2+1] = temp16 >> 8; - } - - /* TODO: validate SROM content */ - /* acquire MAC addr */ - DEBUG(printf("Using MAC addr= ")); - for(i=0;i<6;i++){ - dep->de_address.ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET]; - DEBUG(printf("%02X%c",dep->de_address.ea_addr[i],i!=5?'-':'\n')); - } - DEBUG(printf("probe success\n")); return TRUE; } -static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits){ +static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits) +{ u16_t retVal = 0; int i; u32_t csr = 0; @@ -356,7 +155,11 @@ static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits){ more readable, the following macro is also just to clear up the code a little.*/ - #define EMIT do { io_outl(CSR_ADDR(dep, CSR9), csr | csr2); io_outl(CSR_ADDR(dep, CSR1), 0);} while(0) +#define EMIT \ + do { \ + io_outl(CSR_ADDR(dep, CSR9), csr | csr2); \ + io_outl(CSR_ADDR(dep, CSR1), 0); \ + } while(0) /* init */ csr = 0; EMIT; @@ -404,180 +207,87 @@ static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits){ return retVal; } -static void de_update_conf(dpeth_t * dep) +static ssize_t do_recv(struct netdriver_data *data, size_t max) { - static char dpc_fmt[] = "x:d:x"; - char ec_key[16]; - long val; + u32_t size; + dpeth_t *dep; + de_loc_descr_t *descr; - strlcpy(ec_key, "DEETH0", sizeof(ec_key)); - ec_key[5] += de_instance; + dep = &de_state; - dep->de_mode = DEM_ENABLED; - switch (env_parse(ec_key, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) { - case EP_OFF: dep->de_mode = DEM_DISABLED; break; - case EP_ON: dep->de_mode = DEM_SINK; break; - } - dep->de_base_port = 0; - - return; -} + descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]]; -static void do_vread_s(const message * mp, int from_int) -{ - u8_t *buffer; - u32_t size; - int r, ix = 0; - vir_bytes bytes; - dpeth_t *dep = NULL; - de_loc_descr_t *descr = NULL; - iovec_dat_s_t *iovp = NULL; + /* check if packet is in the current descr and only there */ + if ((descr->descr->des[DES0] & DES0_OWN) || + !(descr->descr->des[DES0] & DES0_FS) || + !(descr->descr->des[DES0] & DES0_LS)) + return SUSPEND; - dep = &de_state; + /*TODO: multi-descr msgs...*/ + /* We only support packets contained in a single descriptor. + Setting the descriptor buffer size to less then + ETH_MAX_PACK_SIZE will result in multi-descriptor + packets that we won't be able to handle + */ - dep->de_client = mp->m_source; - - if (dep->de_mode == DEM_ENABLED) { - - descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]]; - - /* check if packet is in the current descr and only there */ - if( !( !(descr->descr->des[DES0] & DES0_OWN) && - (descr->descr->des[DES0] & DES0_FS) && - (descr->descr->des[DES0] & DES0_LS) )) - goto suspend; - - - /*TODO: multi-descr msgs...*/ - /* We only support packets contained in a single descriptor. - Setting the descriptor buffer size to less then - ETH_MAX_PACK_SIZE will result in multi-descriptor - packets that we won't be able to handle - */ - assert(!(descr->descr->des[DES0]&DES0_OWN)); - assert(descr->descr->des[DES0]&DES0_FS); - assert(descr->descr->des[DES0]&DES0_LS); - - /* Check for abnormal messages. We assert here - because this driver is for a virtualized - envrionment where we will not get bad packets - */ - assert(!(descr->descr->des[DES0]&DES0_ES)); - assert(!(descr->descr->des[DES0]&DES0_RE)); - - - /* Setup the iovec entry to allow copying into - client layer - */ - dep->de_read_iovec.iod_proc_nr = mp->m_source; - de_get_userdata_s(mp->m_source, mp->m_net_netdrv_dl_readv_s.grant, 0, - mp->m_net_netdrv_dl_readv_s.count, - dep->de_read_iovec.iod_iovec); - dep->de_read_iovec.iod_iovec_s = mp->m_net_netdrv_dl_readv_s.count; - dep->de_read_iovec.iod_grant = mp->m_net_netdrv_dl_readv_s.grant; - dep->de_read_iovec.iod_iovec_offset = 0; - size = de_calc_iov_size(&dep->de_read_iovec); - if (size < ETH_MAX_PACK_SIZE) - panic("%s %d", str_SizeErrMsg, size); - - /* Copy buffer to user area and clear ownage */ - size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT; - - /*TODO: Complain to MS */ - /*HACK: VPC2007 returns packet of invalid size. Ethernet standard - specify 46 bytes as the minimum for valid payload. However, this is - artificial in so far as for certain packet types, notably ARP, less - then 46 bytes are needed to contain the full information. In a non - virtualized environment the 46 bytes rule is enforced in order to give - guarantee in the collison detection scheme. Of course, this being a - driver for a VPC2007, we won't have collisions and I can only suppose - MS decided to cut packet size to true minimum, regardless of the - 46 bytes payload standard. Note that this seems to not happen in - bridged mode. Note also, that the card does not return runt or - incomplete frames to us, so this hack is safe - */ - if(size<60){ - memset(&descr->buf1[size], 0, 60-size); - size=60; - } - /* End ugly hack */ - - iovp = &dep->de_read_iovec; - buffer = descr->buf1; - dep->bytes_rx += size; - dep->de_stat.ets_packetR++; - dep->de_read_s = size; - - do { - bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ - if (bytes >= size) - bytes = size; - - r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0, - (vir_bytes)buffer, bytes); - if (r != OK) - panic("%s %d", str_CopyErrMsg, r); - buffer += bytes; - - if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ - de_next_iov(iovp); - ix = 0; - } - } while ((size -= bytes) > 0); - - descr->descr->des[DES0]=DES0_OWN; - dep->cur_descr[DESCR_RECV]++; - if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR) - dep->cur_descr[DESCR_RECV] = 0; - - DEBUG(printf("Read returned size = %d\n", size)); - - /* Reply information */ - dep->de_flags |= DEF_ACK_RECV; - dep->de_flags &= NOT(DEF_READING); - } + /* Check for abnormal messages. We assert here + because this driver is for a virtualized + envrionment where we will not get bad packets + */ + assert(!(descr->descr->des[DES0]&DES0_ES)); + assert(!(descr->descr->des[DES0]&DES0_RE)); - if(!from_int){ - do_reply(dep); - } - return; + /* Copy buffer to user area and clear ownage */ + size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT; - suspend: - if(from_int){ - assert(dep->de_flags & DEF_READING); - return; + /* HACK: VPC2007 sends short-sized packets, pad to minimum ethernet length */ + if(size<60){ + memset(&descr->buf1[size], 0, 60-size); + size=60; } - assert(!(dep->de_flags & DEF_READING)); - dep->rx_return_msg = *mp; - dep->de_flags |= DEF_READING; - do_reply(dep); - return; + /* Truncate large packets */ + if (size > max) + size = max; + + netdriver_copyout(data, 0, descr->buf1, size); + + dep->de_stat.ets_packetR++; + + descr->descr->des[DES0]=DES0_OWN; + dep->cur_descr[DESCR_RECV]++; + if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR) + dep->cur_descr[DESCR_RECV] = 0; + + DEBUG(printf("Read returned size = %d\n", size)); + + return size; } -static void de_conf_addr(dpeth_t * dep) +static void de_conf_addr(dpeth_t *dep, ether_addr_t *addr) { - static char ea_fmt[] = "x:x:x:x:x:x"; - char ea_key[16]; - int ix; - long val; - - strlcpy(ea_key, "DEETH0_EA", sizeof(ea_key)); - ea_key[5] += de_instance; - - for (ix = 0; ix < SA_ADDR_LEN; ix++) { - val = dep->de_address.ea_addr[ix]; - if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET) - break; - dep->de_address.ea_addr[ix] = val; + u16_t temp16; + int i; + + DEBUG(printf("Reading SROM...\n")); + + for(i=0;i<(1<srom[i*2] = temp16 & 0xFF; + dep->srom[i*2+1] = temp16 >> 8; } - if (ix != 0 && ix != SA_ADDR_LEN) - env_parse(ea_key, "?", 0, &val, 0L, 0L); - return; + /* TODO: validate SROM content */ + /* acquire MAC addr */ + DEBUG(printf("Using MAC addr= ")); + for(i=0;i<6;i++){ + addr->ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET]; + DEBUG(printf("%02X%c", addr->ea_addr[i],i!=5?'-':'\n')); + } + DEBUG(printf("probe success\n")); } -static void de_first_init(dpeth_t *dep) +static void de_init_buf(dpeth_t *dep) { int i,j,r; vir_bytes descr_vir = (vir_bytes)dep->sendrecv_descr_buf; @@ -585,7 +295,6 @@ static void de_first_init(dpeth_t *dep) de_loc_descr_t *loc_descr; phys_bytes temp; - for(i=0;i<2;i++){ loc_descr = &dep->descr[i][0]; for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){ @@ -595,7 +304,7 @@ static void de_first_init(dpeth_t *dep) descr_vir += sizeof(de_descr_t); /* assign space for buffer */ - loc_descr->buf1 = (u8_t*)buffer_vir; + loc_descr->buf1 = (u8_t*)buffer_vir; buffer_vir += (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE); loc_descr->buf2 = 0; loc_descr++; @@ -610,9 +319,9 @@ static void de_first_init(dpeth_t *dep) temp = (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE); for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){ /* translate buffers physical address */ - r = sys_umap(SELF, VM_D, (vir_bytes)loc_descr->buf1, temp, + r = sys_umap(SELF, VM_D, (vir_bytes)loc_descr->buf1, temp, (phys_bytes *) &(loc_descr->descr->des[DES_BUF1])); - if(r != OK) panic("umap failed: %d", r); + if(r != OK) panic("umap failed: %d", r); loc_descr->descr->des[DES_BUF2] = 0; memset(&loc_descr->descr->des[DES0],0,sizeof(u32_t)); loc_descr->descr->des[DES1] = temp; @@ -623,15 +332,15 @@ static void de_first_init(dpeth_t *dep) loc_descr++; } } - + /* record physical location of two first descriptor */ - r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_RECV][0].descr, + r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_RECV][0].descr, sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_RECV]); - if(r != OK) panic("%s %d", str_UmapErrMsg, r); + if(r != OK) panic("sys_umap failed: %d", r); r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_TRAN][0].descr, sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_TRAN]); - if(r != OK) panic("%s %d", str_UmapErrMsg, r); + if(r != OK) panic("sys_umap failed: %d", r); DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n", dep->sendrecv_descr_phys_addr[DESCR_TRAN], @@ -643,58 +352,59 @@ static void de_first_init(dpeth_t *dep) for(j=0;j< (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR);j++){ r = sys_umap(SELF, VM_D, (vir_bytes)&(loc_descr->descr), sizeof(de_descr_t), &temp); - if(r != OK) - panic("%s %d", str_UmapErrMsg, r); + if(r != OK) panic("sys_umap failed: %d", r); if( ((loc_descr->descr->des[DES_BUF1] & 0x3) != 0) || ((loc_descr->descr->des[DES_BUF2] & 0x3) != 0) || ((temp&0x3)!=0) ) - panic("%s 0x%lx", str_AlignErrMsg, temp); + panic("alignment error: 0x%lx", temp); loc_descr++; } } - + /* Init default values */ dep->cur_descr[DESCR_TRAN]=1; dep->cur_descr[DESCR_RECV]=0; - dep->bytes_rx = 0; - dep->bytes_tx = 0; - - /* Set the interrupt handler policy. Request interrupts not to be reenabled - * automatically. Return the IRQ line number when an interrupt occurs. - */ - dep->de_hook = dep->de_irq; - sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook); - sys_irqenable(&dep->de_hook); } -static void do_interrupt(const dpeth_t *dep){ +static void do_intr(unsigned int __unused mask) +{ + dpeth_t *dep; u32_t val; + + dep = &de_state; + val = io_inl(CSR_ADDR(dep, CSR5)); if(val & CSR5_AIS){ panic("Abnormal Int CSR5=: %d", val); } - if( (dep->de_flags & DEF_READING) && (val & CSR5_RI) ){ - do_vread_s(&dep->rx_return_msg, TRUE); - } - - if( (dep->de_flags & DEF_SENDING) && (val & CSR5_TI) ){ - do_vwrite_s(&dep->tx_return_msg, TRUE); - } - + if (val & CSR5_RI) + netdriver_recv(); + + if (val & CSR5_TI) + netdriver_send(); + /* ack and reset interrupts */ io_outl(CSR_ADDR(dep, CSR5), 0xFFFFFFFF); - return; + + sys_irqenable(&dep->de_hook); } -static void de_reset(const dpeth_t *dep){ +static void de_reset(const dpeth_t *dep) +{ io_outl(CSR_ADDR(dep, CSR0), CSR0_SWR); } -static void de_hw_conf(const dpeth_t *dep){ +static void do_stop(void) +{ + de_reset(&de_state); +} + +static void de_hw_conf(const dpeth_t *dep) +{ u32_t val; /* CSR0 - global host bus prop */ @@ -714,18 +424,20 @@ static void de_hw_conf(const dpeth_t *dep){ io_outl(CSR_ADDR(dep, CSR7), val); /* CSR6 - operating mode register */ - val = CSR6_MBO | CSR6_PS | CSR6_FD | CSR6_HBD | + val = CSR6_MBO | CSR6_PS | CSR6_FD | CSR6_HBD | CSR6_PCS | CSR6_SCR | CSR6_TR_00; io_outl(CSR_ADDR(dep, CSR6), val); } -static void de_start(const dpeth_t *dep){ +static void de_start(const dpeth_t *dep) +{ u32_t val; val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST | CSR6_SR; io_outl(CSR_ADDR(dep, CSR6), val); } -static void de_setup_frame(const dpeth_t *dep){ +static void de_setup_frame(const dpeth_t *dep, const ether_addr_t *addr) +{ int i; u32_t val; @@ -739,165 +451,71 @@ static void de_setup_frame(const dpeth_t *dep){ dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF; for(i=1;i<16;i++){ memset(&(dep->descr[DESCR_TRAN][0].buf1[12*i]), 0, 12); - dep->descr[DESCR_TRAN][0].buf1[12*i+0] = dep->de_address.ea_addr[0]; - dep->descr[DESCR_TRAN][0].buf1[12*i+1] = dep->de_address.ea_addr[1]; - dep->descr[DESCR_TRAN][0].buf1[12*i+4] = dep->de_address.ea_addr[2]; - dep->descr[DESCR_TRAN][0].buf1[12*i+5] = dep->de_address.ea_addr[3]; - dep->descr[DESCR_TRAN][0].buf1[12*i+8] = dep->de_address.ea_addr[4]; - dep->descr[DESCR_TRAN][0].buf1[12*i+9] = dep->de_address.ea_addr[5]; + dep->descr[DESCR_TRAN][0].buf1[12*i+0] = addr->ea_addr[0]; + dep->descr[DESCR_TRAN][0].buf1[12*i+1] = addr->ea_addr[1]; + dep->descr[DESCR_TRAN][0].buf1[12*i+4] = addr->ea_addr[2]; + dep->descr[DESCR_TRAN][0].buf1[12*i+5] = addr->ea_addr[3]; + dep->descr[DESCR_TRAN][0].buf1[12*i+8] = addr->ea_addr[4]; + dep->descr[DESCR_TRAN][0].buf1[12*i+9] = addr->ea_addr[5]; } dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN; - dep->descr[DESCR_TRAN][0].descr->des[DES1] = DES1_SET | + dep->descr[DESCR_TRAN][0].descr->des[DES1] = DES1_SET | DE_SETUP_FRAME_SIZE | DES1_IC; /* start transmit process to process setup frame */ val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST; - io_outl(CSR_ADDR(dep, CSR6), val); + io_outl(CSR_ADDR(dep, CSR6), val); io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); - - return; -} - -static int de_calc_iov_size(iovec_dat_s_t * iovp){ - int size, ix; - size = ix = 0; - - do{ - size += iovp->iod_iovec[ix].iov_size; - if (++ix >= IOVEC_NR) { - de_next_iov(iovp); - ix = 0; - } - } while (ix < iovp->iod_iovec_s); - return size; } -static void de_get_userdata_s(int user_proc, cp_grant_id_t grant, - vir_bytes offset, int count, void *loc_addr){ - int rc; - vir_bytes len; - - len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t); - rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len); - if (rc != OK) - panic("%s %d", str_CopyErrMsg, rc); - return; -} - -static void de_next_iov(iovec_dat_s_t * iovp){ - - iovp->iod_iovec_s -= IOVEC_NR; - iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_t); - de_get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, iovp->iod_iovec_offset, - iovp->iod_iovec_s, iovp->iod_iovec); - return; -} - -static void do_vwrite_s(const message * mp, int from_int){ - static u8_t setupDone = 0; - int size, r, bytes, ix, totalsize; +static int do_send(struct netdriver_data *data, size_t size) +{ + static int setup_done = 0; dpeth_t *dep; - iovec_dat_s_t *iovp = NULL; de_loc_descr_t *descr = NULL; - u8_t *buffer = NULL; dep = &de_state; - dep->de_client = mp->m_source; + descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]]; - if (dep->de_mode == DEM_ENABLED) { - - if (!from_int && (dep->de_flags & DEF_SENDING)) - panic("%s", str_BusyErrMsg); + if(( descr->descr->des[DES0] & DES0_OWN)!=0) + return SUSPEND; - descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]]; + if(!setup_done && (dep->cur_descr[DESCR_TRAN] == 0) ){ + dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0; + setup_done=1; + } - if(( descr->descr->des[DES0] & DES0_OWN)!=0) - goto suspend; + netdriver_copyin(data, 0, descr->buf1, size); - if(!setupDone && (dep->cur_descr[DESCR_TRAN] == 0) ){ - dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0; - setupDone=1; - } + descr->descr->des[DES1] = (descr->descr->des[DES1]&DES1_ER) | + DES1_FS | DES1_LS | DES1_IC | size; + descr->descr->des[DES0] = DES0_OWN; - buffer = descr->buf1; - iovp = &dep->de_write_iovec; - iovp->iod_proc_nr = mp->m_source; - de_get_userdata_s(mp->m_source, mp->m_net_netdrv_dl_writev_s.grant, 0, - mp->m_net_netdrv_dl_writev_s.count, iovp->iod_iovec); - iovp->iod_iovec_s = mp->m_net_netdrv_dl_writev_s.count; - iovp->iod_grant = mp->m_net_netdrv_dl_writev_s.grant; - iovp->iod_iovec_offset = 0; - totalsize = size = de_calc_iov_size(iovp); - if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE) - panic("%s %d", str_SizeErrMsg, size); - - dep->bytes_tx += size; - dep->de_stat.ets_packetT++; - - ix=0; - do { - bytes = iovp->iod_iovec[ix].iov_size; - if (bytes >= size) - bytes = size; - - r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, - 0, (vir_bytes)buffer, bytes); - if (r != OK) - panic("%s %d", str_CopyErrMsg, r); - buffer += bytes; - - if (++ix >= IOVEC_NR) { - de_next_iov(iovp); - ix = 0; - } - } while ((size -= bytes) > 0); - - descr->descr->des[DES1] = (descr->descr->des[DES1]&DES1_ER) | - DES1_FS | DES1_LS | DES1_IC | totalsize; - descr->descr->des[DES0] = DES0_OWN; - - dep->cur_descr[DESCR_TRAN]++; - if(dep->cur_descr[DESCR_TRAN] >= DE_NB_SEND_DESCR) - dep->cur_descr[DESCR_TRAN] = 0; - - io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); - } - - dep->de_flags |= DEF_ACK_SEND; - if(from_int){ - dep->de_flags &= NOT(DEF_SENDING); - return; - } - do_reply(dep); - return; - - suspend: - if(from_int) - panic("should not happen: %d", 0); - - dep->de_stat.ets_transDef++; - dep->de_flags |= DEF_SENDING; - dep->de_stat.ets_transDef++; - dep->tx_return_msg = *mp; - do_reply(dep); -} + dep->cur_descr[DESCR_TRAN]++; + if(dep->cur_descr[DESCR_TRAN] >= DE_NB_SEND_DESCR) + dep->cur_descr[DESCR_TRAN] = 0; + + io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); -static void warning(const char *type, int err){ - printf("Warning: %s sys_%s failed (%d)\n", str_DevName, type, err); - return; + dep->de_stat.ets_packetT++; + + return OK; } -static u32_t io_inl(u16_t port){ +static u32_t io_inl(u16_t port) +{ u32_t value; int rc; - if ((rc = sys_inl(port, &value)) != OK) warning("inl", rc); + if ((rc = sys_inl(port, &value)) != OK) + panic("sys_inl failed: %d", rc); return value; } -static void io_outl(u16_t port, u32_t value){ +static void io_outl(u16_t port, u32_t value) +{ int rc; - if ((rc = sys_outl(port, value)) != OK) warning("outl", rc); - return; + if ((rc = sys_outl(port, value)) != OK) + panic("sys_outl failed: %d", rc); } diff --git a/minix/drivers/net/dec21140A/dec21140A.h b/minix/drivers/net/dec21140A/dec21140A.h index 6a8b4ea95..74f8af910 100644 --- a/minix/drivers/net/dec21140A/dec21140A.h +++ b/minix/drivers/net/dec21140A/dec21140A.h @@ -11,37 +11,21 @@ Created: 09/01/2009 Nicolas Tittley (first.last @ gmail DOT com) #include -#define DE_FKEY 7 /* Shift+ this value will dump info on console */ - -#define NOT(x) (~(x)) - #if debug == 1 # define DEBUG(statm) statm #else # define DEBUG(statm) #endif - -#define SA_ADDR_LEN sizeof(ether_addr_t) - #define DE_NB_SEND_DESCR 32 #define DE_SEND_BUF_SIZE (ETH_MAX_PACK_SIZE+2) #define DE_NB_RECV_DESCR 32 #define DE_RECV_BUF_SIZE (ETH_MAX_PACK_SIZE+2) -#define IOVEC_NR 16 + #define DE_MIN_BASE_ADDR 0x0400 #define DE_SROM_EA_OFFSET 20 #define DE_SETUP_FRAME_SIZE 192 - -typedef struct iovec_dat_s { - iovec_s_t iod_iovec[IOVEC_NR]; - int iod_iovec_s; - endpoint_t iod_proc_nr; - cp_grant_id_t iod_grant; - vir_bytes iod_iovec_offset; -} iovec_dat_s_t; - typedef struct de_descr { u32_t des[4]; } de_descr_t; @@ -53,9 +37,6 @@ typedef struct de_local_descr { } de_loc_descr_t; typedef struct dpeth { - - message rx_return_msg; /* Holds VREAD message until int */ - message tx_return_msg; /* Holds VWRITE message until int */ char de_name[32]; /* Name of this interface */ port_t de_base_port; /* Base port, for multiple card instance */ int de_irq; /* IRQ line number */ @@ -63,10 +44,7 @@ typedef struct dpeth { int de_type; /* What kind of hardware */ - ether_addr_t de_address; /* Ethernet Address */ eth_stat_t de_stat; /* Stats */ - unsigned long bytes_tx; /* Number of bytes sent */ - unsigned long bytes_rx; /* Number of bytes recv */ /* Space reservation. We will allocate all structures later in the code. here we just make sure we have the space we need at compile time */ @@ -81,42 +59,11 @@ typedef struct dpeth { #define DESCR_RECV 0 #define DESCR_TRAN 1 - int de_flags; /* Send/Receive mode (Configuration) */ - -#define DEF_EMPTY 0x0000 -#define DEF_READING 0x0001 -#define DEF_RECV_BUSY 0x0002 -#define DEF_ACK_RECV 0x0004 -#define DEF_SENDING 0x0010 -#define DEF_XMIT_BUSY 0x0020 -#define DEF_ACK_SEND 0x0040 -#define DEF_PROMISC 0x0100 -#define DEF_MULTI 0x0200 -#define DEF_BROAD 0x0400 -#define DEF_ENABLED 0x2000 -#define DEF_STOPPED 0x4000 - - int de_mode; /* Status of the Interface */ - -#define DEM_DISABLED 0x0000 -#define DEM_SINK 0x0001 -#define DEM_ENABLED 0x0002 - - /* Serial ROM */ #define SROM_BITWIDTH 6 u8_t srom[((1<