3 Copyright (C) 2001-2017 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 #include <exec/memory.h>
24 #include <exec/execbase.h>
25 #include <exec/errors.h>
26 #include <exec/tasks.h>
28 #include <proto/exec.h>
30 #include <proto/alib.h>
32 #include <clib/alib_protos.h>
34 #include <proto/utility.h>
35 #include <proto/dos.h>
36 #include <proto/timer.h>
41 #include "unit_protos.h"
42 #include "request_protos.h"
43 #include "encryption_protos.h"
44 #include "timer_protos.h"
47 #define TASK_PRIORITY 0
48 #define STACK_SIZE 4096
50 (P2_EVENTF_INFO | P2_EVENTF_ALLOCMEM | P2_EVENTF_TXFAIL | P2_EVENTF_RX)
51 #define MAX_S_REC_SIZE 50
52 #define LUCENT_DBM_OFFSET 149
53 #define INTERSIL_DBM_OFFSET 100
54 #define SCAN_BUFFER_SIZE 2000
55 #define BEACON_BUFFER_SIZE 8000
56 #define SCAN_TAG_COUNT 8 +10
57 #define INFO_TAG_COUNT 4 +10
58 #define LUCENT_PDA_ADDRESS 0x390000
59 #define LUCENT_PDA_SIZE 1000
60 #define FRAME_BUFFER_SIZE (P2_H2FRM_ETHFRAME + ETH_HEADERSIZE \
61 + SNAP_HEADERSIZE + ETH_MTU + EIV_SIZE + ICV_SIZE + MIC_SIZE)
64 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
65 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
66 UWORD upper_bound_right
, struct DevBase
*base
);
67 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
);
68 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
));
69 static UBYTE
*GetRXBuffer(struct DevUnit
*unit
, const UBYTE
*address
,
70 UWORD frag_no
, UWORD
*buffer_no
, struct DevBase
*base
);
71 static VOID
DistributeRXPacket(struct DevUnit
*unit
, UBYTE
*frame
,
72 struct DevBase
*base
);
73 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
74 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
75 struct DevBase
*base
);
76 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
77 struct DevBase
*base
);
78 static VOID
SaveBeacon(struct DevUnit
*unit
, const UBYTE
*frame
,
79 struct DevBase
*base
);
80 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
));
81 static VOID
InfoInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
));
82 static VOID
ResetHandler(REG(a1
, struct DevUnit
*unit
),
83 REG(a6
, APTR int_code
));
84 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
85 struct DevBase
*base
);
86 static BOOL
LoadFirmware(struct DevUnit
*unit
, struct DevBase
*base
);
87 static const TEXT
*ParseNextSRecord(const TEXT
*s
, UBYTE
*type
, UBYTE
*data
,
88 UWORD
*data_length
, ULONG
*location
, struct DevBase
*base
);
89 static VOID
P2DoCmd(struct DevUnit
*unit
, UWORD command
, UWORD param
,
90 struct DevBase
*base
);
91 static BOOL
P2Seek(struct DevUnit
*unit
, UWORD path_no
, UWORD rec_no
,
92 UWORD offset
, struct DevBase
*base
);
93 static VOID
P2SetID(struct DevUnit
*unit
, UWORD rec_no
, const UBYTE
*id
,
94 UWORD length
, struct DevBase
*base
);
95 static VOID
P2SetWord(struct DevUnit
*unit
, UWORD rec_no
, UWORD value
,
96 struct DevBase
*base
);
97 static UWORD
P2GetWord(struct DevUnit
*unit
, UWORD rec_no
,
98 struct DevBase
*base
);
99 static UWORD
P2AllocMem(struct DevUnit
*unit
, UWORD size
,
100 struct DevBase
*base
);
101 static VOID
P2SetData(struct DevUnit
*unit
, UWORD rec_no
, const UBYTE
*data
,
102 UWORD length
, struct DevBase
*base
);
103 static BOOL
P2ReadRec(struct DevUnit
*unit
, UWORD rec_no
, APTR buffer
,
104 UWORD max_length
, struct DevBase
*base
);
105 static LONG
ConvertLevel(struct DevUnit
*unit
, UWORD raw_level
,
106 struct DevBase
*base
);
107 static LONG
ConvertScanLevel(struct DevUnit
*unit
, UWORD raw_level
,
108 struct DevBase
*base
);
109 static UBYTE
*GetIE(UBYTE id
, UBYTE
*ies
, UWORD ies_length
,
110 struct DevBase
*base
);
111 static BOOL
CompareMACAddresses(APTR mac1
, APTR mac2
);
112 static VOID
UnitTask(struct DevUnit
*unit
);
113 static UPINT
StrLen(const TEXT
*s
);
116 static const UBYTE snap_template
[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
117 static const UBYTE scan_params
[] = {0xff, 0x3f, 0x01, 0x00, 0x00, 0x00};
118 static const TEXT h1_firmware_file_name
[] = "DEVS:Firmware/HermesI";
119 static const TEXT h2_firmware_file_name
[] = "DEVS:Firmware/HermesII";
120 static const TEXT h25_firmware_file_name
[] = "DEVS:Firmware/HermesII.5";
121 static const UBYTE h2_wpa_ie
[] =
123 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00,
124 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50,
125 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02,
130 #if defined(__mc68000) && !defined(__AROS__)
131 #define AddUnitTask(task, initial_pc, unit) \
133 task->tc_SPReg -= sizeof(APTR); \
134 *((APTR *)task->tc_SPReg) = unit; \
135 AddTask(task, initial_pc, NULL); \
139 #define AddUnitTask(task, initial_pc, unit) \
141 struct TagItem _task_tags[] = \
142 {{AT_Param1, (UPINT)unit}, {TAG_END, 0}}; \
143 AddTask(task, initial_pc, NULL, _task_tags); \
147 #define AddUnitTask(task, initial_pc, unit) \
149 struct TagItem _task_tags[] = \
151 {TASKTAG_CODETYPE, CODETYPE_PPC}, \
152 {TASKTAG_PC, (UPINT)initial_pc}, \
153 {TASKTAG_PPC_ARG1, (UPINT)unit}, \
156 struct TaskInitExtension _task_init = {0xfff0, 0, _task_tags}; \
157 AddTask(task, &_task_init, NULL); \
161 #define AddUnitTask(task, initial_pc, unit) \
163 struct TagItem _task_tags[] = \
164 {{TASKTAG_ARG1, (UPINT)unit}, {TAG_END, 0}}; \
165 NewAddTask(task, initial_pc, NULL, _task_tags); \
171 /****i* prism2.device/CreateUnit *******************************************
174 * CreateUnit -- Create a unit.
177 * unit = CreateUnit(index, card, io_tags, bus)
179 * struct DevUnit *CreateUnit(ULONG, APTR, struct TagItem *, UWORD);
182 * Creates a new unit.
184 ****************************************************************************
188 struct DevUnit
*CreateUnit(ULONG index
, APTR card
,
189 const struct TagItem
*io_tags
, UWORD bus
, struct DevBase
*base
)
192 struct DevUnit
*unit
;
194 struct MsgPort
*port
;
198 unit
= AllocMem(sizeof(struct DevUnit
), MEMF_CLEAR
| MEMF_PUBLIC
);
209 (APTR
)GetTagData(IOTAG_WordsIn
, (UPINT
)NULL
, io_tags
);
211 (APTR
)GetTagData(IOTAG_WordsOut
, (UPINT
)NULL
, io_tags
);
213 (APTR
)GetTagData(IOTAG_BEWordOut
, (UPINT
)NULL
, io_tags
);
215 (APTR
)GetTagData(IOTAG_LEWordIn
, (UPINT
)NULL
, io_tags
);
217 (APTR
)GetTagData(IOTAG_LEWordOut
, (UPINT
)NULL
, io_tags
);
218 if(unit
->WordsIn
== NULL
|| unit
->WordsOut
== NULL
219 || unit
->BEWordOut
== NULL
|| unit
->LEWordIn
== NULL
220 || unit
->LEWordOut
== NULL
)
226 InitSemaphore(&unit
->access_lock
);
227 success
= InitialiseAdapter(unit
, FALSE
, base
);
228 unit
->flags
|= UNITF_HAVEADAPTER
;
230 /* Create the message ports for queuing requests */
232 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
234 unit
->request_ports
[i
] = port
= AllocMem(sizeof(struct MsgPort
),
235 MEMF_PUBLIC
| MEMF_CLEAR
);
241 NewList(&port
->mp_MsgList
);
242 port
->mp_Flags
= PA_IGNORE
;
243 port
->mp_SigTask
= &unit
->tx_int
;
247 /* Allocate buffers */
249 unit
->rx_buffer
= AllocVec(FRAME_BUFFER_SIZE
, MEMF_PUBLIC
);
250 unit
->rx_buffers
= AllocVec(FRAME_BUFFER_SIZE
* RX_BUFFER_COUNT
,
252 for(i
= 0; i
< RX_BUFFER_COUNT
; i
++)
253 unit
->rx_fragment_nos
[i
] = -1;
254 unit
->tx_buffer
= AllocVec(ETH_MAXPACKETSIZE
, MEMF_PUBLIC
);
255 unit
->rx_descriptor
= AllocVec(FRAME_BUFFER_SIZE
,
256 MEMF_PUBLIC
| MEMF_CLEAR
);
257 unit
->tx_descriptor
= AllocVec(FRAME_BUFFER_SIZE
,
258 MEMF_PUBLIC
| MEMF_CLEAR
);
259 unit
->scan_results_rec
= AllocVec(SCAN_BUFFER_SIZE
, MEMF_PUBLIC
);
260 unit
->next_beacon
= unit
->beacons
=
261 AllocVec(BEACON_BUFFER_SIZE
, MEMF_PUBLIC
);
262 if(unit
->rx_buffer
== NULL
|| unit
->rx_buffers
== NULL
263 || unit
->tx_buffer
== NULL
|| unit
->rx_descriptor
== NULL
264 || unit
->tx_descriptor
== NULL
|| unit
->scan_results_rec
== NULL
265 || unit
->beacons
== NULL
)
271 NewList((APTR
)&unit
->openers
);
272 NewList((APTR
)&unit
->type_trackers
);
273 NewList((APTR
)&unit
->multicast_ranges
);
275 /* Record maximum speed in BPS */
277 unit
->speed
= 11000000;
279 /* Initialise status, transmit, receive and stats interrupts */
281 unit
->status_int
.is_Node
.ln_Name
=
282 base
->device
.dd_Library
.lib_Node
.ln_Name
;
283 unit
->status_int
.is_Code
= (APTR
)StatusInt
;
284 unit
->status_int
.is_Data
= unit
;
286 unit
->rx_int
.is_Node
.ln_Name
=
287 base
->device
.dd_Library
.lib_Node
.ln_Name
;
288 unit
->rx_int
.is_Code
= (APTR
)RXInt
;
289 unit
->rx_int
.is_Data
= unit
;
291 unit
->tx_int
.is_Node
.ln_Name
=
292 base
->device
.dd_Library
.lib_Node
.ln_Name
;
293 unit
->tx_int
.is_Code
= (APTR
)TXInt
;
294 unit
->tx_int
.is_Data
= unit
;
296 unit
->info_int
.is_Node
.ln_Name
=
297 base
->device
.dd_Library
.lib_Node
.ln_Name
;
298 unit
->info_int
.is_Code
= (APTR
)InfoInt
;
299 unit
->info_int
.is_Data
= unit
;
301 unit
->reset_handler
.is_Node
.ln_Name
=
302 base
->device
.dd_Library
.lib_Node
.ln_Name
;
303 unit
->reset_handler
.is_Code
= (APTR
)ResetHandler
;
304 unit
->reset_handler
.is_Data
= unit
;
306 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
311 /* Create a new task */
314 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
321 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
328 /* Initialise and start task */
330 task
->tc_Node
.ln_Type
= NT_TASK
;
331 task
->tc_Node
.ln_Pri
= TASK_PRIORITY
;
332 task
->tc_Node
.ln_Name
= base
->device
.dd_Library
.lib_Node
.ln_Name
;
333 task
->tc_SPUpper
= stack
+ STACK_SIZE
;
334 task
->tc_SPLower
= stack
;
335 task
->tc_SPReg
= task
->tc_SPUpper
;
336 NewList(&task
->tc_MemEntry
);
338 if(AddUnitTask(task
, UnitTask
, unit
) != NULL
)
339 unit
->flags
|= UNITF_TASKADDED
;
346 /* Set default wireless options */
348 unit
->mode
= S2PORT_MANAGED
;
353 DeleteUnit(unit
, base
);
362 /****i* prism2.device/DeleteUnit *******************************************
365 * DeleteUnit -- Delete a unit.
370 * VOID DeleteUnit(struct DevUnit *);
376 * unit - Device unit (may be NULL).
381 ****************************************************************************
385 VOID
DeleteUnit(struct DevUnit
*unit
, struct DevBase
*base
)
397 if((unit
->flags
& UNITF_TASKADDED
) != 0)
400 FreeMem(task
->tc_SPLower
, STACK_SIZE
);
402 FreeMem(task
, sizeof(struct Task
));
405 /* Free request queues */
407 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
409 if(unit
->request_ports
[i
] != NULL
)
410 FreeMem(unit
->request_ports
[i
], sizeof(struct MsgPort
));
415 if((unit
->flags
& UNITF_ONLINE
) != 0) /* Needed! */
416 GoOffline(unit
, base
);
418 /* Clear target SSID */
420 P2SetID(unit
, P2_REC_DESIREDSSID
, unit
->ssid
, 0, base
);
422 /* Free buffers and unit structure */
424 FreeVec(unit
->beacons
);
425 FreeVec(unit
->scan_results_rec
);
426 FreeVec(unit
->tx_descriptor
);
427 FreeVec(unit
->rx_descriptor
);
428 FreeVec(unit
->tx_buffer
);
429 FreeVec(unit
->rx_buffers
);
430 FreeVec(unit
->rx_buffer
);
432 FreeMem(unit
, sizeof(struct DevUnit
));
440 /****i* prism2.device/InitialiseAdapter ************************************
446 * success = InitialiseAdapter(unit, reinsertion)
448 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
457 * success - Success indicator.
459 ****************************************************************************
463 BOOL
InitialiseAdapter(struct DevUnit
*unit
, BOOL reinsertion
,
464 struct DevBase
*base
)
466 UWORD id
, version
, revision
, i
;
467 BOOL success
= TRUE
, loaded
;
468 UBYTE address
[ETH_ADDRESSSIZE
];
471 /* Wait for card to be ready following bus-specific reset, then start
474 while((unit
->LEWordIn(unit
->card
, P2_REG_COMMAND
)
475 & P2_REG_COMMANDF_BUSY
) != 0);
477 P2DoCmd(unit
, P2_CMD_INIT
, 0, base
);
479 /* Determine firmware type */
481 P2DoCmd(unit
, P2_CMD_ACCESS
, P2_REC_NICIDENTITY
, base
);
482 P2Seek(unit
, 1, P2_REC_NICIDENTITY
, 4, base
);
483 id
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
484 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
485 version
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
486 revision
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
488 if((id
& 0x8000) != 0)
491 unit
->firmware_type
= SYMBOL_FIRMWARE
;
493 unit
->firmware_type
= INTERSIL_FIRMWARE
;
497 P2DoCmd(unit
, P2_CMD_ACCESS
, P2_REC_PRIIDENTITY
, base
);
498 P2Seek(unit
, 1, P2_REC_PRIIDENTITY
, 0, base
);
499 length
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
501 unit
->firmware_type
= LUCENT_FIRMWARE
;
504 P2DoCmd(unit
, P2_CMD_ACCESS
, P2_REC_STAIDENTITY
, base
);
505 P2Seek(unit
, 1, P2_REC_STAIDENTITY
, 4, base
);
506 id
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
507 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
508 version
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
509 revision
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
511 unit
->firmware_type
= HERMES2G_FIRMWARE
;
513 unit
->firmware_type
= HERMES2_FIRMWARE
;
517 /* Download firmware if necessary or available */
519 loaded
= LoadFirmware(unit
, base
);
520 if(!loaded
&& unit
->firmware_type
>= HERMES2_FIRMWARE
)
525 /* Determine features, and get offsets of certain fields within frame
528 P2DoCmd(unit
, P2_CMD_ACCESS
, P2_REC_STAIDENTITY
, base
);
529 P2Seek(unit
, 1, P2_REC_STAIDENTITY
, 4, base
);
530 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
531 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
532 version
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
533 revision
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
535 if(P2GetWord(unit
, P2_REC_HASWEP
, base
) != 0)
536 unit
->flags
|= UNITF_HASWEP
| UNITF_HARDWEP
;
538 unit
->ethernet_offset
= P2_FRM_ETHFRAME
;
539 unit
->data_offset
= P2_FRM_DATA
;
540 unit
->txcontrol_offset
= P2_FRM_TXCONTROL
;
541 unit
->datalen_offset
= P2_FRM_DATALEN
;
543 if(unit
->firmware_type
== LUCENT_FIRMWARE
)
545 if(version
> 6 || version
== 6 && revision
>= 6)
546 unit
->flags
|= UNITF_HASADHOC
;
549 unit
->flags
|= UNITF_HASTKIP
| UNITF_HARDTKIP
;
550 unit
->txcontrol_offset
= P2_FRM_ALTTXCONTROL
;
553 else if(unit
->firmware_type
>= HERMES2_FIRMWARE
)
555 unit
->flags
|= UNITF_HASADHOC
| UNITF_HASTKIP
| UNITF_HARDTKIP
;
556 unit
->ethernet_offset
= P2_H2FRM_ETHFRAME
;
557 unit
->data_offset
= P2_H2FRM_DATA
;
558 unit
->txcontrol_offset
= P2_H2FRM_TXCONTROL
;
559 unit
->datalen_offset
= P2_H2FRM_DATALEN
;
561 else if(unit
->firmware_type
== INTERSIL_FIRMWARE
)
563 unit
->flags
|= UNITF_HASADHOC
| UNITF_HASWEP
;
564 if(version
== 1 && revision
>= 7)
565 unit
->flags
|= UNITF_HASTKIP
| UNITF_HASCCMP
;
568 /* Get default channel and MAC address */
570 unit
->channel
= P2GetWord(unit
, P2_REC_OWNCHNL
, base
);
571 P2DoCmd(unit
, P2_CMD_ACCESS
, P2_REC_ADDRESS
, base
);
572 P2Seek(unit
, 1, P2_REC_ADDRESS
, 4, base
);
573 unit
->WordsIn(unit
->card
, P2_REG_DATA1
, (UWORD
*)address
,
574 ETH_ADDRESSSIZE
/ 2);
576 /* If card has been re-inserted, check it has the same address as
581 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
582 if(address
[i
] != unit
->default_address
[i
])
589 CopyMem(address
, unit
->default_address
, ETH_ADDRESSSIZE
);
591 /* Get initial on-card TX buffer */
593 unit
->tx_frame_id
= P2AllocMem(unit
, FRAME_BUFFER_SIZE
, base
);
597 if((unit
->flags
& UNITF_HARDWEP
) == 0)
598 unit
->iv_sizes
[S2ENC_WEP
] = IV_SIZE
;
599 if((unit
->flags
& UNITF_HARDTKIP
) == 0)
600 unit
->iv_sizes
[S2ENC_TKIP
] = EIV_SIZE
;
601 unit
->iv_sizes
[S2ENC_CCMP
] = EIV_SIZE
;
603 /* Set encryption functions */
605 unit
->fragment_encrypt_functions
[S2ENC_NONE
] = WriteClearFragment
;
607 if((unit
->flags
& UNITF_HARDWEP
) != 0)
608 unit
->fragment_encrypt_functions
[S2ENC_WEP
] = WriteClearFragment
;
610 unit
->fragment_encrypt_functions
[S2ENC_WEP
] = EncryptWEPFragment
;
612 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
613 unit
->fragment_encrypt_functions
[S2ENC_TKIP
] = WriteClearFragment
;
615 unit
->fragment_encrypt_functions
[S2ENC_TKIP
] = EncryptTKIPFragment
;
617 unit
->fragment_encrypt_functions
[S2ENC_CCMP
] = EncryptCCMPFragment
;
619 /* Set decryption functions */
621 unit
->fragment_decrypt_functions
[S2ENC_NONE
] = ReadClearFragment
;
623 if((unit
->flags
& UNITF_HARDWEP
) != 0)
624 unit
->fragment_decrypt_functions
[S2ENC_WEP
] = ReadClearFragment
;
626 unit
->fragment_decrypt_functions
[S2ENC_WEP
] = DecryptWEPFragment
;
628 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
629 unit
->fragment_decrypt_functions
[S2ENC_TKIP
] = ReadClearFragment
;
631 unit
->fragment_decrypt_functions
[S2ENC_TKIP
] = DecryptTKIPFragment
;
633 unit
->fragment_decrypt_functions
[S2ENC_CCMP
] = DecryptCCMPFragment
;
643 /****i* prism2.device/ConfigureAdapter *************************************
646 * ConfigureAdapter -- Set up card for transmission/reception.
649 * ConfigureAdapter(unit)
651 * VOID ConfigureAdapter(struct DevUnit *);
653 ****************************************************************************
657 VOID
ConfigureAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
659 UWORD i
, key_length
, port_type
, lowest_enc
= S2ENC_CCMP
,
660 highest_enc
= S2ENC_NONE
, enc_flags
, size
, value
;
661 const struct KeyUnion
*keys
;
663 /* Set MAC address */
665 P2SetData(unit
, P2_REC_ADDRESS
, unit
->address
, ETH_ADDRESSSIZE
,
668 /* Decide on promiscuous mode */
670 P2SetWord(unit
, P2_REC_PROMISC
, FALSE
, base
);
671 SetMulticast(unit
, base
);
673 /* Set wireless parameters */
675 if(unit
->mode
== S2PORT_ADHOC
)
677 P2SetWord(unit
, P2_REC_OWNCHNL
, unit
->channel
, base
);
678 P2SetID(unit
, P2_REC_OWNSSID
, unit
->ssid
, unit
->ssid_length
, base
);
680 if(unit
->mode
== S2PORT_MANAGED
)
684 if((unit
->flags
& UNITF_ONLINE
) == 0)
685 P2SetWord(unit
, P2_REC_PORTTYPE
, port_type
, base
);
686 P2SetWord(unit
, P2_REC_CREATEIBSS
, unit
->mode
== S2PORT_ADHOC
, base
);
687 P2SetID(unit
, P2_REC_DESIREDSSID
, unit
->ssid
, unit
->ssid_length
, base
);
689 /* Determine highest encryption type in use */
691 for(i
= 0; i
< WIFI_KEYCOUNT
; i
++)
693 if(unit
->keys
[i
].type
> highest_enc
)
694 highest_enc
= unit
->keys
[i
].type
;
695 if(unit
->keys
[i
].type
< lowest_enc
)
696 lowest_enc
= unit
->keys
[i
].type
;
699 if(unit
->wpa_ie
[1] != 0)
700 highest_enc
= S2ENC_TKIP
;
702 /* Allow reception of beacon/probe-response frames */
704 if(unit
->firmware_type
== INTERSIL_FIRMWARE
)
705 P2SetWord(unit
, P2_REC_RXMGMTFRAMES
, 1, base
);
707 /* Transmit at 11Mbps, with fallback */
709 if(unit
->firmware_type
== INTERSIL_FIRMWARE
710 || unit
->firmware_type
== SYMBOL_FIRMWARE
)
711 P2SetWord(unit
, P2_REC_TXRATE
, 0xf, base
);
713 /* Configure authentication and encryption */
715 if(unit
->firmware_type
>= LUCENT_FIRMWARE
)
717 /* Set authentication and encryption modes */
719 P2SetWord(unit
, P2_REC_ALTAUTHTYPE
, unit
->auth_types
, base
);
721 P2SetWord(unit
, P2_REC_ALTENCRYPTION
, highest_enc
, base
);
723 /* Set up firmware-based WEP encryption if appropriate */
725 if(highest_enc
== S2ENC_WEP
&& (unit
->flags
& UNITF_HARDWEP
) != 0)
727 P2SetWord(unit
, P2_REC_ALTTXCRYPTKEY
, unit
->tx_key_no
, base
);
728 P2Seek(unit
, 1, P2_REC_DEFLTCRYPTKEYS
, 0, base
);
729 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, P2_ALTWEPRECLEN
);
730 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, P2_REC_DEFLTCRYPTKEYS
);
732 for(i
= 0; i
< WIFI_KEYCOUNT
; i
++)
734 key_length
= keys
[i
].u
.wep
.length
;
736 key_length
= WIFI_WEP128LEN
;
737 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, key_length
);
738 unit
->WordsOut(unit
->card
, P2_REG_DATA1
,
739 (UWORD
*)keys
[i
].u
.wep
.key
, (key_length
+ 1) / 2);
742 P2DoCmd(unit
, P2_CMD_ACCESS
| P2_CMDF_WRITE
,
743 P2_REC_DEFLTCRYPTKEYS
, base
);
746 /* Set key management suite to PSK */
748 if(highest_enc
> S2ENC_WEP
)
750 value
= (unit
->firmware_type
>= HERMES2_FIRMWARE
) ? 4 : 2;
751 P2SetWord(unit
, P2_REC_KEYMGMTSUITE
, value
, base
);
756 /* Set authentication mode */
758 P2SetWord(unit
, P2_REC_AUTHTYPE
, unit
->auth_types
, base
);
760 /* Set encryption flags */
762 if(highest_enc
> S2ENC_NONE
)
763 enc_flags
= P2_REC_ENCRYPTIONF_ENABLE
;
767 if(highest_enc
> S2ENC_WEP
768 || highest_enc
== S2ENC_WEP
&& (unit
->flags
& UNITF_HARDWEP
) == 0)
769 enc_flags
|= P2_REC_ENCRYPTIONF_HOSTDECRYPT
770 | P2_REC_ENCRYPTIONF_HOSTENCRYPT
;
771 P2SetWord(unit
, P2_REC_ENCRYPTION
, enc_flags
, base
);
773 /* Set up firmware-based WEP encryption if appropriate */
775 if(highest_enc
== S2ENC_WEP
&& (unit
->flags
& UNITF_HARDWEP
) != 0)
777 P2SetWord(unit
, P2_REC_TXCRYPTKEY
, unit
->tx_key_no
, base
);
780 for(i
= 0; i
< WIFI_KEYCOUNT
; i
++)
782 key_length
= keys
[i
].u
.wep
.length
;
784 key_length
= keys
[unit
->tx_key_no
].u
.wep
.length
;
785 P2SetData(unit
, P2_REC_CRYPTKEY0
+ i
, keys
[i
].u
.wep
.key
,
790 /* Set or clear WPA IE */
792 if(highest_enc
> S2ENC_WEP
)
793 size
= unit
->wpa_ie
[1] + 2;
796 P2SetID(unit
, P2_REC_WPAIE
, unit
->wpa_ie
, size
, base
);
798 /* Let supplicant handle association and roaming */
800 P2SetWord(unit
, P2_REC_ROAMINGMODE
, 3, base
);
803 /* Restart the transceiver if we're already online */
805 if((unit
->flags
& UNITF_ONLINE
) != 0)
807 P2DoCmd(unit
, P2_CMD_DISABLE
, 0, base
);
808 P2DoCmd(unit
, P2_CMD_ENABLE
, 0, base
);
810 /* Attempt to join specified network */
812 if(unit
->firmware_type
== INTERSIL_FIRMWARE
)
814 unit
->bssid
[ETH_ADDRESSSIZE
] = unit
->channel
;
815 P2SetData(unit
, P2_REC_JOIN
, unit
->bssid
, ETH_ADDRESSSIZE
+ 2,
827 /****i* prism2.device/GoOnline *********************************************
830 * GoOnline -- Enable transmission/reception.
835 * VOID GoOnline(struct DevUnit *);
837 ****************************************************************************
841 VOID
GoOnline(struct DevUnit
*unit
, struct DevBase
*base
)
843 /* Enable interrupts */
845 unit
->flags
|= UNITF_ONLINE
;
846 unit
->LEWordOut(unit
->card
, P2_REG_INTMASK
, INT_MASK
);
848 /* Enable the transceiver */
850 P2DoCmd(unit
, P2_CMD_ENABLE
, 0, base
);
852 /* Record start time and report Online event */
854 GetSysTime(&unit
->stats
.LastStart
);
855 ReportEvents(unit
, S2EVENT_ONLINE
, base
);
862 /****i* prism2.device/GoOffline ********************************************
865 * GoOffline -- Disable transmission/reception.
870 * VOID GoOffline(struct DevUnit *);
880 ****************************************************************************
884 VOID
GoOffline(struct DevUnit
*unit
, struct DevBase
*base
)
886 unit
->flags
&= ~UNITF_ONLINE
;
887 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
889 /* Stop interrupts */
891 unit
->LEWordOut(unit
->card
, P2_REG_INTMASK
, 0);
892 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, 0xffff);
894 /* Update statistics */
896 UpdateStats(unit
, base
);
898 /* Stop transmission and reception */
900 P2DoCmd(unit
, P2_CMD_DISABLE
, 0, base
);
903 /* Flush pending read and write requests */
905 FlushUnit(unit
, WRITE_QUEUE
, S2ERR_OUTOFSERVICE
, base
);
907 /* Report Offline event and return */
909 ReportEvents(unit
, S2EVENT_OFFLINE
, base
);
915 /****i* prism2.device/SetOptions *******************************************
918 * SetOptions -- Set and use interface options.
921 * SetOptions(unit, tag_list)
923 * VOID SetOptions(struct DevUnit *, struct TagItem *);
925 ****************************************************************************
929 VOID
SetOptions(struct DevUnit
*unit
, const struct TagItem
*tag_list
,
930 struct DevBase
*base
)
932 struct TagItem
*tag_item
, *tlist
= (struct TagItem
*)tag_list
;
937 while((tag_item
= NextTagItem(&tlist
)) != NULL
)
939 switch(tag_item
->ti_Tag
)
942 id
= (const TEXT
*)tag_item
->ti_Data
;
944 CopyMem(id
, unit
->ssid
, length
);
945 unit
->ssid_length
= length
;
949 CopyMem((APTR
)tag_item
->ti_Data
, unit
->bssid
, ETH_ADDRESSSIZE
);
952 case S2INFO_DefaultKeyNo
:
953 unit
->tx_key_no
= tag_item
->ti_Data
;
956 case S2INFO_PortType
:
957 unit
->mode
= tag_item
->ti_Data
;
961 unit
->channel
= tag_item
->ti_Data
;
965 if(tag_item
->ti_Data
!= (UPINT
)NULL
)
967 /* Hermes-II uses an "unusual" WPA IE in its association
968 request. So we use a matching IE everywhere else too */
970 if(unit
->firmware_type
>= HERMES2_FIRMWARE
)
973 ie
= (const UBYTE
*)tag_item
->ti_Data
;
974 CopyMem(ie
, unit
->wpa_ie
, ie
[1] + 2);
983 case S2INFO_AuthTypes
:
984 unit
->auth_types
= tag_item
->ti_Data
;
994 /****i* prism2.device/SetKey ***********************************************
997 * SetKey -- Set an encryption key.
1000 * SetKey(unit, index, type, key, key_length,
1003 * VOID SetKey(struct DevUnit *, ULONG, ULONG, UBYTE *, ULONG,
1006 ****************************************************************************
1010 VOID
SetKey(struct DevUnit
*unit
, ULONG index
, ULONG type
, const UBYTE
*key
,
1011 ULONG key_length
, const UBYTE
*rx_counter
, struct DevBase
*base
)
1013 struct KeyUnion
*slot
;
1014 const UBYTE tx_counter
[8] = {0, 0, 0, 0, 0x10, 0, 0, 0};
1016 struct EClockVal eclock
;
1019 slot
= &unit
->keys
[index
];
1023 CopyMem(key
, slot
->u
.wep
.key
, key_length
);
1024 slot
->u
.wep
.length
= key_length
;
1026 if((unit
->flags
& UNITF_HARDWEP
) == 0)
1028 /* Create a reasonably random IV */
1030 ReadEClock(&eclock
);
1031 slot
->u
.wep
.tx_iv
= FastRand(eclock
.ev_lo
^ eclock
.ev_hi
);
1037 CopyMem(key
, slot
->u
.tkip
.key
, 16);
1038 CopyMem(key
+ 16, slot
->u
.tkip
.tx_mic_key
, MIC_SIZE
);
1039 CopyMem(key
+ 24, slot
->u
.tkip
.rx_mic_key
, MIC_SIZE
);
1040 slot
->u
.tkip
.tx_iv_low
= 0;
1041 slot
->u
.tkip
.tx_iv_high
= 0;
1042 slot
->u
.tkip
.rx_iv_low
= LEWord(*(UWORD
*)rx_counter
);
1043 slot
->u
.tkip
.rx_iv_high
= LELong(*(ULONG
*)(rx_counter
+ 2));
1044 slot
->u
.tkip
.tx_ttak_set
= FALSE
;
1045 slot
->u
.tkip
.rx_ttak_set
= FALSE
;
1047 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
1049 /* For Hermes, load parameters for hardware encryption. The
1050 pairwise key is treated differently from group keys on
1051 Hermes-II, but not on Hermes-I */
1053 if(unit
->firmware_type
>= HERMES2_FIRMWARE
&& index
== 0)
1055 P2Seek(unit
, 1, P2_REC_ADDMAPPEDTKIPKEY
, 0, base
);
1056 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, 28);
1057 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
,
1058 P2_REC_ADDMAPPEDTKIPKEY
);
1059 unit
->WordsOut(unit
->card
, P2_REG_DATA1
,
1060 (UWORD
*)unit
->bssid
, ETH_ADDRESSSIZE
/ 2);
1061 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (UWORD
*)key
,
1063 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (UWORD
*)tx_counter
,
1065 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (UWORD
*)rx_counter
,
1067 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, 0);
1068 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (UWORD
*)key
+ 16,
1070 P2DoCmd(unit
, P2_CMD_ACCESS
| P2_CMDF_WRITE
,
1071 P2_REC_ADDMAPPEDTKIPKEY
, base
);
1075 P2Seek(unit
, 1, P2_REC_ADDDEFAULTTKIPKEY
, 0, base
);
1076 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, 26);
1077 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
,
1078 P2_REC_ADDDEFAULTTKIPKEY
);
1079 if(index
== unit
->tx_key_no
)
1081 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, index
);
1082 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (UWORD
*)rx_counter
,
1084 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, 0);
1085 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (UWORD
*)key
,
1087 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (UWORD
*)tx_counter
,
1089 P2DoCmd(unit
, P2_CMD_ACCESS
| P2_CMDF_WRITE
,
1090 P2_REC_ADDDEFAULTTKIPKEY
, base
);
1095 /* Convert key to native endianness */
1097 for(i
= 0; i
< 8; i
++)
1098 slot
->u
.tkip
.key
[i
] = LEWord(slot
->u
.tkip
.key
[i
]);
1104 CopyMem(key
, slot
->u
.ccmp
.key
, 16);
1105 slot
->u
.ccmp
.tx_iv_low
= 0;
1106 slot
->u
.ccmp
.tx_iv_high
= 0;
1107 slot
->u
.ccmp
.rx_iv_low
= LEWord(*(UWORD
*)rx_counter
);
1108 slot
->u
.ccmp
.rx_iv_high
= LELong(*(ULONG
*)(rx_counter
+ 2));
1109 slot
->u
.ccmp
.stream_set
= FALSE
;
1112 /* Clear TKIP key if necessary */
1114 if(slot
->type
== S2ENC_TKIP
&& type
!= S2ENC_TKIP
)
1116 if(unit
->firmware_type
>= HERMES2_FIRMWARE
&& index
== 0)
1117 P2SetData(unit
, P2_REC_REMMAPPEDTKIPKEY
, unit
->bssid
,
1118 ETH_ADDRESSSIZE
, base
);
1119 else if(unit
->firmware_type
>= LUCENT_FIRMWARE
)
1120 P2SetWord(unit
, P2_REC_REMDEFAULTTKIPKEY
, index
, base
);
1123 /* Update type of key in selected slot */
1133 /****i* prism2.device/AddMulticastRange ************************************
1139 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1141 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1143 ****************************************************************************
1147 BOOL
AddMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
1148 const UBYTE
*upper_bound
, struct DevBase
*base
)
1150 struct AddressRange
*range
;
1151 ULONG lower_bound_left
, upper_bound_left
;
1152 UWORD lower_bound_right
, upper_bound_right
;
1154 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
1155 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
1156 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
1157 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
1159 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
1160 upper_bound_left
, upper_bound_right
, base
);
1166 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1169 range
->lower_bound_left
= lower_bound_left
;
1170 range
->lower_bound_right
= lower_bound_right
;
1171 range
->upper_bound_left
= upper_bound_left
;
1172 range
->upper_bound_right
= upper_bound_right
;
1173 range
->add_count
= 1;
1176 AddTail((APTR
)&unit
->multicast_ranges
, (APTR
)range
);
1177 unit
->range_count
++;
1178 SetMulticast(unit
, base
);
1183 return range
!= NULL
;
1188 /****i* prism2.device/RemMulticastRange ************************************
1194 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1196 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1198 ****************************************************************************
1202 BOOL
RemMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
1203 const UBYTE
*upper_bound
, struct DevBase
*base
)
1205 struct AddressRange
*range
;
1206 ULONG lower_bound_left
, upper_bound_left
;
1207 UWORD lower_bound_right
, upper_bound_right
;
1209 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
1210 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
1211 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
1212 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
1214 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
1215 upper_bound_left
, upper_bound_right
, base
);
1219 if(--range
->add_count
== 0)
1222 Remove((APTR
)range
);
1223 unit
->range_count
--;
1224 SetMulticast(unit
, base
);
1226 FreeMem(range
, sizeof(struct AddressRange
));
1230 return range
!= NULL
;
1235 /****i* prism2.device/FindMulticastRange ***********************************
1238 * FindMulticastRange
1241 * range = FindMulticastRange(unit, lower_bound_left,
1242 * lower_bound_right, upper_bound_left, upper_bound_right)
1244 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1245 * UWORD, ULONG, UWORD);
1247 ****************************************************************************
1251 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
1252 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
1253 UWORD upper_bound_right
, struct DevBase
*base
)
1255 struct AddressRange
*range
, *tail
;
1258 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1259 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1261 while(range
!= tail
&& !found
)
1263 if(lower_bound_left
== range
->lower_bound_left
&&
1264 lower_bound_right
== range
->lower_bound_right
&&
1265 upper_bound_left
== range
->upper_bound_left
&&
1266 upper_bound_right
== range
->upper_bound_right
)
1269 range
= (APTR
)range
->node
.mln_Succ
;
1280 /****i* prism2.device/SetMulticast *****************************************
1286 * SetMulticast(unit)
1288 * VOID SetMulticast(struct DevUnit *);
1290 ****************************************************************************
1294 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
)
1297 UWORD address_right
, i
= 0;
1298 struct AddressRange
*range
, *tail
;
1301 /* Fill in multicast list */
1303 P2Seek(unit
, 1, P2_REC_MCASTLIST
, 4, base
);
1305 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1306 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1308 while(range
!= tail
&& i
< P2_MAXMCASTENTRIES
)
1310 address_left
= range
->lower_bound_left
;
1311 address_right
= range
->lower_bound_right
;
1312 range_ended
= FALSE
;
1314 while(!range_ended
&& i
++ < P2_MAXMCASTENTRIES
)
1316 unit
->BEWordOut(unit
->card
, P2_REG_DATA1
,
1317 (UWORD
)(address_left
>> 16));
1318 unit
->BEWordOut(unit
->card
, P2_REG_DATA1
, (UWORD
)address_left
);
1319 unit
->BEWordOut(unit
->card
, P2_REG_DATA1
, (UWORD
)address_right
);
1321 if(address_left
== range
->upper_bound_left
&&
1322 address_right
== range
->upper_bound_right
)
1324 if(++address_right
== 0)
1329 range
= (APTR
)range
->node
.mln_Succ
;
1332 /* Turn promiscuous mode on or off depending on the previous state and
1333 whether we've overflowed the multicast list */
1335 if((unit
->flags
& UNITF_PROM
) == 0)
1339 if((unit
->flags
& UNITF_ALLMCAST
) == 0)
1341 P2SetWord(unit
, P2_REC_PROMISC
, TRUE
, base
);
1342 unit
->flags
|= UNITF_ALLMCAST
;
1347 if((unit
->flags
& UNITF_ALLMCAST
) != 0)
1349 P2SetWord(unit
, P2_REC_PROMISC
, FALSE
, base
);
1350 unit
->flags
&= ~UNITF_ALLMCAST
;
1353 /* Only commit multicast list if promiscuity is off */
1355 P2Seek(unit
, 1, P2_REC_MCASTLIST
, 0, base
);
1356 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
,
1357 1 + ETH_ADDRESSSIZE
/ 2 * i
);
1358 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, P2_REC_MCASTLIST
);
1359 P2DoCmd(unit
, P2_CMD_ACCESS
| P2_CMDF_WRITE
, P2_REC_MCASTLIST
,
1369 /****i* prism2.device/FindTypeStats ****************************************
1375 * stats = FindTypeStats(unit, list,
1378 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1381 ****************************************************************************
1385 struct TypeStats
*FindTypeStats(struct DevUnit
*unit
, struct MinList
*list
,
1386 ULONG packet_type
, struct DevBase
*base
)
1388 struct TypeStats
*stats
, *tail
;
1391 stats
= (APTR
)list
->mlh_Head
;
1392 tail
= (APTR
)&list
->mlh_Tail
;
1394 while(stats
!= tail
&& !found
)
1396 if(stats
->packet_type
== packet_type
)
1399 stats
= (APTR
)stats
->node
.mln_Succ
;
1410 /****i* prism2.device/FlushUnit ********************************************
1416 * FlushUnit(unit, last_queue, error)
1418 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1420 ****************************************************************************
1424 VOID
FlushUnit(struct DevUnit
*unit
, UBYTE last_queue
, BYTE error
,
1425 struct DevBase
*base
)
1427 struct IORequest
*request
;
1429 struct Opener
*opener
, *tail
;
1431 /* Abort queued requests */
1433 for(i
= 0; i
<= last_queue
; i
++)
1435 while((request
= (APTR
)GetMsg(unit
->request_ports
[i
])) != NULL
)
1437 request
->io_Error
= error
;
1438 ReplyMsg((APTR
)request
);
1443 opener
= (APTR
)unit
->openers
.mlh_Head
;
1444 tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1446 /* Flush every opener's read queue */
1448 while(opener
!= tail
)
1450 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1452 request
->io_Error
= error
;
1453 ReplyMsg((APTR
)request
);
1455 opener
= (APTR
)opener
->node
.mln_Succ
;
1459 opener
= request
->ios2_BufferManagement
;
1460 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1462 request
->io_Error
= error
;
1463 ReplyMsg((APTR
)request
);
1474 /****i* prism2.device/StatusInt ********************************************
1480 * finished = StatusInt(unit)
1482 * BOOL StatusInt(struct DevUnit *);
1492 ****************************************************************************
1494 * int_code is really in A5, but GCC 2.95.3 doesn't seem able to handle that.
1495 * Since we don't use this parameter, we can lie.
1499 BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
1501 struct DevBase
*base
;
1502 UWORD events
, int_mask
;
1504 base
= unit
->device
;
1505 events
= unit
->LEWordIn(unit
->card
, P2_REG_EVENTS
);
1507 /* Turning off ints acknowledges the request? */
1509 int_mask
= unit
->LEWordIn(unit
->card
, P2_REG_INTMASK
);
1510 unit
->LEWordOut(unit
->card
, P2_REG_INTMASK
, 0);
1514 if((events
& P2_EVENTF_INFO
) != 0)
1516 int_mask
&= ~P2_EVENTF_INFO
;
1517 Cause(&unit
->info_int
);
1519 if((events
& P2_EVENTF_RX
) != 0)
1521 int_mask
&= ~P2_EVENTF_RX
;
1522 Cause(&unit
->rx_int
);
1524 if((events
& P2_EVENTF_ALLOCMEM
) != 0)
1526 unit
->tx_frame_id
= unit
->LEWordIn(unit
->card
, P2_REG_ALLOCFID
);
1527 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, P2_EVENTF_ALLOCMEM
);
1528 Cause(&unit
->tx_int
);
1530 if((events
& P2_EVENTF_TXFAIL
) != 0)
1532 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_TX
,
1534 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, P2_EVENTF_TXFAIL
);
1538 int_mask
= INT_MASK
;
1540 unit
->LEWordOut(unit
->card
, P2_REG_INTMASK
, int_mask
);
1547 /****i* prism2.device/RXInt ************************************************
1550 * RXInt -- Soft interrupt for packet reception.
1555 * VOID RXInt(struct DevUnit *);
1560 * unit - A unit of this device.
1565 ****************************************************************************
1569 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
1571 UWORD frame_status
, frame_id
, ieee_length
, frame_control
, frame_type
,
1572 frame_subtype
, encryption
, key_no
, buffer_no
, old_length
;
1573 struct DevBase
*base
;
1576 UBYTE
*buffer
, *p
, *frame
, *data
;
1578 base
= unit
->device
;
1580 while((unit
->LEWordIn(unit
->card
, P2_REG_EVENTS
) & P2_EVENTF_RX
) != 0)
1583 frame_id
= unit
->LEWordIn(unit
->card
, P2_REG_RXFID
);
1584 P2Seek(unit
, 1, frame_id
, P2_FRM_STATUS
, base
);
1585 frame_status
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
1587 if((frame_status
& (P2_FRM_STATUSF_BADCRYPT
| P2_FRM_STATUSF_BADCRC
))
1590 /* Read frame descriptor from card */
1592 P2Seek(unit
, 1, frame_id
, 0, base
);
1593 unit
->WordsIn(unit
->card
, P2_REG_DATA1
,
1594 (UWORD
*)unit
->rx_descriptor
,
1595 (unit
->ethernet_offset
+ ETH_HEADERSIZE
) / 2);
1596 frame
= unit
->rx_descriptor
+ unit
->ethernet_offset
;
1597 ieee_length
= BEWord(*(UWORD
*)(frame
+ ETH_PACKET_IEEELEN
));
1598 data
= frame
+ ETH_PACKET_DATA
;
1599 unit
->WordsIn(unit
->card
, P2_REG_DATA1
, (UWORD
*)data
,
1600 (ieee_length
+ MIC_SIZE
+ 1) / 2);
1602 LEWord(*(UWORD
*)(unit
->rx_descriptor
+ P2_FRM_HEADER
));
1604 /* Get buffer to store fragment in */
1606 frag_no
= LEWord(*(UWORD
*)(unit
->rx_descriptor
+ P2_FRM_HEADER
1607 + WIFI_FRM_SEQCONTROL
));
1608 buffer
= GetRXBuffer(unit
, frame
+ ETH_PACKET_SOURCE
, frag_no
,
1611 /* Get location to put new data */
1615 if((frag_no
& 0xf ) > 0)
1616 old_length
= BEWord(*(UWORD
*)(buffer
+ ETH_PACKET_IEEELEN
));
1619 /* Copy header to new frame */
1621 CopyMem(frame
, buffer
, ETH_HEADERSIZE
);
1624 p
= buffer
+ ETH_HEADERSIZE
+ old_length
;
1626 /* Get encryption type and key index */
1628 if((frame_control
& WIFI_FRM_CONTROLF_WEP
) != 0)
1630 key_no
= data
[3] >> 6 & 0x3;
1631 encryption
= unit
->keys
[key_no
].type
;
1634 encryption
= S2ENC_NONE
;
1636 /* Append fragment to frame, decrypting/checking fragment if
1639 is_good
= unit
->fragment_decrypt_functions
[encryption
](unit
,
1640 unit
->rx_descriptor
+ P2_FRM_HEADER
, data
, &ieee_length
, p
,
1643 /* Update length in frame being built with current fragment, or
1644 increment bad frame counter if fragment is bad */
1648 ieee_length
+= old_length
;
1649 *(UWORD
*)(buffer
+ ETH_PACKET_IEEELEN
) =
1650 MakeBEWord(ieee_length
);
1653 unit
->stats
.BadData
++;
1655 /* If all fragments have arrived, process the complete frame */
1657 if((frame_control
& WIFI_FRM_CONTROLF_MOREFRAGS
) == 0)
1661 /* Decrypt complete frame if necessary */
1663 data
= buffer
+ ETH_HEADERSIZE
;
1664 if(encryption
== S2ENC_TKIP
)
1666 /* Hermes cards don't include MIC in frame length, so
1667 we need to grab the MIC from the original RX
1670 if(unit
->firmware_type
>= LUCENT_FIRMWARE
)
1672 CopyMem(frame
+ ETH_PACKET_DATA
+ ieee_length
,
1673 data
+ ieee_length
, MIC_SIZE
);
1674 ieee_length
+= MIC_SIZE
;
1677 /* Check Michael MIC */
1680 is_good
= TKIPDecryptFrame(unit
, buffer
, data
,
1681 ieee_length
, data
, key_no
, base
);
1683 ieee_length
-= MIC_SIZE
;
1684 *(UWORD
*)(buffer
+ ETH_PACKET_IEEELEN
) =
1685 MakeBEWord(ieee_length
);
1687 unit
->stats
.BadData
++;
1693 /* Get frame's 802.11 type and subtype */
1695 frame_type
= (frame_control
& WIFI_FRM_CONTROLF_TYPE
)
1696 >> WIFI_FRM_CONTROLB_TYPE
;
1698 (frame_control
& WIFI_FRM_CONTROLF_SUBTYPE
)
1699 >> WIFI_FRM_CONTROLB_SUBTYPE
;
1701 /* If it's a management frame, process it internally;
1702 otherwise distribute it to clients after filtering */
1704 if(frame_type
== WIFI_FRMTYPE_MGMT
)
1706 if(frame_subtype
== 0x5)
1708 CopyMem(unit
->rx_descriptor
+ P2_FRM_HEADER
1709 + WIFI_FRM_ADDRESS3
, buffer
+ ETH_PACKET_SOURCE
,
1711 SaveBeacon(unit
, buffer
, base
);
1714 else if(AddressFilter(unit
, buffer
+ ETH_PACKET_DEST
,
1717 unit
->stats
.PacketsReceived
++;
1718 DistributeRXPacket(unit
, buffer
, base
);
1723 /* Mark fragment buffer as unused for next time */
1725 unit
->rx_fragment_nos
[buffer_no
] = -1;
1728 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_RX
, base
);
1737 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
,
1741 /* Discard packet */
1743 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, P2_EVENTF_RX
);
1746 /* Re-enable RX interrupts */
1749 unit
->LEWordOut(unit
->card
, P2_REG_INTMASK
,
1750 unit
->LEWordIn(unit
->card
, P2_REG_INTMASK
) | P2_EVENTF_RX
);
1758 /****i* prism2.device/GetRXBuffer ******************************************
1761 * GetRXBuffer -- Find an appropriate RX buffer to use.
1764 * buffer = GetRXBuffer(unit, address, frag_no)
1766 * UBYTE *GetRXBuffer(struct DevUnit *, UBYTE *, UWORD);
1768 ****************************************************************************
1772 static UBYTE
*GetRXBuffer(struct DevUnit
*unit
, const UBYTE
*address
,
1773 UWORD frag_no
, UWORD
*buffer_no
, struct DevBase
*base
)
1780 buffer
= unit
->rx_buffers
;
1781 for(i
= 0, found
= FALSE
; i
< RX_BUFFER_COUNT
* 2 && !found
; i
++)
1783 /* Throw away old buffer contents if we didn't find a free slot the
1784 first time around */
1786 if(i
>= RX_BUFFER_COUNT
)
1787 unit
->rx_fragment_nos
[i
% RX_BUFFER_COUNT
] = -1;
1789 /* For a frame's first fragment, find an empty slot; for subsequent
1790 fragments, find a slot with matching source address */
1792 n
= unit
->rx_fragment_nos
[i
% RX_BUFFER_COUNT
];
1793 if(n
== -1 && (frag_no
& 0xf) == 0
1794 || *((ULONG
*)(buffer
+ ETH_PACKET_SOURCE
))
1795 == *((ULONG
*)(address
))
1796 && *((UWORD
*)(buffer
+ ETH_PACKET_SOURCE
+ 4))
1797 == *((UWORD
*)(address
+ 4)))
1801 unit
->rx_fragment_nos
[i
% RX_BUFFER_COUNT
] = frag_no
;
1805 buffer
+= FRAME_BUFFER_SIZE
;
1816 /****i* prism2.device/DistributeRXPacket ***********************************
1819 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1822 * DistributeRXPacket(unit, frame)
1824 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1826 ****************************************************************************
1830 static VOID
DistributeRXPacket(struct DevUnit
*unit
, UBYTE
*frame
,
1831 struct DevBase
*base
)
1833 UWORD packet_size
, ieee_length
;
1834 BOOL is_orphan
= TRUE
, accepted
, is_snap
= FALSE
;
1837 const UBYTE
*template = snap_template
;
1838 struct IOSana2Req
*request
, *request_tail
;
1839 struct Opener
*opener
, *opener_tail
;
1840 struct TypeStats
*tracker
;
1842 ieee_length
= BEWord(*(UWORD
*)(frame
+ ETH_PACKET_IEEELEN
));
1843 packet_size
= ETH_HEADERSIZE
+ ieee_length
;
1844 if(ieee_length
>= SNAP_HEADERSIZE
)
1845 is_snap
= *(const ULONG
*)(frame
+ ETH_PACKET_DATA
)
1846 == *(const ULONG
*)template;
1848 /* De-encapsulate SNAP packets and get packet type */
1852 buffer
= unit
->rx_buffer
;
1853 packet_size
-= SNAP_HEADERSIZE
;
1854 CopyMem(frame
, buffer
, ETH_PACKET_TYPE
);
1855 CopyMem(frame
+ ETH_HEADERSIZE
+ SNAP_FRM_TYPE
,
1856 buffer
+ ETH_PACKET_TYPE
, packet_size
- ETH_PACKET_TYPE
);
1861 packet_type
= BEWord(*((UWORD
*)(buffer
+ ETH_PACKET_TYPE
)));
1863 if(packet_size
<= ETH_MAXPACKETSIZE
)
1865 /* Offer packet to every opener */
1867 opener
= (APTR
)unit
->openers
.mlh_Head
;
1868 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1870 while(opener
!= opener_tail
)
1872 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
1873 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
1876 /* Offer packet to each request until it's accepted */
1878 while(request
!= request_tail
&& !accepted
)
1880 if(request
->ios2_PacketType
== packet_type
)
1882 CopyPacket(unit
, request
, packet_size
, packet_type
,
1887 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1892 opener
= (APTR
)opener
->node
.mln_Succ
;
1895 /* If packet was unwanted, give it to S2_READORPHAN request */
1899 unit
->stats
.UnknownTypesReceived
++;
1900 if(!IsMsgPortEmpty(unit
->request_ports
[ADOPT_QUEUE
]))
1903 (APTR
)unit
->request_ports
[ADOPT_QUEUE
]->
1904 mp_MsgList
.lh_Head
, packet_size
, packet_type
, buffer
,
1909 /* Update remaining statistics */
1911 if(packet_type
<= ETH_MTU
)
1912 packet_type
= ETH_MTU
;
1914 FindTypeStats(unit
, &unit
->type_trackers
, packet_type
, base
);
1917 tracker
->stats
.PacketsReceived
++;
1918 tracker
->stats
.BytesReceived
+= packet_size
;
1922 unit
->stats
.BadData
++;
1929 /****i* prism2.device/CopyPacket *******************************************
1932 * CopyPacket -- Copy packet to client's buffer.
1935 * CopyPacket(unit, request, packet_size, packet_type,
1938 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1941 ****************************************************************************
1945 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
1946 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
1947 struct DevBase
*base
)
1949 struct Opener
*opener
;
1950 BOOL filtered
= FALSE
;
1952 /* Set multicast and broadcast flags */
1954 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
1955 if((*((ULONG
*)(buffer
+ ETH_PACKET_DEST
)) == 0xffffffff) &&
1956 (*((UWORD
*)(buffer
+ ETH_PACKET_DEST
+ 4)) == 0xffff))
1957 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1958 else if((buffer
[ETH_PACKET_DEST
] & 0x1) != 0)
1959 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1961 /* Set source and destination addresses and packet type */
1963 CopyMem(buffer
+ ETH_PACKET_SOURCE
, request
->ios2_SrcAddr
,
1965 CopyMem(buffer
+ ETH_PACKET_DEST
, request
->ios2_DstAddr
,
1967 request
->ios2_PacketType
= packet_type
;
1969 /* Adjust for cooked packet request */
1971 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1973 packet_size
-= ETH_PACKET_DATA
;
1974 buffer
+= ETH_PACKET_DATA
;
1978 packet_size
+= 4; /* Needed for Shapeshifter & Fusion */
1980 request
->ios2_DataLength
= packet_size
;
1984 opener
= request
->ios2_BufferManagement
;
1985 if(request
->ios2_Req
.io_Command
== CMD_READ
&&
1986 opener
->filter_hook
!= NULL
)
1987 if(!CallHookPkt(opener
->filter_hook
, request
, buffer
))
1992 /* Copy packet into opener's buffer and reply packet */
1994 if(!opener
->rx_function(request
->ios2_Data
, buffer
, packet_size
))
1996 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1997 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1999 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
2002 Remove((APTR
)request
);
2003 ReplyMsg((APTR
)request
);
2011 /****i* prism2.device/AddressFilter ****************************************
2014 * AddressFilter -- Determine if an RX packet should be accepted.
2017 * accept = AddressFilter(unit, address)
2019 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
2021 ****************************************************************************
2025 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
2026 struct DevBase
*base
)
2028 struct AddressRange
*range
, *tail
;
2031 UWORD address_right
;
2033 /* Check whether address is unicast/broadcast or multicast */
2035 address_left
= BELong(*((ULONG
*)address
));
2036 address_right
= BEWord(*((UWORD
*)(address
+ 4)));
2038 if(((address_left
& 0x01000000) != 0) &&
2039 !((address_left
== 0xffffffff) && (address_right
== 0xffff)))
2041 /* Check if this multicast address is wanted */
2043 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
2044 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
2047 while((range
!= tail
) && !accept
)
2049 if((address_left
> range
->lower_bound_left
||
2050 address_left
== range
->lower_bound_left
&&
2051 address_right
>= range
->lower_bound_right
) &&
2052 (address_left
< range
->upper_bound_left
||
2053 address_left
== range
->upper_bound_left
&&
2054 address_right
<= range
->upper_bound_right
))
2056 range
= (APTR
)range
->node
.mln_Succ
;
2060 unit
->special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
2068 /****i* prism2.device/SaveBeacon *******************************************
2071 * SaveBeacon -- Save beacon frame for later examination.
2074 * SaveBeacon(unit, frame)
2076 * VOID SaveBeacon(struct DevUnit *, UBYTE *);
2078 ****************************************************************************
2082 static VOID
SaveBeacon(struct DevUnit
*unit
, const UBYTE
*frame
,
2083 struct DevBase
*base
)
2087 /* Store frame for later matching with scan results */
2089 size
= ETH_HEADERSIZE
+ BEWord(*(UWORD
*)(frame
+ ETH_PACKET_IEEELEN
));
2090 if(unit
->next_beacon
+ size
< unit
->beacons
+ BEACON_BUFFER_SIZE
)
2092 CopyMem(frame
, unit
->next_beacon
, size
);
2093 unit
->beacon_count
++;
2094 unit
->next_beacon
+= size
+ sizeof(ULONG
) & ~3;
2102 /****i* prism2.device/TXInt ************************************************
2105 * TXInt -- Soft interrupt for packet transmission.
2110 * VOID TXInt(struct DevUnit *);
2115 * unit - A unit of this device.
2120 ****************************************************************************
2124 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
2126 UWORD i
, packet_size
, send_size
, packet_type
, data_size
, body_size
= 0,
2127 frame_id
, encryption
, control_value
, subtype
;
2128 UBYTE
*buffer
, *desc
= unit
->tx_descriptor
, *plaintext
, *ciphertext
,
2129 *header
, mic_header
[ETH_ADDRESSSIZE
* 2], *q
;
2130 const UBYTE
*p
, *dest
, *source
;
2131 struct DevBase
*base
;
2132 struct IOSana2Req
*request
;
2134 struct Opener
*opener
;
2136 UBYTE
*(*dma_tx_function
)(REG(a0
, APTR
));
2138 struct MsgPort
*port
;
2139 struct TypeStats
*tracker
;
2141 base
= unit
->device
;
2142 port
= unit
->request_ports
[WRITE_QUEUE
];
2144 if(unit
->tx_frame_id
!= 0 && !IsMsgPortEmpty(port
))
2146 /* Get next request and full packet size */
2148 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
2149 packet_size
= request
->ios2_DataLength
;
2150 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
2151 packet_size
+= ETH_PACKET_DATA
;
2153 /* Determine encryption type and frame subtype */
2155 if(packet_size
> ETH_HEADERSIZE
)
2157 encryption
= unit
->keys
[unit
->tx_key_no
].type
;
2162 encryption
= S2ENC_NONE
;
2166 /* Get packet data */
2168 opener
= request
->ios2_BufferManagement
;
2169 dma_tx_function
= opener
->dma_tx_function
;
2170 if(dma_tx_function
!= NULL
)
2171 buffer
= dma_tx_function(request
->ios2_Data
);
2177 buffer
= unit
->tx_buffer
;
2178 if(!opener
->tx_function(buffer
, request
->ios2_Data
,
2179 request
->ios2_DataLength
))
2181 error
= S2ERR_NO_RESOURCES
;
2182 wire_error
= S2WERR_BUFF_ERROR
;
2184 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_TX
,
2191 /* Get packet type and/or length */
2193 data_size
= request
->ios2_DataLength
;
2194 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) != 0)
2196 data_size
-= ETH_PACKET_DATA
;
2197 packet_type
= BEWord(*(UWORD
*)(buffer
+ ETH_PACKET_TYPE
));
2200 packet_type
= request
->ios2_PacketType
;
2201 is_ieee
= packet_type
<= ETH_MTU
;
2203 /* Get source and destination addresses */
2205 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) != 0)
2208 source
= buffer
+ ETH_ADDRESSSIZE
;
2209 buffer
+= ETH_ADDRESSSIZE
* 2 + 2;
2213 dest
= request
->ios2_DstAddr
;
2214 source
= unit
->address
;
2217 /* Clear frame descriptor as far as start of 802.11 header */
2220 for(i
= 0; i
< P2_FRM_HEADER
; i
++)
2224 /* Set TX control field */
2226 control_value
= P2_FRM_TXCONTROLF_NATIVE
;
2227 if(encryption
== S2ENC_TKIP
&& (unit
->flags
& UNITF_HARDTKIP
) != 0)
2228 control_value
|= unit
->tx_key_no
<< P2_FRM_TXCONTROLB_MICKEYID
2229 | P2_FRM_TXCONTROLF_MIC
;
2230 else if(encryption
== S2ENC_NONE
2231 && unit
->firmware_type
< LUCENT_FIRMWARE
)
2232 control_value
|= P2_FRM_TXCONTROLF_NOENC
;
2234 *(UWORD
*)(desc
+ unit
->txcontrol_offset
) =
2235 MakeLEWord(control_value
);
2237 /* Write 802.11 header */
2239 *(UWORD
*)q
= MakeLEWord(
2240 (encryption
== S2ENC_NONE
? 0 : WIFI_FRM_CONTROLF_WEP
)
2241 | (unit
->mode
== S2PORT_ADHOC
? 0 : WIFI_FRM_CONTROLF_TODS
)
2242 | subtype
<< WIFI_FRM_CONTROLB_SUBTYPE
2243 | WIFI_FRMTYPE_DATA
<< WIFI_FRM_CONTROLB_TYPE
);
2249 if(unit
->mode
== S2PORT_ADHOC
)
2253 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
2256 for(i
= 0, p
= source
; i
< ETH_ADDRESSSIZE
; i
++)
2259 if(unit
->mode
== S2PORT_ADHOC
)
2263 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
2267 /* Clear 802.3 header */
2269 q
= desc
+ unit
->ethernet_offset
;
2270 for(i
= 0; i
< ETH_HEADERSIZE
; i
++)
2273 /* Leave room for encryption overhead */
2275 q
= desc
+ unit
->data_offset
;
2277 q
+= unit
->iv_sizes
[encryption
];
2280 /* Write SNAP header */
2284 for(i
= 0, p
= snap_template
; i
< SNAP_FRM_TYPE
; i
++)
2286 *(UWORD
*)q
= MakeBEWord(packet_type
);
2288 body_size
+= SNAP_HEADERSIZE
;
2291 /* Copy data into frame */
2293 CopyMem(buffer
, q
, data_size
);
2294 body_size
+= data_size
;
2296 /* Append MIC to frame for TKIP */
2298 if(encryption
== S2ENC_TKIP
)
2301 for(i
= 0, p
= dest
; i
< ETH_ADDRESSSIZE
; i
++)
2303 for(i
= 0, p
= source
; i
< ETH_ADDRESSSIZE
; i
++)
2305 TKIPEncryptFrame(unit
, mic_header
, plaintext
, body_size
,
2307 body_size
+= MIC_SIZE
;
2310 /* Encrypt fragment if applicable */
2312 unit
->fragment_encrypt_functions
[encryption
](unit
, header
,
2313 plaintext
, &body_size
, ciphertext
, base
);
2315 /* Calculate total length of data to send to adapter */
2317 send_size
= unit
->data_offset
+ body_size
;
2319 /* Fill in length field, adjusting for Hermes peculiarities */
2321 if(unit
->firmware_type
>= LUCENT_FIRMWARE
2322 && encryption
== S2ENC_TKIP
)
2323 body_size
-= MIC_SIZE
;
2325 if(unit
->firmware_type
== LUCENT_FIRMWARE
2326 && (unit
->flags
& UNITF_HARDTKIP
) != 0)
2327 *(UWORD
*)(desc
+ unit
->ethernet_offset
+ ETH_PACKET_IEEELEN
) =
2328 MakeBEWord(body_size
);
2330 *(UWORD
*)(desc
+ unit
->datalen_offset
) = MakeLEWord(body_size
);
2332 /* Write packet to adapter and send */
2334 frame_id
= unit
->tx_frame_id
;
2335 P2Seek(unit
, 0, frame_id
, 0, base
);
2336 unit
->WordsOut(unit
->card
, P2_REG_DATA0
, (UWORD
*)desc
,
2337 (send_size
+ 1) / 2);
2338 unit
->tx_frame_id
= 0;
2339 P2DoCmd(unit
, P2_CMD_TX
| P2_CMDF_RECLAIM
, frame_id
, base
);
2344 request
->ios2_Req
.io_Error
= error
;
2345 request
->ios2_WireError
= wire_error
;
2346 Remove((APTR
)request
);
2347 ReplyMsg((APTR
)request
);
2349 /* Update statistics */
2353 unit
->stats
.PacketsSent
++;
2355 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
2356 request
->ios2_PacketType
, base
);
2359 tracker
->stats
.PacketsSent
++;
2360 tracker
->stats
.BytesSent
+= packet_size
;
2365 /* Don't try to keep sending packets if there's no space left */
2367 if(unit
->tx_frame_id
!= 0)
2368 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
2370 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
2377 /****i* prism2.device/UpdateStats ******************************************
2385 * VOID UpdateStats(struct DevUnit *);
2390 * unit - A unit of this device.
2395 ****************************************************************************
2399 VOID
UpdateStats(struct DevUnit
*unit
, struct DevBase
*base
)
2401 /* Ask for and wait for stats */
2403 if((unit
->flags
& UNITF_ONLINE
) != 0)
2406 unit
->LEWordOut(unit
->card
, P2_REG_INTMASK
,
2407 unit
->LEWordIn(unit
->card
, P2_REG_INTMASK
) & ~P2_EVENTF_INFO
);
2409 P2DoCmd(unit
, P2_CMD_INQUIRE
, P2_INFO_COUNTERS
, base
);
2410 while((unit
->LEWordIn(unit
->card
, P2_REG_EVENTS
) & P2_EVENTF_INFO
)
2412 Cause(&unit
->info_int
);
2420 /****i* prism2.device/InfoInt **********************************************
2428 * VOID InfoInt(struct DevUnit *);
2433 * unit - A unit of this device.
2439 * The only reason this is a (soft) interrupt is so that it won't
2440 * interfere with RXInt() by interrupting it. This would be dangerous
2441 * because they use the same data channel.
2443 ****************************************************************************
2447 static VOID
InfoInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
2449 struct DevBase
*base
;
2450 UWORD id
, length
, rec_length
, status
, ies_length
, data_length
,
2451 ssid_length
, *ap_rec
, *rec
, count
, i
;
2452 UBYTE
*ie
, *ssid
, *descriptor
, *frame
, *data
, *bssid
= unit
->bssid
;
2453 BOOL associated
, is_duplicate
= FALSE
;
2455 base
= unit
->device
;
2456 id
= unit
->LEWordIn(unit
->card
, P2_REG_INFOFID
);
2458 P2Seek(unit
, 1, id
, 0, base
);
2459 length
= (unit
->LEWordIn(unit
->card
, P2_REG_DATA1
) + 1) * 2;
2461 switch(unit
->LEWordIn(unit
->card
, P2_REG_DATA1
))
2463 case P2_INFO_COUNTERS
:
2465 /* Read useful stats and skip others */
2467 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2468 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2470 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2471 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2472 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2473 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2475 unit
->special_stats
[S2SS_ETHERNET_RETRIES
& 0xffff] +=
2476 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
) +
2477 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
) +
2478 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2480 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2482 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2483 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2485 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2486 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2487 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2489 unit
->stats
.BadData
+= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2490 unit
->stats
.Overruns
+= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2492 unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2494 unit
->stats
.BadData
+= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2498 case P2_INFO_SCANRESULTS
:
2499 case P2_INFO_HOSTSCANRESULTS
:
2501 P2ReadRec(unit
, id
, unit
->scan_results_rec
, SCAN_BUFFER_SIZE
, base
);
2502 Signal(unit
->task
, unit
->scan_complete_signal
);
2505 case P2_INFO_SCANRESULT
:
2507 descriptor
= unit
->rx_descriptor
;
2508 P2ReadRec(unit
, id
, descriptor
, FRAME_BUFFER_SIZE
, base
);
2511 /* Save IEEE 802.3 portion of scan result */
2513 frame
= descriptor
+ unit
->ethernet_offset
;
2514 data
= frame
+ ETH_PACKET_DATA
;
2515 CopyMem(descriptor
+ P2_FRM_HEADER
+ WIFI_FRM_ADDRESS3
,
2516 frame
+ ETH_PACKET_SOURCE
, ETH_ADDRESSSIZE
);
2518 LEWord(*(UWORD
*)(descriptor
+ unit
->datalen_offset
));
2519 ies_length
= data_length
- WIFI_BEACON_IES
;
2520 *(UWORD
*)(frame
+ ETH_PACKET_IEEELEN
) = MakeBEWord(data_length
);
2522 /* Append a fake old-style scan record on to fake record list */
2524 rec_length
= LEWord(unit
->scan_results_rec
[0]);
2525 ap_rec
= unit
->scan_results_rec
+ 1 + rec_length
;
2527 /* Check for duplicate scan results */
2529 rec
= unit
->scan_results_rec
+ 2;
2530 count
= (rec_length
- 1) * 2 / P2_APRECLEN
;
2531 for(i
= 0; i
< count
&& !is_duplicate
; i
++, rec
+= P2_APRECLEN
/ 2)
2532 if(CompareMACAddresses(frame
+ ETH_PACKET_SOURCE
,
2533 rec
+ P2_APREC_BSSID
/ 2))
2534 is_duplicate
= TRUE
;
2536 /* Only add new record if there's space and its BSSID hasn't
2537 already been seen */
2539 if(2 + rec_length
* 2 + P2_APRECLEN
< SCAN_BUFFER_SIZE
2542 SaveBeacon(unit
, frame
, base
);
2544 CopyMem(frame
+ ETH_PACKET_SOURCE
, ap_rec
+ P2_APREC_BSSID
/ 2,
2547 ap_rec
[P2_APREC_SIGNAL
/ 2] =
2548 MakeLEWord(descriptor
[P2_FRM_SIGNAL
]);
2550 ap_rec
[P2_APREC_NOISE
/ 2] =
2551 MakeLEWord(descriptor
[P2_FRM_NOISE
]);
2553 ap_rec
[P2_APREC_CHANNEL
/ 2] = MakeLEWord(GetIE(WIFI_IE_CHANNEL
,
2554 data
+ WIFI_BEACON_IES
, ies_length
, base
)[2]);
2556 ap_rec
[P2_APREC_INTERVAL
/ 2] =
2557 *(UWORD
*)(data
+ WIFI_BEACON_INTERVAL
);
2559 ap_rec
[P2_APREC_CAPABILITIES
/ 2] =
2560 *(UWORD
*)(data
+ WIFI_BEACON_CAPABILITIES
);
2562 ie
= GetIE(WIFI_IE_SSID
, data
+ WIFI_BEACON_IES
, ies_length
,
2564 ssid_length
= ie
[1];
2566 ap_rec
[P2_APREC_NAMELEN
/ 2] = MakeLEWord(ssid_length
);
2567 CopyMem(ssid
, ap_rec
+ P2_APREC_NAME
/ 2, ssid_length
);
2569 unit
->scan_results_rec
[0] =
2570 MakeLEWord(rec_length
+ P2_APRECLEN
/ 2);
2574 Signal(unit
->task
, unit
->scan_complete_signal
);
2577 case P2_INFO_LINKSTATUS
:
2579 /* Only report an event if association status has really changed */
2581 status
= unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
2583 if(status
== 1 || unit
->firmware_type
< LUCENT_FIRMWARE
2589 if(!(*(ULONG
*)bssid
== 0 && *(UWORD
*)(bssid
+ 4) == 0))
2591 if(associated
&& (unit
->flags
& UNITF_ASSOCIATED
) == 0)
2593 unit
->flags
|= UNITF_ASSOCIATED
;
2594 ReportEvents(unit
, S2EVENT_CONNECT
, base
);
2596 else if(!associated
&& (unit
->flags
& UNITF_ASSOCIATED
) != 0)
2598 unit
->flags
&= ~UNITF_ASSOCIATED
;
2599 ReportEvents(unit
, S2EVENT_DISCONNECT
, base
);
2604 /* Acknowledge event and re-enable info interrupts */
2606 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, P2_EVENTF_INFO
);
2608 if((unit
->flags
& UNITF_ONLINE
) != 0)
2609 unit
->LEWordOut(unit
->card
, P2_REG_INTMASK
,
2610 unit
->LEWordIn(unit
->card
, P2_REG_INTMASK
) | P2_EVENTF_INFO
);
2618 /****i* prism2.device/ResetHandler *****************************************
2621 * ResetHandler -- Disable hardware before a reboot.
2624 * ResetHandler(unit, int_code)
2626 * VOID ResetHandler(struct DevUnit *, APTR);
2628 ****************************************************************************
2632 static VOID
ResetHandler(REG(a1
, struct DevUnit
*unit
),
2633 REG(a6
, APTR int_code
))
2635 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
2637 /* Stop interrupts */
2639 unit
->LEWordOut(unit
->card
, P2_REG_INTMASK
, 0);
2641 /* Stop transmission and reception */
2643 unit
->LEWordOut(unit
->card
, P2_REG_PARAM0
, 0);
2644 unit
->LEWordOut(unit
->card
, P2_REG_COMMAND
, P2_CMD_DISABLE
);
2652 /****i* prism2.device/ReportEvents *****************************************
2658 * ReportEvents(unit, events)
2660 * VOID ReportEvents(struct DevUnit *, ULONG);
2665 * unit - A unit of this device.
2666 * events - A mask of events to report.
2671 ****************************************************************************
2675 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
2676 struct DevBase
*base
)
2678 struct IOSana2Req
*request
, *tail
, *next_request
;
2681 list
= &unit
->request_ports
[EVENT_QUEUE
]->mp_MsgList
;
2682 next_request
= (APTR
)list
->lh_Head
;
2683 tail
= (APTR
)&list
->lh_Tail
;
2686 while(next_request
!= tail
)
2688 request
= next_request
;
2689 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
2691 if((request
->ios2_WireError
& events
) != 0)
2693 request
->ios2_WireError
= events
;
2694 Remove((APTR
)request
);
2695 ReplyMsg((APTR
)request
);
2705 /****i* prism2.device/SendScanResults **************************************
2708 * SendScanResults -- Reply to all outstanding scan requests.
2711 * SendScanResults(unit)
2713 * VOID SendScanResults(struct DevUnit *);
2718 * unit - A unit of this device.
2723 ****************************************************************************
2727 static VOID
SendScanResults(struct DevUnit
*unit
, struct DevBase
*base
)
2730 struct IOSana2Req
*request
, *tail
, *next_request
;
2733 UWORD count
, i
, j
, ssid_length
, length
, entry_length
, *ap_rec
,
2734 data_length
, frame_length
, ies_length
;
2735 struct TagItem
**tag_lists
, *tag
;
2737 const UBYTE
*beacon
, *ie_bssid
;
2740 list
= &unit
->request_ports
[SCAN_QUEUE
]->mp_MsgList
;
2741 next_request
= (APTR
)list
->lh_Head
;
2742 tail
= (APTR
)&list
->lh_Tail
;
2744 while(next_request
!= tail
)
2746 request
= next_request
;
2747 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
2749 pool
= request
->ios2_Data
;
2751 length
= LEWord(unit
->scan_results_rec
[0]);
2752 ap_rec
= unit
->scan_results_rec
+ 2;
2754 if(unit
->firmware_type
== INTERSIL_FIRMWARE
)
2756 entry_length
= LEWord(unit
->scan_results_rec
[2]);
2758 count
= (length
- 3) * 2 / entry_length
;
2762 entry_length
= P2_APRECLEN
;
2763 count
= (length
- 1) * 2 / entry_length
;
2766 /* Allocate array of tag lists, one for each AP */
2770 tag_lists
= AllocPooled(pool
, count
* sizeof(APTR
));
2771 if(tag_lists
== NULL
)
2772 error
= S2ERR_NO_RESOURCES
;
2777 for(i
= 0; i
< count
&& error
== 0; i
++, ap_rec
+= entry_length
/ 2)
2780 AllocPooled(pool
, SCAN_TAG_COUNT
* sizeof(struct TagItem
));
2781 if(tag_lists
[i
] == NULL
)
2782 error
= S2ERR_NO_RESOURCES
;
2788 tag
->ti_Tag
= S2INFO_BSSID
;
2789 tag
->ti_Data
= (UPINT
)(bssid
=
2790 AllocPooled(pool
, ETH_ADDRESSSIZE
));
2792 CopyMem(ap_rec
+ P2_APREC_BSSID
/ 2, bssid
,
2795 error
= S2ERR_NO_RESOURCES
;
2798 tag
->ti_Tag
= TAG_IGNORE
;
2801 tag
->ti_Tag
= S2INFO_Channel
;
2802 tag
->ti_Data
= LEWord(ap_rec
[P2_APREC_CHANNEL
/ 2]);
2805 tag
->ti_Tag
= S2INFO_BeaconInterval
;
2806 tag
->ti_Data
= LEWord(ap_rec
[P2_APREC_INTERVAL
/ 2]);
2809 tag
->ti_Tag
= S2INFO_Capabilities
;
2810 tag
->ti_Data
= LEWord(ap_rec
[P2_APREC_CAPABILITIES
/ 2]);
2813 tag
->ti_Tag
= S2INFO_Signal
;
2814 tag
->ti_Data
= ConvertScanLevel(unit
,
2815 LEWord(ap_rec
[P2_APREC_SIGNAL
/ 2]), base
);
2818 tag
->ti_Tag
= S2INFO_Noise
;
2819 tag
->ti_Data
= ConvertScanLevel(unit
,
2820 LEWord(ap_rec
[P2_APREC_NOISE
/ 2]), base
);
2824 ssid_length
= LEWord(ap_rec
[P2_APREC_NAMELEN
/ 2]);
2825 tag
->ti_Tag
= S2INFO_SSID
;
2826 tag
->ti_Data
= (UPINT
)(ssid
=
2827 AllocPooled(pool
, 31 + 1));
2830 CopyMem(ap_rec
+ P2_APREC_NAME
/ 2, ssid
, ssid_length
);
2831 ssid
[ssid_length
] = '\0';
2834 error
= S2ERR_NO_RESOURCES
;
2837 tag
->ti_Tag
= TAG_END
;
2841 /* Find IEs for each BSS and insert them into the BSS's tag list */
2843 for(beacon
= unit
->beacons
, i
= 0; i
< unit
->beacon_count
; i
++)
2845 /* Extract IEs from beacon descriptor */
2847 data_length
= BEWord(*(UWORD
*)(beacon
+ ETH_PACKET_IEEELEN
));
2848 ies_length
= data_length
- 12;
2849 frame_length
= ETH_HEADERSIZE
+ data_length
;
2850 ies
= AllocPooled(pool
, sizeof(UWORD
) + ies_length
);
2853 *(UWORD
*)ies
= ies_length
;
2854 CopyMem(beacon
+ ETH_PACKET_DATA
+ WIFI_BEACON_IES
,
2855 ies
+ sizeof(UWORD
), ies_length
);
2858 error
= S2ERR_NO_RESOURCES
;
2860 /* Find matching tag list and add IEs to it */
2862 ie_bssid
= beacon
+ ETH_PACKET_SOURCE
;
2863 for(j
= 0; j
< count
; j
++)
2866 bssid
= (UBYTE
*)tag
->ti_Data
;
2867 if(*(ULONG
*)bssid
== *(ULONG
*)ie_bssid
2868 && *(UWORD
*)(bssid
+ 4) == *(UWORD
*)(ie_bssid
+ 4))
2871 tag
->ti_Tag
= S2INFO_InfoElements
;
2872 tag
->ti_Data
= (PINT
)ies
;
2876 beacon
+= frame_length
+ sizeof(ULONG
) & ~3;
2879 /* Return results */
2883 request
->ios2_StatData
= tag_lists
;
2884 request
->ios2_DataLength
= count
;
2888 request
->ios2_Req
.io_Error
= error
;
2889 request
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
2891 Remove((APTR
)request
);
2892 ReplyMsg((APTR
)request
);
2895 /* Discard collected beacon frames */
2898 unit
->next_beacon
= unit
->beacons
;
2899 unit
->beacon_count
= 0;
2907 /****i* prism2.device/GetNetworkInfo ***************************************
2910 * GetNetworkInfo -- Get information on current network.
2913 * tag_list = GetNetworkInfo(unit, pool)
2915 * struct TagItem *GetNetworkInfo(struct DevUnit *, APTR);
2920 * unit - A unit of this device.
2921 * pool - A memory pool.
2926 ****************************************************************************
2930 struct TagItem
*GetNetworkInfo(struct DevUnit
*unit
, APTR pool
,
2931 struct DevBase
*base
)
2934 struct TagItem
*tag_list
, *tag
;
2938 AllocPooled(pool
, INFO_TAG_COUNT
* sizeof(struct TagItem
));
2939 if(tag_list
== NULL
)
2940 error
= S2ERR_NO_RESOURCES
;
2946 tag
->ti_Tag
= S2INFO_BSSID
;
2947 tag
->ti_Data
= (UPINT
)(bssid
=
2948 AllocPooled(pool
, ETH_ADDRESSSIZE
));
2950 CopyMem(unit
->bssid
, bssid
, ETH_ADDRESSSIZE
);
2952 error
= S2ERR_NO_RESOURCES
;
2955 tag
->ti_Tag
= TAG_IGNORE
;
2958 tag
->ti_Tag
= S2INFO_WPAInfo
;
2959 tag
->ti_Data
= (UPINT
)(ie
=
2960 AllocPooled(pool
, unit
->wpa_ie
[1] + 2));
2962 CopyMem(unit
->wpa_ie
, ie
, unit
->wpa_ie
[1] + 2);
2964 error
= S2ERR_NO_RESOURCES
;
2967 tag
->ti_Tag
= TAG_END
;
2978 /****i* prism2.device/UpdateSignalQuality **********************************
2981 * UpdateSignalQuality -- Read signal quality from card.
2984 * UpdateSignalQuality(unit)
2986 * VOID UpdateSignalQuality(struct DevUnit *);
2991 * unit - A unit of this device.
2996 ****************************************************************************
3000 VOID
UpdateSignalQuality(struct DevUnit
*unit
, struct DevBase
*base
)
3002 P2DoCmd(unit
, P2_CMD_ACCESS
, P2_REC_LINKQUALITY
, base
);
3003 P2Seek(unit
, 1, P2_REC_LINKQUALITY
, 6, base
);
3005 unit
->signal_quality
.SignalLevel
=
3006 ConvertLevel(unit
, unit
->LEWordIn(unit
->card
, P2_REG_DATA1
), base
);
3007 unit
->signal_quality
.NoiseLevel
=
3008 ConvertLevel(unit
, unit
->LEWordIn(unit
->card
, P2_REG_DATA1
), base
);
3015 /****i* prism2.device/StartScan ********************************************
3018 * StartScan -- Start a scan for available networks.
3023 * VOID StartScan(struct DevUnit *);
3028 * unit - A unit of this device.
3033 ****************************************************************************
3037 VOID
StartScan(struct DevUnit
*unit
, const TEXT
*ssid
, struct DevBase
*base
)
3040 UWORD ssid_length
= 0;
3042 /* Ask for a scan */
3044 if((unit
->flags
& UNITF_ONLINE
) != 0)
3047 ssid_length
= StrLen(ssid
);
3048 if(unit
->firmware_type
== INTERSIL_FIRMWARE
)
3050 params
= AllocVec(sizeof(scan_params
) + ssid_length
, MEMF_PUBLIC
);
3053 CopyMem(scan_params
, params
, sizeof(scan_params
));
3055 CopyMem(ssid
, params
+ sizeof(scan_params
), ssid_length
);
3056 params
[4] = ssid_length
;
3057 P2SetData(unit
, P2_REC_HOSTSCAN
, params
,
3058 sizeof(scan_params
) + ssid_length
, base
);
3062 else if(unit
->firmware_type
== SYMBOL_FIRMWARE
)
3063 P2SetWord(unit
, P2_REC_ALTHOSTSCAN
, 0x82, base
);
3064 else if(unit
->firmware_type
>= LUCENT_FIRMWARE
3065 && (unit
->flags
& UNITF_HARDTKIP
) != 0)
3067 /* Initialise fake scan results and ask for a series of raw beacon
3070 unit
->scan_results_rec
[0] = MakeLEWord(1);
3072 P2SetID(unit
, P2_REC_SCANSSID
, ssid
, ssid_length
, base
);
3073 P2SetWord(unit
, P2_REC_SCANCHANNELS
, 0x7fff, base
);
3074 unit
->LEWordOut(unit
->card
, P2_REG_PARAM1
, 0x3fff);
3075 P2DoCmd(unit
, P2_CMD_INQUIRE
, P2_INFO_SCANRESULT
, base
);
3079 P2SetID(unit
, P2_REC_SCANSSID
, ssid
, ssid_length
, base
);
3080 P2DoCmd(unit
, P2_CMD_INQUIRE
, P2_INFO_SCANRESULTS
, base
);
3089 /****i* prism2.device/LoadFirmware *****************************************
3095 * success = LoadFirmware(unit)
3097 * BOOL LoadFirmware(struct DevUnit *);
3102 * unit - A unit of this device.
3105 * success - Success indicator.
3107 ****************************************************************************
3111 static BOOL
LoadFirmware(struct DevUnit
*unit
, struct DevBase
*base
)
3113 BOOL success
= TRUE
;
3114 const TEXT
*file_name
;
3115 struct FileInfoBlock
*info
= NULL
;
3116 UWORD control_reg
, pdr_no
, *pda
= NULL
, *pdr
, *prod_data
, length
;
3117 ULONG location
, start_address
;
3118 BPTR file
= (BPTR
)NULL
;
3120 TEXT
*buffer
= NULL
;
3124 /* Read firmware file */
3126 switch(unit
->firmware_type
)
3128 case LUCENT_FIRMWARE
:
3129 file_name
= h1_firmware_file_name
;
3131 case HERMES2_FIRMWARE
:
3132 file_name
= h2_firmware_file_name
;
3134 case HERMES2G_FIRMWARE
:
3135 file_name
= h25_firmware_file_name
;
3141 if(file_name
== NULL
)
3146 file
= Open(file_name
, MODE_OLDFILE
);
3147 if(file
== (BPTR
)NULL
)
3153 info
= AllocDosObject(DOS_FIB
, NULL
);
3160 if(!ExamineFH(file
, info
))
3166 buffer
= AllocVec(info
->fib_Size
+ 1, MEMF_ANY
);
3167 data
= AllocVec(MAX_S_REC_SIZE
, MEMF_ANY
);
3168 pda
= AllocVec(LUCENT_PDA_SIZE
, MEMF_ANY
);
3169 if(buffer
== NULL
|| data
== NULL
|| pda
== NULL
)
3175 if(Read(file
, buffer
, info
->fib_Size
) == -1)
3177 buffer
[info
->fib_Size
] = '\0';
3182 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, 0xffff);
3183 P2DoCmd(unit
, P2_CMD_INIT
| 0x100, 0, base
);
3184 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, 0xffff);
3185 P2DoCmd(unit
, P2_CMD_INIT
| 0x0, 0, base
);
3186 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, 0xffff);
3188 /* Enable auxiliary ports */
3190 unit
->LEWordOut(unit
->card
, P2_REG_PARAM0
, 0xfe01);
3191 unit
->LEWordOut(unit
->card
, P2_REG_PARAM1
, 0xdc23);
3192 unit
->LEWordOut(unit
->card
, P2_REG_PARAM2
, 0xba45);
3194 control_reg
= unit
->LEWordIn(unit
->card
, P2_REG_CONTROL
);
3196 control_reg
& ~P2_REG_CONTROLF_AUX
| P2_REG_CONTROL_ENABLEAUX
;
3197 unit
->LEWordOut(unit
->card
, P2_REG_CONTROL
, control_reg
);
3199 BusyMilliDelay(5, base
);
3201 (unit
->LEWordIn(unit
->card
, P2_REG_CONTROL
) & P2_REG_CONTROLF_AUX
)
3202 != P2_REG_CONTROL_AUXENABLED
);
3204 /* Read Production Data Area from card */
3206 if(unit
->firmware_type
< HERMES2_FIRMWARE
)
3208 location
= LUCENT_PDA_ADDRESS
;
3209 unit
->LEWordOut(unit
->card
, P2_REG_AUXPAGE
, location
>> 7);
3210 unit
->LEWordOut(unit
->card
, P2_REG_AUXOFFSET
,
3211 location
& (1 << 7) - 1);
3213 unit
->WordsIn(unit
->card
, P2_REG_AUXDATA
,
3214 (UWORD
*)pda
, LUCENT_PDA_SIZE
>> 1);
3217 /* Allow writing to card's RAM */
3219 BusyMilliDelay(100, base
);
3220 start_address
= 0xf8000;
3221 unit
->LEWordOut(unit
->card
, P2_REG_PARAM1
, start_address
>> 16);
3222 P2DoCmd(unit
, P2_CMD_PROGRAM
| P2_CMDF_WRITE
, start_address
, base
);
3224 /* Parse firmware image data and write it to card */
3229 p
= ParseNextSRecord(p
, &type
, data
, &length
, &location
, base
);
3236 /* Check that this is not a "special" record */
3238 if(location
< 0xff000000)
3240 /* Write data to card */
3242 if(unit
->firmware_type
< LUCENT_FIRMWARE
)
3244 unit
->LEWordOut(unit
->card
, P2_REG_PARAM1
,
3246 P2DoCmd(unit
, P2_CMD_PROGRAM
| P2_CMDF_WRITE
, location
,
3250 unit
->LEWordOut(unit
->card
, P2_REG_AUXPAGE
,
3252 unit
->LEWordOut(unit
->card
, P2_REG_AUXOFFSET
,
3253 location
& (1 << 7) - 1);
3255 unit
->WordsOut(unit
->card
, P2_REG_AUXDATA
,
3256 (UWORD
*)data
, length
>> 1);
3262 /* Get location in card memory to begin execution of new
3265 start_address
= location
;
3270 /* Parse PDA plug records and patch firmware */
3275 p
= ParseNextSRecord(p
, &type
, data
, &length
, &location
, base
);
3277 if(p
!= NULL
&& type
== '3' && location
== 0xff000000)
3279 /* Get PDR number and the location where it should be patched
3282 pdr_no
= LELong(*(ULONG
*)data
);
3283 location
= LELong(*(ULONG
*)(data
+ 4));
3284 length
= LELong(*(ULONG
*)(data
+ 8));
3286 /* Find PDR to copy data from */
3289 for(pdr
= pda
; pdr
[1] != 0; pdr
+= LEWord(pdr
[0]) + 1)
3291 if(LEWord(pdr
[1]) == pdr_no
)
3292 prod_data
= pdr
+ 2;
3295 /* Write production data to card if it was found */
3297 if(prod_data
!= NULL
)
3299 if(unit
->firmware_type
< LUCENT_FIRMWARE
)
3301 unit
->LEWordOut(unit
->card
, P2_REG_PARAM1
,
3303 P2DoCmd(unit
, P2_CMD_PROGRAM
| P2_CMDF_WRITE
, location
,
3307 unit
->LEWordOut(unit
->card
, P2_REG_AUXPAGE
, location
>> 7);
3308 unit
->LEWordOut(unit
->card
, P2_REG_AUXOFFSET
,
3309 location
& (1 << 7) - 1);
3311 unit
->WordsOut(unit
->card
, P2_REG_AUXDATA
, prod_data
,
3317 /* Disable auxiliary ports */
3319 control_reg
= unit
->LEWordIn(unit
->card
, P2_REG_CONTROL
);
3321 control_reg
& ~P2_REG_CONTROLF_AUX
| P2_REG_CONTROL_DISABLEAUX
;
3322 unit
->LEWordOut(unit
->card
, P2_REG_CONTROL
, control_reg
);
3324 /* Execute downloaded firmware */
3326 if(unit
->firmware_type
>= HERMES2_FIRMWARE
)
3328 unit
->LEWordOut(unit
->card
, P2_REG_PARAM1
, start_address
>> 16);
3329 P2DoCmd(unit
, P2_CMD_EXECUTE
, start_address
, base
);
3331 else if(unit
->firmware_type
>= LUCENT_FIRMWARE
)
3333 P2DoCmd(unit
, P2_CMD_PROGRAM
, 0, base
);
3334 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, 0xffff);
3335 P2DoCmd(unit
, P2_CMD_INIT
, 0, base
);
3336 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, 0xffff);
3340 unit
->LEWordOut(unit
->card
, P2_REG_PARAM1
, start_address
>> 16);
3341 P2DoCmd(unit
, P2_CMD_PROGRAM
, start_address
, base
);
3342 P2DoCmd(unit
, P2_CMD_INIT
, 0, base
);
3346 /* Free Resources */
3351 FreeDosObject(DOS_FIB
, info
);
3352 if(file
!= (BPTR
)NULL
)
3360 /****i* prism2.device/ParseNextSRecord *************************************
3365 ****************************************************************************
3369 static const TEXT
*ParseNextSRecord(const TEXT
*s
, UBYTE
*type
, UBYTE
*data
,
3370 UWORD
*data_length
, ULONG
*location
, struct DevBase
*base
)
3377 /* Find start of next record, if any */
3382 if(ch
== 'S' || ch
== '\0')
3388 /* Get record type */
3392 /* Skip length field to keep alignment easy */
3396 /* Parse hexadecimal portion of record */
3398 for(i
= 0; (ch
= *s
++) >= '0'; i
++)
3407 if(i
>= 8 && (i
& 0x1) != 0)
3418 *data_length
= (i
>> 1) - 5;
3423 /* Return updated text pointer */
3430 /****i* prism2.device/P2DoCmd **********************************************
3435 ****************************************************************************
3437 * Commands can't fail without software/firmware bug?
3441 static VOID
P2DoCmd(struct DevUnit
*unit
, UWORD command
, UWORD param
,
3442 struct DevBase
*base
)
3444 if(unit
->firmware_type
< LUCENT_FIRMWARE
&& command
== P2_CMD_INIT
)
3445 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, 0xffff);
3447 unit
->LEWordOut(unit
->card
, P2_REG_PARAM0
, param
);
3448 unit
->LEWordOut(unit
->card
, P2_REG_COMMAND
, command
);
3449 while((unit
->LEWordIn(unit
->card
, P2_REG_EVENTS
)
3450 & P2_EVENTF_CMD
) == 0);
3451 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, P2_EVENTF_CMD
);
3453 if(unit
->firmware_type
< LUCENT_FIRMWARE
&& command
== P2_CMD_INIT
)
3454 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, 0xffff);
3459 /****i* prism2.device/P2Seek ***********************************************
3464 ****************************************************************************
3468 static BOOL
P2Seek(struct DevUnit
*unit
, UWORD path_no
, UWORD rec_no
,
3469 UWORD offset
, struct DevBase
*base
)
3474 offset_reg
= P2_REG_OFFSET0
+ path_no
;
3475 while((unit
->LEWordIn(unit
->card
, offset_reg
) & P2_REG_OFFSETF_BUSY
)
3477 unit
->LEWordOut(unit
->card
, P2_REG_SELECT0
+ path_no
, rec_no
);
3478 unit
->LEWordOut(unit
->card
, offset_reg
, offset
);
3479 while((unit
->LEWordIn(unit
->card
, offset_reg
) & P2_REG_OFFSETF_BUSY
)
3482 return (unit
->LEWordIn(unit
->card
, offset_reg
) & P2_REG_OFFSETF_ERROR
)
3488 /****i* prism2.device/P2SetID **********************************************
3494 * id may be NULL as long as length is zero.
3496 ****************************************************************************
3500 static VOID
P2SetID(struct DevUnit
*unit
, UWORD rec_no
, const UBYTE
*id
,
3501 UWORD length
, struct DevBase
*base
)
3503 P2Seek(unit
, 1, rec_no
, 0, base
);
3505 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, length
/ 2 + 3);
3506 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, rec_no
);
3507 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, length
);
3508 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (UWORD
*)id
, (length
+ 1) / 2);
3510 P2DoCmd(unit
, P2_CMD_ACCESS
| P2_CMDF_WRITE
, rec_no
, base
);
3517 /****i* prism2.device/P2SetWord ********************************************
3522 ****************************************************************************
3526 static VOID
P2SetWord(struct DevUnit
*unit
, UWORD rec_no
, UWORD value
,
3527 struct DevBase
*base
)
3529 P2Seek(unit
, 1, rec_no
, 0, base
);
3531 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, 2);
3532 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, rec_no
);
3533 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, value
);
3535 P2DoCmd(unit
, P2_CMD_ACCESS
| P2_CMDF_WRITE
, rec_no
, base
);
3542 /****i* prism2.device/P2GetWord ********************************************
3547 ****************************************************************************
3551 static UWORD
P2GetWord(struct DevUnit
*unit
, UWORD rec_no
,
3552 struct DevBase
*base
)
3554 P2DoCmd(unit
, P2_CMD_ACCESS
, rec_no
, base
);
3555 P2Seek(unit
, 1, rec_no
, 4, base
);
3557 return unit
->LEWordIn(unit
->card
, P2_REG_DATA1
);
3562 /****i* prism2.device/P2AllocMem *******************************************
3567 ****************************************************************************
3571 static UWORD
P2AllocMem(struct DevUnit
*unit
, UWORD size
,
3572 struct DevBase
*base
)
3575 P2DoCmd(unit
, P2_CMD_ALLOCMEM
, size
, base
);
3576 while((unit
->LEWordIn(unit
->card
, P2_REG_EVENTS
) & P2_EVENTF_ALLOCMEM
)
3578 id
= unit
->LEWordIn(unit
->card
, P2_REG_ALLOCFID
);
3579 unit
->LEWordOut(unit
->card
, P2_REG_ACKEVENTS
, P2_EVENTF_ALLOCMEM
);
3585 /****i* prism2.device/P2SetData ********************************************
3590 ****************************************************************************
3594 static VOID
P2SetData(struct DevUnit
*unit
, UWORD rec_no
, const UBYTE
*data
,
3595 UWORD length
, struct DevBase
*base
)
3597 length
= (length
+ 1) / 2;
3598 P2Seek(unit
, 1, rec_no
, 0, base
);
3600 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, 1 + length
);
3601 unit
->LEWordOut(unit
->card
, P2_REG_DATA1
, rec_no
);
3602 unit
->WordsOut(unit
->card
, P2_REG_DATA1
, (const UWORD
*)data
, length
);
3604 P2DoCmd(unit
, P2_CMD_ACCESS
| P2_CMDF_WRITE
, rec_no
, base
);
3611 /****i* prism2.device/P2ReadRec ********************************************
3614 * P2ReadRec -- Load and read an entire record.
3617 * success = P2ReadRec(unit, rec_no, buffer, max_length)
3619 * BOOL P2ReadRec(struct DevUnit *, UWORD, APTR, UWORD);
3624 * unit - A unit of this device.
3625 * rec_no - Record number to read.
3626 * buffer - Buffer to store data in.
3627 * max_length - Maximum number of bytes to store in buffer.
3630 * success - Success indicator.
3632 ****************************************************************************
3636 static BOOL
P2ReadRec(struct DevUnit
*unit
, UWORD rec_no
, APTR buffer
,
3637 UWORD max_length
, struct DevBase
*base
)
3639 BOOL success
= TRUE
;
3642 P2DoCmd(unit
, P2_CMD_ACCESS
, rec_no
, base
);
3643 P2Seek(unit
, 1, rec_no
, 0, base
);
3645 length
= (unit
->LEWordIn(unit
->card
, P2_REG_DATA1
) + 1) * 2;
3646 P2Seek(unit
, 1, rec_no
, 0, base
);
3647 if(length
<= max_length
)
3648 unit
->WordsIn(unit
->card
, P2_REG_DATA1
, (UWORD
*)buffer
,
3657 /****i* prism2.device/ConvertLevel *****************************************
3660 * ConvertLevel -- Convert a signal or noise level to dBm.
3663 * dbm_level = ConvertLevel(unit, raw_level)
3665 * LONG ConvertLevel(struct DevUnit *, UWORD);
3670 * unit - A unit of this device.
3671 * raw_level - The value returned from the hardware.
3674 * dbm_level - The value in dBm.
3676 ****************************************************************************
3680 static LONG
ConvertLevel(struct DevUnit
*unit
, UWORD raw_level
,
3681 struct DevBase
*base
)
3685 if(unit
->firmware_type
>= LUCENT_FIRMWARE
)
3686 dbm_level
= raw_level
- LUCENT_DBM_OFFSET
;
3688 dbm_level
= raw_level
/ 3 - INTERSIL_DBM_OFFSET
;
3695 /****i* prism2.device/ConvertScanLevel *************************************
3698 * ConvertScanLevel -- Convert a signal or noise level to dBm.
3701 * dbm_level = ConvertScanLevel(unit, raw_level)
3703 * LONG ConvertScanLevel(struct DevUnit *, UWORD);
3708 * unit - A unit of this device.
3709 * raw_level - The value returned from the hardware.
3712 * dbm_level - The value in dBm.
3714 ****************************************************************************
3718 static LONG
ConvertScanLevel(struct DevUnit
*unit
, UWORD raw_level
,
3719 struct DevBase
*base
)
3723 if(unit
->firmware_type
>= LUCENT_FIRMWARE
)
3724 dbm_level
= raw_level
- LUCENT_DBM_OFFSET
;
3726 dbm_level
= (WORD
)raw_level
;
3733 /****i* prism2.device/GetIE ************************************************
3739 * ie = GetIE(id, ies, ies_length)
3741 * UBYTE *GetIE(UBYTE, UBYTE *, UWORD);
3746 * id - ID of IE to find.
3747 * ies - A series of IEs.
3748 * ies_length - Length of IE block.
3751 * ie - Pointer to start of IE within block, or NULL if not found.
3753 ****************************************************************************
3757 static UBYTE
*GetIE(UBYTE id
, UBYTE
*ies
, UWORD ies_length
,
3758 struct DevBase
*base
)
3762 for(ie
= ies
; ie
< ies
+ ies_length
&& ie
[0] != id
; ie
+= ie
[1] + 2);
3763 if(ie
>= ies
+ ies_length
)
3771 /****i* prism2.device/CompareMACAddresses **********************************
3774 * CompareMACAddresses -- Compare two MAC addresses for equality.
3777 * same = CompareMACAddresses(mac1, mac2)
3779 * UBYTE *CompareMACAddresses(UBYTE *, UBYTE *);
3782 * mac1 - first MAC address.
3783 * mac2 - second MAC address.
3786 * same - TRUE if MAC addresses are equal.
3788 ****************************************************************************
3792 static BOOL
CompareMACAddresses(APTR mac1
, APTR mac2
)
3794 return *(ULONG
*)mac1
== *(ULONG
*)mac2
3795 && *((UWORD
*)mac1
+ 2) == *((UWORD
*)mac2
+ 2);
3800 /****i* prism2.device/UnitTask *********************************************
3808 * VOID UnitTask(struct DevUnit *);
3811 * Completes deferred requests, and handles card insertion and removal
3812 * in conjunction with the relevant interrupts.
3814 ****************************************************************************
3818 static VOID
UnitTask(struct DevUnit
*unit
)
3820 struct DevBase
*base
;
3821 struct IORequest
*request
;
3822 struct MsgPort
*general_port
;
3823 ULONG signals
= 0, wait_signals
, card_removed_signal
,
3824 card_inserted_signal
, scan_complete_signal
, general_port_signal
;
3826 base
= unit
->device
;
3828 /* Activate general request port */
3830 general_port
= unit
->request_ports
[GENERAL_QUEUE
];
3831 general_port
->mp_SigTask
= unit
->task
;
3832 general_port
->mp_SigBit
= AllocSignal(-1);
3833 general_port_signal
= 1 << general_port
->mp_SigBit
;
3834 general_port
->mp_Flags
= PA_SIGNAL
;
3836 /* Allocate signals for notification of card removal and insertion */
3838 card_removed_signal
= unit
->card_removed_signal
= 1 << AllocSignal(-1);
3839 card_inserted_signal
= unit
->card_inserted_signal
= 1 << AllocSignal(-1);
3840 scan_complete_signal
= unit
->scan_complete_signal
= 1 << AllocSignal(-1);
3841 wait_signals
= (1 << general_port
->mp_SigBit
) | card_removed_signal
3842 | card_inserted_signal
| scan_complete_signal
| SIGBREAKF_CTRL_C
;
3844 /* Tell ourselves to check port for old messages */
3846 Signal(unit
->task
, general_port_signal
);
3848 /* Infinite loop to service requests and signals */
3850 while((signals
& SIGBREAKF_CTRL_C
) == 0)
3852 signals
= Wait(wait_signals
);
3854 if((signals
& card_inserted_signal
) != 0)
3856 if(unit
->insertion_function(unit
->card
, base
))
3858 unit
->flags
|= UNITF_HAVEADAPTER
;
3859 if((unit
->flags
& UNITF_CONFIGURED
) != 0)
3860 ConfigureAdapter(unit
, base
);
3861 if((unit
->flags
& UNITF_WASONLINE
) != 0)
3863 GoOnline(unit
, base
);
3864 unit
->flags
&= ~UNITF_WASONLINE
;
3869 if((signals
& card_removed_signal
) != 0)
3871 unit
->removal_function(unit
->card
, base
);
3872 if((unit
->flags
& UNITF_WASONLINE
) != 0)
3873 GoOffline(unit
, base
);
3876 if((signals
& scan_complete_signal
) != 0)
3877 SendScanResults(unit
, base
);
3879 if((signals
& general_port_signal
) != 0)
3881 while((request
= (APTR
)GetMsg(general_port
)) != NULL
)
3883 /* Service the request as soon as the unit is free */
3885 ObtainSemaphore(&unit
->access_lock
);
3886 ServiceRequest((APTR
)request
, base
);
3894 /****i* prism2.device/StrLen ***********************************************
3900 * length = StrLen(s)
3902 * UPINT StrLen(TEXT *);
3904 ****************************************************************************
3908 static UPINT
StrLen(const TEXT
*s
)
3912 for(p
= s
; *p
!= '\0'; p
++);