4 * This file contains a wireless device driver for Prism based wireless
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"
58 #include <minix/syslib.h>
59 #include <minix/type.h>
60 #include <minix/sysutil.h>
64 #include <minix/endpoint.h>
65 #include "../../kernel/const.h"
66 #include "../../kernel/config.h"
67 #include "../../kernel/type.h"
69 #define VERBOSE 1 /* display message during init */
71 PRIVATE
struct pcitab
{
77 { 0x1260, 0x3873, 0 },
78 { 0x1186, 0x1300, 0 },
83 static timer_t or_watchdog
;
87 #include <minix/com.h>
88 #include <minix/portio.h>
90 #include <net/gen/ether.h>
91 #include <net/gen/eth_io.h>
92 #include <sys/vm_i386.h>
93 #include <sys/types.h>
99 #include "hermes_rid.h"
106 #define OR_M_ENABLED 1
107 #define OR_M_DISABLED 0
110 #define OR_F_BROAD (1<<1)
111 #define OR_F_ENABLED (1<<2)
112 #define OR_F_PROMISC (1<<3)
113 #define OR_F_READING (1<<4)
114 #define OR_F_SEND_AVAIL (1<<5)
115 #define OR_F_PACK_SENT (1<<6)
116 #define OR_F_PACK_RECV (1<<7)
117 #define ORINOCO_INTEN ( HERMES_EV_RX | HERMES_EV_ALLOC |\
118 HERMES_EV_WTERR | HERMES_EV_TXEXC|\
119 HERMES_EV_INFO | HERMES_EV_INFDROP|\
128 PRIVATE t_or or_table
[OR_PORT_NR
];
131 u8_t h_dest
[ETH_ALEN
];
132 u8_t h_src
[ETH_ALEN
];
136 struct header_struct
{
150 #define RUP_EVEN(x) (((x) + 1) & (~1))
152 u8_t encaps_hdr
[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
153 #define ENCAPS_OVERHEAD (sizeof (encaps_hdr) + 2)
155 /********************************************************************
157 ********************************************************************/
159 /* The frequency of each channel in MHz */
160 PRIVATE
const long channel_frequency
[] = {
161 2412, 2417, 2422, 2427, 2432, 2437, 2442,
162 2447, 2452, 2457, 2462, 2467, 2472, 2484
165 #define NUM_CHANNELS (sizeof(channel_frequency) / sizeof(channel_frequency[0]))
167 /* This tables gives the actual meanings of the bitrate IDs returned by the
168 * firmware. Not used yet */
170 int bitrate
; /* in 100s of kilobits */
175 {110, 1, 15}, /* Entry 0 is the default */
184 #define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
187 _PROTOTYPE (static void or_writev
, (message
* mp
, int from_int
, int vectored
));
188 _PROTOTYPE (static void or_readv
, (message
* mp
, int from_int
, int vectored
));
189 _PROTOTYPE (static void or_writev_s
, (message
* mp
, int from_int
));
190 _PROTOTYPE (static void or_readv_s
, (message
* mp
, int from_int
));
191 _PROTOTYPE (static void reply
, (t_or
* orp
, int err
, int may_block
));
192 _PROTOTYPE (static int or_probe
, (t_or
*));
193 _PROTOTYPE (static void or_ev_info
, (t_or
*));
194 _PROTOTYPE (static void or_init
, (message
*));
195 _PROTOTYPE (static void or_pci_conf
, (void));
196 _PROTOTYPE (static void or_init_struct
, (t_or
*));
197 _PROTOTYPE (static void map_hw_buffer
, (t_or
*));
198 _PROTOTYPE (static void or_init_hw
, (t_or
*));
199 _PROTOTYPE (static void or_check_ints
, (t_or
*));
200 _PROTOTYPE (static void or_writerids
, (hermes_t
*, t_or
*));
201 _PROTOTYPE (static void or_readrids
, (hermes_t
*, t_or
*));
202 _PROTOTYPE (static void or_rec_mode
, (t_or
*));
203 _PROTOTYPE (static void mess_reply
, (message
*, message
*));
204 _PROTOTYPE (static u32_t or_get_bar
, (int devind
, t_or
* orp
));
205 _PROTOTYPE (static void or_getstat
, (message
* mp
));
206 _PROTOTYPE (static void or_getstat_s
, (message
* mp
));
207 _PROTOTYPE (static void print_linkstatus
, (t_or
* orp
, u16_t status
));
208 _PROTOTYPE (static int or_get_recvd_packet
, (t_or
*orp
, u16_t rxfid
,
210 _PROTOTYPE (static void orinoco_stop
, (void));
211 _PROTOTYPE (static void or_reset
, (void));
212 _PROTOTYPE (static void or_watchdog_f
, (timer_t
*tp
) );
213 _PROTOTYPE (static void setup_wepkey
, (t_or
*orp
, char *wepkey0
) );
214 _PROTOTYPE (static void or_getstat
, (message
*m
));
215 _PROTOTYPE (static int do_hard_int
, (void));
216 _PROTOTYPE (static void check_int_events
, (void));
217 _PROTOTYPE (static void or_getname
, (message
*m
));
218 _PROTOTYPE (static int or_handler
, (t_or
*orp
));
219 _PROTOTYPE (static void or_dump
, (message
*m
));
221 /* The message used in the main loop is made global, so that rl_watchdog_f()
222 * can change its message type to fake an interrupt message.
225 PRIVATE
int int_event_check
; /* set to TRUE if events arrived */
227 PRIVATE u32_t system_hz
;
229 PRIVATE
const char *progname
;
231 /* SEF functions and variables. */
232 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
233 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
234 EXTERN
char **env_argv
;
236 /*****************************************************************************
240 * The main function of the driver, receiving and processing messages *
241 *****************************************************************************/
242 int main(int argc
, char *argv
[]) {
245 /* SEF local startup. */
246 env_setargs(argc
, argv
);
250 if ((r
= sef_receive (ANY
, &m
)) != OK
)
251 panic("orinoco: sef_receive failed");
253 if (is_notify(m
.m_type
)) {
254 switch (_ENDPOINT_P(m
.m_source
)) {
270 if (getsigset(&set
) != 0) break;
272 if (sigismember(&set
, SIGTERM
))
278 panic("orinoco: illegal notify from: %d",
282 /* done, get new message */
288 or_writev (&m
, FALSE
, TRUE
);
291 or_writev_s (&m
, FALSE
);
294 or_writev (&m
, FALSE
, FALSE
);
297 or_readv (&m
, FALSE
, FALSE
);
300 or_readv (&m
, FALSE
, TRUE
);
303 or_readv_s (&m
, FALSE
);
318 panic("orinoco: illegal message: %d", m
.m_type
);
323 /*===========================================================================*
324 * sef_local_startup *
325 *===========================================================================*/
326 PRIVATE
void sef_local_startup()
328 /* Register init callbacks. */
329 sef_setcb_init_fresh(sef_cb_init_fresh
);
330 sef_setcb_init_restart(sef_cb_init_fresh
);
332 /* No live update support for now. */
334 /* Let SEF perform startup. */
338 /*===========================================================================*
339 * sef_cb_init_fresh *
340 *===========================================================================*/
341 PRIVATE
int sef_cb_init_fresh(int type
, sef_init_info_t
*info
)
343 /* Initialize the orinoco driver. */
344 int fkeys
, sfkeys
, r
;
347 system_hz
= sys_hz();
349 (progname
=strrchr(env_argv
[0],'/')) ? progname
++
350 : (progname
=env_argv
[0]);
352 /* Observe some function key for debug dumps. */
353 fkeys
= sfkeys
= 0; bit_set(sfkeys
, 11);
354 if ((r
=fkey_map(&fkeys
, &sfkeys
)) != OK
)
355 printf("Warning: orinoco couldn't observe F-key(s): %d\n",r
);
357 /* Try to notify INET that we are present (again). If INET cannot
358 * be found, assume this is the first time we started and INET is
360 r
= ds_retrieve_label_num("inet", &inet_proc_nr
);
362 notify(inet_proc_nr
);
364 printf("orinoco: ds_retrieve_label_num failed for 'inet': %d\n", r
);
369 /*****************************************************************************
372 * If a hard interrupt message came in, call the or_check_ints for the right *
374 *****************************************************************************/
375 static void check_int_events(void) {
379 /* the interrupt message doesn't contain information about the port, try
382 orp
< or_table
+ OR_PORT_NR
; orp
++) {
383 if (orp
->or_mode
!= OR_M_ENABLED
)
385 if (!orp
->or_got_int
)
388 assert (orp
->or_flags
& OR_F_ENABLED
);
394 /****************************************************************************
397 * Gets the drivers name, orinoco *
398 ****************************************************************************/
399 static void or_getname(message
*mp
) {
402 strncpy(mp
->DL_NAME
, progname
, sizeof(mp
->DL_NAME
));
403 mp
->DL_NAME
[sizeof(mp
->DL_NAME
) - 1] = '\0';
404 mp
->m_type
= DL_NAME_REPLY
;
406 r
= send(mp
->m_source
, mp
);
408 panic("or_getname: send failed: %d", r
);
412 /*****************************************************************************
415 * Process the interrupts which the card generated *
416 *****************************************************************************/
417 static int do_hard_int(void) {
423 for (i
=0; i
< OR_PORT_NR
; i
++) {
424 /* Run interrupt handler at driver level. */
425 or_handler( &or_table
[i
]);
427 /* Reenable interrupts for this hook. */
428 if ((s
=sys_irqenable(&or_table
[i
].or_hook_id
)) != OK
) {
429 printf("orinoco: error, couldn't enable");
430 printf(" interrupts: %d\n", s
);
437 /*****************************************************************************
440 * Stops the card. The signal to the card itself is not implemented yet. *
441 *****************************************************************************/
442 static void orinoco_stop () {
446 for (i
= 0, orp
= &or_table
[0]; i
<OR_PORT_NR
; i
++, orp
++) {
447 if (orp
->or_mode
!= OR_M_ENABLED
)
449 /* TODO: send a signal to the card to shut it down */
454 /*****************************************************************************
457 * Sometime the card gets screwed, behaving erratically. Solution: reset the *
458 * card. This is actually largely redoing the initialization *
459 *****************************************************************************/
460 static void or_reset() {
461 static clock_t last_reset
, now
;
466 if (OK
!= (r
= getuptime(&now
)))
467 panic("orinoco: getuptime() failed: %d", r
);
469 if(now
- last_reset
< system_hz
* 10) {
470 printf("Resetting card too often. Going to reset driver\n");
474 for (i
= 0, orp
= or_table
; orp
< or_table
+ OR_PORT_NR
; i
++, orp
++) {
475 if(orp
->or_mode
== OR_M_DISABLED
)
476 printf("orinoco port %d is disabled\n", i
);
478 if(orp
->or_mode
!= OR_M_ENABLED
) {
482 orp
->or_need_reset
= 0;
485 orp
->rx_last
= orp
->rx_first
= 0;
486 for(j
= 0; j
< NR_RX_BUFS
; j
++) {
487 orp
->rx_length
[0] = 0;
490 if(orp
->or_flags
& OR_F_SEND_AVAIL
) {
491 orp
->or_tx
.ret_busy
= FALSE
;
492 orp
->or_send_int
= TRUE
;
500 /*****************************************************************************
503 * Dump interesting information about the card on F-key pressed. *
504 * Not implemented yet *
505 *****************************************************************************/
506 static void or_dump (message
*m
)
512 for (orp
= or_table
; orp
< or_table
+ OR_PORT_NR
; orp
++) {
513 if(orp
->or_mode
== OR_M_DISABLED
) {
514 printf("%s is disabled\n", orp
->or_name
);
517 if(orp
->or_mode
!= OR_M_ENABLED
)
520 m
->m_type
= FKEY_CONTROL
;
521 m
->FKEY_REQUEST
= FKEY_EVENTS
;
522 if(OK
!=(sendrec(TTY_PROC_NR
,m
)) )
523 printf("Contacting the TTY failed\n");
525 if(bit_isset(m
->FKEY_SFKEYS
, 11)) {
526 print_linkstatus(orp
, orp
->last_linkstatus
);
531 /*****************************************************************************
534 * The main initialization function, called when a DL_INIT message comes in. *
535 *****************************************************************************/
536 static void or_init (message
* mp
) {
540 static int first_time
= 1;
545 or_pci_conf (); /* Configure PCI devices. */
547 tmr_inittimer(&or_watchdog
);
548 /* Use a synchronous alarm instead of a watchdog timer. */
549 sys_setalarm(system_hz
, 0);
553 if (port
< 0 || port
>= OR_PORT_NR
) {
554 /* illegal port in message */
555 reply
.m_type
= DL_CONF_REPLY
;
557 mess_reply (mp
, &reply
);
561 /* the port resolves to the main orinoco structure */
562 orp
= &or_table
[port
];
563 /* resolving to the main hardware structure */
565 if (orp
->or_mode
== OR_M_DISABLED
) {
566 /* Initialize the orp structure */
567 or_init_struct (orp
);
568 if (orp
->or_mode
== OR_M_DISABLED
) {
569 reply
.m_type
= DL_CONF_REPLY
;
571 mess_reply (mp
, &reply
);
574 if (orp
->or_mode
== OR_M_ENABLED
) {
575 /* initialize card, hardware/firmware */
576 orp
->or_flags
|= OR_F_ENABLED
;
581 assert (orp
->or_mode
== OR_M_ENABLED
);
582 assert (orp
->or_flags
& OR_F_ENABLED
);
584 /* Not supported by the driver yet, but set a couple of options:
585 * multicasting, promiscuity, broadcasting, depending on the users
587 orp
->or_flags
&= ~(OR_F_PROMISC
| OR_F_MULTI
| OR_F_BROAD
);
588 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
589 orp
->or_flags
|= OR_F_PROMISC
;
590 if (mp
->DL_MODE
& DL_MULTI_REQ
)
591 orp
->or_flags
|= OR_F_MULTI
;
592 if (mp
->DL_MODE
& DL_BROAD_REQ
)
593 orp
->or_flags
|= OR_F_BROAD
;
595 orp
->or_client
= mp
->m_source
;
598 /* reply the caller that the configuration succeeded */
599 reply
.m_type
= DL_CONF_REPLY
;
600 reply
.m3_i1
= mp
->DL_PORT
;
601 reply
.m3_i2
= OR_PORT_NR
;
602 *(ether_addr_t
*) reply
.m3_ca1
= orp
->or_address
;
603 mess_reply (mp
, &reply
);
606 /*****************************************************************************
609 * Configure the pci related issues of the card, e.g. finding out where the *
610 * card is in the pci configuration, it's assigned irq, etc. This can be *
611 * done if the boot monitor is provided with information, or the pci bus *
612 * can be searched (at the end: or_probe function) *
613 *****************************************************************************/
614 static void or_pci_conf () {
618 static char envfmt
[] = "*:d.d.d";
619 static char envvar
[] = OR_ENVVAR
"#";
620 static char val
[128];
622 /* extract information from the boot monitor about the pci
623 * configuration if provided */
624 for (i
= 0, orp
= or_table
; i
< OR_PORT_NR
; i
++, orp
++) {
625 strncpy (orp
->or_name
, OR_NAME
, sizeof(OR_NAME
));
626 orp
->or_name
[sizeof(OR_NAME
) - 2] = i
+ '0';
627 orp
->or_seen
= FALSE
;
628 /* whats this envvar; whats the definition;*/
629 /* i guess this whole loop could be removed*/
630 envvar
[sizeof (OR_ENVVAR
) - 1] = '0' + i
;
631 if (0 == env_get_param(envvar
, val
, sizeof(val
)) &&
632 ! env_prefix(envvar
, "pci")) {
636 (void) env_parse (envvar
, envfmt
, 1, &v
, 0, 255);
639 (void) env_parse (envvar
, envfmt
, 2, &v
, 0, 255);
642 (void) env_parse (envvar
, envfmt
, 3, &v
, 0, 255);
643 orp
->or_pci_func
= v
;
646 /* Initialize the pci bus, bridges and cards, if not yet done */
649 /* Try to find out where the card(s) are in the pci bus */
650 for (h
= 1; h
>= 0; h
--)
651 for (i
= 0, orp
= or_table
; i
< OR_PORT_NR
; i
++, orp
++) {
652 if (((orp
->or_pci_bus
| orp
->or_pci_dev
|
653 orp
->or_pci_func
) != 0) != h
) {
661 /*****************************************************************************
664 * Try to find the card based on information provided by pci and get irq and *
666 *****************************************************************************/
667 static int or_probe (t_or
* orp
) {
669 u32_t bar
, reg
, cpuspace_bar
;
672 int i
, r
, devind
, just_one
;
674 if ((orp
->or_pci_bus
| orp
->or_pci_dev
| orp
->or_pci_func
) != 0) {
675 /* The monitor has provided us with clues about where the
676 * device is. Try to find it at that place */
677 r
= pci_find_dev (orp
->or_pci_bus
, orp
->or_pci_dev
,
678 orp
->or_pci_func
, &devind
);
680 printf ("%s: no PCI found at %d.%d.%d\n",
681 orp
->or_name
, orp
->or_pci_bus
,
682 orp
->or_pci_dev
, orp
->or_pci_func
);
685 /* get the information about the card, vendor id and device
687 pci_ids (devind
, &vid
, &did
);
690 /* no clue where the card is. Start looking from the
692 r
= pci_first_dev (&devind
, &vid
, &did
);
699 /* loop through the pcitab to find a maching entry. The match
700 * being between one of the values in pcitab and the
701 * information provided by the pci bus */
702 for (i
= 0; pcitab
[i
].vid
!= 0; i
++) {
703 if (pcitab
[i
].vid
!= vid
)
705 if (pcitab
[i
].did
!= did
)
707 if (pcitab
[i
].checkclass
) {
708 panic("or_probe:class check not implmnted");
710 /* we have found the card in the pci bus */
713 if (pcitab
[i
].vid
!= 0)
717 printf ("%s: wrong PCI device", orp
->or_name
);
718 printf (" (%04x/%04x) found at %d.%d.%d\n", vid
, did
,
719 orp
->or_pci_bus
, orp
->or_pci_dev
,
724 /* if the pci device which was under consideration was not
725 * of the desired brand or type, get the next device */
726 r
= pci_next_dev (&devind
, &vid
, &did
);
731 /* Get the name as advertised by pci */
732 dname
= pci_dev_name (vid
, did
);
734 dname
= "unknown device";
735 printf ("%s: %s (%04x/%04x) at %s\n",
736 orp
->or_name
, dname
, vid
, did
, pci_slot_name (devind
));
738 pci_reserve (devind
);
740 orp
->devind
= devind
;
742 ilr
= pci_attr_r8 (devind
, PCI_ILR
);
745 /* Get the base address */
746 bar
= or_get_bar (devind
, orp
);
747 orp
->or_base_port
= bar
;
753 /*****************************************************************************
756 * Map the memory mapped registers into user space memory *
757 *****************************************************************************/
758 static void map_hw_buffer(t_or
*orp
) {
760 size_t o
, size
, reg_size
;
762 hermes_t
*hw
= &(orp
->hw
);
764 /* This way, the buffer will be at least I386_PAGE_SIZE big: see
765 * calculation with the offset */
766 size
= 2 * I386_PAGE_SIZE
;
768 buf
= (char *)malloc(size
);
770 panic("map_hw_buffer: cannot malloc size: %d", size
);
772 /* Let the mapped memory by I386_PAGE_SIZE aligned */
773 o
= I386_PAGE_SIZE
- ((vir_bytes
)buf
% I386_PAGE_SIZE
);
777 r
= sys_vm_map(SELF
, 1, (vir_bytes
)abuf
,
778 1 * I386_PAGE_SIZE
, (phys_bytes
)orp
->or_base_port
);
784 panic("map_hw_buffer: sys_vm_map failed: %d", r
);
792 /*****************************************************************************
795 * Get the base address from pci (from Base Address Register) and find out *
796 * whether the card is memory mapped or in I/O space. Currently, only *
797 * memmory mapped is supported. *
798 *****************************************************************************/
799 static u32_t
or_get_bar (int devind
, t_or
* orp
) {
801 u32_t bar
, desired_bar
;
804 hermes_t
*hw
= &(orp
->hw
);
806 /* bit 1 off the PCI_BAR register indicates whether the cards registers
807 * are mapped in io-space or shared memory */
808 is_iospace
= pci_attr_r32 (devind
, PCI_BAR
) & 1;
811 /* read where the base address is in I/O space */
812 bar
= pci_attr_r32 (devind
, PCI_BAR
) & 0xffffffe0;
814 if ((bar
& 0x3ff) >= 0x100 - 32 || bar
< 0x400)
815 panic("base address isn't properly configured");
817 /* In I/O space registers are 2 bytes wide, without any spacing
819 hermes_struct_init (hw
, bar
, is_iospace
,
820 HERMES_16BIT_REGSPACING
);
823 printf ("%s: using I/O space address 0x%lx, IRQ %d\n",
824 orp
->or_name
, bar
, orp
->or_irq
);
827 panic("Not implemente yet");
828 /* Although we are able to find the desired bar and irq for an
829 * I/O spaced card, we haven't implemented the right register
830 * accessing functions. This wouldn't be difficult, but we were
831 * not able to test them. Therefore, give an alert here */
835 /* read where the base address is in shared memory */
836 bar
= pci_attr_r32 (devind
, PCI_BAR
) & 0xfffffff0;
837 /* maybe some checking whether the address is legal... */
839 /* Memory mapped registers are 2 bytes wide, aligned on 4
841 hermes_struct_init (hw
, bar
, is_iospace
,
842 HERMES_32BIT_REGSPACING
);
845 printf ("%s: using shared memory address",
847 printf (" 0x%lx, IRQ %d\n", bar
, orp
->or_irq
);
855 /*****************************************************************************
858 * Set the orinoco structure to default values *
859 *****************************************************************************/
860 static void or_init_struct (t_or
* orp
) {
862 static eth_stat_t empty_stat
= { 0, 0, 0, 0, 0, 0 };
864 orp
->or_mode
= OR_M_DISABLED
;
867 orp
->or_mode
= OR_M_ENABLED
;
869 if (orp
->or_mode
!= OR_M_ENABLED
)
873 orp
->or_link_up
= -1;
874 orp
->or_send_int
= 0;
875 orp
->or_clear_rx
= 0;
876 orp
->or_tx_alive
= 0;
877 orp
->or_need_reset
= 0;
884 orp
->or_tx
.ret_busy
= FALSE
;
885 orp
->or_tx
.or_txfid
= NO_FID
;
887 for(i
= 0; i
< NR_RX_BUFS
; i
++) {
888 orp
->rxfid
[i
] = NO_FID
;
889 orp
->rx_length
[i
] = 0;
895 orp
->or_stat
= empty_stat
;
896 orp
->or_flags
= OR_F_EMPTY
;
898 /* Keep an administration in the driver whether the internal
899 buffer is in use. That's what ret_busy is for */
900 orp
->or_tx
.ret_busy
= FALSE
;
902 orp
->or_nicbuf_size
= IEEE802_11_FRAME_LEN
+ ETH_HLEN
;
906 /*****************************************************************************
909 * Initialize hardware and prepare for intercepting the interrupts. At the *
910 * end, the card is up and running *
911 *****************************************************************************/
912 static void or_init_hw (t_or
* orp
) {
914 hermes_t
*hw
= &(orp
->hw
);
915 static int first_time
= TRUE
;
917 /* first step in starting the card */
918 if (hermes_cor_reset(hw
) != 0) {
919 printf ("%s: Failed to start the card\n", orp
->or_name
);
922 /* here begins the real things, yeah! ;) */
923 if (err
= hermes_init (hw
)) {
924 printf ("error value of hermes_init(): %d\n", err
);
927 /* Get the MAC address (which is a data item in the card)*/
928 or_readrids (hw
, orp
);
930 /* Write a few rids to the card, e.g. WEP key*/
931 or_writerids (hw
, orp
);
934 printf ("%s: Ethernet address ", orp
->or_name
);
935 for (i
= 0; i
< 6; i
++) {
936 printf ("%x%c", orp
->or_address
.ea_addr
[i
],
941 /* Prepare internal TX buffer in the card */
942 err
= hermes_allocate (hw
,
944 &(orp
->or_tx
.or_txfid
));
947 printf ("%s:Error %d allocating Tx buffer\n",
950 /* Establish event handle */
952 orp
->or_hook_id
= orp
->or_irq
;
953 if ((s
=sys_irqsetpolicy(orp
->or_irq
, 0,
954 &orp
->or_hook_id
)) != OK
)
955 printf("orinoco: couldn't set IRQ policy: %d\n", s
);
957 if ((s
=sys_irqenable(&orp
->or_hook_id
)) != OK
)
958 printf("orinoco: couldn't enable interrupts: %d\n", s
);
962 /* Tell the card which events should raise an interrupt to the OS */
963 hermes_set_irqmask (hw
, ORINOCO_INTEN
);
965 /* Enable operation */
966 err
= hermes_docmd_wait (hw
, HERMES_CMD_ENABLE
, 0, NULL
);
968 printf ("%s: Error %d enabling MAC port\n", orp
->or_name
, err
);
973 /*****************************************************************************
976 * Read some default rids from the card. A rid (resource identifier) *
977 * is a data item in the firmware, some configuration variable. *
978 * In our case, we are mostly interested in the MAC address for now *
979 *****************************************************************************/
981 static void or_readrids (hermes_t
* hw
, t_or
* orp
) {
983 struct hermes_idstring nickbuf
;
986 /* Read the MAC address */
987 err
= hermes_read_ltv (hw
, USER_BAP
, HERMES_RID_CNFOWNMACADDR
,
988 ETH_ALEN
, NULL
, &orp
->or_address
);
990 printf ("%s: failed to read MAC address!\n", orp
->or_name
);
996 /*****************************************************************************
999 * Write some default rids to the card. A rid (resource identifier) *
1000 * is a data item in the firmware, some configuration variable, e.g. WEP key *
1001 *****************************************************************************/
1002 static void or_writerids (hermes_t
* hw
, t_or
* orp
) {
1004 struct hermes_idstring idbuf
;
1005 u16_t port_type
, max_data_len
, reclen
;
1006 static char essid
[IW_ESSID_MAX_SIZE
+ 1];
1007 static char wepkey0
[LARGE_KEY_LENGTH
+ 1];
1009 /* Set the MAC port */
1011 err
= hermes_write_wordrec (hw
, USER_BAP
, HERMES_RID_CNFPORTTYPE
,
1014 printf ("%s: Error %d setting port type\n", orp
->or_name
, err
);
1018 if (OK
!= env_get_param("essid", essid
, sizeof(essid
))) {
1022 if(strlen(essid
) == 0) {
1023 printf("%s: no essid provided in boot monitor!\n",
1025 printf("Hope you'll connect to the right network... \n");
1028 /* Set the desired ESSID */
1029 idbuf
.len
= strlen (essid
);
1030 memcpy (&idbuf
.val
, essid
, sizeof (idbuf
.val
));
1032 err
= hermes_write_ltv (hw
, USER_BAP
, HERMES_RID_CNFDESIREDSSID
,
1033 HERMES_BYTES_TO_RECLEN (strlen (essid
) + 2),
1036 printf ("%s: Error %d setting DESIREDSSID\n",
1041 if (OK
!= env_get_param("wep", wepkey0
, sizeof(wepkey0
))) {
1045 switch(strlen(wepkey0
)) {
1047 /* No key found in monitor, using no encryption */
1049 case LARGE_KEY_LENGTH
:
1050 setup_wepkey(orp
, wepkey0
);
1053 printf("Invalid key provided. Has to be 13 chars\n");
1058 /*****************************************************************************
1061 * If a wepkey is provided in the boot monitor, set the necessary rids so *
1062 * that the card will decrypt received data and encrypt data to send by *
1063 * by default with this key. *
1064 * It appears that there is a severe bug in setting up WEP. If the driver *
1065 * doesnt function properly, please turn WEP off. *
1066 *****************************************************************************/
1067 static void setup_wepkey(t_or
*orp
, char *wepkey0
) {
1068 int default_key
= 0, err
= 0;
1069 hermes_t
*hw
= &(orp
->hw
);
1071 err
= hermes_write_wordrec (hw
, USER_BAP
,
1072 HERMES_RID_CNFWEPDEFAULTKEYID
,
1075 printf ("%s: Error %d setting the default WEP-key entry\n",
1078 err
= hermes_write_ltv (hw
, USER_BAP
,
1079 HERMES_RID_CNFDEFAULTKEY0
,
1080 HERMES_BYTES_TO_RECLEN(LARGE_KEY_LENGTH
),
1083 printf ("%s: Error %d setting the WEP-key0\n",
1086 err
= hermes_write_wordrec (hw
, USER_BAP
,
1087 HERMES_RID_CNFAUTHENTICATION
,
1090 printf ("%s: Error %d setting the authentication flag\n",
1093 err
= hermes_write_wordrec (hw
, USER_BAP
,
1094 HERMES_RID_CNFWEPFLAGS_INTERSIL
,
1095 HERMES_WEP_PRIVACY_INVOKED
);
1097 printf ("%s: Error %d setting the master wep setting flag\n",
1103 /*****************************************************************************
1106 * Set the desired receive mode, e.g. promiscuous mode. Not implemented yet *
1107 *****************************************************************************/
1108 static void or_rec_mode (t_or
* orp
) {
1112 /*****************************************************************************
1115 * The handler which is called when the card generated an interrupt. Events *
1116 * like EV_INFO and EV_RX have to be handled before an acknowledgement for *
1117 * the event is returned to the card. See also the documentation *
1118 *****************************************************************************/
1119 static int or_handler (t_or
*orp
) {
1120 int i
, err
, length
, nr
= 0;
1121 u16_t evstat
, events
, fid
;
1123 struct hermes_tx_descriptor desc
;
1128 /* Retrieve which kind of event happened */
1129 evstat
= hermes_read_reg (hw
, HERMES_EVSTAT
);
1132 /* There are plenty of events possible. The more interesting events
1133 are actually implemented. Whether the following events actually
1134 raise an interrupt depends on the value of ORINOCO_INTEN. For more
1135 information about the events, see the specification in pdf */
1137 /* Occurs at each tick of the auxiliary time */
1138 if (events
& HERMES_EV_TICK
) {
1139 events
&= ~HERMES_EV_TICK
;
1141 /* Occurs when a wait time-out error is detected */
1142 if (events
& HERMES_EV_WTERR
) {
1143 events
&= ~HERMES_EV_WTERR
;
1146 /* Occurs when an info frame is dropped because there is not enough
1147 buffer space available */
1148 if (events
& HERMES_EV_INFDROP
) {
1149 events
&= ~(HERMES_EV_INFDROP
);
1152 /* This AP-only event will be asserted at the beacon interval prior to
1153 the DTIM interval */
1154 if (events
& HERMES_EV_DTIM
) {
1155 events
&= ~(HERMES_EV_DTIM
);
1158 /* Occurs when a command execution is completed */
1159 if (events
& HERMES_EV_CMD
) {
1160 events
&= ~(HERMES_EV_CMD
);
1163 /* Occurs when the asynchronous transmission process is unsuccessfully
1165 if (events
& HERMES_EV_TXEXC
) {
1167 /* What buffer generated the event? Represented by an fid */
1168 fid
= hermes_read_reg(hw
, HERMES_TXCOMPLFID
);
1170 /* Illegal fid found */
1171 printf("unexpected txexc_fid interrupted\n");
1174 orp
->or_tx
.ret_busy
= FALSE
;
1176 if(orp
->or_flags
& OR_F_SEND_AVAIL
) {
1177 orp
->or_send_int
= TRUE
;
1178 if (!orp
->or_got_int
){
1179 orp
->or_got_int
= TRUE
;
1180 int_event_check
= TRUE
;
1184 /* To detect illegal fids */
1185 hermes_write_reg(hw
, HERMES_TXCOMPLFID
, 0xFFFF);
1186 events
&= ~(HERMES_EV_TXEXC
);
1187 /* We don't do anything else yet.
1188 * Could be used for statistics */
1191 /* Occurs when the asynchronous transmission process is successfully
1193 if (events
& HERMES_EV_TX
) {
1194 events
&= ~(HERMES_EV_TX
);
1195 /* Which buffer was sent, represented by an fid */
1196 fid
= hermes_read_reg (hw
, HERMES_TXCOMPLFID
);
1198 /* Illegal fid found */
1199 printf("unexpected tx_fid interrupted\n");
1202 orp
->or_tx
.ret_busy
= FALSE
;
1204 if(orp
->or_flags
& OR_F_SEND_AVAIL
) {
1205 orp
->or_send_int
= TRUE
;
1206 if (!orp
->or_got_int
){
1207 orp
->or_got_int
= TRUE
;
1208 int_event_check
= TRUE
;
1212 /* To detect illegal fids */
1213 hermes_write_reg(hw
, HERMES_TXCOMPLFID
, 0xFFFF);
1214 /* We don't do anything else when such event happens */
1217 /* Occurs when an info frame is available in the card */
1218 if (events
& HERMES_EV_INFO
) {
1219 events
&= ~(HERMES_EV_INFO
);
1220 /* Process the information, inside the handler (!) */
1224 /* Occurs when a TX buffer is available again for usage */
1225 if (events
& HERMES_EV_ALLOC
) {
1226 /* Which frame is now marked as free? */
1227 fid
= hermes_read_reg (hw
, HERMES_ALLOCFID
);
1229 /* An illegal frame identifier is found. Ignore */
1230 printf("Allocate event on unexpected fid\n");
1234 /* To be able to detect illegal fids */
1235 hermes_write_reg(hw
, HERMES_ALLOCFID
, 0xFFFF);
1237 events
&= ~(HERMES_EV_ALLOC
);
1241 /* Occurs when a frame is received by the asynchronous reception
1244 if (events
& HERMES_EV_RX
) {
1245 orp
->or_ev_rx
= TRUE
;
1246 events
&= ~(HERMES_EV_RX
);
1248 /* If the last buffer is still filled with data, then we don't
1249 * have any buffers available to store the data */
1250 if(orp
->rx_length
[orp
->rx_last
] != 0) {
1251 /* indeed, we are going to overwrite information
1255 /* Which buffer is storing the data (represented by a fid) */
1256 orp
->rxfid
[orp
->rx_last
]
1257 = hermes_read_reg (hw
, HERMES_RXFID
);
1259 /* Get the packet from the card and store it in
1260 * orp->rx_buf[orp->rx_last]. The length is returned by this
1262 length
= or_get_recvd_packet(orp
, orp
->rxfid
[orp
->rx_last
],
1263 (orp
->rx_buf
[orp
->rx_last
]));
1266 /* Error happened. */
1267 printf("length < 0\n");
1270 orp
->rx_length
[orp
->rx_last
] = length
;
1273 /* The next buffer will be used the next time, circularly */
1275 orp
->rx_last
%= NR_RX_BUFS
;
1277 if (!orp
->or_got_int
){
1278 orp
->or_got_int
= TRUE
;
1280 int_event_check
= TRUE
;
1284 printf("Unknown event: 0x%x\n", events
);
1287 /* Acknowledge to the card that the events have been processed. After
1288 * this the card will assume we have processed any buffer which were in
1289 * use for this event. */
1290 hermes_write_reg (hw
, HERMES_EVACK
, evstat
);
1292 evstat
= hermes_read_reg (hw
, HERMES_EVSTAT
);
1293 if(evstat
!= 0 && !(evstat
& HERMES_EV_TICK
)) {
1301 /*****************************************************************************
1304 * Will be called regularly to see whether the driver has crashed. If that *
1305 * condition is detected, reset the driver and card *
1306 *****************************************************************************/
1307 static void or_watchdog_f(timer_t
*tp
) {
1311 /* Use a synchronous alarm instead of a watchdog timer. */
1312 sys_setalarm(system_hz
, 0);
1314 for (i
= 0, orp
= &or_table
[0]; i
<OR_PORT_NR
; i
++, orp
++) {
1315 if (orp
->or_mode
!= OR_M_ENABLED
)
1318 if (!(orp
->or_flags
& OR_F_SEND_AVAIL
)) {
1319 /* Assume that an idle system is alive */
1320 orp
->or_tx_alive
= TRUE
;
1324 if (orp
->connected
== 0) {
1325 orp
->or_tx_alive
= TRUE
;
1328 if (orp
->or_tx_alive
) {
1329 orp
->or_tx_alive
= FALSE
;
1333 printf("or_watchdog_f: resetting port %d\n", i
);
1335 orp
->or_need_reset
= TRUE
;
1336 orp
->or_got_int
= TRUE
;
1341 /*****************************************************************************
1343 *****************************************************************************/
1345 static void mess_reply (message
* req
, message
* reply_mess
) {
1346 if (send (req
->m_source
, reply_mess
) != 0)
1347 panic("orinoco: unable to mess_reply");
1351 /*****************************************************************************
1354 * As far as we can see, this function is never called from 3.1.3. However, *
1355 * it is still in rtl8139, so we'll keep it here as well. It's almost a copy *
1356 * of or_writev_s. We left out the comments. For an explanation, see *
1358 ******************************************************************************/
1359 static void or_writev (message
* mp
, int from_int
, int vectored
) {
1360 int port
, or_client
, count
, size
, err
, data_len
, data_off
, tx_head
;
1361 int o
, j
, n
, i
, s
, p
, cps
;
1364 clock_t timebefore
, t0
;
1365 phys_bytes phys_user
;
1367 struct hermes_tx_descriptor desc
;
1368 struct header_struct hdr
;
1371 phys_bytes phys_databuf
;
1373 static u8_t databuf
[IEEE802_11_DATA_LEN
+ ETH_HLEN
+ 2 + 1];
1374 memset (databuf
, 0, IEEE802_11_DATA_LEN
+ ETH_HLEN
+ 3);
1377 count
= mp
->DL_COUNT
;
1378 if (port
< 0 || port
>= OR_PORT_NR
)
1379 panic("orinoco: illegal port");
1381 or_client
= mp
->DL_PROC
;
1382 orp
= &or_table
[port
];
1383 orp
->or_client
= or_client
;
1387 assert (orp
->or_flags
& OR_F_SEND_AVAIL
);
1388 orp
->or_flags
&= ~OR_F_SEND_AVAIL
;
1389 orp
->or_send_int
= FALSE
;
1390 orp
->or_tx_alive
= TRUE
;
1393 if (orp
->or_tx
.ret_busy
) {
1394 assert(!(orp
->or_flags
& OR_F_SEND_AVAIL
));
1395 orp
->or_flags
|= OR_F_SEND_AVAIL
;
1399 assert (orp
->or_mode
== OR_M_ENABLED
);
1400 assert (orp
->or_flags
& OR_F_ENABLED
);
1402 /* CvR: copied from or_writev_s(), since txfid was not initialized. */
1403 txfid
= orp
->or_tx
.or_txfid
;
1411 for (i
= 0; i
< count
; i
+= IOVEC_NR
,
1412 iov_offset
+= IOVEC_NR
* sizeof (orp
->or_iovec
[0])) {
1417 cps
= sys_vircopy(or_client
, D
,
1418 ((vir_bytes
) mp
->DL_ADDR
) + iov_offset
,
1419 SELF
, D
, (vir_bytes
) orp
->or_iovec
,
1420 n
* sizeof(orp
->or_iovec
[0]));
1421 if (cps
!= OK
) printf("sys_vircopy failed: %d\n", cps
);
1423 for (j
= 0, iovp
= orp
->or_iovec
; j
< n
; j
++, iovp
++) {
1425 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
) {
1426 printf("invalid packet size\n");
1428 cps
= sys_vircopy(or_client
, D
, iovp
->iov_addr
,
1429 SELF
, D
, (vir_bytes
) databuf
+ o
, s
);
1431 printf("sys_vircopy failed: %d\n",cps
);
1437 if (size
< ETH_MIN_PACK_SIZE
)
1438 printf("invalid packet size %d\n", size
);
1440 size
= mp
->DL_COUNT
;
1441 if (size
< ETH_MIN_PACK_SIZE
1442 || size
> ETH_MAX_PACK_SIZE_TAGGED
)
1443 printf("invalid packet size %d\n", size
);
1445 cps
= sys_vircopy(or_client
, D
, (vir_bytes
)mp
->DL_ADDR
,
1446 SELF
, D
, (vir_bytes
) databuf
, size
);
1447 if (cps
!= OK
) printf("sys_abscopy failed: %d\n", cps
);
1450 memset (&desc
, 0, sizeof (desc
));
1451 desc
.tx_control
= HERMES_TXCTRL_TX_OK
| HERMES_TXCTRL_TX_EX
;
1453 err
= hermes_bap_pwrite (hw
, USER_BAP
, &desc
, sizeof (desc
), txfid
,
1460 eh
= (struct ethhdr
*) databuf
;
1461 if (ntohs (eh
->h_proto
) > 1500) {
1463 data_len
= size
- ETH_HLEN
;
1464 data_off
= HERMES_802_3_OFFSET
+ sizeof (hdr
);
1466 memcpy (hdr
.dest
, eh
->h_dest
, ETH_ALEN
);
1467 memcpy (hdr
.src
, eh
->h_src
, ETH_ALEN
);
1468 hdr
.len
= htons (data_len
+ ENCAPS_OVERHEAD
);
1470 memcpy (&hdr
.dsap
, &encaps_hdr
, sizeof (encaps_hdr
));
1471 hdr
.ethertype
= eh
->h_proto
;
1473 err
= hermes_bap_pwrite (hw
, USER_BAP
, &hdr
, sizeof (hdr
),
1474 txfid
, HERMES_802_3_OFFSET
);
1476 printf ("%s: Error %d writing packet header to BAP\n",
1483 data_len
= size
+ ETH_HLEN
;
1484 data_off
= HERMES_802_3_OFFSET
;
1488 err
= hermes_bap_pwrite (hw
, USER_BAP
,
1489 (void *) &(databuf
[p
]), RUP_EVEN (data_len
),
1492 printf ("hermes_bap_pwrite(data): error %d\n", err
);
1496 orp
->or_tx
.ret_busy
= TRUE
;
1498 err
= hermes_docmd_wait (hw
, HERMES_CMD_TX
| HERMES_CMD_RECL
,
1501 orp
->or_tx
.ret_busy
= FALSE
;
1502 printf ("hermes_docmd_wait(TX|RECL): error %d\n", err
);
1507 orp
->or_flags
|= OR_F_PACK_SENT
;
1513 reply (orp
, OK
, FALSE
);
1517 orp
->or_tx_mess
= *mp
;
1518 reply (orp
, OK
, FALSE
);
1524 /*****************************************************************************
1527 * Write data which is denoted by the message to the card and send it. *
1528 *****************************************************************************/
1529 static void or_writev_s (message
* mp
, int from_int
) {
1530 int port
, or_client
, count
, size
, err
, data_len
, data_off
, tx_head
;
1531 int o
, j
, n
, i
, s
, p
, cps
;
1534 clock_t timebefore
, t0
;
1535 phys_bytes phys_user
;
1537 struct hermes_tx_descriptor desc
;
1539 struct header_struct hdr
;
1541 phys_bytes phys_databuf
;
1544 /* We need space for the max packet size itself, plus an ethernet
1545 * header, plus 2 bytes so we can align the IP header on a
1546 * 32bit boundary, plus 1 byte so we can read in odd length
1547 * packets from the card, which has an IO granularity of 16
1549 static u8_t databuf
[IEEE802_11_DATA_LEN
+ ETH_HLEN
+ 2 + 1];
1550 memset (databuf
, 0, IEEE802_11_DATA_LEN
+ ETH_HLEN
+ 3);
1553 count
= mp
->DL_COUNT
;
1554 if (port
< 0 || port
>= OR_PORT_NR
)
1555 panic("orinoco: illegal port");
1557 or_client
= mp
->DL_PROC
;
1558 orp
= &or_table
[port
];
1559 orp
->or_client
= or_client
;
1562 /* Switch off interrupts. The card is accessable via 2 BAPs, one for
1563 * reading and one for writing. In theory these BAPs should be
1564 * independent, but in practice, the are not. By switching off the
1565 * interrupts of the card, the chances of one interfering with the
1566 * other should be less */
1568 /* We were called with from_int, meaning that the last time we
1569 * were called, no tx buffers were available, and we had to
1570 * suspend. Now, we'll try again to find an empty buffer in the
1572 assert (orp
->or_flags
& OR_F_SEND_AVAIL
);
1573 orp
->or_flags
&= ~OR_F_SEND_AVAIL
;
1574 orp
->or_send_int
= FALSE
;
1575 orp
->or_tx_alive
= TRUE
;
1578 txfid
= orp
->or_tx
.or_txfid
;
1580 if (orp
->or_tx
.ret_busy
|| orp
->connected
== 0) {
1581 /* there is no buffer in the card available */
1582 assert(!(orp
->or_flags
& OR_F_SEND_AVAIL
));
1583 /* Remember that there is a packet to be sent available */
1584 orp
->or_flags
|= OR_F_SEND_AVAIL
;
1585 goto suspend_write_s
;
1588 assert (orp
->or_mode
== OR_M_ENABLED
);
1589 assert (orp
->or_flags
& OR_F_ENABLED
);
1592 /* Copy the data to be send from the vector to the databuf */
1595 for (i
= 0; i
< count
; i
+= IOVEC_NR
,
1596 iov_offset
+= IOVEC_NR
* sizeof (orp
->or_iovec_s
[0])) {
1602 cps
= sys_safecopyfrom(or_client
, mp
->DL_GRANT
, iov_offset
,
1603 (vir_bytes
) orp
->or_iovec_s
,
1604 n
* sizeof(orp
->or_iovec_s
[0]), D
);
1606 printf("orinoco: sys_safecopyfrom failed: %d\n", cps
);
1608 for (j
= 0, iovp
= orp
->or_iovec_s
; j
< n
; j
++, iovp
++) {
1610 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
) {
1611 printf("Orinoco: invalid pkt size\n");
1614 cps
= sys_safecopyfrom(or_client
, iovp
->iov_grant
, 0,
1615 (vir_bytes
) databuf
+ o
, s
, D
);
1617 printf("orinoco: sys_safecopyfrom failed:%d\n",
1625 assert(size
>= ETH_MIN_PACK_SIZE
);
1627 memset (&desc
, 0, sizeof (desc
));
1628 /* Reclaim the tx buffer once the data is sent (OK), or it is clear
1629 * that transmission failed (EX). Reclaiming means that we can reuse
1630 * the buffer again for transmission */
1631 desc
.tx_control
= HERMES_TXCTRL_TX_OK
| HERMES_TXCTRL_TX_EX
;
1632 /* Actually, this reclaim bit is the only thing which needs to be set
1633 * in the descriptor */
1634 err
= hermes_bap_pwrite (hw
, USER_BAP
, &desc
, sizeof (desc
), txfid
,
1637 printf("hermes_bap_pwrite() descriptor error:resetting card\n");
1638 /* When this happens, the card is quite confused: it will not
1639 * recover. Reset it */
1644 eh
= (struct ethhdr
*) databuf
;
1645 /* Encapsulate Ethernet-II frames */
1646 if (ntohs (eh
->h_proto
) > 1500) {
1647 /* Ethernet-II frame */
1648 data_len
= size
- ETH_HLEN
;
1649 data_off
= HERMES_802_3_OFFSET
+ sizeof (hdr
);
1652 memcpy (hdr
.dest
, eh
->h_dest
, ETH_ALEN
);
1653 memcpy (hdr
.src
, eh
->h_src
, ETH_ALEN
);
1654 hdr
.len
= htons (data_len
+ ENCAPS_OVERHEAD
);
1657 memcpy (&hdr
.dsap
, &encaps_hdr
, sizeof (encaps_hdr
));
1658 hdr
.ethertype
= eh
->h_proto
;
1660 err
= hermes_bap_pwrite (hw
, USER_BAP
, &hdr
, sizeof (hdr
),
1661 txfid
, HERMES_802_3_OFFSET
);
1663 printf ("%s: Error %d writing packet header to BAP\n",
1670 /* IEEE 802.3 frame */
1671 data_len
= size
+ ETH_HLEN
;
1672 data_off
= HERMES_802_3_OFFSET
;
1676 /* Round up for odd length packets */
1677 err
= hermes_bap_pwrite (hw
, USER_BAP
,
1678 (void *) &(databuf
[p
]), RUP_EVEN (data_len
),
1681 printf ("hermes_bap_pwrite(data): error %d\n", err
);
1685 /* this should be before the docmd_wait. Cause otherwise the bit can
1686 be cleared in the handler (if irq's not off) before it is set
1687 and then 1 reset (ret_busy=false) is lost */
1688 orp
->or_tx
.ret_busy
= TRUE
;
1690 /* Send the packet which was constructed in txfid */
1691 err
= hermes_docmd_wait (hw
, HERMES_CMD_TX
| HERMES_CMD_RECL
,
1694 printf ("hermes_docmd_wait(TX|RECL): error %d\n", err
);
1695 /* Mark the buffer as available again */
1696 orp
->or_tx
.ret_busy
= FALSE
;
1701 /* If the interrupt handler called, don't send a reply. The reply
1702 * will be sent after all interrupts are handled.
1704 orp
->or_flags
|= OR_F_PACK_SENT
;
1710 reply (orp
, OK
, FALSE
);
1714 orp
->or_tx_mess
= *mp
;
1716 reply (orp
, OK
, FALSE
);
1721 /*****************************************************************************
1724 * Send a message back to the caller, informing it about the data received *
1726 *****************************************************************************/
1727 static void reply (t_or
* orp
, int err
, int may_block
) {
1732 if (orp
->or_flags
& OR_F_PACK_SENT
)
1733 status
|= DL_PACK_SEND
;
1734 if (orp
->or_flags
& OR_F_PACK_RECV
)
1735 status
|= DL_PACK_RECV
;
1737 reply
.m_type
= DL_TASK_REPLY
;
1738 reply
.DL_PORT
= orp
- or_table
;
1739 assert(reply
.DL_PORT
== 0);
1740 reply
.DL_PROC
= orp
->or_client
;
1741 reply
.DL_STAT
= status
| ((u32_t
) err
<< 16);
1742 reply
.DL_COUNT
= orp
->or_read_s
;
1744 if (OK
!= (r
= getuptime(&now
)))
1745 panic("orinoco: getuptime() failed: %d", r
);
1747 reply
.DL_CLCK
= now
;
1748 r
= send (orp
->or_client
, &reply
);
1750 if (r
== ELOCKED
&& may_block
) {
1755 panic("orinoco: send failed: %d", r
);
1758 orp
->or_flags
&= ~(OR_F_PACK_SENT
| OR_F_PACK_RECV
);
1763 /*****************************************************************************
1766 * Process information which comes in from the card *
1767 *****************************************************************************/
1768 static void or_ev_info (t_or
* orp
) {
1770 int err
, len
, type
, i
;
1771 hermes_t
*hw
= &orp
->hw
;
1778 infofid
= hermes_read_reg (hw
, HERMES_INFOFID
);
1779 err
= hermes_bap_pread (hw
, IRQ_BAP
, &info
, sizeof (info
), infofid
,
1782 printf ("%s: error %d reading info frame.\n", orp
->or_name
,
1787 len
= HERMES_RECLEN_TO_BYTES (info
.len
);
1791 case HERMES_INQ_TALLIES
:
1793 struct hermes_tallies_frame tallies
;
1795 if (len
> sizeof (tallies
)) {
1796 printf ("%s: Tallies frame too long ",
1798 printf ("(%d bytes)\n", len
);
1799 len
= sizeof (tallies
);
1801 hermes_read_words (hw
, HERMES_DATA1
,
1802 (void *) &tallies
, len
/ 2);
1803 /* TODO: do something with the tallies structure */
1807 case HERMES_INQ_LINKSTATUS
: {
1809 struct hermes_linkstatus linkstatus
;
1811 if (len
!= sizeof (linkstatus
)) {
1812 printf ("%s: Unexpected size for linkstatus ",
1814 printf ("frame (%d bytes)\n", len
);
1817 hermes_read_words (hw
, HERMES_DATA1
,
1818 (void *) &linkstatus
, len
/ 2);
1819 newstatus
= linkstatus
.linkstatus
;
1821 if ((newstatus
== HERMES_LINKSTATUS_CONNECTED
)
1822 || (newstatus
== HERMES_LINKSTATUS_AP_CHANGE
)
1823 || (newstatus
== HERMES_LINKSTATUS_AP_IN_RANGE
)) {
1826 if(orp
->or_flags
& OR_F_SEND_AVAIL
) {
1827 orp
->or_send_int
= TRUE
;
1828 orp
->or_got_int
= TRUE
;
1829 int_event_check
= TRUE
;
1834 else if ((newstatus
==
1835 HERMES_LINKSTATUS_NOT_CONNECTED
)
1837 HERMES_LINKSTATUS_DISCONNECTED
)
1839 HERMES_LINKSTATUS_AP_OUT_OF_RANGE
)
1841 HERMES_LINKSTATUS_ASSOC_FAILED
)) {
1845 if (newstatus
!= orp
->last_linkstatus
)
1846 print_linkstatus(orp
, newstatus
);
1848 orp
->last_linkstatus
= newstatus
;
1852 printf ("%s:Unknown information frame received(type %04x).\n",
1853 orp
->or_name
, type
);
1858 /*****************************************************************************
1859 * or_print_linkstatus *
1861 * Process information which comes in from the card *
1862 *****************************************************************************/
1863 static void print_linkstatus (t_or
* orp
, u16_t status
) {
1867 hermes_t
*hw
= &(orp
->hw
);
1870 case HERMES_LINKSTATUS_NOT_CONNECTED
:
1871 s
= "Not Connected";
1873 case HERMES_LINKSTATUS_CONNECTED
:
1876 case HERMES_LINKSTATUS_DISCONNECTED
:
1879 case HERMES_LINKSTATUS_AP_CHANGE
:
1882 case HERMES_LINKSTATUS_AP_OUT_OF_RANGE
:
1883 s
= "AP Out of Range";
1885 case HERMES_LINKSTATUS_AP_IN_RANGE
:
1888 case HERMES_LINKSTATUS_ASSOC_FAILED
:
1889 s
= "Association Failed";
1895 printf ("%s: link status: %s, ", orp
->or_name
, s
);
1897 err
= hermes_read_wordrec (hw
, USER_BAP
,
1898 HERMES_RID_CURRENTCHANNEL
, &d
);
1900 printf ("%s: Error %d \n", orp
->or_name
, err
);
1903 printf("channel: %d, freq: %d MHz ",
1904 d
, (channel_frequency
[d
-1]));
1909 /*****************************************************************************
1912 * Process events which have been postponed in the interrupt handler *
1913 *****************************************************************************/
1914 static void or_check_ints (t_or
* orp
) {
1916 hermes_t
*hw
= &orp
->hw
;
1918 if (orp
->or_need_reset
)
1920 if ((orp
->rx_first
!=orp
->rx_last
) && (orp
->or_flags
& OR_F_READING
)) {
1922 if (orp
->or_rx_mess
.m_type
== DL_READV
) {
1923 or_readv (&orp
->or_rx_mess
, TRUE
, TRUE
);
1924 } else if(orp
->or_rx_mess
.m_type
== DL_READV_S
) {
1925 or_readv_s (&orp
->or_rx_mess
, TRUE
);
1927 assert(orp
->or_rx_mess
.m_type
== DL_READ
);
1928 or_readv (&orp
->or_rx_mess
, TRUE
, FALSE
);
1932 if (orp
->or_send_int
) {
1933 if (orp
->or_tx_mess
.m_type
== DL_WRITEV
) {
1934 or_writev (&orp
->or_tx_mess
, TRUE
, TRUE
);
1936 else if(orp
->or_tx_mess
.m_type
== DL_WRITEV_S
) {
1937 or_writev_s (&orp
->or_tx_mess
, TRUE
);
1939 assert(orp
->or_tx_mess
.m_type
== DL_WRITE
);
1940 or_writev (&orp
->or_tx_mess
, TRUE
, FALSE
);
1944 if (orp
->or_flags
& (OR_F_PACK_SENT
| OR_F_PACK_RECV
)) {
1945 reply (orp
, OK
, TRUE
);
1950 /*****************************************************************************
1953 * is there an LLC and SNAP header in the ethernet packet? The inet task *
1954 * isn't very interested in it... *
1955 *****************************************************************************/
1956 static int is_ethersnap(struct header_struct
*hdr
) {
1958 /* We de-encapsulate all packets which, a) have SNAP headers
1959 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
1960 * and where b) the OUI of the SNAP header is 00:00:00 or
1961 * 00:00:f8 - we need both because different APs appear to use
1962 * different OUIs for some reason */
1963 return (memcmp(&hdr
->dsap
, &encaps_hdr
, 5) == 0)
1964 && ( (hdr
->oui
[2] == 0x00) || (hdr
->oui
[2] == 0xf8) );
1967 /*****************************************************************************
1970 * As far as we can see, this function is never called from 3.1.3. However, *
1971 * it is still in rtl8139, so we'll keep it here as well. It's almost a copy *
1972 * of or_readv_s. We left out the comments. For an explanation, see *
1974 *****************************************************************************/
1975 static void or_readv (message
* mp
, int from_int
, int vectored
) {
1976 int i
, j
, n
, o
, s
, s1
, dl_port
, or_client
, count
, size
, err
, yep
, cps
;
1979 unsigned amount
, totlen
, packlen
;
1980 struct hermes_rx_descriptor desc
;
1981 phys_bytes dst_phys
;
1982 u16_t d_start
, d_end
, status
;
1983 struct header_struct hdr
;
1987 struct header_struct
*h
;
1992 dl_port
= mp
->DL_PORT
;
1993 count
= mp
->DL_COUNT
;
1994 if (dl_port
< 0 || dl_port
>= OR_PORT_NR
)
1995 panic("orinoco: illegal port: %d", dl_port
);
1997 orp
= &or_table
[dl_port
];
1998 or_client
= mp
->DL_PROC
;
1999 orp
->or_client
= or_client
;
2001 assert (orp
->or_mode
== OR_M_ENABLED
);
2002 assert (orp
->or_flags
& OR_F_ENABLED
);
2004 if (!from_int
&& (orp
->rx_first
==orp
->rx_last
)) {
2008 databuf
= &(orp
->rx_buf
[orp
->rx_first
][0]);
2009 length
= orp
->rx_length
[orp
->rx_first
];
2011 orp
->rxfid
[orp
->rx_first
] = NO_FID
;
2012 orp
->rx_length
[orp
->rx_first
] = 0;
2015 orp
->rx_first
%= NR_RX_BUFS
;
2023 for (i
= 0; i
< count
; i
+= IOVEC_NR
,
2024 iov_offset
+= IOVEC_NR
* sizeof(orp
->or_iovec
[0])) {
2030 cps
= sys_vircopy(or_client
, D
,
2031 (vir_bytes
) mp
->DL_ADDR
+ iov_offset
,
2032 SELF
, D
, (vir_bytes
) orp
->or_iovec
,
2033 n
* sizeof(orp
->or_iovec
[0]));
2034 if (cps
!= OK
) printf("sys_vircopy failed: %d (%d)\n",
2037 for (j
= 0, iovp
= orp
->or_iovec
; j
< n
; j
++, iovp
++) {
2039 if (size
+ s
> length
) {
2040 assert (length
> size
);
2044 cps
= sys_vircopy(SELF
, D
,
2045 (vir_bytes
) databuf
+ o
,
2049 printf("sys_vircopy failed:%d (%d)\n",
2060 assert (size
>= length
);
2063 orp
->or_stat
.ets_packetR
++;
2064 orp
->or_read_s
= length
;
2065 orp
->or_flags
&= ~OR_F_READING
;
2066 orp
->or_flags
|= OR_F_PACK_RECV
;
2069 reply (orp
, OK
, FALSE
);
2075 assert (orp
->or_flags
& OR_F_READING
);
2079 orp
->or_rx_mess
= *mp
;
2080 assert (!(orp
->or_flags
& OR_F_READING
));
2081 orp
->or_flags
|= OR_F_READING
;
2083 reply (orp
, OK
, FALSE
);
2087 /*****************************************************************************
2090 * Copy the data which is stored in orp->rx_buf[orp->rx_first] in the vector *
2091 * which was given with the message *mp *
2092 *****************************************************************************/
2093 static void or_readv_s (message
* mp
, int from_int
) {
2094 int i
, j
, n
, o
, s
, s1
, dl_port
, or_client
, count
, size
, err
, cps
;
2095 int iov_offset
= 0, length
, offset
;
2098 unsigned amount
, totlen
, packlen
;
2099 struct hermes_rx_descriptor desc
;
2100 phys_bytes dst_phys
;
2101 u16_t d_start
, d_end
, status
;
2102 struct header_struct hdr
;
2105 struct header_struct
*h
;
2109 phys_bytes databuf_phys
;
2113 dl_port
= mp
->DL_PORT
;
2114 count
= mp
->DL_COUNT
;
2115 if (dl_port
< 0 || dl_port
>= OR_PORT_NR
)
2116 panic("orinoco: illegal port: %d", dl_port
);
2118 orp
= &or_table
[dl_port
];
2119 or_client
= mp
->DL_PROC
;
2120 orp
->or_client
= or_client
;
2122 assert (orp
->or_mode
== OR_M_ENABLED
);
2123 assert (orp
->or_flags
& OR_F_ENABLED
);
2125 if (!from_int
&& (orp
->rx_first
==orp
->rx_last
))
2128 /* if we are not called from a hard int (data is not yet available) and
2129 * there are no buffers (or->rx_buf[x]) which contain any data, we cant
2130 * copy any data to the inet server. Goto suspend, and wait for data
2132 goto suspend_readv_s
;
2137 /* and store the pointer to this data in databuf */
2138 databuf
= &(orp
->rx_buf
[orp
->rx_first
][0]);
2139 length
= orp
->rx_length
[orp
->rx_first
];
2141 orp
->rxfid
[orp
->rx_first
] = NO_FID
;
2142 orp
->rx_length
[orp
->rx_first
] = 0;
2144 /* Next time, the next buffer with data will be retrieved */
2146 orp
->rx_first
%= NR_RX_BUFS
;
2149 /* The data which we want to be copied to the vector starts at
2150 * *databuf and will be copied to the vecor below */
2152 for (i
= 0; i
< count
; i
+= IOVEC_NR
,
2153 iov_offset
+= IOVEC_NR
* sizeof(orp
->or_iovec_s
[0])) {
2158 cps
= sys_safecopyfrom(or_client
, mp
->DL_GRANT
, iov_offset
,
2159 (vir_bytes
)orp
->or_iovec_s
,
2160 n
* sizeof(orp
->or_iovec_s
[0]), D
);
2162 panic("orinoco: warning: sys_safecopytp failed: %d", cps
);
2164 for (j
= 0, iovp
= orp
->or_iovec_s
; j
< n
; j
++, iovp
++) {
2166 if (size
+ s
> length
) {
2167 assert (length
> size
);
2170 cps
= sys_safecopyto(or_client
, iovp
->iov_grant
, 0,
2171 (vir_bytes
) databuf
+ o
, s
, D
);
2173 panic("orinoco: warning: sys_safecopy failed: %d", cps
);
2184 assert(size
>= length
);
2186 orp
->or_stat
.ets_packetR
++;
2188 orp
->or_read_s
= length
;
2189 orp
->or_flags
&= ~OR_F_READING
;
2190 orp
->or_flags
|= OR_F_PACK_RECV
;
2193 /* There was data in the orp->rx_buf[x] which is now copied to
2194 * the inet sever. Tell the inet server */
2195 reply (orp
, OK
, FALSE
);
2201 assert (orp
->or_flags
& OR_F_READING
);
2202 /* No need to store any state */
2206 /* We want to store the message, so that next time when we are called
2207 * by hard int, we know where to copy the received data */
2208 orp
->or_rx_mess
= *mp
;
2209 assert (!(orp
->or_flags
& OR_F_READING
));
2210 orp
->or_flags
|= OR_F_READING
;
2212 reply (orp
, OK
, FALSE
);
2217 /*****************************************************************************
2218 * or_get_recvd_packet *
2220 * The card has received data. Retrieve the data from the card and put it *
2221 * in a buffer in the driver (in the orp structure) *
2222 *****************************************************************************/
2223 static int or_get_recvd_packet(t_or
*orp
, u16_t rxfid
, u8_t
*databuf
) {
2224 struct hermes_rx_descriptor desc
;
2226 struct header_struct hdr
;
2227 int err
, length
, offset
;
2230 memset(databuf
, 0, IEEE802_11_FRAME_LEN
);
2234 /* Read the data from the buffer in the card which holds the data.
2235 * First get the descriptor which will tell us whether the packet is
2237 err
= hermes_bap_pread (hw
, IRQ_BAP
, &desc
, sizeof (desc
), rxfid
, 0);
2239 printf("Orinoco: error %d reading Rx descriptor. "
2240 "Frame dropped\n", err
);
2241 orp
->or_stat
.ets_recvErr
++;
2245 status
= desc
.status
;
2247 if (status
& HERMES_RXSTAT_ERR
) {
2248 if (status
& HERMES_RXSTAT_UNDECRYPTABLE
) {
2249 printf("Error reading Orinoco Rx descriptor.Dropped");
2251 orp
->or_stat
.ets_CRCerr
++;
2252 printf("Orinoco: Bad CRC on Rx. Frame dropped\n");
2254 orp
->or_stat
.ets_recvErr
++;
2258 /* For now we ignore the 802.11 header completely, assuming
2259 that the card's firmware has handled anything vital. The only
2260 thing we want to know is the length of the received data */
2261 err
= hermes_bap_pread (hw
, IRQ_BAP
, &hdr
, sizeof (hdr
),
2262 rxfid
, HERMES_802_3_OFFSET
);
2265 printf("Orinoco: error %d reading frame header. "
2266 "Frame dropped\n", err
);
2267 orp
->or_stat
.ets_recvErr
++;
2271 length
= ntohs (hdr
.len
);
2275 /* No for even an 802.2 LLC header */
2276 printf("Orinoco: error in frame length: length = %d\n",
2278 /* orp->or_stat.ets_recvErr++; */
2282 if (length
> IEEE802_11_DATA_LEN
) {
2283 printf("Orinoco: Oversized frame received (%d bytes)\n",
2285 orp
->or_stat
.ets_recvErr
++;
2289 length
+= sizeof (struct ethhdr
);
2290 offset
= HERMES_802_3_OFFSET
;
2292 /* Read the interesting parts of the data to the drivers memory. This
2293 * would be everything from the 802.3 layer and up */
2294 err
= hermes_bap_pread (hw
,
2295 IRQ_BAP
, (void *) databuf
, RUP_EVEN (length
),
2299 printf("Orinoco: error doing hermes_bap_pread()\n");
2300 orp
->or_stat
.ets_recvErr
++;
2304 /* Some types of firmware give us the SNAP and OUI headers. Remove these.
2306 if (is_ethersnap(&hdr
)) {
2310 memcpy (databuf
+ ETH_ALEN
* 2,
2311 databuf
+ sizeof(struct header_struct
) - 2,
2312 length
- ETH_ALEN
* 2);
2315 if(length
<60) length
=60;
2320 /*****************************************************************************
2323 * Return the statistics structure. The statistics aren't updated until now, *
2324 * so this won't return much interesting yet. *
2325 *****************************************************************************/
2326 static void or_getstat (message
* mp
) {
2332 if (port
< 0 || port
>= OR_PORT_NR
)
2333 panic("orinoco: illegal port: %d", port
);
2334 orp
= &or_table
[port
];
2335 orp
->or_client
= mp
->DL_PROC
;
2337 assert (orp
->or_mode
== OR_M_ENABLED
);
2338 assert (orp
->or_flags
& OR_F_ENABLED
);
2340 stats
= orp
->or_stat
;
2342 r
= sys_datacopy(SELF
, (vir_bytes
)&stats
, mp
->DL_PROC
,
2343 (vir_bytes
) mp
->DL_ADDR
, sizeof(stats
));
2345 panic("or_getstat: send failed: %d", r
);
2348 mp
->m_type
= DL_STAT_REPLY
;
2352 r
= send(mp
->m_source
, mp
);
2354 panic("orinoco: getstat failed: %d", r
);
2356 /*reply (orp, OK, FALSE);*/
2360 /*****************************************************************************
2363 * Return the statistics structure. The statistics aren't updated until now, *
2364 * so this won't return much interesting yet. *
2365 *****************************************************************************/
2366 static void or_getstat_s (message
* mp
) {
2372 if (port
< 0 || port
>= OR_PORT_NR
)
2373 panic("orinoco: illegal port: %d", port
);
2375 orp
= &or_table
[port
];
2376 orp
->or_client
= mp
->DL_PROC
;
2378 assert (orp
->or_mode
== OR_M_ENABLED
);
2379 assert (orp
->or_flags
& OR_F_ENABLED
);
2381 stats
= orp
->or_stat
;
2383 r
= sys_safecopyto(mp
->DL_PROC
, mp
->DL_GRANT
, 0,
2384 (vir_bytes
) &stats
, sizeof(stats
), D
);
2386 panic("or_getstat_s: sys_safecopyto failed: %d", r
);
2389 mp
->m_type
= DL_STAT_REPLY
;
2393 r
= send(mp
->m_source
, mp
);
2395 panic("orinoco: getstat_s failed: %d", r
);