3 Copyright (C) 2001-2012 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>
27 #include <proto/exec.h>
29 #include <proto/alib.h>
31 #include <clib/alib_protos.h>
33 #include <proto/utility.h>
34 #include <proto/dos.h>
35 #include <proto/timer.h>
39 #include "unit_protos.h"
40 #include "request_protos.h"
41 #include "encryption_protos.h"
43 #include "hal/ah_desc.h"
46 #define TASK_PRIORITY 0
47 #define STACK_SIZE 4096
49 (HAL_INT_GLOBAL | HAL_INT_TX | HAL_INT_TXDESC | HAL_INT_RX \
51 #define TX_POWER (20 << 1)
53 #define G_MGMT_RATE 2000
54 #define B_MGMT_RATE 1000
55 #define FRAME_BUFFER_SIZE (WIFI_FRM_DATA + SNAP_HEADERSIZE \
56 + 2 * ETH_MTU + EIV_SIZE + ICV_SIZE + MIC_SIZE + FCS_SIZE + 4)
57 #define MAX_CHANNEL_COUNT 100
60 #define AbsExecBase sys_base
63 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
64 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
65 UWORD upper_bound_right
, struct DevBase
*base
);
66 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
);
67 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
));
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
DistributeMgmtFrame(struct DevUnit
*unit
, UBYTE
*frame
,
79 UWORD frame_size
, struct DevBase
*base
);
80 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
));
81 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
));
82 static VOID
MgmtTXInt(REG(a1
, struct DevUnit
*unit
),
83 REG(a6
, APTR int_code
));
84 static VOID
MgmtTXEndInt(REG(a1
, struct DevUnit
*unit
),
85 REG(a6
, APTR int_code
));
86 static VOID
ResetHandler(REG(a1
, struct DevUnit
*unit
),
87 REG(a6
, APTR int_code
));
88 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
89 struct DevBase
*base
);
90 static VOID
UnitTask(struct ExecBase
*sys_base
);
93 static const UBYTE snap_template
[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
94 #if !defined(__AROS__)
95 static const UBYTE broadcast_address
[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
97 static const ULONG g_retry_rates
[] = {54000, 36000, 18000, 2000};
98 static const ULONG b_retry_rates
[] = {11000, 5500, 2000, 1000};
103 #define AddTask(task, initial_pc, final_pc) \
104 IExec->AddTask(task, initial_pc, final_pc, NULL)
107 static const struct EmulLibEntry mos_task_trap
=
113 #define UnitTask &mos_task_trap
117 #define AddTask(task, initial_pc, final_pc) \
119 struct TagItem _task_tags[] = \
120 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
121 NewAddTask(task, initial_pc, final_pc, _task_tags); \
127 /****i* atheros5000.device/CreateUnit **************************************
130 * CreateUnit -- Create a unit.
133 * unit = CreateUnit(index, io_base, id, card,
136 * struct DevUnit *CreateUnit(ULONG, APTR, UWORD, APTR,
137 * struct TagItem *, UWORD);
140 * Creates a new unit.
142 ****************************************************************************
146 struct DevUnit
*CreateUnit(ULONG index
, APTR io_base
, UWORD id
, APTR card
,
147 struct TagItem
*io_tags
, UWORD bus
, struct DevBase
*base
)
150 struct DevUnit
*unit
;
152 struct MsgPort
*port
;
154 struct ath_desc
*tx_desc
, *rx_desc
;
157 HAL_STATUS hal_status
;
159 unit
= AllocMem(sizeof(struct DevUnit
), MEMF_CLEAR
| MEMF_PUBLIC
);
165 /* Initialise lists etc. */
167 NewList((APTR
)&unit
->openers
);
168 NewList((APTR
)&unit
->type_trackers
);
169 NewList((APTR
)&unit
->multicast_ranges
);
176 /* Store DMA memory hooks */
179 (APTR
)GetTagData(IOTAG_AllocDMAMem
, (UPINT
)NULL
, io_tags
);
181 (APTR
)GetTagData(IOTAG_FreeDMAMem
, (UPINT
)NULL
, io_tags
);
182 if(unit
->AllocDMAMem
== NULL
|| unit
->FreeDMAMem
== NULL
)
190 unit
->hal
= ath_hal_attach(id
, unit
, NULL
, io_base
, &hal_status
);
192 if(unit
->hal
== NULL
)
198 InitSemaphore(&unit
->access_lock
);
200 /* Create the message ports for queuing requests */
202 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
204 unit
->request_ports
[i
] = port
= AllocMem(sizeof(struct MsgPort
),
205 MEMF_PUBLIC
| MEMF_CLEAR
);
211 NewList(&port
->mp_MsgList
);
212 port
->mp_Flags
= PA_IGNORE
;
218 unit
->request_ports
[WRITE_QUEUE
]->mp_SigTask
= &unit
->tx_int
;
219 unit
->request_ports
[MGMT_QUEUE
]->mp_SigTask
= &unit
->mgmt_int
;
222 /* Allocate buffers and descriptors */
224 unit
->tx_buffer
= AllocVec(ETH_MAXPACKETSIZE
, MEMF_PUBLIC
);
225 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
227 unit
->tx_buffers
[i
] =
228 unit
->AllocDMAMem(unit
->card
, FRAME_BUFFER_SIZE
, 4);
229 if(unit
->tx_buffers
[i
] == NULL
)
232 for(i
= 0; i
< MGMT_SLOT_COUNT
; i
++)
234 unit
->mgmt_buffers
[i
] =
235 unit
->AllocDMAMem(unit
->card
, FRAME_BUFFER_SIZE
, 4);
236 if(unit
->mgmt_buffers
[i
] == NULL
)
239 unit
->rx_buffer
= AllocVec(FRAME_BUFFER_SIZE
, MEMF_PUBLIC
);
240 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
242 unit
->rx_buffers
[i
] =
243 unit
->AllocDMAMem(unit
->card
, FRAME_BUFFER_SIZE
, 4);
244 if(unit
->rx_buffers
[i
] == NULL
)
248 AllocVec(FRAME_BUFFER_SIZE
* FRAME_BUFFER_COUNT
, MEMF_PUBLIC
);
249 for(i
= 0; i
< FRAME_BUFFER_COUNT
; i
++)
250 unit
->rx_fragment_nos
[i
] = -1;
251 unit
->tx_descs
= unit
->AllocDMAMem(unit
->card
,
252 sizeof(struct ath_desc
) * TX_SLOT_COUNT
, 4);
253 unit
->mgmt_descs
= unit
->AllocDMAMem(unit
->card
,
254 sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
, 4);
255 unit
->rx_descs
= unit
->AllocDMAMem(unit
->card
,
256 sizeof(struct ath_desc
) * RX_SLOT_COUNT
, 4);
257 unit
->tx_requests
= AllocVec(sizeof(APTR
) * TX_SLOT_COUNT
,
259 unit
->mgmt_requests
= AllocVec(sizeof(APTR
) * MGMT_SLOT_COUNT
,
261 unit
->channels
= AllocVec(sizeof(HAL_CHANNEL
) * MAX_CHANNEL_COUNT
,
262 MEMF_PUBLIC
| MEMF_CLEAR
);
263 if(unit
->tx_buffer
== NULL
264 || unit
->rx_buffer
== NULL
265 || unit
->rx_frames
== NULL
266 || unit
->tx_descs
== NULL
267 || unit
->mgmt_descs
== NULL
268 || unit
->rx_descs
== NULL
269 || unit
->tx_requests
== NULL
270 || unit
->mgmt_requests
== NULL
271 || unit
->channels
== NULL
)
277 /* Initialise network adapter hardware */
279 success
= InitialiseAdapter(unit
, FALSE
, base
);
280 unit
->flags
|= UNITF_HAVEADAPTER
;
285 /* Get physical addresses of DMA structures */
287 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
289 (ULONG
)(UPINT
)CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
290 if(dma_size
!= sizeof(struct ath_desc
) * TX_SLOT_COUNT
)
292 CachePostDMA(unit
->tx_descs
, &dma_size
, 0);
294 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
296 dma_size
= FRAME_BUFFER_SIZE
;
297 unit
->tx_buffers_p
[i
] =
298 (ULONG
)(UPINT
)CachePreDMA(unit
->tx_buffers
[i
], &dma_size
, 0);
299 if(dma_size
!= FRAME_BUFFER_SIZE
)
301 CachePostDMA(unit
->tx_buffers
[i
], &dma_size
, 0);
304 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
306 (ULONG
)(UPINT
)CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
307 if(dma_size
!= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
)
309 CachePostDMA(unit
->mgmt_descs
, &dma_size
, 0);
311 for(i
= 0; i
< MGMT_SLOT_COUNT
; i
++)
313 dma_size
= FRAME_BUFFER_SIZE
;
314 unit
->mgmt_buffers_p
[i
] =
315 (ULONG
)(UPINT
)CachePreDMA(unit
->mgmt_buffers
[i
], &dma_size
, 0);
316 if(dma_size
!= FRAME_BUFFER_SIZE
)
318 CachePostDMA(unit
->mgmt_buffers
[i
], &dma_size
, 0);
321 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
323 (ULONG
)(UPINT
)CachePreDMA(unit
->rx_descs
, &dma_size
, 0);
324 if(dma_size
!= sizeof(struct ath_desc
) * RX_SLOT_COUNT
)
326 CachePostDMA(unit
->rx_descs
, &dma_size
, 0);
328 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
330 dma_size
= FRAME_BUFFER_SIZE
;
331 unit
->rx_buffers_p
[i
] =
332 (ULONG
)(UPINT
)CachePreDMA(unit
->rx_buffers
[i
], &dma_size
, 0);
333 if(dma_size
!= FRAME_BUFFER_SIZE
)
335 CachePostDMA(unit
->rx_buffers
[i
], &dma_size
, 0);
338 /* Construct TX ring */
340 for(tx_desc
= unit
->tx_descs
, i
= 0; i
< TX_SLOT_COUNT
; i
++)
342 tx_desc
->ds_data
= unit
->tx_buffers_p
[i
];
346 /* Construct management frame TX ring */
348 for(tx_desc
= unit
->mgmt_descs
, i
= 0; i
< MGMT_SLOT_COUNT
; i
++)
350 tx_desc
->ds_data
= unit
->mgmt_buffers_p
[i
];
354 /* Construct RX ring */
356 for(rx_desc
= unit
->rx_descs
, i
= 0; i
< RX_SLOT_COUNT
; i
++)
358 rx_desc
->ds_link
= unit
->rx_descs_p
+ ((i
+ 1) % RX_SLOT_COUNT
)
359 * sizeof(struct ath_desc
);
360 rx_desc
->ds_data
= unit
->rx_buffers_p
[i
];
361 unit
->hal
->ah_setupRxDesc(unit
->hal
, rx_desc
, FRAME_BUFFER_SIZE
,
366 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
367 CachePreDMA(unit
->rx_descs
, &dma_size
, 0);
369 /* Record maximum speed in BPS */
371 unit
->speed
= 54000000;
373 /* Initialise status, transmit, receive and stats interrupts */
375 unit
->status_int
.is_Node
.ln_Name
=
376 base
->device
.dd_Library
.lib_Node
.ln_Name
;
377 unit
->status_int
.is_Code
= (APTR
)StatusInt
;
378 unit
->status_int
.is_Data
= unit
;
380 unit
->rx_int
.is_Node
.ln_Name
=
381 base
->device
.dd_Library
.lib_Node
.ln_Name
;
382 unit
->rx_int
.is_Code
= (APTR
)RXInt
;
383 unit
->rx_int
.is_Data
= unit
;
385 unit
->tx_int
.is_Node
.ln_Name
=
386 base
->device
.dd_Library
.lib_Node
.ln_Name
;
387 unit
->tx_int
.is_Code
= (APTR
)TXInt
;
388 unit
->tx_int
.is_Data
= unit
;
390 unit
->tx_end_int
.is_Node
.ln_Name
=
391 base
->device
.dd_Library
.lib_Node
.ln_Name
;
392 unit
->tx_end_int
.is_Code
= (APTR
)TXEndInt
;
393 unit
->tx_end_int
.is_Data
= unit
;
395 unit
->mgmt_int
.is_Node
.ln_Name
=
396 base
->device
.dd_Library
.lib_Node
.ln_Name
;
397 unit
->mgmt_int
.is_Code
= (APTR
)MgmtTXInt
;
398 unit
->mgmt_int
.is_Data
= unit
;
400 unit
->mgmt_end_int
.is_Node
.ln_Name
=
401 base
->device
.dd_Library
.lib_Node
.ln_Name
;
402 unit
->mgmt_end_int
.is_Code
= (APTR
)MgmtTXEndInt
;
403 unit
->mgmt_end_int
.is_Data
= unit
;
405 unit
->reset_handler
.is_Node
.ln_Name
=
406 base
->device
.dd_Library
.lib_Node
.ln_Name
;
407 unit
->reset_handler
.is_Code
= (APTR
)ResetHandler
;
408 unit
->reset_handler
.is_Data
= unit
;
410 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
411 unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
= PA_SOFTINT
;
413 /* Create a new task */
416 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
423 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
430 /* Initialise and start task */
432 task
->tc_Node
.ln_Type
= NT_TASK
;
433 task
->tc_Node
.ln_Pri
= TASK_PRIORITY
;
434 task
->tc_Node
.ln_Name
= base
->device
.dd_Library
.lib_Node
.ln_Name
;
435 task
->tc_SPUpper
= stack
+ STACK_SIZE
;
436 task
->tc_SPLower
= stack
;
437 task
->tc_SPReg
= stack
+ STACK_SIZE
;
438 NewList(&task
->tc_MemEntry
);
440 if(AddTask(task
, UnitTask
, NULL
) == NULL
)
446 /* Send the unit to the new task */
448 task
->tc_UserData
= unit
;
450 /* Set default wireless options */
452 unit
->mode
= S2PORT_MANAGED
;
457 DeleteUnit(unit
, base
);
466 /****i* atheros5000.device/DeleteUnit **************************************
469 * DeleteUnit -- Delete a unit.
474 * VOID DeleteUnit(struct DevUnit *);
480 * unit - Device unit (may be NULL).
485 ****************************************************************************
489 VOID
DeleteUnit(struct DevUnit
*unit
, struct DevBase
*base
)
499 if(task
->tc_UserData
!= NULL
)
502 FreeMem(task
->tc_SPLower
, STACK_SIZE
);
503 Signal(unit
->task
, SIGBREAKF_CTRL_C
);
505 FreeMem(task
, sizeof(struct Task
));
508 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
510 if(unit
->request_ports
[i
] != NULL
)
511 FreeMem(unit
->request_ports
[i
], sizeof(struct MsgPort
));
514 if((unit
->flags
& UNITF_ONLINE
) != 0) /* Needed! */
515 GoOffline(unit
, base
);
517 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
518 unit
->FreeDMAMem(unit
->card
, unit
->tx_buffers
[i
]);
519 for(i
= 0; i
< MGMT_SLOT_COUNT
; i
++)
520 unit
->FreeDMAMem(unit
->card
, unit
->mgmt_buffers
[i
]);
521 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
522 unit
->FreeDMAMem(unit
->card
, unit
->rx_buffers
[i
]);
524 FreeVec(unit
->tx_buffer
);
525 FreeVec(unit
->rx_frames
);
526 FreeVec(unit
->tx_requests
);
527 FreeVec(unit
->mgmt_requests
);
528 FreeVec(unit
->channels
);
529 FreeVec(unit
->rx_buffer
);
531 if(unit
->hal
!= NULL
)
532 unit
->hal
->ah_detach(unit
->hal
);
534 FreeMem(unit
, sizeof(struct DevUnit
));
542 /****i* atheros5000.device/InitialiseAdapter *******************************
548 * success = InitialiseAdapter(unit, reinsertion)
550 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
559 * success - Success indicator.
561 ****************************************************************************
565 BOOL
InitialiseAdapter(struct DevUnit
*unit
, BOOL reinsertion
,
566 struct DevBase
*base
)
568 UBYTE i
, reg_class_id
;
570 unsigned int channel_count
, reg_class_count
;
571 HAL_TXQ_INFO queue_info
= {0};
573 /* Get default MAC address */
575 unit
->hal
->ah_getMacAddress(unit
->hal
, unit
->default_address
);
577 /* Get default antenna */
579 unit
->antenna
= unit
->hal
->ah_getDefAntenna(unit
->hal
);
581 /* Reset key cache */
583 for(i
= 0; i
< WIFI_KEYCOUNT
; i
++)
584 unit
->hal
->ah_resetKeyCacheEntry(unit
->hal
, i
);
586 /* Initialise channels and rates */
588 ath_hal_init_channels(unit
->hal
, unit
->channels
,
589 MAX_CHANNEL_COUNT
, &channel_count
,
590 ®_class_id
, 1, ®_class_count
, CTRY_DEFAULT
,
591 HAL_MODE_11B
| HAL_MODE_PUREG
, TRUE
,
593 unit
->channel_count
= channel_count
;
596 unit
->band
= S2BAND_B
;
598 /* Check if multi-rate retries are supported */
600 if(unit
->hal
->ah_setupXTxDesc(unit
->hal
, NULL
, 0, 0, 0, 0, 0, 0))
601 unit
->flags
|= UNITF_SLOWRETRIES
;
603 /* Set up TX queue */
605 queue_info
.tqi_aifs
= HAL_TXQ_USEDEFAULT
;
606 queue_info
.tqi_cwmin
= HAL_TXQ_USEDEFAULT
;
607 queue_info
.tqi_cwmax
= HAL_TXQ_USEDEFAULT
;
608 queue_info
.tqi_qflags
=
609 HAL_TXQ_TXEOLINT_ENABLE
| HAL_TXQ_TXDESCINT_ENABLE
;
612 unit
->hal
->ah_setupTxQueue(unit
->hal
, HAL_TX_QUEUE_DATA
, &queue_info
);
613 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->tx_queue_no
);
615 /* Set up management frame TX queue */
617 queue_info
.tqi_aifs
= HAL_TXQ_USEDEFAULT
;
618 queue_info
.tqi_cwmin
= HAL_TXQ_USEDEFAULT
;
619 queue_info
.tqi_cwmax
= HAL_TXQ_USEDEFAULT
;
620 queue_info
.tqi_qflags
=
621 HAL_TXQ_TXEOLINT_ENABLE
| HAL_TXQ_TXDESCINT_ENABLE
;
623 unit
->mgmt_queue_no
=
624 unit
->hal
->ah_setupTxQueue(unit
->hal
, HAL_TX_QUEUE_DATA
, &queue_info
);
625 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->mgmt_queue_no
);
627 /* Find out hardware encryption capabilities */
629 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
630 HAL_CIPHER_WEP
, NULL
) == HAL_OK
)
631 unit
->flags
|= UNITF_HARDWEP
;
632 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
633 HAL_CIPHER_TKIP
, NULL
) == HAL_OK
)
634 unit
->flags
|= UNITF_HARDTKIP
;
636 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
637 HAL_CIPHER_MIC
, NULL
) == HAL_OK
)
639 if(unit
->hal
->ah_setCapability(unit
->hal
, HAL_CAP_TKIP_MIC
,
642 unit
->flags
|= UNITF_HARDMIC
;
645 if(unit
->hal
->ah_setCapability(unit
->hal
, HAL_CAP_TKIP_MIC
,
648 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_TKIP_SPLIT
, 0,
650 unit
->flags
|= UNITF_SPLITMIC
;
651 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
652 HAL_CIPHER_AES_OCB
, NULL
) == HAL_OK
)
653 unit
->flags
|= UNITF_HARDAESOCB
;
654 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
655 HAL_CIPHER_AES_CCM
, NULL
) == HAL_OK
)
656 unit
->flags
|= UNITF_HARDCCMP
;
660 unit
->iv_sizes
[S2ENC_WEP
] = IV_SIZE
;
661 unit
->iv_sizes
[S2ENC_TKIP
] = EIV_SIZE
;
662 unit
->iv_sizes
[S2ENC_CCMP
] = EIV_SIZE
;
664 /* Set encryption functions */
666 unit
->fragment_encrypt_functions
[S2ENC_NONE
] = WriteClearFragment
;
668 if((unit
->flags
& UNITF_HARDWEP
) != 0)
669 unit
->fragment_encrypt_functions
[S2ENC_WEP
] = WriteWEPFragment
;
671 unit
->fragment_encrypt_functions
[S2ENC_WEP
] = EncryptWEPFragment
;
673 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
674 unit
->fragment_encrypt_functions
[S2ENC_TKIP
] = WriteTKIPFragment
;
676 unit
->fragment_encrypt_functions
[S2ENC_TKIP
] = EncryptTKIPFragment
;
678 if((unit
->flags
& UNITF_HARDCCMP
) != 0)
679 unit
->fragment_encrypt_functions
[S2ENC_CCMP
] = WriteCCMPFragment
;
681 unit
->fragment_encrypt_functions
[S2ENC_CCMP
] = EncryptCCMPFragment
;
683 /* Set decryption functions */
685 unit
->fragment_decrypt_functions
[S2ENC_NONE
] = ReadClearFragment
;
687 if((unit
->flags
& UNITF_HARDWEP
) != 0)
688 unit
->fragment_decrypt_functions
[S2ENC_WEP
] = ReadWEPFragment
;
690 unit
->fragment_decrypt_functions
[S2ENC_WEP
] = DecryptWEPFragment
;
692 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
693 unit
->fragment_decrypt_functions
[S2ENC_TKIP
] = ReadTKIPFragment
;
695 unit
->fragment_decrypt_functions
[S2ENC_TKIP
] = DecryptTKIPFragment
;
697 if((unit
->flags
& UNITF_HARDCCMP
) != 0)
698 unit
->fragment_decrypt_functions
[S2ENC_CCMP
] = ReadCCMPFragment
;
700 unit
->fragment_decrypt_functions
[S2ENC_CCMP
] = DecryptCCMPFragment
;
709 /****i* atheros5000.device/ConfigureAdapter ********************************
712 * ConfigureAdapter -- Set up card for transmission/reception.
715 * ConfigureAdapter(unit)
717 * VOID ConfigureAdapter(struct DevUnit *);
719 ****************************************************************************
723 VOID
ConfigureAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
725 UWORD i
, j
, key_length
, hal_band
, key_type
;
726 const struct KeyUnion
*keys
;
727 HAL_CHANNEL
*channel
= unit
->channels
, *ch
;
728 ULONG freq
= 2407 + unit
->channel
* 5;
732 const HAL_RATE_TABLE
*rate_table
;
734 /* Get band-specific parameters */
736 if(unit
->band
== S2BAND_G
)
738 hal_band
= HAL_MODE_11G
;
739 unit
->band_mask
= CHANNEL_G
;
740 unit
->tx_rates
= g_retry_rates
;
741 unit
->mgmt_rate
= G_MGMT_RATE
;
743 else if(unit
->band
== S2BAND_B
)
745 hal_band
= HAL_MODE_11B
;
746 unit
->band_mask
= CHANNEL_B
;
747 unit
->tx_rates
= b_retry_rates
;
748 unit
->mgmt_rate
= B_MGMT_RATE
;
750 unit
->rate_table
= unit
->hal
->ah_getRateTable(unit
->hal
, hal_band
);
752 /* Find rate codes to match our optimal and retry rates */
754 rate_table
= unit
->rate_table
;
755 for(i
= 0; i
< rate_table
->rateCount
; i
++)
757 for(j
= 0; j
< 4; j
++)
759 if(rate_table
->info
[i
].rateKbps
== unit
->tx_rates
[j
])
761 unit
->tx_rate_codes
[j
] = rate_table
->info
[i
].rateCode
;
762 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
763 unit
->tx_rate_codes
[j
] |= rate_table
->info
[i
].shortPreamble
;
766 if(rate_table
->info
[i
].rateKbps
== unit
->mgmt_rate
)
768 unit
->mgmt_rate_code
= rate_table
->info
[i
].rateCode
;
769 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
770 unit
->mgmt_rate_code
|= rate_table
->info
[i
].shortPreamble
;
774 /* Find a channel that matches requirements */
776 for(i
= 0, ch
= unit
->channels
; i
< unit
->channel_count
; i
++, ch
++)
778 if(ch
->channel
== freq
779 && (ch
->channelFlags
& unit
->band_mask
) == unit
->band_mask
)
783 /* Stop the transceiver if we're already online */
785 if((unit
->flags
& UNITF_ONLINE
) != 0)
787 /* Disable frame transmission */
789 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
790 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
791 unit
->hal
->ah_setRxFilter(unit
->hal
, 0);
794 /* Disable frame reception */
796 unit
->hal
->ah_stopPcuReceive(unit
->hal
);
797 unit
->hal
->ah_stopDmaReceive(unit
->hal
);
799 /* Disable interrupts */
801 unit
->hal
->ah_setInterrupts(unit
->hal
, 0);
804 /* Calculate RX filter mask */
806 unit
->filter_mask
= HAL_RX_FILTER_UCAST
| HAL_RX_FILTER_MCAST
807 | HAL_RX_FILTER_BCAST
;
808 if((unit
->flags
& UNITF_PROM
) != 0)
809 unit
->filter_mask
|= HAL_RX_FILTER_PROM
;
810 if(unit
->mode
!= S2PORT_MANAGED
)
811 unit
->filter_mask
|= HAL_RX_FILTER_PROBEREQ
;
815 unit
->hal
->ah_reset(unit
->hal
, HAL_M_STA
, channel
, FALSE
, &status
);
817 /* Set MAC address and miscellaneous wireless parameters */
819 unit
->hal
->ah_setMacAddress(unit
->hal
, unit
->address
);
820 unit
->hal
->ah_setPCUConfig(unit
->hal
);
821 SetMulticast(unit
, base
);
822 unit
->hal
->ah_setDefAntenna(unit
->hal
, unit
->antenna
);
823 unit
->hal
->ah_perCalibration(unit
->hal
, channel
, &iq_done
);
824 unit
->hal
->ah_setTxPowerLimit(unit
->hal
, TX_POWER
);
826 /* Set association ID */
828 unit
->hal
->ah_writeAssocid(unit
->hal
, unit
->bssid
, unit
->assoc_id
);
830 /* Put on a reassuring light */
832 unit
->hal
->ah_setLedState(unit
->hal
, HAL_LED_RUN
);
834 /* Set or clear default encryption keys where appropriate */
837 for(i
= 0; i
< WIFI_KEYCOUNT
; i
++)
839 key_type
= unit
->keys
[i
].type
;
840 if(key_type
<= S2ENC_WEP
841 || key_type
== S2ENC_TKIP
&& (unit
->flags
& UNITF_HARDTKIP
) == 0
842 || key_type
== S2ENC_CCMP
&& (unit
->flags
& UNITF_HARDCCMP
) == 0)
844 if(key_type
== S2ENC_WEP
&& (unit
->flags
& UNITF_HARDWEP
) != 0)
846 hal_key
.kv_type
= HAL_CIPHER_WEP
;
847 key_length
= keys
[i
].u
.wep
.length
;
848 CopyMem(keys
[i
].u
.wep
.key
, hal_key
.kv_val
, key_length
);
852 hal_key
.kv_type
= HAL_CIPHER_CLR
;
855 hal_key
.kv_len
= key_length
;
856 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, i
, &hal_key
,
861 /* Set pointer to RX ring */
863 unit
->hal
->ah_setRxDP(unit
->hal
,
864 unit
->rx_descs_p
+ unit
->rx_slot
* sizeof(struct ath_desc
));
866 /* Restart the transceiver if we're already online */
868 if((unit
->flags
& UNITF_ONLINE
) != 0)
870 /* Enable interrupts */
872 unit
->hal
->ah_setInterrupts(unit
->hal
, INT_MASK
);
874 /* Enable frame reception */
876 unit
->hal
->ah_enableReceive(unit
->hal
);
877 unit
->hal
->ah_setRxFilter(unit
->hal
, unit
->filter_mask
);
878 unit
->hal
->ah_startPcuReceive(unit
->hal
);
881 /* Reset TX queues */
883 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->tx_queue_no
);
884 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->mgmt_queue_no
);
895 /****i* atheros5000.device/GoOnline ****************************************
898 * GoOnline -- Enable transmission/reception.
903 * VOID GoOnline(struct DevUnit *);
905 ****************************************************************************
909 VOID
GoOnline(struct DevUnit
*unit
, struct DevBase
*base
)
911 /* Enable interrupts */
913 unit
->flags
|= UNITF_ONLINE
;
914 unit
->hal
->ah_setInterrupts(unit
->hal
, INT_MASK
);
916 /* Enable frame reception */
918 unit
->hal
->ah_enableReceive(unit
->hal
);
919 unit
->hal
->ah_setRxFilter(unit
->hal
, unit
->filter_mask
);
920 unit
->hal
->ah_startPcuReceive(unit
->hal
);
923 /* Reset TX queues */
925 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->tx_queue_no
);
926 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->mgmt_queue_no
);
929 /* Record start time and report Online event */
931 GetSysTime(&unit
->stats
.LastStart
);
932 ReportEvents(unit
, S2EVENT_ONLINE
, base
);
939 /****i* atheros5000.device/GoOffline ***************************************
942 * GoOffline -- Disable transmission/reception.
947 * VOID GoOffline(struct DevUnit *);
957 ****************************************************************************
961 VOID
GoOffline(struct DevUnit
*unit
, struct DevBase
*base
)
963 unit
->flags
&= ~UNITF_ONLINE
;
964 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
966 /* Disable frame transmission */
968 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
969 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
971 /* Disable frame reception */
973 unit
->hal
->ah_stopPcuReceive(unit
->hal
);
974 unit
->hal
->ah_stopDmaReceive(unit
->hal
);
975 unit
->hal
->ah_setRxFilter(unit
->hal
, 0);
978 /* Stop interrupts */
980 unit
->hal
->ah_setInterrupts(unit
->hal
, 0);
982 /* Update statistics */
984 UpdateStats(unit
, base
);
987 /* Flush pending read and write requests */
989 FlushUnit(unit
, MGMT_QUEUE
, S2ERR_OUTOFSERVICE
, base
);
991 /* Report Offline event and return */
993 ReportEvents(unit
, S2EVENT_OFFLINE
, base
);
999 /****i* atheros5000.device/SetOptions **************************************
1002 * SetOptions -- Set and use interface options.
1005 * reconfigure = SetOptions(unit, tag_list)
1007 * BOOL SetOptions(struct DevUnit *, struct TagItem *);
1009 ****************************************************************************
1013 BOOL
SetOptions(struct DevUnit
*unit
, const struct TagItem
*tag_list
,
1014 struct DevBase
*base
)
1016 struct TagItem
*tag_item
, *tlist
= (struct TagItem
*)tag_list
;
1017 BOOL reconfigure
= TRUE
;
1019 while((tag_item
= NextTagItem(&tlist
)) != NULL
)
1021 switch(tag_item
->ti_Tag
)
1024 ReportEvents(unit
, S2EVENT_CONNECT
, base
);
1028 CopyMem((APTR
)tag_item
->ti_Data
, unit
->bssid
, ETH_ADDRESSSIZE
);
1031 case S2INFO_AssocID
:
1032 unit
->assoc_id
= tag_item
->ti_Data
;
1035 case S2INFO_Capabilities
:
1036 unit
->capabilities
= tag_item
->ti_Data
;
1037 if((unit
->capabilities
& (1 << 5)) != 0)
1038 unit
->flags
|= UNITF_SHORTPREAMBLE
;
1040 unit
->flags
&= ~UNITF_SHORTPREAMBLE
;
1043 case S2INFO_DefaultKeyNo
:
1044 unit
->tx_key_no
= tag_item
->ti_Data
;
1047 case S2INFO_PortType
:
1048 unit
->mode
= tag_item
->ti_Data
;
1051 case S2INFO_Channel
:
1052 if(tag_item
->ti_Data
!= unit
->channel
)
1054 unit
->channel
= tag_item
->ti_Data
;
1060 if(tag_item
->ti_Data
!= unit
->band
)
1062 unit
->band
= tag_item
->ti_Data
;
1074 /****i* atheros5000.device/SetKey ******************************************
1077 * SetKey -- Set an encryption key.
1080 * SetKey(unit, index, type, key, key_length,
1083 * VOID SetKey(struct DevUnit *, ULONG, ULONG, UBYTE *, ULONG,
1086 ****************************************************************************
1090 VOID
SetKey(struct DevUnit
*unit
, ULONG index
, ULONG type
, const UBYTE
*key
,
1091 ULONG key_length
, const UBYTE
*rx_counter
, struct DevBase
*base
)
1093 struct KeyUnion
*slot
;
1094 struct EClockVal eclock
;
1099 slot
= &unit
->keys
[index
];
1103 CopyMem(key
, slot
->u
.wep
.key
, key_length
);
1104 slot
->u
.wep
.length
= key_length
;
1106 if((unit
->flags
& UNITF_HARDWEP
) == 0)
1108 /* Create a reasonably random IV */
1110 ReadEClock(&eclock
);
1111 slot
->u
.wep
.tx_iv
= FastRand(eclock
.ev_lo
^ eclock
.ev_hi
);
1117 CopyMem(key
, slot
->u
.tkip
.key
, 16);
1118 CopyMem(key
+ 16, slot
->u
.tkip
.tx_mic_key
, MIC_SIZE
);
1119 CopyMem(key
+ 24, slot
->u
.tkip
.rx_mic_key
, MIC_SIZE
);
1120 slot
->u
.tkip
.tx_iv_low
= 0;
1121 slot
->u
.tkip
.tx_iv_high
= 0;
1122 slot
->u
.tkip
.rx_iv_low
= LEWord(*(UWORD
*)rx_counter
);
1123 slot
->u
.tkip
.rx_iv_high
= LELong(*(ULONG
*)(rx_counter
+ 2));
1124 slot
->u
.tkip
.tx_ttak_set
= FALSE
;
1125 slot
->u
.tkip
.rx_ttak_set
= FALSE
;
1127 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
1129 // TO DO: Wait for TX queue to empty
1130 /* Load parameters for hardware encryption */
1132 hal_key
.kv_type
= HAL_CIPHER_TKIP
;
1133 hal_key
.kv_len
= 16;
1134 CopyMem(slot
->u
.tkip
.key
, hal_key
.kv_val
, 16);
1136 CopyMem(slot
->u
.tkip
.tx_mic_key
, hal_key
.kv_mic
, MIC_SIZE
);
1137 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
, &hal_key
,
1138 unit
->bssid
, FALSE
);
1139 CopyMem(slot
->u
.tkip
.rx_mic_key
, hal_key
.kv_mic
, MIC_SIZE
);
1140 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
+ 32, &hal_key
,
1141 unit
->bssid
, FALSE
);
1145 /* Convert key to native endianness */
1147 for(i
= 0; i
< 8; i
++)
1148 slot
->u
.tkip
.key
[i
] = LEWord(slot
->u
.tkip
.key
[i
]);
1154 CopyMem(key
, slot
->u
.ccmp
.key
, 16);
1155 slot
->u
.ccmp
.tx_iv_low
= 0;
1156 slot
->u
.ccmp
.tx_iv_high
= 0;
1157 slot
->u
.ccmp
.rx_iv_low
= LEWord(*(UWORD
*)rx_counter
);
1158 slot
->u
.ccmp
.rx_iv_high
= LELong(*(ULONG
*)(rx_counter
+ 2));
1159 slot
->u
.ccmp
.stream_set
= FALSE
;
1161 if((unit
->flags
& UNITF_HARDCCMP
) != 0)
1163 // TO DO: Wait for TX queue to empty
1164 /* Load parameters for hardware encryption */
1166 hal_key
.kv_type
= HAL_CIPHER_AES_CCM
;
1167 hal_key
.kv_len
= 16;
1168 CopyMem(slot
->u
.ccmp
.key
, hal_key
.kv_val
, 16);
1169 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
, &hal_key
,
1170 unit
->bssid
, FALSE
);
1174 /* Update type of key in selected slot */
1184 /****i* atheros5000.device/AddMulticastRange *******************************
1190 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1192 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1194 ****************************************************************************
1198 BOOL
AddMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
1199 const UBYTE
*upper_bound
, struct DevBase
*base
)
1201 struct AddressRange
*range
;
1202 ULONG lower_bound_left
, upper_bound_left
;
1203 UWORD lower_bound_right
, upper_bound_right
;
1205 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
1206 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
1207 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
1208 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
1210 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
1211 upper_bound_left
, upper_bound_right
, base
);
1217 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1220 range
->lower_bound_left
= lower_bound_left
;
1221 range
->lower_bound_right
= lower_bound_right
;
1222 range
->upper_bound_left
= upper_bound_left
;
1223 range
->upper_bound_right
= upper_bound_right
;
1224 range
->add_count
= 1;
1227 AddTail((APTR
)&unit
->multicast_ranges
, (APTR
)range
);
1228 unit
->range_count
++;
1229 SetMulticast(unit
, base
);
1234 return range
!= NULL
;
1239 /****i* atheros5000.device/RemMulticastRange *******************************
1245 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1247 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1249 ****************************************************************************
1253 BOOL
RemMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
1254 const UBYTE
*upper_bound
, struct DevBase
*base
)
1256 struct AddressRange
*range
;
1257 ULONG lower_bound_left
, upper_bound_left
;
1258 UWORD lower_bound_right
, upper_bound_right
;
1260 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
1261 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
1262 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
1263 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
1265 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
1266 upper_bound_left
, upper_bound_right
, base
);
1270 if(--range
->add_count
== 0)
1273 Remove((APTR
)range
);
1274 unit
->range_count
--;
1275 SetMulticast(unit
, base
);
1277 FreeMem(range
, sizeof(struct AddressRange
));
1281 return range
!= NULL
;
1286 /****i* atheros5000.device/FindMulticastRange ******************************
1289 * FindMulticastRange
1292 * range = FindMulticastRange(unit, lower_bound_left,
1293 * lower_bound_right, upper_bound_left, upper_bound_right)
1295 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1296 * UWORD, ULONG, UWORD);
1298 ****************************************************************************
1302 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
1303 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
1304 UWORD upper_bound_right
, struct DevBase
*base
)
1306 struct AddressRange
*range
, *tail
;
1309 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1310 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1312 while(range
!= tail
&& !found
)
1314 if(lower_bound_left
== range
->lower_bound_left
&&
1315 lower_bound_right
== range
->lower_bound_right
&&
1316 upper_bound_left
== range
->upper_bound_left
&&
1317 upper_bound_right
== range
->upper_bound_right
)
1320 range
= (APTR
)range
->node
.mln_Succ
;
1331 /****i* atheros5000.device/SetMulticast ************************************
1337 * SetMulticast(unit)
1339 * VOID SetMulticast(struct DevUnit *);
1341 ****************************************************************************
1345 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
)
1347 unit
->hal
->ah_setMulticastFilter(unit
->hal
, 0xffffffff, 0xffffffff);
1354 /****i* atheros5000.device/FindTypeStats ***********************************
1360 * stats = FindTypeStats(unit, list,
1363 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1366 ****************************************************************************
1370 struct TypeStats
*FindTypeStats(struct DevUnit
*unit
, struct MinList
*list
,
1371 ULONG packet_type
, struct DevBase
*base
)
1373 struct TypeStats
*stats
, *tail
;
1376 stats
= (APTR
)list
->mlh_Head
;
1377 tail
= (APTR
)&list
->mlh_Tail
;
1379 while(stats
!= tail
&& !found
)
1381 if(stats
->packet_type
== packet_type
)
1384 stats
= (APTR
)stats
->node
.mln_Succ
;
1395 /****i* atheros5000.device/FlushUnit ***************************************
1401 * FlushUnit(unit, last_queue, error)
1403 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1405 ****************************************************************************
1409 VOID
FlushUnit(struct DevUnit
*unit
, UBYTE last_queue
, BYTE error
,
1410 struct DevBase
*base
)
1412 struct IORequest
*request
;
1414 struct Opener
*opener
, *tail
;
1416 /* Abort queued requests */
1418 for(i
= 0; i
<= last_queue
; i
++)
1420 while((request
= (APTR
)GetMsg(unit
->request_ports
[i
])) != NULL
)
1422 request
->io_Error
= IOERR_ABORTED
;
1423 ReplyMsg((APTR
)request
);
1428 opener
= (APTR
)unit
->openers
.mlh_Head
;
1429 tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1431 /* Flush every opener's read queues */
1433 while(opener
!= tail
)
1435 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1437 request
->io_Error
= error
;
1438 ReplyMsg((APTR
)request
);
1440 while((request
= (APTR
)GetMsg(&opener
->mgmt_port
)) != NULL
)
1442 request
->io_Error
= error
;
1443 ReplyMsg((APTR
)request
);
1445 opener
= (APTR
)opener
->node
.mln_Succ
;
1449 opener
= request
->ios2_BufferManagement
;
1450 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1452 request
->io_Error
= IOERR_ABORTED
;
1453 ReplyMsg((APTR
)request
);
1455 while((request
= (APTR
)GetMsg(&opener
->mgmt_port
)) != NULL
)
1457 request
->io_Error
= IOERR_ABORTED
;
1458 ReplyMsg((APTR
)request
);
1469 /****i* atheros5000.device/StatusInt ***************************************
1475 * finished = StatusInt(unit)
1477 * BOOL StatusInt(struct DevUnit *);
1487 ****************************************************************************
1489 * int_code is really in A5, but GCC 2.95.3 doesn't seem able to handle that.
1490 * Since we don't use this parameter, we can lie.
1494 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
1496 struct DevBase
*base
;
1497 uint32_t queue_mask
;
1498 HAL_INT ints
, int_mask
;
1500 base
= unit
->device
;
1501 int_mask
= unit
->hal
->ah_getInterrupts(unit
->hal
);
1503 if(!unit
->hal
->ah_isInterruptPending(unit
->hal
)) return FALSE
;
1507 if(unit
->hal
->ah_getPendingInterrupts(unit
->hal
, &ints
))
1509 if((ints
& HAL_INT_TX
) != 0)
1511 int_mask
&= ~(HAL_INT_TX
| HAL_INT_TXDESC
);
1512 queue_mask
= 1 << unit
->tx_queue_no
| 1 << unit
->mgmt_queue_no
;
1513 unit
->hal
->ah_getTxIntrQueue(unit
->hal
, &queue_mask
);
1514 if((queue_mask
& 1 << unit
->tx_queue_no
) != 0)
1515 Cause(&unit
->tx_end_int
);
1516 if((queue_mask
& 1 << unit
->mgmt_queue_no
) != 0)
1517 Cause(&unit
->mgmt_end_int
);
1519 if((ints
& HAL_INT_RX
) != 0)
1521 int_mask
&= ~(HAL_INT_RX
| HAL_INT_RXEOL
);
1522 Cause(&unit
->rx_int
);
1527 int_mask
= INT_MASK
;
1529 // unit->hal->ah_setInterrupts(unit->hal, int_mask))
1536 /****i* atheros5000.device/RXInt *******************************************
1539 * RXInt -- Soft interrupt for packet reception.
1544 * VOID RXInt(struct DevUnit *);
1549 * unit - A unit of this device.
1554 ****************************************************************************
1558 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
1560 UWORD ieee_length
, frame_control
, frame_type
, slot
, next_slot
,
1561 encryption
, key_no
, buffer_no
, old_length
;
1562 struct DevBase
*base
;
1565 struct ath_desc
*rx_desc
, *next_desc
;
1566 ULONG dma_size
, rx_desc_p
;
1567 UBYTE
*buffer
, *p
, *frame
, *data
, *snap_frame
, *source
;
1568 struct ath_rx_status status
;
1570 base
= unit
->device
;
1571 slot
= unit
->rx_slot
;
1572 rx_desc
= unit
->rx_descs
+ slot
;
1573 rx_desc_p
= unit
->rx_descs_p
+ slot
* sizeof(struct ath_desc
);
1574 next_slot
= (slot
+ 1) % RX_SLOT_COUNT
;
1575 next_desc
= unit
->rx_descs
+ next_slot
;
1577 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
1578 CachePostDMA(unit
->rx_descs
, &dma_size
, 0);
1580 while(unit
->hal
->ah_procRxDesc(unit
->hal
, rx_desc
, rx_desc_p
, next_desc
,
1581 unit
->hal
->ah_getTsf64(unit
->hal
), &status
) != HAL_EINPROGRESS
)
1584 buffer
= unit
->rx_buffers
[slot
];
1586 dma_size
= FRAME_BUFFER_SIZE
;
1587 CachePostDMA(buffer
, &dma_size
, 0);
1589 if(status
.rs_status
== 0
1590 && status
.rs_datalen
>= WIFI_FRM_DATA
+ FCS_SIZE
)
1592 /* Get fragment info */
1595 ieee_length
= status
.rs_datalen
- FCS_SIZE
- WIFI_FRM_DATA
;
1596 data
= frame
+ WIFI_FRM_DATA
;
1598 LEWord(*(UWORD
*)(frame
+ WIFI_FRM_CONTROL
));
1600 /* Get buffer to store fragment in */
1602 frag_no
= LEWord(*(UWORD
*)(frame
+ WIFI_FRM_SEQCONTROL
));
1603 if(unit
->mode
== S2PORT_ADHOC
)
1604 source
= frame
+ WIFI_FRM_ADDRESS2
;
1606 source
= frame
+ WIFI_FRM_ADDRESS3
;
1607 snap_frame
= GetRXBuffer(unit
, source
, frag_no
, &buffer_no
, base
);
1609 /* Get location to put new data */
1611 if(snap_frame
!= NULL
)
1613 if((frag_no
& 0xf ) > 0)
1615 BEWord(*(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
));
1618 /* Create new 802.3 header */
1620 CopyMem(frame
+ WIFI_FRM_ADDRESS1
, snap_frame
,
1622 CopyMem(source
, snap_frame
+ ETH_PACKET_SOURCE
,
1626 p
= snap_frame
+ ETH_HEADERSIZE
+ old_length
;
1628 /* Get encryption type and key index */
1630 if((frame_control
& WIFI_FRM_CONTROLF_WEP
) != 0)
1632 key_no
= data
[3] >> 6 & 0x3;
1633 encryption
= unit
->keys
[key_no
].type
;
1636 encryption
= S2ENC_NONE
;
1638 /* Append fragment to frame, decrypting/checking fragment if
1641 is_good
= unit
->fragment_decrypt_functions
[encryption
](unit
,
1642 frame
, data
, &ieee_length
, p
, base
);
1644 /* Update length in frame being built with current fragment, or
1645 increment bad frame counter if fragment is bad */
1649 ieee_length
+= old_length
;
1650 *(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
) =
1651 MakeBEWord(ieee_length
);
1654 unit
->stats
.BadData
++;
1656 /* If all fragments have arrived, process the complete frame */
1658 if((frame_control
& WIFI_FRM_CONTROLF_MOREFRAGS
) == 0)
1662 /* Decrypt complete frame if necessary */
1664 data
= snap_frame
+ ETH_HEADERSIZE
;
1665 if(encryption
== S2ENC_TKIP
)
1666 // && (unit->flags & UNITF_HARDTKIP) == 0)
1667 // && (unit->flags & UNITF_HARDMIC) == 0)
1669 is_good
= TKIPDecryptFrame(unit
, snap_frame
, data
,
1670 ieee_length
, data
, key_no
, base
);
1671 ieee_length
-= MIC_SIZE
;
1672 *(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
) =
1673 MakeBEWord(ieee_length
);
1675 unit
->stats
.BadData
++;
1681 /* Get frame's 802.11 type and subtype */
1683 frame_type
= (frame_control
& WIFI_FRM_CONTROLF_TYPE
)
1684 >> WIFI_FRM_CONTROLB_TYPE
;
1686 /* If it's a management frame, process it separately;
1687 otherwise distribute it to clients after filtering */
1689 if(frame_type
== WIFI_FRMTYPE_MGMT
)
1691 DistributeMgmtFrame(unit
, frame
, status
.rs_datalen
- 4,
1694 else if(AddressFilter(unit
, snap_frame
+ ETH_PACKET_DEST
,
1697 unit
->stats
.PacketsReceived
++;
1698 DistributeRXPacket(unit
, snap_frame
, base
);
1703 /* Mark fragment buffer as unused for next time */
1705 unit
->rx_fragment_nos
[buffer_no
] = -1;
1708 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_RX
, base
);
1717 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
,
1721 /* Prepare descriptor for next time */
1723 unit
->hal
->ah_setupRxDesc(unit
->hal
, rx_desc
, FRAME_BUFFER_SIZE
,
1726 dma_size
= FRAME_BUFFER_SIZE
;
1727 CachePreDMA(buffer
, &dma_size
, 0);
1729 /* Get next descriptor */
1732 rx_desc
= next_desc
;
1733 rx_desc_p
= unit
->rx_descs_p
+ slot
* sizeof(struct ath_desc
);
1734 next_slot
= (slot
+ 1) % RX_SLOT_COUNT
;
1735 next_desc
= unit
->rx_descs
+ next_slot
;
1738 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
1739 CachePreDMA(unit
->rx_descs
, &dma_size
, 0);
1741 unit
->rx_slot
= slot
;
1742 // TO DO: unstall reception?
1744 /* Re-enable RX interrupts */
1748 unit
->hal
->ah_setInterrupts(unit
->hal
,
1749 unit
->hal
->ah_getInterrupts(unit
->hal
) | HAL_INT_RX
| HAL_INT_RXEOL
);
1758 /****i* atheros5000.device/GetRXBuffer *************************************
1761 * GetRXBuffer -- Find an appropriate RX frame 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_frames
;
1781 for(i
= 0, found
= FALSE
; i
< FRAME_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
>= FRAME_BUFFER_COUNT
)
1787 unit
->rx_fragment_nos
[i
% FRAME_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
% FRAME_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
% FRAME_BUFFER_COUNT
] = frag_no
;
1805 buffer
+= FRAME_BUFFER_SIZE
;
1816 /****i* atheros5000.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* atheros5000.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* atheros5000.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* atheros5000.device/DistributeMgmtFrame *****************************
2071 * DistributeMgmtFrame -- Send a management frame to clients.
2074 * DistributeMgmtFrame(unit, frame, frame_size)
2076 * VOID DistributeMgmtFrame(struct DevUnit *, UBYTE *, UWORD);
2078 ****************************************************************************
2082 static VOID
DistributeMgmtFrame(struct DevUnit
*unit
, UBYTE
*frame
,
2083 UWORD frame_size
, struct DevBase
*base
)
2085 struct IOSana2Req
*request
;
2086 struct Opener
*opener
, *opener_tail
;
2088 /* Send packet to every opener */
2090 opener
= (APTR
)unit
->openers
.mlh_Head
;
2091 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
2093 while(opener
!= opener_tail
)
2095 request
= (APTR
)RemHead(&opener
->mgmt_port
.mp_MsgList
);
2099 /* Copy packet into opener's buffer and reply packet */
2101 if(frame_size
<= request
->ios2_DataLength
)
2103 CopyMem(frame
, request
->ios2_Data
, frame_size
);
2104 request
->ios2_DataLength
= frame_size
;
2108 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
2109 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
2111 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
2114 ReplyMsg((APTR
)request
);
2116 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
2119 opener
= (APTR
)opener
->node
.mln_Succ
;
2127 /****i* atheros5000.device/TXInt *******************************************
2130 * TXInt -- Soft interrupt for packet transmission.
2135 * VOID TXInt(struct DevUnit *);
2140 * unit - A unit of this device.
2145 ****************************************************************************
2149 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
2151 struct DevBase
*base
;
2152 UWORD i
, frame_size
, data_size
, packet_type
, body_size
, slot
, new_slot
,
2153 last_slot
, encryption
, subtype
, duration
;
2154 UBYTE
*buffer
, *q
, *plaintext
, *ciphertext
, *frame
,
2155 mic_header
[ETH_ADDRESSSIZE
* 2];
2156 const UBYTE
*p
, *dest
, *source
;
2157 struct IOSana2Req
*request
;
2158 BOOL proceed
= TRUE
, is_ieee
;
2159 struct Opener
*opener
;
2160 ULONG wire_error
, dma_size
;
2161 struct ath_desc
*tx_desc
, *last_desc
;
2162 UBYTE
*(*dma_tx_function
)(REG(a0
, APTR
));
2164 struct MsgPort
*port
;
2165 struct TypeStats
*tracker
;
2166 const HAL_RATE_TABLE
*rate_table
;
2168 base
= unit
->device
;
2169 port
= unit
->request_ports
[WRITE_QUEUE
];
2170 rate_table
= unit
->rate_table
;
2172 while(proceed
&& (!IsMsgPortEmpty(port
)))
2174 slot
= unit
->tx_in_slot
;
2175 new_slot
= (slot
+ 1) % TX_SLOT_COUNT
;
2177 // if(new_slot != unit->tx_out_slot)
2178 if(slot
== unit
->tx_out_slot
) // one packet at a time
2183 /* Get request and DMA frame descriptor */
2185 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
2187 Remove((APTR
)request
);
2188 unit
->tx_requests
[slot
] = request
;
2189 tx_desc
= unit
->tx_descs
+ slot
;
2190 frame
= unit
->tx_buffers
[slot
];
2192 /* Get packet data */
2194 opener
= request
->ios2_BufferManagement
;
2195 dma_tx_function
= opener
->dma_tx_function
;
2196 if(dma_tx_function
!= NULL
)
2197 buffer
= dma_tx_function(request
->ios2_Data
);
2203 buffer
= unit
->tx_buffer
;
2204 if(!opener
->tx_function(buffer
, request
->ios2_Data
,
2205 request
->ios2_DataLength
))
2207 error
= S2ERR_NO_RESOURCES
;
2208 wire_error
= S2WERR_BUFF_ERROR
;
2210 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
2211 | S2EVENT_TX
, base
);
2217 /* Get packet type and/or length */
2219 data_size
= request
->ios2_DataLength
;
2220 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) != 0)
2222 data_size
-= ETH_PACKET_DATA
;
2223 packet_type
= BEWord(*(UWORD
*)(buffer
+ ETH_PACKET_TYPE
));
2226 packet_type
= request
->ios2_PacketType
;
2227 is_ieee
= packet_type
<= ETH_MTU
;
2229 /* Determine encryption type and frame subtype */
2233 encryption
= unit
->keys
[unit
->tx_key_no
].type
;
2238 encryption
= S2ENC_NONE
;
2242 /* Get source and destination addresses */
2244 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) != 0)
2247 source
= buffer
+ ETH_ADDRESSSIZE
;
2248 buffer
+= ETH_ADDRESSSIZE
* 2 + 2;
2252 dest
= request
->ios2_DstAddr
;
2253 source
= unit
->address
;
2256 /* Write 802.11 header */
2259 *(UWORD
*)q
= MakeLEWord(
2260 (encryption
== S2ENC_NONE
? 0 : WIFI_FRM_CONTROLF_WEP
)
2261 | (unit
->mode
== S2PORT_ADHOC
? 0 : WIFI_FRM_CONTROLF_TODS
)
2262 | subtype
<< WIFI_FRM_CONTROLB_SUBTYPE
2263 | WIFI_FRMTYPE_DATA
<< WIFI_FRM_CONTROLB_TYPE
);
2266 i
= rate_table
->rateCodeToIndex
[unit
->tx_rate_codes
[0]];
2267 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
2268 duration
= rate_table
->info
[i
].spAckDuration
;
2270 duration
= rate_table
->info
[i
].lpAckDuration
;
2271 *(UWORD
*)q
= MakeLEWord(duration
);
2274 if(unit
->mode
== S2PORT_ADHOC
)
2278 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
2281 for(i
= 0, p
= source
; i
< ETH_ADDRESSSIZE
; i
++)
2284 if(unit
->mode
== S2PORT_ADHOC
)
2288 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
2293 // TO DO: need to pad header to 4-byte boundary?
2295 /* Leave room for encryption overhead */
2298 q
+= unit
->iv_sizes
[encryption
];
2301 /* Write SNAP header */
2305 for(i
= 0, p
= snap_template
;
2306 i
< SNAP_FRM_TYPE
; i
++)
2308 *(UWORD
*)q
= MakeBEWord(packet_type
);
2310 body_size
+= SNAP_HEADERSIZE
;
2313 /* Copy data into frame */
2315 CopyMem(buffer
, q
, data_size
);
2316 body_size
+= data_size
;
2318 /* Append MIC to frame for TKIP */
2320 if(encryption
== S2ENC_TKIP
)
2322 // if((unit->flags & UNITF_HARDMIC) == 0)
2325 for(i
= 0, p
= dest
; i
< ETH_ADDRESSSIZE
; i
++)
2327 for(i
= 0, p
= source
; i
< ETH_ADDRESSSIZE
; i
++)
2329 TKIPEncryptFrame(unit
, mic_header
, plaintext
, body_size
,
2332 body_size
+= MIC_SIZE
;
2335 /* Encrypt fragment if applicable */
2337 unit
->fragment_encrypt_functions
[encryption
](unit
, frame
,
2338 plaintext
, &body_size
, ciphertext
, base
);
2340 /* Fill in DMA descriptor for packet transmission */
2342 frame_size
= WIFI_FRM_DATA
+ body_size
;
2343 tx_desc
->ds_link
= (ULONG
)(UPINT
)NULL
;
2344 unit
->hal
->ah_setupTxDesc(unit
->hal
, tx_desc
, frame_size
+ 4, // + CRC?
2345 WIFI_FRM_DATA
, HAL_PKT_TYPE_NORMAL
, TX_POWER
,
2346 ((unit
->flags
& UNITF_SLOWRETRIES
) != 0) ?
2347 unit
->tx_rate_codes
[0] : unit
->tx_rate_codes
[1],
2348 ((unit
->flags
& UNITF_SLOWRETRIES
) != 0) ? 1 : TX_TRIES
,
2349 HAL_TXKEYIX_INVALID
,
2350 HAL_ANTENNA_MIN_MODE
,
2351 HAL_TXDESC_INTREQ
| HAL_TXDESC_CLRDMASK
,
2353 if((unit
->flags
& UNITF_SLOWRETRIES
) != 0)
2354 unit
->hal
->ah_setupXTxDesc(unit
->hal
, tx_desc
,
2355 unit
->tx_rate_codes
[1], 1,
2356 unit
->tx_rate_codes
[2], 1,
2357 unit
->tx_rate_codes
[3], TX_TRIES
- 3);
2358 unit
->hal
->ah_fillTxDesc(unit
->hal
, tx_desc
, frame_size
, TRUE
, TRUE
,
2361 dma_size
= frame_size
;
2362 CachePreDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2364 /* Pass packet to adapter */
2366 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
2367 last_slot
= (slot
+ TX_SLOT_COUNT
- 1) % TX_SLOT_COUNT
;
2368 if(unit
->tx_out_slot
!= slot
)
2369 //if(unit->hal->ah_numTxPending(unit->hal, unit->tx_queue_no) > 0)
2372 unit
->tx_descs
+ last_slot
;
2373 last_desc
->ds_link
= unit
->tx_descs_p
+ slot
* sizeof(struct ath_desc
);
2374 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2375 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2379 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2380 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2381 unit
->hal
->ah_setTxDP(unit
->hal
, unit
->tx_queue_no
,
2382 unit
->tx_descs_p
+ slot
* sizeof(struct ath_desc
));
2385 unit
->hal
->ah_startTxDma(unit
->hal
, unit
->tx_queue_no
);
2386 unit
->tx_in_slot
= new_slot
;
2390 /* Reply failed request */
2392 request
->ios2_Req
.io_Error
= error
;
2393 request
->ios2_WireError
= wire_error
;
2394 ReplyMsg((APTR
)request
);
2397 /* Update statistics */
2401 unit
->stats
.PacketsSent
++;
2403 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
2404 request
->ios2_PacketType
, base
);
2407 tracker
->stats
.PacketsSent
++;
2408 tracker
->stats
.BytesSent
+= ETH_HEADERSIZE
+ data_size
;
2416 /* Don't try to keep sending packets if there's no space left */
2419 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
2421 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
2428 /****i* atheros5000.device/TXEndInt ****************************************
2431 * TXEndInt -- Clean up after a data frame has been sent.
2434 * TXEndInt(unit, int_code)
2436 * VOID TXEndInt(struct DevUnit *, APTR);
2439 * I think it's safe to assume that there will always be at least one
2440 * completed packet whenever this interrupt is called.
2442 ****************************************************************************
2446 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
),
2447 REG(a6
, APTR int_code
))
2449 UWORD frame_size
, new_out_slot
, i
;
2451 struct DevBase
*base
;
2452 struct IOSana2Req
*request
;
2454 struct TypeStats
*tracker
;
2456 /* Find out which packets have completed */
2458 base
= unit
->device
;
2459 new_out_slot
= (unit
->tx_in_slot
+ TX_SLOT_COUNT
2460 - unit
->hal
->ah_numTxPending(unit
->hal
, unit
->tx_queue_no
))
2463 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2464 CachePostDMA(unit
->tx_descs
, &dma_size
, 0);
2466 /* Retire sent packets */
2468 for(i
= unit
->tx_out_slot
; i
!= new_out_slot
;
2469 i
= (i
+ 1) % TX_SLOT_COUNT
)
2471 frame
= unit
->tx_buffers
[i
];
2472 dma_size
= FRAME_BUFFER_SIZE
;
2473 CachePostDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2475 /* Update statistics */
2477 request
= unit
->tx_requests
[i
];
2478 frame_size
= request
->ios2_DataLength
;
2479 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
2480 frame_size
+= ETH_HEADERSIZE
;
2482 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
2483 request
->ios2_PacketType
, base
);
2486 tracker
->stats
.PacketsSent
++;
2487 tracker
->stats
.BytesSent
+= frame_size
;
2492 request
->ios2_Req
.io_Error
= 0;
2493 ReplyMsg((APTR
)request
);
2496 unit
->tx_out_slot
= i
;
2498 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2499 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2501 /* Restart downloads if they had stopped */
2503 if(unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
== PA_IGNORE
)
2504 Cause(&unit
->tx_int
);
2511 /****i* atheros5000.device/MgmtTXInt ***************************************
2514 * MgmtTXInt -- Soft interrupt for management frame transmission.
2519 * VOID MgmtTXInt(struct DevUnit *);
2524 * unit - A unit of this device.
2529 ****************************************************************************
2533 static VOID
MgmtTXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
2535 struct DevBase
*base
;
2536 UWORD frame_size
, slot
, new_slot
, last_slot
, i
, duration
;
2538 struct IOSana2Req
*request
;
2539 BOOL proceed
= TRUE
, has_bssid
;
2541 struct ath_desc
*desc
, *last_desc
;
2542 struct MsgPort
*port
;
2543 const HAL_RATE_TABLE
*rate_table
;
2545 base
= unit
->device
;
2546 port
= unit
->request_ports
[MGMT_QUEUE
];
2547 rate_table
= unit
->rate_table
;
2549 while(proceed
&& (!IsMsgPortEmpty(port
)))
2551 slot
= unit
->mgmt_in_slot
;
2552 new_slot
= (slot
+ 1) % MGMT_SLOT_COUNT
;
2554 // if(new_slot != unit->mgmt_out_slot)
2555 if(slot
== unit
->mgmt_out_slot
) // one packet at a time
2557 /* Get request and DMA frame descriptor */
2559 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
2561 Remove((APTR
)request
);
2562 unit
->mgmt_requests
[slot
] = request
;
2563 desc
= unit
->mgmt_descs
+ slot
;
2564 frame
= unit
->mgmt_buffers
[slot
];
2566 /* Get packet length */
2568 frame_size
= request
->ios2_DataLength
;
2570 /* Copy frame into DMA buffer */
2572 CopyMem(request
->ios2_Data
, frame
, frame_size
);
2576 has_bssid
= ((frame
+ WIFI_FRM_ADDRESS1
)[0] & 0x1) == 0;
2577 i
= rate_table
->rateCodeToIndex
[unit
->mgmt_rate_code
];
2580 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
2581 duration
= rate_table
->info
[i
].spAckDuration
;
2583 duration
= rate_table
->info
[i
].lpAckDuration
;
2587 *(UWORD
*)(frame
+ WIFI_FRM_DURATION
) = MakeLEWord(duration
);
2589 /* Fill in DMA descriptor for packet transmission */
2591 desc
->ds_link
= (ULONG
)(UPINT
)NULL
;
2592 unit
->hal
->ah_setupTxDesc(unit
->hal
, desc
, frame_size
+ 4, // + CRC?
2593 WIFI_FRM_DATA
, HAL_PKT_TYPE_NORMAL
, TX_POWER
,
2594 unit
->mgmt_rate_code
, TX_TRIES
, HAL_TXKEYIX_INVALID
,
2595 HAL_ANTENNA_MIN_MODE
,
2596 HAL_TXDESC_INTREQ
| HAL_TXDESC_CLRDMASK
2597 | (has_bssid
? 0 : HAL_TXDESC_NOACK
),
2599 unit
->hal
->ah_fillTxDesc(unit
->hal
, desc
, frame_size
, TRUE
, TRUE
,
2602 dma_size
= frame_size
;
2603 CachePreDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2605 /* Pass packet to adapter */
2607 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2608 last_slot
= (slot
+ MGMT_SLOT_COUNT
- 1) % MGMT_SLOT_COUNT
;
2609 if(unit
->mgmt_out_slot
!= slot
)
2610 //if(unit->hal->ah_numTxPending(unit->hal, unit->mgmt_queue_no) > 0)
2612 last_desc
= unit
->mgmt_descs
+ last_slot
;
2613 last_desc
->ds_link
=
2614 unit
->mgmt_descs_p
+ slot
* sizeof(struct ath_desc
);
2615 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2616 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2620 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2621 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2622 unit
->hal
->ah_setTxDP(unit
->hal
, unit
->mgmt_queue_no
,
2623 unit
->mgmt_descs_p
+ slot
* sizeof(struct ath_desc
));
2626 unit
->hal
->ah_startTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2627 unit
->mgmt_in_slot
= new_slot
;
2633 /* Don't try to keep sending packets if there's no space left */
2636 unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
= PA_SOFTINT
;
2638 unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
= PA_IGNORE
;
2645 /****i* atheros5000.device/MgmtTXEndInt ************************************
2648 * MgmtTXEndInt -- Clean up after a management frame has been sent.
2651 * MgmtTXEndInt(unit, int_code)
2653 * VOID MgmtTXEndInt(struct DevUnit *, APTR);
2656 * I think it's safe to assume that there will always be at least one
2657 * completed packet whenever this interrupt is called.
2659 ****************************************************************************
2663 static VOID
MgmtTXEndInt(REG(a1
, struct DevUnit
*unit
),
2664 REG(a6
, APTR int_code
))
2666 UWORD new_out_slot
, i
;
2668 struct DevBase
*base
;
2669 struct IOSana2Req
*request
;
2672 /* Find out which packets have completed */
2674 base
= unit
->device
;
2675 new_out_slot
= (unit
->mgmt_in_slot
+ MGMT_SLOT_COUNT
2676 - unit
->hal
->ah_numTxPending(unit
->hal
, unit
->mgmt_queue_no
))
2679 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2680 CachePostDMA(unit
->mgmt_descs
, &dma_size
, 0);
2682 /* Retire sent frames */
2684 for(i
= unit
->mgmt_out_slot
; i
!= new_out_slot
;
2685 i
= (i
+ 1) % MGMT_SLOT_COUNT
)
2687 frame
= unit
->mgmt_buffers
[i
];
2688 dma_size
= FRAME_BUFFER_SIZE
;
2689 CachePostDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2693 request
= unit
->mgmt_requests
[i
];
2694 request
->ios2_Req
.io_Error
= 0;
2695 ReplyMsg((APTR
)request
);
2698 unit
->mgmt_out_slot
= i
;
2700 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2701 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2703 /* Restart downloads if they had stopped */
2705 if(unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
== PA_IGNORE
)
2706 Cause(&unit
->mgmt_int
);
2713 /****i* atheros5000.device/ResetHandler ************************************
2716 * ResetHandler -- Disable hardware before a reboot.
2719 * ResetHandler(unit, int_code)
2721 * VOID ResetHandler(struct DevUnit *, APTR);
2723 ****************************************************************************
2727 static VOID
ResetHandler(REG(a1
, struct DevUnit
*unit
),
2728 REG(a6
, APTR int_code
))
2730 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
2732 /* Disable frame transmission */
2734 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
2735 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2737 /* Disable frame reception */
2739 unit
->hal
->ah_stopPcuReceive(unit
->hal
);
2740 unit
->hal
->ah_stopDmaReceive(unit
->hal
);
2742 /* Stop interrupts */
2744 unit
->hal
->ah_setInterrupts(unit
->hal
, 0);
2752 /****i* atheros5000.device/UpdateStats *************************************
2760 * VOID UpdateStats(struct DevUnit *);
2765 * unit - A unit of this device.
2770 ****************************************************************************
2774 VOID
UpdateStats(struct DevUnit
*unit
, struct DevBase
*base
)
2776 /* Ask for and wait for stats */
2783 /****i* atheros5000.device/ReportEvents ************************************
2789 * ReportEvents(unit, events)
2791 * VOID ReportEvents(struct DevUnit *, ULONG);
2796 * unit - A unit of this device.
2797 * events - A mask of events to report.
2802 ****************************************************************************
2806 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
2807 struct DevBase
*base
)
2809 struct IOSana2Req
*request
, *tail
, *next_request
;
2812 list
= &unit
->request_ports
[EVENT_QUEUE
]->mp_MsgList
;
2813 next_request
= (APTR
)list
->lh_Head
;
2814 tail
= (APTR
)&list
->lh_Tail
;
2817 while(next_request
!= tail
)
2819 request
= next_request
;
2820 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
2822 if((request
->ios2_WireError
& events
) != 0)
2824 request
->ios2_WireError
= events
;
2825 Remove((APTR
)request
);
2826 ReplyMsg((APTR
)request
);
2836 /****i* atheros5000.device/GetRadioBands ***********************************
2839 * GetRadioBands -- Get information on current network.
2842 * tag_list = GetRadioBands(unit, pool)
2844 * struct TagItem *GetRadioBands(struct DevUnit *, APTR);
2849 * unit - A unit of this device.
2850 * pool - A memory pool.
2855 ****************************************************************************
2860 struct TagItem
*GetRadioBands(struct DevUnit
*unit
, APTR pool
,
2861 struct DevBase
*base
)
2864 struct Sana2RadioBand
*bands
;
2867 bands
= AllocPooled(pool
, sizeof(struct Sana2RadioBand
) * 3);
2869 error
= S2ERR_NO_RESOURCES
;
2873 for(i
= 0; i
< 1; i
++)
2875 bands
[i
] = AllocPooled(pool
, sizeof(UWORD
) * unit
->channel_counts
[S2BAND_B
]);
2888 /****i* atheros5000.device/UnitTask ****************************************
2899 * Completes deferred requests, and handles card insertion and removal
2900 * in conjunction with the relevant interrupts.
2902 ****************************************************************************
2910 static VOID
UnitTask(struct ExecBase
*sys_base
)
2913 struct IORequest
*request
;
2914 struct DevUnit
*unit
;
2915 struct DevBase
*base
;
2916 struct MsgPort
*general_port
;
2917 ULONG signals
= 0, wait_signals
, card_removed_signal
,
2918 card_inserted_signal
, general_port_signal
;
2920 /* Get parameters */
2922 task
= AbsExecBase
->ThisTask
;
2923 unit
= task
->tc_UserData
;
2924 base
= unit
->device
;
2926 /* Activate general request port */
2928 general_port
= unit
->request_ports
[GENERAL_QUEUE
];
2929 general_port
->mp_SigTask
= task
;
2930 general_port
->mp_SigBit
= AllocSignal(-1);
2931 general_port_signal
= 1 << general_port
->mp_SigBit
;
2932 general_port
->mp_Flags
= PA_SIGNAL
;
2934 /* Allocate signals for notification of card removal and insertion */
2936 card_removed_signal
= unit
->card_removed_signal
= 1 << AllocSignal(-1);
2937 card_inserted_signal
= unit
->card_inserted_signal
= 1 << AllocSignal(-1);
2938 wait_signals
= (1 << general_port
->mp_SigBit
) | card_removed_signal
2939 | card_inserted_signal
| SIGBREAKF_CTRL_C
;
2941 /* Tell ourselves to check port for old messages */
2943 Signal(task
, general_port_signal
);
2945 /* Infinite loop to service requests and signals */
2947 while((signals
& SIGBREAKF_CTRL_C
) == 0)
2949 signals
= Wait(wait_signals
);
2951 if((signals
& card_inserted_signal
) != 0)
2953 if(unit
->insertion_function(unit
->card
, base
))
2955 unit
->flags
|= UNITF_HAVEADAPTER
;
2956 if((unit
->flags
& UNITF_CONFIGURED
) != 0)
2957 ConfigureAdapter(unit
, base
);
2958 if((unit
->flags
& UNITF_WASONLINE
) != 0)
2960 GoOnline(unit
, base
);
2961 unit
->flags
&= ~UNITF_WASONLINE
;
2966 if((signals
& card_removed_signal
) != 0)
2968 unit
->removal_function(unit
->card
, base
);
2969 if((unit
->flags
& UNITF_WASONLINE
) != 0)
2970 GoOffline(unit
, base
);
2973 if((signals
& general_port_signal
) != 0)
2975 while((request
= (APTR
)GetMsg(general_port
)) != NULL
)
2977 /* Service the request as soon as the unit is free */
2979 ObtainSemaphore(&unit
->access_lock
);
2980 ServiceRequest((APTR
)request
, base
);
2985 FreeMem(task
->tc_SPLower
, STACK_SIZE
);