* 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
#define ETH_HLEN 14
static t_or or_state;
-static int or_instance;
struct ethhdr {
u8_t h_dest[ETH_ALEN];
#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 */
#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 *
* *
* 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);
}
/*****************************************************************************
* 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;
}
/*****************************************************************************
* 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);
}
/*****************************************************************************
* 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;
}
/*****************************************************************************
* 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;
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 */
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;
/* 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");
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;
* *
* 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;
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,
/* 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);
/* 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 *
* *
* 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);
}
/*****************************************************************************
* 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;
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;
}
* 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);
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 */
}
/*****************************************************************************
* 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);
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);
/* 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) {
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 */
}
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);
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]));
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);
}
}
-
/*****************************************************************************
- * 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;
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
* 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;
}
/* 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;
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;
}
* *
* 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;
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
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];
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) {
}
length = ntohs (hdr.len);
-
+
/* Sanity checks */
if (length < 3) {
/* No for even an 802.2 LLC header */
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));
}
-