dec21140A ethernet driver for virtualpc, contributed by nicolas tittley.
[minix.git] / drivers / orinoco / orinoco.c
blob17302cd47a4215681eb9b30226f8845435c8b8ec
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>
10 * * The valid messages and their parameters are:
12 * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
13 * |------------+----------+---------+----------+---------+---------+---------|
14 * | HARDINT | | | | | | |
15 * |------------|----------|---------|----------|---------|---------|---------|
16 * | DL_WRITE | port nr | proc nr | count | mode | address | |
17 * |------------|----------|---------|----------|---------|---------|---------|
18 * | DL_WRITEV | port nr | proc nr | count | mode | address | |
19 * |------------|----------|---------|----------|---------|---------|---------|
20 * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant |
21 * |------------|----------|---------|----------|---------|---------|---------|
22 * | DL_READ | port nr | proc nr | count | | address | |
23 * |------------|----------|---------|----------|---------|---------|---------|
24 * | DL_READV | port nr | proc nr | count | | address | |
25 * |------------|----------|---------|----------|---------|---------|---------|
26 * | DL_READV_S | port nr | proc nr | count | | | grant |
27 * |------------|----------|---------|----------|---------|---------|---------|
28 * | DL_CONF | port nr | proc nr | | mode | address | |
29 * |------------|----------|---------|----------|---------|---------|---------|
30 * | DL_GETSTAT | port nr | proc nr | | | address | |
31 * |------------|----------|---------|----------|---------|---------|---------|
32 * |DL_GETSTAT_S| port nr | proc nr | | | | grant |
33 * |------------|----------|---------|----------|---------|---------|---------|
34 * | DL_STOP | port_nr | | | | | |
35 * |------------|----------|---------|----------|---------|---------|---------|
37 * The messages sent are:
39 * m_type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
40 * |------------|----------|---------|----------|---------|---------|
41 * |DL_TASK_REPL| port nr | proc nr | rd-count | err|stat| clock |
42 * |------------|----------|---------|----------|---------|---------|
44 * m_type m3_i1 m3_i2 m3_ca1
45 * |------------|---------|-----------|---------------|
46 * |DL_CONF_REPL| port nr | last port | ethernet addr |
47 * |------------|---------|-----------|---------------|
49 * m_type DL_PORT DL_STAT
50 * |------------|---------|-----------|
51 * |DL_STAT_REPL| port nr | err |
52 * |------------|---------|-----------|
56 #include "../drivers.h"
57 #include <string.h>
58 #include <stddef.h>
59 #include <minix/keymap.h>
60 #include <minix/syslib.h>
61 #include <minix/type.h>
62 #include <minix/sysutil.h>
63 #include <timers.h>
64 #include <sys/ioc_memory.h>
65 #include <ibm/pci.h>
66 #include <minix/ds.h>
67 #include <minix/endpoint.h>
68 #include "../../kernel/const.h"
69 #include "../../kernel/config.h"
70 #include "../../kernel/type.h"
72 #define tmra_ut timer_t
73 #define tmra_inittimer(tp) tmr_inittimer(tp)
74 #define VERBOSE 1 /* display message during init */
76 PRIVATE struct pcitab {
77 u16_t vid;
78 u16_t did;
79 int checkclass;
80 } pcitab[]=
82 { 0x1260, 0x3873, 0 },
83 { 0x1186, 0x1300, 0 },
84 { 0x0000, 0x0000, 0 }
88 static tmra_ut or_watchdog;
90 #include <stdio.h>
91 #include <stdlib.h>
92 #include <minix/com.h>
93 #include <minix/portio.h>
94 #include <net/hton.h>
95 #include <net/gen/ether.h>
96 #include <net/gen/eth_io.h>
97 #include <sys/vm_i386.h>
98 #include <sys/types.h>
99 #include <fcntl.h>
100 #include <unistd.h>
101 #include <errno.h>
103 #include "assert.h"
104 #include "hermes.h"
105 #include "hermes_rid.h"
106 #include "orinoco.h"
108 #define ERR -1
110 #define debug 0
112 #define OR_M_ENABLED 1
113 #define OR_M_DISABLED 0
114 #define OR_F_EMPTY 0
115 #define OR_F_MULTI 1
116 #define OR_F_BROAD (1<<1)
117 #define OR_F_ENABLED (1<<2)
118 #define OR_F_PROMISC (1<<3)
119 #define OR_F_READING (1<<4)
120 #define OR_F_SEND_AVAIL (1<<5)
121 #define OR_F_PACK_SENT (1<<6)
122 #define OR_F_PACK_RECV (1<<7)
123 #define ORINOCO_INTEN ( HERMES_EV_RX | HERMES_EV_ALLOC |\
124 HERMES_EV_WTERR | HERMES_EV_TXEXC|\
125 HERMES_EV_INFO | HERMES_EV_INFDROP|\
126 HERMES_EV_TX)
128 #define NO_FID (-1)
129 #define ETH_ALEN 6
130 #define USER_BAP 0
131 #define IRQ_BAP 1
132 #define ETH_HLEN 14
134 static int or_nr_task = ANY;
135 static t_or or_table[OR_PORT_NR];
137 struct ethhdr {
138 u8_t h_dest[ETH_ALEN];
139 u8_t h_src[ETH_ALEN];
140 u16_t h_proto;
143 struct header_struct {
144 /* 802.3 */
145 u8_t dest[ETH_ALEN];
146 u8_t src[ETH_ALEN];
147 u16_t len;
148 /* 802.2 */
149 u8_t dsap;
150 u8_t ssap;
151 u8_t ctrl;
152 /* SNAP */
153 u8_t oui[3];
154 u16_t ethertype;
157 #define RUP_EVEN(x) (((x) + 1) & (~1))
159 u8_t encaps_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
160 #define ENCAPS_OVERHEAD (sizeof (encaps_hdr) + 2)
162 /********************************************************************
163 * Data tables *
164 ********************************************************************/
166 /* The frequency of each channel in MHz */
167 const long channel_frequency[] = {
168 2412, 2417, 2422, 2427, 2432, 2437, 2442,
169 2447, 2452, 2457, 2462, 2467, 2472, 2484
172 #define NUM_CHANNELS (sizeof(channel_frequency) / sizeof(channel_frequency[0]))
174 /* This tables gives the actual meanings of the bitrate IDs returned by the
175 * firmware. Not used yet */
176 struct {
177 int bitrate; /* in 100s of kilobits */
178 int automatic;
179 u16_t txratectrl;
180 } bitrate_table[] =
182 {110, 1, 15}, /* Entry 0 is the default */
183 {10, 0, 1},
184 {10, 1, 1},
185 {20, 0, 2},
186 {20, 1, 3},
187 {55, 0, 4},
188 {55, 1, 7},
189 {110, 0, 8},};
191 #define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
194 _PROTOTYPE (static void or_writev, (message * mp, int from_int, int vectored));
195 _PROTOTYPE (static void or_readv, (message * mp, int from_int, int vectored));
196 _PROTOTYPE (static void or_writev_s, (message * mp, int from_int));
197 _PROTOTYPE (static void or_readv_s, (message * mp, int from_int));
198 _PROTOTYPE (static void reply, (t_or * orp, int err, int may_block));
199 _PROTOTYPE (static int or_probe, (t_or *));
200 _PROTOTYPE (static void or_ev_info, (t_or *));
201 _PROTOTYPE (static void or_init, (message *));
202 _PROTOTYPE (static void or_pci_conf, (void));
203 _PROTOTYPE (static void or_init_struct, (t_or *));
204 _PROTOTYPE (static void map_hw_buffer, (t_or *));
205 _PROTOTYPE (static void or_init_hw, (t_or *));
206 _PROTOTYPE (static void or_check_ints, (t_or *));
207 _PROTOTYPE (static void or_writerids, (hermes_t *, t_or *));
208 _PROTOTYPE (static void or_readrids, (hermes_t *, t_or *));
209 _PROTOTYPE (static void or_rec_mode, (t_or *));
210 _PROTOTYPE (static void mess_reply, (message *, message *));
211 _PROTOTYPE (static u32_t or_get_bar, (int devind, t_or * orp));
212 _PROTOTYPE (static void or_getstat, (message * mp));
213 _PROTOTYPE (static void or_getstat_s, (message * mp));
214 _PROTOTYPE (static void print_linkstatus, (t_or * orp, u16_t status));
215 _PROTOTYPE (static int or_get_recvd_packet, (t_or *orp, u16_t rxfid,
216 u8_t *databuf));
217 _PROTOTYPE (static void orinoco_stop, (void));
218 _PROTOTYPE (static void or_reset, (void));
219 _PROTOTYPE (static void or_watchdog_f, (timer_t *tp) );
220 _PROTOTYPE (static void setup_wepkey, (t_or *orp, char *wepkey0) );
221 _PROTOTYPE (static void or_getstat, (message *m));
222 _PROTOTYPE (static int do_hard_int, (void));
223 _PROTOTYPE (static void check_int_events, (void));
224 _PROTOTYPE (static void or_getname, (message *m));
225 _PROTOTYPE (static int or_handler, (t_or *orp));
226 _PROTOTYPE (static void or_dump, (message *m));
228 /* The message used in the main loop is made global, so that rl_watchdog_f()
229 * can change its message type to fake an interrupt message.
231 PRIVATE message m;
232 PRIVATE int int_event_check; /* set to TRUE if events arrived */
234 u32_t system_hz;
236 static char *progname;
237 extern int errno;
239 /* SEF functions and variables. */
240 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
241 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
242 EXTERN int env_argc;
243 EXTERN char **env_argv;
245 /*****************************************************************************
246 * main *
249 * The main function of the driver, receiving and processing messages *
250 *****************************************************************************/
251 int main(int argc, char *argv[]) {
252 int r;
254 /* SEF local startup. */
255 env_setargs(argc, argv);
256 sef_local_startup();
258 while (TRUE) {
259 if ((r = sef_receive (ANY, &m)) != OK)
260 panic(__FILE__, "orinoco: sef_receive failed", NO_NUM);
262 if (is_notify(m.m_type)) {
263 switch (_ENDPOINT_P(m.m_source)) {
264 case CLOCK:
265 or_watchdog_f(NULL);
266 break;
267 case HARDWARE:
268 do_hard_int();
269 if (int_event_check)
270 check_int_events();
271 break ;
272 case TTY_PROC_NR:
273 or_dump(&m);
274 break;
275 case PM_PROC_NR:
277 sigset_t set;
279 if (getsigset(&set) != 0) break;
281 if (sigismember(&set, SIGTERM))
282 orinoco_stop();
284 break;
286 default:
287 panic(__FILE__,
288 "orinoco: illegal notify from:",
289 m.m_source);
292 /* done, get new message */
293 continue;
296 switch (m.m_type) {
297 case DL_WRITEV:
298 or_writev (&m, FALSE, TRUE);
299 break;
300 case DL_WRITEV_S:
301 or_writev_s (&m, FALSE);
302 break;
303 case DL_WRITE:
304 or_writev (&m, FALSE, FALSE);
305 break;
306 case DL_READ:
307 or_readv (&m, FALSE, FALSE);
308 break;
309 case DL_READV:
310 or_readv (&m, FALSE, TRUE);
311 break;
312 case DL_READV_S:
313 or_readv_s (&m, FALSE);
314 break;
315 case DL_CONF:
316 or_init (&m);
317 break;
318 case DL_GETSTAT:
319 or_getstat (&m);
320 break;
321 case DL_GETSTAT_S:
322 or_getstat_s (&m);
323 break;
324 case DL_GETNAME:
325 or_getname(&m);
326 break;
327 default:
328 panic(__FILE__,"orinoco: illegal message:", m.m_type);
333 /*===========================================================================*
334 * sef_local_startup *
335 *===========================================================================*/
336 PRIVATE void sef_local_startup()
338 /* Register init callbacks. */
339 sef_setcb_init_fresh(sef_cb_init_fresh);
340 sef_setcb_init_restart(sef_cb_init_fresh);
342 /* No live update support for now. */
344 /* Let SEF perform startup. */
345 sef_startup();
348 /*===========================================================================*
349 * sef_cb_init_fresh *
350 *===========================================================================*/
351 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
353 /* Initialize the orinoco driver. */
354 int fkeys, sfkeys, r;
355 u32_t inet_proc_nr;
357 system_hz = sys_hz();
359 (progname=strrchr(env_argv[0],'/')) ? progname++
360 : (progname=env_argv[0]);
362 /* Observe some function key for debug dumps. */
363 fkeys = sfkeys = 0; bit_set(sfkeys, 11);
364 if ((r=fkey_map(&fkeys, &sfkeys)) != OK)
365 printf("Warning: orinoco couldn't observe F-key(s): %d\n",r);
367 /* Try to notify INET that we are present (again). If INET cannot
368 * be found, assume this is the first time we started and INET is
369 * not yet alive. */
370 r = ds_retrieve_label_num("inet", &inet_proc_nr);
371 if (r == OK)
372 notify(inet_proc_nr);
373 else if (r != ESRCH)
374 printf("orinoco: ds_retrieve_label_num failed for 'inet': %d\n", r);
376 return(OK);
379 /*****************************************************************************
380 * check_int_events *
382 * If a hard interrupt message came in, call the or_check_ints for the right *
383 * card *
384 *****************************************************************************/
385 static void check_int_events(void) {
386 int i;
387 t_or *orp;
389 /* the interrupt message doesn't contain information about the port, try
390 * to find it */
391 for (orp = or_table;
392 orp < or_table + OR_PORT_NR; orp++) {
393 if (orp->or_mode != OR_M_ENABLED)
394 continue;
395 if (!orp->or_got_int)
396 continue;
397 orp->or_got_int = 0;
398 assert (orp->or_flags & OR_F_ENABLED);
399 or_check_ints (orp);
404 /****************************************************************************
405 * or_getname *
407 * Gets the drivers name, orinoco *
408 ****************************************************************************/
409 static void or_getname(message *mp) {
410 int r;
412 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
413 mp->DL_NAME[sizeof(mp->DL_NAME) - 1] = '\0';
414 mp->m_type = DL_NAME_REPLY;
416 r = send(mp->m_source, mp);
417 if(r != OK) {
418 panic(__FILE__, "or_getname: send failed", r);
422 /*****************************************************************************
423 * do_hard_int *
425 * Process the interrupts which the card generated *
426 *****************************************************************************/
427 static int do_hard_int(void) {
428 u16_t evstat;
429 hermes_t *hw;
430 int i,s;
431 t_or *orp;
433 for (i=0; i < OR_PORT_NR; i ++) {
434 /* Run interrupt handler at driver level. */
435 or_handler( &or_table[i]);
437 /* Reenable interrupts for this hook. */
438 if ((s=sys_irqenable(&or_table[i].or_hook_id)) != OK) {
439 printf("orinoco: error, couldn't enable");
440 printf(" interrupts: %d\n", s);
447 /*****************************************************************************
448 * orinoco_stop *
450 * Stops the card. The signal to the card itself is not implemented yet. *
451 *****************************************************************************/
452 static void orinoco_stop () {
453 int i;
454 t_or *orp;
456 for (i= 0, orp= &or_table[0]; i<OR_PORT_NR; i++, orp++) {
457 if (orp->or_mode != OR_M_ENABLED)
458 continue;
459 /* TODO: send a signal to the card to shut it down */
461 exit(0);
464 /*****************************************************************************
465 * or_reset *
467 * Sometime the card gets screwed, behaving erratically. Solution: reset the *
468 * card. This is actually largely redoing the initialization *
469 *****************************************************************************/
470 static void or_reset() {
471 static clock_t last_reset, now;
472 t_or *orp;
473 int i, j, r;
474 u16_t irqmask;
476 if (OK != (r = getuptime(&now)))
477 panic(__FILE__, "orinoco: getuptime() failed:", r);
479 if(now - last_reset < system_hz * 10) {
480 printf("Resetting card too often. Going to reset driver\n");
481 exit(1);
484 for (i = 0, orp = or_table; orp < or_table + OR_PORT_NR; i++, orp++) {
485 if(orp->or_mode == OR_M_DISABLED)
486 printf("orinoco port %d is disabled\n", i);
488 if(orp->or_mode != OR_M_ENABLED) {
489 continue;
492 orp->or_need_reset = 0;
493 or_init_hw(orp);
495 orp->rx_last = orp->rx_first = 0;
496 for(j = 0; j < NR_RX_BUFS; j++) {
497 orp->rx_length[0] = 0;
500 if(orp->or_flags & OR_F_SEND_AVAIL) {
501 orp->or_tx.ret_busy = FALSE;
502 orp->or_send_int = TRUE;
506 last_reset = now;
510 /*****************************************************************************
511 * or_dump *
513 * Dump interesting information about the card on F-key pressed. *
514 * Not implemented yet *
515 *****************************************************************************/
516 static void or_dump (message *m) {
517 t_or *orp;
518 int i, err;
519 u16_t evstat =0, d;
521 for (i = 0, orp = or_table; orp < or_table + OR_PORT_NR; i++, orp++) {
522 if(orp->or_mode == OR_M_DISABLED) {
523 printf("%s is disabled\n", orp->or_name);
526 if(orp->or_mode != OR_M_ENABLED)
527 continue;
529 m->m_type = FKEY_CONTROL;
530 m->FKEY_REQUEST = FKEY_EVENTS;
531 if(OK!=(sendrec(TTY_PROC_NR,m)) )
532 printf("Contacting the TTY failed\n");
534 if(bit_isset(m->FKEY_SFKEYS, 11)) {
535 print_linkstatus(orp, orp->last_linkstatus);
540 /*****************************************************************************
541 * or_init *
543 * The main initialization function, called when a DL_INIT message comes in. *
544 *****************************************************************************/
545 static void or_init (message * mp) {
546 int port, err, i;
547 t_or *orp;
548 message reply;
549 static int first_time = 1;
550 hermes_t *hw;
551 clock_t t0,t1;
553 if (first_time) {
554 first_time = 0;
555 or_pci_conf (); /* Configure PCI devices. */
557 tmra_inittimer(&or_watchdog);
558 /* Use a synchronous alarm instead of a watchdog timer. */
559 sys_setalarm(system_hz, 0);
562 port = mp->DL_PORT;
563 if (port < 0 || port >= OR_PORT_NR) {
564 /* illegal port in message */
565 reply.m_type = DL_CONF_REPLY;
566 reply.m3_i1 = ENXIO;
567 mess_reply (mp, &reply);
568 return;
571 /* the port resolves to the main orinoco structure */
572 orp = &or_table[port];
573 /* resolving to the main hardware structure */
574 hw = &(orp->hw);
576 if (orp->or_mode == OR_M_DISABLED) {
577 /* Initialize the orp structure */
578 or_init_struct (orp);
579 if (orp->or_mode == OR_M_DISABLED) {
580 reply.m_type = DL_CONF_REPLY;
581 reply.m3_i1 = ENXIO;
582 mess_reply (mp, &reply);
583 return;
585 if (orp->or_mode == OR_M_ENABLED) {
586 /* initialize card, hardware/firmware */
587 orp->or_flags |= OR_F_ENABLED;
588 or_init_hw (orp);
592 assert (orp->or_mode == OR_M_ENABLED);
593 assert (orp->or_flags & OR_F_ENABLED);
595 /* Not supported by the driver yet, but set a couple of options:
596 * multicasting, promiscuity, broadcasting, depending on the users
597 * needs */
598 orp->or_flags &= ~(OR_F_PROMISC | OR_F_MULTI | OR_F_BROAD);
599 if (mp->DL_MODE & DL_PROMISC_REQ)
600 orp->or_flags |= OR_F_PROMISC;
601 if (mp->DL_MODE & DL_MULTI_REQ)
602 orp->or_flags |= OR_F_MULTI;
603 if (mp->DL_MODE & DL_BROAD_REQ)
604 orp->or_flags |= OR_F_BROAD;
606 orp->or_client = mp->m_source;
607 or_rec_mode (orp);
609 /* reply the caller that the configuration succeeded */
610 reply.m_type = DL_CONF_REPLY;
611 reply.m3_i1 = mp->DL_PORT;
612 reply.m3_i2 = OR_PORT_NR;
613 *(ether_addr_t *) reply.m3_ca1 = orp->or_address;
614 mess_reply (mp, &reply);
617 /*****************************************************************************
618 * or_pci_conf *
620 * Configure the pci related issues of the card, e.g. finding out where the *
621 * card is in the pci configuration, it's assigned irq, etc. This can be *
622 * done if the boot monitor is provided with information, or the pci bus *
623 * can be searched (at the end: or_probe function) *
624 *****************************************************************************/
625 static void or_pci_conf () {
626 long v;
627 t_or *orp;
628 int i, h;
629 static char envfmt[] = "*:d.d.d";
630 static char envvar[] = OR_ENVVAR "#";
631 static char val[128];
633 /* extract information from the boot monitor about the pci
634 * configuration if provided */
635 for (i = 0, orp = or_table; i < OR_PORT_NR; i++, orp++) {
636 strncpy (orp->or_name, OR_NAME, sizeof(OR_NAME));
637 orp->or_name[sizeof(OR_NAME) - 2] = i + '0';
638 orp->or_seen = FALSE;
639 /* whats this envvar; whats the definition;*/
640 /* i guess this whole loop could be removed*/
641 envvar[sizeof (OR_ENVVAR) - 1] = '0' + i;
642 if (0 == env_get_param(envvar, val, sizeof(val)) &&
643 ! env_prefix(envvar, "pci")) {
644 env_panic(envvar);
646 v = 0;
647 (void) env_parse (envvar, envfmt, 1, &v, 0, 255);
648 orp->or_pci_bus = v;
649 v = 0;
650 (void) env_parse (envvar, envfmt, 2, &v, 0, 255);
651 orp->or_pci_dev = v;
652 v = 0;
653 (void) env_parse (envvar, envfmt, 3, &v, 0, 255);
654 orp->or_pci_func = v;
657 /* Initialize the pci bus, bridges and cards, if not yet done */
658 pci_init ();
660 /* Try to find out where the card(s) are in the pci bus */
661 for (h = 1; h >= 0; h--)
662 for (i = 0, orp = or_table; i < OR_PORT_NR; i++, orp++) {
663 if (((orp->or_pci_bus | orp->or_pci_dev |
664 orp->or_pci_func) != 0) != h) {
665 continue;
667 if (or_probe (orp))
668 orp->or_seen = TRUE;
672 /*****************************************************************************
673 * or_probe *
675 * Try to find the card based on information provided by pci and get irq and *
676 * bar *
677 *****************************************************************************/
678 static int or_probe (t_or * orp) {
679 u8_t ilr;
680 u32_t bar, reg, cpuspace_bar;
681 char *dname;
682 u16_t vid, did;
683 int i, r, devind, just_one;
685 if ((orp->or_pci_bus | orp->or_pci_dev | orp->or_pci_func) != 0) {
686 /* The monitor has provided us with clues about where the
687 * device is. Try to find it at that place */
688 r = pci_find_dev (orp->or_pci_bus, orp->or_pci_dev,
689 orp->or_pci_func, &devind);
690 if (r == 0) {
691 printf ("%s: no PCI found at %d.%d.%d\n",
692 orp->or_name, orp->or_pci_bus,
693 orp->or_pci_dev, orp->or_pci_func);
694 return (0);
696 /* get the information about the card, vendor id and device
697 * id */
698 pci_ids (devind, &vid, &did);
699 just_one = TRUE;
700 } else {
701 /* no clue where the card is. Start looking from the
702 * beginning */
703 r = pci_first_dev (&devind, &vid, &did);
704 if (r == 0)
705 return (0);
706 just_one = FALSE;
709 while (TRUE) {
710 /* loop through the pcitab to find a maching entry. The match
711 * being between one of the values in pcitab and the
712 * information provided by the pci bus */
713 for (i = 0; pcitab[i].vid != 0; i++) {
714 if (pcitab[i].vid != vid)
715 continue;
716 if (pcitab[i].did != did)
717 continue;
718 if (pcitab[i].checkclass) {
719 panic(__FILE__, "or_probe:class check not implmnted",
720 NO_NUM);
722 /* we have found the card in the pci bus */
723 break;
725 if (pcitab[i].vid != 0)
726 break;
728 if (just_one) {
729 printf ("%s: wrong PCI device", orp->or_name);
730 printf (" (%04x/%04x) found at %d.%d.%d\n", vid, did,
731 orp->or_pci_bus, orp->or_pci_dev,
732 orp->or_pci_func);
733 return (0);
736 /* if the pci device which was under consideration was not
737 * of the desired brand or type, get the next device */
738 r = pci_next_dev (&devind, &vid, &did);
739 if (!r)
740 return (0);
743 /* Get the name as advertised by pci */
744 dname = pci_dev_name (vid, did);
745 if (!dname)
746 dname = "unknown device";
747 printf ("%s: %s (%04x/%04x) at %s\n",
748 orp->or_name, dname, vid, did, pci_slot_name (devind));
750 pci_reserve (devind);
752 orp->devind = devind;
753 /* Get the irq */
754 ilr = pci_attr_r8 (devind, PCI_ILR);
755 orp->or_irq = ilr;
757 /* Get the base address */
758 bar = or_get_bar (devind, orp);
759 orp->or_base_port = bar;
761 map_hw_buffer(orp);
762 return TRUE;
765 /*****************************************************************************
766 * map_hw_buffer *
768 * Map the memory mapped registers into user space memory *
769 *****************************************************************************/
770 static void map_hw_buffer(t_or *orp) {
771 int r;
772 size_t o, size, reg_size;
773 char *buf, *abuf;
774 hermes_t *hw = &(orp->hw);
776 /* This way, the buffer will be at least I386_PAGE_SIZE big: see
777 * calculation with the offset */
778 size = 2 * I386_PAGE_SIZE;
780 buf = (char *)malloc(size);
781 if(buf == NULL)
782 panic(__FILE__, "map_hw_buffer: cannot malloc size:", size);
784 /* Let the mapped memory by I386_PAGE_SIZE aligned */
785 o = I386_PAGE_SIZE - ((vir_bytes)buf % I386_PAGE_SIZE);
786 abuf = buf + o;
788 #if 0
789 r = sys_vm_map(SELF, 1, (vir_bytes)abuf,
790 1 * I386_PAGE_SIZE, (phys_bytes)orp->or_base_port);
791 #else
792 r = ENOSYS;
793 #endif
795 if(r!=OK)
796 panic(__FILE__, "map_hw_buffer: sys_vm_map failed:", r);
799 hw->locmem = abuf;
804 /*****************************************************************************
805 * or_get_bar *
807 * Get the base address from pci (from Base Address Register) and find out *
808 * whether the card is memory mapped or in I/O space. Currently, only *
809 * memmory mapped is supported. *
810 *****************************************************************************/
811 static u32_t or_get_bar (int devind, t_or * orp) {
813 u32_t bar, desired_bar;
814 int is_iospace, i;
815 u16_t check, check2;
816 hermes_t *hw = &(orp->hw);
818 /* bit 1 off the PCI_BAR register indicates whether the cards registers
819 * are mapped in io-space or shared memory */
820 is_iospace = pci_attr_r32 (devind, PCI_BAR) & 1;
822 if (is_iospace) {
823 /* read where the base address is in I/O space */
824 bar = pci_attr_r32 (devind, PCI_BAR) & 0xffffffe0;
826 if ((bar & 0x3ff) >= 0x100 - 32 || bar < 0x400)
827 panic(__FILE__,"base address isn't properly configured",
828 NO_NUM);
830 /* In I/O space registers are 2 bytes wide, without any spacing
831 * in between */
832 hermes_struct_init (hw, bar, is_iospace,
833 HERMES_16BIT_REGSPACING);
835 if (debug) {
836 printf ("%s: using I/O space address 0x%lx, IRQ %d\n",
837 orp->or_name, bar, orp->or_irq);
840 panic(__FILE__, "Not implemente yet", NO_NUM);
841 /* Although we are able to find the desired bar and irq for an
842 * I/O spaced card, we haven't implemented the right register
843 * accessing functions. This wouldn't be difficult, but we were
844 * not able to test them. Therefore, give an alert here */
846 return bar;
847 } else {
848 /* read where the base address is in shared memory */
849 bar = pci_attr_r32 (devind, PCI_BAR) & 0xfffffff0;
850 /* maybe some checking whether the address is legal... */
852 /* Memory mapped registers are 2 bytes wide, aligned on 4
853 * bytes */
854 hermes_struct_init (hw, bar, is_iospace,
855 HERMES_32BIT_REGSPACING);
857 if (debug){
858 printf ("%s: using shared memory address",
859 orp->or_name);
860 printf (" 0x%lx, IRQ %d\n", bar, orp->or_irq);
863 return bar;
868 /*****************************************************************************
869 * or_init_struct *
871 * Set the orinoco structure to default values *
872 *****************************************************************************/
873 static void or_init_struct (t_or * orp) {
874 int i = 0;
875 static eth_stat_t empty_stat = { 0, 0, 0, 0, 0, 0 };
877 orp->or_mode = OR_M_DISABLED;
879 if (orp->or_seen)
880 orp->or_mode = OR_M_ENABLED;
882 if (orp->or_mode != OR_M_ENABLED)
883 return;
885 orp->or_got_int = 0;
886 orp->or_link_up = -1;
887 orp->or_send_int = 0;
888 orp->or_clear_rx = 0;
889 orp->or_tx_alive = 0;
890 orp->or_need_reset = 0;
892 orp->or_read_s = 0;
893 orp->or_tx_head = 0;
894 orp->or_tx_tail = 0;
895 orp->connected = 0;
897 orp->or_tx.ret_busy = FALSE;
898 orp->or_tx.or_txfid = NO_FID;
900 for(i = 0; i < NR_RX_BUFS; i++) {
901 orp->rxfid[i] = NO_FID;
902 orp->rx_length[i] = 0;
904 orp->rx_current = 0;
905 orp->rx_first = 0;
906 orp->rx_last = 0;
908 orp->or_stat = empty_stat;
909 orp->or_flags = OR_F_EMPTY;
911 /* Keep an administration in the driver whether the internal
912 buffer is in use. That's what ret_busy is for */
913 orp->or_tx.ret_busy = FALSE;
915 orp->or_nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
919 /*****************************************************************************
920 * or_init_hw *
922 * Initialize hardware and prepare for intercepting the interrupts. At the *
923 * end, the card is up and running *
924 *****************************************************************************/
925 static void or_init_hw (t_or * orp) {
926 int i, err, s;
927 hermes_t *hw = &(orp->hw);
928 static int first_time = TRUE;
930 /* first step in starting the card */
931 if (hermes_cor_reset(hw) != 0) {
932 printf ("%s: Failed to start the card\n", orp->or_name);
935 /* here begins the real things, yeah! ;) */
936 if (err = hermes_init (hw)) {
937 printf ("error value of hermes_init(): %d\n", err);
940 /* Get the MAC address (which is a data item in the card)*/
941 or_readrids (hw, orp);
943 /* Write a few rids to the card, e.g. WEP key*/
944 or_writerids (hw, orp);
946 if (debug) {
947 printf ("%s: Ethernet address ", orp->or_name);
948 for (i = 0; i < 6; i++) {
949 printf ("%x%c", orp->or_address.ea_addr[i],
950 i < 5 ? ':' : '\n');
954 /* Prepare internal TX buffer in the card */
955 err = hermes_allocate (hw,
956 orp->or_nicbuf_size,
957 &(orp->or_tx.or_txfid));
959 if (err)
960 printf ("%s:Error %d allocating Tx buffer\n",
961 orp->or_name, err);
963 /* Establish event handle */
964 if(first_time) {
965 orp->or_hook_id = orp->or_irq;
966 if ((s=sys_irqsetpolicy(orp->or_irq, 0,
967 &orp->or_hook_id)) != OK)
968 printf("orinoco: couldn't set IRQ policy: %d\n", s);
970 if ((s=sys_irqenable(&orp->or_hook_id)) != OK)
971 printf("orinoco: couldn't enable interrupts: %d\n", s);
972 first_time = FALSE;
975 /* Tell the card which events should raise an interrupt to the OS */
976 hermes_set_irqmask (hw, ORINOCO_INTEN);
978 /* Enable operation */
979 err = hermes_docmd_wait (hw, HERMES_CMD_ENABLE, 0, NULL);
980 if (err) {
981 printf ("%s: Error %d enabling MAC port\n", orp->or_name, err);
986 /*****************************************************************************
987 * or_readrids *
989 * Read some default rids from the card. A rid (resource identifier) *
990 * is a data item in the firmware, some configuration variable. *
991 * In our case, we are mostly interested in the MAC address for now *
992 *****************************************************************************/
994 static void or_readrids (hermes_t * hw, t_or * orp) {
995 int err, len, i;
996 struct hermes_idstring nickbuf;
997 u16_t reclen, d;
999 /* Read the MAC address */
1000 err = hermes_read_ltv (hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
1001 ETH_ALEN, NULL, &orp->or_address);
1002 if (err) {
1003 printf ("%s: failed to read MAC address!\n", orp->or_name);
1004 return;
1009 /*****************************************************************************
1010 * or_writerids *
1012 * Write some default rids to the card. A rid (resource identifier) *
1013 * is a data item in the firmware, some configuration variable, e.g. WEP key *
1014 *****************************************************************************/
1015 static void or_writerids (hermes_t * hw, t_or * orp) {
1016 int err;
1017 struct hermes_idstring idbuf;
1018 u16_t port_type, max_data_len, reclen;
1019 static char essid[IW_ESSID_MAX_SIZE + 1];
1020 static char wepkey0[LARGE_KEY_LENGTH + 1];
1022 /* Set the MAC port */
1023 port_type = 1;
1024 err = hermes_write_wordrec (hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
1025 port_type);
1026 if (err) {
1027 printf ("%s: Error %d setting port type\n", orp->or_name, err);
1028 return;
1031 if (OK != env_get_param("essid", essid, sizeof(essid))) {
1032 essid[0] = 0;
1035 if(strlen(essid) == 0) {
1036 printf("%s: no essid provided in boot monitor!\n",
1037 orp->or_name);
1038 printf("Hope you'll connect to the right network... \n");
1041 /* Set the desired ESSID */
1042 idbuf.len = strlen (essid);
1043 memcpy (&idbuf.val, essid, sizeof (idbuf.val));
1045 err = hermes_write_ltv (hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
1046 HERMES_BYTES_TO_RECLEN (strlen (essid) + 2),
1047 &idbuf);
1048 if (err) {
1049 printf ("%s: Error %d setting DESIREDSSID\n",
1050 orp->or_name, err);
1051 return;
1054 if (OK != env_get_param("wep", wepkey0, sizeof(wepkey0))) {
1055 wepkey0[0] = 0;
1058 switch(strlen(wepkey0)) {
1059 case 0:
1060 /* No key found in monitor, using no encryption */
1061 break;
1062 case LARGE_KEY_LENGTH:
1063 setup_wepkey(orp, wepkey0);
1064 break;
1065 default:
1066 printf("Invalid key provided. Has to be 13 chars\n");
1067 break;
1071 /*****************************************************************************
1072 * setup_wepkey *
1074 * If a wepkey is provided in the boot monitor, set the necessary rids so *
1075 * that the card will decrypt received data and encrypt data to send by *
1076 * by default with this key. *
1077 * It appears that there is a severe bug in setting up WEP. If the driver *
1078 * doesnt function properly, please turn WEP off. *
1079 *****************************************************************************/
1080 static void setup_wepkey(t_or *orp, char *wepkey0) {
1081 int default_key = 0, err = 0;
1082 hermes_t *hw = &(orp->hw);
1084 err = hermes_write_wordrec (hw, USER_BAP,
1085 HERMES_RID_CNFWEPDEFAULTKEYID,
1086 default_key);
1087 if (err)
1088 printf ("%s: Error %d setting the default WEP-key entry\n",
1089 orp->or_name, err);
1091 err = hermes_write_ltv (hw, USER_BAP,
1092 HERMES_RID_CNFDEFAULTKEY0,
1093 HERMES_BYTES_TO_RECLEN(LARGE_KEY_LENGTH),
1094 wepkey0);
1095 if (err)
1096 printf ("%s: Error %d setting the WEP-key0\n",
1097 orp->or_name, err);
1099 err = hermes_write_wordrec (hw, USER_BAP,
1100 HERMES_RID_CNFAUTHENTICATION,
1101 HERMES_AUTH_OPEN);
1102 if (err)
1103 printf ("%s: Error %d setting the authentication flag\n",
1104 orp->or_name, err);
1106 err = hermes_write_wordrec (hw, USER_BAP,
1107 HERMES_RID_CNFWEPFLAGS_INTERSIL,
1108 HERMES_WEP_PRIVACY_INVOKED);
1109 if (err)
1110 printf ("%s: Error %d setting the master wep setting flag\n",
1111 orp->or_name, err);
1116 /*****************************************************************************
1117 * or_rec_mode *
1119 * Set the desired receive mode, e.g. promiscuous mode. Not implemented yet *
1120 *****************************************************************************/
1121 static void or_rec_mode (t_or * orp) {
1122 /* TODO */
1125 /*****************************************************************************
1126 * or_handler *
1128 * The handler which is called when the card generated an interrupt. Events *
1129 * like EV_INFO and EV_RX have to be handled before an acknowledgement for *
1130 * the event is returned to the card. See also the documentation *
1131 *****************************************************************************/
1132 static int or_handler (t_or *orp) {
1133 int i, err, length, nr = 0;
1134 u16_t evstat, events, fid;
1135 hermes_t *hw;
1136 struct hermes_tx_descriptor desc;
1138 hw = &(orp->hw);
1140 beginning:
1141 /* Retrieve which kind of event happened */
1142 evstat = hermes_read_reg (hw, HERMES_EVSTAT);
1143 events = evstat;
1145 /* There are plenty of events possible. The more interesting events
1146 are actually implemented. Whether the following events actually
1147 raise an interrupt depends on the value of ORINOCO_INTEN. For more
1148 information about the events, see the specification in pdf */
1150 /* Occurs at each tick of the auxiliary time */
1151 if (events & HERMES_EV_TICK) {
1152 events &= ~HERMES_EV_TICK;
1154 /* Occurs when a wait time-out error is detected */
1155 if (events & HERMES_EV_WTERR) {
1156 events &= ~HERMES_EV_WTERR;
1159 /* Occurs when an info frame is dropped because there is not enough
1160 buffer space available */
1161 if (events & HERMES_EV_INFDROP) {
1162 events &= ~(HERMES_EV_INFDROP);
1165 /* This AP-only event will be asserted at the beacon interval prior to
1166 the DTIM interval */
1167 if (events & HERMES_EV_DTIM) {
1168 events &= ~(HERMES_EV_DTIM);
1171 /* Occurs when a command execution is completed */
1172 if (events & HERMES_EV_CMD) {
1173 events &= ~(HERMES_EV_CMD);
1176 /* Occurs when the asynchronous transmission process is unsuccessfully
1177 completed */
1178 if (events & HERMES_EV_TXEXC) {
1180 /* What buffer generated the event? Represented by an fid */
1181 fid = hermes_read_reg(hw, HERMES_TXCOMPLFID);
1182 if(fid == 0xFFFF) {
1183 /* Illegal fid found */
1184 printf("unexpected txexc_fid interrupted\n");
1187 orp->or_tx.ret_busy = FALSE;
1189 if(orp->or_flags & OR_F_SEND_AVAIL) {
1190 orp->or_send_int = TRUE;
1191 if (!orp->or_got_int){
1192 orp->or_got_int = TRUE;
1193 int_event_check = TRUE;
1197 /* To detect illegal fids */
1198 hermes_write_reg(hw, HERMES_TXCOMPLFID, 0xFFFF);
1199 events &= ~(HERMES_EV_TXEXC);
1200 /* We don't do anything else yet.
1201 * Could be used for statistics */
1204 /* Occurs when the asynchronous transmission process is successfully
1205 completed */
1206 if (events & HERMES_EV_TX) {
1207 events &= ~(HERMES_EV_TX);
1208 /* Which buffer was sent, represented by an fid */
1209 fid = hermes_read_reg (hw, HERMES_TXCOMPLFID);
1210 if(fid == 0xFFFF) {
1211 /* Illegal fid found */
1212 printf("unexpected tx_fid interrupted\n");
1215 orp->or_tx.ret_busy = FALSE;
1217 if(orp->or_flags & OR_F_SEND_AVAIL) {
1218 orp->or_send_int = TRUE;
1219 if (!orp->or_got_int){
1220 orp->or_got_int = TRUE;
1221 int_event_check = TRUE;
1225 /* To detect illegal fids */
1226 hermes_write_reg(hw, HERMES_TXCOMPLFID, 0xFFFF);
1227 /* We don't do anything else when such event happens */
1230 /* Occurs when an info frame is available in the card */
1231 if (events & HERMES_EV_INFO) {
1232 events &= ~(HERMES_EV_INFO);
1233 /* Process the information, inside the handler (!) */
1234 or_ev_info(orp);
1237 /* Occurs when a TX buffer is available again for usage */
1238 if (events & HERMES_EV_ALLOC) {
1239 /* Which frame is now marked as free? */
1240 fid = hermes_read_reg (hw, HERMES_ALLOCFID);
1241 if (fid == 0xFFFF){
1242 /* An illegal frame identifier is found. Ignore */
1243 printf("Allocate event on unexpected fid\n");
1244 return ;
1247 /* To be able to detect illegal fids */
1248 hermes_write_reg(hw, HERMES_ALLOCFID, 0xFFFF);
1250 events &= ~(HERMES_EV_ALLOC);
1254 /* Occurs when a frame is received by the asynchronous reception
1255 * process */
1257 if (events & HERMES_EV_RX) {
1258 orp->or_ev_rx = TRUE;
1259 events &= ~(HERMES_EV_RX);
1261 /* If the last buffer is still filled with data, then we don't
1262 * have any buffers available to store the data */
1263 if(orp->rx_length[orp->rx_last] != 0) {
1264 /* indeed, we are going to overwrite information
1265 * in a buffer */
1268 /* Which buffer is storing the data (represented by a fid) */
1269 orp->rxfid[orp->rx_last]
1270 = hermes_read_reg (hw, HERMES_RXFID);
1272 /* Get the packet from the card and store it in
1273 * orp->rx_buf[orp->rx_last]. The length is returned by this
1274 * function */
1275 length = or_get_recvd_packet(orp, orp->rxfid[orp->rx_last],
1276 (orp->rx_buf[orp->rx_last]));
1278 if(length < 0) {
1279 /* Error happened. */
1280 printf("length < 0\n");
1281 goto next;
1282 } else {
1283 orp->rx_length[orp->rx_last] = length;
1286 /* The next buffer will be used the next time, circularly */
1287 orp->rx_last++;
1288 orp->rx_last %= NR_RX_BUFS;
1290 if (!orp->or_got_int){
1291 orp->or_got_int = TRUE;
1293 int_event_check = TRUE;
1295 next:
1296 if (events) {
1297 printf("Unknown event: 0x%x\n", events);
1300 /* Acknowledge to the card that the events have been processed. After
1301 * this the card will assume we have processed any buffer which were in
1302 * use for this event. */
1303 hermes_write_reg (hw, HERMES_EVACK, evstat);
1305 evstat = hermes_read_reg (hw, HERMES_EVSTAT);
1306 if(evstat != 0 && !(evstat & HERMES_EV_TICK)) {
1307 goto beginning;
1310 return (1);
1314 /*****************************************************************************
1315 * or_watchdog_f *
1317 * Will be called regularly to see whether the driver has crashed. If that *
1318 * condition is detected, reset the driver and card *
1319 *****************************************************************************/
1320 static void or_watchdog_f(timer_t *tp) {
1321 int i;
1322 t_or *orp;
1324 /* Use a synchronous alarm instead of a watchdog timer. */
1325 sys_setalarm(system_hz, 0);
1327 for (i= 0, orp = &or_table[0]; i<OR_PORT_NR; i++, orp++) {
1328 if (orp->or_mode != OR_M_ENABLED)
1329 continue;
1331 if (!(orp->or_flags & OR_F_SEND_AVAIL)) {
1332 /* Assume that an idle system is alive */
1333 orp->or_tx_alive= TRUE;
1334 continue;
1337 if (orp->connected == 0) {
1338 orp->or_tx_alive= TRUE;
1339 continue;
1341 if (orp->or_tx_alive) {
1342 orp->or_tx_alive= FALSE;
1343 continue;
1346 printf("or_watchdog_f: resetting port %d\n", i);
1348 orp->or_need_reset= TRUE;
1349 orp->or_got_int= TRUE;
1350 check_int_events();
1354 /*****************************************************************************
1355 * mess_reply *
1356 *****************************************************************************/
1358 static void mess_reply (message * req, message * reply_mess) {
1359 if (send (req->m_source, reply_mess) != 0)
1360 panic(__FILE__, "orinoco: unable to mess_reply", NO_NUM);
1364 /*****************************************************************************
1365 * or_writev *
1367 * As far as we can see, this function is never called from 3.1.3. However, *
1368 * it is still in rtl8139, so we'll keep it here as well. It's almost a copy *
1369 * of or_writev_s. We left out the comments. For an explanation, see *
1370 * or_writev_s *
1371 ******************************************************************************/
1372 static void or_writev (message * mp, int from_int, int vectored) {
1373 int port, or_client, count, size, err, data_len, data_off, tx_head;
1374 int o, j, n, i, s, p, cps ;
1375 struct ethhdr *eh;
1376 t_or *orp;
1377 clock_t timebefore, t0;
1378 phys_bytes phys_user;
1379 hermes_t *hw;
1380 struct hermes_tx_descriptor desc;
1381 struct header_struct hdr;
1383 iovec_t *iovp;
1384 phys_bytes phys_databuf;
1385 u16_t txfid;
1386 static u8_t databuf[IEEE802_11_DATA_LEN + ETH_HLEN + 2 + 1];
1387 memset (databuf, 0, IEEE802_11_DATA_LEN + ETH_HLEN + 3);
1389 port = mp->DL_PORT;
1390 count = mp->DL_COUNT;
1391 if (port < 0 || port >= OR_PORT_NR)
1392 panic(__FILE__, "orinoco: illegal port", NO_NUM);
1394 or_client = mp->DL_PROC;
1395 orp = &or_table[port];
1396 orp->or_client = or_client;
1397 hw = &(orp->hw);
1399 if (from_int) {
1400 assert (orp->or_flags & OR_F_SEND_AVAIL);
1401 orp->or_flags &= ~OR_F_SEND_AVAIL;
1402 orp->or_send_int = FALSE;
1403 orp->or_tx_alive = TRUE;
1406 if (orp->or_tx.ret_busy) {
1407 assert(!(orp->or_flags & OR_F_SEND_AVAIL));
1408 orp->or_flags |= OR_F_SEND_AVAIL;
1409 goto suspend_write;
1412 assert (orp->or_mode == OR_M_ENABLED);
1413 assert (orp->or_flags & OR_F_ENABLED);
1415 if (vectored) {
1417 int iov_offset = 0;
1418 size = 0;
1419 o = 0;
1421 for (i = 0; i < count; i += IOVEC_NR,
1422 iov_offset += IOVEC_NR * sizeof (orp->or_iovec[0])) {
1424 n = IOVEC_NR;
1425 if (i + n > count)
1426 n = count - i;
1427 cps = sys_vircopy(or_client, D,
1428 ((vir_bytes) mp->DL_ADDR) + iov_offset,
1429 SELF, D, (vir_bytes) orp->or_iovec,
1430 n * sizeof(orp->or_iovec[0]));
1431 if (cps != OK) printf("sys_vircopy failed: %d\n", cps);
1433 for (j = 0, iovp = orp->or_iovec; j < n; j++, iovp++) {
1434 s = iovp->iov_size;
1435 if (size + s > ETH_MAX_PACK_SIZE_TAGGED) {
1436 printf("invalid packet size\n");
1438 cps = sys_vircopy(or_client, D, iovp->iov_addr,
1439 SELF, D, (vir_bytes) databuf + o, s);
1440 if (cps != OK)
1441 printf("sys_vircopy failed: %d\n",cps);
1443 size += s;
1444 o += s;
1447 if (size < ETH_MIN_PACK_SIZE)
1448 printf("invalid packet size %d\n", size);
1449 } else {
1450 size = mp->DL_COUNT;
1451 if (size < ETH_MIN_PACK_SIZE
1452 || size > ETH_MAX_PACK_SIZE_TAGGED)
1453 printf("invalid packet size %d\n", size);
1455 cps = sys_vircopy(or_client, D, (vir_bytes)mp->DL_ADDR,
1456 SELF, D, (vir_bytes) databuf, size);
1457 if (cps != OK) printf("sys_abscopy failed: %d\n", cps);
1460 memset (&desc, 0, sizeof (desc));
1461 desc.tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
1463 err = hermes_bap_pwrite (hw, USER_BAP, &desc, sizeof (desc), txfid,
1465 if (err) {
1466 or_reset();
1467 goto fail;
1470 eh = (struct ethhdr *) databuf;
1471 if (ntohs (eh->h_proto) > 1500) {
1473 data_len = size - ETH_HLEN;
1474 data_off = HERMES_802_3_OFFSET + sizeof (hdr);
1476 memcpy (hdr.dest, eh->h_dest, ETH_ALEN);
1477 memcpy (hdr.src, eh->h_src, ETH_ALEN);
1478 hdr.len = htons (data_len + ENCAPS_OVERHEAD);
1480 memcpy (&hdr.dsap, &encaps_hdr, sizeof (encaps_hdr));
1481 hdr.ethertype = eh->h_proto;
1483 err = hermes_bap_pwrite (hw, USER_BAP, &hdr, sizeof (hdr),
1484 txfid, HERMES_802_3_OFFSET);
1485 if (err) {
1486 printf ("%s: Error %d writing packet header to BAP\n",
1487 orp->or_name, err);
1488 goto fail;
1491 p = ETH_HLEN;
1492 } else {
1493 data_len = size + ETH_HLEN;
1494 data_off = HERMES_802_3_OFFSET;
1495 p = 0;
1498 err = hermes_bap_pwrite (hw, USER_BAP,
1499 (void *) &(databuf[p]), RUP_EVEN (data_len),
1500 txfid, data_off);
1501 if (err) {
1502 printf ("hermes_bap_pwrite(data): error %d\n", err);
1503 goto fail;
1506 orp->or_tx.ret_busy = TRUE;
1508 err = hermes_docmd_wait (hw, HERMES_CMD_TX | HERMES_CMD_RECL,
1509 txfid, NULL);
1510 if (err) {
1511 orp->or_tx.ret_busy = FALSE;
1512 printf ("hermes_docmd_wait(TX|RECL): error %d\n", err);
1513 goto fail;
1516 fail:
1517 orp->or_flags |= OR_F_PACK_SENT;
1519 if (from_int) {
1520 return;
1523 reply (orp, OK, FALSE);
1524 return;
1526 suspend_write:
1527 orp->or_tx_mess = *mp;
1528 reply (orp, OK, FALSE);
1529 return;
1534 /*****************************************************************************
1535 * or_writev_s *
1537 * Write data which is denoted by the message to the card and send it. *
1538 *****************************************************************************/
1539 static void or_writev_s (message * mp, int from_int) {
1540 int port, or_client, count, size, err, data_len, data_off, tx_head;
1541 int o, j, n, i, s, p, cps ;
1542 struct ethhdr *eh;
1543 t_or *orp;
1544 clock_t timebefore, t0;
1545 phys_bytes phys_user;
1546 hermes_t *hw;
1547 struct hermes_tx_descriptor desc;
1548 int iov_offset = 0;
1549 struct header_struct hdr;
1550 iovec_s_t *iovp;
1551 phys_bytes phys_databuf;
1552 u16_t txfid;
1554 /* We need space for the max packet size itself, plus an ethernet
1555 * header, plus 2 bytes so we can align the IP header on a
1556 * 32bit boundary, plus 1 byte so we can read in odd length
1557 * packets from the card, which has an IO granularity of 16
1558 * bits */
1559 static u8_t databuf[IEEE802_11_DATA_LEN + ETH_HLEN + 2 + 1];
1560 memset (databuf, 0, IEEE802_11_DATA_LEN + ETH_HLEN + 3);
1562 port = mp->DL_PORT;
1563 count = mp->DL_COUNT;
1564 if (port < 0 || port >= OR_PORT_NR)
1565 panic(__FILE__, "orinoco: illegal port", NO_NUM);
1567 or_client = mp->DL_PROC;
1568 orp = &or_table[port];
1569 orp->or_client = or_client;
1570 hw = &(orp->hw);
1572 /* Switch off interrupts. The card is accessable via 2 BAPs, one for
1573 * reading and one for writing. In theory these BAPs should be
1574 * independent, but in practice, the are not. By switching off the
1575 * interrupts of the card, the chances of one interfering with the
1576 * other should be less */
1577 if (from_int){
1578 /* We were called with from_int, meaning that the last time we
1579 * were called, no tx buffers were available, and we had to
1580 * suspend. Now, we'll try again to find an empty buffer in the
1581 * card */
1582 assert (orp->or_flags & OR_F_SEND_AVAIL);
1583 orp->or_flags &= ~OR_F_SEND_AVAIL;
1584 orp->or_send_int = FALSE;
1585 orp->or_tx_alive = TRUE;
1588 txfid = orp->or_tx.or_txfid;
1590 if (orp->or_tx.ret_busy || orp->connected == 0) {
1591 /* there is no buffer in the card available */
1592 assert(!(orp->or_flags & OR_F_SEND_AVAIL));
1593 /* Remember that there is a packet to be sent available */
1594 orp->or_flags |= OR_F_SEND_AVAIL;
1595 goto suspend_write_s;
1598 assert (orp->or_mode == OR_M_ENABLED);
1599 assert (orp->or_flags & OR_F_ENABLED);
1602 /* Copy the data to be send from the vector to the databuf */
1603 size = 0;
1604 o = 0;
1605 for (i = 0; i < count; i += IOVEC_NR,
1606 iov_offset += IOVEC_NR * sizeof (orp->or_iovec_s[0])) {
1608 n = IOVEC_NR;
1609 if (i + n > count)
1610 n = count - i;
1612 cps = sys_safecopyfrom(or_client, mp->DL_GRANT, iov_offset,
1613 (vir_bytes) orp->or_iovec_s,
1614 n * sizeof(orp->or_iovec_s[0]), D);
1615 if (cps != OK)
1616 printf("orinoco: sys_safecopyfrom failed: %d\n", cps);
1618 for (j = 0, iovp = orp->or_iovec_s; j < n; j++, iovp++) {
1619 s = iovp->iov_size;
1620 if (size + s > ETH_MAX_PACK_SIZE_TAGGED) {
1621 printf("Orinoco: invalid pkt size\n");
1624 cps = sys_safecopyfrom(or_client, iovp->iov_grant, 0,
1625 (vir_bytes) databuf + o, s, D);
1626 if (cps != OK)
1627 printf("orinoco: sys_safecopyfrom failed:%d\n",
1628 cps);
1630 size += s;
1631 o += s;
1635 assert(size >= ETH_MIN_PACK_SIZE);
1637 memset (&desc, 0, sizeof (desc));
1638 /* Reclaim the tx buffer once the data is sent (OK), or it is clear
1639 * that transmission failed (EX). Reclaiming means that we can reuse
1640 * the buffer again for transmission */
1641 desc.tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
1642 /* Actually, this reclaim bit is the only thing which needs to be set
1643 * in the descriptor */
1644 err = hermes_bap_pwrite (hw, USER_BAP, &desc, sizeof (desc), txfid,
1646 if (err) {
1647 printf("hermes_bap_pwrite() descriptor error:resetting card\n");
1648 /* When this happens, the card is quite confused: it will not
1649 * recover. Reset it */
1650 or_reset();
1651 goto fail;
1654 eh = (struct ethhdr *) databuf;
1655 /* Encapsulate Ethernet-II frames */
1656 if (ntohs (eh->h_proto) > 1500) {
1657 /* Ethernet-II frame */
1658 data_len = size - ETH_HLEN;
1659 data_off = HERMES_802_3_OFFSET + sizeof (hdr);
1661 /* 802.3 header */
1662 memcpy (hdr.dest, eh->h_dest, ETH_ALEN);
1663 memcpy (hdr.src, eh->h_src, ETH_ALEN);
1664 hdr.len = htons (data_len + ENCAPS_OVERHEAD);
1666 /* 802.2 header */
1667 memcpy (&hdr.dsap, &encaps_hdr, sizeof (encaps_hdr));
1668 hdr.ethertype = eh->h_proto;
1670 err = hermes_bap_pwrite (hw, USER_BAP, &hdr, sizeof (hdr),
1671 txfid, HERMES_802_3_OFFSET);
1672 if (err) {
1673 printf ("%s: Error %d writing packet header to BAP\n",
1674 orp->or_name, err);
1675 goto fail;
1678 p = ETH_HLEN;
1679 } else {
1680 /* IEEE 802.3 frame */
1681 data_len = size + ETH_HLEN;
1682 data_off = HERMES_802_3_OFFSET;
1683 p = 0;
1686 /* Round up for odd length packets */
1687 err = hermes_bap_pwrite (hw, USER_BAP,
1688 (void *) &(databuf[p]), RUP_EVEN (data_len),
1689 txfid, data_off);
1690 if (err) {
1691 printf ("hermes_bap_pwrite(data): error %d\n", err);
1692 goto fail;
1695 /* this should be before the docmd_wait. Cause otherwise the bit can
1696 be cleared in the handler (if irq's not off) before it is set
1697 and then 1 reset (ret_busy=false) is lost */
1698 orp->or_tx.ret_busy = TRUE;
1700 /* Send the packet which was constructed in txfid */
1701 err = hermes_docmd_wait (hw, HERMES_CMD_TX | HERMES_CMD_RECL,
1702 txfid, NULL);
1703 if (err) {
1704 printf ("hermes_docmd_wait(TX|RECL): error %d\n", err);
1705 /* Mark the buffer as available again */
1706 orp->or_tx.ret_busy = FALSE;
1707 goto fail;
1710 fail:
1711 /* If the interrupt handler called, don't send a reply. The reply
1712 * will be sent after all interrupts are handled.
1714 orp->or_flags |= OR_F_PACK_SENT;
1716 if (from_int) {
1717 return;
1720 reply (orp, OK, FALSE);
1721 return;
1723 suspend_write_s:
1724 orp->or_tx_mess = *mp;
1726 reply (orp, OK, FALSE);
1727 return;
1731 /*****************************************************************************
1732 * reply *
1734 * Send a message back to the caller, informing it about the data received *
1735 * or sent *
1736 *****************************************************************************/
1737 static void reply (t_or * orp, int err, int may_block) {
1738 message reply;
1739 int status = 0, r;
1740 clock_t now;
1742 if (orp->or_flags & OR_F_PACK_SENT)
1743 status |= DL_PACK_SEND;
1744 if (orp->or_flags & OR_F_PACK_RECV)
1745 status |= DL_PACK_RECV;
1747 reply.m_type = DL_TASK_REPLY;
1748 reply.DL_PORT = orp - or_table;
1749 assert(reply.DL_PORT == 0);
1750 reply.DL_PROC = orp->or_client;
1751 reply.DL_STAT = status | ((u32_t) err << 16);
1752 reply.DL_COUNT = orp->or_read_s;
1754 if (OK != (r = getuptime(&now)))
1755 panic(__FILE__, "orinoco: getuptime() failed:", r);
1757 reply.DL_CLCK = now;
1758 r = send (orp->or_client, &reply);
1760 if (r == ELOCKED && may_block) {
1761 return;
1764 if (r < 0)
1765 panic(__FILE__, "orinoco: send failed:", r);
1767 orp->or_read_s = 0;
1768 orp->or_flags &= ~(OR_F_PACK_SENT | OR_F_PACK_RECV);
1773 /*****************************************************************************
1774 * or_ev_info *
1776 * Process information which comes in from the card *
1777 *****************************************************************************/
1778 static void or_ev_info (t_or * orp) {
1779 u16_t infofid;
1780 int err, len, type, i;
1781 hermes_t *hw = &orp->hw;
1783 struct {
1784 u16_t len;
1785 u16_t type;
1786 } info;
1788 infofid = hermes_read_reg (hw, HERMES_INFOFID);
1789 err = hermes_bap_pread (hw, IRQ_BAP, &info, sizeof (info), infofid,
1791 if (err) {
1792 printf ("%s: error %d reading info frame.\n", orp->or_name,
1793 err);
1794 return;
1797 len = HERMES_RECLEN_TO_BYTES (info.len);
1798 type = info.type;
1800 switch (type) {
1801 case HERMES_INQ_TALLIES:
1803 struct hermes_tallies_frame tallies;
1805 if (len > sizeof (tallies)) {
1806 printf ("%s: Tallies frame too long ",
1807 orp->or_name);
1808 printf ("(%d bytes)\n", len);
1809 len = sizeof (tallies);
1811 hermes_read_words (hw, HERMES_DATA1,
1812 (void *) &tallies, len / 2);
1813 /* TODO: do something with the tallies structure */
1815 break;
1817 case HERMES_INQ_LINKSTATUS: {
1818 u16_t newstatus;
1819 struct hermes_linkstatus linkstatus;
1821 if (len != sizeof (linkstatus)) {
1822 printf ("%s: Unexpected size for linkstatus ",
1823 orp->or_name);
1824 printf ("frame (%d bytes)\n", len);
1827 hermes_read_words (hw, HERMES_DATA1,
1828 (void *) &linkstatus, len / 2);
1829 newstatus = linkstatus.linkstatus;
1831 if ((newstatus == HERMES_LINKSTATUS_CONNECTED)
1832 || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
1833 || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE)) {
1834 orp->connected = 1;
1836 if(orp->or_flags & OR_F_SEND_AVAIL) {
1837 orp->or_send_int = TRUE;
1838 orp->or_got_int = TRUE;
1839 int_event_check = TRUE;
1844 else if ((newstatus ==
1845 HERMES_LINKSTATUS_NOT_CONNECTED)
1846 || (newstatus ==
1847 HERMES_LINKSTATUS_DISCONNECTED)
1848 || (newstatus ==
1849 HERMES_LINKSTATUS_AP_OUT_OF_RANGE)
1850 || (newstatus ==
1851 HERMES_LINKSTATUS_ASSOC_FAILED)) {
1852 orp->connected = 0;
1855 if (newstatus != orp->last_linkstatus)
1856 print_linkstatus(orp, newstatus);
1858 orp->last_linkstatus = newstatus;
1860 break;
1861 default:
1862 printf ("%s:Unknown information frame received(type %04x).\n",
1863 orp->or_name, type);
1864 break;
1868 /*****************************************************************************
1869 * or_print_linkstatus *
1871 * Process information which comes in from the card *
1872 *****************************************************************************/
1873 static void print_linkstatus (t_or * orp, u16_t status) {
1874 int err;
1875 u16_t d;
1876 char *s;
1877 hermes_t *hw = &(orp->hw);
1879 switch (status) {
1880 case HERMES_LINKSTATUS_NOT_CONNECTED:
1881 s = "Not Connected";
1882 break;
1883 case HERMES_LINKSTATUS_CONNECTED:
1884 s = "Connected";
1885 break;
1886 case HERMES_LINKSTATUS_DISCONNECTED:
1887 s = "Disconnected";
1888 break;
1889 case HERMES_LINKSTATUS_AP_CHANGE:
1890 s = "AP Changed";
1891 break;
1892 case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
1893 s = "AP Out of Range";
1894 break;
1895 case HERMES_LINKSTATUS_AP_IN_RANGE:
1896 s = "AP In Range";
1897 break;
1898 case HERMES_LINKSTATUS_ASSOC_FAILED:
1899 s = "Association Failed";
1900 break;
1901 default:
1902 s = "UNKNOWN";
1905 printf ("%s: link status: %s, ", orp->or_name, s);
1907 err = hermes_read_wordrec (hw, USER_BAP,
1908 HERMES_RID_CURRENTCHANNEL, &d);
1909 if (err) {
1910 printf ("%s: Error %d \n", orp->or_name, err);
1911 return;
1913 printf("channel: %d, freq: %d MHz ",
1914 d, (channel_frequency[d-1]));
1919 /*****************************************************************************
1920 * or_check_ints *
1922 * Process events which have been postponed in the interrupt handler *
1923 *****************************************************************************/
1924 static void or_check_ints (t_or * orp) {
1925 int or_flags;
1926 hermes_t *hw = &orp->hw;
1928 if (orp->or_need_reset)
1929 or_reset();
1930 if ((orp->rx_first!=orp->rx_last) && (orp->or_flags & OR_F_READING)) {
1931 orp->or_ev_rx = 0;
1932 if (orp->or_rx_mess.m_type == DL_READV) {
1933 or_readv (&orp->or_rx_mess, TRUE, TRUE);
1934 } else if(orp->or_rx_mess.m_type == DL_READV_S) {
1935 or_readv_s (&orp->or_rx_mess, TRUE);
1936 } else {
1937 assert(orp->or_rx_mess.m_type == DL_READ);
1938 or_readv (&orp->or_rx_mess, TRUE, FALSE);
1942 if (orp->or_send_int) {
1943 if (orp->or_tx_mess.m_type == DL_WRITEV) {
1944 or_writev (&orp->or_tx_mess, TRUE, TRUE);
1946 else if(orp->or_tx_mess.m_type == DL_WRITEV_S) {
1947 or_writev_s (&orp->or_tx_mess, TRUE);
1948 } else {
1949 assert(orp->or_tx_mess.m_type == DL_WRITE);
1950 or_writev (&orp->or_tx_mess, TRUE, FALSE);
1954 if (orp->or_flags & (OR_F_PACK_SENT | OR_F_PACK_RECV)) {
1955 reply (orp, OK, TRUE);
1960 /*****************************************************************************
1961 * is_ethersnap *
1963 * is there an LLC and SNAP header in the ethernet packet? The inet task *
1964 * isn't very interested in it... *
1965 *****************************************************************************/
1966 static int is_ethersnap(struct header_struct *hdr) {
1968 /* We de-encapsulate all packets which, a) have SNAP headers
1969 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
1970 * and where b) the OUI of the SNAP header is 00:00:00 or
1971 * 00:00:f8 - we need both because different APs appear to use
1972 * different OUIs for some reason */
1973 return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
1974 && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
1977 /*****************************************************************************
1978 * or_readv *
1980 * As far as we can see, this function is never called from 3.1.3. However, *
1981 * it is still in rtl8139, so we'll keep it here as well. It's almost a copy *
1982 * of or_readv_s. We left out the comments. For an explanation, see *
1983 * or_readv_s *
1984 *****************************************************************************/
1985 static void or_readv (message * mp, int from_int, int vectored) {
1986 int i, j, n, o, s, s1, dl_port, or_client, count, size, err, yep, cps;
1987 port_t port;
1988 clock_t timebefore;
1989 unsigned amount, totlen, packlen;
1990 struct hermes_rx_descriptor desc;
1991 phys_bytes dst_phys;
1992 u16_t d_start, d_end, rxfid, status;
1993 struct header_struct hdr;
1994 int length, offset;
1995 u32_t l, rxstat;
1996 struct ethhdr *eh;
1997 struct header_struct *h;
1998 t_or *orp;
1999 hermes_t *hw;
2000 iovec_t *iovp;
2001 u8_t *databuf;
2003 dl_port = mp->DL_PORT;
2004 count = mp->DL_COUNT;
2005 if (dl_port < 0 || dl_port >= OR_PORT_NR)
2006 panic(__FILE__, "orinoco: illegal port:", dl_port);
2008 orp = &or_table[dl_port];
2009 or_client = mp->DL_PROC;
2010 orp->or_client = or_client;
2011 hw = &(orp->hw);
2013 assert (orp->or_mode == OR_M_ENABLED);
2014 assert (orp->or_flags & OR_F_ENABLED);
2016 if (!from_int && (orp->rx_first==orp->rx_last)) {
2017 goto suspend_readv;
2020 rxfid = orp->rxfid[orp->rx_first];
2021 databuf = &(orp->rx_buf[orp->rx_first][0]);
2022 length = orp->rx_length[orp->rx_first];
2024 orp->rxfid[orp->rx_first] = NO_FID;
2025 orp->rx_length[orp->rx_first] = 0;
2027 orp->rx_first++;
2028 orp->rx_first %= NR_RX_BUFS;
2030 o = 0;
2032 if (vectored) {
2033 int iov_offset = 0;
2034 size = 0;
2036 for (i = 0; i < count; i += IOVEC_NR,
2037 iov_offset += IOVEC_NR * sizeof(orp->or_iovec[0])) {
2039 n = IOVEC_NR;
2040 if (i + n > count)
2041 n = count - i;
2043 cps = sys_vircopy(or_client, D,
2044 (vir_bytes) mp->DL_ADDR + iov_offset,
2045 SELF, D, (vir_bytes) orp->or_iovec,
2046 n * sizeof(orp->or_iovec[0]));
2047 if (cps != OK) printf("sys_vircopy failed: %d (%d)\n",
2048 cps, __LINE__);
2050 for (j = 0, iovp = orp->or_iovec; j < n; j++, iovp++) {
2051 s = iovp->iov_size;
2052 if (size + s > length) {
2053 assert (length > size);
2054 s = length - size;
2057 cps = sys_vircopy(SELF, D,
2058 (vir_bytes) databuf + o,
2059 or_client, D,
2060 iovp->iov_addr, s);
2061 if (cps != OK)
2062 printf("sys_vircopy failed:%d (%d)\n",
2063 cps, __LINE__);
2065 size += s;
2066 if (size == length)
2067 break;
2068 o += s;
2070 if (size == length)
2071 break;
2073 assert (size >= length);
2076 orp->or_stat.ets_packetR++;
2077 orp->or_read_s = length;
2078 orp->or_flags &= ~OR_F_READING;
2079 orp->or_flags |= OR_F_PACK_RECV;
2081 if (!from_int)
2082 reply (orp, OK, FALSE);
2084 return;
2086 suspend_readv :
2087 if (from_int) {
2088 assert (orp->or_flags & OR_F_READING);
2089 return;
2092 orp->or_rx_mess = *mp;
2093 assert (!(orp->or_flags & OR_F_READING));
2094 orp->or_flags |= OR_F_READING;
2096 reply (orp, OK, FALSE);
2100 /*****************************************************************************
2101 * or_readv_s *
2103 * Copy the data which is stored in orp->rx_buf[orp->rx_first] in the vector *
2104 * which was given with the message *mp *
2105 *****************************************************************************/
2106 static void or_readv_s (message * mp, int from_int) {
2107 int i, j, n, o, s, s1, dl_port, or_client, count, size, err, cps;
2108 int iov_offset = 0, length, offset;
2109 port_t port;
2110 clock_t timebefore;
2111 unsigned amount, totlen, packlen;
2112 struct hermes_rx_descriptor desc;
2113 phys_bytes dst_phys;
2114 u16_t d_start, d_end, rxfid, status;
2115 struct header_struct hdr;
2116 u32_t l, rxstat;
2117 struct ethhdr *eh;
2118 struct header_struct *h;
2119 t_or *orp;
2120 hermes_t *hw;
2122 iovec_s_t *iovp;
2123 phys_bytes databuf_phys;
2125 u8_t *databuf;
2127 dl_port = mp->DL_PORT;
2128 count = mp->DL_COUNT;
2129 if (dl_port < 0 || dl_port >= OR_PORT_NR)
2130 panic(__FILE__, "orinoco: illegal port:", dl_port);
2132 orp = &or_table[dl_port];
2133 or_client = mp->DL_PROC;
2134 orp->or_client = or_client;
2135 hw = &(orp->hw);
2137 assert (orp->or_mode == OR_M_ENABLED);
2138 assert (orp->or_flags & OR_F_ENABLED);
2140 if (!from_int && (orp->rx_first==orp->rx_last))
2143 /* if we are not called from a hard int (data is not yet available) and
2144 * there are no buffers (or->rx_buf[x]) which contain any data, we cant
2145 * copy any data to the inet server. Goto suspend, and wait for data
2146 * to arrive */
2147 goto suspend_readv_s;
2152 /* get the buffer which contains new data */
2153 rxfid = orp->rxfid[orp->rx_first];
2154 /* and store the pointer to this data in databuf */
2155 databuf = &(orp->rx_buf[orp->rx_first][0]);
2156 length = orp->rx_length[orp->rx_first];
2158 orp->rxfid[orp->rx_first] = NO_FID;
2159 orp->rx_length[orp->rx_first] = 0;
2161 /* Next time, the next buffer with data will be retrieved */
2162 orp->rx_first++;
2163 orp->rx_first %= NR_RX_BUFS;
2165 o = 0;
2166 /* The data which we want to be copied to the vector starts at
2167 * *databuf and will be copied to the vecor below */
2168 size = 0;
2169 for (i = 0; i < count; i += IOVEC_NR,
2170 iov_offset += IOVEC_NR * sizeof(orp->or_iovec_s[0])) {
2171 n = IOVEC_NR;
2172 if (i + n > count)
2173 n = count - i;
2175 cps = sys_safecopyfrom(or_client, mp->DL_GRANT, iov_offset,
2176 (vir_bytes)orp->or_iovec_s,
2177 n * sizeof(orp->or_iovec_s[0]), D);
2178 if (cps != OK)
2179 panic(__FILE__,
2180 "orinoco: warning, sys_safecopytp failed:", cps);
2182 for (j = 0, iovp = orp->or_iovec_s; j < n; j++, iovp++) {
2183 s = iovp->iov_size;
2184 if (size + s > length) {
2185 assert (length > size);
2186 s = length - size;
2188 cps = sys_safecopyto(or_client, iovp->iov_grant, 0,
2189 (vir_bytes) databuf + o, s, D);
2190 if (cps != OK)
2191 panic(__FILE__,
2192 "orinoco: warning, sys_safecopy failed:",
2193 cps);
2195 size += s;
2196 if (size == length)
2197 break;
2198 o += s;
2200 if (size == length)
2201 break;
2204 assert(size >= length);
2206 orp->or_stat.ets_packetR++;
2207 drop:
2208 orp->or_read_s = length;
2209 orp->or_flags &= ~OR_F_READING;
2210 orp->or_flags |= OR_F_PACK_RECV;
2212 if (!from_int) {
2213 /* There was data in the orp->rx_buf[x] which is now copied to
2214 * the inet sever. Tell the inet server */
2215 reply (orp, OK, FALSE);
2218 return;
2219 suspend_readv_s:
2220 if (from_int) {
2221 assert (orp->or_flags & OR_F_READING);
2222 /* No need to store any state */
2223 return;
2226 /* We want to store the message, so that next time when we are called
2227 * by hard int, we know where to copy the received data */
2228 orp->or_rx_mess = *mp;
2229 assert (!(orp->or_flags & OR_F_READING));
2230 orp->or_flags |= OR_F_READING;
2232 reply (orp, OK, FALSE);
2237 /*****************************************************************************
2238 * or_get_recvd_packet *
2240 * The card has received data. Retrieve the data from the card and put it *
2241 * in a buffer in the driver (in the orp structure) *
2242 *****************************************************************************/
2243 static int or_get_recvd_packet(t_or *orp, u16_t rxfid, u8_t *databuf) {
2244 struct hermes_rx_descriptor desc;
2245 hermes_t *hw;
2246 struct header_struct hdr;
2247 int err, length, offset;
2248 struct ethhdr *eh;
2249 u16_t status;
2251 memset(databuf, 0, IEEE802_11_FRAME_LEN);
2253 hw = &(orp->hw);
2255 /* Read the data from the buffer in the card which holds the data.
2256 * First get the descriptor which will tell us whether the packet is
2257 * healthy*/
2258 err = hermes_bap_pread (hw, IRQ_BAP, &desc, sizeof (desc), rxfid, 0);
2259 if (err) {
2260 printf("Orinoco: error %d reading Rx descriptor. "
2261 "Frame dropped\n", err);
2262 orp->or_stat.ets_recvErr++;
2263 return -1;
2266 status = desc.status;
2268 if (status & HERMES_RXSTAT_ERR) {
2269 if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
2270 printf("Error reading Orinoco Rx descriptor.Dropped");
2271 } else {
2272 orp->or_stat.ets_CRCerr++;
2273 printf("Orinoco: Bad CRC on Rx. Frame dropped\n");
2275 orp->or_stat.ets_recvErr++;
2276 return -1;
2279 /* For now we ignore the 802.11 header completely, assuming
2280 that the card's firmware has handled anything vital. The only
2281 thing we want to know is the length of the received data */
2282 err = hermes_bap_pread (hw, IRQ_BAP, &hdr, sizeof (hdr),
2283 rxfid, HERMES_802_3_OFFSET);
2285 if (err) {
2286 printf("Orinoco: error %d reading frame header. "
2287 "Frame dropped\n", err);
2288 orp->or_stat.ets_recvErr++;
2289 return -1;
2292 length = ntohs (hdr.len);
2294 /* Sanity checks */
2295 if (length < 3) {
2296 /* No for even an 802.2 LLC header */
2297 printf("Orinoco: error in frame length: length = %d\n",
2298 length);
2299 /* orp->or_stat.ets_recvErr++; */
2300 return -1;
2303 if (length > IEEE802_11_DATA_LEN) {
2304 printf("Orinoco: Oversized frame received (%d bytes)\n",
2305 length);
2306 orp->or_stat.ets_recvErr++;
2307 return -1;
2310 length += sizeof (struct ethhdr);
2311 offset = HERMES_802_3_OFFSET;
2313 /* Read the interesting parts of the data to the drivers memory. This
2314 * would be everything from the 802.3 layer and up */
2315 err = hermes_bap_pread (hw,
2316 IRQ_BAP, (void *) databuf, RUP_EVEN (length),
2317 rxfid, offset);
2319 if (err) {
2320 printf("Orinoco: error doing hermes_bap_pread()\n");
2321 orp->or_stat.ets_recvErr++;
2322 return -1;
2325 /* Some types of firmware give us the SNAP and OUI headers. Remove these.
2327 if (is_ethersnap(&hdr)) {
2328 eh = (struct ethhdr *) databuf;
2329 length -= 8;
2332 memcpy (databuf + ETH_ALEN * 2,
2333 databuf + sizeof(struct header_struct) - 2,
2334 length - ETH_ALEN * 2);
2337 if(length<60) length=60;
2339 return length;
2342 /*****************************************************************************
2343 * or_getstat *
2345 * Return the statistics structure. The statistics aren't updated until now, *
2346 * so this won't return much interesting yet. *
2347 *****************************************************************************/
2348 static void or_getstat (message * mp) {
2349 int r, port;
2350 eth_stat_t stats;
2351 t_or *orp;
2353 port = mp->DL_PORT;
2354 if (port < 0 || port >= OR_PORT_NR)
2355 panic(__FILE__, "orinoco: illegal port:", port);
2356 orp = &or_table[port];
2357 orp->or_client = mp->DL_PROC;
2359 assert (orp->or_mode == OR_M_ENABLED);
2360 assert (orp->or_flags & OR_F_ENABLED);
2362 stats = orp->or_stat;
2364 r = sys_datacopy(SELF, (vir_bytes)&stats, mp->DL_PROC,
2365 (vir_bytes) mp->DL_ADDR, sizeof(stats));
2366 if(r != OK) {
2367 panic(__FILE__, "or_getstat: send failed:", r);
2370 mp->m_type = DL_STAT_REPLY;
2371 mp->DL_PORT = port;
2372 mp->DL_STAT = OK;
2374 r = send(mp->m_source, mp);
2375 if(r != OK)
2376 panic(__FILE__, "orinoco: getstat failed:", r);
2378 /*reply (orp, OK, FALSE);*/
2382 /*****************************************************************************
2383 * or_getstat_s *
2385 * Return the statistics structure. The statistics aren't updated until now, *
2386 * so this won't return much interesting yet. *
2387 *****************************************************************************/
2388 static void or_getstat_s (message * mp) {
2389 int r, port;
2390 eth_stat_t stats;
2391 t_or *orp;
2393 port = mp->DL_PORT;
2394 if (port < 0 || port >= OR_PORT_NR)
2395 panic(__FILE__, "orinoco: illegal port:", port);
2396 assert(port==0);
2397 orp = &or_table[port];
2398 orp->or_client = mp->DL_PROC;
2400 assert (orp->or_mode == OR_M_ENABLED);
2401 assert (orp->or_flags & OR_F_ENABLED);
2403 stats = orp->or_stat;
2405 r = sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0,
2406 (vir_bytes) &stats, sizeof(stats), D);
2407 if(r != OK) {
2408 panic(__FILE__, "or_getstat_s: sys_safecopyto failed:", r);
2411 mp->m_type = DL_STAT_REPLY;
2412 mp->DL_PORT = port;
2413 mp->DL_STAT = OK;
2415 r = send(mp->m_source, mp);
2416 if(r != OK)
2417 panic(__FILE__, "orinoco: getstat_s failed:", r);