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 CopyMem((APTR
)tag_item
->ti_Data
, unit
->bssid
, ETH_ADDRESSSIZE
);
1025 case S2INFO_AssocID
:
1026 unit
->assoc_id
= tag_item
->ti_Data
;
1029 case S2INFO_Capabilities
:
1030 unit
->capabilities
= tag_item
->ti_Data
;
1031 if((unit
->capabilities
& (1 << 5)) != 0)
1032 unit
->flags
|= UNITF_SHORTPREAMBLE
;
1034 unit
->flags
&= ~UNITF_SHORTPREAMBLE
;
1037 case S2INFO_DefaultKeyNo
:
1038 unit
->tx_key_no
= tag_item
->ti_Data
;
1041 case S2INFO_PortType
:
1042 unit
->mode
= tag_item
->ti_Data
;
1045 case S2INFO_Channel
:
1046 if(tag_item
->ti_Data
!= unit
->channel
)
1048 unit
->channel
= tag_item
->ti_Data
;
1054 if(tag_item
->ti_Data
!= unit
->band
)
1056 unit
->band
= tag_item
->ti_Data
;
1068 /****i* atheros5000.device/SetKey ******************************************
1071 * SetKey -- Set an encryption key.
1074 * SetKey(unit, index, type, key, key_length,
1077 * VOID SetKey(struct DevUnit *, ULONG, ULONG, UBYTE *, ULONG,
1080 ****************************************************************************
1084 VOID
SetKey(struct DevUnit
*unit
, ULONG index
, ULONG type
, const UBYTE
*key
,
1085 ULONG key_length
, const UBYTE
*rx_counter
, struct DevBase
*base
)
1087 struct KeyUnion
*slot
;
1088 struct EClockVal eclock
;
1093 slot
= &unit
->keys
[index
];
1097 CopyMem(key
, slot
->u
.wep
.key
, key_length
);
1098 slot
->u
.wep
.length
= key_length
;
1100 if((unit
->flags
& UNITF_HARDWEP
) == 0)
1102 /* Create a reasonably random IV */
1104 ReadEClock(&eclock
);
1105 slot
->u
.wep
.tx_iv
= FastRand(eclock
.ev_lo
^ eclock
.ev_hi
);
1111 CopyMem(key
, slot
->u
.tkip
.key
, 16);
1112 CopyMem(key
+ 16, slot
->u
.tkip
.tx_mic_key
, MIC_SIZE
);
1113 CopyMem(key
+ 24, slot
->u
.tkip
.rx_mic_key
, MIC_SIZE
);
1114 slot
->u
.tkip
.tx_iv_low
= 0;
1115 slot
->u
.tkip
.tx_iv_high
= 0;
1116 slot
->u
.tkip
.rx_iv_low
= LEWord(*(UWORD
*)rx_counter
);
1117 slot
->u
.tkip
.rx_iv_high
= LELong(*(ULONG
*)(rx_counter
+ 2));
1118 slot
->u
.tkip
.tx_ttak_set
= FALSE
;
1119 slot
->u
.tkip
.rx_ttak_set
= FALSE
;
1121 if((unit
->flags
& UNITF_HARDTKIP
) != 0)
1123 // TO DO: Wait for TX queue to empty
1124 /* Load parameters for hardware encryption */
1126 hal_key
.kv_type
= HAL_CIPHER_TKIP
;
1127 hal_key
.kv_len
= 16;
1128 CopyMem(slot
->u
.tkip
.key
, hal_key
.kv_val
, 16);
1130 CopyMem(slot
->u
.tkip
.tx_mic_key
, hal_key
.kv_mic
, MIC_SIZE
);
1131 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
, &hal_key
,
1132 unit
->bssid
, FALSE
);
1133 CopyMem(slot
->u
.tkip
.rx_mic_key
, hal_key
.kv_mic
, MIC_SIZE
);
1134 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
+ 32, &hal_key
,
1135 unit
->bssid
, FALSE
);
1139 /* Convert key to native endianness */
1141 for(i
= 0; i
< 8; i
++)
1142 slot
->u
.tkip
.key
[i
] = LEWord(slot
->u
.tkip
.key
[i
]);
1148 CopyMem(key
, slot
->u
.ccmp
.key
, 16);
1149 slot
->u
.ccmp
.tx_iv_low
= 0;
1150 slot
->u
.ccmp
.tx_iv_high
= 0;
1151 slot
->u
.ccmp
.rx_iv_low
= LEWord(*(UWORD
*)rx_counter
);
1152 slot
->u
.ccmp
.rx_iv_high
= LELong(*(ULONG
*)(rx_counter
+ 2));
1153 slot
->u
.ccmp
.stream_set
= FALSE
;
1155 if((unit
->flags
& UNITF_HARDCCMP
) != 0)
1157 // TO DO: Wait for TX queue to empty
1158 /* Load parameters for hardware encryption */
1160 hal_key
.kv_type
= HAL_CIPHER_AES_CCM
;
1161 hal_key
.kv_len
= 16;
1162 CopyMem(slot
->u
.ccmp
.key
, hal_key
.kv_val
, 16);
1163 unit
->hal
->ah_setKeyCacheEntry(unit
->hal
, index
, &hal_key
,
1164 unit
->bssid
, FALSE
);
1168 /* Update type of key in selected slot */
1178 /****i* atheros5000.device/AddMulticastRange *******************************
1184 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1186 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1188 ****************************************************************************
1192 BOOL
AddMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
1193 const UBYTE
*upper_bound
, struct DevBase
*base
)
1195 struct AddressRange
*range
;
1196 ULONG lower_bound_left
, upper_bound_left
;
1197 UWORD lower_bound_right
, upper_bound_right
;
1199 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
1200 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
1201 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
1202 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
1204 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
1205 upper_bound_left
, upper_bound_right
, base
);
1211 range
= AllocMem(sizeof(struct AddressRange
), MEMF_PUBLIC
);
1214 range
->lower_bound_left
= lower_bound_left
;
1215 range
->lower_bound_right
= lower_bound_right
;
1216 range
->upper_bound_left
= upper_bound_left
;
1217 range
->upper_bound_right
= upper_bound_right
;
1218 range
->add_count
= 1;
1221 AddTail((APTR
)&unit
->multicast_ranges
, (APTR
)range
);
1222 unit
->range_count
++;
1223 SetMulticast(unit
, base
);
1228 return range
!= NULL
;
1233 /****i* atheros5000.device/RemMulticastRange *******************************
1239 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1241 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1243 ****************************************************************************
1247 BOOL
RemMulticastRange(struct DevUnit
*unit
, const UBYTE
*lower_bound
,
1248 const UBYTE
*upper_bound
, struct DevBase
*base
)
1250 struct AddressRange
*range
;
1251 ULONG lower_bound_left
, upper_bound_left
;
1252 UWORD lower_bound_right
, upper_bound_right
;
1254 lower_bound_left
= BELong(*((ULONG
*)lower_bound
));
1255 lower_bound_right
= BEWord(*((UWORD
*)(lower_bound
+ 4)));
1256 upper_bound_left
= BELong(*((ULONG
*)upper_bound
));
1257 upper_bound_right
= BEWord(*((UWORD
*)(upper_bound
+ 4)));
1259 range
= FindMulticastRange(unit
, lower_bound_left
, lower_bound_right
,
1260 upper_bound_left
, upper_bound_right
, base
);
1264 if(--range
->add_count
== 0)
1267 Remove((APTR
)range
);
1268 unit
->range_count
--;
1269 SetMulticast(unit
, base
);
1271 FreeMem(range
, sizeof(struct AddressRange
));
1275 return range
!= NULL
;
1280 /****i* atheros5000.device/FindMulticastRange ******************************
1283 * FindMulticastRange
1286 * range = FindMulticastRange(unit, lower_bound_left,
1287 * lower_bound_right, upper_bound_left, upper_bound_right)
1289 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1290 * UWORD, ULONG, UWORD);
1292 ****************************************************************************
1296 static struct AddressRange
*FindMulticastRange(struct DevUnit
*unit
,
1297 ULONG lower_bound_left
, UWORD lower_bound_right
, ULONG upper_bound_left
,
1298 UWORD upper_bound_right
, struct DevBase
*base
)
1300 struct AddressRange
*range
, *tail
;
1303 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
1304 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
1306 while(range
!= tail
&& !found
)
1308 if(lower_bound_left
== range
->lower_bound_left
&&
1309 lower_bound_right
== range
->lower_bound_right
&&
1310 upper_bound_left
== range
->upper_bound_left
&&
1311 upper_bound_right
== range
->upper_bound_right
)
1314 range
= (APTR
)range
->node
.mln_Succ
;
1325 /****i* atheros5000.device/SetMulticast ************************************
1331 * SetMulticast(unit)
1333 * VOID SetMulticast(struct DevUnit *);
1335 ****************************************************************************
1339 static VOID
SetMulticast(struct DevUnit
*unit
, struct DevBase
*base
)
1341 unit
->hal
->ah_setMulticastFilter(unit
->hal
, 0xffffffff, 0xffffffff);
1348 /****i* atheros5000.device/FindTypeStats ***********************************
1354 * stats = FindTypeStats(unit, list,
1357 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1360 ****************************************************************************
1364 struct TypeStats
*FindTypeStats(struct DevUnit
*unit
, struct MinList
*list
,
1365 ULONG packet_type
, struct DevBase
*base
)
1367 struct TypeStats
*stats
, *tail
;
1370 stats
= (APTR
)list
->mlh_Head
;
1371 tail
= (APTR
)&list
->mlh_Tail
;
1373 while(stats
!= tail
&& !found
)
1375 if(stats
->packet_type
== packet_type
)
1378 stats
= (APTR
)stats
->node
.mln_Succ
;
1389 /****i* atheros5000.device/FlushUnit ***************************************
1395 * FlushUnit(unit, last_queue, error)
1397 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1399 ****************************************************************************
1403 VOID
FlushUnit(struct DevUnit
*unit
, UBYTE last_queue
, BYTE error
,
1404 struct DevBase
*base
)
1406 struct IORequest
*request
;
1408 struct Opener
*opener
, *tail
;
1410 /* Abort queued requests */
1412 for(i
= 0; i
<= last_queue
; i
++)
1414 while((request
= (APTR
)GetMsg(unit
->request_ports
[i
])) != NULL
)
1416 request
->io_Error
= IOERR_ABORTED
;
1417 ReplyMsg((APTR
)request
);
1422 opener
= (APTR
)unit
->openers
.mlh_Head
;
1423 tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1425 /* Flush every opener's read queues */
1427 while(opener
!= tail
)
1429 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1431 request
->io_Error
= error
;
1432 ReplyMsg((APTR
)request
);
1434 while((request
= (APTR
)GetMsg(&opener
->mgmt_port
)) != NULL
)
1436 request
->io_Error
= error
;
1437 ReplyMsg((APTR
)request
);
1439 opener
= (APTR
)opener
->node
.mln_Succ
;
1443 opener
= request
->ios2_BufferManagement
;
1444 while((request
= (APTR
)GetMsg(&opener
->read_port
)) != NULL
)
1446 request
->io_Error
= IOERR_ABORTED
;
1447 ReplyMsg((APTR
)request
);
1449 while((request
= (APTR
)GetMsg(&opener
->mgmt_port
)) != NULL
)
1451 request
->io_Error
= IOERR_ABORTED
;
1452 ReplyMsg((APTR
)request
);
1463 /****i* atheros5000.device/StatusInt ***************************************
1469 * finished = StatusInt(unit)
1471 * BOOL StatusInt(struct DevUnit *);
1481 ****************************************************************************
1483 * int_code is really in A5, but GCC 2.95.3 doesn't seem able to handle that.
1484 * Since we don't use this parameter, we can lie.
1488 static BOOL
StatusInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
1490 struct DevBase
*base
;
1491 uint32_t queue_mask
;
1492 HAL_INT ints
, int_mask
;
1494 base
= unit
->device
;
1495 int_mask
= unit
->hal
->ah_getInterrupts(unit
->hal
);
1497 if(!unit
->hal
->ah_isInterruptPending(unit
->hal
)) return FALSE
;
1501 if(unit
->hal
->ah_getPendingInterrupts(unit
->hal
, &ints
))
1503 if((ints
& HAL_INT_TX
) != 0)
1505 int_mask
&= ~(HAL_INT_TX
| HAL_INT_TXDESC
);
1506 queue_mask
= 1 << unit
->tx_queue_no
| 1 << unit
->mgmt_queue_no
;
1507 unit
->hal
->ah_getTxIntrQueue(unit
->hal
, &queue_mask
);
1508 if((queue_mask
& 1 << unit
->tx_queue_no
) != 0)
1509 Cause(&unit
->tx_end_int
);
1510 if((queue_mask
& 1 << unit
->mgmt_queue_no
) != 0)
1511 Cause(&unit
->mgmt_end_int
);
1513 if((ints
& HAL_INT_RX
) != 0)
1515 int_mask
&= ~(HAL_INT_RX
| HAL_INT_RXEOL
);
1516 Cause(&unit
->rx_int
);
1521 int_mask
= INT_MASK
;
1523 // unit->hal->ah_setInterrupts(unit->hal, int_mask))
1530 /****i* atheros5000.device/RXInt *******************************************
1533 * RXInt -- Soft interrupt for packet reception.
1538 * VOID RXInt(struct DevUnit *);
1543 * unit - A unit of this device.
1548 ****************************************************************************
1552 static VOID
RXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
1554 UWORD ieee_length
, frame_control
, frame_type
, slot
, next_slot
,
1555 encryption
, key_no
, buffer_no
, old_length
;
1556 struct DevBase
*base
;
1559 struct ath_desc
*rx_desc
, *next_desc
;
1560 ULONG dma_size
, rx_desc_p
;
1561 UBYTE
*buffer
, *p
, *frame
, *data
, *snap_frame
, *source
;
1562 struct ath_rx_status status
;
1564 base
= unit
->device
;
1565 slot
= unit
->rx_slot
;
1566 rx_desc
= unit
->rx_descs
+ slot
;
1567 rx_desc_p
= unit
->rx_descs_p
+ slot
* sizeof(struct ath_desc
);
1568 next_slot
= (slot
+ 1) % RX_SLOT_COUNT
;
1569 next_desc
= unit
->rx_descs
+ next_slot
;
1571 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
1572 CachePostDMA(unit
->rx_descs
, &dma_size
, 0);
1574 while(unit
->hal
->ah_procRxDesc(unit
->hal
, rx_desc
, rx_desc_p
, next_desc
,
1575 unit
->hal
->ah_getTsf64(unit
->hal
), &status
) != HAL_EINPROGRESS
)
1578 buffer
= unit
->rx_buffers
[slot
];
1580 dma_size
= FRAME_BUFFER_SIZE
;
1581 CachePostDMA(buffer
, &dma_size
, 0);
1583 if(status
.rs_status
== 0
1584 && status
.rs_datalen
>= WIFI_FRM_DATA
+ FCS_SIZE
)
1586 /* Get fragment info */
1589 ieee_length
= status
.rs_datalen
- FCS_SIZE
- WIFI_FRM_DATA
;
1590 data
= frame
+ WIFI_FRM_DATA
;
1592 LEWord(*(UWORD
*)(frame
+ WIFI_FRM_CONTROL
));
1594 /* Get buffer to store fragment in */
1596 frag_no
= LEWord(*(UWORD
*)(frame
+ WIFI_FRM_SEQCONTROL
));
1597 if(unit
->mode
== S2PORT_ADHOC
)
1598 source
= frame
+ WIFI_FRM_ADDRESS2
;
1600 source
= frame
+ WIFI_FRM_ADDRESS3
;
1601 snap_frame
= GetRXBuffer(unit
, source
, frag_no
, &buffer_no
, base
);
1603 /* Get location to put new data */
1605 if(snap_frame
!= NULL
)
1607 if((frag_no
& 0xf ) > 0)
1609 BEWord(*(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
));
1612 /* Create new 802.3 header */
1614 CopyMem(frame
+ WIFI_FRM_ADDRESS1
, snap_frame
,
1616 CopyMem(source
, snap_frame
+ ETH_PACKET_SOURCE
,
1620 p
= snap_frame
+ ETH_HEADERSIZE
+ old_length
;
1622 /* Get encryption type and key index */
1624 if((frame_control
& WIFI_FRM_CONTROLF_WEP
) != 0)
1626 key_no
= data
[3] >> 6 & 0x3;
1627 encryption
= unit
->keys
[key_no
].type
;
1630 encryption
= S2ENC_NONE
;
1632 /* Append fragment to frame, decrypting/checking fragment if
1635 is_good
= unit
->fragment_decrypt_functions
[encryption
](unit
,
1636 frame
, data
, &ieee_length
, p
, base
);
1638 /* Update length in frame being built with current fragment, or
1639 increment bad frame counter if fragment is bad */
1643 ieee_length
+= old_length
;
1644 *(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
) =
1645 MakeBEWord(ieee_length
);
1648 unit
->stats
.BadData
++;
1650 /* If all fragments have arrived, process the complete frame */
1652 if((frame_control
& WIFI_FRM_CONTROLF_MOREFRAGS
) == 0)
1656 /* Decrypt complete frame if necessary */
1658 data
= snap_frame
+ ETH_HEADERSIZE
;
1659 if(encryption
== S2ENC_TKIP
)
1660 // && (unit->flags & UNITF_HARDTKIP) == 0)
1661 // && (unit->flags & UNITF_HARDMIC) == 0)
1663 is_good
= TKIPDecryptFrame(unit
, snap_frame
, data
,
1664 ieee_length
, data
, key_no
, base
);
1665 ieee_length
-= MIC_SIZE
;
1666 *(UWORD
*)(snap_frame
+ ETH_PACKET_IEEELEN
) =
1667 MakeBEWord(ieee_length
);
1669 unit
->stats
.BadData
++;
1675 /* Get frame's 802.11 type and subtype */
1677 frame_type
= (frame_control
& WIFI_FRM_CONTROLF_TYPE
)
1678 >> WIFI_FRM_CONTROLB_TYPE
;
1680 /* If it's a management frame, process it separately;
1681 otherwise distribute it to clients after filtering */
1683 if(frame_type
== WIFI_FRMTYPE_MGMT
)
1685 DistributeMgmtFrame(unit
, frame
, status
.rs_datalen
- 4,
1688 else if(AddressFilter(unit
, snap_frame
+ ETH_PACKET_DEST
,
1691 unit
->stats
.PacketsReceived
++;
1692 DistributeRXPacket(unit
, snap_frame
, base
);
1697 /* Mark fragment buffer as unused for next time */
1699 unit
->rx_fragment_nos
[buffer_no
] = -1;
1702 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_RX
, base
);
1711 ReportEvents(unit
, S2EVENT_ERROR
| S2EVENT_HARDWARE
| S2EVENT_RX
,
1715 /* Prepare descriptor for next time */
1717 unit
->hal
->ah_setupRxDesc(unit
->hal
, rx_desc
, FRAME_BUFFER_SIZE
,
1720 dma_size
= FRAME_BUFFER_SIZE
;
1721 CachePreDMA(buffer
, &dma_size
, 0);
1723 /* Get next descriptor */
1726 rx_desc
= next_desc
;
1727 rx_desc_p
= unit
->rx_descs_p
+ slot
* sizeof(struct ath_desc
);
1728 next_slot
= (slot
+ 1) % RX_SLOT_COUNT
;
1729 next_desc
= unit
->rx_descs
+ next_slot
;
1732 dma_size
= sizeof(struct ath_desc
) * RX_SLOT_COUNT
;
1733 CachePreDMA(unit
->rx_descs
, &dma_size
, 0);
1735 unit
->rx_slot
= slot
;
1736 // TO DO: unstall reception?
1738 /* Re-enable RX interrupts */
1742 unit
->hal
->ah_setInterrupts(unit
->hal
,
1743 unit
->hal
->ah_getInterrupts(unit
->hal
) | HAL_INT_RX
| HAL_INT_RXEOL
);
1752 /****i* atheros5000.device/GetRXBuffer *************************************
1755 * GetRXBuffer -- Find an appropriate RX frame buffer to use.
1758 * buffer = GetRXBuffer(unit, address, frag_no)
1760 * UBYTE *GetRXBuffer(struct DevUnit *, UBYTE *, UWORD);
1762 ****************************************************************************
1766 static UBYTE
*GetRXBuffer(struct DevUnit
*unit
, const UBYTE
*address
,
1767 UWORD frag_no
, UWORD
*buffer_no
, struct DevBase
*base
)
1774 buffer
= unit
->rx_frames
;
1775 for(i
= 0, found
= FALSE
; i
< FRAME_BUFFER_COUNT
* 2 && !found
; i
++)
1777 /* Throw away old buffer contents if we didn't find a free slot the
1778 first time around */
1780 if(i
>= FRAME_BUFFER_COUNT
)
1781 unit
->rx_fragment_nos
[i
% FRAME_BUFFER_COUNT
] = -1;
1783 /* For a frame's first fragment, find an empty slot; for subsequent
1784 fragments, find a slot with matching source address */
1786 n
= unit
->rx_fragment_nos
[i
% FRAME_BUFFER_COUNT
];
1787 if(n
== -1 && (frag_no
& 0xf) == 0
1788 || *((ULONG
*)(buffer
+ ETH_PACKET_SOURCE
))
1789 == *((ULONG
*)(address
))
1790 && *((UWORD
*)(buffer
+ ETH_PACKET_SOURCE
+ 4))
1791 == *((UWORD
*)(address
+ 4)))
1795 unit
->rx_fragment_nos
[i
% FRAME_BUFFER_COUNT
] = frag_no
;
1799 buffer
+= FRAME_BUFFER_SIZE
;
1810 /****i* atheros5000.device/DistributeRXPacket ******************************
1813 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1816 * DistributeRXPacket(unit, frame)
1818 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1820 ****************************************************************************
1824 static VOID
DistributeRXPacket(struct DevUnit
*unit
, UBYTE
*frame
,
1825 struct DevBase
*base
)
1827 UWORD packet_size
, ieee_length
;
1828 BOOL is_orphan
= TRUE
, accepted
, is_snap
= FALSE
;
1831 const UBYTE
*template = snap_template
;
1832 struct IOSana2Req
*request
, *request_tail
;
1833 struct Opener
*opener
, *opener_tail
;
1834 struct TypeStats
*tracker
;
1836 ieee_length
= BEWord(*(UWORD
*)(frame
+ ETH_PACKET_IEEELEN
));
1837 packet_size
= ETH_HEADERSIZE
+ ieee_length
;
1838 if(ieee_length
>= SNAP_HEADERSIZE
)
1839 is_snap
= *(const ULONG
*)(frame
+ ETH_PACKET_DATA
)
1840 == *(const ULONG
*)template;
1842 /* De-encapsulate SNAP packets and get packet type */
1846 buffer
= unit
->rx_buffer
;
1847 packet_size
-= SNAP_HEADERSIZE
;
1848 CopyMem(frame
, buffer
, ETH_PACKET_TYPE
);
1849 CopyMem(frame
+ ETH_HEADERSIZE
+ SNAP_FRM_TYPE
,
1850 buffer
+ ETH_PACKET_TYPE
, packet_size
- ETH_PACKET_TYPE
);
1855 packet_type
= BEWord(*((UWORD
*)(buffer
+ ETH_PACKET_TYPE
)));
1857 if(packet_size
<= ETH_MAXPACKETSIZE
)
1859 /* Offer packet to every opener */
1861 opener
= (APTR
)unit
->openers
.mlh_Head
;
1862 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
1864 while(opener
!= opener_tail
)
1866 request
= (APTR
)opener
->read_port
.mp_MsgList
.lh_Head
;
1867 request_tail
= (APTR
)&opener
->read_port
.mp_MsgList
.lh_Tail
;
1870 /* Offer packet to each request until it's accepted */
1872 while(request
!= request_tail
&& !accepted
)
1874 if(request
->ios2_PacketType
== packet_type
)
1876 CopyPacket(unit
, request
, packet_size
, packet_type
,
1881 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
1886 opener
= (APTR
)opener
->node
.mln_Succ
;
1889 /* If packet was unwanted, give it to S2_READORPHAN request */
1893 unit
->stats
.UnknownTypesReceived
++;
1894 if(!IsMsgPortEmpty(unit
->request_ports
[ADOPT_QUEUE
]))
1897 (APTR
)unit
->request_ports
[ADOPT_QUEUE
]->
1898 mp_MsgList
.lh_Head
, packet_size
, packet_type
, buffer
,
1903 /* Update remaining statistics */
1905 if(packet_type
<= ETH_MTU
)
1906 packet_type
= ETH_MTU
;
1908 FindTypeStats(unit
, &unit
->type_trackers
, packet_type
, base
);
1911 tracker
->stats
.PacketsReceived
++;
1912 tracker
->stats
.BytesReceived
+= packet_size
;
1916 unit
->stats
.BadData
++;
1923 /****i* atheros5000.device/CopyPacket **************************************
1926 * CopyPacket -- Copy packet to client's buffer.
1929 * CopyPacket(unit, request, packet_size, packet_type,
1932 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1935 ****************************************************************************
1939 static VOID
CopyPacket(struct DevUnit
*unit
, struct IOSana2Req
*request
,
1940 UWORD packet_size
, UWORD packet_type
, UBYTE
*buffer
,
1941 struct DevBase
*base
)
1943 struct Opener
*opener
;
1944 BOOL filtered
= FALSE
;
1946 /* Set multicast and broadcast flags */
1948 request
->ios2_Req
.io_Flags
&= ~(SANA2IOF_BCAST
| SANA2IOF_MCAST
);
1949 if((*((ULONG
*)(buffer
+ ETH_PACKET_DEST
)) == 0xffffffff) &&
1950 (*((UWORD
*)(buffer
+ ETH_PACKET_DEST
+ 4)) == 0xffff))
1951 request
->ios2_Req
.io_Flags
|= SANA2IOF_BCAST
;
1952 else if((buffer
[ETH_PACKET_DEST
] & 0x1) != 0)
1953 request
->ios2_Req
.io_Flags
|= SANA2IOF_MCAST
;
1955 /* Set source and destination addresses and packet type */
1957 CopyMem(buffer
+ ETH_PACKET_SOURCE
, request
->ios2_SrcAddr
,
1959 CopyMem(buffer
+ ETH_PACKET_DEST
, request
->ios2_DstAddr
,
1961 request
->ios2_PacketType
= packet_type
;
1963 /* Adjust for cooked packet request */
1965 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
1967 packet_size
-= ETH_PACKET_DATA
;
1968 buffer
+= ETH_PACKET_DATA
;
1972 packet_size
+= 4; /* Needed for Shapeshifter & Fusion? */
1974 request
->ios2_DataLength
= packet_size
;
1978 opener
= request
->ios2_BufferManagement
;
1979 if(request
->ios2_Req
.io_Command
== CMD_READ
&&
1980 opener
->filter_hook
!= NULL
)
1981 if(!CallHookPkt(opener
->filter_hook
, request
, buffer
))
1986 /* Copy packet into opener's buffer and reply packet */
1988 if(!opener
->rx_function(request
->ios2_Data
, buffer
, packet_size
))
1990 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
1991 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
1993 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
1996 Remove((APTR
)request
);
1997 ReplyMsg((APTR
)request
);
2005 /****i* atheros5000.device/AddressFilter ***********************************
2008 * AddressFilter -- Determine if an RX packet should be accepted.
2011 * accept = AddressFilter(unit, address)
2013 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
2015 ****************************************************************************
2019 static BOOL
AddressFilter(struct DevUnit
*unit
, UBYTE
*address
,
2020 struct DevBase
*base
)
2022 struct AddressRange
*range
, *tail
;
2025 UWORD address_right
;
2027 /* Check whether address is unicast/broadcast or multicast */
2029 address_left
= BELong(*((ULONG
*)address
));
2030 address_right
= BEWord(*((UWORD
*)(address
+ 4)));
2032 if(((address_left
& 0x01000000) != 0) &&
2033 !((address_left
== 0xffffffff) && (address_right
== 0xffff)))
2035 /* Check if this multicast address is wanted */
2037 range
= (APTR
)unit
->multicast_ranges
.mlh_Head
;
2038 tail
= (APTR
)&unit
->multicast_ranges
.mlh_Tail
;
2041 while((range
!= tail
) && !accept
)
2043 if((address_left
> range
->lower_bound_left
||
2044 address_left
== range
->lower_bound_left
&&
2045 address_right
>= range
->lower_bound_right
) &&
2046 (address_left
< range
->upper_bound_left
||
2047 address_left
== range
->upper_bound_left
&&
2048 address_right
<= range
->upper_bound_right
))
2050 range
= (APTR
)range
->node
.mln_Succ
;
2054 unit
->special_stats
[S2SS_ETHERNET_BADMULTICAST
& 0xffff]++;
2062 /****i* atheros5000.device/DistributeMgmtFrame *****************************
2065 * DistributeMgmtFrame -- Send a management frame to clients.
2068 * DistributeMgmtFrame(unit, frame, frame_size)
2070 * VOID DistributeMgmtFrame(struct DevUnit *, UBYTE *, UWORD);
2072 ****************************************************************************
2076 static VOID
DistributeMgmtFrame(struct DevUnit
*unit
, UBYTE
*frame
,
2077 UWORD frame_size
, struct DevBase
*base
)
2079 struct IOSana2Req
*request
;
2080 struct Opener
*opener
, *opener_tail
;
2082 /* Send packet to every opener */
2084 opener
= (APTR
)unit
->openers
.mlh_Head
;
2085 opener_tail
= (APTR
)&unit
->openers
.mlh_Tail
;
2087 while(opener
!= opener_tail
)
2089 request
= (APTR
)RemHead(&opener
->mgmt_port
.mp_MsgList
);
2093 /* Copy packet into opener's buffer and reply packet */
2095 if(frame_size
<= request
->ios2_DataLength
)
2097 CopyMem(frame
, request
->ios2_Data
, frame_size
);
2098 request
->ios2_DataLength
= frame_size
;
2102 request
->ios2_Req
.io_Error
= S2ERR_NO_RESOURCES
;
2103 request
->ios2_WireError
= S2WERR_BUFF_ERROR
;
2105 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
| S2EVENT_RX
,
2108 ReplyMsg((APTR
)request
);
2110 (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
2113 opener
= (APTR
)opener
->node
.mln_Succ
;
2121 /****i* atheros5000.device/TXInt *******************************************
2124 * TXInt -- Soft interrupt for packet transmission.
2129 * VOID TXInt(struct DevUnit *);
2134 * unit - A unit of this device.
2139 ****************************************************************************
2143 static VOID
TXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
2145 struct DevBase
*base
;
2146 UWORD i
, frame_size
, data_size
, packet_type
, body_size
, slot
, new_slot
,
2147 last_slot
, encryption
, subtype
, duration
;
2148 UBYTE
*buffer
, *q
, *plaintext
, *ciphertext
, *frame
,
2149 mic_header
[ETH_ADDRESSSIZE
* 2];
2150 const UBYTE
*p
, *dest
, *source
;
2151 struct IOSana2Req
*request
;
2152 BOOL proceed
= TRUE
, is_ieee
;
2153 struct Opener
*opener
;
2154 ULONG wire_error
, dma_size
;
2155 struct ath_desc
*tx_desc
, *last_desc
;
2156 UBYTE
*(*dma_tx_function
)(REG(a0
, APTR
));
2158 struct MsgPort
*port
;
2159 struct TypeStats
*tracker
;
2160 const HAL_RATE_TABLE
*rate_table
;
2162 base
= unit
->device
;
2163 port
= unit
->request_ports
[WRITE_QUEUE
];
2164 rate_table
= unit
->rate_table
;
2166 while(proceed
&& (!IsMsgPortEmpty(port
)))
2168 slot
= unit
->tx_in_slot
;
2169 new_slot
= (slot
+ 1) % TX_SLOT_COUNT
;
2171 // if(new_slot != unit->tx_out_slot)
2172 if(slot
== unit
->tx_out_slot
) // one packet at a time
2177 /* Get request and DMA frame descriptor */
2179 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
2181 Remove((APTR
)request
);
2182 unit
->tx_requests
[slot
] = request
;
2183 tx_desc
= unit
->tx_descs
+ slot
;
2184 frame
= unit
->tx_buffers
[slot
];
2186 /* Get packet data */
2188 opener
= request
->ios2_BufferManagement
;
2189 dma_tx_function
= opener
->dma_tx_function
;
2190 if(dma_tx_function
!= NULL
)
2191 buffer
= dma_tx_function(request
->ios2_Data
);
2197 buffer
= unit
->tx_buffer
;
2198 if(!opener
->tx_function(buffer
, request
->ios2_Data
,
2199 request
->ios2_DataLength
))
2201 error
= S2ERR_NO_RESOURCES
;
2202 wire_error
= S2WERR_BUFF_ERROR
;
2204 S2EVENT_ERROR
| S2EVENT_SOFTWARE
| S2EVENT_BUFF
2205 | S2EVENT_TX
, base
);
2211 /* Get packet type and/or length */
2213 data_size
= request
->ios2_DataLength
;
2214 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) != 0)
2216 data_size
-= ETH_PACKET_DATA
;
2217 packet_type
= BEWord(*(UWORD
*)(buffer
+ ETH_PACKET_TYPE
));
2220 packet_type
= request
->ios2_PacketType
;
2221 is_ieee
= packet_type
<= ETH_MTU
;
2223 /* Determine encryption type and frame subtype */
2227 encryption
= unit
->keys
[unit
->tx_key_no
].type
;
2232 encryption
= S2ENC_NONE
;
2236 /* Get source and destination addresses */
2238 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) != 0)
2241 source
= buffer
+ ETH_ADDRESSSIZE
;
2242 buffer
+= ETH_ADDRESSSIZE
* 2 + 2;
2246 dest
= request
->ios2_DstAddr
;
2247 source
= unit
->address
;
2250 /* Write 802.11 header */
2253 *(UWORD
*)q
= MakeLEWord(
2254 (encryption
== S2ENC_NONE
? 0 : WIFI_FRM_CONTROLF_WEP
)
2255 | (unit
->mode
== S2PORT_ADHOC
? 0 : WIFI_FRM_CONTROLF_TODS
)
2256 | subtype
<< WIFI_FRM_CONTROLB_SUBTYPE
2257 | WIFI_FRMTYPE_DATA
<< WIFI_FRM_CONTROLB_TYPE
);
2260 i
= rate_table
->rateCodeToIndex
[unit
->tx_rate_codes
[0]];
2261 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
2262 duration
= rate_table
->info
[i
].spAckDuration
;
2264 duration
= rate_table
->info
[i
].lpAckDuration
;
2265 *(UWORD
*)q
= MakeLEWord(duration
);
2268 if(unit
->mode
== S2PORT_ADHOC
)
2272 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
2275 for(i
= 0, p
= source
; i
< ETH_ADDRESSSIZE
; i
++)
2278 if(unit
->mode
== S2PORT_ADHOC
)
2282 for(i
= 0; i
< ETH_ADDRESSSIZE
; i
++)
2287 // TO DO: need to pad header to 4-byte boundary?
2289 /* Leave room for encryption overhead */
2292 q
+= unit
->iv_sizes
[encryption
];
2295 /* Write SNAP header */
2299 for(i
= 0, p
= snap_template
;
2300 i
< SNAP_FRM_TYPE
; i
++)
2302 *(UWORD
*)q
= MakeBEWord(packet_type
);
2304 body_size
+= SNAP_HEADERSIZE
;
2307 /* Copy data into frame */
2309 CopyMem(buffer
, q
, data_size
);
2310 body_size
+= data_size
;
2312 /* Append MIC to frame for TKIP */
2314 if(encryption
== S2ENC_TKIP
)
2316 // if((unit->flags & UNITF_HARDMIC) == 0)
2319 for(i
= 0, p
= dest
; i
< ETH_ADDRESSSIZE
; i
++)
2321 for(i
= 0, p
= source
; i
< ETH_ADDRESSSIZE
; i
++)
2323 TKIPEncryptFrame(unit
, mic_header
, plaintext
, body_size
,
2326 body_size
+= MIC_SIZE
;
2329 /* Encrypt fragment if applicable */
2331 unit
->fragment_encrypt_functions
[encryption
](unit
, frame
,
2332 plaintext
, &body_size
, ciphertext
, base
);
2334 /* Fill in DMA descriptor for packet transmission */
2336 frame_size
= WIFI_FRM_DATA
+ body_size
;
2337 tx_desc
->ds_link
= (ULONG
)(UPINT
)NULL
;
2338 unit
->hal
->ah_setupTxDesc(unit
->hal
, tx_desc
, frame_size
+ 4, // + CRC?
2339 WIFI_FRM_DATA
, HAL_PKT_TYPE_NORMAL
, TX_POWER
,
2340 ((unit
->flags
& UNITF_SLOWRETRIES
) != 0) ?
2341 unit
->tx_rate_codes
[0] : unit
->tx_rate_codes
[1],
2342 ((unit
->flags
& UNITF_SLOWRETRIES
) != 0) ? 1 : TX_TRIES
,
2343 HAL_TXKEYIX_INVALID
,
2344 HAL_ANTENNA_MIN_MODE
,
2345 HAL_TXDESC_INTREQ
| HAL_TXDESC_CLRDMASK
,
2347 if((unit
->flags
& UNITF_SLOWRETRIES
) != 0)
2348 unit
->hal
->ah_setupXTxDesc(unit
->hal
, tx_desc
,
2349 unit
->tx_rate_codes
[1], 1,
2350 unit
->tx_rate_codes
[2], 1,
2351 unit
->tx_rate_codes
[3], TX_TRIES
- 3);
2352 unit
->hal
->ah_fillTxDesc(unit
->hal
, tx_desc
, frame_size
, TRUE
, TRUE
,
2355 dma_size
= frame_size
;
2356 CachePreDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2358 /* Pass packet to adapter */
2360 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
2361 last_slot
= (slot
+ TX_SLOT_COUNT
- 1) % TX_SLOT_COUNT
;
2362 if(unit
->tx_out_slot
!= slot
)
2363 //if(unit->hal->ah_numTxPending(unit->hal, unit->tx_queue_no) > 0)
2366 unit
->tx_descs
+ last_slot
;
2367 last_desc
->ds_link
= unit
->tx_descs_p
+ slot
* sizeof(struct ath_desc
);
2368 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2369 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2373 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2374 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2375 unit
->hal
->ah_setTxDP(unit
->hal
, unit
->tx_queue_no
,
2376 unit
->tx_descs_p
+ slot
* sizeof(struct ath_desc
));
2379 unit
->hal
->ah_startTxDma(unit
->hal
, unit
->tx_queue_no
);
2380 unit
->tx_in_slot
= new_slot
;
2384 /* Reply failed request */
2386 request
->ios2_Req
.io_Error
= error
;
2387 request
->ios2_WireError
= wire_error
;
2388 ReplyMsg((APTR
)request
);
2391 /* Update statistics */
2395 unit
->stats
.PacketsSent
++;
2397 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
2398 request
->ios2_PacketType
, base
);
2401 tracker
->stats
.PacketsSent
++;
2402 tracker
->stats
.BytesSent
+= ETH_HEADERSIZE
+ data_size
;
2410 /* Don't try to keep sending packets if there's no space left */
2413 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_SOFTINT
;
2415 unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
= PA_IGNORE
;
2422 /****i* atheros5000.device/TXEndInt ****************************************
2425 * TXEndInt -- Clean up after a data frame has been sent.
2428 * TXEndInt(unit, int_code)
2430 * VOID TXEndInt(struct DevUnit *, APTR);
2433 * I think it's safe to assume that there will always be at least one
2434 * completed packet whenever this interrupt is called.
2436 ****************************************************************************
2440 static VOID
TXEndInt(REG(a1
, struct DevUnit
*unit
),
2441 REG(a6
, APTR int_code
))
2443 UWORD frame_size
, new_out_slot
, i
;
2445 struct DevBase
*base
;
2446 struct IOSana2Req
*request
;
2448 struct TypeStats
*tracker
;
2450 /* Find out which packets have completed */
2452 base
= unit
->device
;
2453 new_out_slot
= (unit
->tx_in_slot
+ TX_SLOT_COUNT
2454 - unit
->hal
->ah_numTxPending(unit
->hal
, unit
->tx_queue_no
))
2457 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2458 CachePostDMA(unit
->tx_descs
, &dma_size
, 0);
2460 /* Retire sent packets */
2462 for(i
= unit
->tx_out_slot
; i
!= new_out_slot
;
2463 i
= (i
+ 1) % TX_SLOT_COUNT
)
2465 frame
= unit
->tx_buffers
[i
];
2466 dma_size
= FRAME_BUFFER_SIZE
;
2467 CachePostDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2469 /* Update statistics */
2471 request
= unit
->tx_requests
[i
];
2472 frame_size
= request
->ios2_DataLength
;
2473 if((request
->ios2_Req
.io_Flags
& SANA2IOF_RAW
) == 0)
2474 frame_size
+= ETH_HEADERSIZE
;
2476 tracker
= FindTypeStats(unit
, &unit
->type_trackers
,
2477 request
->ios2_PacketType
, base
);
2480 tracker
->stats
.PacketsSent
++;
2481 tracker
->stats
.BytesSent
+= frame_size
;
2486 request
->ios2_Req
.io_Error
= 0;
2487 ReplyMsg((APTR
)request
);
2490 unit
->tx_out_slot
= i
;
2492 dma_size
= sizeof(struct ath_desc
) * TX_SLOT_COUNT
;
2493 CachePreDMA(unit
->tx_descs
, &dma_size
, 0);
2495 /* Restart downloads if they had stopped */
2497 if(unit
->request_ports
[WRITE_QUEUE
]->mp_Flags
== PA_IGNORE
)
2498 Cause(&unit
->tx_int
);
2505 /****i* atheros5000.device/MgmtTXInt ***************************************
2508 * MgmtTXInt -- Soft interrupt for management frame transmission.
2513 * VOID MgmtTXInt(struct DevUnit *);
2518 * unit - A unit of this device.
2523 ****************************************************************************
2527 static VOID
MgmtTXInt(REG(a1
, struct DevUnit
*unit
), REG(a6
, APTR int_code
))
2529 struct DevBase
*base
;
2530 UWORD frame_size
, slot
, new_slot
, last_slot
, i
, duration
;
2532 struct IOSana2Req
*request
;
2533 BOOL proceed
= TRUE
, has_bssid
;
2535 struct ath_desc
*desc
, *last_desc
;
2536 struct MsgPort
*port
;
2537 const HAL_RATE_TABLE
*rate_table
;
2539 base
= unit
->device
;
2540 port
= unit
->request_ports
[MGMT_QUEUE
];
2541 rate_table
= unit
->rate_table
;
2543 while(proceed
&& (!IsMsgPortEmpty(port
)))
2545 slot
= unit
->mgmt_in_slot
;
2546 new_slot
= (slot
+ 1) % MGMT_SLOT_COUNT
;
2548 // if(new_slot != unit->mgmt_out_slot)
2549 if(slot
== unit
->mgmt_out_slot
) // one packet at a time
2551 /* Get request and DMA frame descriptor */
2553 request
= (APTR
)port
->mp_MsgList
.lh_Head
;
2555 Remove((APTR
)request
);
2556 unit
->mgmt_requests
[slot
] = request
;
2557 desc
= unit
->mgmt_descs
+ slot
;
2558 frame
= unit
->mgmt_buffers
[slot
];
2560 /* Get packet length */
2562 frame_size
= request
->ios2_DataLength
;
2564 /* Copy frame into DMA buffer */
2566 CopyMem(request
->ios2_Data
, frame
, frame_size
);
2570 has_bssid
= ((frame
+ WIFI_FRM_ADDRESS1
)[0] & 0x1) == 0;
2571 i
= rate_table
->rateCodeToIndex
[unit
->mgmt_rate_code
];
2574 if((unit
->flags
& UNITF_SHORTPREAMBLE
) != 0)
2575 duration
= rate_table
->info
[i
].spAckDuration
;
2577 duration
= rate_table
->info
[i
].lpAckDuration
;
2581 *(UWORD
*)(frame
+ WIFI_FRM_DURATION
) = MakeLEWord(duration
);
2583 /* Fill in DMA descriptor for packet transmission */
2585 desc
->ds_link
= (ULONG
)(UPINT
)NULL
;
2586 unit
->hal
->ah_setupTxDesc(unit
->hal
, desc
, frame_size
+ 4, // + CRC?
2587 WIFI_FRM_DATA
, HAL_PKT_TYPE_NORMAL
, TX_POWER
,
2588 unit
->mgmt_rate_code
, TX_TRIES
, HAL_TXKEYIX_INVALID
,
2589 HAL_ANTENNA_MIN_MODE
,
2590 HAL_TXDESC_INTREQ
| HAL_TXDESC_CLRDMASK
2591 | (has_bssid
? 0 : HAL_TXDESC_NOACK
),
2593 unit
->hal
->ah_fillTxDesc(unit
->hal
, desc
, frame_size
, TRUE
, TRUE
,
2596 dma_size
= frame_size
;
2597 CachePreDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2599 /* Pass packet to adapter */
2601 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2602 last_slot
= (slot
+ MGMT_SLOT_COUNT
- 1) % MGMT_SLOT_COUNT
;
2603 if(unit
->mgmt_out_slot
!= slot
)
2604 //if(unit->hal->ah_numTxPending(unit->hal, unit->mgmt_queue_no) > 0)
2606 last_desc
= unit
->mgmt_descs
+ last_slot
;
2607 last_desc
->ds_link
=
2608 unit
->mgmt_descs_p
+ slot
* sizeof(struct ath_desc
);
2609 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2610 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2614 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2615 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2616 unit
->hal
->ah_setTxDP(unit
->hal
, unit
->mgmt_queue_no
,
2617 unit
->mgmt_descs_p
+ slot
* sizeof(struct ath_desc
));
2620 unit
->hal
->ah_startTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2621 unit
->mgmt_in_slot
= new_slot
;
2627 /* Don't try to keep sending packets if there's no space left */
2630 unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
= PA_SOFTINT
;
2632 unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
= PA_IGNORE
;
2639 /****i* atheros5000.device/MgmtTXEndInt ************************************
2642 * MgmtTXEndInt -- Clean up after a management frame has been sent.
2645 * MgmtTXEndInt(unit, int_code)
2647 * VOID MgmtTXEndInt(struct DevUnit *, APTR);
2650 * I think it's safe to assume that there will always be at least one
2651 * completed packet whenever this interrupt is called.
2653 ****************************************************************************
2657 static VOID
MgmtTXEndInt(REG(a1
, struct DevUnit
*unit
),
2658 REG(a6
, APTR int_code
))
2660 UWORD new_out_slot
, i
;
2662 struct DevBase
*base
;
2663 struct IOSana2Req
*request
;
2666 /* Find out which packets have completed */
2668 base
= unit
->device
;
2669 new_out_slot
= (unit
->mgmt_in_slot
+ MGMT_SLOT_COUNT
2670 - unit
->hal
->ah_numTxPending(unit
->hal
, unit
->mgmt_queue_no
))
2673 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2674 CachePostDMA(unit
->mgmt_descs
, &dma_size
, 0);
2676 /* Retire sent frames */
2678 for(i
= unit
->mgmt_out_slot
; i
!= new_out_slot
;
2679 i
= (i
+ 1) % MGMT_SLOT_COUNT
)
2681 frame
= unit
->mgmt_buffers
[i
];
2682 dma_size
= FRAME_BUFFER_SIZE
;
2683 CachePostDMA(frame
, &dma_size
, DMA_ReadFromRAM
);
2687 request
= unit
->mgmt_requests
[i
];
2688 request
->ios2_Req
.io_Error
= 0;
2689 ReplyMsg((APTR
)request
);
2692 unit
->mgmt_out_slot
= i
;
2694 dma_size
= sizeof(struct ath_desc
) * MGMT_SLOT_COUNT
;
2695 CachePreDMA(unit
->mgmt_descs
, &dma_size
, 0);
2697 /* Restart downloads if they had stopped */
2699 if(unit
->request_ports
[MGMT_QUEUE
]->mp_Flags
== PA_IGNORE
)
2700 Cause(&unit
->mgmt_int
);
2707 /****i* atheros5000.device/ResetHandler ************************************
2710 * ResetHandler -- Disable hardware before a reboot.
2713 * ResetHandler(unit, int_code)
2715 * VOID ResetHandler(struct DevUnit *, APTR);
2717 ****************************************************************************
2721 static VOID
ResetHandler(REG(a1
, struct DevUnit
*unit
),
2722 REG(a6
, APTR int_code
))
2724 if((unit
->flags
& UNITF_HAVEADAPTER
) != 0)
2726 /* Disable frame transmission */
2728 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->tx_queue_no
);
2729 unit
->hal
->ah_stopTxDma(unit
->hal
, unit
->mgmt_queue_no
);
2731 /* Disable frame reception */
2733 unit
->hal
->ah_stopPcuReceive(unit
->hal
);
2734 unit
->hal
->ah_stopDmaReceive(unit
->hal
);
2736 /* Stop interrupts */
2738 unit
->hal
->ah_setInterrupts(unit
->hal
, 0);
2746 /****i* atheros5000.device/UpdateStats *************************************
2754 * VOID UpdateStats(struct DevUnit *);
2759 * unit - A unit of this device.
2764 ****************************************************************************
2768 VOID
UpdateStats(struct DevUnit
*unit
, struct DevBase
*base
)
2770 /* Ask for and wait for stats */
2777 /****i* atheros5000.device/ReportEvents ************************************
2783 * ReportEvents(unit, events)
2785 * VOID ReportEvents(struct DevUnit *, ULONG);
2790 * unit - A unit of this device.
2791 * events - A mask of events to report.
2796 ****************************************************************************
2800 static VOID
ReportEvents(struct DevUnit
*unit
, ULONG events
,
2801 struct DevBase
*base
)
2803 struct IOSana2Req
*request
, *tail
, *next_request
;
2806 list
= &unit
->request_ports
[EVENT_QUEUE
]->mp_MsgList
;
2807 next_request
= (APTR
)list
->lh_Head
;
2808 tail
= (APTR
)&list
->lh_Tail
;
2811 while(next_request
!= tail
)
2813 request
= next_request
;
2814 next_request
= (APTR
)request
->ios2_Req
.io_Message
.mn_Node
.ln_Succ
;
2816 if((request
->ios2_WireError
& events
) != 0)
2818 request
->ios2_WireError
= events
;
2819 Remove((APTR
)request
);
2820 ReplyMsg((APTR
)request
);
2830 /****i* atheros5000.device/GetRadioBands ***********************************
2833 * GetRadioBands -- Get information on current network.
2836 * tag_list = GetRadioBands(unit, pool)
2838 * struct TagItem *GetRadioBands(struct DevUnit *, APTR);
2843 * unit - A unit of this device.
2844 * pool - A memory pool.
2849 ****************************************************************************
2854 struct TagItem
*GetRadioBands(struct DevUnit
*unit
, APTR pool
,
2855 struct DevBase
*base
)
2858 struct Sana2RadioBand
*bands
;
2861 bands
= AllocPooled(pool
, sizeof(struct Sana2RadioBand
) * 3);
2863 error
= S2ERR_NO_RESOURCES
;
2867 for(i
= 0; i
< 1; i
++)
2869 bands
[i
] = AllocPooled(pool
, sizeof(UWORD
) * unit
->channel_counts
[S2BAND_B
]);
2882 /****i* atheros5000.device/UnitTask ****************************************
2893 * Completes deferred requests, and handles card insertion and removal
2894 * in conjunction with the relevant interrupts.
2896 ****************************************************************************
2904 static VOID
UnitTask(struct ExecBase
*sys_base
)
2907 struct IORequest
*request
;
2908 struct DevUnit
*unit
;
2909 struct DevBase
*base
;
2910 struct MsgPort
*general_port
;
2911 ULONG signals
= 0, wait_signals
, card_removed_signal
,
2912 card_inserted_signal
, general_port_signal
;
2914 /* Get parameters */
2916 task
= AbsExecBase
->ThisTask
;
2917 unit
= task
->tc_UserData
;
2918 base
= unit
->device
;
2920 /* Activate general request port */
2922 general_port
= unit
->request_ports
[GENERAL_QUEUE
];
2923 general_port
->mp_SigTask
= task
;
2924 general_port
->mp_SigBit
= AllocSignal(-1);
2925 general_port_signal
= 1 << general_port
->mp_SigBit
;
2926 general_port
->mp_Flags
= PA_SIGNAL
;
2928 /* Allocate signals for notification of card removal and insertion */
2930 card_removed_signal
= unit
->card_removed_signal
= 1 << AllocSignal(-1);
2931 card_inserted_signal
= unit
->card_inserted_signal
= 1 << AllocSignal(-1);
2932 wait_signals
= (1 << general_port
->mp_SigBit
) | card_removed_signal
2933 | card_inserted_signal
| SIGBREAKF_CTRL_C
;
2935 /* Tell ourselves to check port for old messages */
2937 Signal(task
, general_port_signal
);
2939 /* Infinite loop to service requests and signals */
2941 while((signals
& SIGBREAKF_CTRL_C
) == 0)
2943 signals
= Wait(wait_signals
);
2945 if((signals
& card_inserted_signal
) != 0)
2947 if(unit
->insertion_function(unit
->card
, base
))
2949 unit
->flags
|= UNITF_HAVEADAPTER
;
2950 if((unit
->flags
& UNITF_CONFIGURED
) != 0)
2951 ConfigureAdapter(unit
, base
);
2952 if((unit
->flags
& UNITF_WASONLINE
) != 0)
2954 GoOnline(unit
, base
);
2955 unit
->flags
&= ~UNITF_WASONLINE
;
2960 if((signals
& card_removed_signal
) != 0)
2962 unit
->removal_function(unit
->card
, base
);
2963 if((unit
->flags
& UNITF_WASONLINE
) != 0)
2964 GoOffline(unit
, base
);
2967 if((signals
& general_port_signal
) != 0)
2969 while((request
= (APTR
)GetMsg(general_port
)) != NULL
)
2971 /* Service the request as soon as the unit is free */
2973 ObtainSemaphore(&unit
->access_lock
);
2974 ServiceRequest((APTR
)request
, base
);
2979 FreeMem(task
->tc_SPLower
, STACK_SIZE
);