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 static const UBYTE broadcast_address
[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
95 static const ULONG g_retry_rates
[] = {54000, 36000, 18000, 2000};
96 static const ULONG b_retry_rates
[] = {11000, 5500, 2000, 1000};
101 #define AddTask(task, initial_pc, final_pc) \
102 IExec->AddTask(task, initial_pc, final_pc, NULL)
105 static const struct EmulLibEntry mos_task_trap
=
111 #define UnitTask &mos_task_trap
115 #define AddTask(task, initial_pc, final_pc) \
117 struct TagItem _task_tags[] = \
118 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
119 NewAddTask(task, initial_pc, final_pc, _task_tags); \
125 /****i* atheros5000.device/CreateUnit **************************************
128 * CreateUnit -- Create a unit.
131 * unit = CreateUnit(index, io_base, id, card,
134 * struct DevUnit *CreateUnit(ULONG, APTR, UWORD, APTR,
135 * struct TagItem *, UWORD);
138 * Creates a new unit.
140 ****************************************************************************
144 struct DevUnit
*CreateUnit(ULONG index
, APTR io_base
, UWORD id
, APTR card
,
145 const struct TagItem
*io_tags
, UWORD bus
, struct DevBase
*base
)
148 struct DevUnit
*unit
;
150 struct MsgPort
*port
;
152 struct ath_desc
*tx_desc
, *rx_desc
;
155 HAL_STATUS hal_status
;
157 unit
= AllocMem(sizeof(struct DevUnit
), MEMF_CLEAR
| MEMF_PUBLIC
);
163 /* Initialise lists etc. */
165 NewList((APTR
)&unit
->openers
);
166 NewList((APTR
)&unit
->type_trackers
);
167 NewList((APTR
)&unit
->multicast_ranges
);
174 /* Store DMA memory hooks */
177 (APTR
)GetTagData(IOTAG_AllocDMAMem
, (UPINT
)NULL
, io_tags
);
179 (APTR
)GetTagData(IOTAG_FreeDMAMem
, (UPINT
)NULL
, io_tags
);
180 if(unit
->AllocDMAMem
== NULL
|| unit
->FreeDMAMem
== NULL
)
188 unit
->hal
= ath_hal_attach(id
, unit
, NULL
, io_base
, &hal_status
);
190 if(unit
->hal
== NULL
)
196 InitSemaphore(&unit
->access_lock
);
198 /* Create the message ports for queuing requests */
200 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
202 unit
->request_ports
[i
] = port
= AllocMem(sizeof(struct MsgPort
),
203 MEMF_PUBLIC
| MEMF_CLEAR
);
209 NewList(&port
->mp_MsgList
);
210 port
->mp_Flags
= PA_IGNORE
;
216 unit
->request_ports
[WRITE_QUEUE
]->mp_SigTask
= &unit
->tx_int
;
217 unit
->request_ports
[MGMT_QUEUE
]->mp_SigTask
= &unit
->mgmt_int
;
220 /* Allocate buffers and descriptors */
222 unit
->tx_buffer
= AllocVec(ETH_MAXPACKETSIZE
, MEMF_PUBLIC
);
223 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
225 unit
->tx_buffers
[i
] =
226 unit
->AllocDMAMem(unit
->card
, FRAME_BUFFER_SIZE
, 4);
227 if(unit
->tx_buffers
[i
] == NULL
)
230 for(i
= 0; i
< MGMT_SLOT_COUNT
; i
++)
232 unit
->mgmt_buffers
[i
] =
233 unit
->AllocDMAMem(unit
->card
, FRAME_BUFFER_SIZE
, 4);
234 if(unit
->mgmt_buffers
[i
] == NULL
)
237 unit
->rx_buffer
= AllocVec(FRAME_BUFFER_SIZE
, MEMF_PUBLIC
);
238 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
240 unit
->rx_buffers
[i
] =
241 unit
->AllocDMAMem(unit
->card
, FRAME_BUFFER_SIZE
, 4);
242 if(unit
->rx_buffers
[i
] == NULL
)
246 AllocVec(FRAME_BUFFER_SIZE
* FRAME_BUFFER_COUNT
, MEMF_PUBLIC
);
247 for(i
= 0; i
< FRAME_BUFFER_COUNT
; i
++)
248 unit
->rx_fragment_nos
[i
] = -1;
249 unit
->tx_descs
= unit
->AllocDMAMem(unit
->card
,
250 sizeof(struct ath_desc
) * TX_SLOT_COUNT
, 4);
251 unit
->mgmt_descs
= unit
->AllocDMAMem(unit
->card
,
252 sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
, 4);
253 unit
->rx_descs
= unit
->AllocDMAMem(unit
->card
,
254 sizeof(struct ath_desc
) * RX_SLOT_COUNT
, 4);
255 unit
->tx_requests
= AllocVec(sizeof(APTR
) * TX_SLOT_COUNT
,
257 unit
->mgmt_requests
= AllocVec(sizeof(APTR
) * MGMT_SLOT_COUNT
,
259 unit
->channels
= AllocVec(sizeof(HAL_CHANNEL
) * MAX_CHANNEL_COUNT
,
260 MEMF_PUBLIC
| MEMF_CLEAR
);
261 if(unit
->tx_buffer
== NULL
262 || unit
->rx_buffer
== NULL
263 || unit
->rx_frames
== NULL
264 || unit
->tx_descs
== NULL
265 || unit
->mgmt_descs
== NULL
266 || unit
->rx_descs
== NULL
267 || unit
->tx_requests
== NULL
268 || unit
->mgmt_requests
== NULL
269 || unit
->channels
== NULL
)
275 /* Initialise network adapter hardware */
277 success
= InitialiseAdapter(unit
, FALSE
, base
);
278 unit
->flags
|= UNITF_HAVEADAPTER
;
283 /* Get physical addresses of DMA structures */
285 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
287 (ULONG
)(UPINT
)CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
288 if(dma_size
!= sizeof(struct ath_desc
) * TX_SLOT_COUNT
)
290 CachePostDMA(unit
->tx_descs
, &dma_size
, 0);
292 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
294 dma_size
= FRAME_BUFFER_SIZE
;
295 unit
->tx_buffers_p
[i
] =
296 (ULONG
)(UPINT
)CachePreDMA(unit
->tx_buffers
[i
], &dma_size
, 0);
297 if(dma_size
!= FRAME_BUFFER_SIZE
)
299 CachePostDMA(unit
->tx_buffers
[i
], &dma_size
, 0);
302 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
304 (ULONG
)(UPINT
)CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
305 if(dma_size
!= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
)
307 CachePostDMA(unit
->mgmt_descs
, &dma_size
, 0);
309 for(i
= 0; i
< MGMT_SLOT_COUNT
; i
++)
311 dma_size
= FRAME_BUFFER_SIZE
;
312 unit
->mgmt_buffers_p
[i
] =
313 (ULONG
)(UPINT
)CachePreDMA(unit
->mgmt_buffers
[i
], &dma_size
, 0);
314 if(dma_size
!= FRAME_BUFFER_SIZE
)
316 CachePostDMA(unit
->mgmt_buffers
[i
], &dma_size
, 0);
319 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
321 (ULONG
)(UPINT
)CachePreDMA(unit
->rx_descs
, &dma_size
, 0);
322 if(dma_size
!= sizeof(struct ath_desc
) * RX_SLOT_COUNT
)
324 CachePostDMA(unit
->rx_descs
, &dma_size
, 0);
326 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
328 dma_size
= FRAME_BUFFER_SIZE
;
329 unit
->rx_buffers_p
[i
] =
330 (ULONG
)(UPINT
)CachePreDMA(unit
->rx_buffers
[i
], &dma_size
, 0);
331 if(dma_size
!= FRAME_BUFFER_SIZE
)
333 CachePostDMA(unit
->rx_buffers
[i
], &dma_size
, 0);
336 /* Construct TX ring */
338 for(tx_desc
= unit
->tx_descs
, i
= 0; i
< TX_SLOT_COUNT
; i
++)
340 tx_desc
->ds_data
= unit
->tx_buffers_p
[i
];
344 /* Construct management frame TX ring */
346 for(tx_desc
= unit
->mgmt_descs
, i
= 0; i
< MGMT_SLOT_COUNT
; i
++)
348 tx_desc
->ds_data
= unit
->mgmt_buffers_p
[i
];
352 /* Construct RX ring */
354 for(rx_desc
= unit
->rx_descs
, i
= 0; i
< RX_SLOT_COUNT
; i
++)
356 rx_desc
->ds_link
= unit
->rx_descs_p
+ ((i
+ 1) % RX_SLOT_COUNT
)
357 * sizeof(struct ath_desc
);
358 rx_desc
->ds_data
= unit
->rx_buffers_p
[i
];
359 unit
->hal
->ah_setupRxDesc(unit
->hal
, rx_desc
, FRAME_BUFFER_SIZE
,
364 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
365 CachePreDMA(unit
->rx_descs
, &dma_size
, 0);
367 /* Record maximum speed in BPS */
369 unit
->speed
= 54000000;
371 /* Initialise status, transmit, receive and stats interrupts */
373 unit
->status_int
.is_Node
.ln_Name
=
374 base
->device
.dd_Library
.lib_Node
.ln_Name
;
375 unit
->status_int
.is_Code
= (APTR
)StatusInt
;
376 unit
->status_int
.is_Data
= unit
;
378 unit
->rx_int
.is_Node
.ln_Name
=
379 base
->device
.dd_Library
.lib_Node
.ln_Name
;
380 unit
->rx_int
.is_Code
= (APTR
)RXInt
;
381 unit
->rx_int
.is_Data
= unit
;
383 unit
->tx_int
.is_Node
.ln_Name
=
384 base
->device
.dd_Library
.lib_Node
.ln_Name
;
385 unit
->tx_int
.is_Code
= (APTR
)TXInt
;
386 unit
->tx_int
.is_Data
= unit
;
388 unit
->tx_end_int
.is_Node
.ln_Name
=
389 base
->device
.dd_Library
.lib_Node
.ln_Name
;
390 unit
->tx_end_int
.is_Code
= (APTR
)TXEndInt
;
391 unit
->tx_end_int
.is_Data
= unit
;
393 unit
->mgmt_int
.is_Node
.ln_Name
=
394 base
->device
.dd_Library
.lib_Node
.ln_Name
;
395 unit
->mgmt_int
.is_Code
= (APTR
)MgmtTXInt
;
396 unit
->mgmt_int
.is_Data
= unit
;
398 unit
->mgmt_end_int
.is_Node
.ln_Name
=
399 base
->device
.dd_Library
.lib_Node
.ln_Name
;
400 unit
->mgmt_end_int
.is_Code
= (APTR
)MgmtTXEndInt
;
401 unit
->mgmt_end_int
.is_Data
= unit
;
403 unit
->reset_handler
.is_Node
.ln_Name
=
404 base
->device
.dd_Library
.lib_Node
.ln_Name
;
405 unit
->reset_handler
.is_Code
= (APTR
)ResetHandler
;
406 unit
->reset_handler
.is_Data
= unit
;
408 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
409 unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
= PA_SOFTINT
;
411 /* Create a new task */
414 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
421 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
428 /* Initialise and start task */
430 task
->tc_Node
.ln_Type
= NT_TASK
;
431 task
->tc_Node
.ln_Pri
= TASK_PRIORITY
;
432 task
->tc_Node
.ln_Name
= base
->device
.dd_Library
.lib_Node
.ln_Name
;
433 task
->tc_SPUpper
= stack
+ STACK_SIZE
;
434 task
->tc_SPLower
= stack
;
435 task
->tc_SPReg
= stack
+ STACK_SIZE
;
436 NewList(&task
->tc_MemEntry
);
438 if(AddTask(task
, UnitTask
, NULL
) == NULL
)
444 /* Send the unit to the new task */
446 task
->tc_UserData
= unit
;
448 /* Set default wireless options */
450 unit
->mode
= S2PORT_MANAGED
;
455 DeleteUnit(unit
, base
);
464 /****i* atheros5000.device/DeleteUnit **************************************
467 * DeleteUnit -- Delete a unit.
472 * VOID DeleteUnit(struct DevUnit *);
478 * unit - Device unit (may be NULL).
483 ****************************************************************************
487 VOID
DeleteUnit(struct DevUnit
*unit
, struct DevBase
*base
)
497 if(task
->tc_UserData
!= NULL
)
500 FreeMem(task
->tc_SPLower
, STACK_SIZE
);
501 Signal(unit
->task
, SIGBREAKF_CTRL_C
);
503 FreeMem(task
, sizeof(struct Task
));
506 for(i
= 0; i
< REQUEST_QUEUE_COUNT
; i
++)
508 if(unit
->request_ports
[i
] != NULL
)
509 FreeMem(unit
->request_ports
[i
], sizeof(struct MsgPort
));
512 if((unit
->flags
& UNITF_ONLINE
) != 0) /* Needed! */
513 GoOffline(unit
, base
);
515 for(i
= 0; i
< TX_SLOT_COUNT
; i
++)
516 unit
->FreeDMAMem(unit
->card
, unit
->tx_buffers
[i
]);
517 for(i
= 0; i
< MGMT_SLOT_COUNT
; i
++)
518 unit
->FreeDMAMem(unit
->card
, unit
->mgmt_buffers
[i
]);
519 for(i
= 0; i
< RX_SLOT_COUNT
; i
++)
520 unit
->FreeDMAMem(unit
->card
, unit
->rx_buffers
[i
]);
522 FreeVec(unit
->tx_buffer
);
523 FreeVec(unit
->rx_frames
);
524 FreeVec(unit
->tx_requests
);
525 FreeVec(unit
->mgmt_requests
);
526 FreeVec(unit
->channels
);
527 FreeVec(unit
->rx_buffer
);
529 if(unit
->hal
!= NULL
)
530 unit
->hal
->ah_detach(unit
->hal
);
532 FreeMem(unit
, sizeof(struct DevUnit
));
540 /****i* atheros5000.device/InitialiseAdapter *******************************
546 * success = InitialiseAdapter(unit, reinsertion)
548 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
557 * success - Success indicator.
559 ****************************************************************************
563 BOOL
InitialiseAdapter(struct DevUnit
*unit
, BOOL reinsertion
,
564 struct DevBase
*base
)
566 UBYTE i
, reg_class_id
;
568 unsigned int channel_count
, reg_class_count
;
569 HAL_TXQ_INFO queue_info
= {0};
571 /* Get default MAC address */
573 unit
->hal
->ah_getMacAddress(unit
->hal
, unit
->default_address
);
575 /* Get default antenna */
577 unit
->antenna
= unit
->hal
->ah_getDefAntenna(unit
->hal
);
579 /* Reset key cache */
581 for(i
= 0; i
< WIFI_KEYCOUNT
; i
++)
582 unit
->hal
->ah_resetKeyCacheEntry(unit
->hal
, i
);
584 /* Initialise channels and rates */
586 ath_hal_init_channels(unit
->hal
, unit
->channels
,
587 MAX_CHANNEL_COUNT
, &channel_count
,
588 ®_class_id
, 1, ®_class_count
, CTRY_DEFAULT
,
589 HAL_MODE_11B
| HAL_MODE_PUREG
, TRUE
,
591 unit
->channel_count
= channel_count
;
594 unit
->band
= S2BAND_B
;
596 /* Check if multi-rate retries are supported */
598 if(unit
->hal
->ah_setupXTxDesc(unit
->hal
, NULL
, 0, 0, 0, 0, 0, 0))
599 unit
->flags
|= UNITF_SLOWRETRIES
;
601 /* Set up TX queue */
603 queue_info
.tqi_aifs
= HAL_TXQ_USEDEFAULT
;
604 queue_info
.tqi_cwmin
= HAL_TXQ_USEDEFAULT
;
605 queue_info
.tqi_cwmax
= HAL_TXQ_USEDEFAULT
;
606 queue_info
.tqi_qflags
=
607 HAL_TXQ_TXEOLINT_ENABLE
| HAL_TXQ_TXDESCINT_ENABLE
;
610 unit
->hal
->ah_setupTxQueue(unit
->hal
, HAL_TX_QUEUE_DATA
, &queue_info
);
611 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->tx_queue_no
);
613 /* Set up management frame TX queue */
615 queue_info
.tqi_aifs
= HAL_TXQ_USEDEFAULT
;
616 queue_info
.tqi_cwmin
= HAL_TXQ_USEDEFAULT
;
617 queue_info
.tqi_cwmax
= HAL_TXQ_USEDEFAULT
;
618 queue_info
.tqi_qflags
=
619 HAL_TXQ_TXEOLINT_ENABLE
| HAL_TXQ_TXDESCINT_ENABLE
;
621 unit
->mgmt_queue_no
=
622 unit
->hal
->ah_setupTxQueue(unit
->hal
, HAL_TX_QUEUE_DATA
, &queue_info
);
623 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->mgmt_queue_no
);
625 /* Find out hardware encryption capabilities */
627 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
628 HAL_CIPHER_WEP
, NULL
) == HAL_OK
)
629 unit
->flags
|= UNITF_HARDWEP
;
630 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
631 HAL_CIPHER_TKIP
, NULL
) == HAL_OK
)
632 unit
->flags
|= UNITF_HARDTKIP
;
634 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
635 HAL_CIPHER_MIC
, NULL
) == HAL_OK
)
637 if(unit
->hal
->ah_setCapability(unit
->hal
, HAL_CAP_TKIP_MIC
,
640 unit
->flags
|= UNITF_HARDMIC
;
643 if(unit
->hal
->ah_setCapability(unit
->hal
, HAL_CAP_TKIP_MIC
,
646 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_TKIP_SPLIT
, 0,
648 unit
->flags
|= UNITF_SPLITMIC
;
649 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
650 HAL_CIPHER_AES_OCB
, NULL
) == HAL_OK
)
651 unit
->flags
|= UNITF_HARDAESOCB
;
652 if(unit
->hal
->ah_getCapability(unit
->hal
, HAL_CAP_CIPHER
,
653 HAL_CIPHER_AES_CCM
, NULL
) == HAL_OK
)
654 unit
->flags
|= UNITF_HARDCCMP
;
658 unit
->iv_sizes
[S2ENC_WEP
] = IV_SIZE
;
659 unit
->iv_sizes
[S2ENC_TKIP
] = EIV_SIZE
;
660 unit
->iv_sizes
[S2ENC_CCMP
] = EIV_SIZE
;
662 /* Set encryption functions */
664 unit
->fragment_encrypt_functions
[S2ENC_NONE
] = WriteClearFragment
;
666 if((unit
->flags
& UNITF_HARDWEP
) != 0)
667 unit
->fragment_encrypt_functions
[S2ENC_WEP
] = WriteWEPFragment
;
669 unit
->fragment_encrypt_functions
[S2ENC_WEP
] = EncryptWEPFragment
;
671 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
672 unit
->fragment_encrypt_functions
[S2ENC_TKIP
] = WriteTKIPFragment
;
674 unit
->fragment_encrypt_functions
[S2ENC_TKIP
] = EncryptTKIPFragment
;
676 if((unit
->flags
& UNITF_HARDCCMP
) != 0)
677 unit
->fragment_encrypt_functions
[S2ENC_CCMP
] = WriteCCMPFragment
;
679 unit
->fragment_encrypt_functions
[S2ENC_CCMP
] = EncryptCCMPFragment
;
681 /* Set decryption functions */
683 unit
->fragment_decrypt_functions
[S2ENC_NONE
] = ReadClearFragment
;
685 if((unit
->flags
& UNITF_HARDWEP
) != 0)
686 unit
->fragment_decrypt_functions
[S2ENC_WEP
] = ReadWEPFragment
;
688 unit
->fragment_decrypt_functions
[S2ENC_WEP
] = DecryptWEPFragment
;
690 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
691 unit
->fragment_decrypt_functions
[S2ENC_TKIP
] = ReadTKIPFragment
;
693 unit
->fragment_decrypt_functions
[S2ENC_TKIP
] = DecryptTKIPFragment
;
695 if((unit
->flags
& UNITF_HARDCCMP
) != 0)
696 unit
->fragment_decrypt_functions
[S2ENC_CCMP
] = ReadCCMPFragment
;
698 unit
->fragment_decrypt_functions
[S2ENC_CCMP
] = DecryptCCMPFragment
;
707 /****i* atheros5000.device/ConfigureAdapter ********************************
710 * ConfigureAdapter -- Set up card for transmission/reception.
713 * ConfigureAdapter(unit)
715 * VOID ConfigureAdapter(struct DevUnit *);
717 ****************************************************************************
721 VOID
ConfigureAdapter(struct DevUnit
*unit
, struct DevBase
*base
)
723 UWORD i
, j
, key_length
, hal_band
, key_type
;
724 const struct KeyUnion
*keys
;
725 HAL_CHANNEL
*channel
= unit
->channels
, *ch
;
726 ULONG freq
= 2407 + unit
->channel
* 5;
730 const HAL_RATE_TABLE
*rate_table
;
732 /* Get band-specific parameters */
734 if(unit
->band
== S2BAND_G
)
736 hal_band
= HAL_MODE_11G
;
737 unit
->band_mask
= CHANNEL_G
;
738 unit
->tx_rates
= g_retry_rates
;
739 unit
->mgmt_rate
= G_MGMT_RATE
;
741 else if(unit
->band
== S2BAND_B
)
743 hal_band
= HAL_MODE_11B
;
744 unit
->band_mask
= CHANNEL_B
;
745 unit
->tx_rates
= b_retry_rates
;
746 unit
->mgmt_rate
= B_MGMT_RATE
;
748 unit
->rate_table
= unit
->hal
->ah_getRateTable(unit
->hal
, hal_band
);
750 /* Find rate codes to match our optimal and retry rates */
752 rate_table
= unit
->rate_table
;
753 for(i
= 0; i
< rate_table
->rateCount
; i
++)
755 for(j
= 0; j
< 4; j
++)
757 if(rate_table
->info
[i
].rateKbps
== unit
->tx_rates
[j
])
759 unit
->tx_rate_codes
[j
] = rate_table
->info
[i
].rateCode
;
760 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
761 unit
->tx_rate_codes
[j
] |= rate_table
->info
[i
].shortPreamble
;
764 if(rate_table
->info
[i
].rateKbps
== unit
->mgmt_rate
)
766 unit
->mgmt_rate_code
= rate_table
->info
[i
].rateCode
;
767 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
768 unit
->mgmt_rate_code
|= rate_table
->info
[i
].shortPreamble
;
772 /* Find a channel that matches requirements */
774 for(i
= 0, ch
= unit
->channels
; i
< unit
->channel_count
; i
++, ch
++)
776 if(ch
->channel
== freq
777 && (ch
->channelFlags
& unit
->band_mask
) == unit
->band_mask
)
781 /* Stop the transceiver if we're already online */
783 if((unit
->flags
& UNITF_ONLINE
) != 0)
785 /* Disable frame transmission */
787 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
788 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
789 unit
->hal
->ah_setRxFilter(unit
->hal
, 0);
792 /* Disable frame reception */
794 unit
->hal
->ah_stopPcuReceive(unit
->hal
);
795 unit
->hal
->ah_stopDmaReceive(unit
->hal
);
797 /* Disable interrupts */
799 unit
->hal
->ah_setInterrupts(unit
->hal
, 0);
802 /* Calculate RX filter mask */
804 unit
->filter_mask
= HAL_RX_FILTER_UCAST
| HAL_RX_FILTER_MCAST
805 | HAL_RX_FILTER_BCAST
;
806 if((unit
->flags
& UNITF_PROM
) != 0)
807 unit
->filter_mask
|= HAL_RX_FILTER_PROM
;
808 if(unit
->mode
!= S2PORT_MANAGED
)
809 unit
->filter_mask
|= HAL_RX_FILTER_PROBEREQ
;
813 unit
->hal
->ah_reset(unit
->hal
, HAL_M_STA
, channel
, FALSE
, &status
);
815 /* Set MAC address and miscellaneous wireless parameters */
817 unit
->hal
->ah_setMacAddress(unit
->hal
, unit
->address
);
818 unit
->hal
->ah_setPCUConfig(unit
->hal
);
819 SetMulticast(unit
, base
);
820 unit
->hal
->ah_setDefAntenna(unit
->hal
, unit
->antenna
);
821 unit
->hal
->ah_perCalibration(unit
->hal
, channel
, &iq_done
);
822 unit
->hal
->ah_setTxPowerLimit(unit
->hal
, TX_POWER
);
824 /* Set association ID */
826 unit
->hal
->ah_writeAssocid(unit
->hal
, unit
->bssid
, unit
->assoc_id
);
828 /* Put on a reassuring light */
830 unit
->hal
->ah_setLedState(unit
->hal
, HAL_LED_RUN
);
832 /* Set or clear default encryption keys where appropriate */
835 for(i
= 0; i
< WIFI_KEYCOUNT
; i
++)
837 key_type
= unit
->keys
[i
].type
;
838 if(key_type
<= S2ENC_WEP
839 || key_type
== S2ENC_TKIP
&& (unit
->flags
& UNITF_HARDTKIP
) == 0
840 || key_type
== S2ENC_CCMP
&& (unit
->flags
& UNITF_HARDCCMP
) == 0)
842 if(key_type
== S2ENC_WEP
&& (unit
->flags
& UNITF_HARDWEP
) != 0)
844 hal_key
.kv_type
= HAL_CIPHER_WEP
;
845 key_length
= keys
[i
].u
.wep
.length
;
846 CopyMem(keys
[i
].u
.wep
.key
, hal_key
.kv_val
, key_length
);
850 hal_key
.kv_type
= HAL_CIPHER_CLR
;
853 hal_key
.kv_len
= key_length
;
854 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, i
, &hal_key
,
859 /* Set pointer to RX ring */
861 unit
->hal
->ah_setRxDP(unit
->hal
,
862 unit
->rx_descs_p
+ unit
->rx_slot
* sizeof(struct ath_desc
));
864 /* Restart the transceiver if we're already online */
866 if((unit
->flags
& UNITF_ONLINE
) != 0)
868 /* Enable interrupts */
870 unit
->hal
->ah_setInterrupts(unit
->hal
, INT_MASK
);
872 /* Enable frame reception */
874 unit
->hal
->ah_enableReceive(unit
->hal
);
875 unit
->hal
->ah_setRxFilter(unit
->hal
, unit
->filter_mask
);
876 unit
->hal
->ah_startPcuReceive(unit
->hal
);
879 /* Reset TX queues */
881 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->tx_queue_no
);
882 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->mgmt_queue_no
);
893 /****i* atheros5000.device/GoOnline ****************************************
896 * GoOnline -- Enable transmission/reception.
901 * VOID GoOnline(struct DevUnit *);
903 ****************************************************************************
907 VOID
GoOnline(struct DevUnit
*unit
, struct DevBase
*base
)
909 /* Enable interrupts */
911 unit
->flags
|= UNITF_ONLINE
;
912 unit
->hal
->ah_setInterrupts(unit
->hal
, INT_MASK
);
914 /* Enable frame reception */
916 unit
->hal
->ah_enableReceive(unit
->hal
);
917 unit
->hal
->ah_setRxFilter(unit
->hal
, unit
->filter_mask
);
918 unit
->hal
->ah_startPcuReceive(unit
->hal
);
921 /* Reset TX queues */
923 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->tx_queue_no
);
924 unit
->hal
->ah_resetTxQueue(unit
->hal
, unit
->mgmt_queue_no
);
927 /* Record start time and report Online event */
929 GetSysTime(&unit
->stats
.LastStart
);
930 ReportEvents(unit
, S2EVENT_ONLINE
, base
);
937 /****i* atheros5000.device/GoOffline ***************************************
940 * GoOffline -- Disable transmission/reception.
945 * VOID GoOffline(struct DevUnit *);
955 ****************************************************************************
959 VOID
GoOffline(struct DevUnit
*unit
, struct DevBase
*base
)
961 unit
->flags
&= ~UNITF_ONLINE
;
962 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
964 /* Disable frame transmission */
966 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
967 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
969 /* Disable frame reception */
971 unit
->hal
->ah_stopPcuReceive(unit
->hal
);
972 unit
->hal
->ah_stopDmaReceive(unit
->hal
);
973 unit
->hal
->ah_setRxFilter(unit
->hal
, 0);
976 /* Stop interrupts */
978 unit
->hal
->ah_setInterrupts(unit
->hal
, 0);
980 /* Update statistics */
982 UpdateStats(unit
, base
);
985 /* Flush pending read and write requests */
987 FlushUnit(unit
, MGMT_QUEUE
, S2ERR_OUTOFSERVICE
, base
);
989 /* Report Offline event and return */
991 ReportEvents(unit
, S2EVENT_OFFLINE
, base
);
997 /****i* atheros5000.device/SetOptions **************************************
1000 * SetOptions -- Set and use interface options.
1003 * reconfigure = SetOptions(unit, tag_list)
1005 * BOOL SetOptions(struct DevUnit *, struct TagItem *);
1007 ****************************************************************************
1011 BOOL
SetOptions(struct DevUnit
*unit
, const struct TagItem
*tag_list
,
1012 struct DevBase
*base
)
1014 struct TagItem
*tag_item
, *tlist
= (struct TagItem
*)tag_list
;
1015 BOOL reconfigure
= TRUE
;
1017 while((tag_item
= NextTagItem(&tlist
)) != NULL
)
1019 switch(tag_item
->ti_Tag
)
1022 ReportEvents(unit
, S2EVENT_CONNECT
, base
);
1026 CopyMem((APTR
)tag_item
->ti_Data
, unit
->bssid
, ETH_ADDRESSSIZE
);
1029 case S2INFO_AssocID
:
1030 unit
->assoc_id
= tag_item
->ti_Data
;
1033 case S2INFO_Capabilities
:
1034 unit
->capabilities
= tag_item
->ti_Data
;
1035 if((unit
->capabilities
& (1 << 5)) != 0)
1036 unit
->flags
|= UNITF_SHORTPREAMBLE
;
1038 unit
->flags
&= ~UNITF_SHORTPREAMBLE
;
1041 case S2INFO_DefaultKeyNo
:
1042 unit
->tx_key_no
= tag_item
->ti_Data
;
1045 case S2INFO_PortType
:
1046 unit
->mode
= tag_item
->ti_Data
;
1049 case S2INFO_Channel
:
1050 if(tag_item
->ti_Data
!= unit
->channel
)
1052 unit
->channel
= tag_item
->ti_Data
;
1058 if(tag_item
->ti_Data
!= unit
->band
)
1060 unit
->band
= tag_item
->ti_Data
;
1072 /****i* atheros5000.device/SetKey ******************************************
1075 * SetKey -- Set an encryption key.
1078 * SetKey(unit, index, type, key, key_length,
1081 * VOID SetKey(struct DevUnit *, ULONG, ULONG, UBYTE *, ULONG,
1084 ****************************************************************************
1088 VOID
SetKey(struct DevUnit
*unit
, ULONG index
, ULONG type
, const UBYTE
*key
,
1089 ULONG key_length
, const UBYTE
*rx_counter
, struct DevBase
*base
)
1091 struct KeyUnion
*slot
;
1092 struct EClockVal eclock
;
1097 slot
= &unit
->keys
[index
];
1101 CopyMem(key
, slot
->u
.wep
.key
, key_length
);
1102 slot
->u
.wep
.length
= key_length
;
1104 if((unit
->flags
& UNITF_HARDWEP
) == 0)
1106 /* Create a reasonably random IV */
1108 ReadEClock(&eclock
);
1109 slot
->u
.wep
.tx_iv
= FastRand(eclock
.ev_lo
^ eclock
.ev_hi
);
1115 CopyMem(key
, slot
->u
.tkip
.key
, 16);
1116 CopyMem(key
+ 16, slot
->u
.tkip
.tx_mic_key
, MIC_SIZE
);
1117 CopyMem(key
+ 24, slot
->u
.tkip
.rx_mic_key
, MIC_SIZE
);
1118 slot
->u
.tkip
.tx_iv_low
= 0;
1119 slot
->u
.tkip
.tx_iv_high
= 0;
1120 slot
->u
.tkip
.rx_iv_low
= LEWord(*(UWORD
*)rx_counter
);
1121 slot
->u
.tkip
.rx_iv_high
= LELong(*(ULONG
*)(rx_counter
+ 2));
1122 slot
->u
.tkip
.tx_ttak_set
= FALSE
;
1123 slot
->u
.tkip
.rx_ttak_set
= FALSE
;
1125 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
1127 // TO DO: Wait for TX queue to empty
1128 /* Load parameters for hardware encryption */
1130 hal_key
.kv_type
= HAL_CIPHER_TKIP
;
1131 hal_key
.kv_len
= 16;
1132 CopyMem(slot
->u
.tkip
.key
, hal_key
.kv_val
, 16);
1134 CopyMem(slot
->u
.tkip
.tx_mic_key
, hal_key
.kv_mic
, MIC_SIZE
);
1135 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
, &hal_key
,
1136 unit
->bssid
, FALSE
);
1137 CopyMem(slot
->u
.tkip
.rx_mic_key
, hal_key
.kv_mic
, MIC_SIZE
);
1138 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
+ 32, &hal_key
,
1139 unit
->bssid
, FALSE
);
1143 /* Convert key to native endianness */
1145 for(i
= 0; i
< 8; i
++)
1146 slot
->u
.tkip
.key
[i
] = LEWord(slot
->u
.tkip
.key
[i
]);
1152 CopyMem(key
, slot
->u
.ccmp
.key
, 16);
1153 slot
->u
.ccmp
.tx_iv_low
= 0;
1154 slot
->u
.ccmp
.tx_iv_high
= 0;
1155 slot
->u
.ccmp
.rx_iv_low
= LEWord(*(UWORD
*)rx_counter
);
1156 slot
->u
.ccmp
.rx_iv_high
= LELong(*(ULONG
*)(rx_counter
+ 2));
1157 slot
->u
.ccmp
.stream_set
= FALSE
;
1159 if((unit
->flags
& UNITF_HARDCCMP
) != 0)
1161 // TO DO: Wait for TX queue to empty
1162 /* Load parameters for hardware encryption */
1164 hal_key
.kv_type
= HAL_CIPHER_AES_CCM
;
1165 hal_key
.kv_len
= 16;
1166 CopyMem(slot
->u
.ccmp
.key
, hal_key
.kv_val
, 16);
1167 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
, &hal_key
,
1168 unit
->bssid
, FALSE
);
1172 /* Update type of key in selected slot */
1182 /****i* atheros5000.device/AddMulticastRange *******************************
1188 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1190 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1192 ****************************************************************************
1196 BOOL
AddMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
1197 const UBYTE
*upper_bound
, struct DevBase
*base
)
1199 struct AddressRange
*range
;
1200 ULONG lower_bound_left
, upper_bound_left
;
1201 UWORD lower_bound_right
, upper_bound_right
;
1203 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
1204 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
1205 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
1206 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
1208 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
1209 upper_bound_left
, upper_bound_right
, base
);
1215 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1218 range
->lower_bound_left
= lower_bound_left
;
1219 range
->lower_bound_right
= lower_bound_right
;
1220 range
->upper_bound_left
= upper_bound_left
;
1221 range
->upper_bound_right
= upper_bound_right
;
1222 range
->add_count
= 1;
1225 AddTail((APTR
)&unit
->multicast_ranges
, (APTR
)range
);
1226 unit
->range_count
++;
1227 SetMulticast(unit
, base
);
1232 return range
!= NULL
;
1237 /****i* atheros5000.device/RemMulticastRange *******************************
1243 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1245 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1247 ****************************************************************************
1251 BOOL
RemMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
1252 const UBYTE
*upper_bound
, struct DevBase
*base
)
1254 struct AddressRange
*range
;
1255 ULONG lower_bound_left
, upper_bound_left
;
1256 UWORD lower_bound_right
, upper_bound_right
;
1258 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
1259 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
1260 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
1261 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
1263 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
1264 upper_bound_left
, upper_bound_right
, base
);
1268 if(--range
->add_count
== 0)
1271 Remove((APTR
)range
);
1272 unit
->range_count
--;
1273 SetMulticast(unit
, base
);
1275 FreeMem(range
, sizeof(struct AddressRange
));
1279 return range
!= NULL
;
1284 /****i* atheros5000.device/FindMulticastRange ******************************
1287 * FindMulticastRange
1290 * range = FindMulticastRange(unit, lower_bound_left,
1291 * lower_bound_right, upper_bound_left, upper_bound_right)
1293 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1294 * UWORD, ULONG, UWORD);
1296 ****************************************************************************
1300 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
1301 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
1302 UWORD upper_bound_right
, struct DevBase
*base
)
1304 struct AddressRange
*range
, *tail
;
1307 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1308 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1310 while(range
!= tail
&& !found
)
1312 if(lower_bound_left
== range
->lower_bound_left
&&
1313 lower_bound_right
== range
->lower_bound_right
&&
1314 upper_bound_left
== range
->upper_bound_left
&&
1315 upper_bound_right
== range
->upper_bound_right
)
1318 range
= (APTR
)range
->node
.mln_Succ
;
1329 /****i* atheros5000.device/SetMulticast ************************************
1335 * SetMulticast(unit)
1337 * VOID SetMulticast(struct DevUnit *);
1339 ****************************************************************************
1343 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
)
1345 unit
->hal
->ah_setMulticastFilter(unit
->hal
, 0xffffffff, 0xffffffff);
1352 /****i* atheros5000.device/FindTypeStats ***********************************
1358 * stats = FindTypeStats(unit, list,
1361 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1364 ****************************************************************************
1368 struct TypeStats
*FindTypeStats(struct DevUnit
*unit
, struct MinList
*list
,
1369 ULONG packet_type
, struct DevBase
*base
)
1371 struct TypeStats
*stats
, *tail
;
1374 stats
= (APTR
)list
->mlh_Head
;
1375 tail
= (APTR
)&list
->mlh_Tail
;
1377 while(stats
!= tail
&& !found
)
1379 if(stats
->packet_type
== packet_type
)
1382 stats
= (APTR
)stats
->node
.mln_Succ
;
1393 /****i* atheros5000.device/FlushUnit ***************************************
1399 * FlushUnit(unit, last_queue, error)
1401 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1403 ****************************************************************************
1407 VOID
FlushUnit(struct DevUnit
*unit
, UBYTE last_queue
, BYTE error
,
1408 struct DevBase
*base
)
1410 struct IORequest
*request
;
1412 struct Opener
*opener
, *tail
;
1414 /* Abort queued requests */
1416 for(i
= 0; i
<= last_queue
; i
++)
1418 while((request
= (APTR
)GetMsg(unit
->request_ports
[i
])) != NULL
)
1420 request
->io_Error
= IOERR_ABORTED
;
1421 ReplyMsg((APTR
)request
);
1426 opener
= (APTR
)unit
->openers
.mlh_Head
;
1427 tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1429 /* Flush every opener's read queues */
1431 while(opener
!= tail
)
1433 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1435 request
->io_Error
= error
;
1436 ReplyMsg((APTR
)request
);
1438 while((request
= (APTR
)GetMsg(&opener
->mgmt_port
)) != NULL
)
1440 request
->io_Error
= error
;
1441 ReplyMsg((APTR
)request
);
1443 opener
= (APTR
)opener
->node
.mln_Succ
;
1447 opener
= request
->ios2_BufferManagement
;
1448 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1450 request
->io_Error
= IOERR_ABORTED
;
1451 ReplyMsg((APTR
)request
);
1453 while((request
= (APTR
)GetMsg(&opener
->mgmt_port
)) != NULL
)
1455 request
->io_Error
= IOERR_ABORTED
;
1456 ReplyMsg((APTR
)request
);
1467 /****i* atheros5000.device/StatusInt ***************************************
1473 * finished = StatusInt(unit)
1475 * BOOL StatusInt(struct DevUnit *);
1485 ****************************************************************************
1487 * int_code is really in A5, but GCC 2.95.3 doesn't seem able to handle that.
1488 * Since we don't use this parameter, we can lie.
1492 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
1494 struct DevBase
*base
;
1495 uint32_t queue_mask
;
1496 HAL_INT ints
, int_mask
;
1498 base
= unit
->device
;
1499 int_mask
= unit
->hal
->ah_getInterrupts(unit
->hal
);
1501 if(!unit
->hal
->ah_isInterruptPending(unit
->hal
)) return FALSE
;
1505 if(unit
->hal
->ah_getPendingInterrupts(unit
->hal
, &ints
))
1507 if((ints
& HAL_INT_TX
) != 0)
1509 int_mask
&= ~(HAL_INT_TX
| HAL_INT_TXDESC
);
1510 queue_mask
= 1 << unit
->tx_queue_no
| 1 << unit
->mgmt_queue_no
;
1511 unit
->hal
->ah_getTxIntrQueue(unit
->hal
, &queue_mask
);
1512 if((queue_mask
& 1 << unit
->tx_queue_no
) != 0)
1513 Cause(&unit
->tx_end_int
);
1514 if((queue_mask
& 1 << unit
->mgmt_queue_no
) != 0)
1515 Cause(&unit
->mgmt_end_int
);
1517 if((ints
& HAL_INT_RX
) != 0)
1519 int_mask
&= ~(HAL_INT_RX
| HAL_INT_RXEOL
);
1520 Cause(&unit
->rx_int
);
1525 int_mask
= INT_MASK
;
1527 // unit->hal->ah_setInterrupts(unit->hal, int_mask))
1534 /****i* atheros5000.device/RXInt *******************************************
1537 * RXInt -- Soft interrupt for packet reception.
1542 * VOID RXInt(struct DevUnit *);
1547 * unit - A unit of this device.
1552 ****************************************************************************
1556 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
1558 UWORD ieee_length
, frame_control
, frame_type
, slot
, next_slot
,
1559 encryption
, key_no
, buffer_no
, old_length
;
1560 struct DevBase
*base
;
1563 struct ath_desc
*rx_desc
, *next_desc
;
1564 ULONG dma_size
, rx_desc_p
;
1565 UBYTE
*buffer
, *p
, *frame
, *data
, *snap_frame
, *source
;
1566 struct ath_rx_status status
;
1568 base
= unit
->device
;
1569 slot
= unit
->rx_slot
;
1570 rx_desc
= unit
->rx_descs
+ slot
;
1571 rx_desc_p
= unit
->rx_descs_p
+ slot
* sizeof(struct ath_desc
);
1572 next_slot
= (slot
+ 1) % RX_SLOT_COUNT
;
1573 next_desc
= unit
->rx_descs
+ next_slot
;
1575 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
1576 CachePostDMA(unit
->rx_descs
, &dma_size
, 0);
1578 while(unit
->hal
->ah_procRxDesc(unit
->hal
, rx_desc
, rx_desc_p
, next_desc
,
1579 unit
->hal
->ah_getTsf64(unit
->hal
), &status
) != HAL_EINPROGRESS
)
1582 buffer
= unit
->rx_buffers
[slot
];
1584 dma_size
= FRAME_BUFFER_SIZE
;
1585 CachePostDMA(buffer
, &dma_size
, 0);
1587 if(status
.rs_status
== 0
1588 && status
.rs_datalen
>= WIFI_FRM_DATA
+ FCS_SIZE
)
1590 /* Get fragment info */
1593 ieee_length
= status
.rs_datalen
- FCS_SIZE
- WIFI_FRM_DATA
;
1594 data
= frame
+ WIFI_FRM_DATA
;
1596 LEWord(*(UWORD
*)(frame
+ WIFI_FRM_CONTROL
));
1598 /* Get buffer to store fragment in */
1600 frag_no
= LEWord(*(UWORD
*)(frame
+ WIFI_FRM_SEQCONTROL
));
1601 if(unit
->mode
== S2PORT_ADHOC
)
1602 source
= frame
+ WIFI_FRM_ADDRESS2
;
1604 source
= frame
+ WIFI_FRM_ADDRESS3
;
1605 snap_frame
= GetRXBuffer(unit
, source
, frag_no
, &buffer_no
, base
);
1607 /* Get location to put new data */
1609 if(snap_frame
!= NULL
)
1611 if((frag_no
& 0xf ) > 0)
1613 BEWord(*(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
));
1616 /* Create new 802.3 header */
1618 CopyMem(frame
+ WIFI_FRM_ADDRESS1
, snap_frame
,
1620 CopyMem(source
, snap_frame
+ ETH_PACKET_SOURCE
,
1624 p
= snap_frame
+ 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 frame
, data
, &ieee_length
, p
, base
);
1642 /* Update length in frame being built with current fragment, or
1643 increment bad frame counter if fragment is bad */
1647 ieee_length
+= old_length
;
1648 *(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
) =
1649 MakeBEWord(ieee_length
);
1652 unit
->stats
.BadData
++;
1654 /* If all fragments have arrived, process the complete frame */
1656 if((frame_control
& WIFI_FRM_CONTROLF_MOREFRAGS
) == 0)
1660 /* Decrypt complete frame if necessary */
1662 data
= snap_frame
+ ETH_HEADERSIZE
;
1663 if(encryption
== S2ENC_TKIP
)
1664 // && (unit->flags & UNITF_HARDTKIP) == 0)
1665 // && (unit->flags & UNITF_HARDMIC) == 0)
1667 is_good
= TKIPDecryptFrame(unit
, snap_frame
, data
,
1668 ieee_length
, data
, key_no
, base
);
1669 ieee_length
-= MIC_SIZE
;
1670 *(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
) =
1671 MakeBEWord(ieee_length
);
1673 unit
->stats
.BadData
++;
1679 /* Get frame's 802.11 type and subtype */
1681 frame_type
= (frame_control
& WIFI_FRM_CONTROLF_TYPE
)
1682 >> WIFI_FRM_CONTROLB_TYPE
;
1684 /* If it's a management frame, process it separately;
1685 otherwise distribute it to clients after filtering */
1687 if(frame_type
== WIFI_FRMTYPE_MGMT
)
1689 DistributeMgmtFrame(unit
, frame
, status
.rs_datalen
- 4,
1692 else if(AddressFilter(unit
, snap_frame
+ ETH_PACKET_DEST
,
1695 unit
->stats
.PacketsReceived
++;
1696 DistributeRXPacket(unit
, snap_frame
, base
);
1701 /* Mark fragment buffer as unused for next time */
1703 unit
->rx_fragment_nos
[buffer_no
] = -1;
1706 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_RX
, base
);
1715 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
,
1719 /* Prepare descriptor for next time */
1721 unit
->hal
->ah_setupRxDesc(unit
->hal
, rx_desc
, FRAME_BUFFER_SIZE
,
1724 dma_size
= FRAME_BUFFER_SIZE
;
1725 CachePreDMA(buffer
, &dma_size
, 0);
1727 /* Get next descriptor */
1730 rx_desc
= next_desc
;
1731 rx_desc_p
= unit
->rx_descs_p
+ slot
* sizeof(struct ath_desc
);
1732 next_slot
= (slot
+ 1) % RX_SLOT_COUNT
;
1733 next_desc
= unit
->rx_descs
+ next_slot
;
1736 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
1737 CachePreDMA(unit
->rx_descs
, &dma_size
, 0);
1739 unit
->rx_slot
= slot
;
1740 // TO DO: unstall reception?
1742 /* Re-enable RX interrupts */
1746 unit
->hal
->ah_setInterrupts(unit
->hal
,
1747 unit
->hal
->ah_getInterrupts(unit
->hal
) | HAL_INT_RX
| HAL_INT_RXEOL
);
1756 /****i* atheros5000.device/GetRXBuffer *************************************
1759 * GetRXBuffer -- Find an appropriate RX frame buffer to use.
1762 * buffer = GetRXBuffer(unit, address, frag_no)
1764 * UBYTE *GetRXBuffer(struct DevUnit *, UBYTE *, UWORD);
1766 ****************************************************************************
1770 static UBYTE
*GetRXBuffer(struct DevUnit
*unit
, const UBYTE
*address
,
1771 UWORD frag_no
, UWORD
*buffer_no
, struct DevBase
*base
)
1778 buffer
= unit
->rx_frames
;
1779 for(i
= 0, found
= FALSE
; i
< FRAME_BUFFER_COUNT
* 2 && !found
; i
++)
1781 /* Throw away old buffer contents if we didn't find a free slot the
1782 first time around */
1784 if(i
>= FRAME_BUFFER_COUNT
)
1785 unit
->rx_fragment_nos
[i
% FRAME_BUFFER_COUNT
] = -1;
1787 /* For a frame's first fragment, find an empty slot; for subsequent
1788 fragments, find a slot with matching source address */
1790 n
= unit
->rx_fragment_nos
[i
% FRAME_BUFFER_COUNT
];
1791 if(n
== -1 && (frag_no
& 0xf) == 0
1792 || *((ULONG
*)(buffer
+ ETH_PACKET_SOURCE
))
1793 == *((ULONG
*)(address
))
1794 && *((UWORD
*)(buffer
+ ETH_PACKET_SOURCE
+ 4))
1795 == *((UWORD
*)(address
+ 4)))
1799 unit
->rx_fragment_nos
[i
% FRAME_BUFFER_COUNT
] = frag_no
;
1803 buffer
+= FRAME_BUFFER_SIZE
;
1814 /****i* atheros5000.device/DistributeRXPacket ******************************
1817 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1820 * DistributeRXPacket(unit, frame)
1822 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1824 ****************************************************************************
1828 static VOID
DistributeRXPacket(struct DevUnit
*unit
, UBYTE
*frame
,
1829 struct DevBase
*base
)
1831 UWORD packet_size
, ieee_length
;
1832 BOOL is_orphan
= TRUE
, accepted
, is_snap
= FALSE
;
1835 const UBYTE
*template = snap_template
;
1836 struct IOSana2Req
*request
, *request_tail
;
1837 struct Opener
*opener
, *opener_tail
;
1838 struct TypeStats
*tracker
;
1840 ieee_length
= BEWord(*(UWORD
*)(frame
+ ETH_PACKET_IEEELEN
));
1841 packet_size
= ETH_HEADERSIZE
+ ieee_length
;
1842 if(ieee_length
>= SNAP_HEADERSIZE
)
1843 is_snap
= *(const ULONG
*)(frame
+ ETH_PACKET_DATA
)
1844 == *(const ULONG
*)template;
1846 /* De-encapsulate SNAP packets and get packet type */
1850 buffer
= unit
->rx_buffer
;
1851 packet_size
-= SNAP_HEADERSIZE
;
1852 CopyMem(frame
, buffer
, ETH_PACKET_TYPE
);
1853 CopyMem(frame
+ ETH_HEADERSIZE
+ SNAP_FRM_TYPE
,
1854 buffer
+ ETH_PACKET_TYPE
, packet_size
- ETH_PACKET_TYPE
);
1859 packet_type
= BEWord(*((UWORD
*)(buffer
+ ETH_PACKET_TYPE
)));
1861 if(packet_size
<= ETH_MAXPACKETSIZE
)
1863 /* Offer packet to every opener */
1865 opener
= (APTR
)unit
->openers
.mlh_Head
;
1866 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1868 while(opener
!= opener_tail
)
1870 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
1871 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
1874 /* Offer packet to each request until it's accepted */
1876 while(request
!= request_tail
&& !accepted
)
1878 if(request
->ios2_PacketType
== packet_type
)
1880 CopyPacket(unit
, request
, packet_size
, packet_type
,
1885 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1890 opener
= (APTR
)opener
->node
.mln_Succ
;
1893 /* If packet was unwanted, give it to S2_READORPHAN request */
1897 unit
->stats
.UnknownTypesReceived
++;
1898 if(!IsMsgPortEmpty(unit
->request_ports
[ADOPT_QUEUE
]))
1901 (APTR
)unit
->request_ports
[ADOPT_QUEUE
]->
1902 mp_MsgList
.lh_Head
, packet_size
, packet_type
, buffer
,
1907 /* Update remaining statistics */
1909 if(packet_type
<= ETH_MTU
)
1910 packet_type
= ETH_MTU
;
1912 FindTypeStats(unit
, &unit
->type_trackers
, packet_type
, base
);
1915 tracker
->stats
.PacketsReceived
++;
1916 tracker
->stats
.BytesReceived
+= packet_size
;
1920 unit
->stats
.BadData
++;
1927 /****i* atheros5000.device/CopyPacket **************************************
1930 * CopyPacket -- Copy packet to client's buffer.
1933 * CopyPacket(unit, request, packet_size, packet_type,
1936 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1939 ****************************************************************************
1943 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
1944 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
1945 struct DevBase
*base
)
1947 struct Opener
*opener
;
1948 BOOL filtered
= FALSE
;
1950 /* Set multicast and broadcast flags */
1952 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
1953 if((*((ULONG
*)(buffer
+ ETH_PACKET_DEST
)) == 0xffffffff) &&
1954 (*((UWORD
*)(buffer
+ ETH_PACKET_DEST
+ 4)) == 0xffff))
1955 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1956 else if((buffer
[ETH_PACKET_DEST
] & 0x1) != 0)
1957 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1959 /* Set source and destination addresses and packet type */
1961 CopyMem(buffer
+ ETH_PACKET_SOURCE
, request
->ios2_SrcAddr
,
1963 CopyMem(buffer
+ ETH_PACKET_DEST
, request
->ios2_DstAddr
,
1965 request
->ios2_PacketType
= packet_type
;
1967 /* Adjust for cooked packet request */
1969 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1971 packet_size
-= ETH_PACKET_DATA
;
1972 buffer
+= ETH_PACKET_DATA
;
1976 packet_size
+= 4; /* Needed for Shapeshifter & Fusion? */
1978 request
->ios2_DataLength
= packet_size
;
1982 opener
= request
->ios2_BufferManagement
;
1983 if(request
->ios2_Req
.io_Command
== CMD_READ
&&
1984 opener
->filter_hook
!= NULL
)
1985 if(!CallHookPkt(opener
->filter_hook
, request
, buffer
))
1990 /* Copy packet into opener's buffer and reply packet */
1992 if(!opener
->rx_function(request
->ios2_Data
, buffer
, packet_size
))
1994 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1995 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1997 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
2000 Remove((APTR
)request
);
2001 ReplyMsg((APTR
)request
);
2009 /****i* atheros5000.device/AddressFilter ***********************************
2012 * AddressFilter -- Determine if an RX packet should be accepted.
2015 * accept = AddressFilter(unit, address)
2017 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
2019 ****************************************************************************
2023 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
2024 struct DevBase
*base
)
2026 struct AddressRange
*range
, *tail
;
2029 UWORD address_right
;
2031 /* Check whether address is unicast/broadcast or multicast */
2033 address_left
= BELong(*((ULONG
*)address
));
2034 address_right
= BEWord(*((UWORD
*)(address
+ 4)));
2036 if(((address_left
& 0x01000000) != 0) &&
2037 !((address_left
== 0xffffffff) && (address_right
== 0xffff)))
2039 /* Check if this multicast address is wanted */
2041 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
2042 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
2045 while((range
!= tail
) && !accept
)
2047 if((address_left
> range
->lower_bound_left
||
2048 address_left
== range
->lower_bound_left
&&
2049 address_right
>= range
->lower_bound_right
) &&
2050 (address_left
< range
->upper_bound_left
||
2051 address_left
== range
->upper_bound_left
&&
2052 address_right
<= range
->upper_bound_right
))
2054 range
= (APTR
)range
->node
.mln_Succ
;
2058 unit
->special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
2066 /****i* atheros5000.device/DistributeMgmtFrame *****************************
2069 * DistributeMgmtFrame -- Send a management frame to clients.
2072 * DistributeMgmtFrame(unit, frame, frame_size)
2074 * VOID DistributeMgmtFrame(struct DevUnit *, UBYTE *, UWORD);
2076 ****************************************************************************
2080 static VOID
DistributeMgmtFrame(struct DevUnit
*unit
, UBYTE
*frame
,
2081 UWORD frame_size
, struct DevBase
*base
)
2083 struct IOSana2Req
*request
;
2084 struct Opener
*opener
, *opener_tail
;
2086 /* Send packet to every opener */
2088 opener
= (APTR
)unit
->openers
.mlh_Head
;
2089 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
2091 while(opener
!= opener_tail
)
2093 request
= (APTR
)RemHead(&opener
->mgmt_port
.mp_MsgList
);
2097 /* Copy packet into opener's buffer and reply packet */
2099 if(frame_size
<= request
->ios2_DataLength
)
2101 CopyMem(frame
, request
->ios2_Data
, frame_size
);
2102 request
->ios2_DataLength
= frame_size
;
2106 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
2107 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
2109 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
2112 ReplyMsg((APTR
)request
);
2114 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
2117 opener
= (APTR
)opener
->node
.mln_Succ
;
2125 /****i* atheros5000.device/TXInt *******************************************
2128 * TXInt -- Soft interrupt for packet transmission.
2133 * VOID TXInt(struct DevUnit *);
2138 * unit - A unit of this device.
2143 ****************************************************************************
2147 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
2149 struct DevBase
*base
;
2150 UWORD i
, frame_size
, data_size
, packet_type
, body_size
, slot
, new_slot
,
2151 last_slot
, encryption
, subtype
, duration
;
2152 UBYTE
*buffer
, *q
, *plaintext
, *ciphertext
, *frame
,
2153 mic_header
[ETH_ADDRESSSIZE
* 2];
2154 const UBYTE
*p
, *dest
, *source
;
2155 struct IOSana2Req
*request
;
2156 BOOL proceed
= TRUE
, is_ieee
;
2157 struct Opener
*opener
;
2158 ULONG wire_error
, dma_size
;
2159 struct ath_desc
*tx_desc
, *last_desc
;
2160 UBYTE
*(*dma_tx_function
)(REG(a0
, APTR
));
2162 struct MsgPort
*port
;
2163 struct TypeStats
*tracker
;
2164 const HAL_RATE_TABLE
*rate_table
;
2166 base
= unit
->device
;
2167 port
= unit
->request_ports
[WRITE_QUEUE
];
2168 rate_table
= unit
->rate_table
;
2170 while(proceed
&& (!IsMsgPortEmpty(port
)))
2172 slot
= unit
->tx_in_slot
;
2173 new_slot
= (slot
+ 1) % TX_SLOT_COUNT
;
2175 // if(new_slot != unit->tx_out_slot)
2176 if(slot
== unit
->tx_out_slot
) // one packet at a time
2181 /* Get request and DMA frame descriptor */
2183 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
2185 Remove((APTR
)request
);
2186 unit
->tx_requests
[slot
] = request
;
2187 tx_desc
= unit
->tx_descs
+ slot
;
2188 frame
= unit
->tx_buffers
[slot
];
2190 /* Get packet data */
2192 opener
= request
->ios2_BufferManagement
;
2193 dma_tx_function
= opener
->dma_tx_function
;
2194 if(dma_tx_function
!= NULL
)
2195 buffer
= dma_tx_function(request
->ios2_Data
);
2201 buffer
= unit
->tx_buffer
;
2202 if(!opener
->tx_function(buffer
, request
->ios2_Data
,
2203 request
->ios2_DataLength
))
2205 error
= S2ERR_NO_RESOURCES
;
2206 wire_error
= S2WERR_BUFF_ERROR
;
2208 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
2209 | S2EVENT_TX
, base
);
2215 /* Get packet type and/or length */
2217 data_size
= request
->ios2_DataLength
;
2218 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) != 0)
2220 data_size
-= ETH_PACKET_DATA
;
2221 packet_type
= BEWord(*(UWORD
*)(buffer
+ ETH_PACKET_TYPE
));
2224 packet_type
= request
->ios2_PacketType
;
2225 is_ieee
= packet_type
<= ETH_MTU
;
2227 /* Determine encryption type and frame subtype */
2231 encryption
= unit
->keys
[unit
->tx_key_no
].type
;
2236 encryption
= S2ENC_NONE
;
2240 /* Get source and destination addresses */
2242 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) != 0)
2245 source
= buffer
+ ETH_ADDRESSSIZE
;
2246 buffer
+= ETH_ADDRESSSIZE
* 2 + 2;
2250 dest
= request
->ios2_DstAddr
;
2251 source
= unit
->address
;
2254 /* Write 802.11 header */
2257 *(UWORD
*)q
= MakeLEWord(
2258 (encryption
== S2ENC_NONE
? 0 : WIFI_FRM_CONTROLF_WEP
)
2259 | (unit
->mode
== S2PORT_ADHOC
? 0 : WIFI_FRM_CONTROLF_TODS
)
2260 | subtype
<< WIFI_FRM_CONTROLB_SUBTYPE
2261 | WIFI_FRMTYPE_DATA
<< WIFI_FRM_CONTROLB_TYPE
);
2264 i
= rate_table
->rateCodeToIndex
[unit
->tx_rate_codes
[0]];
2265 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
2266 duration
= rate_table
->info
[i
].spAckDuration
;
2268 duration
= rate_table
->info
[i
].lpAckDuration
;
2269 *(UWORD
*)q
= MakeLEWord(duration
);
2272 if(unit
->mode
== S2PORT_ADHOC
)
2276 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
2279 for(i
= 0, p
= source
; i
< ETH_ADDRESSSIZE
; i
++)
2282 if(unit
->mode
== S2PORT_ADHOC
)
2286 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
2291 // TO DO: need to pad header to 4-byte boundary?
2293 /* Leave room for encryption overhead */
2296 q
+= unit
->iv_sizes
[encryption
];
2299 /* Write SNAP header */
2303 for(i
= 0, p
= snap_template
;
2304 i
< SNAP_FRM_TYPE
; i
++)
2306 *(UWORD
*)q
= MakeBEWord(packet_type
);
2308 body_size
+= SNAP_HEADERSIZE
;
2311 /* Copy data into frame */
2313 CopyMem(buffer
, q
, data_size
);
2314 body_size
+= data_size
;
2316 /* Append MIC to frame for TKIP */
2318 if(encryption
== S2ENC_TKIP
)
2320 // if((unit->flags & UNITF_HARDMIC) == 0)
2323 for(i
= 0, p
= dest
; i
< ETH_ADDRESSSIZE
; i
++)
2325 for(i
= 0, p
= source
; i
< ETH_ADDRESSSIZE
; i
++)
2327 TKIPEncryptFrame(unit
, mic_header
, plaintext
, body_size
,
2330 body_size
+= MIC_SIZE
;
2333 /* Encrypt fragment if applicable */
2335 unit
->fragment_encrypt_functions
[encryption
](unit
, frame
,
2336 plaintext
, &body_size
, ciphertext
, base
);
2338 /* Fill in DMA descriptor for packet transmission */
2340 frame_size
= WIFI_FRM_DATA
+ body_size
;
2341 tx_desc
->ds_link
= (ULONG
)(UPINT
)NULL
;
2342 unit
->hal
->ah_setupTxDesc(unit
->hal
, tx_desc
, frame_size
+ 4, // + CRC?
2343 WIFI_FRM_DATA
, HAL_PKT_TYPE_NORMAL
, TX_POWER
,
2344 ((unit
->flags
& UNITF_SLOWRETRIES
) != 0) ?
2345 unit
->tx_rate_codes
[0] : unit
->tx_rate_codes
[1],
2346 ((unit
->flags
& UNITF_SLOWRETRIES
) != 0) ? 1 : TX_TRIES
,
2347 HAL_TXKEYIX_INVALID
,
2348 HAL_ANTENNA_MIN_MODE
,
2349 HAL_TXDESC_INTREQ
| HAL_TXDESC_CLRDMASK
,
2351 if((unit
->flags
& UNITF_SLOWRETRIES
) != 0)
2352 unit
->hal
->ah_setupXTxDesc(unit
->hal
, tx_desc
,
2353 unit
->tx_rate_codes
[1], 1,
2354 unit
->tx_rate_codes
[2], 1,
2355 unit
->tx_rate_codes
[3], TX_TRIES
- 3);
2356 unit
->hal
->ah_fillTxDesc(unit
->hal
, tx_desc
, frame_size
, TRUE
, TRUE
,
2359 dma_size
= frame_size
;
2360 CachePreDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2362 /* Pass packet to adapter */
2364 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
2365 last_slot
= (slot
+ TX_SLOT_COUNT
- 1) % TX_SLOT_COUNT
;
2366 if(unit
->tx_out_slot
!= slot
)
2367 //if(unit->hal->ah_numTxPending(unit->hal, unit->tx_queue_no) > 0)
2370 unit
->tx_descs
+ last_slot
;
2371 last_desc
->ds_link
= unit
->tx_descs_p
+ slot
* sizeof(struct ath_desc
);
2372 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2373 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2377 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2378 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2379 unit
->hal
->ah_setTxDP(unit
->hal
, unit
->tx_queue_no
,
2380 unit
->tx_descs_p
+ slot
* sizeof(struct ath_desc
));
2383 unit
->hal
->ah_startTxDma(unit
->hal
, unit
->tx_queue_no
);
2384 unit
->tx_in_slot
= new_slot
;
2388 /* Reply failed request */
2390 request
->ios2_Req
.io_Error
= error
;
2391 request
->ios2_WireError
= wire_error
;
2392 ReplyMsg((APTR
)request
);
2395 /* Update statistics */
2399 unit
->stats
.PacketsSent
++;
2401 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
2402 request
->ios2_PacketType
, base
);
2405 tracker
->stats
.PacketsSent
++;
2406 tracker
->stats
.BytesSent
+= ETH_HEADERSIZE
+ data_size
;
2414 /* Don't try to keep sending packets if there's no space left */
2417 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
2419 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
2426 /****i* atheros5000.device/TXEndInt ****************************************
2429 * TXEndInt -- Clean up after a data frame has been sent.
2432 * TXEndInt(unit, int_code)
2434 * VOID TXEndInt(struct DevUnit *, APTR);
2437 * I think it's safe to assume that there will always be at least one
2438 * completed packet whenever this interrupt is called.
2440 ****************************************************************************
2444 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
),
2445 REG(a6
, APTR int_code
))
2447 UWORD frame_size
, new_out_slot
, i
;
2449 struct DevBase
*base
;
2450 struct IOSana2Req
*request
;
2452 struct TypeStats
*tracker
;
2454 /* Find out which packets have completed */
2456 base
= unit
->device
;
2457 new_out_slot
= (unit
->tx_in_slot
+ TX_SLOT_COUNT
2458 - unit
->hal
->ah_numTxPending(unit
->hal
, unit
->tx_queue_no
))
2461 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2462 CachePostDMA(unit
->tx_descs
, &dma_size
, 0);
2464 /* Retire sent packets */
2466 for(i
= unit
->tx_out_slot
; i
!= new_out_slot
;
2467 i
= (i
+ 1) % TX_SLOT_COUNT
)
2469 frame
= unit
->tx_buffers
[i
];
2470 dma_size
= FRAME_BUFFER_SIZE
;
2471 CachePostDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2473 /* Update statistics */
2475 request
= unit
->tx_requests
[i
];
2476 frame_size
= request
->ios2_DataLength
;
2477 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
2478 frame_size
+= ETH_HEADERSIZE
;
2480 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
2481 request
->ios2_PacketType
, base
);
2484 tracker
->stats
.PacketsSent
++;
2485 tracker
->stats
.BytesSent
+= frame_size
;
2490 request
->ios2_Req
.io_Error
= 0;
2491 ReplyMsg((APTR
)request
);
2494 unit
->tx_out_slot
= i
;
2496 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2497 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2499 /* Restart downloads if they had stopped */
2501 if(unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
== PA_IGNORE
)
2502 Cause(&unit
->tx_int
);
2509 /****i* atheros5000.device/MgmtTXInt ***************************************
2512 * MgmtTXInt -- Soft interrupt for management frame transmission.
2517 * VOID MgmtTXInt(struct DevUnit *);
2522 * unit - A unit of this device.
2527 ****************************************************************************
2531 static VOID
MgmtTXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
2533 struct DevBase
*base
;
2534 UWORD frame_size
, slot
, new_slot
, last_slot
, i
, duration
;
2536 struct IOSana2Req
*request
;
2537 BOOL proceed
= TRUE
, has_bssid
;
2539 struct ath_desc
*desc
, *last_desc
;
2540 struct MsgPort
*port
;
2541 const HAL_RATE_TABLE
*rate_table
;
2543 base
= unit
->device
;
2544 port
= unit
->request_ports
[MGMT_QUEUE
];
2545 rate_table
= unit
->rate_table
;
2547 while(proceed
&& (!IsMsgPortEmpty(port
)))
2549 slot
= unit
->mgmt_in_slot
;
2550 new_slot
= (slot
+ 1) % MGMT_SLOT_COUNT
;
2552 // if(new_slot != unit->mgmt_out_slot)
2553 if(slot
== unit
->mgmt_out_slot
) // one packet at a time
2555 /* Get request and DMA frame descriptor */
2557 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
2559 Remove((APTR
)request
);
2560 unit
->mgmt_requests
[slot
] = request
;
2561 desc
= unit
->mgmt_descs
+ slot
;
2562 frame
= unit
->mgmt_buffers
[slot
];
2564 /* Get packet length */
2566 frame_size
= request
->ios2_DataLength
;
2568 /* Copy frame into DMA buffer */
2570 CopyMem(request
->ios2_Data
, frame
, frame_size
);
2574 has_bssid
= ((frame
+ WIFI_FRM_ADDRESS1
)[0] & 0x1) == 0;
2575 i
= rate_table
->rateCodeToIndex
[unit
->mgmt_rate_code
];
2578 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
2579 duration
= rate_table
->info
[i
].spAckDuration
;
2581 duration
= rate_table
->info
[i
].lpAckDuration
;
2585 *(UWORD
*)(frame
+ WIFI_FRM_DURATION
) = MakeLEWord(duration
);
2587 /* Fill in DMA descriptor for packet transmission */
2589 desc
->ds_link
= (ULONG
)(UPINT
)NULL
;
2590 unit
->hal
->ah_setupTxDesc(unit
->hal
, desc
, frame_size
+ 4, // + CRC?
2591 WIFI_FRM_DATA
, HAL_PKT_TYPE_NORMAL
, TX_POWER
,
2592 unit
->mgmt_rate_code
, TX_TRIES
, HAL_TXKEYIX_INVALID
,
2593 HAL_ANTENNA_MIN_MODE
,
2594 HAL_TXDESC_INTREQ
| HAL_TXDESC_CLRDMASK
2595 | (has_bssid
? 0 : HAL_TXDESC_NOACK
),
2597 unit
->hal
->ah_fillTxDesc(unit
->hal
, desc
, frame_size
, TRUE
, TRUE
,
2600 dma_size
= frame_size
;
2601 CachePreDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2603 /* Pass packet to adapter */
2605 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2606 last_slot
= (slot
+ MGMT_SLOT_COUNT
- 1) % MGMT_SLOT_COUNT
;
2607 if(unit
->mgmt_out_slot
!= slot
)
2608 //if(unit->hal->ah_numTxPending(unit->hal, unit->mgmt_queue_no) > 0)
2610 last_desc
= unit
->mgmt_descs
+ last_slot
;
2611 last_desc
->ds_link
=
2612 unit
->mgmt_descs_p
+ slot
* sizeof(struct ath_desc
);
2613 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2614 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2618 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2619 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2620 unit
->hal
->ah_setTxDP(unit
->hal
, unit
->mgmt_queue_no
,
2621 unit
->mgmt_descs_p
+ slot
* sizeof(struct ath_desc
));
2624 unit
->hal
->ah_startTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2625 unit
->mgmt_in_slot
= new_slot
;
2631 /* Don't try to keep sending packets if there's no space left */
2634 unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
= PA_SOFTINT
;
2636 unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
= PA_IGNORE
;
2643 /****i* atheros5000.device/MgmtTXEndInt ************************************
2646 * MgmtTXEndInt -- Clean up after a management frame has been sent.
2649 * MgmtTXEndInt(unit, int_code)
2651 * VOID MgmtTXEndInt(struct DevUnit *, APTR);
2654 * I think it's safe to assume that there will always be at least one
2655 * completed packet whenever this interrupt is called.
2657 ****************************************************************************
2661 static VOID
MgmtTXEndInt(REG(a1
, struct DevUnit
*unit
),
2662 REG(a6
, APTR int_code
))
2664 UWORD new_out_slot
, i
;
2666 struct DevBase
*base
;
2667 struct IOSana2Req
*request
;
2670 /* Find out which packets have completed */
2672 base
= unit
->device
;
2673 new_out_slot
= (unit
->mgmt_in_slot
+ MGMT_SLOT_COUNT
2674 - unit
->hal
->ah_numTxPending(unit
->hal
, unit
->mgmt_queue_no
))
2677 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2678 CachePostDMA(unit
->mgmt_descs
, &dma_size
, 0);
2680 /* Retire sent frames */
2682 for(i
= unit
->mgmt_out_slot
; i
!= new_out_slot
;
2683 i
= (i
+ 1) % MGMT_SLOT_COUNT
)
2685 frame
= unit
->mgmt_buffers
[i
];
2686 dma_size
= FRAME_BUFFER_SIZE
;
2687 CachePostDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2691 request
= unit
->mgmt_requests
[i
];
2692 request
->ios2_Req
.io_Error
= 0;
2693 ReplyMsg((APTR
)request
);
2696 unit
->mgmt_out_slot
= i
;
2698 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2699 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2701 /* Restart downloads if they had stopped */
2703 if(unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
== PA_IGNORE
)
2704 Cause(&unit
->mgmt_int
);
2711 /****i* atheros5000.device/ResetHandler ************************************
2714 * ResetHandler -- Disable hardware before a reboot.
2717 * ResetHandler(unit, int_code)
2719 * VOID ResetHandler(struct DevUnit *, APTR);
2721 ****************************************************************************
2725 static VOID
ResetHandler(REG(a1
, struct DevUnit
*unit
),
2726 REG(a6
, APTR int_code
))
2728 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
2730 /* Disable frame transmission */
2732 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
2733 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2735 /* Disable frame reception */
2737 unit
->hal
->ah_stopPcuReceive(unit
->hal
);
2738 unit
->hal
->ah_stopDmaReceive(unit
->hal
);
2740 /* Stop interrupts */
2742 unit
->hal
->ah_setInterrupts(unit
->hal
, 0);
2750 /****i* atheros5000.device/UpdateStats *************************************
2758 * VOID UpdateStats(struct DevUnit *);
2763 * unit - A unit of this device.
2768 ****************************************************************************
2772 VOID
UpdateStats(struct DevUnit
*unit
, struct DevBase
*base
)
2774 /* Ask for and wait for stats */
2781 /****i* atheros5000.device/ReportEvents ************************************
2787 * ReportEvents(unit, events)
2789 * VOID ReportEvents(struct DevUnit *, ULONG);
2794 * unit - A unit of this device.
2795 * events - A mask of events to report.
2800 ****************************************************************************
2804 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
2805 struct DevBase
*base
)
2807 struct IOSana2Req
*request
, *tail
, *next_request
;
2810 list
= &unit
->request_ports
[EVENT_QUEUE
]->mp_MsgList
;
2811 next_request
= (APTR
)list
->lh_Head
;
2812 tail
= (APTR
)&list
->lh_Tail
;
2815 while(next_request
!= tail
)
2817 request
= next_request
;
2818 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
2820 if((request
->ios2_WireError
& events
) != 0)
2822 request
->ios2_WireError
= events
;
2823 Remove((APTR
)request
);
2824 ReplyMsg((APTR
)request
);
2834 /****i* atheros5000.device/GetRadioBands ***********************************
2837 * GetRadioBands -- Get information on current network.
2840 * tag_list = GetRadioBands(unit, pool)
2842 * struct TagItem *GetRadioBands(struct DevUnit *, APTR);
2847 * unit - A unit of this device.
2848 * pool - A memory pool.
2853 ****************************************************************************
2858 struct TagItem
*GetRadioBands(struct DevUnit
*unit
, APTR pool
,
2859 struct DevBase
*base
)
2862 struct Sana2RadioBand
*bands
;
2865 bands
= AllocPooled(pool
, sizeof(struct Sana2RadioBand
) * 3);
2867 error
= S2ERR_NO_RESOURCES
;
2871 for(i
= 0; i
< 1; i
++)
2873 bands
[i
] = AllocPooled(pool
, sizeof(UWORD
) * unit
->channel_counts
[S2BAND_B
]);
2886 /****i* atheros5000.device/UnitTask ****************************************
2897 * Completes deferred requests, and handles card insertion and removal
2898 * in conjunction with the relevant interrupts.
2900 ****************************************************************************
2908 static VOID
UnitTask(struct ExecBase
*sys_base
)
2911 struct IORequest
*request
;
2912 struct DevUnit
*unit
;
2913 struct DevBase
*base
;
2914 struct MsgPort
*general_port
;
2915 ULONG signals
= 0, wait_signals
, card_removed_signal
,
2916 card_inserted_signal
, general_port_signal
;
2918 /* Get parameters */
2920 task
= AbsExecBase
->ThisTask
;
2921 unit
= task
->tc_UserData
;
2922 base
= unit
->device
;
2924 /* Activate general request port */
2926 general_port
= unit
->request_ports
[GENERAL_QUEUE
];
2927 general_port
->mp_SigTask
= task
;
2928 general_port
->mp_SigBit
= AllocSignal(-1);
2929 general_port_signal
= 1 << general_port
->mp_SigBit
;
2930 general_port
->mp_Flags
= PA_SIGNAL
;
2932 /* Allocate signals for notification of card removal and insertion */
2934 card_removed_signal
= unit
->card_removed_signal
= 1 << AllocSignal(-1);
2935 card_inserted_signal
= unit
->card_inserted_signal
= 1 << AllocSignal(-1);
2936 wait_signals
= (1 << general_port
->mp_SigBit
) | card_removed_signal
2937 | card_inserted_signal
| SIGBREAKF_CTRL_C
;
2939 /* Tell ourselves to check port for old messages */
2941 Signal(task
, general_port_signal
);
2943 /* Infinite loop to service requests and signals */
2945 while((signals
& SIGBREAKF_CTRL_C
) == 0)
2947 signals
= Wait(wait_signals
);
2949 if((signals
& card_inserted_signal
) != 0)
2951 if(unit
->insertion_function(unit
->card
, base
))
2953 unit
->flags
|= UNITF_HAVEADAPTER
;
2954 if((unit
->flags
& UNITF_CONFIGURED
) != 0)
2955 ConfigureAdapter(unit
, base
);
2956 if((unit
->flags
& UNITF_WASONLINE
) != 0)
2958 GoOnline(unit
, base
);
2959 unit
->flags
&= ~UNITF_WASONLINE
;
2964 if((signals
& card_removed_signal
) != 0)
2966 unit
->removal_function(unit
->card
, base
);
2967 if((unit
->flags
& UNITF_WASONLINE
) != 0)
2968 GoOffline(unit
, base
);
2971 if((signals
& general_port_signal
) != 0)
2973 while((request
= (APTR
)GetMsg(general_port
)) != NULL
)
2975 /* Service the request as soon as the unit is free */
2977 ObtainSemaphore(&unit
->access_lock
);
2978 ServiceRequest((APTR
)request
, base
);
2983 FreeMem(task
->tc_SPLower
, STACK_SIZE
);