iso9660fs: initialize buffer cache
[minix.git] / drivers / orinoco / orinoco.c
blob06f260c29f88ee5cca2fa7b6b66e648e21ac219c
1 /*
2 * orinoco.c
4 * This file contains a wireless device driver for Prism based wireless
5 * cards.
7 * Created by Stevens Le Blond <slblond@few.vu.nl>
8 * and Michael Valkering <mjvalker@cs.vu.nl>
12 #include <minix/drivers.h>
13 #include <minix/netdriver.h>
14 #include <string.h>
15 #include <minix/syslib.h>
16 #include <minix/type.h>
17 #include <minix/sysutil.h>
18 #include <timers.h>
19 #include <machine/pci.h>
20 #include <minix/ds.h>
21 #include <minix/endpoint.h>
22 #include "kernel/const.h"
23 #include "kernel/config.h"
24 #include "kernel/type.h"
26 #define VERBOSE 1 /* display message during init */
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <minix/com.h>
32 #include <minix/portio.h>
33 #include <net/hton.h>
34 #include <net/gen/ether.h>
35 #include <net/gen/eth_io.h>
36 #include <machine/vm.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39 #include <errno.h>
41 #include "assert.h"
42 #include "hermes.h"
43 #include "hermes_rid.h"
44 #include "orinoco.h"
46 #define ERR -1
48 #define debug 0
50 #define OR_M_ENABLED 1
51 #define OR_M_DISABLED 0
52 #define OR_F_EMPTY 0
53 #define OR_F_MULTI 1
54 #define OR_F_BROAD (1<<1)
55 #define OR_F_ENABLED (1<<2)
56 #define OR_F_PROMISC (1<<3)
57 #define OR_F_READING (1<<4)
58 #define OR_F_SEND_AVAIL (1<<5)
59 #define OR_F_PACK_SENT (1<<6)
60 #define OR_F_PACK_RECV (1<<7)
61 #define ORINOCO_INTEN ( HERMES_EV_RX | HERMES_EV_ALLOC |\
62 HERMES_EV_WTERR | HERMES_EV_TXEXC|\
63 HERMES_EV_INFO | HERMES_EV_INFDROP|\
64 HERMES_EV_TX)
66 #define NO_FID (-1)
67 #define ETH_ALEN 6
68 #define USER_BAP 0
69 #define IRQ_BAP 1
70 #define ETH_HLEN 14
72 static t_or or_state;
73 static int or_instance;
75 struct ethhdr {
76 u8_t h_dest[ETH_ALEN];
77 u8_t h_src[ETH_ALEN];
78 u16_t h_proto;
81 struct header_struct {
82 /* 802.3 */
83 u8_t dest[ETH_ALEN];
84 u8_t src[ETH_ALEN];
85 u16_t len;
86 /* 802.2 */
87 u8_t dsap;
88 u8_t ssap;
89 u8_t ctrl;
90 /* SNAP */
91 u8_t oui[3];
92 u16_t ethertype;
95 #define RUP_EVEN(x) (((x) + 1) & (~1))
97 u8_t encaps_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
98 #define ENCAPS_OVERHEAD (sizeof (encaps_hdr) + 2)
100 /********************************************************************
101 * Data tables *
102 ********************************************************************/
104 /* The frequency of each channel in MHz */
105 static const long channel_frequency[] = {
106 2412, 2417, 2422, 2427, 2432, 2437, 2442,
107 2447, 2452, 2457, 2462, 2467, 2472, 2484
110 #define NUM_CHANNELS (sizeof(channel_frequency) / sizeof(channel_frequency[0]))
112 /* This tables gives the actual meanings of the bitrate IDs returned by the
113 * firmware. Not used yet */
114 struct {
115 int bitrate; /* in 100s of kilobits */
116 int automatic;
117 u16_t txratectrl;
118 } bitrate_table[] =
120 {110, 1, 15}, /* Entry 0 is the default */
121 {10, 0, 1},
122 {10, 1, 1},
123 {20, 0, 2},
124 {20, 1, 3},
125 {55, 0, 4},
126 {55, 1, 7},
127 {110, 0, 8},};
129 #define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
132 static void or_writev_s(message * mp, int from_int);
133 static void or_readv_s(message * mp, int from_int);
134 static void reply(t_or * orp);
135 static int or_probe(t_or *, int skip);
136 static void or_ev_info(t_or *);
137 static void or_init(message *);
138 static void or_pci_conf(void);
139 static void or_init_struct(t_or *);
140 static void map_hw_buffer(t_or *);
141 static void or_init_hw(t_or *);
142 static void or_check_ints(t_or *);
143 static void or_writerids(hermes_t *, t_or *);
144 static void or_readrids(hermes_t *, t_or *);
145 static void or_rec_mode(t_or *);
146 static void mess_reply(message *, message *);
147 static u32_t or_get_bar(int devind, t_or * orp);
148 static void or_getstat_s(message * mp);
149 static void print_linkstatus(t_or * orp, u16_t status);
150 static int or_get_recvd_packet(t_or *orp, u16_t rxfid, u8_t *databuf);
151 static void or_reset(void);
152 static void or_watchdog_f(timer_t *tp);
153 static void setup_wepkey(t_or *orp, char *wepkey0);
154 static void do_hard_int(void);
155 static void check_int_events(void);
156 static void or_handler(t_or *orp);
157 static void or_dump(message *m);
159 /* The message used in the main loop is made global, so that rl_watchdog_f()
160 * can change its message type to fake an interrupt message.
162 static message m;
163 static int int_event_check; /* set to TRUE if events arrived */
165 static u32_t system_hz;
167 /* SEF functions and variables. */
168 static void sef_local_startup(void);
169 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
170 static void sef_cb_signal_handler(int signo);
172 /*****************************************************************************
173 * main *
176 * The main function of the driver, receiving and processing messages *
177 *****************************************************************************/
178 int main(int argc, char *argv[]) {
179 int r;
180 int ipc_status;
182 /* SEF local startup. */
183 env_setargs(argc, argv);
184 sef_local_startup();
186 while (TRUE) {
187 if ((r = netdriver_receive (ANY, &m, &ipc_status)) != OK)
188 panic("orinoco: netdriver_receive failed");
190 if (is_ipc_notify(ipc_status)) {
191 switch (_ENDPOINT_P(m.m_source)) {
192 case CLOCK:
193 or_watchdog_f(NULL);
194 break;
195 case HARDWARE:
196 do_hard_int();
197 if (int_event_check)
198 check_int_events();
199 break ;
200 case TTY_PROC_NR:
201 or_dump(&m);
202 break;
203 default:
204 panic("orinoco: illegal notify from: %d",
205 m.m_source);
208 /* done, get new message */
209 continue;
212 switch (m.m_type) {
213 case DL_WRITEV_S:
214 or_writev_s (&m, FALSE);
215 break;
216 case DL_READV_S:
217 or_readv_s (&m, FALSE);
218 break;
219 case DL_CONF:
220 or_init (&m);
221 break;
222 case DL_GETSTAT_S:
223 or_getstat_s (&m);
224 break;
225 default:
226 panic("orinoco: illegal message: %d", m.m_type);
231 /*===========================================================================*
232 * sef_local_startup *
233 *===========================================================================*/
234 static void sef_local_startup()
236 /* Register init callbacks. */
237 sef_setcb_init_fresh(sef_cb_init_fresh);
238 sef_setcb_init_lu(sef_cb_init_fresh);
239 sef_setcb_init_restart(sef_cb_init_fresh);
241 /* Register live update callbacks. */
242 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
243 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
245 /* Register signal callbacks. */
246 sef_setcb_signal_handler(sef_cb_signal_handler);
248 /* Let SEF perform startup. */
249 sef_startup();
252 /*===========================================================================*
253 * sef_cb_init_fresh *
254 *===========================================================================*/
255 static int sef_cb_init_fresh(int type, sef_init_info_t *info)
257 /* Initialize the orinoco driver. */
258 long v;
259 int fkeys, sfkeys, r;
261 system_hz = sys_hz();
263 v = 0;
264 (void) env_parse("instance", "d", 0, &v, 0, 255);
265 or_instance = (int) v;
267 /* Observe some function key for debug dumps. */
268 fkeys = sfkeys = 0; bit_set(sfkeys, 11);
269 if ((r=fkey_map(&fkeys, &sfkeys)) != OK)
270 printf("Warning: orinoco couldn't observe F-key(s): %d\n",r);
272 /* Announce we are up! */
273 netdriver_announce();
275 return(OK);
278 /*===========================================================================*
279 * sef_cb_signal_handler *
280 *===========================================================================*/
281 static void sef_cb_signal_handler(int signo)
283 t_or *orp;
285 /* Only check for termination signal, ignore anything else. */
286 if (signo != SIGTERM) return;
288 orp = &or_state;
290 if (orp->or_mode == OR_M_ENABLED) {
291 /* TODO: send a signal to the card to shut it down */
293 exit(0);
296 /*****************************************************************************
297 * check_int_events *
299 * If a hard interrupt message came in, call the or_check_ints for the right *
300 * card *
301 *****************************************************************************/
302 static void check_int_events(void) {
303 t_or *orp;
305 /* the interrupt message doesn't contain information about the port, try
306 * to find it */
307 orp = &or_state;
309 if (orp->or_mode != OR_M_ENABLED)
310 return;
311 if (!orp->or_got_int)
312 return;
313 orp->or_got_int = 0;
314 assert (orp->or_flags & OR_F_ENABLED);
315 or_check_ints (orp);
319 /*****************************************************************************
320 * do_hard_int *
322 * Process the interrupts which the card generated *
323 *****************************************************************************/
324 static void do_hard_int(void)
326 int s;
328 /* Run interrupt handler at driver level. */
329 or_handler(&or_state);
331 /* Reenable interrupts for this hook. */
332 if ((s=sys_irqenable(&or_state.or_hook_id)) != OK) {
333 printf("orinoco: error, couldn't enable");
334 printf(" interrupts: %d\n", s);
338 /*****************************************************************************
339 * or_reset *
341 * Sometime the card gets screwed, behaving erratically. Solution: reset the *
342 * card. This is actually largely redoing the initialization *
343 *****************************************************************************/
344 static void or_reset() {
345 static clock_t last_reset, now;
346 t_or *orp;
347 int i, r;
349 if (OK != (r = getuptime(&now)))
350 panic("orinoco: getuptime() failed: %d", r);
352 if(now - last_reset < system_hz * 10) {
353 printf("Resetting card too often. Going to reset driver\n");
354 exit(1);
357 last_reset = now;
359 orp = &or_state;
361 if(orp->or_mode == OR_M_DISABLED)
362 printf("orinoco instance %d is disabled\n", or_instance);
364 if(orp->or_mode != OR_M_ENABLED) {
365 return;
368 orp->or_need_reset = 0;
369 or_init_hw(orp);
371 orp->rx_last = orp->rx_first = 0;
372 for(i = 0; i < NR_RX_BUFS; i++) {
373 orp->rx_length[0] = 0;
376 if(orp->or_flags & OR_F_SEND_AVAIL) {
377 orp->or_tx.ret_busy = FALSE;
378 orp->or_send_int = TRUE;
382 /*****************************************************************************
383 * or_dump *
385 * Dump interesting information about the card on F-key pressed. *
386 * Not implemented yet *
387 *****************************************************************************/
388 static void or_dump (message *m)
390 t_or *orp;
392 orp = &or_state;
394 if(orp->or_mode == OR_M_DISABLED) {
395 printf("%s is disabled\n", orp->or_name);
398 if(orp->or_mode != OR_M_ENABLED)
399 return;
401 m->m_type = FKEY_CONTROL;
402 m->FKEY_REQUEST = FKEY_EVENTS;
403 if(OK!=(sendrec(TTY_PROC_NR,m)) )
404 printf("Contacting the TTY failed\n");
406 if(bit_isset(m->FKEY_SFKEYS, 11)) {
407 print_linkstatus(orp, orp->last_linkstatus);
411 /*****************************************************************************
412 * or_init *
414 * The main initialization function, called when a DL_INIT message comes in. *
415 *****************************************************************************/
416 static void or_init (message * mp) {
417 t_or *orp;
418 message reply;
419 static int first_time = 1;
421 if (first_time) {
422 first_time = 0;
423 or_pci_conf (); /* Configure PCI devices. */
425 /* Use a synchronous alarm instead of a watchdog timer. */
426 sys_setalarm(system_hz, 0);
429 orp = &or_state;
431 if (orp->or_mode == OR_M_DISABLED) {
432 /* Initialize the orp structure */
433 or_init_struct (orp);
434 if (orp->or_mode == OR_M_DISABLED) {
435 reply.m_type = DL_CONF_REPLY;
436 reply.DL_STAT = ENXIO;
437 mess_reply (mp, &reply);
438 return;
440 if (orp->or_mode == OR_M_ENABLED) {
441 /* initialize card, hardware/firmware */
442 orp->or_flags |= OR_F_ENABLED;
443 or_init_hw (orp);
447 assert (orp->or_mode == OR_M_ENABLED);
448 assert (orp->or_flags & OR_F_ENABLED);
450 /* Not supported by the driver yet, but set a couple of options:
451 * multicasting, promiscuity, broadcasting, depending on the users
452 * needs */
453 orp->or_flags &= ~(OR_F_PROMISC | OR_F_MULTI | OR_F_BROAD);
454 if (mp->DL_MODE & DL_PROMISC_REQ)
455 orp->or_flags |= OR_F_PROMISC;
456 if (mp->DL_MODE & DL_MULTI_REQ)
457 orp->or_flags |= OR_F_MULTI;
458 if (mp->DL_MODE & DL_BROAD_REQ)
459 orp->or_flags |= OR_F_BROAD;
461 or_rec_mode (orp);
463 /* reply the caller that the configuration succeeded */
464 reply.m_type = DL_CONF_REPLY;
465 reply.DL_STAT = OK;
466 *(ether_addr_t *) reply.DL_HWADDR = orp->or_address;
467 mess_reply (mp, &reply);
470 /*****************************************************************************
471 * or_pci_conf *
473 * Configure the pci related issues of the card, e.g. finding out where the *
474 * card is in the pci configuration, it's assigned irq, etc. This can be *
475 * done if the boot monitor is provided with information, or the pci bus *
476 * can be searched (at the end: or_probe function) *
477 *****************************************************************************/
478 static void or_pci_conf () {
479 t_or *orp;
481 /* extract information from the boot monitor about the pci
482 * configuration if provided */
483 orp = &or_state;
485 strncpy (orp->or_name, OR_NAME, sizeof(OR_NAME));
486 orp->or_name[sizeof(OR_NAME) - 2] = or_instance + '0';
487 orp->or_seen = FALSE;
489 /* Initialize the pci bus, bridges and cards, if not yet done */
490 pci_init ();
492 /* Try to find out where the card is in the pci bus */
493 if (or_probe (orp, or_instance))
494 orp->or_seen = TRUE;
497 /*****************************************************************************
498 * or_probe *
500 * Try to find the card based on information provided by pci and get irq and *
501 * bar *
502 *****************************************************************************/
503 static int or_probe (t_or * orp, int skip)
505 u8_t ilr;
506 u32_t bar;
507 char *dname;
508 u16_t vid, did;
509 int r, devind;
511 /* Start looking from the beginning */
512 r = pci_first_dev (&devind, &vid, &did);
513 if (r == 0)
514 return (0);
516 /* Skip as many instances as requested */
517 while (skip--) {
518 r = pci_next_dev (&devind, &vid, &did);
519 if (!r)
520 return (0);
523 /* Get the name as advertised by pci */
524 dname = pci_dev_name (vid, did);
525 if (!dname)
526 dname = "unknown device";
527 printf ("%s: %s (%04x/%04x) at %s\n",
528 orp->or_name, dname, vid, did, pci_slot_name (devind));
530 pci_reserve (devind);
532 orp->devind = devind;
533 /* Get the irq */
534 ilr = pci_attr_r8 (devind, PCI_ILR);
535 orp->or_irq = ilr;
537 /* Get the base address */
538 bar = or_get_bar (devind, orp);
539 orp->or_base_port = bar;
541 map_hw_buffer(orp);
542 return TRUE;
545 /*****************************************************************************
546 * map_hw_buffer *
548 * Map the memory mapped registers into user space memory *
549 *****************************************************************************/
550 static void map_hw_buffer(t_or *orp)
552 int r;
553 size_t o, size;
554 char *buf, *abuf;
555 hermes_t *hw = &(orp->hw);
557 /* This way, the buffer will be at least I386_PAGE_SIZE big: see
558 * calculation with the offset */
559 size = 2 * I386_PAGE_SIZE;
561 buf = (char *)malloc(size);
562 if(buf == NULL)
563 panic("map_hw_buffer: cannot malloc size: %d", size);
565 /* Let the mapped memory by I386_PAGE_SIZE aligned */
566 o = I386_PAGE_SIZE - ((vir_bytes)buf % I386_PAGE_SIZE);
567 abuf = buf + o;
569 #if 0
570 r = sys_vm_map(SELF, 1, (vir_bytes)abuf,
571 1 * I386_PAGE_SIZE, (phys_bytes)orp->or_base_port);
572 #else
573 r = ENOSYS;
574 #endif
576 if(r!=OK)
577 panic("map_hw_buffer: sys_vm_map failed: %d", r);
580 hw->locmem = abuf;
585 /*****************************************************************************
586 * or_get_bar *
588 * Get the base address from pci (from Base Address Register) and find out *
589 * whether the card is memory mapped or in I/O space. Currently, only *
590 * memmory mapped is supported. *
591 *****************************************************************************/
592 static u32_t or_get_bar (int devind, t_or * orp)
594 u32_t bar;
595 int is_iospace;
596 hermes_t *hw = &(orp->hw);
598 /* bit 1 off the PCI_BAR register indicates whether the cards registers
599 * are mapped in io-space or shared memory */
600 is_iospace = pci_attr_r32 (devind, PCI_BAR) & 1;
602 if (is_iospace) {
603 /* read where the base address is in I/O space */
604 bar = pci_attr_r32 (devind, PCI_BAR) & 0xffffffe0;
606 if ((bar & 0x3ff) >= 0x100 - 32 || bar < 0x400)
607 panic("base address isn't properly configured");
609 /* In I/O space registers are 2 bytes wide, without any spacing
610 * in between */
611 hermes_struct_init (hw, bar, is_iospace,
612 HERMES_16BIT_REGSPACING);
614 if (debug) {
615 printf ("%s: using I/O space address 0x%x, IRQ %d\n",
616 orp->or_name, bar, orp->or_irq);
619 panic("Not implemented yet");
620 /* Although we are able to find the desired bar and irq for an
621 * I/O spaced card, we haven't implemented the right register
622 * accessing functions. This wouldn't be difficult, but we were
623 * not able to test them. Therefore, give an alert here */
625 return bar;
626 } else {
627 /* read where the base address is in shared memory */
628 bar = pci_attr_r32 (devind, PCI_BAR) & 0xfffffff0;
629 /* maybe some checking whether the address is legal... */
631 /* Memory mapped registers are 2 bytes wide, aligned on 4
632 * bytes */
633 hermes_struct_init (hw, bar, is_iospace,
634 HERMES_32BIT_REGSPACING);
636 if (debug){
637 printf ("%s: using shared memory address",
638 orp->or_name);
639 printf (" 0x%x, IRQ %d\n", bar, orp->or_irq);
642 return bar;
647 /*****************************************************************************
648 * or_init_struct *
650 * Set the orinoco structure to default values *
651 *****************************************************************************/
652 static void or_init_struct (t_or * orp)
654 int i = 0;
655 static eth_stat_t empty_stat = { 0, 0, 0, 0, 0, 0 };
657 orp->or_mode = OR_M_DISABLED;
659 if (orp->or_seen)
660 orp->or_mode = OR_M_ENABLED;
662 if (orp->or_mode != OR_M_ENABLED)
663 return;
665 orp->or_got_int = 0;
666 orp->or_link_up = -1;
667 orp->or_send_int = 0;
668 orp->or_clear_rx = 0;
669 orp->or_tx_alive = 0;
670 orp->or_need_reset = 0;
672 orp->or_read_s = 0;
673 orp->or_tx_head = 0;
674 orp->or_tx_tail = 0;
675 orp->connected = 0;
677 orp->or_tx.ret_busy = FALSE;
678 orp->or_tx.or_txfid = NO_FID;
680 for(i = 0; i < NR_RX_BUFS; i++) {
681 orp->rxfid[i] = NO_FID;
682 orp->rx_length[i] = 0;
684 orp->rx_current = 0;
685 orp->rx_first = 0;
686 orp->rx_last = 0;
688 orp->or_stat = empty_stat;
689 orp->or_flags = OR_F_EMPTY;
691 /* Keep an administration in the driver whether the internal
692 buffer is in use. That's what ret_busy is for */
693 orp->or_tx.ret_busy = FALSE;
695 orp->or_nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
699 /*****************************************************************************
700 * or_init_hw *
702 * Initialize hardware and prepare for intercepting the interrupts. At the *
703 * end, the card is up and running *
704 *****************************************************************************/
705 static void or_init_hw (t_or * orp)
707 int i, err, s;
708 hermes_t *hw = &(orp->hw);
709 static int first_time = TRUE;
711 /* first step in starting the card */
712 if (hermes_cor_reset(hw) != 0) {
713 printf ("%s: Failed to start the card\n", orp->or_name);
716 /* here begins the real things, yeah! ;) */
717 if ((err = hermes_init (hw)) != 0) {
718 printf ("error value of hermes_init(): %d\n", err);
721 /* Get the MAC address (which is a data item in the card)*/
722 or_readrids (hw, orp);
724 /* Write a few rids to the card, e.g. WEP key*/
725 or_writerids (hw, orp);
727 if (debug) {
728 printf ("%s: Ethernet address ", orp->or_name);
729 for (i = 0; i < 6; i++) {
730 printf ("%x%c", orp->or_address.ea_addr[i],
731 i < 5 ? ':' : '\n');
735 /* Prepare internal TX buffer in the card */
736 err = hermes_allocate (hw,
737 orp->or_nicbuf_size,
738 &(orp->or_tx.or_txfid));
740 if (err)
741 printf ("%s:Error %d allocating Tx buffer\n",
742 orp->or_name, err);
744 /* Establish event handle */
745 if(first_time) {
746 orp->or_hook_id = orp->or_irq;
747 if ((s=sys_irqsetpolicy(orp->or_irq, 0,
748 &orp->or_hook_id)) != OK)
749 printf("orinoco: couldn't set IRQ policy: %d\n", s);
751 if ((s=sys_irqenable(&orp->or_hook_id)) != OK)
752 printf("orinoco: couldn't enable interrupts: %d\n", s);
753 first_time = FALSE;
756 /* Tell the card which events should raise an interrupt to the OS */
757 hermes_set_irqmask (hw, ORINOCO_INTEN);
759 /* Enable operation */
760 err = hermes_docmd_wait (hw, HERMES_CMD_ENABLE, 0, NULL);
761 if (err) {
762 printf ("%s: Error %d enabling MAC port\n", orp->or_name, err);
767 /*****************************************************************************
768 * or_readrids *
770 * Read some default rids from the card. A rid (resource identifier) *
771 * is a data item in the firmware, some configuration variable. *
772 * In our case, we are mostly interested in the MAC address for now *
773 *****************************************************************************/
775 static void or_readrids (hermes_t * hw, t_or * orp)
777 /* Read the MAC address */
778 int err = hermes_read_ltv (hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
779 ETH_ALEN, NULL, &orp->or_address);
780 if (err) {
781 printf ("%s: failed to read MAC address!\n", orp->or_name);
782 return;
787 /*****************************************************************************
788 * or_writerids *
790 * Write some default rids to the card. A rid (resource identifier) *
791 * is a data item in the firmware, some configuration variable, e.g. WEP key *
792 *****************************************************************************/
793 static void or_writerids (hermes_t * hw, t_or * orp)
795 int err;
796 struct hermes_idstring idbuf;
797 u16_t port_type;
798 static char essid[IW_ESSID_MAX_SIZE + 1];
799 static char wepkey0[LARGE_KEY_LENGTH + 1];
801 /* Set the MAC port */
802 port_type = 1;
803 err = hermes_write_wordrec (hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
804 port_type);
805 if (err) {
806 printf ("%s: Error %d setting port type\n", orp->or_name, err);
807 return;
810 if (OK != env_get_param("essid", essid, sizeof(essid))) {
811 essid[0] = 0;
814 if(strlen(essid) == 0) {
815 printf("%s: no essid provided in boot monitor!\n",
816 orp->or_name);
817 printf("Hope you'll connect to the right network... \n");
820 /* Set the desired ESSID */
821 idbuf.len = strlen (essid);
822 memcpy (&idbuf.val, essid, sizeof (idbuf.val));
824 err = hermes_write_ltv (hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
825 HERMES_BYTES_TO_RECLEN (strlen (essid) + 2),
826 &idbuf);
827 if (err) {
828 printf ("%s: Error %d setting DESIREDSSID\n",
829 orp->or_name, err);
830 return;
833 if (OK != env_get_param("wep", wepkey0, sizeof(wepkey0))) {
834 wepkey0[0] = 0;
837 switch(strlen(wepkey0)) {
838 case 0:
839 /* No key found in monitor, using no encryption */
840 break;
841 case LARGE_KEY_LENGTH:
842 setup_wepkey(orp, wepkey0);
843 break;
844 default:
845 printf("Invalid key provided. Has to be 13 chars\n");
846 break;
850 /*****************************************************************************
851 * setup_wepkey *
853 * If a wepkey is provided in the boot monitor, set the necessary rids so *
854 * that the card will decrypt received data and encrypt data to send by *
855 * by default with this key. *
856 * It appears that there is a severe bug in setting up WEP. If the driver *
857 * doesnt function properly, please turn WEP off. *
858 *****************************************************************************/
859 static void setup_wepkey(t_or *orp, char *wepkey0) {
860 int default_key = 0, err = 0;
861 hermes_t *hw = &(orp->hw);
863 err = hermes_write_wordrec (hw, USER_BAP,
864 HERMES_RID_CNFWEPDEFAULTKEYID,
865 default_key);
866 if (err)
867 printf ("%s: Error %d setting the default WEP-key entry\n",
868 orp->or_name, err);
870 err = hermes_write_ltv (hw, USER_BAP,
871 HERMES_RID_CNFDEFAULTKEY0,
872 HERMES_BYTES_TO_RECLEN(LARGE_KEY_LENGTH),
873 wepkey0);
874 if (err)
875 printf ("%s: Error %d setting the WEP-key0\n",
876 orp->or_name, err);
878 err = hermes_write_wordrec (hw, USER_BAP,
879 HERMES_RID_CNFAUTHENTICATION,
880 HERMES_AUTH_OPEN);
881 if (err)
882 printf ("%s: Error %d setting the authentication flag\n",
883 orp->or_name, err);
885 err = hermes_write_wordrec (hw, USER_BAP,
886 HERMES_RID_CNFWEPFLAGS_INTERSIL,
887 HERMES_WEP_PRIVACY_INVOKED);
888 if (err)
889 printf ("%s: Error %d setting the master wep setting flag\n",
890 orp->or_name, err);
895 /*****************************************************************************
896 * or_rec_mode *
898 * Set the desired receive mode, e.g. promiscuous mode. Not implemented yet *
899 *****************************************************************************/
900 static void or_rec_mode (t_or * orp) {
901 /* TODO */
904 /*****************************************************************************
905 * or_handler *
907 * The handler which is called when the card generated an interrupt. Events *
908 * like EV_INFO and EV_RX have to be handled before an acknowledgement for *
909 * the event is returned to the card. See also the documentation *
910 *****************************************************************************/
911 static void or_handler (t_or *orp)
913 int length;
914 u16_t evstat, events, fid;
915 hermes_t *hw = &(orp->hw);
917 beginning:
918 /* Retrieve which kind of event happened */
919 evstat = hermes_read_reg (hw, HERMES_EVSTAT);
920 events = evstat;
922 /* There are plenty of events possible. The more interesting events
923 are actually implemented. Whether the following events actually
924 raise an interrupt depends on the value of ORINOCO_INTEN. For more
925 information about the events, see the specification in pdf */
927 /* Occurs at each tick of the auxiliary time */
928 if (events & HERMES_EV_TICK) {
929 events &= ~HERMES_EV_TICK;
931 /* Occurs when a wait time-out error is detected */
932 if (events & HERMES_EV_WTERR) {
933 events &= ~HERMES_EV_WTERR;
936 /* Occurs when an info frame is dropped because there is not enough
937 buffer space available */
938 if (events & HERMES_EV_INFDROP) {
939 events &= ~(HERMES_EV_INFDROP);
942 /* This AP-only event will be asserted at the beacon interval prior to
943 the DTIM interval */
944 if (events & HERMES_EV_DTIM) {
945 events &= ~(HERMES_EV_DTIM);
948 /* Occurs when a command execution is completed */
949 if (events & HERMES_EV_CMD) {
950 events &= ~(HERMES_EV_CMD);
953 /* Occurs when the asynchronous transmission process is unsuccessfully
954 completed */
955 if (events & HERMES_EV_TXEXC) {
957 /* What buffer generated the event? Represented by an fid */
958 fid = hermes_read_reg(hw, HERMES_TXCOMPLFID);
959 if(fid == 0xFFFF) {
960 /* Illegal fid found */
961 printf("unexpected txexc_fid interrupted\n");
964 orp->or_tx.ret_busy = FALSE;
966 if(orp->or_flags & OR_F_SEND_AVAIL) {
967 orp->or_send_int = TRUE;
968 if (!orp->or_got_int){
969 orp->or_got_int = TRUE;
970 int_event_check = TRUE;
974 /* To detect illegal fids */
975 hermes_write_reg(hw, HERMES_TXCOMPLFID, 0xFFFF);
976 events &= ~(HERMES_EV_TXEXC);
977 /* We don't do anything else yet.
978 * Could be used for statistics */
981 /* Occurs when the asynchronous transmission process is successfully
982 completed */
983 if (events & HERMES_EV_TX) {
984 events &= ~(HERMES_EV_TX);
985 /* Which buffer was sent, represented by an fid */
986 fid = hermes_read_reg (hw, HERMES_TXCOMPLFID);
987 if(fid == 0xFFFF) {
988 /* Illegal fid found */
989 printf("unexpected tx_fid interrupted\n");
992 orp->or_tx.ret_busy = FALSE;
994 if(orp->or_flags & OR_F_SEND_AVAIL) {
995 orp->or_send_int = TRUE;
996 if (!orp->or_got_int){
997 orp->or_got_int = TRUE;
998 int_event_check = TRUE;
1002 /* To detect illegal fids */
1003 hermes_write_reg(hw, HERMES_TXCOMPLFID, 0xFFFF);
1004 /* We don't do anything else when such event happens */
1007 /* Occurs when an info frame is available in the card */
1008 if (events & HERMES_EV_INFO) {
1009 events &= ~(HERMES_EV_INFO);
1010 /* Process the information, inside the handler (!) */
1011 or_ev_info(orp);
1014 /* Occurs when a TX buffer is available again for usage */
1015 if (events & HERMES_EV_ALLOC) {
1016 /* Which frame is now marked as free? */
1017 fid = hermes_read_reg (hw, HERMES_ALLOCFID);
1018 if (fid == 0xFFFF){
1019 /* An illegal frame identifier is found. Ignore */
1020 printf("Allocate event on unexpected fid\n");
1021 return ;
1024 /* To be able to detect illegal fids */
1025 hermes_write_reg(hw, HERMES_ALLOCFID, 0xFFFF);
1027 events &= ~(HERMES_EV_ALLOC);
1031 /* Occurs when a frame is received by the asynchronous reception
1032 * process */
1034 if (events & HERMES_EV_RX) {
1035 orp->or_ev_rx = TRUE;
1036 events &= ~(HERMES_EV_RX);
1038 /* If the last buffer is still filled with data, then we don't
1039 * have any buffers available to store the data */
1040 if(orp->rx_length[orp->rx_last] != 0) {
1041 /* indeed, we are going to overwrite information
1042 * in a buffer */
1045 /* Which buffer is storing the data (represented by a fid) */
1046 orp->rxfid[orp->rx_last]
1047 = hermes_read_reg (hw, HERMES_RXFID);
1049 /* Get the packet from the card and store it in
1050 * orp->rx_buf[orp->rx_last]. The length is returned by this
1051 * function */
1052 length = or_get_recvd_packet(orp, orp->rxfid[orp->rx_last],
1053 (orp->rx_buf[orp->rx_last]));
1055 if(length < 0) {
1056 /* Error happened. */
1057 printf("length < 0\n");
1058 goto next;
1059 } else {
1060 orp->rx_length[orp->rx_last] = length;
1063 /* The next buffer will be used the next time, circularly */
1064 orp->rx_last++;
1065 orp->rx_last %= NR_RX_BUFS;
1067 if (!orp->or_got_int){
1068 orp->or_got_int = TRUE;
1070 int_event_check = TRUE;
1072 next:
1073 if (events) {
1074 printf("Unknown event: 0x%x\n", events);
1077 /* Acknowledge to the card that the events have been processed. After
1078 * this the card will assume we have processed any buffer which were in
1079 * use for this event. */
1080 hermes_write_reg (hw, HERMES_EVACK, evstat);
1082 evstat = hermes_read_reg (hw, HERMES_EVSTAT);
1083 if(evstat != 0 && !(evstat & HERMES_EV_TICK)) {
1084 goto beginning;
1089 /*****************************************************************************
1090 * or_watchdog_f *
1092 * Will be called regularly to see whether the driver has crashed. If that *
1093 * condition is detected, reset the driver and card *
1094 *****************************************************************************/
1095 static void or_watchdog_f(timer_t *tp)
1097 t_or *orp;
1099 /* Use a synchronous alarm instead of a watchdog timer. */
1100 sys_setalarm(system_hz, 0);
1102 orp = &or_state;
1104 if (orp->or_mode != OR_M_ENABLED)
1105 return;
1107 if (!(orp->or_flags & OR_F_SEND_AVAIL)) {
1108 /* Assume that an idle system is alive */
1109 orp->or_tx_alive= TRUE;
1110 return;
1113 if (orp->connected == 0) {
1114 orp->or_tx_alive= TRUE;
1115 return;
1117 if (orp->or_tx_alive) {
1118 orp->or_tx_alive= FALSE;
1119 return;
1122 printf("or_watchdog_f: resetting instance %d\n", or_instance);
1124 orp->or_need_reset= TRUE;
1125 orp->or_got_int= TRUE;
1126 check_int_events();
1129 /*****************************************************************************
1130 * mess_reply *
1131 *****************************************************************************/
1132 static void mess_reply (message * req, message * reply_mess)
1134 if (send (req->m_source, reply_mess) != 0)
1135 panic("orinoco: unable to mess_reply");
1139 /*****************************************************************************
1140 * or_writev_s *
1142 * Write data which is denoted by the message to the card and send it. *
1143 *****************************************************************************/
1144 static void or_writev_s (message * mp, int from_int) {
1145 int count, size, err, data_len, data_off;
1146 int o, j, n, i, s, p, cps ;
1147 struct ethhdr *eh;
1148 t_or *orp;
1149 hermes_t *hw;
1150 struct hermes_tx_descriptor desc;
1151 int iov_offset = 0;
1152 struct header_struct hdr;
1153 iovec_s_t *iovp;
1154 u16_t txfid;
1156 /* We need space for the max packet size itself, plus an ethernet
1157 * header, plus 2 bytes so we can align the IP header on a
1158 * 32bit boundary, plus 1 byte so we can read in odd length
1159 * packets from the card, which has an IO granularity of 16
1160 * bits */
1161 static u8_t databuf[IEEE802_11_DATA_LEN + ETH_HLEN + 2 + 1];
1162 memset (databuf, 0, IEEE802_11_DATA_LEN + ETH_HLEN + 3);
1164 orp = &or_state;
1166 count = mp->DL_COUNT;
1168 orp->or_client = mp->m_source;
1169 hw = &(orp->hw);
1171 /* Switch off interrupts. The card is accessable via 2 BAPs, one for
1172 * reading and one for writing. In theory these BAPs should be
1173 * independent, but in practice, the are not. By switching off the
1174 * interrupts of the card, the chances of one interfering with the
1175 * other should be less */
1176 if (from_int){
1177 /* We were called with from_int, meaning that the last time we
1178 * were called, no tx buffers were available, and we had to
1179 * suspend. Now, we'll try again to find an empty buffer in the
1180 * card */
1181 assert (orp->or_flags & OR_F_SEND_AVAIL);
1182 orp->or_flags &= ~OR_F_SEND_AVAIL;
1183 orp->or_send_int = FALSE;
1184 orp->or_tx_alive = TRUE;
1187 txfid = orp->or_tx.or_txfid;
1189 if (orp->or_tx.ret_busy || orp->connected == 0) {
1190 /* there is no buffer in the card available */
1191 assert(!(orp->or_flags & OR_F_SEND_AVAIL));
1192 /* Remember that there is a packet to be sent available */
1193 orp->or_flags |= OR_F_SEND_AVAIL;
1194 goto suspend_write_s;
1197 assert (orp->or_mode == OR_M_ENABLED);
1198 assert (orp->or_flags & OR_F_ENABLED);
1201 /* Copy the data to be send from the vector to the databuf */
1202 size = 0;
1203 o = 0;
1204 for (i = 0; i < count; i += IOVEC_NR,
1205 iov_offset += IOVEC_NR * sizeof (orp->or_iovec_s[0])) {
1207 n = IOVEC_NR;
1208 if (i + n > count)
1209 n = count - i;
1211 cps = sys_safecopyfrom(mp->m_source, mp->DL_GRANT, iov_offset,
1212 (vir_bytes) orp->or_iovec_s,
1213 n * sizeof(orp->or_iovec_s[0]));
1214 if (cps != OK)
1215 printf("orinoco: sys_safecopyfrom failed: %d\n", cps);
1217 for (j = 0, iovp = orp->or_iovec_s; j < n; j++, iovp++) {
1218 s = iovp->iov_size;
1219 if (size + s > ETH_MAX_PACK_SIZE_TAGGED) {
1220 printf("Orinoco: invalid pkt size\n");
1223 cps = sys_safecopyfrom(mp->m_source, iovp->iov_grant,
1224 0, (vir_bytes) databuf + o, s);
1225 if (cps != OK)
1226 printf("orinoco: sys_safecopyfrom failed:%d\n",
1227 cps);
1229 size += s;
1230 o += s;
1234 assert(size >= ETH_MIN_PACK_SIZE);
1236 memset (&desc, 0, sizeof (desc));
1237 /* Reclaim the tx buffer once the data is sent (OK), or it is clear
1238 * that transmission failed (EX). Reclaiming means that we can reuse
1239 * the buffer again for transmission */
1240 desc.tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
1241 /* Actually, this reclaim bit is the only thing which needs to be set
1242 * in the descriptor */
1243 err = hermes_bap_pwrite (hw, USER_BAP, &desc, sizeof (desc), txfid,
1245 if (err) {
1246 printf("hermes_bap_pwrite() descriptor error:resetting card\n");
1247 /* When this happens, the card is quite confused: it will not
1248 * recover. Reset it */
1249 or_reset();
1250 goto fail;
1253 eh = (struct ethhdr *) databuf;
1254 /* Encapsulate Ethernet-II frames */
1255 if (ntohs (eh->h_proto) > 1500) {
1256 /* Ethernet-II frame */
1257 data_len = size - ETH_HLEN;
1258 data_off = HERMES_802_3_OFFSET + sizeof (hdr);
1260 /* 802.3 header */
1261 memcpy (hdr.dest, eh->h_dest, ETH_ALEN);
1262 memcpy (hdr.src, eh->h_src, ETH_ALEN);
1263 hdr.len = htons (data_len + ENCAPS_OVERHEAD);
1265 /* 802.2 header */
1266 memcpy (&hdr.dsap, &encaps_hdr, sizeof (encaps_hdr));
1267 hdr.ethertype = eh->h_proto;
1269 err = hermes_bap_pwrite (hw, USER_BAP, &hdr, sizeof (hdr),
1270 txfid, HERMES_802_3_OFFSET);
1271 if (err) {
1272 printf ("%s: Error %d writing packet header to BAP\n",
1273 orp->or_name, err);
1274 goto fail;
1277 p = ETH_HLEN;
1278 } else {
1279 /* IEEE 802.3 frame */
1280 data_len = size + ETH_HLEN;
1281 data_off = HERMES_802_3_OFFSET;
1282 p = 0;
1285 /* Round up for odd length packets */
1286 err = hermes_bap_pwrite (hw, USER_BAP,
1287 (void *) &(databuf[p]), RUP_EVEN (data_len),
1288 txfid, data_off);
1289 if (err) {
1290 printf ("hermes_bap_pwrite(data): error %d\n", err);
1291 goto fail;
1294 /* this should be before the docmd_wait. Cause otherwise the bit can
1295 be cleared in the handler (if irq's not off) before it is set
1296 and then 1 reset (ret_busy=false) is lost */
1297 orp->or_tx.ret_busy = TRUE;
1299 /* Send the packet which was constructed in txfid */
1300 err = hermes_docmd_wait (hw, HERMES_CMD_TX | HERMES_CMD_RECL,
1301 txfid, NULL);
1302 if (err) {
1303 printf ("hermes_docmd_wait(TX|RECL): error %d\n", err);
1304 /* Mark the buffer as available again */
1305 orp->or_tx.ret_busy = FALSE;
1306 goto fail;
1309 fail:
1310 /* If the interrupt handler called, don't send a reply. The reply
1311 * will be sent after all interrupts are handled.
1313 orp->or_flags |= OR_F_PACK_SENT;
1315 if (from_int) {
1316 return;
1319 reply (orp);
1320 return;
1322 suspend_write_s:
1323 orp->or_tx_mess = *mp;
1325 reply (orp);
1326 return;
1330 /*****************************************************************************
1331 * reply *
1333 * Send a message back to the caller, informing it about the data received *
1334 * or sent *
1335 *****************************************************************************/
1336 static void reply (t_or * orp) {
1337 message reply;
1338 int flags = DL_NOFLAGS, r;
1340 if (orp->or_flags & OR_F_PACK_SENT)
1341 flags |= DL_PACK_SEND;
1342 if (orp->or_flags & OR_F_PACK_RECV)
1343 flags |= DL_PACK_RECV;
1345 reply.m_type = DL_TASK_REPLY;
1346 reply.DL_FLAGS = flags;
1347 reply.DL_COUNT = orp->or_read_s;
1349 r = send (orp->or_client, &reply);
1351 if (r < 0)
1352 panic("orinoco: send failed: %d", r);
1354 orp->or_read_s = 0;
1355 orp->or_flags &= ~(OR_F_PACK_SENT | OR_F_PACK_RECV);
1359 /*****************************************************************************
1360 * or_ev_info *
1362 * Process information which comes in from the card *
1363 *****************************************************************************/
1364 static void or_ev_info (t_or * orp)
1366 u16_t infofid;
1367 int err, len, type;
1368 hermes_t *hw = &orp->hw;
1370 struct {
1371 u16_t len;
1372 u16_t type;
1373 } info;
1375 infofid = hermes_read_reg (hw, HERMES_INFOFID);
1376 err = hermes_bap_pread (hw, IRQ_BAP, &info, sizeof (info), infofid,
1378 if (err) {
1379 printf ("%s: error %d reading info frame.\n", orp->or_name,
1380 err);
1381 return;
1384 len = HERMES_RECLEN_TO_BYTES (info.len);
1385 type = info.type;
1387 switch (type) {
1388 case HERMES_INQ_TALLIES:
1390 struct hermes_tallies_frame tallies;
1392 if (len > sizeof (tallies)) {
1393 printf ("%s: Tallies frame too long ",
1394 orp->or_name);
1395 printf ("(%d bytes)\n", len);
1396 len = sizeof (tallies);
1398 hermes_read_words (hw, HERMES_DATA1,
1399 (void *) &tallies, len / 2);
1400 /* TODO: do something with the tallies structure */
1402 break;
1404 case HERMES_INQ_LINKSTATUS: {
1405 u16_t newstatus;
1406 struct hermes_linkstatus linkstatus;
1408 if (len != sizeof (linkstatus)) {
1409 printf ("%s: Unexpected size for linkstatus ",
1410 orp->or_name);
1411 printf ("frame (%d bytes)\n", len);
1414 hermes_read_words (hw, HERMES_DATA1,
1415 (void *) &linkstatus, len / 2);
1416 newstatus = linkstatus.linkstatus;
1418 if ((newstatus == HERMES_LINKSTATUS_CONNECTED)
1419 || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
1420 || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE)) {
1421 orp->connected = 1;
1423 if(orp->or_flags & OR_F_SEND_AVAIL) {
1424 orp->or_send_int = TRUE;
1425 orp->or_got_int = TRUE;
1426 int_event_check = TRUE;
1431 else if ((newstatus ==
1432 HERMES_LINKSTATUS_NOT_CONNECTED)
1433 || (newstatus ==
1434 HERMES_LINKSTATUS_DISCONNECTED)
1435 || (newstatus ==
1436 HERMES_LINKSTATUS_AP_OUT_OF_RANGE)
1437 || (newstatus ==
1438 HERMES_LINKSTATUS_ASSOC_FAILED)) {
1439 orp->connected = 0;
1442 if (newstatus != orp->last_linkstatus)
1443 print_linkstatus(orp, newstatus);
1445 orp->last_linkstatus = newstatus;
1447 break;
1448 default:
1449 printf ("%s:Unknown information frame received(type %04x).\n",
1450 orp->or_name, type);
1451 break;
1455 /*****************************************************************************
1456 * or_print_linkstatus *
1458 * Process information which comes in from the card *
1459 *****************************************************************************/
1460 static void print_linkstatus (t_or * orp, u16_t status) {
1461 int err;
1462 u16_t d;
1463 char *s;
1464 hermes_t *hw = &(orp->hw);
1466 switch (status) {
1467 case HERMES_LINKSTATUS_NOT_CONNECTED:
1468 s = "Not Connected";
1469 break;
1470 case HERMES_LINKSTATUS_CONNECTED:
1471 s = "Connected";
1472 break;
1473 case HERMES_LINKSTATUS_DISCONNECTED:
1474 s = "Disconnected";
1475 break;
1476 case HERMES_LINKSTATUS_AP_CHANGE:
1477 s = "AP Changed";
1478 break;
1479 case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
1480 s = "AP Out of Range";
1481 break;
1482 case HERMES_LINKSTATUS_AP_IN_RANGE:
1483 s = "AP In Range";
1484 break;
1485 case HERMES_LINKSTATUS_ASSOC_FAILED:
1486 s = "Association Failed";
1487 break;
1488 default:
1489 s = "UNKNOWN";
1492 printf ("%s: link status: %s, ", orp->or_name, s);
1494 err = hermes_read_wordrec (hw, USER_BAP,
1495 HERMES_RID_CURRENTCHANNEL, &d);
1496 if (err) {
1497 printf ("%s: Error %d \n", orp->or_name, err);
1498 return;
1500 printf("channel: %d, freq: %ld MHz ",
1501 d, (channel_frequency[d-1]));
1506 /*****************************************************************************
1507 * or_check_ints *
1509 * Process events which have been postponed in the interrupt handler *
1510 *****************************************************************************/
1511 static void or_check_ints (t_or * orp)
1513 if (orp->or_need_reset)
1514 or_reset();
1515 if ((orp->rx_first!=orp->rx_last) && (orp->or_flags & OR_F_READING)) {
1516 orp->or_ev_rx = 0;
1517 or_readv_s (&orp->or_rx_mess, TRUE);
1520 if (orp->or_send_int) {
1521 or_writev_s (&orp->or_tx_mess, TRUE);
1524 if (orp->or_flags & (OR_F_PACK_SENT | OR_F_PACK_RECV)) {
1525 reply (orp);
1530 /*****************************************************************************
1531 * is_ethersnap *
1533 * is there an LLC and SNAP header in the ethernet packet? The inet task *
1534 * isn't very interested in it... *
1535 *****************************************************************************/
1536 static int is_ethersnap(struct header_struct *hdr) {
1538 /* We de-encapsulate all packets which, a) have SNAP headers
1539 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
1540 * and where b) the OUI of the SNAP header is 00:00:00 or
1541 * 00:00:f8 - we need both because different APs appear to use
1542 * different OUIs for some reason */
1543 return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
1544 && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
1547 /*****************************************************************************
1548 * or_readv_s *
1550 * Copy the data which is stored in orp->rx_buf[orp->rx_first] in the vector *
1551 * which was given with the message *mp *
1552 *****************************************************************************/
1553 static void or_readv_s (message * mp, int from_int)
1555 int i, j, n, o, s, count, size, cps;
1556 int iov_offset = 0, length;
1557 t_or *orp;
1558 iovec_s_t *iovp;
1559 u8_t *databuf;
1561 orp = &or_state;
1563 orp->or_client = mp->m_source;
1564 count = mp->DL_COUNT;
1566 assert (orp->or_mode == OR_M_ENABLED);
1567 assert (orp->or_flags & OR_F_ENABLED);
1569 if (!from_int && (orp->rx_first==orp->rx_last))
1572 /* if we are not called from a hard int (data is not yet available) and
1573 * there are no buffers (or->rx_buf[x]) which contain any data, we cant
1574 * copy any data to the inet server. Goto suspend, and wait for data
1575 * to arrive */
1576 goto suspend_readv_s;
1581 /* and store the pointer to this data in databuf */
1582 databuf = &(orp->rx_buf[orp->rx_first][0]);
1583 length = orp->rx_length[orp->rx_first];
1585 orp->rxfid[orp->rx_first] = NO_FID;
1586 orp->rx_length[orp->rx_first] = 0;
1588 /* Next time, the next buffer with data will be retrieved */
1589 orp->rx_first++;
1590 orp->rx_first %= NR_RX_BUFS;
1592 o = 0;
1593 /* The data which we want to be copied to the vector starts at
1594 * *databuf and will be copied to the vecor below */
1595 size = 0;
1596 for (i = 0; i < count; i += IOVEC_NR,
1597 iov_offset += IOVEC_NR * sizeof(orp->or_iovec_s[0])) {
1598 n = IOVEC_NR;
1599 if (i + n > count)
1600 n = count - i;
1602 cps = sys_safecopyfrom(mp->m_source, mp->DL_GRANT, iov_offset,
1603 (vir_bytes)orp->or_iovec_s,
1604 n * sizeof(orp->or_iovec_s[0]));
1605 if (cps != OK)
1606 panic("orinoco: warning: sys_safecopytp failed: %d", cps);
1608 for (j = 0, iovp = orp->or_iovec_s; j < n; j++, iovp++) {
1609 s = iovp->iov_size;
1610 if (size + s > length) {
1611 assert (length > size);
1612 s = length - size;
1614 cps = sys_safecopyto(mp->m_source, iovp->iov_grant, 0,
1615 (vir_bytes) databuf + o, s);
1616 if (cps != OK)
1617 panic("orinoco: warning: sys_safecopy failed: %d", cps);
1619 size += s;
1620 if (size == length)
1621 break;
1622 o += s;
1624 if (size == length)
1625 break;
1628 assert(size >= length);
1630 orp->or_stat.ets_packetR++;
1631 orp->or_read_s = length;
1632 orp->or_flags &= ~OR_F_READING;
1633 orp->or_flags |= OR_F_PACK_RECV;
1635 if (!from_int) {
1636 /* There was data in the orp->rx_buf[x] which is now copied to
1637 * the inet sever. Tell the inet server */
1638 reply (orp);
1641 return;
1642 suspend_readv_s:
1643 if (from_int) {
1644 assert (orp->or_flags & OR_F_READING);
1645 /* No need to store any state */
1646 return;
1649 /* We want to store the message, so that next time when we are called
1650 * by hard int, we know where to copy the received data */
1651 orp->or_rx_mess = *mp;
1652 assert (!(orp->or_flags & OR_F_READING));
1653 orp->or_flags |= OR_F_READING;
1655 reply (orp);
1660 /*****************************************************************************
1661 * or_get_recvd_packet *
1663 * The card has received data. Retrieve the data from the card and put it *
1664 * in a buffer in the driver (in the orp structure) *
1665 *****************************************************************************/
1666 static int or_get_recvd_packet(t_or *orp, u16_t rxfid, u8_t *databuf) {
1667 struct hermes_rx_descriptor desc;
1668 hermes_t *hw;
1669 struct header_struct hdr;
1670 int err, length, offset;
1671 u16_t status;
1673 memset(databuf, 0, IEEE802_11_FRAME_LEN);
1675 hw = &(orp->hw);
1677 /* Read the data from the buffer in the card which holds the data.
1678 * First get the descriptor which will tell us whether the packet is
1679 * healthy*/
1680 err = hermes_bap_pread (hw, IRQ_BAP, &desc, sizeof (desc), rxfid, 0);
1681 if (err) {
1682 printf("Orinoco: error %d reading Rx descriptor. "
1683 "Frame dropped\n", err);
1684 orp->or_stat.ets_recvErr++;
1685 return -1;
1688 status = desc.status;
1690 if (status & HERMES_RXSTAT_ERR) {
1691 if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
1692 printf("Error reading Orinoco Rx descriptor.Dropped");
1693 } else {
1694 orp->or_stat.ets_CRCerr++;
1695 printf("Orinoco: Bad CRC on Rx. Frame dropped\n");
1697 orp->or_stat.ets_recvErr++;
1698 return -1;
1701 /* For now we ignore the 802.11 header completely, assuming
1702 that the card's firmware has handled anything vital. The only
1703 thing we want to know is the length of the received data */
1704 err = hermes_bap_pread (hw, IRQ_BAP, &hdr, sizeof (hdr),
1705 rxfid, HERMES_802_3_OFFSET);
1707 if (err) {
1708 printf("Orinoco: error %d reading frame header. "
1709 "Frame dropped\n", err);
1710 orp->or_stat.ets_recvErr++;
1711 return -1;
1714 length = ntohs (hdr.len);
1716 /* Sanity checks */
1717 if (length < 3) {
1718 /* No for even an 802.2 LLC header */
1719 printf("Orinoco: error in frame length: length = %d\n",
1720 length);
1721 /* orp->or_stat.ets_recvErr++; */
1722 return -1;
1725 if (length > IEEE802_11_DATA_LEN) {
1726 printf("Orinoco: Oversized frame received (%d bytes)\n",
1727 length);
1728 orp->or_stat.ets_recvErr++;
1729 return -1;
1732 length += sizeof (struct ethhdr);
1733 offset = HERMES_802_3_OFFSET;
1735 /* Read the interesting parts of the data to the drivers memory. This
1736 * would be everything from the 802.3 layer and up */
1737 err = hermes_bap_pread (hw,
1738 IRQ_BAP, (void *) databuf, RUP_EVEN (length),
1739 rxfid, offset);
1741 if (err) {
1742 printf("Orinoco: error doing hermes_bap_pread()\n");
1743 orp->or_stat.ets_recvErr++;
1744 return -1;
1747 /* Some types of firmware give us the SNAP and OUI headers. Remove these.
1749 if (is_ethersnap(&hdr)) {
1750 length -= 8;
1753 memcpy (databuf + ETH_ALEN * 2,
1754 databuf + sizeof(struct header_struct) - 2,
1755 length - ETH_ALEN * 2);
1758 if(length<60) length=60;
1760 return length;
1763 /*****************************************************************************
1764 * or_getstat_s *
1766 * Return the statistics structure. The statistics aren't updated until now, *
1767 * so this won't return much interesting yet. *
1768 *****************************************************************************/
1769 static void or_getstat_s (message * mp) {
1770 int r;
1771 eth_stat_t stats;
1772 t_or *orp;
1774 orp = &or_state;
1776 assert (orp->or_mode == OR_M_ENABLED);
1777 assert (orp->or_flags & OR_F_ENABLED);
1779 stats = orp->or_stat;
1781 r = sys_safecopyto(mp->m_source, mp->DL_GRANT, 0,
1782 (vir_bytes) &stats, sizeof(stats));
1783 if(r != OK) {
1784 panic("or_getstat_s: sys_safecopyto failed: %d", r);
1787 mp->m_type = DL_STAT_REPLY;
1789 r = send(mp->m_source, mp);
1790 if(r != OK)
1791 panic("orinoco: getstat_s failed: %d", r);