diff --git a/minix/drivers/net/orinoco/Makefile b/minix/drivers/net/orinoco/Makefile index 172e7d319..a71e040a0 100644 --- a/minix/drivers/net/orinoco/Makefile +++ b/minix/drivers/net/orinoco/Makefile @@ -2,8 +2,8 @@ PROG= orinoco SRCS= orinoco.c hermes.c -DPADD+= ${LIBNETDRIVER} ${LIBSYS} ${LIBTIMERS} -LDADD+= -lnetdriver -lsys -ltimers +DPADD+= ${LIBNETDRIVER} ${LIBSYS} +LDADD+= -lnetdriver -lsys CPPFLAGS.orinoco.c+= -I${NETBSDSRCDIR}/minix diff --git a/minix/drivers/net/orinoco/orinoco.c b/minix/drivers/net/orinoco/orinoco.c index b645c284f..fd71ffa2a 100644 --- a/minix/drivers/net/orinoco/orinoco.c +++ b/minix/drivers/net/orinoco/orinoco.c @@ -2,53 +2,26 @@ * orinoco.c * * This file contains a wireless device driver for Prism based wireless - * cards. + * cards. * - * Created by Stevens Le Blond + * Created by Stevens Le Blond * and Michael Valkering * */ #include #include -#include -#include -#include -#include -#include #include #include #include -#include -#include -#include "kernel/const.h" -#include "kernel/config.h" -#include "kernel/type.h" #define VERBOSE 1 /* display message during init */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "assert.h" #include "hermes.h" #include "hermes_rid.h" #include "orinoco.h" -#define ERR -1 - -#define debug 0 - #define OR_M_ENABLED 1 #define OR_M_DISABLED 0 #define OR_F_EMPTY 0 @@ -72,7 +45,6 @@ #define ETH_HLEN 14 static t_or or_state; -static int or_instance; struct ethhdr { u8_t h_dest[ETH_ALEN]; @@ -111,7 +83,7 @@ static const long channel_frequency[] = { #define NUM_CHANNELS (sizeof(channel_frequency) / sizeof(channel_frequency[0])) -/* This tables gives the actual meanings of the bitrate IDs returned by the +/* This tables gives the actual meanings of the bitrate IDs returned by the * firmware. Not used yet */ struct { int bitrate; /* in 100s of kilobits */ @@ -130,45 +102,39 @@ struct { #define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0])) - -static void or_writev_s(message * mp, int from_int); -static void or_readv_s(message * mp, int from_int); -static void reply(t_or * orp); -static int or_probe(t_or *, int skip); +static void or_other(const message *m_ptr, int ipc_status); +static void or_stop(void); +static int or_probe(t_or *, unsigned int skip); static void or_ev_info(t_or *); -static void or_init(message *); -static void or_pci_conf(void); -static void or_init_struct(t_or *); -static void or_init_hw(t_or *); +static int or_init(unsigned int instance, ether_addr_t *addr); +static void or_init_struct(t_or *, unsigned int); +static void or_init_hw(t_or *, ether_addr_t *); static void or_check_ints(t_or *); static void or_writerids(hermes_t *, t_or *); -static void or_readrids(hermes_t *, t_or *); -static void or_rec_mode(t_or *); -static void mess_reply(message *, message *); +static void or_readrids(hermes_t *, t_or *, ether_addr_t *); static u32_t or_get_bar(int devind, t_or * orp); -static void or_getstat_s(message * mp); +static void or_stat(eth_stat_t *stat); static void print_linkstatus(t_or * orp, u16_t status); +static ssize_t or_recv(struct netdriver_data *data, size_t max); static int or_get_recvd_packet(t_or *orp, u16_t rxfid, u8_t *databuf); static void or_reset(void); -static void or_watchdog_f(minix_timer_t *tp); +static void or_alarm(clock_t stamp); +static int or_send(struct netdriver_data *data, size_t size); static void setup_wepkey(t_or *orp, char *wepkey0); -static void do_hard_int(void); -static void check_int_events(void); +static void or_intr(unsigned int mask); static void or_handler(t_or *orp); -static void or_dump(message *m); +static void or_dump(void); -/* The message used in the main loop is made global, so that rl_watchdog_f() - * can change its message type to fake an interrupt message. - */ -static message m; -static int int_event_check; /* set to TRUE if events arrived */ - -static u32_t system_hz; - -/* SEF functions and variables. */ -static void sef_local_startup(void); -static int sef_cb_init_fresh(int type, sef_init_info_t *info); -static void sef_cb_signal_handler(int signo); +static const struct netdriver or_table = { + .ndr_init = or_init, + .ndr_stop = or_stop, + .ndr_recv = or_recv, + .ndr_send = or_send, + .ndr_stat = or_stat, + .ndr_intr = or_intr, + .ndr_alarm = or_alarm, + .ndr_other = or_other +}; /***************************************************************************** * main * @@ -176,164 +142,62 @@ static void sef_cb_signal_handler(int signo); * * * The main function of the driver, receiving and processing messages * *****************************************************************************/ -int main(int argc, char *argv[]) { - int r; - int ipc_status; - - /* SEF local startup. */ +int main(int argc, char *argv[]) +{ env_setargs(argc, argv); - sef_local_startup(); - while (TRUE) { - if ((r = netdriver_receive (ANY, &m, &ipc_status)) != OK) - panic("orinoco: netdriver_receive failed"); + netdriver_task(&or_table); - if (is_ipc_notify(ipc_status)) { - switch (_ENDPOINT_P(m.m_source)) { - case CLOCK: - or_watchdog_f(NULL); - break; - case HARDWARE: - do_hard_int(); - if (int_event_check) - check_int_events(); - break ; - case TTY_PROC_NR: - or_dump(&m); - break; - default: - panic("orinoco: illegal notify from: %d", - m.m_source); - } - - /* done, get new message */ - continue; - } - - switch (m.m_type) { - case DL_WRITEV_S: - or_writev_s (&m, FALSE); - break; - case DL_READV_S: - or_readv_s (&m, FALSE); - break; - case DL_CONF: - or_init (&m); - break; - case DL_GETSTAT_S: - or_getstat_s (&m); - break; - default: - panic("orinoco: 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); - - /* Let SEF perform startup. */ - sef_startup(); -} - -/*===========================================================================* - * sef_cb_init_fresh * - *===========================================================================*/ -static int sef_cb_init_fresh(int type, sef_init_info_t *info) -{ -/* Initialize the orinoco driver. */ - long v; - int fkeys, sfkeys, r; - - system_hz = sys_hz(); - - v = 0; - (void) env_parse("instance", "d", 0, &v, 0, 255); - or_instance = (int) v; - - /* Observe some function key for debug dumps. */ - fkeys = sfkeys = 0; bit_set(sfkeys, 11); - if ((r=fkey_map(&fkeys, &sfkeys)) != OK) - printf("Warning: orinoco couldn't observe F-key(s): %d\n",r); - - /* Announce we are up! */ - netdriver_announce(); - - return(OK); -} - -/*===========================================================================* - * sef_cb_signal_handler * - *===========================================================================*/ -static void sef_cb_signal_handler(int signo) -{ - t_or *orp; - - /* Only check for termination signal, ignore anything else. */ - if (signo != SIGTERM) return; - - orp = &or_state; - - if (orp->or_mode == OR_M_ENABLED) { - /* TODO: send a signal to the card to shut it down */ - } - exit(0); + return 0; } /***************************************************************************** - * check_int_events * + * or_other * * * - * If a hard interrupt message came in, call the or_check_ints for the right * - * card * + * * + * Process miscellaneous messages * *****************************************************************************/ -static void check_int_events(void) { - t_or *orp; - - /* the interrupt message doesn't contain information about the port, try - * to find it */ - orp = &or_state; - - if (orp->or_mode != OR_M_ENABLED) - return; - if (!orp->or_got_int) - return; - orp->or_got_int = 0; - assert (orp->or_flags & OR_F_ENABLED); - or_check_ints (orp); - +static void or_other(const message *m_ptr, int ipc_status) +{ + if (is_ipc_notify(ipc_status) && m_ptr->m_source == TTY_PROC_NR) + or_dump(); } /***************************************************************************** - * do_hard_int * + * or_stop * + * * + * Stop the card * + *****************************************************************************/ +static void or_stop(void) +{ + t_or *orp; + + orp = &or_state; + + /* TODO: send a signal to the card to shut it down */ +} + +/***************************************************************************** + * or_intr * * * * Process the interrupts which the card generated * *****************************************************************************/ -static void do_hard_int(void) +static void or_intr(unsigned int __unused mask) { + t_or *orp; int s; + orp = &or_state; + /* Run interrupt handler at driver level. */ - or_handler(&or_state); + or_handler(orp); /* Reenable interrupts for this hook. */ - if ((s=sys_irqenable(&or_state.or_hook_id)) != OK) { - printf("orinoco: error, couldn't enable"); - printf(" interrupts: %d\n", s); - } + if ((s=sys_irqenable(&orp->or_hook_id)) != OK) + printf("orinoco: error, couldn't enable interrupts: %d\n", s); + + /* Perform tasks based on the flagged conditions. */ + or_check_ints(orp); } /***************************************************************************** @@ -342,42 +206,36 @@ static void do_hard_int(void) * Sometime the card gets screwed, behaving erratically. Solution: reset the * * card. This is actually largely redoing the initialization * *****************************************************************************/ -static void or_reset() { - static clock_t last_reset, now; +static void or_reset(void) +{ + static clock_t last_reset, now; t_or *orp; int i, r; if (OK != (r = getticks(&now))) panic("orinoco: getuptime() failed: %d", r); - if(now - last_reset < system_hz * 10) { + if(now - last_reset < sys_hz() * 10) { printf("Resetting card too often. Going to reset driver\n"); exit(1); } last_reset = now; - + orp = &or_state; - if(orp->or_mode == OR_M_DISABLED) - printf("orinoco instance %d is disabled\n", or_instance); - - if(orp->or_mode != OR_M_ENABLED) { - return; - } - - orp->or_need_reset = 0; - or_init_hw(orp); + orp->or_need_reset = FALSE; + or_init_hw(orp, NULL); orp->rx_last = orp->rx_first = 0; for(i = 0; i < NR_RX_BUFS; i++) { orp->rx_length[0] = 0; } - if(orp->or_flags & OR_F_SEND_AVAIL) { - orp->or_tx.ret_busy = FALSE; - orp->or_send_int = TRUE; - } + if (orp->or_tx.ret_busy) + orp->or_tx_busy--; + orp->or_tx.ret_busy = FALSE; + orp->or_send_int = TRUE; } /***************************************************************************** @@ -386,24 +244,17 @@ static void or_reset() { * Dump interesting information about the card on F-key pressed. * * Not implemented yet * *****************************************************************************/ -static void or_dump (message *m) - { +static void or_dump(void) +{ t_or *orp; int sfkeys; orp = &or_state; - if(orp->or_mode == OR_M_DISABLED) { - printf("%s is disabled\n", orp->or_name); - } - - if(orp->or_mode != OR_M_ENABLED) - return; - if(OK != fkey_events(NULL, &sfkeys)) { printf("Contacting the TTY failed\n"); } - + if(bit_isset(sfkeys, 11)) { print_linkstatus(orp, orp->last_linkstatus); } @@ -412,88 +263,34 @@ static void or_dump (message *m) /***************************************************************************** * or_init * * * - * The main initialization function, called when a DL_INIT message comes in. * + * The main initialization function, called at startup. * *****************************************************************************/ -static void or_init (message * mp) { +static int or_init(unsigned int instance, ether_addr_t *addr) +{ + int fkeys, sfkeys, r; t_or *orp; - message reply; - static int first_time = 1; - - if (first_time) { - first_time = 0; - or_pci_conf (); /* Configure PCI devices. */ - - /* Use a synchronous alarm instead of a watchdog timer. */ - sys_setalarm(system_hz, 0); - } orp = &or_state; - if (orp->or_mode == OR_M_DISABLED) { - /* Initialize the orp structure */ - or_init_struct (orp); - if (orp->or_mode == OR_M_DISABLED) { - reply.m_type = DL_CONF_REPLY; - reply.m_netdrv_net_dl_conf.stat = ENXIO; - mess_reply (mp, &reply); - return; - } - if (orp->or_mode == OR_M_ENABLED) { - /* initialize card, hardware/firmware */ - orp->or_flags |= OR_F_ENABLED; - or_init_hw (orp); - } - } + /* Initialize the orp structure */ + or_init_struct(orp, instance); - assert (orp->or_mode == OR_M_ENABLED); - assert (orp->or_flags & OR_F_ENABLED); - - /* Not supported by the driver yet, but set a couple of options: - * multicasting, promiscuity, broadcasting, depending on the users - * needs */ - orp->or_flags &= ~(OR_F_PROMISC | OR_F_MULTI | OR_F_BROAD); - if (mp->m_net_netdrv_dl_conf.mode & DL_PROMISC_REQ) - orp->or_flags |= OR_F_PROMISC; - if (mp->m_net_netdrv_dl_conf.mode & DL_MULTI_REQ) - orp->or_flags |= OR_F_MULTI; - if (mp->m_net_netdrv_dl_conf.mode & DL_BROAD_REQ) - orp->or_flags |= OR_F_BROAD; - - or_rec_mode (orp); - - /* reply the caller that the configuration succeeded */ - reply.m_type = DL_CONF_REPLY; - reply.m_netdrv_net_dl_conf.stat = OK; - memcpy(reply.m_netdrv_net_dl_conf.hw_addr, orp->or_address.ea_addr, - sizeof(reply.m_netdrv_net_dl_conf.hw_addr)); - mess_reply (mp, &reply); -} - -/***************************************************************************** - * or_pci_conf * - * * - * Configure the pci related issues of the card, e.g. finding out where the * - * card is in the pci configuration, it's assigned irq, etc. This can be * - * done if the boot monitor is provided with information, or the pci bus * - * can be searched (at the end: or_probe function) * - *****************************************************************************/ -static void or_pci_conf () { - t_or *orp; - - /* extract information from the boot monitor about the pci - * configuration if provided */ - orp = &or_state; - - strncpy (orp->or_name, OR_NAME, sizeof(OR_NAME)); - orp->or_name[sizeof(OR_NAME) - 2] = or_instance + '0'; - orp->or_seen = FALSE; - - /* Initialize the pci bus, bridges and cards, if not yet done */ - pci_init (); - /* Try to find out where the card is in the pci bus */ - if (or_probe (orp, or_instance)) - orp->or_seen = TRUE; + if (!or_probe(orp, instance)) + return ENXIO; + + /* initialize card, hardware/firmware */ + or_init_hw(orp, addr); + + /* Use a synchronous alarm instead of a watchdog timer. */ + sys_setalarm(sys_hz(), 0); + + /* Observe some function key for debug dumps. */ + fkeys = sfkeys = 0; bit_set(sfkeys, 11); + if ((r=fkey_map(&fkeys, &sfkeys)) != OK) + printf("Warning: orinoco couldn't observe F-key(s): %d\n",r); + + return OK; } /***************************************************************************** @@ -502,7 +299,7 @@ static void or_pci_conf () { * Try to find the card based on information provided by pci and get irq and * * bar * *****************************************************************************/ -static int or_probe (t_or * orp, int skip) +static int or_probe(t_or * orp, unsigned int skip) { u8_t ilr; u32_t bar; @@ -510,30 +307,31 @@ static int or_probe (t_or * orp, int skip) u16_t vid, did; int r, devind; + pci_init(); + /* Start looking from the beginning */ - r = pci_first_dev (&devind, &vid, &did); + r = pci_first_dev(&devind, &vid, &did); if (r == 0) - return (0); + return FALSE; /* Skip as many instances as requested */ while (skip--) { - r = pci_next_dev (&devind, &vid, &did); + r = pci_next_dev(&devind, &vid, &did); if (!r) - return (0); + return FALSE; } /* Get the name as advertised by pci */ - dname = pci_dev_name (vid, did); + dname = pci_dev_name(vid, did); if (!dname) dname = "unknown device"; - printf ("%s: %s (%04x/%04x) at %s\n", - orp->or_name, dname, vid, did, pci_slot_name (devind)); + printf("%s: %s (%04x/%04x) at %s\n", + orp->or_name, dname, vid, did, pci_slot_name(devind)); - pci_reserve (devind); + pci_reserve(devind); - orp->devind = devind; /* Get the irq */ - ilr = pci_attr_r8 (devind, PCI_ILR); + ilr = pci_attr_r8(devind, PCI_ILR); orp->or_irq = ilr; /* Map registers into memory */ @@ -546,15 +344,14 @@ static int or_probe (t_or * orp, int skip) return TRUE; } - /***************************************************************************** * or_get_bar * * * - * Get the base address from pci (from Base Address Register) and find out * + * Get the base address from pci (from Base Address Register) and find out * * whether the card is memory mapped or in I/O space. Currently, only * * memmory mapped is supported. * *****************************************************************************/ -static u32_t or_get_bar (int devind, t_or * orp) +static u32_t or_get_bar(int devind, t_or * orp) { u32_t bar; int is_iospace; @@ -562,11 +359,11 @@ static u32_t or_get_bar (int devind, t_or * orp) /* bit 1 off the PCI_BAR register indicates whether the cards registers * are mapped in io-space or shared memory */ - is_iospace = pci_attr_r32 (devind, PCI_BAR) & 1; + is_iospace = pci_attr_r32(devind, PCI_BAR) & 1; if (is_iospace) { /* read where the base address is in I/O space */ - bar = pci_attr_r32 (devind, PCI_BAR) & 0xffffffe0; + bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; if ((bar & 0x3ff) >= 0x100 - 32 || bar < 0x400) panic("base address isn't properly configured"); @@ -576,33 +373,32 @@ static u32_t or_get_bar (int devind, t_or * orp) hermes_struct_init (hw, bar, is_iospace, HERMES_16BIT_REGSPACING); - if (debug) { - printf ("%s: using I/O space address 0x%x, IRQ %d\n", - orp->or_name, bar, orp->or_irq); - } +#if VERBOSE + printf ("%s: using I/O space address 0x%x, IRQ %d\n", + orp->or_name, bar, orp->or_irq); +#endif panic("Not implemented yet"); - /* Although we are able to find the desired bar and irq for an - * I/O spaced card, we haven't implemented the right register + /* Although we are able to find the desired bar and irq for an + * I/O spaced card, we haven't implemented the right register * accessing functions. This wouldn't be difficult, but we were * not able to test them. Therefore, give an alert here */ return bar; } else { /* read where the base address is in shared memory */ - bar = pci_attr_r32 (devind, PCI_BAR) & 0xfffffff0; + bar = pci_attr_r32(devind, PCI_BAR) & 0xfffffff0; /* maybe some checking whether the address is legal... */ - /* Memory mapped registers are 2 bytes wide, aligned on 4 + /* Memory mapped registers are 2 bytes wide, aligned on 4 * bytes */ hermes_struct_init (hw, bar, is_iospace, HERMES_32BIT_REGSPACING); - if (debug){ - printf ("%s: using shared memory address", - orp->or_name); - printf (" 0x%x, IRQ %d\n", bar, orp->or_irq); - } +#if VERBOSE + printf ("%s: using shared memory address", orp->or_name); + printf (" 0x%x, IRQ %d\n", bar, orp->or_irq); +#endif return bar; @@ -614,62 +410,44 @@ static u32_t or_get_bar (int devind, t_or * orp) * * * Set the orinoco structure to default values * *****************************************************************************/ -static void or_init_struct (t_or * orp) +static void or_init_struct(t_or * orp, unsigned int instance) { - int i = 0; - static eth_stat_t empty_stat = { 0, 0, 0, 0, 0, 0 }; + int i; - orp->or_mode = OR_M_DISABLED; + memset(orp, 0, sizeof(*orp)); - if (orp->or_seen) - orp->or_mode = OR_M_ENABLED; + strlcpy(orp->or_name, OR_NAME, sizeof(orp->or_name)); + orp->or_name[sizeof(OR_NAME) - 2] = instance + '0'; - if (orp->or_mode != OR_M_ENABLED) - return; - - orp->or_got_int = 0; orp->or_link_up = -1; - orp->or_send_int = 0; - orp->or_clear_rx = 0; - orp->or_tx_alive = 0; - orp->or_need_reset = 0; - orp->or_read_s = 0; - orp->or_tx_head = 0; - orp->or_tx_tail = 0; - orp->connected = 0; - - orp->or_tx.ret_busy = FALSE; orp->or_tx.or_txfid = NO_FID; for(i = 0; i < NR_RX_BUFS; i++) { orp->rxfid[i] = NO_FID; orp->rx_length[i] = 0; } - orp->rx_current = 0; - orp->rx_first = 0; - orp->rx_last = 0; - - orp->or_stat = empty_stat; - orp->or_flags = OR_F_EMPTY; /* Keep an administration in the driver whether the internal buffer is in use. That's what ret_busy is for */ orp->or_tx.ret_busy = FALSE; + orp->or_tx_busy = 0; orp->or_nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN; - } /***************************************************************************** * or_init_hw * * * * Initialize hardware and prepare for intercepting the interrupts. At the * - * end, the card is up and running * + * end, the card is up and running. May be called multiple times. * *****************************************************************************/ -static void or_init_hw (t_or * orp) +static void or_init_hw(t_or * orp, ether_addr_t * addr) { - int i, err, s; +#if VERBOSE + int i; +#endif + int err, s; hermes_t *hw = &(orp->hw); static int first_time = TRUE; @@ -683,19 +461,19 @@ static void or_init_hw (t_or * orp) printf ("error value of hermes_init(): %d\n", err); } - /* Get the MAC address (which is a data item in the card)*/ - or_readrids (hw, orp); + if (first_time) { + /* Get the MAC address (which is a data item in the card)*/ + or_readrids(hw, orp, addr); + } /* Write a few rids to the card, e.g. WEP key*/ or_writerids (hw, orp); - if (debug) { - printf ("%s: Ethernet address ", orp->or_name); - for (i = 0; i < 6; i++) { - printf ("%x%c", orp->or_address.ea_addr[i], - i < 5 ? ':' : '\n'); - } - } +#if VERBOSE + printf ("%s: Ethernet address ", orp->or_name); + for (i = 0; i < 6; i++) + printf("%x%c", addr->ea_addr[i], i < 5 ? ':' : '\n'); +#endif /* Prepare internal TX buffer in the card */ err = hermes_allocate (hw, @@ -708,8 +486,8 @@ static void or_init_hw (t_or * orp) /* Establish event handle */ if(first_time) { - orp->or_hook_id = orp->or_irq; - if ((s=sys_irqsetpolicy(orp->or_irq, 0, + orp->or_hook_id = orp->or_irq; + if ((s=sys_irqsetpolicy(orp->or_irq, 0, &orp->or_hook_id)) != OK) printf("orinoco: couldn't set IRQ policy: %d\n", s); @@ -723,12 +501,10 @@ static void or_init_hw (t_or * orp) /* Enable operation */ err = hermes_docmd_wait (hw, HERMES_CMD_ENABLE, 0, NULL); - if (err) { - printf ("%s: Error %d enabling MAC port\n", orp->or_name, err); - } + if (err) + printf("%s: Error %d enabling MAC port\n", orp->or_name, err); } - /***************************************************************************** * or_readrids * * * @@ -736,17 +512,17 @@ static void or_init_hw (t_or * orp) * is a data item in the firmware, some configuration variable. * * In our case, we are mostly interested in the MAC address for now * *****************************************************************************/ - -static void or_readrids (hermes_t * hw, t_or * orp) +static void or_readrids(hermes_t * hw, t_or * orp, ether_addr_t * addr) { - /* Read the MAC address */ - int err = hermes_read_ltv (hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, - ETH_ALEN, NULL, &orp->or_address); - if (err) { - printf ("%s: failed to read MAC address!\n", orp->or_name); - return; - } + int err; + assert(addr != NULL); + + /* Read the MAC address */ + err = hermes_read_ltv (hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, + ETH_ALEN, NULL, addr); + if (err) + printf("%s: failed to read MAC address!\n", orp->or_name); } /***************************************************************************** @@ -755,18 +531,15 @@ static void or_readrids (hermes_t * hw, t_or * orp) * Write some default rids to the card. A rid (resource identifier) * * is a data item in the firmware, some configuration variable, e.g. WEP key * *****************************************************************************/ -static void or_writerids (hermes_t * hw, t_or * orp) +static void or_writerids(hermes_t * hw, t_or * orp) { int err; struct hermes_idstring idbuf; - u16_t port_type; static char essid[IW_ESSID_MAX_SIZE + 1]; static char wepkey0[LARGE_KEY_LENGTH + 1]; /* Set the MAC port */ - port_type = 1; - err = hermes_write_wordrec (hw, USER_BAP, HERMES_RID_CNFPORTTYPE, - port_type); + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, 1); if (err) { printf ("%s: Error %d setting port type\n", orp->or_name, err); return; @@ -790,7 +563,7 @@ static void or_writerids (hermes_t * hw, t_or * orp) HERMES_BYTES_TO_RECLEN (strlen (essid) + 2), &idbuf); if (err) { - printf ("%s: Error %d setting DESIREDSSID\n", + printf ("%s: Error %d setting DESIREDSSID\n", orp->or_name, err); return; } @@ -821,7 +594,8 @@ static void or_writerids (hermes_t * hw, t_or * orp) * It appears that there is a severe bug in setting up WEP. If the driver * * doesnt function properly, please turn WEP off. * *****************************************************************************/ -static void setup_wepkey(t_or *orp, char *wepkey0) { +static void setup_wepkey(t_or *orp, char *wepkey0) +{ int default_key = 0, err = 0; hermes_t *hw = &(orp->hw); @@ -830,40 +604,30 @@ static void setup_wepkey(t_or *orp, char *wepkey0) { default_key); if (err) printf ("%s: Error %d setting the default WEP-key entry\n", - orp->or_name, err); - - err = hermes_write_ltv (hw, USER_BAP, + orp->or_name, err); + + err = hermes_write_ltv (hw, USER_BAP, HERMES_RID_CNFDEFAULTKEY0, HERMES_BYTES_TO_RECLEN(LARGE_KEY_LENGTH), wepkey0); - if (err) + if (err) printf ("%s: Error %d setting the WEP-key0\n", - orp->or_name, err); - - err = hermes_write_wordrec (hw, USER_BAP, + orp->or_name, err); + + err = hermes_write_wordrec (hw, USER_BAP, HERMES_RID_CNFAUTHENTICATION, HERMES_AUTH_OPEN); if (err) printf ("%s: Error %d setting the authentication flag\n", - orp->or_name, err); + orp->or_name, err); - err = hermes_write_wordrec (hw, USER_BAP, + err = hermes_write_wordrec (hw, USER_BAP, HERMES_RID_CNFWEPFLAGS_INTERSIL, HERMES_WEP_PRIVACY_INVOKED); if (err) printf ("%s: Error %d setting the master wep setting flag\n", - orp->or_name, err); - -} + orp->or_name, err); - -/***************************************************************************** - * or_rec_mode * - * * - * Set the desired receive mode, e.g. promiscuous mode. Not implemented yet * - *****************************************************************************/ -static void or_rec_mode (t_or * orp) { - /* TODO */ } /***************************************************************************** @@ -873,12 +637,12 @@ static void or_rec_mode (t_or * orp) { * like EV_INFO and EV_RX have to be handled before an acknowledgement for * * the event is returned to the card. See also the documentation * *****************************************************************************/ -static void or_handler (t_or *orp) +static void or_handler(t_or *orp) { int length; u16_t evstat, events, fid; hermes_t *hw = &(orp->hw); - + beginning: /* Retrieve which kind of event happened */ evstat = hermes_read_reg (hw, HERMES_EVSTAT); @@ -903,8 +667,8 @@ beginning: if (events & HERMES_EV_INFDROP) { events &= ~(HERMES_EV_INFDROP); } - - /* This AP-only event will be asserted at the beacon interval prior to + + /* This AP-only event will be asserted at the beacon interval prior to the DTIM interval */ if (events & HERMES_EV_DTIM) { events &= ~(HERMES_EV_DTIM); @@ -918,7 +682,6 @@ beginning: /* Occurs when the asynchronous transmission process is unsuccessfully completed */ if (events & HERMES_EV_TXEXC) { - /* What buffer generated the event? Represented by an fid */ fid = hermes_read_reg(hw, HERMES_TXCOMPLFID); if(fid == 0xFFFF) { @@ -926,20 +689,17 @@ beginning: printf("unexpected txexc_fid interrupted\n"); } + if (orp->or_tx.ret_busy) + orp->or_tx_busy--; orp->or_tx.ret_busy = FALSE; - if(orp->or_flags & OR_F_SEND_AVAIL) { - orp->or_send_int = TRUE; - if (!orp->or_got_int){ - orp->or_got_int = TRUE; - int_event_check = TRUE; - } - } + orp->or_send_int = TRUE; + orp->or_got_int = TRUE; /* To detect illegal fids */ hermes_write_reg(hw, HERMES_TXCOMPLFID, 0xFFFF); events &= ~(HERMES_EV_TXEXC); - /* We don't do anything else yet. + /* We don't do anything else yet. * Could be used for statistics */ } @@ -954,15 +714,13 @@ beginning: printf("unexpected tx_fid interrupted\n"); } + if (orp->or_tx.ret_busy) + orp->or_tx_busy--; orp->or_tx.ret_busy = FALSE; - if(orp->or_flags & OR_F_SEND_AVAIL) { - orp->or_send_int = TRUE; - if (!orp->or_got_int){ - orp->or_got_int = TRUE; - int_event_check = TRUE; - } - } + orp->or_send_int = TRUE; + orp->or_got_int = TRUE; + orp->or_tx_alive = TRUE; /* To detect illegal fids */ hermes_write_reg(hw, HERMES_TXCOMPLFID, 0xFFFF); @@ -983,37 +741,35 @@ beginning: if (fid == 0xFFFF){ /* An illegal frame identifier is found. Ignore */ printf("Allocate event on unexpected fid\n"); - return ; + goto next; } /* To be able to detect illegal fids */ hermes_write_reg(hw, HERMES_ALLOCFID, 0xFFFF); - + events &= ~(HERMES_EV_ALLOC); } - - /* Occurs when a frame is received by the asynchronous reception - * process */ - + /* Occurs when a frame is received */ if (events & HERMES_EV_RX) { - orp->or_ev_rx = TRUE; events &= ~(HERMES_EV_RX); - /* If the last buffer is still filled with data, then we don't + /* If the last buffer is still filled with data, then we don't * have any buffers available to store the data */ if(orp->rx_length[orp->rx_last] != 0) { /* indeed, we are going to overwrite information - * in a buffer */ + * in a buffer + */ } /* Which buffer is storing the data (represented by a fid) */ orp->rxfid[orp->rx_last] = hermes_read_reg (hw, HERMES_RXFID); - /* Get the packet from the card and store it in - * orp->rx_buf[orp->rx_last]. The length is returned by this - * function */ + /* Get the packet from the card and store it in + * orp->rx_buf[orp->rx_last]. The length is returned by this + * function + */ length = or_get_recvd_packet(orp, orp->rxfid[orp->rx_last], (orp->rx_buf[orp->rx_last])); @@ -1029,17 +785,14 @@ beginning: orp->rx_last++; orp->rx_last %= NR_RX_BUFS; - if (!orp->or_got_int){ - orp->or_got_int = TRUE; - } - int_event_check = TRUE; + orp->or_got_int = TRUE; } next: - if (events) { + if (events) { printf("Unknown event: 0x%x\n", events); } - /* Acknowledge to the card that the events have been processed. After + /* Acknowledge to the card that the events have been processed. After * this the card will assume we have processed any buffer which were in * use for this event. */ hermes_write_reg (hw, HERMES_EVACK, evstat); @@ -1050,26 +803,22 @@ next: } } - /***************************************************************************** - * or_watchdog_f * + * or_alarm * * * * Will be called regularly to see whether the driver has crashed. If that * * condition is detected, reset the driver and card * *****************************************************************************/ -static void or_watchdog_f(minix_timer_t *tp) +static void or_alarm(clock_t __unused stamp) { t_or *orp; - + /* Use a synchronous alarm instead of a watchdog timer. */ - sys_setalarm(system_hz, 0); + sys_setalarm(sys_hz(), 0); orp = &or_state; - if (orp->or_mode != OR_M_ENABLED) - return; - - if (!(orp->or_flags & OR_F_SEND_AVAIL)) { + if (orp->or_tx_busy == 0) { /* Assume that an idle system is alive */ orp->or_tx_alive= TRUE; return; @@ -1083,39 +832,28 @@ static void or_watchdog_f(minix_timer_t *tp) orp->or_tx_alive= FALSE; return; } - - printf("or_watchdog_f: resetting instance %d\n", or_instance); - + + printf("or_alarm: resetting card\n"); + orp->or_need_reset= TRUE; orp->or_got_int= TRUE; - check_int_events(); + or_check_ints(orp); } /***************************************************************************** - * mess_reply * - *****************************************************************************/ -static void mess_reply (message * req, message * reply_mess) -{ - if (ipc_send(req->m_source, reply_mess) != 0) - panic("orinoco: unable to mess_reply"); - -} - -/***************************************************************************** - * or_writev_s * + * or_send * * * - * Write data which is denoted by the message to the card and send it. * + * Send a packet, if possible * *****************************************************************************/ -static void or_writev_s (message * mp, int from_int) { - int count, size, err, data_len, data_off; - int o, j, n, i, s, p, cps ; +static int or_send(struct netdriver_data *data, size_t size) +{ + size_t p, data_len, data_off; + int err; struct ethhdr *eh; t_or *orp; hermes_t *hw; struct hermes_tx_descriptor desc; - int iov_offset = 0; struct header_struct hdr; - iovec_s_t *iovp; u16_t txfid; /* We need space for the max packet size itself, plus an ethernet @@ -1124,120 +862,72 @@ static void or_writev_s (message * mp, int from_int) { * packets from the card, which has an IO granularity of 16 * bits */ static u8_t databuf[IEEE802_11_DATA_LEN + ETH_HLEN + 2 + 1]; - memset (databuf, 0, IEEE802_11_DATA_LEN + ETH_HLEN + 3); orp = &or_state; - - count = mp->m_net_netdrv_dl_writev_s.count; - - orp->or_client = mp->m_source; hw = &(orp->hw); /* Switch off interrupts. The card is accessable via 2 BAPs, one for - * reading and one for writing. In theory these BAPs should be + * reading and one for writing. In theory these BAPs should be * independent, but in practice, the are not. By switching off the * interrupts of the card, the chances of one interfering with the - * other should be less */ - if (from_int){ - /* We were called with from_int, meaning that the last time we - * were called, no tx buffers were available, and we had to - * suspend. Now, we'll try again to find an empty buffer in the - * card */ - assert (orp->or_flags & OR_F_SEND_AVAIL); - orp->or_flags &= ~OR_F_SEND_AVAIL; - orp->or_send_int = FALSE; - orp->or_tx_alive = TRUE; - } + * other should be less + */ + /* ..except that this is not happening at all here. */ txfid = orp->or_tx.or_txfid; if (orp->or_tx.ret_busy || orp->connected == 0) { /* there is no buffer in the card available */ - assert(!(orp->or_flags & OR_F_SEND_AVAIL)); - /* Remember that there is a packet to be sent available */ - orp->or_flags |= OR_F_SEND_AVAIL; - goto suspend_write_s; + return SUSPEND; } - assert (orp->or_mode == OR_M_ENABLED); - assert (orp->or_flags & OR_F_ENABLED); + /* Copy the data to be sent from the vector to the databuf */ + netdriver_copyin(data, 0, databuf, size); + /* Zero out the rest of the buffer */ + memset(&databuf[size], 0, sizeof(databuf) - size); - /* Copy the data to be send from the vector to the databuf */ - size = 0; - o = 0; - for (i = 0; i < count; i += IOVEC_NR, - iov_offset += IOVEC_NR * sizeof (orp->or_iovec_s[0])) { - - n = IOVEC_NR; - if (i + n > count) - n = count - i; - - cps = sys_safecopyfrom(mp->m_source, - mp->m_net_netdrv_dl_writev_s.grant, iov_offset, - (vir_bytes) orp->or_iovec_s, - n * sizeof(orp->or_iovec_s[0])); - if (cps != OK) - printf("orinoco: sys_safecopyfrom failed: %d\n", cps); - - for (j = 0, iovp = orp->or_iovec_s; j < n; j++, iovp++) { - s = iovp->iov_size; - if (size + s > ETH_MAX_PACK_SIZE_TAGGED) { - printf("Orinoco: invalid pkt size\n"); - } - - cps = sys_safecopyfrom(mp->m_source, iovp->iov_grant, - 0, (vir_bytes) databuf + o, s); - if (cps != OK) - printf("orinoco: sys_safecopyfrom failed:%d\n", - cps); - - size += s; - o += s; - } - } - - assert(size >= ETH_MIN_PACK_SIZE); - - memset (&desc, 0, sizeof (desc)); - /* Reclaim the tx buffer once the data is sent (OK), or it is clear - * that transmission failed (EX). Reclaiming means that we can reuse - * the buffer again for transmission */ + memset(&desc, 0, sizeof(desc)); + /* Reclaim the tx buffer once the data is sent (OK), or it is clear + * that transmission failed (EX). Reclaiming means that we can reuse + * the buffer again for transmission + */ desc.tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; - /* Actually, this reclaim bit is the only thing which needs to be set - * in the descriptor */ - err = hermes_bap_pwrite (hw, USER_BAP, &desc, sizeof (desc), txfid, - 0); + /* Actually, this reclaim bit is the only thing which needs to be set + * in the descriptor + */ + err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0); if (err) { printf("hermes_bap_pwrite() descriptor error:resetting card\n"); - /* When this happens, the card is quite confused: it will not - * recover. Reset it */ + /* When this happens, the card is quite confused: it will not + * recover. Reset it + */ or_reset(); - goto fail; + return OK; /* pretend the packet was sent anyway.. */ } eh = (struct ethhdr *) databuf; /* Encapsulate Ethernet-II frames */ - if (ntohs (eh->h_proto) > 1500) { + if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */ data_len = size - ETH_HLEN; data_off = HERMES_802_3_OFFSET + sizeof (hdr); /* 802.3 header */ - memcpy (hdr.dest, eh->h_dest, ETH_ALEN); - memcpy (hdr.src, eh->h_src, ETH_ALEN); - hdr.len = htons (data_len + ENCAPS_OVERHEAD); + memcpy(hdr.dest, eh->h_dest, ETH_ALEN); + memcpy(hdr.src, eh->h_src, ETH_ALEN); + hdr.len = htons(data_len + ENCAPS_OVERHEAD); /* 802.2 header */ - memcpy (&hdr.dsap, &encaps_hdr, sizeof (encaps_hdr)); + memcpy(&hdr.dsap, &encaps_hdr, sizeof (encaps_hdr)); hdr.ethertype = eh->h_proto; - err = hermes_bap_pwrite (hw, USER_BAP, &hdr, sizeof (hdr), + err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), txfid, HERMES_802_3_OFFSET); if (err) { - printf ("%s: Error %d writing packet header to BAP\n", + printf("%s: Error %d writing packet header to BAP\n", orp->or_name, err); - goto fail; + return OK; /* pretend the packet was sent anyway.. */ } p = ETH_HLEN; @@ -1249,86 +939,44 @@ static void or_writev_s (message * mp, int from_int) { } /* Round up for odd length packets */ - err = hermes_bap_pwrite (hw, USER_BAP, - (void *) &(databuf[p]), RUP_EVEN (data_len), - txfid, data_off); + err = hermes_bap_pwrite(hw, USER_BAP, (void *) &(databuf[p]), + RUP_EVEN(data_len), txfid, data_off); if (err) { - printf ("hermes_bap_pwrite(data): error %d\n", err); - goto fail; + printf("hermes_bap_pwrite(data): error %d\n", err); + return OK; /* pretend the packet was sent anyway.. */ } - /* this should be before the docmd_wait. Cause otherwise the bit can - be cleared in the handler (if irq's not off) before it is set - and then 1 reset (ret_busy=false) is lost */ + /* this should be before the docmd_wait. Cause otherwise the bit can + * be cleared in the handler (if irq's not off) before it is set + * and then 1 reset (ret_busy=false) is lost + */ orp->or_tx.ret_busy = TRUE; + orp->or_tx_busy++; /* Send the packet which was constructed in txfid */ err = hermes_docmd_wait (hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, NULL); if (err) { - printf ("hermes_docmd_wait(TX|RECL): error %d\n", err); + printf("hermes_docmd_wait(TX|RECL): error %d\n", err); /* Mark the buffer as available again */ orp->or_tx.ret_busy = FALSE; - goto fail; - } - -fail: - /* If the interrupt handler called, don't send a reply. The reply - * will be sent after all interrupts are handled. - */ - orp->or_flags |= OR_F_PACK_SENT; - - if (from_int) { - return; + orp->or_tx_busy--; + return OK; /* pretend the packet was sent anyway.. */ } - reply (orp); - return; - -suspend_write_s: - orp->or_tx_mess = *mp; - - reply (orp); - return; + return OK; } - -/***************************************************************************** - * reply * - * * - * Send a message back to the caller, informing it about the data received * - * or sent * - *****************************************************************************/ -static void reply (t_or * orp) { - message reply; - int flags = DL_NOFLAGS, r; - - if (orp->or_flags & OR_F_PACK_SENT) - flags |= DL_PACK_SEND; - if (orp->or_flags & OR_F_PACK_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 = orp->or_read_s; - - r = ipc_send(orp->or_client, &reply); - - if (r < 0) - panic("orinoco: send failed: %d", r); - - orp->or_read_s = 0; - orp->or_flags &= ~(OR_F_PACK_SENT | OR_F_PACK_RECV); -} - - /***************************************************************************** * or_ev_info * * * * Process information which comes in from the card * *****************************************************************************/ -static void or_ev_info (t_or * orp) +static void or_ev_info(t_or * orp) { + struct hermes_tallies_frame tallies; + struct hermes_linkstatus linkstatus; + u16_t newstatus; u16_t infofid; int err, len, type; hermes_t *hw = &orp->hw; @@ -1352,67 +1000,48 @@ static void or_ev_info (t_or * orp) switch (type) { case HERMES_INQ_TALLIES: - { - struct hermes_tallies_frame tallies; - - if (len > sizeof (tallies)) { - printf ("%s: Tallies frame too long ", - orp->or_name); - printf ("(%d bytes)\n", len); - len = sizeof (tallies); - } - hermes_read_words (hw, HERMES_DATA1, - (void *) &tallies, len / 2); - /* TODO: do something with the tallies structure */ + if (len > sizeof(tallies)) { + printf("%s: Tallies frame too long ", orp->or_name); + printf("(%d bytes)\n", len); + len = sizeof (tallies); } + hermes_read_words(hw, HERMES_DATA1, (void *)&tallies, len / 2); + /* TODO: do something with the tallies structure */ break; - case HERMES_INQ_LINKSTATUS: { - u16_t newstatus; - struct hermes_linkstatus linkstatus; + case HERMES_INQ_LINKSTATUS: + if (len != sizeof(linkstatus)) { + printf("%s: Unexpected size for linkstatus ", + orp->or_name); + printf("frame (%d bytes)\n", len); + } - if (len != sizeof (linkstatus)) { - printf ("%s: Unexpected size for linkstatus ", - orp->or_name); - printf ("frame (%d bytes)\n", len); - } + hermes_read_words(hw, HERMES_DATA1, (void *)&linkstatus, + len / 2); + newstatus = linkstatus.linkstatus; - hermes_read_words (hw, HERMES_DATA1, - (void *) &linkstatus, len / 2); - newstatus = linkstatus.linkstatus; - - if ((newstatus == HERMES_LINKSTATUS_CONNECTED) - || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) - || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE)) { - orp->connected = 1; - - if(orp->or_flags & OR_F_SEND_AVAIL) { - orp->or_send_int = TRUE; + if ((newstatus == HERMES_LINKSTATUS_CONNECTED) + || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) + || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE)) { + orp->connected = 1; + orp->or_send_int = TRUE; orp->or_got_int = TRUE; - int_event_check = TRUE; + } + else if ((newstatus == HERMES_LINKSTATUS_NOT_CONNECTED) + || (newstatus == HERMES_LINKSTATUS_DISCONNECTED) + || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE) + || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED)) { + orp->connected = 0; } + if (newstatus != orp->last_linkstatus) + print_linkstatus(orp, newstatus); - } - else if ((newstatus == - HERMES_LINKSTATUS_NOT_CONNECTED) - || (newstatus == - HERMES_LINKSTATUS_DISCONNECTED) - || (newstatus == - HERMES_LINKSTATUS_AP_OUT_OF_RANGE) - || (newstatus == - HERMES_LINKSTATUS_ASSOC_FAILED)) { - orp->connected = 0; - } + orp->last_linkstatus = newstatus; - if (newstatus != orp->last_linkstatus) - print_linkstatus(orp, newstatus); - - orp->last_linkstatus = newstatus; - } break; default: - printf ("%s:Unknown information frame received(type %04x).\n", + printf("%s:Unknown information frame received (type %04x).\n", orp->or_name, type); break; } @@ -1423,7 +1052,8 @@ static void or_ev_info (t_or * orp) * * * Process information which comes in from the card * *****************************************************************************/ -static void print_linkstatus (t_or * orp, u16_t status) { +static void print_linkstatus(t_or * orp, u16_t status) +{ int err; u16_t d; char *s; @@ -1455,52 +1085,45 @@ static void print_linkstatus (t_or * orp, u16_t status) { s = "UNKNOWN"; } - printf ("%s: link status: %s, ", orp->or_name, s); + printf("%s: link status: %s, ", orp->or_name, s); - err = hermes_read_wordrec (hw, USER_BAP, - HERMES_RID_CURRENTCHANNEL, &d); + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &d); if (err) { - printf ("%s: Error %d \n", orp->or_name, err); + printf("error %d\n", err); return; } - printf("channel: %d, freq: %ld MHz ", - d, (channel_frequency[d-1])); - + printf("channel: %d, freq: %ld MHz\n", d, (channel_frequency[d-1])); } - /***************************************************************************** * or_check_ints * * * * Process events which have been postponed in the interrupt handler * *****************************************************************************/ -static void or_check_ints (t_or * orp) +static void or_check_ints(t_or * orp) { + if (!orp->or_got_int) + return; + orp->or_got_int = FALSE; + if (orp->or_need_reset) or_reset(); - if ((orp->rx_first!=orp->rx_last) && (orp->or_flags & OR_F_READING)) { - orp->or_ev_rx = 0; - or_readv_s (&orp->or_rx_mess, TRUE); - } - if (orp->or_send_int) { - or_writev_s (&orp->or_tx_mess, TRUE); - } + if (orp->rx_first != orp->rx_last) + netdriver_recv(); - if (orp->or_flags & (OR_F_PACK_SENT | OR_F_PACK_RECV)) { - reply (orp); - } + if (orp->or_send_int) + netdriver_send(); } - /***************************************************************************** * is_ethersnap * * * * is there an LLC and SNAP header in the ethernet packet? The inet task * * isn't very interested in it... * *****************************************************************************/ -static int is_ethersnap(struct header_struct *hdr) { - +static int is_ethersnap(struct header_struct *hdr) +{ /* We de-encapsulate all packets which, a) have SNAP headers * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header * and where b) the OUI of the SNAP header is 00:00:00 or @@ -1509,42 +1132,24 @@ static int is_ethersnap(struct header_struct *hdr) { return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0) && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) ); } - + /***************************************************************************** - * or_readv_s * + * or_recv * * * - * Copy the data which is stored in orp->rx_buf[orp->rx_first] in the vector * - * which was given with the message *mp * + * Receive a packet, if one is available * *****************************************************************************/ -static void or_readv_s (message * mp, int from_int) +static ssize_t or_recv(struct netdriver_data *data, size_t max) { - int i, j, n, o, s, count, size, cps; - int iov_offset = 0, length; t_or *orp; - iovec_s_t *iovp; u8_t *databuf; + size_t length; orp = &or_state; - orp->or_client = mp->m_source; - count = mp->m_net_netdrv_dl_readv_s.count; + if (orp->rx_first == orp->rx_last) + return SUSPEND; - assert (orp->or_mode == OR_M_ENABLED); - assert (orp->or_flags & OR_F_ENABLED); - - if (!from_int && (orp->rx_first==orp->rx_last)) - - { - /* if we are not called from a hard int (data is not yet available) and - * there are no buffers (or->rx_buf[x]) which contain any data, we cant - * copy any data to the inet server. Goto suspend, and wait for data - * to arrive */ - goto suspend_readv_s; - } - - - - /* and store the pointer to this data in databuf */ + /* store the pointer to this data in databuf */ databuf = &(orp->rx_buf[orp->rx_first][0]); length = orp->rx_length[orp->rx_first]; @@ -1555,94 +1160,36 @@ static void or_readv_s (message * mp, int from_int) orp->rx_first++; orp->rx_first %= NR_RX_BUFS; - o = 0; - /* The data which we want to be copied to the vector starts at - * *databuf and will be copied to the vecor below */ - size = 0; - for (i = 0; i < count; i += IOVEC_NR, - iov_offset += IOVEC_NR * sizeof(orp->or_iovec_s[0])) { - n = IOVEC_NR; - if (i + n > count) - n = count - i; + if (length > max) + length = max; - cps = sys_safecopyfrom(mp->m_source, - mp->m_net_netdrv_dl_readv_s.grant, iov_offset, - (vir_bytes)orp->or_iovec_s, - n * sizeof(orp->or_iovec_s[0])); - if (cps != OK) - panic("orinoco: warning: sys_safecopytp failed: %d", cps); - - for (j = 0, iovp = orp->or_iovec_s; j < n; j++, iovp++) { - s = iovp->iov_size; - if (size + s > length) { - assert (length > size); - s = length - size; - } - cps = sys_safecopyto(mp->m_source, iovp->iov_grant, 0, - (vir_bytes) databuf + o, s); - if (cps != OK) - panic("orinoco: warning: sys_safecopy failed: %d", cps); - - size += s; - if (size == length) - break; - o += s; - } - if (size == length) - break; - } - - assert(size >= length); + netdriver_copyout(data, 0, databuf, length); orp->or_stat.ets_packetR++; - orp->or_read_s = length; - orp->or_flags &= ~OR_F_READING; - orp->or_flags |= OR_F_PACK_RECV; - - if (!from_int) { - /* There was data in the orp->rx_buf[x] which is now copied to - * the inet sever. Tell the inet server */ - reply (orp); - } - - return; -suspend_readv_s: - if (from_int) { - assert (orp->or_flags & OR_F_READING); - /* No need to store any state */ - return; - } - - /* We want to store the message, so that next time when we are called - * by hard int, we know where to copy the received data */ - orp->or_rx_mess = *mp; - assert (!(orp->or_flags & OR_F_READING)); - orp->or_flags |= OR_F_READING; - - reply (orp); + return length; } - /***************************************************************************** * or_get_recvd_packet * * * * The card has received data. Retrieve the data from the card and put it * * in a buffer in the driver (in the orp structure) * *****************************************************************************/ -static int or_get_recvd_packet(t_or *orp, u16_t rxfid, u8_t *databuf) { +static int or_get_recvd_packet(t_or *orp, u16_t rxfid, u8_t *databuf) +{ struct hermes_rx_descriptor desc; hermes_t *hw; struct header_struct hdr; int err, length, offset; u16_t status; - + memset(databuf, 0, IEEE802_11_FRAME_LEN); hw = &(orp->hw); - /* Read the data from the buffer in the card which holds the data. - * First get the descriptor which will tell us whether the packet is + /* Read the data from the buffer in the card which holds the data. + * First get the descriptor which will tell us whether the packet is * healthy*/ err = hermes_bap_pread (hw, IRQ_BAP, &desc, sizeof (desc), rxfid, 0); if (err) { @@ -1679,7 +1226,7 @@ static int or_get_recvd_packet(t_or *orp, u16_t rxfid, u8_t *databuf) { } length = ntohs (hdr.len); - + /* Sanity checks */ if (length < 3) { /* No for even an 802.2 LLC header */ @@ -1711,50 +1258,29 @@ static int or_get_recvd_packet(t_or *orp, u16_t rxfid, u8_t *databuf) { return -1; } - /* Some types of firmware give us the SNAP and OUI headers. Remove these. + /* Some types of firmware give us the SNAP and OUI headers. Remove + * these. */ if (is_ethersnap(&hdr)) { length -= 8; - - memcpy (databuf + ETH_ALEN * 2, - databuf + sizeof(struct header_struct) - 2, + memcpy(databuf + ETH_ALEN * 2, + databuf + sizeof(struct header_struct) - 2, length - ETH_ALEN * 2); } if(length<60) length=60; - + return length; } /***************************************************************************** - * or_getstat_s * + * or_stat * * * * Return the statistics structure. The statistics aren't updated until now, * * so this won't return much interesting yet. * *****************************************************************************/ -static void or_getstat_s (message * mp) { - int r; - eth_stat_t stats; - t_or *orp; - - orp = &or_state; - - assert (orp->or_mode == OR_M_ENABLED); - assert (orp->or_flags & OR_F_ENABLED); - - stats = orp->or_stat; - - r = sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant, - 0, (vir_bytes) &stats, sizeof(stats)); - if(r != OK) { - panic("or_getstat_s: sys_safecopyto failed: %d", r); - } - - mp->m_type = DL_STAT_REPLY; - - r = ipc_send(mp->m_source, mp); - if(r != OK) - panic("orinoco: getstat_s failed: %d", r); +static void or_stat(eth_stat_t *stat) +{ + memcpy(stat, &or_state.or_stat, sizeof(*stat)); } - diff --git a/minix/drivers/net/orinoco/orinoco.h b/minix/drivers/net/orinoco/orinoco.h index a9ade97ad..97c38eb1c 100644 --- a/minix/drivers/net/orinoco/orinoco.h +++ b/minix/drivers/net/orinoco/orinoco.h @@ -26,73 +26,39 @@ typedef struct s_or { int or_irq; int or_hook_id; - int or_mode; - int or_flags; - char *or_model; - int or_client; int or_link_up; int or_got_int; int or_tx_alive; int or_send_int; - int or_clear_rx; int or_need_reset; int or_report_link; /* Events */ - int or_ev_rx; - int or_ev_tx; - int or_ev_info; - int or_ev_txexc; - int or_ev_alloc; int connected; - u16_t channel_mask; - u16_t channel; - u16_t ap_density; - u16_t rts_thresh; - int bitratemode; int last_linkstatus; - int max_data_len; - int port_type; /* Rx */ phys_bytes or_rx_buf; - vir_bytes or_read_s; u16_t rxfid[NR_RX_BUFS]; int rx_length[NR_RX_BUFS]; u8_t rx_buf[NR_RX_BUFS][IEEE802_11_FRAME_LEN]; - u8_t rx_offset[NR_RX_BUFS]; int rx_first; int rx_last; int rx_current; /* Tx */ u16_t or_nicbuf_size; - vir_bytes or_transm_s; int or_tx_head; int or_tx_tail; + int or_tx_busy; struct { int ret_busy; u16_t or_txfid; } or_tx; - u32_t or_ertxth; - /* PCI related */ - int or_seen; - int devind; - - /* 'large' items */ - irq_hook_t or_hook; eth_stat_t or_stat; - message or_rx_mess; - message or_tx_mess; - ether_addr_t or_address; - iovec_t or_iovec[IOVEC_NR]; - iovec_s_t or_iovec_s[IOVEC_NR]; - char or_name[sizeof (OR_NAME)]; + char or_name[sizeof(OR_NAME)]; hermes_t hw; - char nick[IW_ESSID_MAX_SIZE + 1]; - - } t_or;