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