Report S2EVENT_CONNECT when a new SSID is selected.
[AROS.git] / workbench / devs / networks / realtek8180 / unit.c
blob1d4be32a296a3cbc469069e4573919d20f575e84
1 /*
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,
18 MA 02111-1307, USA.
23 #include <exec/memory.h>
24 #include <exec/execbase.h>
25 #include <exec/errors.h>
27 #include <proto/exec.h>
28 #ifndef __amigaos4__
29 #include <proto/alib.h>
30 #else
31 #include <clib/alib_protos.h>
32 #endif
33 #include <proto/utility.h>
34 #include <proto/timer.h>
36 #include "device.h"
38 #include "unit_protos.h"
39 #include "request_protos.h"
40 #include "radio_protos.h"
41 #include "eeprom_protos.h"
42 #include "encryption_protos.h"
43 #include "timer_protos.h"
44 #include "realtek8187.h"
47 #define TASK_PRIORITY 0
48 #define STACK_SIZE 4096
49 #define INT_MASK 0xffff
50 #define TX_TRIES 7
51 #define SIFS_TIME 14
53 #ifndef AbsExecBase
54 #define AbsExecBase sys_base
55 #endif
57 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base);
58 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
59 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
60 UWORD upper_bound_right, struct DevBase *base);
61 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base);
62 static UBYTE *GetRXBuffer(struct DevUnit *unit, const UBYTE *address,
63 UWORD frag_no, UWORD *buffer_no, struct DevBase *base);
64 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *frame,
65 struct DevBase *base);
66 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
67 UWORD packet_size, UWORD packet_type, UBYTE *buffer,
68 struct DevBase *base);
69 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
70 struct DevBase *base);
71 static VOID DistributeMgmtFrame(struct DevUnit *unit, UBYTE *frame,
72 UWORD frame_size, struct DevBase *base);
73 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code));
74 static VOID MgmtTXInt(REG(a1, struct DevUnit *unit),
75 REG(a6, APTR int_code));
76 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
77 struct DevBase *base);
78 static UWORD GetDuration(struct DevUnit *unit, UWORD length, UWORD rate,
79 BOOL short_preamble, struct DevBase *base);
80 static UWORD AckRate(struct DevUnit *unit, UWORD data_rate,
81 struct DevBase *base);
82 static VOID UnitTask(struct ExecBase *sys_base);
85 static const UBYTE snap_template[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
86 static const UBYTE broadcast_address[] =
87 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
90 #ifdef __amigaos4__
91 #undef AddTask
92 #define AddTask(task, initial_pc, final_pc) \
93 IExec->AddTask(task, initial_pc, final_pc, NULL)
94 #endif
95 #ifdef __MORPHOS__
96 static const struct EmulLibEntry mos_task_trap =
98 TRAP_LIB,
100 (APTR)UnitTask
102 #define UnitTask &mos_task_trap
103 #endif
104 #ifdef __AROS__
105 #undef AddTask
106 #define AddTask(task, initial_pc, final_pc) \
107 ({ \
108 struct TagItem _task_tags[] = \
109 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
110 NewAddTask(task, initial_pc, final_pc, _task_tags); \
112 #endif
116 /****i* realtek8180.device/CreateUnit **************************************
118 * NAME
119 * CreateUnit -- Create a unit.
121 * SYNOPSIS
122 * unit = CreateUnit(index, io_base, id, card,
123 * io_tags, bus)
125 * struct DevUnit *CreateUnit(ULONG, APTR, UWORD, APTR,
126 * struct TagItem *, UWORD);
128 * FUNCTION
129 * Creates a new unit.
131 ****************************************************************************
135 struct DevUnit *CreateUnit(ULONG index, APTR card,
136 const struct TagItem *io_tags, UWORD bus, struct DevBase *base)
138 BOOL success = TRUE;
139 struct DevUnit *unit;
140 struct Task *task;
141 struct MsgPort *port;
142 UWORD i;
143 APTR stack;
145 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
146 if(unit == NULL)
147 success = FALSE;
149 if(success)
151 /* Initialise lists etc. */
153 NewList((APTR)&unit->openers);
154 NewList((APTR)&unit->type_trackers);
155 NewList((APTR)&unit->multicast_ranges);
157 unit->index = index;
158 unit->device = base;
159 unit->card = card;
160 unit->bus = bus;
161 unit->generation = RTL8187B1_GEN;
162 unit->tx_rate = 11;
163 unit->tx_rate_code = 3; /* 11 Mbps */
164 unit->mgmt_rate = 1;
165 unit->mgmt_rate_code = 0; /* 1 Mbps */
166 unit->channel = 1;
168 /* Store I/O hooks */
170 unit->ByteOut =
171 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
172 unit->ByteIn =
173 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
174 unit->LEWordIn =
175 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
176 unit->LELongIn =
177 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
178 unit->LEWordOut =
179 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
180 unit->LELongOut =
181 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
182 unit->AllocDMAMem =
183 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
184 unit->FreeDMAMem =
185 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
186 unit->SendFrame =
187 (APTR)GetTagData(IOTAG_SendFrame, (UPINT)NULL, io_tags);
188 unit->ReceiveFrame =
189 (APTR)GetTagData(IOTAG_ReceiveFrame, (UPINT)NULL, io_tags);
190 if(unit->ByteIn == NULL
191 || unit->ByteOut == NULL
192 || unit->LEWordIn == NULL
193 || unit->LELongIn == NULL
194 || unit->LEWordOut == NULL
195 || unit->LELongOut == NULL
196 || unit->AllocDMAMem == NULL
197 || unit->FreeDMAMem == NULL
198 || unit->SendFrame == NULL
199 || unit->ReceiveFrame == NULL)
200 success = FALSE;
203 if(success)
205 InitSemaphore(&unit->access_lock);
207 /* Create the message ports for queuing requests */
209 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
211 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
212 MEMF_PUBLIC | MEMF_CLEAR);
213 if(port == NULL)
214 success = FALSE;
216 if(success)
218 NewList(&port->mp_MsgList);
219 port->mp_Flags = PA_IGNORE;
223 if(success)
225 unit->request_ports[WRITE_QUEUE]->mp_SigTask = &unit->tx_int;
226 unit->request_ports[MGMT_QUEUE]->mp_SigTask = &unit->mgmt_int;
229 /* Allocate buffers and descriptors */
231 unit->tx_buffer = AllocVec(ETH_MAXPACKETSIZE, MEMF_PUBLIC);
232 for(i = 0; i < TX_SLOT_COUNT; i++)
234 unit->tx_descs[i] = unit->AllocDMAMem(unit->card,
235 R8180_MAXDESCSIZE + FRAME_BUFFER_SIZE, 4);
236 if(unit->tx_descs[i] != NULL)
237 unit->tx_buffers[i] = unit->tx_descs[i] + R8180_MAXDESCSIZE;
238 else
239 success = FALSE;
241 unit->rx_buffer = AllocVec(FRAME_BUFFER_SIZE, MEMF_PUBLIC);
242 for(i = 0; i < RX_SLOT_COUNT; i++)
244 if(unit->bus != USB_BUS)
246 unit->rx_descs[i] = unit->AllocDMAMem(unit->card,
247 R8180_MAXDESCSIZE, 4);
248 if(unit->rx_descs[i] == NULL)
249 success = FALSE;
251 unit->rx_buffers[i] = unit->AllocDMAMem(unit->card,
252 FRAME_BUFFER_SIZE + R8180_MAXDESCSIZE, 4);
253 if(unit->rx_buffers[i] == NULL)
254 success = FALSE;
256 unit->rx_frames =
257 AllocVec(FRAME_BUFFER_SIZE * FRAME_BUFFER_COUNT, MEMF_PUBLIC);
258 for(i = 0; i < FRAME_BUFFER_COUNT; i++)
259 unit->rx_fragment_nos[i] = -1;
260 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
261 MEMF_PUBLIC);
262 if(unit->tx_buffer == NULL
263 || unit->rx_buffer == NULL
264 || unit->rx_frames == NULL
265 || unit->tx_requests == NULL)
266 success = FALSE;
269 if(success)
271 /* Initialise network adapter hardware */
273 success = InitialiseAdapter(unit, FALSE, base);
274 unit->flags |= UNITF_HAVEADAPTER;
277 if(success)
279 /* Record maximum speed in BPS */
281 unit->speed = 54000000;
283 /* Initialise interrupts */
285 unit->rx_int.is_Node.ln_Name =
286 base->device.dd_Library.lib_Node.ln_Name;
287 unit->rx_int.is_Code = (APTR)RXInt;
288 unit->rx_int.is_Data = unit;
290 unit->tx_int.is_Node.ln_Name =
291 base->device.dd_Library.lib_Node.ln_Name;
292 unit->tx_int.is_Code = (APTR)TXInt;
293 unit->tx_int.is_Data = unit;
295 unit->mgmt_int.is_Node.ln_Name =
296 base->device.dd_Library.lib_Node.ln_Name;
297 unit->mgmt_int.is_Code = (APTR)MgmtTXInt;
298 unit->mgmt_int.is_Data = unit;
300 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
301 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
303 /* Create a new task */
305 unit->task = task =
306 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
307 if(task == NULL)
308 success = FALSE;
311 if(success)
313 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
314 if(stack == NULL)
315 success = FALSE;
318 if(success)
320 /* Initialise and start task */
322 task->tc_Node.ln_Type = NT_TASK;
323 task->tc_Node.ln_Pri = TASK_PRIORITY;
324 task->tc_Node.ln_Name = base->device.dd_Library.lib_Node.ln_Name;
325 task->tc_SPUpper = stack + STACK_SIZE;
326 task->tc_SPLower = stack;
327 task->tc_SPReg = stack + STACK_SIZE;
328 NewList(&task->tc_MemEntry);
330 if(AddTask(task, UnitTask, NULL) == NULL)
331 success = FALSE;
334 if(success)
336 /* Send the unit to the new task */
338 task->tc_UserData = unit;
340 /* Set default wireless options */
342 unit->mode = S2PORT_MANAGED;
345 if(!success)
347 DeleteUnit(unit, base);
348 unit = NULL;
351 return unit;
356 /****i* realtek8180.device/DeleteUnit **************************************
358 * NAME
359 * DeleteUnit -- Delete a unit.
361 * SYNOPSIS
362 * DeleteUnit(unit)
364 * VOID DeleteUnit(struct DevUnit *);
366 * FUNCTION
367 * Deletes a unit.
369 * INPUTS
370 * unit - Device unit (may be NULL).
372 * RESULT
373 * None.
375 ****************************************************************************
379 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
381 UBYTE i;
382 struct Task *task;
384 if(unit != NULL)
386 task = unit->task;
387 if(task != NULL)
389 if(task->tc_UserData != NULL)
391 RemTask(task);
392 FreeMem(task->tc_SPLower, STACK_SIZE);
394 FreeMem(task, sizeof(struct Task));
397 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
399 if(unit->request_ports[i] != NULL)
400 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
403 if((unit->flags & UNITF_ONLINE) != 0) /* Needed! */
404 GoOffline(unit, base);
406 if((unit->flags & UNITF_HAVEADAPTER) != 0)
407 DeinitialiseAdapter(unit, base);
409 for(i = 0; i < TX_SLOT_COUNT; i++)
410 unit->FreeDMAMem(unit->card, unit->tx_descs[i]);
411 for(i = 0; i < RX_SLOT_COUNT; i++)
413 unit->FreeDMAMem(unit->card, unit->rx_buffers[i]);
414 if(unit->bus != USB_BUS)
415 unit->FreeDMAMem(unit->card, unit->rx_descs[i]);
418 FreeVec(unit->tx_buffer);
419 FreeVec(unit->rx_frames);
420 FreeVec(unit->tx_requests);
421 FreeVec(unit->rx_buffer);
423 FreeMem(unit, sizeof(struct DevUnit));
426 return;
431 /****i* realtek8180.device/InitialiseAdapter *******************************
433 * NAME
434 * InitialiseAdapter
436 * SYNOPSIS
437 * success = InitialiseAdapter(unit, reinsertion)
439 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
441 * FUNCTION
443 * INPUTS
444 * unit
445 * reinsertion
447 * RESULT
448 * success - Success indicator.
450 ****************************************************************************
454 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
455 struct DevBase *base)
457 BOOL success = FALSE;
458 UBYTE reg_62, revision;
459 UWORD *p, i;
460 ULONG rx_conf;
462 /* Initialise EEPROM */
464 rx_conf = unit->LELongIn(unit->card, 0x100 + R8180REG_RXCONF);
465 unit->eeprom_addr_size = ((rx_conf & (1 << 6)) != 0) ? 8 : 6;
467 BusyMicroDelay(10, base);
468 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
470 /* Get default MAC address */
472 p = (UWORD *)unit->default_address;
473 for(i = 0; i < ETH_ADDRESSSIZE / sizeof(UWORD); i++)
474 *p++ = LEWord(ReadEEPROM(unit, R8180ROM_ADDRESS0 + i, base));
476 /* Refine main chip revision */
478 if(unit->generation == RTL8187B1_GEN)
480 revision = unit->ByteIn(unit->card, 0x100 + 0xe1);
481 if(revision == 1 || revision == 2)
482 unit->generation = RTL8187B2_GEN;
484 else
486 if((unit->LELongIn(unit->card, 0x100 + R8180REG_TXCONF)
487 & R8180REG_TXCONFF_HWVER) == 6 << R8180REG_TXCONFB_HWVER)
488 unit->generation = RTL8187B0_GEN;
491 /* Set up power tables */
493 GetPower(unit, base);
495 /* Tune the radio */
497 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
498 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
499 | R8180REG_CONFIG3F_ANAPARAMWRITE | R8180REG_CONFIG3F_GNTSELECT);
500 unit->LELongOut(unit->card, 0x100 + R8180REG_ANAPARAM2, 0x727f3f52);
501 unit->LELongOut(unit->card, 0x100 + R8180REG_ANAPARAM1, 0x45090658);
502 unit->ByteOut(unit->card, 0x100 + R8180REG_ANAPARAM3, 0);
504 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
505 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
506 & ~R8180REG_CONFIG3F_ANAPARAMWRITE);
508 /* Reset PLL sequence */
510 unit->ByteOut(unit->card, 0x161, 0x10);
511 reg_62 = unit->ByteIn(unit->card, 0x162);
512 unit->ByteOut(unit->card, 0x162, reg_62 & ~(1 << 5));
513 unit->ByteOut(unit->card, 0x162, reg_62 | (1 << 5));
515 /* Send reset command */
517 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
518 unit->ByteIn(unit->card, 0x100 + R8180REG_COMMAND)
519 & 0x2 | R8180REG_COMMANDF_RESET);
521 for(i = 0; i < 10 && !success; i++)
523 BusyMilliDelay(2, base);
524 if((unit->ByteIn(unit->card, 0x100 + R8180REG_COMMAND)
525 & R8180REG_COMMANDF_RESET) == 0)
526 success = TRUE;
529 if(success && unit->generation == RTL8187L_GEN)
531 /* Reload registers from EEPROM */
533 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_LOAD);
535 for(i = 0, success = FALSE; i < 10 && !success; i++)
537 BusyMilliDelay(4, base);
538 if((unit->ByteIn(unit->card, 0x100 + R8180REG_EEPROM)
539 & R8180REG_EEPROMF_COMMAND) == 0)
540 success = TRUE;
544 if(success)
546 /* Set up rates */
548 if(unit->generation == RTL8187L_GEN)
549 unit->LEWordOut(unit->card, 0x12d, 0xfff);
550 else
551 unit->LEWordOut(unit->card, 0x134, 0xfff);
552 unit->LEWordOut(unit->card, 0x12c, 0x1ff);
553 unit->ByteOut(unit->card, 0x100 + R8180REG_CWCONF,
554 unit->ByteIn(unit->card, 0x100 + R8180REG_CWCONF)
555 | R8180REG_CWCONFF_PPRETRYSHIFT);
556 unit->ByteOut(unit->card, 0x100 + R8180REG_TXAGCCTL,
557 unit->ByteIn(unit->card, 0x100 + R8180REG_TXAGCCTL)
558 | R8180REG_TXAGCCTLF_PPGAINSHIFT);
560 unit->LEWordOut(unit->card, 0x1e0 | 1 << 16, 0xfff);
561 unit->ByteOut(unit->card, 0x100 + R8180REG_RATEFALLBACK,
562 unit->ByteIn(unit->card, 0x100 + R8180REG_RATEFALLBACK)
563 | R8180REG_RATEFALLBACKF_ENABLE);
565 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR,
566 unit->ByteIn(unit->card, 0x100 + R8180REG_MSR) & 0xf3);
567 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR,
568 unit->ByteIn(unit->card, 0x100 + R8180REG_MSR)
569 | R8180REG_MSRF_ENEDCA);
570 unit->ByteOut(unit->card, 0x100 + R8180REG_ACMCONTROL, 0);
572 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMWINDOW, 2);
573 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL, 100);
574 unit->LEWordOut(unit->card, 0x1d4 | 1 << 16, 0xffff);
576 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
577 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG1,
578 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG1) & 0x3f | 0x80);
579 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, 0);
581 unit->ByteOut(unit->card, 0x100 + R8180REG_WPACONF, 0);
583 unit->ByteOut(unit->card, 0x1f0, 0x32);
584 unit->ByteOut(unit->card, 0x1f1, 0x32);
585 unit->ByteOut(unit->card, 0x1f2, 0x0);
586 unit->ByteOut(unit->card, 0x1f3, 0x0);
587 unit->ByteOut(unit->card, 0x1f4, 0x32);
588 unit->ByteOut(unit->card, 0x1f5, 0x43);
589 unit->ByteOut(unit->card, 0x1f6, 0x0);
590 unit->ByteOut(unit->card, 0x1f7, 0x0);
591 unit->ByteOut(unit->card, 0x1f8, 0x46);
592 unit->ByteOut(unit->card, 0x1f9, 0xa4);
593 unit->ByteOut(unit->card, 0x1fa, 0x0);
594 unit->ByteOut(unit->card, 0x1fb, 0x0);
595 unit->ByteOut(unit->card, 0x1fc, 0x96);
596 unit->ByteOut(unit->card, 0x1fd, 0xa4);
597 unit->ByteOut(unit->card, 0x1fe, 0x0);
598 unit->ByteOut(unit->card, 0x1ff, 0x0);
600 unit->ByteOut(unit->card, 0x158 | 1 << 16, 0x4b);
601 unit->ByteOut(unit->card, 0x159 | 1 << 16, 0x0);
602 unit->ByteOut(unit->card, 0x15a | 1 << 16, 0x4b);
603 unit->ByteOut(unit->card, 0x15b | 1 << 16, 0x0);
604 unit->ByteOut(unit->card, 0x160 | 1 << 16, 0x4b);
605 unit->ByteOut(unit->card, 0x161 | 1 << 16, 0x9);
606 unit->ByteOut(unit->card, 0x162 | 1 << 16, 0x4b);
607 unit->ByteOut(unit->card, 0x163 | 1 << 16, 0x9);
608 unit->ByteOut(unit->card, 0x1ce | 1 << 16, 0xf);
609 unit->ByteOut(unit->card, 0x1cf | 1 << 16, 0x0);
610 unit->ByteOut(unit->card, 0x1e0 | 1 << 16, 0xff);
611 unit->ByteOut(unit->card, 0x1e1 | 1 << 16, 0xf);
612 unit->ByteOut(unit->card, 0x1e2 | 1 << 16, 0x0);
613 unit->ByteOut(unit->card, 0x1f0 | 1 << 16, 0x4e);
614 unit->ByteOut(unit->card, 0x1f1 | 1 << 16, 0x1);
615 unit->ByteOut(unit->card, 0x1f2 | 1 << 16, 0x2);
616 unit->ByteOut(unit->card, 0x1f3 | 1 << 16, 0x3);
617 unit->ByteOut(unit->card, 0x1f4 | 1 << 16, 0x4);
618 unit->ByteOut(unit->card, 0x1f5 | 1 << 16, 0x5);
619 unit->ByteOut(unit->card, 0x1f6 | 1 << 16, 0x6);
620 unit->ByteOut(unit->card, 0x1f7 | 1 << 16, 0x7);
621 unit->ByteOut(unit->card, 0x1f8 | 1 << 16, 0x8);
623 unit->ByteOut(unit->card, 0x14e | 2 << 16, 0x0);
624 unit->ByteOut(unit->card, 0x10c | 2 << 16, 0x4);
625 unit->ByteOut(unit->card, 0x121 | 2 << 16, 0x61);
626 unit->ByteOut(unit->card, 0x122 | 2 << 16, 0x68);
627 unit->ByteOut(unit->card, 0x123 | 2 << 16, 0x6f);
628 unit->ByteOut(unit->card, 0x124 | 2 << 16, 0x76);
629 unit->ByteOut(unit->card, 0x125 | 2 << 16, 0x7d);
630 unit->ByteOut(unit->card, 0x126 | 2 << 16, 0x84);
631 unit->ByteOut(unit->card, 0x127 | 2 << 16, 0x8d);
632 unit->ByteOut(unit->card, 0x14d | 2 << 16, 0x8);
633 unit->ByteOut(unit->card, 0x150 | 2 << 16, 0x5);
634 unit->ByteOut(unit->card, 0x151 | 2 << 16, 0xf5);
635 unit->ByteOut(unit->card, 0x152 | 2 << 16, 0x4);
636 unit->ByteOut(unit->card, 0x153 | 2 << 16, 0xa0);
637 unit->ByteOut(unit->card, 0x154 | 2 << 16, 0x1f);
638 unit->ByteOut(unit->card, 0x155 | 2 << 16, 0x23);
639 unit->ByteOut(unit->card, 0x156 | 2 << 16, 0x45);
640 unit->ByteOut(unit->card, 0x157 | 2 << 16, 0x67);
641 unit->ByteOut(unit->card, 0x158 | 2 << 16, 0x8);
642 unit->ByteOut(unit->card, 0x159 | 2 << 16, 0x8);
643 unit->ByteOut(unit->card, 0x15a | 2 << 16, 0x8);
644 unit->ByteOut(unit->card, 0x15b | 2 << 16, 0x8);
645 unit->ByteOut(unit->card, 0x160 | 2 << 16, 0x8);
646 unit->ByteOut(unit->card, 0x161 | 2 << 16, 0x8);
647 unit->ByteOut(unit->card, 0x162 | 2 << 16, 0x8);
648 unit->ByteOut(unit->card, 0x163 | 2 << 16, 0x8);
649 unit->ByteOut(unit->card, 0x164 | 2 << 16, 0xcf);
650 unit->ByteOut(unit->card, 0x172 | 2 << 16, 0x56);
651 unit->ByteOut(unit->card, 0x173 | 2 << 16, 0x9a);
653 unit->ByteOut(unit->card, 0x134, 0xf0);
654 unit->ByteOut(unit->card, 0x135, 0xf);
655 unit->ByteOut(unit->card, 0x15b, 0x40);
656 unit->ByteOut(unit->card, 0x184, 0x88);
657 unit->ByteOut(unit->card, 0x185, 0x24);
658 unit->ByteOut(unit->card, 0x188, 0x54);
659 unit->ByteOut(unit->card, 0x18b, 0xb8);
660 unit->ByteOut(unit->card, 0x18c, 0x7);
661 unit->ByteOut(unit->card, 0x18d, 0x0);
662 unit->ByteOut(unit->card, 0x194, 0x1b);
663 unit->ByteOut(unit->card, 0x195, 0x12);
664 unit->ByteOut(unit->card, 0x196, 0x0);
665 unit->ByteOut(unit->card, 0x197, 0x6);
666 unit->ByteOut(unit->card, 0x19d, 0x1a);
667 unit->ByteOut(unit->card, 0x19f, 0x10);
668 unit->ByteOut(unit->card, 0x1b4, 0x22);
669 unit->ByteOut(unit->card, 0x1be, 0x80);
670 unit->ByteOut(unit->card, 0x1db, 0x0);
671 unit->ByteOut(unit->card, 0x1ee, 0x0);
672 unit->ByteOut(unit->card, 0x191, 0x3);
673 unit->ByteOut(unit->card, 0x14c | 2 << 16, 0x0);
675 unit->ByteOut(unit->card, 0x19f | 3 << 16, 0x0);
676 unit->ByteOut(unit->card, 0x18c, 0x1);
677 unit->ByteOut(unit->card, 0x18d, 0x10);
678 unit->ByteOut(unit->card, 0x18e, 0x8);
679 unit->ByteOut(unit->card, 0x18f, 0x0);
681 unit->LEWordOut(unit->card, 0x100 + R8180REG_TIDACMAP, 0xfa50);
682 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMIG, 0);
684 unit->LELongOut(unit->card, 0x1f0 | 1 << 16, 0);
685 unit->LELongOut(unit->card, 0x1f4 | 1 << 16, 0);
686 unit->ByteOut(unit->card, 0x1f8 | 1 << 16, 0);
688 unit->LELongOut(unit->card, 0x100 + R8180REG_RFTIMING, 0x4001);
690 unit->LEWordOut(unit->card, 0x172 | 2 << 16, 0x569a);
692 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
694 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
695 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
696 | R8180REG_CONFIG3F_ANAPARAMWRITE);
697 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, 0);
699 /* Turn LED on */
701 unit->ByteOut(unit->card, 0x100 + R8180REG_GPIO0, 1);
702 unit->ByteOut(unit->card, 0x100 + R8180REG_GPENABLE, 0);
704 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSOUTPUT, 0x480);
705 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSSELECT, 0x2488);
706 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSENABLE, 0x1fff);
707 BusyMilliDelay(100, base);
709 /* Initialise radio */
711 success = InitialiseRadio(unit, base);
713 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
714 R8180REG_COMMANDF_TXENABLE | R8180REG_COMMANDF_RXENABLE);
715 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMASK, INT_MASK);
717 unit->ByteOut(unit->card, 0x41, 0xf4);
718 unit->ByteOut(unit->card, 0x40, 0);
719 unit->ByteOut(unit->card, 0x42, 0);
720 unit->ByteOut(unit->card, 0x42, 1);
721 unit->ByteOut(unit->card, 0x40, 0xf);
722 unit->ByteOut(unit->card, 0x42, 0);
723 unit->ByteOut(unit->card, 0x42, 1);
725 unit->ByteOut(unit->card, 0x1db,
726 unit->ByteIn(unit->card, 0x1db) | 1 << 2);
727 unit->LEWordOut(unit->card, 0x172 | 3 << 16, 0x59fa);
728 unit->LEWordOut(unit->card, 0x174 | 3 << 16, 0x59d2);
729 unit->LEWordOut(unit->card, 0x176 | 3 << 16, 0x59d2);
730 unit->LEWordOut(unit->card, 0x178 | 3 << 16, 0x19fa);
731 unit->LEWordOut(unit->card, 0x17a | 3 << 16, 0x19fa);
732 unit->LEWordOut(unit->card, 0x17c | 3 << 16, 0xd0);
733 unit->ByteOut(unit->card, 0x161, 0);
734 unit->ByteOut(unit->card, 0x180 | 1 << 16, 0xf);
735 unit->ByteOut(unit->card, 0x183 | 1 << 16, 3);
736 unit->ByteOut(unit->card, 0x1da, 0x10);
737 unit->ByteOut(unit->card, 0x14d | 2 << 16, 8);
739 unit->LELongOut(unit->card, 0x100 + R8180REG_HSSIPARA, 0x600321b);
741 /* Set maximum RX frame size */
743 unit->LEWordOut(unit->card, 0x1ec | 1 << 16, 0x800);
745 unit->ByteOut(unit->card, 0x100 + R8180REG_ACMCONTROL, 0);
746 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR, R8180REG_MSRF_ENEDCA);
749 if(success)
751 unit->LELongOut(unit->card, 0x100 + R8180REG_RXCONF,
752 R8180REG_RXCONFF_EARLYTHRESH
753 | R8180REG_RXCONFF_AUTORESETPHY
754 | R8180REG_RXCONFF_CHECKBSSID
755 | R8180REG_RXCONFF_MGMT
756 | R8180REG_RXCONFF_DATA
757 | 7 << R8180REG_RXCONFB_FIFOTHRESH
758 | 7 << R8180REG_RXCONFB_MAXDMA
759 | R8180REG_RXCONFF_BCAST
760 | R8180REG_RXCONFF_MCAST
761 | R8180REG_RXCONFF_UCAST);
762 unit->ByteOut(unit->card, 0x100 + R8180REG_TXAGCCTL,
763 unit->ByteIn(unit->card, 0x100 + R8180REG_TXAGCCTL)
764 & ~(R8180REG_TXAGCCTLF_PPGAINSHIFT
765 | R8180REG_TXAGCCTLF_PPANTSELSHIFT
766 | R8180REG_TXAGCCTLF_FEEDBACKANT));
767 unit->LELongOut(unit->card, 0x100 + R8180REG_TXCONF,
768 R8180REG_TXCONFF_DISREQQSIZE
769 | 7 << R8180REG_TXCONFB_MAXDMA
770 | TX_TRIES << R8180REG_TXCONFB_SHORTTRIES
771 | TX_TRIES << R8180REG_TXCONFB_LONGTRIES);
774 /* Determine features, and get offsets of certain fields within frame
775 descriptors */
777 unit->retries_offset = R8180FRM_RETRY;
778 unit->tx_desc_size = 32;
779 unit->rx_desc_size = 20;
781 /* Set IV sizes */
783 unit->iv_sizes[S2ENC_WEP] = IV_SIZE;
784 unit->iv_sizes[S2ENC_TKIP] = EIV_SIZE;
785 unit->iv_sizes[S2ENC_CCMP] = EIV_SIZE;
787 /* Set encryption functions */
789 unit->fragment_encrypt_functions[S2ENC_NONE] = WriteClearFragment;
791 if((unit->flags & UNITF_HARDWEP) != 0)
792 unit->fragment_encrypt_functions[S2ENC_WEP] = WriteWEPFragment;
793 else
794 unit->fragment_encrypt_functions[S2ENC_WEP] = EncryptWEPFragment;
796 if((unit->flags & UNITF_HARDTKIP) != 0)
797 unit->fragment_encrypt_functions[S2ENC_TKIP] = WriteTKIPFragment;
798 else
799 unit->fragment_encrypt_functions[S2ENC_TKIP] = EncryptTKIPFragment;
801 if((unit->flags & UNITF_HARDCCMP) != 0)
802 unit->fragment_encrypt_functions[S2ENC_CCMP] = WriteCCMPFragment;
803 else
804 unit->fragment_encrypt_functions[S2ENC_CCMP] = EncryptCCMPFragment;
806 /* Set decryption functions */
808 unit->fragment_decrypt_functions[S2ENC_NONE] = ReadClearFragment;
810 if((unit->flags & UNITF_HARDWEP) != 0)
811 unit->fragment_decrypt_functions[S2ENC_WEP] = ReadWEPFragment;
812 else
813 unit->fragment_decrypt_functions[S2ENC_WEP] = DecryptWEPFragment;
815 if((unit->flags & UNITF_HARDTKIP) != 0)
816 unit->fragment_decrypt_functions[S2ENC_TKIP] = ReadTKIPFragment;
817 else
818 unit->fragment_decrypt_functions[S2ENC_TKIP] = DecryptTKIPFragment;
820 if((unit->flags & UNITF_HARDCCMP) != 0)
821 unit->fragment_decrypt_functions[S2ENC_CCMP] = ReadCCMPFragment;
822 else
823 unit->fragment_decrypt_functions[S2ENC_CCMP] = DecryptCCMPFragment;
825 /* Return */
827 return success;
832 /****i* realtek8180.device/DeinitialiseAdapter *****************************
834 * NAME
835 * DeinitialiseAdapter
837 * SYNOPSIS
838 * DeinitialiseAdapter(unit)
840 * VOID DeinitialiseAdapter(struct DevUnit *);
842 * FUNCTION
844 * INPUTS
845 * unit
847 * RESULT
848 * None.
850 ****************************************************************************
854 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base)
856 /* Turn LED off */
858 unit->ByteOut(unit->card, 0x100 + R8180REG_GPIO0, 1);
859 unit->ByteOut(unit->card, 0x100 + R8180REG_GPENABLE, 1);
861 return;
866 /****i* realtek8180.device/ConfigureAdapter ********************************
868 * NAME
869 * ConfigureAdapter -- Set up card for transmission/reception.
871 * SYNOPSIS
872 * ConfigureAdapter(unit)
874 * VOID ConfigureAdapter(struct DevUnit *);
876 ****************************************************************************
880 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
882 UBYTE msr;
883 UWORD i;
885 /* Set BSSID */
887 for(i = 0; i < ETH_ADDRESSSIZE; i++)
888 unit->ByteOut(unit->card, 0x100 + R8180REG_BSSID + i, unit->bssid[i]);
890 /* Set channel and power */
892 SetPower(unit, base);
894 msr = unit->ByteIn(unit->card, 0x100 + R8180REG_MSR)
895 & ~R8180REG_MSRF_LINK;
896 if(unit->assoc_id != 0)
898 msr |= 2 << R8180REG_MSRB_LINK;
899 if(unit->generation >= RTL8187B0_GEN)
900 msr |= R8180REG_MSRF_ENEDCA;
902 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR, msr);
904 /* Set intervals */
906 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMWINDOW, 2);
907 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMTRINTERVAL, 100);
908 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL, 100);
909 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL2, 100);
911 if(unit->generation >= RTL8187B0_GEN)
913 unit->ByteOut(unit->card, 0x100 + R8180REG_SIFS, 0x22);
914 if(unit->band == S2BAND_G)
915 unit->ByteOut(unit->card, 0x100 + R8180REG_SLOT, 0x9);
916 else
917 unit->ByteOut(unit->card, 0x100 + R8180REG_SLOT, 0x14);
918 unit->ByteOut(unit->card, 0x100 + R8180REG_EIFS, 0x5b);
919 unit->ByteOut(unit->card, 0x100 + R8180REG_SENSECOUNT, 0x5b);
922 /* Return */
924 return;
929 /****i* realtek8180.device/GoOnline ****************************************
931 * NAME
932 * GoOnline -- Enable transmission/reception.
934 * SYNOPSIS
935 * GoOnline(unit)
937 * VOID GoOnline(struct DevUnit *);
939 ****************************************************************************
943 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
945 /* Enable interrupts */
947 unit->flags |= UNITF_ONLINE;
948 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMASK, INT_MASK);
950 /* Enable frame transmission and reception */
952 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
953 R8180REG_COMMANDF_TXENABLE | R8180REG_COMMANDF_RXENABLE);
955 /* Record start time and report Online event */
957 GetSysTime(&unit->stats.LastStart);
958 ReportEvents(unit, S2EVENT_ONLINE, base);
960 return;
965 /****i* realtek8180.device/GoOffline ***************************************
967 * NAME
968 * GoOffline -- Disable transmission/reception.
970 * SYNOPSIS
971 * GoOffline(unit)
973 * VOID GoOffline(struct DevUnit *);
975 * FUNCTION
977 * INPUTS
978 * unit
980 * RESULT
981 * None.
983 ****************************************************************************
987 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
989 unit->flags &= ~UNITF_ONLINE;
991 /* Flush pending read and write requests */
993 FlushUnit(unit, MGMT_QUEUE, S2ERR_OUTOFSERVICE, base);
995 /* Report Offline event and return */
997 ReportEvents(unit, S2EVENT_OFFLINE, base);
998 return;
1003 /****i* realtek8180.device/SetOptions **************************************
1005 * NAME
1006 * SetOptions -- Set and use interface options.
1008 * SYNOPSIS
1009 * reconfigure = SetOptions(unit, tag_list)
1011 * BOOL SetOptions(struct DevUnit *, struct TagItem *);
1013 ****************************************************************************
1017 BOOL SetOptions(struct DevUnit *unit, const struct TagItem *tag_list,
1018 struct DevBase *base)
1020 struct TagItem *tag_item, *tlist = (struct TagItem *)tag_list;
1021 BOOL reconfigure = TRUE;
1023 while((tag_item = NextTagItem(&tlist)) != NULL)
1025 switch(tag_item->ti_Tag)
1027 case S2INFO_SSID:
1028 ReportEvents(unit, S2EVENT_CONNECT, base);
1029 break;
1031 case S2INFO_BSSID:
1032 CopyMem((APTR)tag_item->ti_Data, unit->bssid, ETH_ADDRESSSIZE);
1033 break;
1035 case S2INFO_AssocID:
1036 unit->assoc_id = tag_item->ti_Data;
1037 break;
1039 case S2INFO_Capabilities:
1040 unit->capabilities = tag_item->ti_Data;
1041 if((unit->capabilities & (1 << 5)) != 0)
1042 unit->flags |= UNITF_SHORTPREAMBLE;
1043 else
1044 unit->flags &= ~UNITF_SHORTPREAMBLE;
1045 break;
1047 case S2INFO_DefaultKeyNo:
1048 unit->tx_key_no = tag_item->ti_Data;
1049 break;
1051 case S2INFO_PortType:
1052 unit->mode = tag_item->ti_Data;
1053 break;
1055 case S2INFO_Channel:
1056 if(tag_item->ti_Data != unit->channel)
1058 unit->channel = tag_item->ti_Data;
1059 reconfigure = TRUE;
1061 break;
1063 case S2INFO_Band:
1064 unit->band = tag_item->ti_Data;
1065 if(unit->band == S2BAND_G)
1067 unit->tx_rate = 54;
1068 unit->tx_rate_code = 11; /* 54 Mbps */
1069 unit->mgmt_rate = 2;
1070 unit->mgmt_rate_code = 1; /* 2 Mbps */
1072 else if(unit->band == S2BAND_B)
1074 unit->tx_rate = 11;
1075 unit->tx_rate_code = 3; /* 11 Mbps */
1076 unit->mgmt_rate = 1;
1077 unit->mgmt_rate_code = 0; /* 1 Mbps */
1079 break;
1084 return reconfigure;
1089 /****i* realtek8180.device/SetKey ******************************************
1091 * NAME
1092 * SetKey -- Set an encryption key.
1094 * SYNOPSIS
1095 * SetKey(unit, index, type, key, key_length,
1096 * rx_counter)
1098 * VOID SetKey(struct DevUnit *, ULONG, ULONG, UBYTE *, ULONG,
1099 * UBYTE *);
1101 ****************************************************************************
1105 VOID SetKey(struct DevUnit *unit, ULONG index, ULONG type, const UBYTE *key,
1106 ULONG key_length, const UBYTE *rx_counter, struct DevBase *base)
1108 struct KeyUnion *slot;
1109 struct EClockVal eclock;
1110 UWORD i;
1112 Disable();
1113 slot = &unit->keys[index];
1114 switch(type)
1116 case S2ENC_WEP:
1117 CopyMem(key, slot->u.wep.key, key_length);
1118 slot->u.wep.length = key_length;
1120 if((unit->flags & UNITF_HARDWEP) == 0)
1122 /* Create a reasonably random IV */
1124 ReadEClock(&eclock);
1125 slot->u.wep.tx_iv = FastRand(eclock.ev_lo ^ eclock.ev_hi);
1128 break;
1130 case S2ENC_TKIP:
1131 CopyMem(key, slot->u.tkip.key, 16);
1132 CopyMem(key + 16, slot->u.tkip.tx_mic_key, MIC_SIZE);
1133 CopyMem(key + 24, slot->u.tkip.rx_mic_key, MIC_SIZE);
1134 slot->u.tkip.tx_iv_low = 0;
1135 slot->u.tkip.tx_iv_high = 0;
1136 slot->u.tkip.rx_iv_low = LEWord(*(UWORD *)rx_counter);
1137 slot->u.tkip.rx_iv_high = LELong(*(ULONG *)(rx_counter + 2));
1138 slot->u.tkip.tx_ttak_set = FALSE;
1139 slot->u.tkip.rx_ttak_set = FALSE;
1141 if((unit->flags & UNITF_HARDTKIP) != 0)
1144 else
1146 /* Convert key to native endianness */
1148 for(i = 0; i < 8; i++)
1149 slot->u.tkip.key[i] = LEWord(slot->u.tkip.key[i]);
1152 break;
1154 case S2ENC_CCMP:
1155 CopyMem(key, slot->u.ccmp.key, 16);
1156 slot->u.ccmp.tx_iv_low = 0;
1157 slot->u.ccmp.tx_iv_high = 0;
1158 slot->u.ccmp.rx_iv_low = LEWord(*(UWORD *)rx_counter);
1159 slot->u.ccmp.rx_iv_high = LELong(*(ULONG *)(rx_counter + 2));
1160 slot->u.ccmp.stream_set = FALSE;
1163 /* Update type of key in selected slot */
1165 slot->type = type;
1166 Enable();
1168 return;
1173 /****i* realtek8180.device/AddMulticastRange *******************************
1175 * NAME
1176 * AddMulticastRange
1178 * SYNOPSIS
1179 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1181 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1183 ****************************************************************************
1187 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1188 const UBYTE *upper_bound, struct DevBase *base)
1190 struct AddressRange *range;
1191 ULONG lower_bound_left, upper_bound_left;
1192 UWORD lower_bound_right, upper_bound_right;
1194 lower_bound_left = BELong(*((ULONG *)lower_bound));
1195 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1196 upper_bound_left = BELong(*((ULONG *)upper_bound));
1197 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1199 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1200 upper_bound_left, upper_bound_right, base);
1202 if(range != NULL)
1203 range->add_count++;
1204 else
1206 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1207 if(range != NULL)
1209 range->lower_bound_left = lower_bound_left;
1210 range->lower_bound_right = lower_bound_right;
1211 range->upper_bound_left = upper_bound_left;
1212 range->upper_bound_right = upper_bound_right;
1213 range->add_count = 1;
1215 Disable();
1216 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
1217 unit->range_count++;
1218 SetMulticast(unit, base);
1219 Enable();
1223 return range != NULL;
1228 /****i* realtek8180.device/RemMulticastRange *******************************
1230 * NAME
1231 * RemMulticastRange
1233 * SYNOPSIS
1234 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1236 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1238 ****************************************************************************
1242 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1243 const UBYTE *upper_bound, struct DevBase *base)
1245 struct AddressRange *range;
1246 ULONG lower_bound_left, upper_bound_left;
1247 UWORD lower_bound_right, upper_bound_right;
1249 lower_bound_left = BELong(*((ULONG *)lower_bound));
1250 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1251 upper_bound_left = BELong(*((ULONG *)upper_bound));
1252 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1254 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1255 upper_bound_left, upper_bound_right, base);
1257 if(range != NULL)
1259 if(--range->add_count == 0)
1261 Disable();
1262 Remove((APTR)range);
1263 unit->range_count--;
1264 SetMulticast(unit, base);
1265 Enable();
1266 FreeMem(range, sizeof(struct AddressRange));
1270 return range != NULL;
1275 /****i* realtek8180.device/FindMulticastRange ******************************
1277 * NAME
1278 * FindMulticastRange
1280 * SYNOPSIS
1281 * range = FindMulticastRange(unit, lower_bound_left,
1282 * lower_bound_right, upper_bound_left, upper_bound_right)
1284 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1285 * UWORD, ULONG, UWORD);
1287 ****************************************************************************
1291 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
1292 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
1293 UWORD upper_bound_right, struct DevBase *base)
1295 struct AddressRange *range, *tail;
1296 BOOL found = FALSE;
1298 range = (APTR)unit->multicast_ranges.mlh_Head;
1299 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1301 while(range != tail && !found)
1303 if(lower_bound_left == range->lower_bound_left &&
1304 lower_bound_right == range->lower_bound_right &&
1305 upper_bound_left == range->upper_bound_left &&
1306 upper_bound_right == range->upper_bound_right)
1307 found = TRUE;
1308 else
1309 range = (APTR)range->node.mln_Succ;
1312 if(!found)
1313 range = NULL;
1315 return range;
1320 /****i* realtek8180.device/SetMulticast ************************************
1322 * NAME
1323 * SetMulticast
1325 * SYNOPSIS
1326 * SetMulticast(unit)
1328 * VOID SetMulticast(struct DevUnit *);
1330 ****************************************************************************
1334 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base)
1336 return;
1341 /****i* realtek8180.device/FindTypeStats ***********************************
1343 * NAME
1344 * FindTypeStats
1346 * SYNOPSIS
1347 * stats = FindTypeStats(unit, list,
1348 * packet_type)
1350 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1351 * ULONG);
1353 ****************************************************************************
1357 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
1358 ULONG packet_type, struct DevBase *base)
1360 struct TypeStats *stats, *tail;
1361 BOOL found = FALSE;
1363 stats = (APTR)list->mlh_Head;
1364 tail = (APTR)&list->mlh_Tail;
1366 while(stats != tail && !found)
1368 if(stats->packet_type == packet_type)
1369 found = TRUE;
1370 else
1371 stats = (APTR)stats->node.mln_Succ;
1374 if(!found)
1375 stats = NULL;
1377 return stats;
1382 /****i* realtek8180.device/FlushUnit ***************************************
1384 * NAME
1385 * FlushUnit
1387 * SYNOPSIS
1388 * FlushUnit(unit, last_queue, error)
1390 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1392 ****************************************************************************
1396 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
1397 struct DevBase *base)
1399 struct IORequest *request;
1400 UBYTE i;
1401 struct Opener *opener, *tail;
1403 /* Abort queued requests */
1405 for(i = 0; i <= last_queue; i++)
1407 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
1409 request->io_Error = IOERR_ABORTED;
1410 ReplyMsg((APTR)request);
1414 #if 1
1415 opener = (APTR)unit->openers.mlh_Head;
1416 tail = (APTR)&unit->openers.mlh_Tail;
1418 /* Flush every opener's read queues */
1420 while(opener != tail)
1422 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1424 request->io_Error = error;
1425 ReplyMsg((APTR)request);
1427 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
1429 request->io_Error = error;
1430 ReplyMsg((APTR)request);
1432 opener = (APTR)opener->node.mln_Succ;
1435 #else
1436 opener = request->ios2_BufferManagement;
1437 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1439 request->io_Error = IOERR_ABORTED;
1440 ReplyMsg((APTR)request);
1442 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
1444 request->io_Error = IOERR_ABORTED;
1445 ReplyMsg((APTR)request);
1447 #endif
1449 /* Return */
1451 return;
1456 /****i* realtek8180.device/RXInt *******************************************
1458 * NAME
1459 * RXInt -- Soft interrupt for packet reception.
1461 * SYNOPSIS
1462 * RXInt(unit)
1464 * VOID RXInt(struct DevUnit *);
1466 * FUNCTION
1468 * INPUTS
1469 * unit - A unit of this device.
1471 * RESULT
1472 * None.
1474 ****************************************************************************
1478 VOID RXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
1480 UWORD ieee_length, frame_control, frame_type, slot, next_slot,
1481 frame_size, frame_subtype, encryption, key_no, buffer_no, old_length;
1482 struct DevBase *base;
1483 BOOL is_good, proceed = TRUE;
1484 LONG frag_no;
1485 ULONG status;
1486 UBYTE *rx_desc, *buffer, *p, *frame, *data, *snap_frame, *source;
1488 base = unit->device;
1489 slot = unit->rx_slot;
1490 rx_desc = unit->rx_descs[slot];
1491 next_slot = (slot + 1) % RX_SLOT_COUNT;
1493 while(proceed)
1495 is_good = TRUE;
1496 buffer = unit->rx_buffers[slot];
1498 status = LELong(*(ULONG *)(rx_desc + R8180FRM_RXSTATUS));
1499 frame_size = status & R8180FRM_RXSTATUSF_LENGTH;
1501 if((status & (R8180FRM_RXSTATUSF_DMAERR | R8180FRM_RXSTATUSF_OVERFLOW
1502 | R8180FRM_RXSTATUSF_RXERR | R8180FRM_RXSTATUSF_BADCRC)) == 0
1503 && frame_size >= WIFI_FRM_DATA + 4)
1505 /* Get fragment info */
1507 frame = buffer;
1508 ieee_length = frame_size - 4 - WIFI_FRM_DATA;
1509 data = frame + WIFI_FRM_DATA;
1510 frame_control =
1511 LEWord(*(UWORD *)(frame + WIFI_FRM_CONTROL));
1513 /* Get buffer to store fragment in */
1515 frag_no = LEWord(*(UWORD *)(frame + WIFI_FRM_SEQCONTROL));
1516 if(unit->mode == S2PORT_ADHOC)
1517 source = frame + WIFI_FRM_ADDRESS2;
1518 else
1519 source = frame + WIFI_FRM_ADDRESS3;
1520 snap_frame = GetRXBuffer(unit, source, frag_no, &buffer_no, base);
1522 /* Get location to put new data */
1524 if(snap_frame != NULL)
1526 if((frag_no & 0xf ) > 0)
1527 old_length =
1528 BEWord(*(UWORD *)(snap_frame + ETH_PACKET_IEEELEN));
1529 else
1531 /* Create new 802.3 header */
1533 CopyMem(frame + WIFI_FRM_ADDRESS1, snap_frame,
1534 ETH_ADDRESSSIZE);
1535 CopyMem(source, snap_frame + ETH_PACKET_SOURCE,
1536 ETH_ADDRESSSIZE);
1537 old_length = 0;
1539 p = snap_frame + ETH_HEADERSIZE + old_length;
1541 /* Append fragment to frame, decrypting fragment if necessary */
1543 if((frame_control & WIFI_FRM_CONTROLF_WEP) != 0)
1545 key_no = data[3] >> 6 & 0x3;
1546 encryption = unit->keys[key_no].type;
1548 else
1549 encryption = S2ENC_NONE;
1551 /* Decrypt, check and/or copy fragment */
1553 is_good = unit->fragment_decrypt_functions[encryption](unit,
1554 frame, data, &ieee_length, p, base);
1556 /* Update length in frame being built with current fragment, or
1557 increment bad frame counter if fragment is bad */
1559 if(is_good)
1561 ieee_length += old_length;
1562 *(UWORD *)(snap_frame + ETH_PACKET_IEEELEN) =
1563 MakeBEWord(ieee_length);
1565 else
1566 unit->stats.BadData++;
1568 /* If all fragments have arrived, process the complete frame */
1570 if((frame_control & WIFI_FRM_CONTROLF_MOREFRAGS) == 0)
1572 if(is_good)
1574 /* Decrypt complete frame if necessary */
1576 data = snap_frame + ETH_HEADERSIZE;
1577 if(encryption == S2ENC_TKIP
1578 && (unit->flags & UNITF_HARDTKIP) == 0)
1580 is_good = TKIPDecryptFrame(unit, snap_frame, data,
1581 ieee_length, data, key_no, base);
1582 ieee_length -= MIC_SIZE;
1583 *(UWORD *)(snap_frame + ETH_PACKET_IEEELEN) =
1584 MakeBEWord(ieee_length);
1585 if(!is_good)
1586 unit->stats.BadData++;
1590 if(is_good)
1592 /* Get frame's 802.11 type and subtype */
1594 frame_type = (frame_control & WIFI_FRM_CONTROLF_TYPE)
1595 >> WIFI_FRM_CONTROLB_TYPE;
1596 frame_subtype =
1597 (frame_control & WIFI_FRM_CONTROLF_SUBTYPE)
1598 >> WIFI_FRM_CONTROLB_SUBTYPE;
1600 /* If it's a management frame, process it separately;
1601 otherwise distribute it to clients after filtering */
1603 if(frame_type == WIFI_FRMTYPE_MGMT)
1605 if(frame_subtype != 8)
1606 DistributeMgmtFrame(unit, frame, frame_size - 4,
1607 base);
1609 else if(AddressFilter(unit, snap_frame + ETH_PACKET_DEST,
1610 base))
1612 unit->stats.PacketsReceived++;
1613 DistributeRXPacket(unit, snap_frame, base);
1618 /* Mark fragment buffer as unused for next time */
1620 unit->rx_fragment_nos[buffer_no] = -1;
1622 else
1623 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_RX, base);
1625 else
1627 is_good = FALSE;
1630 if(!is_good)
1632 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1633 base);
1636 /* Prepare descriptor for next time */
1638 unit->ReceiveFrame(unit->card, buffer,
1639 FRAME_BUFFER_SIZE + R8180_MAXDESCSIZE);
1641 /* Get next descriptor */
1643 slot = next_slot;
1644 if(unit->bus == USB_BUS)
1645 proceed = FALSE;
1648 unit->rx_slot = slot;
1650 return;
1655 /****i* realtek8180.device/GetRXBuffer *************************************
1657 * NAME
1658 * GetRXBuffer -- Find an appropriate RX frame buffer to use.
1660 * SYNOPSIS
1661 * buffer = GetRXBuffer(unit, address, frag_no)
1663 * UBYTE *GetRXBuffer(struct DevUnit *, UBYTE *, UWORD);
1665 ****************************************************************************
1669 static UBYTE *GetRXBuffer(struct DevUnit *unit, const UBYTE *address,
1670 UWORD frag_no, UWORD *buffer_no, struct DevBase *base)
1672 UWORD i;
1673 UBYTE *buffer;
1674 LONG n;
1675 BOOL found;
1677 buffer = unit->rx_frames;
1678 for(i = 0, found = FALSE; i < FRAME_BUFFER_COUNT * 2 && !found; i++)
1680 /* Throw away old buffer contents if we didn't find a free slot the
1681 first time around */
1683 if(i >= FRAME_BUFFER_COUNT)
1684 unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT] = -1;
1686 /* For a frame's first fragment, find an empty slot; for subsequent
1687 fragments, find a slot with matching source address */
1689 n = unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT];
1690 if(n == -1 && (frag_no & 0xf) == 0
1691 || *((ULONG *)(buffer + ETH_PACKET_SOURCE))
1692 == *((ULONG *)(address))
1693 && *((UWORD *)(buffer + ETH_PACKET_SOURCE + 4))
1694 == *((UWORD *)(address + 4)))
1696 found = TRUE;
1697 if(n == -1)
1698 unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT] = frag_no;
1699 *buffer_no = i;
1701 else
1702 buffer += FRAME_BUFFER_SIZE;
1705 if(!found)
1706 buffer = NULL;
1708 return buffer;
1713 /****i* realtek8180.device/DistributeRXPacket ******************************
1715 * NAME
1716 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1718 * SYNOPSIS
1719 * DistributeRXPacket(unit, frame)
1721 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1723 ****************************************************************************
1727 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *frame,
1728 struct DevBase *base)
1730 UWORD packet_size, ieee_length;
1731 BOOL is_orphan = TRUE, accepted, is_snap = FALSE;
1732 ULONG packet_type;
1733 UBYTE *buffer;
1734 const UBYTE *template = snap_template;
1735 struct IOSana2Req *request, *request_tail;
1736 struct Opener *opener, *opener_tail;
1737 struct TypeStats *tracker;
1739 buffer = unit->rx_buffer;
1740 ieee_length = BEWord(*(UWORD *)(frame + ETH_PACKET_IEEELEN));
1741 packet_size = ETH_HEADERSIZE + ieee_length;
1742 if(ieee_length >= SNAP_HEADERSIZE)
1743 is_snap = *(const ULONG *)(frame + ETH_PACKET_DATA)
1744 == *(const ULONG *)template;
1746 /* De-encapsulate SNAP packets and get packet type */
1748 if(is_snap)
1750 packet_size -= SNAP_HEADERSIZE;
1751 CopyMem(frame, buffer, ETH_PACKET_TYPE);
1752 CopyMem(frame + ETH_HEADERSIZE + SNAP_FRM_TYPE,
1753 buffer + ETH_PACKET_TYPE, packet_size - ETH_PACKET_TYPE);
1755 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1757 /* Offer packet to every opener */
1759 opener = (APTR)unit->openers.mlh_Head;
1760 opener_tail = (APTR)&unit->openers.mlh_Tail;
1762 while(opener != opener_tail)
1764 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1765 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1766 accepted = FALSE;
1768 /* Offer packet to each request until it's accepted */
1770 while(request != request_tail && !accepted)
1772 if(request->ios2_PacketType == packet_type)
1774 CopyPacket(unit, request, packet_size, packet_type,
1775 buffer, base);
1776 accepted = TRUE;
1778 request =
1779 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1782 if(accepted)
1783 is_orphan = FALSE;
1784 opener = (APTR)opener->node.mln_Succ;
1787 /* If packet was unwanted, give it to S2_READORPHAN request */
1789 if(is_orphan)
1791 unit->stats.UnknownTypesReceived++;
1792 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1794 CopyPacket(unit,
1795 (APTR)unit->request_ports[ADOPT_QUEUE]->
1796 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1797 base);
1801 /* Update remaining statistics */
1803 if(packet_type <= ETH_MTU)
1804 packet_type = ETH_MTU;
1805 tracker =
1806 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1807 if(tracker != NULL)
1809 tracker->stats.PacketsReceived++;
1810 tracker->stats.BytesReceived += packet_size;
1813 return;
1818 /****i* realtek8180.device/CopyPacket **************************************
1820 * NAME
1821 * CopyPacket -- Copy packet to client's buffer.
1823 * SYNOPSIS
1824 * CopyPacket(unit, request, packet_size, packet_type,
1825 * buffer)
1827 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1828 * UBYTE *);
1830 ****************************************************************************
1834 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1835 UWORD packet_size, UWORD packet_type, UBYTE *buffer,
1836 struct DevBase *base)
1838 struct Opener *opener;
1839 BOOL filtered = FALSE;
1841 /* Set multicast and broadcast flags */
1843 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1844 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1845 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1846 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1847 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1848 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1850 /* Set source and destination addresses and packet type */
1852 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1853 ETH_ADDRESSSIZE);
1854 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1855 ETH_ADDRESSSIZE);
1856 request->ios2_PacketType = packet_type;
1858 /* Adjust for cooked packet request */
1860 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1862 packet_size -= ETH_PACKET_DATA;
1863 buffer += ETH_PACKET_DATA;
1865 #ifdef USE_HACKS
1866 else
1867 packet_size += 4; /* Needed for Shapeshifter & Fusion? */
1868 #endif
1869 request->ios2_DataLength = packet_size;
1871 /* Filter packet */
1873 opener = request->ios2_BufferManagement;
1874 if(request->ios2_Req.io_Command == CMD_READ &&
1875 opener->filter_hook != NULL)
1876 if(!CallHookPkt(opener->filter_hook, request, buffer))
1877 filtered = TRUE;
1879 if(!filtered)
1881 /* Copy packet into opener's buffer and reply packet */
1883 if(!opener->rx_function(request->ios2_Data, buffer, packet_size))
1885 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1886 request->ios2_WireError = S2WERR_BUFF_ERROR;
1887 ReportEvents(unit,
1888 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1889 base);
1891 Remove((APTR)request);
1892 ReplyMsg((APTR)request);
1895 return;
1900 /****i* realtek8180.device/AddressFilter ***********************************
1902 * NAME
1903 * AddressFilter -- Determine if an RX packet should be accepted.
1905 * SYNOPSIS
1906 * accept = AddressFilter(unit, address)
1908 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1910 ****************************************************************************
1914 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1915 struct DevBase *base)
1917 struct AddressRange *range, *tail;
1918 BOOL accept = TRUE;
1919 ULONG address_left;
1920 UWORD address_right;
1922 /* Check whether address is unicast/broadcast or multicast */
1924 address_left = BELong(*((ULONG *)address));
1925 address_right = BEWord(*((UWORD *)(address + 4)));
1927 if(((address_left & 0x01000000) != 0) &&
1928 !((address_left == 0xffffffff) && (address_right == 0xffff)))
1930 /* Check if this multicast address is wanted */
1932 range = (APTR)unit->multicast_ranges.mlh_Head;
1933 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1934 accept = FALSE;
1936 while((range != tail) && !accept)
1938 if((address_left > range->lower_bound_left ||
1939 address_left == range->lower_bound_left &&
1940 address_right >= range->lower_bound_right) &&
1941 (address_left < range->upper_bound_left ||
1942 address_left == range->upper_bound_left &&
1943 address_right <= range->upper_bound_right))
1944 accept = TRUE;
1945 range = (APTR)range->node.mln_Succ;
1948 if(!accept)
1949 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1952 return accept;
1957 /****i* realtek8180.device/DistributeMgmtFrame *****************************
1959 * NAME
1960 * DistributeMgmtFrame -- Send a management frame to clients.
1962 * SYNOPSIS
1963 * DistributeMgmtFrame(unit, frame, frame_size)
1965 * VOID DistributeMgmtFrame(struct DevUnit *, UBYTE *, UWORD);
1967 ****************************************************************************
1971 static VOID DistributeMgmtFrame(struct DevUnit *unit, UBYTE *frame,
1972 UWORD frame_size, struct DevBase *base)
1974 struct IOSana2Req *request;
1975 struct Opener *opener, *opener_tail;
1977 /* Send packet to every opener */
1979 opener = (APTR)unit->openers.mlh_Head;
1980 opener_tail = (APTR)&unit->openers.mlh_Tail;
1982 while(opener != opener_tail)
1984 request = (APTR)RemHead(&opener->mgmt_port.mp_MsgList);
1986 if(request != NULL)
1988 /* Copy packet into opener's buffer and reply packet */
1990 if(frame_size <= request->ios2_DataLength)
1992 CopyMem(frame, request->ios2_Data, frame_size);
1993 request->ios2_DataLength = frame_size;
1995 else
1997 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1998 request->ios2_WireError = S2WERR_BUFF_ERROR;
1999 ReportEvents(unit,
2000 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
2001 base);
2003 ReplyMsg((APTR)request);
2004 request =
2005 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2008 opener = (APTR)opener->node.mln_Succ;
2011 return;
2016 /****i* realtek8180.device/TXInt *******************************************
2018 * NAME
2019 * TXInt -- Soft interrupt for packet transmission.
2021 * SYNOPSIS
2022 * TXInt(unit)
2024 * VOID TXInt(struct DevUnit *);
2026 * FUNCTION
2028 * INPUTS
2029 * unit - A unit of this device.
2031 * RESULT
2032 * None.
2034 ****************************************************************************
2038 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
2040 struct DevBase *base;
2041 UWORD i, frame_size, data_size, packet_type, body_size, slot, new_slot,
2042 encryption, subtype, duration;
2043 UBYTE *buffer, *q, *plaintext, *ciphertext, *frame,
2044 mic_header[ETH_ADDRESSSIZE * 2];
2045 const UBYTE *p, *dest, *source;
2046 struct IOSana2Req *request;
2047 BOOL proceed = TRUE, is_ieee, has_bssid;
2048 struct Opener *opener;
2049 ULONG wire_error, control_value;
2050 UBYTE *tx_desc;
2051 UBYTE *(*dma_tx_function)(REG(a0, APTR));
2052 BYTE error;
2053 struct MsgPort *port;
2054 struct TypeStats *tracker;
2056 base = unit->device;
2057 port = unit->request_ports[WRITE_QUEUE];
2059 while(proceed && (!IsMsgPortEmpty(port)))
2061 slot = unit->tx_in_slot;
2062 new_slot = (slot + 1) % TX_SLOT_COUNT;
2064 if(new_slot != unit->tx_out_slot)
2066 error = 0;
2067 body_size = 0;
2069 /* Get request and DMA frame descriptor */
2071 request = (APTR)port->mp_MsgList.lh_Head;
2073 Remove((APTR)request);
2074 unit->tx_requests[slot] = request;
2075 tx_desc = unit->tx_descs[slot];
2076 frame = unit->tx_buffers[slot];
2078 /* Get packet data */
2080 opener = request->ios2_BufferManagement;
2081 dma_tx_function = opener->dma_tx_function;
2082 if(dma_tx_function != NULL)
2083 buffer = dma_tx_function(request->ios2_Data);
2084 else
2085 buffer = NULL;
2087 if(buffer == NULL)
2089 buffer = unit->tx_buffer;
2090 if(!opener->tx_function(buffer, request->ios2_Data,
2091 request->ios2_DataLength))
2093 error = S2ERR_NO_RESOURCES;
2094 wire_error = S2WERR_BUFF_ERROR;
2095 ReportEvents(unit,
2096 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
2097 | S2EVENT_TX, base);
2101 if(error == 0)
2103 /* Get packet type and/or length */
2105 data_size = request->ios2_DataLength;
2106 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) != 0)
2108 data_size -= ETH_PACKET_DATA;
2109 packet_type = BEWord(*(UWORD *)(buffer + ETH_PACKET_TYPE));
2111 else
2112 packet_type = request->ios2_PacketType;
2113 is_ieee = packet_type <= ETH_MTU;
2115 /* Determine encryption type and frame subtype */
2117 if(data_size > 0)
2119 encryption = unit->keys[unit->tx_key_no].type;
2120 subtype = 0;
2122 else
2124 encryption = S2ENC_NONE;
2125 subtype = 4;
2128 /* Get source and destination addresses */
2130 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) != 0)
2132 dest = buffer;
2133 source = buffer + ETH_ADDRESSSIZE;
2134 buffer += ETH_ADDRESSSIZE * 2 + 2;
2136 else
2138 dest = request->ios2_DstAddr;
2139 source = unit->address;
2142 /* Write 802.11 header */
2144 q = frame;
2145 *(UWORD *)q = MakeLEWord(
2146 (encryption == S2ENC_NONE ? 0 : WIFI_FRM_CONTROLF_WEP)
2147 | (unit->mode == S2PORT_ADHOC ? 0 : WIFI_FRM_CONTROLF_TODS)
2148 | subtype << WIFI_FRM_CONTROLB_SUBTYPE
2149 | WIFI_FRMTYPE_DATA << WIFI_FRM_CONTROLB_TYPE);
2150 q += 4;
2152 if(unit->mode == S2PORT_ADHOC)
2153 p = dest;
2154 else
2155 p = unit->bssid;
2156 for(i = 0; i < ETH_ADDRESSSIZE; i++)
2157 *q++ = *p++;
2159 for(i = 0, p = source; i < ETH_ADDRESSSIZE; i++)
2160 *q++ = *p++;
2162 if(unit->mode == S2PORT_ADHOC)
2163 p = unit->bssid;
2164 else
2165 p = dest;
2166 for(i = 0; i < ETH_ADDRESSSIZE; i++)
2167 *q++ = *p++;
2168 *(UWORD *)q = MakeLEWord(unit->tx_sequence);
2169 unit->tx_sequence += 0x10;
2170 q += 2;
2172 /* Leave room for encryption overhead */
2174 ciphertext = q;
2175 q += unit->iv_sizes[encryption];
2176 plaintext = q;
2178 /* Write SNAP header */
2180 if(!is_ieee)
2182 for(i = 0, p = snap_template;
2183 i < SNAP_FRM_TYPE; i++)
2184 *q++ = *p++;
2185 *(UWORD *)q = MakeBEWord(packet_type);
2186 q += 2;
2187 body_size += SNAP_HEADERSIZE;
2190 /* Copy data into frame */
2192 CopyMem(buffer, q, data_size);
2193 body_size += data_size;
2195 /* Append MIC to frame for TKIP */
2197 if(encryption == S2ENC_TKIP)
2199 q = mic_header;
2200 for(i = 0, p = dest; i < ETH_ADDRESSSIZE; i++)
2201 *q++ = *p++;
2202 for(i = 0, p = source; i < ETH_ADDRESSSIZE; i++)
2203 *q++ = *p++;
2204 TKIPEncryptFrame(unit, mic_header, plaintext, body_size,
2205 plaintext, base);
2206 body_size += MIC_SIZE;
2209 /* Encrypt fragment if applicable */
2211 unit->fragment_encrypt_functions[encryption](unit, frame,
2212 plaintext, &body_size, ciphertext, base);
2214 /* Clear frame descriptor as far as start of 802.11 header */
2216 q = tx_desc;
2217 for(i = 0; i < unit->tx_desc_size; i++)
2218 *q++ = 0;
2220 /* Set TX control field */
2222 frame_size = WIFI_FRM_DATA + body_size;
2223 control_value = R8180FRM_TXCONTROLF_NOENC
2224 | R8180FRM_TXCONTROLF_FIRSTFRAG
2225 | R8180FRM_TXCONTROLF_LASTFRAG
2226 | unit->tx_rate_code << R8180FRM_TXCONTROLB_RATE
2227 | frame_size;
2228 *(ULONG *)(tx_desc + R8180FRM_TXCONTROL) =
2229 MakeLELong(control_value);
2231 /* Set durations */
2233 has_bssid = ((frame + WIFI_FRM_ADDRESS1)[0] & 0x1) == 0;
2234 if(has_bssid)
2235 duration = SIFS_TIME + GetDuration(unit, 14,
2236 AckRate(unit, unit->tx_rate, base), FALSE, base);
2237 else
2238 duration = 0;
2239 *(UWORD *)(frame + WIFI_FRM_DURATION) = MakeLEWord(duration);
2241 if(unit->generation >= RTL8187B0_GEN)
2243 duration += GetDuration(unit, frame_size + 4,
2244 unit->tx_rate,
2245 (unit->flags & UNITF_SHORTPREAMBLE) != 0 && has_bssid,
2246 base);
2247 *(UWORD *)(tx_desc + R8180FRM_TXDUR) = MakeLEWord(duration);
2250 /* Set max number of retries */
2252 *(ULONG *)(tx_desc + unit->retries_offset) =
2253 MakeLELong((TX_TRIES - 1) << 8);
2255 /* Pass packet to adapter */
2257 unit->SendFrame(unit->card, tx_desc,
2258 R8180_MAXDESCSIZE + frame_size);
2259 unit->tx_in_slot = new_slot;
2261 else
2263 /* Reply failed request */
2265 request->ios2_Req.io_Error = error;
2266 request->ios2_WireError = wire_error;
2267 ReplyMsg((APTR)request);
2270 /* Update statistics */
2272 if(error == 0)
2274 unit->stats.PacketsSent++;
2276 tracker = FindTypeStats(unit, &unit->type_trackers,
2277 request->ios2_PacketType, base);
2278 if(tracker != NULL)
2280 tracker->stats.PacketsSent++;
2281 tracker->stats.BytesSent += ETH_HEADERSIZE + data_size;
2285 else
2286 proceed = FALSE;
2289 /* Don't try to keep sending packets if there's no space left */
2291 if(proceed)
2293 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
2294 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2296 else
2298 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_IGNORE;
2299 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2302 return;
2307 /****i* realtek8180.device/MgmtTXInt ***************************************
2309 * NAME
2310 * MgmtTXInt -- Soft interrupt for management frame transmission.
2312 * SYNOPSIS
2313 * MgmtTXInt(unit)
2315 * VOID MgmtTXInt(struct DevUnit *);
2317 * FUNCTION
2319 * INPUTS
2320 * unit - A unit of this device.
2322 * RESULT
2323 * None.
2325 ****************************************************************************
2329 static VOID MgmtTXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
2331 struct DevBase *base;
2332 UWORD frame_size, slot, new_slot, i, duration;
2333 UBYTE *desc, *frame, *q;
2334 struct IOSana2Req *request;
2335 BOOL proceed = TRUE, has_bssid;
2336 ULONG control_value;
2337 struct MsgPort *port;
2339 base = unit->device;
2340 port = unit->request_ports[MGMT_QUEUE];
2342 while(proceed && (!IsMsgPortEmpty(port)))
2344 slot = unit->tx_in_slot;
2345 new_slot = (slot + 1) % TX_SLOT_COUNT;
2347 if(new_slot != unit->tx_out_slot)
2349 /* Get request and frame descriptor */
2351 request = (APTR)port->mp_MsgList.lh_Head;
2353 Remove((APTR)request);
2354 unit->tx_requests[slot] = request;
2355 desc = unit->tx_descs[slot];
2356 frame = unit->tx_buffers[slot];
2358 /* Get packet length */
2360 frame_size = request->ios2_DataLength;
2362 /* Copy frame into transmit buffer */
2364 CopyMem(request->ios2_Data, frame, frame_size);
2366 /* Clear frame descriptor as far as start of 802.11 header */
2368 q = desc;
2369 for(i = 0; i < unit->tx_desc_size; i++)
2370 *q++ = 0;
2372 /* Set TX control field */
2374 control_value = R8180FRM_TXCONTROLF_NOENC
2375 | R8180FRM_TXCONTROLF_FIRSTFRAG
2376 | R8180FRM_TXCONTROLF_LASTFRAG
2377 | unit->mgmt_rate_code << R8180FRM_TXCONTROLB_RATE
2378 | frame_size;
2379 *(ULONG *)(desc + R8180FRM_TXCONTROL) = MakeLELong(control_value);
2381 /* Set durations */
2383 has_bssid = ((frame + WIFI_FRM_ADDRESS1)[0] & 0x1) == 0;
2384 if(has_bssid)
2385 duration = SIFS_TIME + GetDuration(unit, 14,
2386 AckRate(unit, unit->mgmt_rate, base), FALSE, base);
2387 else
2388 duration = 0;
2389 *(UWORD *)(frame + WIFI_FRM_DURATION) = MakeLEWord(duration);
2391 if(unit->generation >= RTL8187B0_GEN)
2393 duration += GetDuration(unit, frame_size + 4,
2394 unit->mgmt_rate, FALSE, base);
2395 *(UWORD *)(desc + R8180FRM_TXDUR) = MakeLEWord(duration);
2398 /* Set max number of retries */
2400 *(ULONG *)(desc + unit->retries_offset) =
2401 MakeLELong((TX_TRIES - 1) << 8);
2403 /* Set sequence number */
2405 *(UWORD *)(frame + WIFI_FRM_SEQCONTROL) =
2406 MakeLEWord(unit->tx_sequence);
2407 unit->tx_sequence += 0x10;
2409 /* Pass packet to adapter */
2411 unit->SendFrame(unit->card, desc, R8180_MAXDESCSIZE + frame_size);
2412 unit->tx_in_slot = new_slot;
2414 else
2415 proceed = FALSE;
2418 /* Don't try to keep sending packets if there's no space left */
2420 if(proceed)
2422 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2423 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
2425 else
2427 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2428 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_IGNORE;
2431 return;
2436 /****i* realtek8180.device/RetireTXSlot ************************************
2438 * NAME
2439 * RetireTXSlot -- Clean up after a frame has been sent.
2441 * SYNOPSIS
2442 * RetireTXSlot(unit)
2444 * VOID RetireTXSlot(struct DevUnit *);
2446 ****************************************************************************
2450 VOID RetireTXSlot(struct DevUnit *unit, struct DevBase *base)
2452 UWORD frame_size, slot;
2453 struct IOSana2Req *request;
2454 struct TypeStats *tracker;
2456 /* Update statistics */
2458 slot = unit->tx_out_slot;
2459 request = unit->tx_requests[slot];
2460 if(request->ios2_Req.io_Command != S2_WRITEMGMT)
2462 frame_size = request->ios2_DataLength;
2463 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2464 frame_size += ETH_HEADERSIZE;
2466 tracker = FindTypeStats(unit, &unit->type_trackers,
2467 request->ios2_PacketType, base);
2468 if(tracker != NULL)
2470 tracker->stats.PacketsSent++;
2471 tracker->stats.BytesSent += frame_size;
2475 /* Reply request */
2477 request->ios2_Req.io_Error = 0;
2478 ReplyMsg((APTR)request);
2480 unit->tx_out_slot = (slot + 1) % TX_SLOT_COUNT;
2482 /* Restart downloads if they had stopped */
2484 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
2485 Cause(&unit->tx_int);
2486 if(unit->request_ports[MGMT_QUEUE]->mp_Flags == PA_IGNORE)
2487 Cause(&unit->mgmt_int);
2489 return;
2494 /****i* realtek8180.device/ReportEvents ************************************
2496 * NAME
2497 * ReportEvents
2499 * SYNOPSIS
2500 * ReportEvents(unit, events)
2502 * VOID ReportEvents(struct DevUnit *, ULONG);
2504 * FUNCTION
2506 * INPUTS
2507 * unit - A unit of this device.
2508 * events - A mask of events to report.
2510 * RESULT
2511 * None.
2513 ****************************************************************************
2517 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
2518 struct DevBase *base)
2520 struct IOSana2Req *request, *tail, *next_request;
2521 struct List *list;
2523 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
2524 next_request = (APTR)list->lh_Head;
2525 tail = (APTR)&list->lh_Tail;
2527 Disable();
2528 while(next_request != tail)
2530 request = next_request;
2531 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2533 if((request->ios2_WireError & events) != 0)
2535 request->ios2_WireError = events;
2536 Remove((APTR)request);
2537 ReplyMsg((APTR)request);
2540 Enable();
2542 return;
2547 /****i* realtek8180.device/GetDuration *************************************
2549 * NAME
2550 * GetDuration -- Calculate a duration value.
2552 * SYNOPSIS
2553 * GetDuration(unit, length, rate, is_mgmt)
2555 * VOID GetDuration(struct DevUnit *);
2557 * FUNCTION
2558 * Calculates a duration for a frame of given length when transmitted
2559 * at a given rate. If this is a transmiss
2561 * INPUTS
2562 * unit - A unit of this device.
2563 * length - Length of frame whose duration is to be calculated.
2564 * rate - Rate frame will be transmitted at (in Mbps, rounded down).
2565 * is_short - Indicates if frame has a short preamble.
2567 * RESULT
2568 * None.
2570 ****************************************************************************
2574 static UWORD GetDuration(struct DevUnit *unit, UWORD length, UWORD rate,
2575 BOOL short_preamble, struct DevBase *base)
2577 UWORD duration, cycles;
2579 if (rate % 3 != 0)
2581 duration = 97 + (length * 8 - 1) / rate;
2582 if (!short_preamble || rate == 1)
2583 duration += 96;
2585 else
2587 cycles = rate * 4;
2588 duration = ((length + 29) / cycles + 1) * 4 + 26;
2591 return duration;
2596 /****i* realtek8180.device/AckRate *****************************************
2598 * NAME
2599 * AckRate -- Get the ACK rate corresponding to a data rate.
2601 * SYNOPSIS
2602 * ack_rate = AckRate(unit, data_rate)
2604 * UWORD AckRate(struct DevUnit *, UWORD);
2606 * FUNCTION
2607 * Calculates the rate at which the ACK frame for a data frame with the
2608 * given rate should be transmitted.
2610 * INPUTS
2611 * unit - A unit of this device.
2612 * rate - Rate data frame is transmitted at (in Mbps, rounded down).
2614 * RESULT
2615 * ack_rate - The rate for the ACK frame (Mbps, rounded down).
2617 ****************************************************************************
2621 static UWORD AckRate(struct DevUnit *unit, UWORD data_rate,
2622 struct DevBase *base)
2624 UWORD ack_rate;
2626 switch(data_rate)
2628 case 54:
2629 case 48:
2630 case 36:
2631 case 24:
2632 ack_rate = 24;
2633 break;
2634 case 18:
2635 case 12:
2636 ack_rate = 12;
2637 break;
2638 case 9:
2639 case 6:
2640 ack_rate = 6;
2641 break;
2642 case 11:
2643 case 5:
2644 case 2:
2645 ack_rate = 2;
2646 break;
2647 case 1:
2648 ack_rate = 1;
2649 break;
2652 return ack_rate;
2657 /****i* realtek8180.device/UnitTask ****************************************
2659 * NAME
2660 * UnitTask
2662 * SYNOPSIS
2663 * UnitTask()
2665 * VOID UnitTask();
2667 * FUNCTION
2668 * Completes deferred requests, and handles card insertion and removal
2669 * in conjunction with the relevant interrupts.
2671 ****************************************************************************
2675 #ifdef __MORPHOS__
2676 #undef UnitTask
2677 #endif
2679 static VOID UnitTask(struct ExecBase *sys_base)
2681 struct Task *task;
2682 struct IORequest *request;
2683 struct DevUnit *unit;
2684 struct DevBase *base;
2685 struct MsgPort *general_port;
2686 ULONG signals = 0, wait_signals, card_removed_signal,
2687 card_inserted_signal, general_port_signal;
2689 /* Get parameters */
2691 task = AbsExecBase->ThisTask;
2692 unit = task->tc_UserData;
2693 base = unit->device;
2695 /* Activate general request port */
2697 general_port = unit->request_ports[GENERAL_QUEUE];
2698 general_port->mp_SigTask = task;
2699 general_port->mp_SigBit = AllocSignal(-1);
2700 general_port_signal = 1 << general_port->mp_SigBit;
2701 general_port->mp_Flags = PA_SIGNAL;
2703 /* Allocate signals for notification of card removal and insertion */
2705 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
2706 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
2707 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
2708 | card_inserted_signal | SIGBREAKF_CTRL_C;
2710 /* Tell ourselves to check port for old messages */
2712 Signal(task, general_port_signal);
2714 /* Infinite loop to service requests and signals */
2716 while(TRUE)
2718 signals = Wait(wait_signals);
2720 if((signals & card_inserted_signal) != 0)
2722 if(unit->insertion_function(unit->card, base))
2724 unit->flags |= UNITF_HAVEADAPTER;
2725 if((unit->flags & UNITF_CONFIGURED) != 0)
2726 ConfigureAdapter(unit, base);
2727 if((unit->flags & UNITF_WASONLINE) != 0)
2729 GoOnline(unit, base);
2730 unit->flags &= ~UNITF_WASONLINE;
2735 if((signals & card_removed_signal) != 0)
2737 unit->removal_function(unit->card, base);
2738 if((unit->flags & UNITF_WASONLINE) != 0)
2739 GoOffline(unit, base);
2742 if((signals & general_port_signal) != 0)
2744 while((request = (APTR)GetMsg(general_port)) != NULL)
2746 /* Service the request as soon as the unit is free */
2748 ObtainSemaphore(&unit->access_lock);
2749 ServiceRequest((APTR)request, base);