]> Zhao Yanbai Git Server - minix.git/commitdiff
orinoco: use new libnetdriver 23/2923/1
authorDavid van Moolenbroek <david@minix3.org>
Tue, 2 Dec 2014 14:05:26 +0000 (14:05 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 4 Dec 2014 12:10:51 +0000 (12:10 +0000)
Change-Id: I003590539dd76f4be8e067f986bb1f17b151490d

minix/drivers/net/orinoco/Makefile
minix/drivers/net/orinoco/orinoco.c
minix/drivers/net/orinoco/orinoco.h

index 172e7d3190dde1044a28253952a50feff6d12fe9..a71e040a01725d5730f1dbbeab4e37400ec23516 100644 (file)
@@ -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
 
index b645c284fdc6896804bb57fd1b3068cae6e885df..fd71ffa2af0454d64fbffff3f3d7a2975a188a1e 100644 (file)
@@ -2,53 +2,26 @@
  * orinoco.c
  *
  * This file contains a wireless device driver for Prism based wireless
- * cards. 
+ * cards.
  *
- * Created by Stevens Le Blond <slblond@few.vu.nl> 
+ * Created by Stevens Le Blond <slblond@few.vu.nl>
  *        and Michael Valkering <mjvalker@cs.vu.nl>
  *
  */
 
 #include       <minix/drivers.h>
 #include       <minix/netdriver.h>
-#include       <string.h>
-#include       <minix/syslib.h>
-#include       <minix/type.h>
-#include       <minix/sysutil.h>
-#include       <minix/timers.h>
 #include       <machine/pci.h>
 #include       <machine/vmparam.h>
 #include       <sys/mman.h>
-#include       <minix/ds.h>
-#include       <minix/endpoint.h>
-#include       "kernel/const.h"
-#include       "kernel/config.h"
-#include       "kernel/type.h"
 
 #define                VERBOSE         1       /* display message during init */
 
-
-#include       <stdio.h>
-#include       <stdlib.h>
-#include       <minix/com.h>
-#include       <minix/portio.h>
-#include       <net/hton.h>
-#include       <net/gen/ether.h>
-#include       <net/gen/eth_io.h>
-#include       <machine/vm.h>
-#include       <sys/types.h>
-#include       <unistd.h>
-#include       <errno.h>
-
 #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);
-
-/* 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 void or_dump(void);
+
+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. */
-       env_setargs(argc, argv);
-       sef_local_startup();
-
-       while (TRUE) {
-               if ((r = netdriver_receive (ANY, &m, &ipc_status)) != OK)
-                       panic("orinoco: netdriver_receive failed");
-
-               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()
+int main(int argc, char *argv[])
 {
-  /* 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);
+       env_setargs(argc, argv);
 
-       /* Announce we are up! */
-       netdriver_announce();
+       netdriver_task(&or_table);
 
-       return(OK);
+       return 0;
 }
 
-/*===========================================================================*
- *                        sef_cb_signal_handler                             *
- *===========================================================================*/
-static void sef_cb_signal_handler(int signo)
+/*****************************************************************************
+ *            or_other                                                       *
+ *                                                                           *
+ *                                                                           *
+ * Process miscellaneous messages                                            *
+ *****************************************************************************/
+static void or_other(const message *m_ptr, int ipc_status)
 {
-       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);
+       if (is_ipc_notify(ipc_status) && m_ptr->m_source == TTY_PROC_NR)
+               or_dump();
 }
 
 /*****************************************************************************
- *                    check_int_events                                       *
+ *                    or_stop                                                *
  *                                                                           *
- * If a hard interrupt message came in, call the or_check_ints for the right *
- * card                                                                      *
+ * Stop the card                                                             *
  *****************************************************************************/
-static void check_int_events(void) {
+static void or_stop(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);
-
+       /* TODO: send a signal to the card to shut it down */
 }
 
 /*****************************************************************************
- *                do_hard_int                                                *
+ *                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_state;
 
-       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);
-}
+       /* Try to find out where the card is in the pci bus */
+       if (!or_probe(orp, instance))
+               return ENXIO;
 
-/*****************************************************************************
- *                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;
+       /* initialize card, hardware/firmware */
+       or_init_hw(orp, addr);
 
-       /* extract information from the boot monitor about the pci 
-        * configuration if provided */
-       orp = &or_state;
+       /* Use a synchronous alarm instead of a watchdog timer. */
+       sys_setalarm(sys_hz(), 0);
 
-       strncpy (orp->or_name, OR_NAME, sizeof(OR_NAME));
-       orp->or_name[sizeof(OR_NAME) - 2] = or_instance + '0';
-       orp->or_seen = FALSE;
+       /* 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);
 
-       /* 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;
+       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 };
-
-       orp->or_mode = OR_M_DISABLED;
+       int i;
 
-       if (orp->or_seen)
-               orp->or_mode = OR_M_ENABLED;
+       memset(orp, 0, sizeof(*orp));
 
-       if (orp->or_mode != OR_M_ENABLED)
-               return;
+       strlcpy(orp->or_name, OR_NAME, sizeof(orp->or_name));
+       orp->or_name[sizeof(OR_NAME) - 2] = instance + '0';
 
-       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);
-       
-       orp->or_need_reset= TRUE;
-       orp->or_got_int= TRUE;
-       check_int_events();
-}
 
-/*****************************************************************************
- *                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");
+       printf("or_alarm: resetting card\n");
 
+       orp->or_need_reset= TRUE;
+       orp->or_got_int= TRUE;
+       or_check_ints(orp);
 }
 
 /*****************************************************************************
- *                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 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;
-               }
-       }
+       /* Copy the data to be sent from the vector to the databuf */
+       netdriver_copyin(data, 0, databuf, size);
 
-       assert(size >= ETH_MIN_PACK_SIZE); 
+       /* Zero out the rest of the buffer */
+       memset(&databuf[size], 0, sizeof(databuf) - 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;
-}
-
-
-/*****************************************************************************
- *                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);
+       return OK;
 }
 
-
 /*****************************************************************************
  *                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;
-
-                       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;
+       case HERMES_INQ_LINKSTATUS:
+               if (len != sizeof(linkstatus))  {
+                       printf("%s: Unexpected size for linkstatus ",
+                               orp->or_name);
+                       printf("frame (%d bytes)\n", len);
+               }
 
-                       if ((newstatus == HERMES_LINKSTATUS_CONNECTED)
-                           || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
-                           || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE)) {
-                               orp->connected = 1;
+               hermes_read_words(hw, HERMES_DATA1, (void *)&linkstatus,
+                       len / 2);
+               newstatus = linkstatus.linkstatus;
 
-               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;
-                       }
-
-                       if (newstatus != orp->last_linkstatus)
-                               print_linkstatus(orp, newstatus);
+               orp->last_linkstatus = 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;
-
-       assert (orp->or_mode == OR_M_ENABLED);
-       assert (orp->or_flags & OR_F_ENABLED);
+       if (orp->rx_first == orp->rx_last)
+               return SUSPEND;
 
-       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;
-
-               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;
-       }
+       if (length > max)
+               length = max;
 
-       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));
 }
-
index a9ade97ad61178edf68e01ae8f3f181af5ef0c42..97c38eb1ce9a4fbfde97a2f707ee122014ae7e13 100644 (file)
@@ -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;