revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / realtek8180 / unit.c
blobfc636c233b55112ab368d8766b12df104f59b2e3
1 /*
3 Copyright (C) 2001-2017 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 #include <exec/memory.h>
24 #include <exec/execbase.h>
25 #include <exec/errors.h>
26 #include <exec/tasks.h>
28 #include <proto/exec.h>
29 #ifndef __amigaos4__
30 #include <proto/alib.h>
31 #else
32 #include <clib/alib_protos.h>
33 #endif
34 #include <proto/utility.h>
35 #include <proto/timer.h>
37 #include "device.h"
38 #include "task.h"
39 #include "realtek8187.h"
41 #include "unit_protos.h"
42 #include "request_protos.h"
43 #include "radio_protos.h"
44 #include "eeprom_protos.h"
45 #include "encryption_protos.h"
46 #include "timer_protos.h"
49 #define TASK_PRIORITY 0
50 #define STACK_SIZE 4096
51 #define INT_MASK 0xffff
52 #define TX_TRIES 7
53 #define SIFS_TIME 14
55 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base);
56 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
57 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
58 UWORD upper_bound_right, struct DevBase *base);
59 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base);
60 static UBYTE *GetRXBuffer(struct DevUnit *unit, const UBYTE *address,
61 UWORD frag_no, UWORD *buffer_no, struct DevBase *base);
62 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *frame,
63 struct DevBase *base);
64 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
65 UWORD packet_size, UWORD packet_type, UBYTE *buffer,
66 struct DevBase *base);
67 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
68 struct DevBase *base);
69 static VOID DistributeMgmtFrame(struct DevUnit *unit, UBYTE *frame,
70 UWORD frame_size, struct DevBase *base);
71 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code));
72 static VOID MgmtTXInt(REG(a1, struct DevUnit *unit),
73 REG(a6, APTR int_code));
74 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
75 struct DevBase *base);
76 static UWORD GetDuration(struct DevUnit *unit, UWORD length, UWORD rate,
77 BOOL short_preamble, struct DevBase *base);
78 static UWORD AckRate(struct DevUnit *unit, UWORD data_rate,
79 struct DevBase *base);
80 static VOID UnitTask(struct DevUnit *unit);
83 static const UBYTE snap_template[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
86 /****i* realtek8180.device/CreateUnit **************************************
88 * NAME
89 * CreateUnit -- Create a unit.
91 * SYNOPSIS
92 * unit = CreateUnit(index, io_base, id, card,
93 * io_tags, bus)
95 * struct DevUnit *CreateUnit(ULONG, APTR, UWORD, APTR,
96 * struct TagItem *, UWORD);
98 * FUNCTION
99 * Creates a new unit.
101 ****************************************************************************
105 struct DevUnit *CreateUnit(ULONG index, APTR card,
106 const struct TagItem *io_tags, UWORD bus, struct DevBase *base)
108 BOOL success = TRUE;
109 struct DevUnit *unit;
110 struct Task *task;
111 struct MsgPort *port;
112 UWORD i;
113 APTR stack;
115 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
116 if(unit == NULL)
117 success = FALSE;
119 if(success)
121 /* Initialise lists etc. */
123 NewList((APTR)&unit->openers);
124 NewList((APTR)&unit->type_trackers);
125 NewList((APTR)&unit->multicast_ranges);
127 unit->index = index;
128 unit->device = base;
129 unit->card = card;
130 unit->bus = bus;
131 unit->generation = RTL8187B1_GEN;
132 unit->tx_rate = 11;
133 unit->tx_rate_code = 3; /* 11 Mbps */
134 unit->mgmt_rate = 1;
135 unit->mgmt_rate_code = 0; /* 1 Mbps */
136 unit->channel = 1;
138 /* Store I/O hooks */
140 unit->ByteOut =
141 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
142 unit->ByteIn =
143 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
144 unit->LEWordIn =
145 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
146 unit->LELongIn =
147 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
148 unit->LEWordOut =
149 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
150 unit->LELongOut =
151 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
152 unit->AllocDMAMem =
153 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
154 unit->FreeDMAMem =
155 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
156 unit->SendFrame =
157 (APTR)GetTagData(IOTAG_SendFrame, (UPINT)NULL, io_tags);
158 unit->ReceiveFrame =
159 (APTR)GetTagData(IOTAG_ReceiveFrame, (UPINT)NULL, io_tags);
160 if(unit->ByteIn == NULL
161 || unit->ByteOut == NULL
162 || unit->LEWordIn == NULL
163 || unit->LELongIn == NULL
164 || unit->LEWordOut == NULL
165 || unit->LELongOut == NULL
166 || unit->AllocDMAMem == NULL
167 || unit->FreeDMAMem == NULL
168 || unit->SendFrame == NULL
169 || unit->ReceiveFrame == NULL)
170 success = FALSE;
173 if(success)
175 InitSemaphore(&unit->access_lock);
177 /* Create the message ports for queuing requests */
179 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
181 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
182 MEMF_PUBLIC | MEMF_CLEAR);
183 if(port == NULL)
184 success = FALSE;
186 if(success)
188 NewList(&port->mp_MsgList);
189 port->mp_Flags = PA_IGNORE;
193 if(success)
195 unit->request_ports[WRITE_QUEUE]->mp_SigTask = &unit->tx_int;
196 unit->request_ports[MGMT_QUEUE]->mp_SigTask = &unit->mgmt_int;
199 /* Allocate buffers and descriptors */
201 unit->tx_buffer = AllocVec(ETH_MAXPACKETSIZE, MEMF_PUBLIC);
202 for(i = 0; i < TX_SLOT_COUNT; i++)
204 unit->tx_descs[i] = unit->AllocDMAMem(unit->card,
205 R8180_MAXDESCSIZE + FRAME_BUFFER_SIZE, 4);
206 if(unit->tx_descs[i] != NULL)
207 unit->tx_buffers[i] = unit->tx_descs[i] + R8180_MAXDESCSIZE;
208 else
209 success = FALSE;
211 unit->rx_buffer = AllocVec(FRAME_BUFFER_SIZE, MEMF_PUBLIC);
212 for(i = 0; i < RX_SLOT_COUNT; i++)
214 if(unit->bus != USB_BUS)
216 unit->rx_descs[i] = unit->AllocDMAMem(unit->card,
217 R8180_MAXDESCSIZE, 4);
218 if(unit->rx_descs[i] == NULL)
219 success = FALSE;
221 unit->rx_buffers[i] = unit->AllocDMAMem(unit->card,
222 FRAME_BUFFER_SIZE + R8180_MAXDESCSIZE, 4);
223 if(unit->rx_buffers[i] == NULL)
224 success = FALSE;
226 unit->rx_frames =
227 AllocVec(FRAME_BUFFER_SIZE * FRAME_BUFFER_COUNT, MEMF_PUBLIC);
228 for(i = 0; i < FRAME_BUFFER_COUNT; i++)
229 unit->rx_fragment_nos[i] = -1;
230 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
231 MEMF_PUBLIC);
232 if(unit->tx_buffer == NULL
233 || unit->rx_buffer == NULL
234 || unit->rx_frames == NULL
235 || unit->tx_requests == NULL)
236 success = FALSE;
239 if(success)
241 /* Initialise network adapter hardware */
243 success = InitialiseAdapter(unit, FALSE, base);
244 unit->flags |= UNITF_HAVEADAPTER;
247 if(success)
249 /* Record maximum speed in BPS */
251 unit->speed = 54000000;
253 /* Initialise interrupts */
255 unit->rx_int.is_Node.ln_Name =
256 base->device.dd_Library.lib_Node.ln_Name;
257 unit->rx_int.is_Code = (APTR)RXInt;
258 unit->rx_int.is_Data = unit;
260 unit->tx_int.is_Node.ln_Name =
261 base->device.dd_Library.lib_Node.ln_Name;
262 unit->tx_int.is_Code = (APTR)TXInt;
263 unit->tx_int.is_Data = unit;
265 unit->mgmt_int.is_Node.ln_Name =
266 base->device.dd_Library.lib_Node.ln_Name;
267 unit->mgmt_int.is_Code = (APTR)MgmtTXInt;
268 unit->mgmt_int.is_Data = unit;
270 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
271 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
273 /* Create a new task */
275 unit->task = task =
276 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
277 if(task == NULL)
278 success = FALSE;
281 if(success)
283 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
284 if(stack == NULL)
285 success = FALSE;
288 if(success)
290 /* Initialise and start task */
292 task->tc_Node.ln_Type = NT_TASK;
293 task->tc_Node.ln_Pri = TASK_PRIORITY;
294 task->tc_Node.ln_Name = base->device.dd_Library.lib_Node.ln_Name;
295 task->tc_SPUpper = stack + STACK_SIZE;
296 task->tc_SPLower = stack;
297 task->tc_SPReg = task->tc_SPUpper;
298 NewList(&task->tc_MemEntry);
300 if(AddUnitTask(task, UnitTask, unit) != NULL)
301 unit->flags |= UNITF_TASKADDED;
302 else
303 success = FALSE;
306 if(success)
308 /* Set default wireless options */
310 unit->mode = S2PORT_MANAGED;
313 if(!success)
315 DeleteUnit(unit, base);
316 unit = NULL;
319 return unit;
324 /****i* realtek8180.device/DeleteUnit **************************************
326 * NAME
327 * DeleteUnit -- Delete a unit.
329 * SYNOPSIS
330 * DeleteUnit(unit)
332 * VOID DeleteUnit(struct DevUnit *);
334 * FUNCTION
335 * Deletes a unit.
337 * INPUTS
338 * unit - Device unit (may be NULL).
340 * RESULT
341 * None.
343 ****************************************************************************
347 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
349 UBYTE i;
350 struct Task *task;
352 if(unit != NULL)
354 task = unit->task;
355 if(task != NULL)
357 if((unit->flags & UNITF_TASKADDED) != 0)
359 RemTask(task);
360 FreeMem(task->tc_SPLower, STACK_SIZE);
362 FreeMem(task, sizeof(struct Task));
365 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
367 if(unit->request_ports[i] != NULL)
368 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
371 if((unit->flags & UNITF_ONLINE) != 0) /* Needed! */
372 GoOffline(unit, base);
374 if((unit->flags & UNITF_HAVEADAPTER) != 0)
375 DeinitialiseAdapter(unit, base);
377 for(i = 0; i < TX_SLOT_COUNT; i++)
378 unit->FreeDMAMem(unit->card, unit->tx_descs[i]);
379 for(i = 0; i < RX_SLOT_COUNT; i++)
381 unit->FreeDMAMem(unit->card, unit->rx_buffers[i]);
382 if(unit->bus != USB_BUS)
383 unit->FreeDMAMem(unit->card, unit->rx_descs[i]);
386 FreeVec(unit->tx_buffer);
387 FreeVec(unit->rx_frames);
388 FreeVec(unit->tx_requests);
389 FreeVec(unit->rx_buffer);
391 FreeMem(unit, sizeof(struct DevUnit));
394 return;
399 /****i* realtek8180.device/InitialiseAdapter *******************************
401 * NAME
402 * InitialiseAdapter
404 * SYNOPSIS
405 * success = InitialiseAdapter(unit, reinsertion)
407 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
409 * FUNCTION
411 * INPUTS
412 * unit
413 * reinsertion
415 * RESULT
416 * success - Success indicator.
418 ****************************************************************************
422 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
423 struct DevBase *base)
425 BOOL success = FALSE;
426 UBYTE reg_62, revision;
427 UWORD *p, i;
428 ULONG rx_conf;
430 /* Initialise EEPROM */
432 rx_conf = unit->LELongIn(unit->card, 0x100 + R8180REG_RXCONF);
433 unit->eeprom_addr_size = ((rx_conf & (1 << 6)) != 0) ? 8 : 6;
435 BusyMicroDelay(10, base);
436 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
438 /* Get default MAC address */
440 p = (UWORD *)unit->default_address;
441 for(i = 0; i < ETH_ADDRESSSIZE / sizeof(UWORD); i++)
442 *p++ = LEWord(ReadEEPROM(unit, R8180ROM_ADDRESS0 + i, base));
444 /* Refine main chip revision */
446 if(unit->generation == RTL8187B1_GEN)
448 revision = unit->ByteIn(unit->card, 0x100 + 0xe1);
449 if(revision == 1 || revision == 2)
450 unit->generation = RTL8187B2_GEN;
452 else
454 if((unit->LELongIn(unit->card, 0x100 + R8180REG_TXCONF)
455 & R8180REG_TXCONFF_HWVER) == 6 << R8180REG_TXCONFB_HWVER)
456 unit->generation = RTL8187B0_GEN;
459 /* Set up power tables */
461 GetPower(unit, base);
463 /* Tune the radio */
465 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
466 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
467 | R8180REG_CONFIG3F_ANAPARAMWRITE | R8180REG_CONFIG3F_GNTSELECT);
468 unit->LELongOut(unit->card, 0x100 + R8180REG_ANAPARAM2, 0x727f3f52);
469 unit->LELongOut(unit->card, 0x100 + R8180REG_ANAPARAM1, 0x45090658);
470 unit->ByteOut(unit->card, 0x100 + R8180REG_ANAPARAM3, 0);
472 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
473 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
474 & ~R8180REG_CONFIG3F_ANAPARAMWRITE);
476 /* Reset PLL sequence */
478 unit->ByteOut(unit->card, 0x161, 0x10);
479 reg_62 = unit->ByteIn(unit->card, 0x162);
480 unit->ByteOut(unit->card, 0x162, reg_62 & ~(1 << 5));
481 unit->ByteOut(unit->card, 0x162, reg_62 | (1 << 5));
483 /* Send reset command */
485 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
486 unit->ByteIn(unit->card, 0x100 + R8180REG_COMMAND)
487 & 0x2 | R8180REG_COMMANDF_RESET);
489 for(i = 0; i < 10 && !success; i++)
491 BusyMilliDelay(2, base);
492 if((unit->ByteIn(unit->card, 0x100 + R8180REG_COMMAND)
493 & R8180REG_COMMANDF_RESET) == 0)
494 success = TRUE;
497 if(success && unit->generation == RTL8187L_GEN)
499 /* Reload registers from EEPROM */
501 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_LOAD);
503 for(i = 0, success = FALSE; i < 10 && !success; i++)
505 BusyMilliDelay(4, base);
506 if((unit->ByteIn(unit->card, 0x100 + R8180REG_EEPROM)
507 & R8180REG_EEPROMF_COMMAND) == 0)
508 success = TRUE;
512 if(success)
514 /* Set up rates */
516 if(unit->generation == RTL8187L_GEN)
517 unit->LEWordOut(unit->card, 0x12d, 0xfff);
518 else
519 unit->LEWordOut(unit->card, 0x134, 0xfff);
520 unit->LEWordOut(unit->card, 0x12c, 0x1ff);
521 unit->ByteOut(unit->card, 0x100 + R8180REG_CWCONF,
522 unit->ByteIn(unit->card, 0x100 + R8180REG_CWCONF)
523 | R8180REG_CWCONFF_PPRETRYSHIFT);
524 unit->ByteOut(unit->card, 0x100 + R8180REG_TXAGCCTL,
525 unit->ByteIn(unit->card, 0x100 + R8180REG_TXAGCCTL)
526 | R8180REG_TXAGCCTLF_PPGAINSHIFT);
528 unit->LEWordOut(unit->card, 0x1e0 | 1 << 16, 0xfff);
529 unit->ByteOut(unit->card, 0x100 + R8180REG_RATEFALLBACK,
530 unit->ByteIn(unit->card, 0x100 + R8180REG_RATEFALLBACK)
531 | R8180REG_RATEFALLBACKF_ENABLE);
533 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR,
534 unit->ByteIn(unit->card, 0x100 + R8180REG_MSR) & 0xf3);
535 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR,
536 unit->ByteIn(unit->card, 0x100 + R8180REG_MSR)
537 | R8180REG_MSRF_ENEDCA);
538 unit->ByteOut(unit->card, 0x100 + R8180REG_ACMCONTROL, 0);
540 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMWINDOW, 2);
541 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL, 100);
542 unit->LEWordOut(unit->card, 0x1d4 | 1 << 16, 0xffff);
544 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
545 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG1,
546 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG1) & 0x3f | 0x80);
547 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, 0);
549 unit->ByteOut(unit->card, 0x100 + R8180REG_WPACONF, 0);
551 unit->ByteOut(unit->card, 0x1f0, 0x32);
552 unit->ByteOut(unit->card, 0x1f1, 0x32);
553 unit->ByteOut(unit->card, 0x1f2, 0x0);
554 unit->ByteOut(unit->card, 0x1f3, 0x0);
555 unit->ByteOut(unit->card, 0x1f4, 0x32);
556 unit->ByteOut(unit->card, 0x1f5, 0x43);
557 unit->ByteOut(unit->card, 0x1f6, 0x0);
558 unit->ByteOut(unit->card, 0x1f7, 0x0);
559 unit->ByteOut(unit->card, 0x1f8, 0x46);
560 unit->ByteOut(unit->card, 0x1f9, 0xa4);
561 unit->ByteOut(unit->card, 0x1fa, 0x0);
562 unit->ByteOut(unit->card, 0x1fb, 0x0);
563 unit->ByteOut(unit->card, 0x1fc, 0x96);
564 unit->ByteOut(unit->card, 0x1fd, 0xa4);
565 unit->ByteOut(unit->card, 0x1fe, 0x0);
566 unit->ByteOut(unit->card, 0x1ff, 0x0);
568 unit->ByteOut(unit->card, 0x158 | 1 << 16, 0x4b);
569 unit->ByteOut(unit->card, 0x159 | 1 << 16, 0x0);
570 unit->ByteOut(unit->card, 0x15a | 1 << 16, 0x4b);
571 unit->ByteOut(unit->card, 0x15b | 1 << 16, 0x0);
572 unit->ByteOut(unit->card, 0x160 | 1 << 16, 0x4b);
573 unit->ByteOut(unit->card, 0x161 | 1 << 16, 0x9);
574 unit->ByteOut(unit->card, 0x162 | 1 << 16, 0x4b);
575 unit->ByteOut(unit->card, 0x163 | 1 << 16, 0x9);
576 unit->ByteOut(unit->card, 0x1ce | 1 << 16, 0xf);
577 unit->ByteOut(unit->card, 0x1cf | 1 << 16, 0x0);
578 unit->ByteOut(unit->card, 0x1e0 | 1 << 16, 0xff);
579 unit->ByteOut(unit->card, 0x1e1 | 1 << 16, 0xf);
580 unit->ByteOut(unit->card, 0x1e2 | 1 << 16, 0x0);
581 unit->ByteOut(unit->card, 0x1f0 | 1 << 16, 0x4e);
582 unit->ByteOut(unit->card, 0x1f1 | 1 << 16, 0x1);
583 unit->ByteOut(unit->card, 0x1f2 | 1 << 16, 0x2);
584 unit->ByteOut(unit->card, 0x1f3 | 1 << 16, 0x3);
585 unit->ByteOut(unit->card, 0x1f4 | 1 << 16, 0x4);
586 unit->ByteOut(unit->card, 0x1f5 | 1 << 16, 0x5);
587 unit->ByteOut(unit->card, 0x1f6 | 1 << 16, 0x6);
588 unit->ByteOut(unit->card, 0x1f7 | 1 << 16, 0x7);
589 unit->ByteOut(unit->card, 0x1f8 | 1 << 16, 0x8);
591 unit->ByteOut(unit->card, 0x14e | 2 << 16, 0x0);
592 unit->ByteOut(unit->card, 0x10c | 2 << 16, 0x4);
593 unit->ByteOut(unit->card, 0x121 | 2 << 16, 0x61);
594 unit->ByteOut(unit->card, 0x122 | 2 << 16, 0x68);
595 unit->ByteOut(unit->card, 0x123 | 2 << 16, 0x6f);
596 unit->ByteOut(unit->card, 0x124 | 2 << 16, 0x76);
597 unit->ByteOut(unit->card, 0x125 | 2 << 16, 0x7d);
598 unit->ByteOut(unit->card, 0x126 | 2 << 16, 0x84);
599 unit->ByteOut(unit->card, 0x127 | 2 << 16, 0x8d);
600 unit->ByteOut(unit->card, 0x14d | 2 << 16, 0x8);
601 unit->ByteOut(unit->card, 0x150 | 2 << 16, 0x5);
602 unit->ByteOut(unit->card, 0x151 | 2 << 16, 0xf5);
603 unit->ByteOut(unit->card, 0x152 | 2 << 16, 0x4);
604 unit->ByteOut(unit->card, 0x153 | 2 << 16, 0xa0);
605 unit->ByteOut(unit->card, 0x154 | 2 << 16, 0x1f);
606 unit->ByteOut(unit->card, 0x155 | 2 << 16, 0x23);
607 unit->ByteOut(unit->card, 0x156 | 2 << 16, 0x45);
608 unit->ByteOut(unit->card, 0x157 | 2 << 16, 0x67);
609 unit->ByteOut(unit->card, 0x158 | 2 << 16, 0x8);
610 unit->ByteOut(unit->card, 0x159 | 2 << 16, 0x8);
611 unit->ByteOut(unit->card, 0x15a | 2 << 16, 0x8);
612 unit->ByteOut(unit->card, 0x15b | 2 << 16, 0x8);
613 unit->ByteOut(unit->card, 0x160 | 2 << 16, 0x8);
614 unit->ByteOut(unit->card, 0x161 | 2 << 16, 0x8);
615 unit->ByteOut(unit->card, 0x162 | 2 << 16, 0x8);
616 unit->ByteOut(unit->card, 0x163 | 2 << 16, 0x8);
617 unit->ByteOut(unit->card, 0x164 | 2 << 16, 0xcf);
618 unit->ByteOut(unit->card, 0x172 | 2 << 16, 0x56);
619 unit->ByteOut(unit->card, 0x173 | 2 << 16, 0x9a);
621 unit->ByteOut(unit->card, 0x134, 0xf0);
622 unit->ByteOut(unit->card, 0x135, 0xf);
623 unit->ByteOut(unit->card, 0x15b, 0x40);
624 unit->ByteOut(unit->card, 0x184, 0x88);
625 unit->ByteOut(unit->card, 0x185, 0x24);
626 unit->ByteOut(unit->card, 0x188, 0x54);
627 unit->ByteOut(unit->card, 0x18b, 0xb8);
628 unit->ByteOut(unit->card, 0x18c, 0x7);
629 unit->ByteOut(unit->card, 0x18d, 0x0);
630 unit->ByteOut(unit->card, 0x194, 0x1b);
631 unit->ByteOut(unit->card, 0x195, 0x12);
632 unit->ByteOut(unit->card, 0x196, 0x0);
633 unit->ByteOut(unit->card, 0x197, 0x6);
634 unit->ByteOut(unit->card, 0x19d, 0x1a);
635 unit->ByteOut(unit->card, 0x19f, 0x10);
636 unit->ByteOut(unit->card, 0x1b4, 0x22);
637 unit->ByteOut(unit->card, 0x1be, 0x80);
638 unit->ByteOut(unit->card, 0x1db, 0x0);
639 unit->ByteOut(unit->card, 0x1ee, 0x0);
640 unit->ByteOut(unit->card, 0x191, 0x3);
641 unit->ByteOut(unit->card, 0x14c | 2 << 16, 0x0);
643 unit->ByteOut(unit->card, 0x19f | 3 << 16, 0x0);
644 unit->ByteOut(unit->card, 0x18c, 0x1);
645 unit->ByteOut(unit->card, 0x18d, 0x10);
646 unit->ByteOut(unit->card, 0x18e, 0x8);
647 unit->ByteOut(unit->card, 0x18f, 0x0);
649 unit->LEWordOut(unit->card, 0x100 + R8180REG_TIDACMAP, 0xfa50);
650 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMIG, 0);
652 unit->LELongOut(unit->card, 0x1f0 | 1 << 16, 0);
653 unit->LELongOut(unit->card, 0x1f4 | 1 << 16, 0);
654 unit->ByteOut(unit->card, 0x1f8 | 1 << 16, 0);
656 unit->LELongOut(unit->card, 0x100 + R8180REG_RFTIMING, 0x4001);
658 unit->LEWordOut(unit->card, 0x172 | 2 << 16, 0x569a);
660 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
662 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
663 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
664 | R8180REG_CONFIG3F_ANAPARAMWRITE);
665 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, 0);
667 /* Turn LED on */
669 unit->ByteOut(unit->card, 0x100 + R8180REG_GPIO0, 1);
670 unit->ByteOut(unit->card, 0x100 + R8180REG_GPENABLE, 0);
672 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSOUTPUT, 0x480);
673 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSSELECT, 0x2488);
674 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSENABLE, 0x1fff);
675 BusyMilliDelay(100, base);
677 /* Initialise radio */
679 success = InitialiseRadio(unit, base);
681 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
682 R8180REG_COMMANDF_TXENABLE | R8180REG_COMMANDF_RXENABLE);
683 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMASK, INT_MASK);
685 unit->ByteOut(unit->card, 0x41, 0xf4);
686 unit->ByteOut(unit->card, 0x40, 0);
687 unit->ByteOut(unit->card, 0x42, 0);
688 unit->ByteOut(unit->card, 0x42, 1);
689 unit->ByteOut(unit->card, 0x40, 0xf);
690 unit->ByteOut(unit->card, 0x42, 0);
691 unit->ByteOut(unit->card, 0x42, 1);
693 unit->ByteOut(unit->card, 0x1db,
694 unit->ByteIn(unit->card, 0x1db) | 1 << 2);
695 unit->LEWordOut(unit->card, 0x172 | 3 << 16, 0x59fa);
696 unit->LEWordOut(unit->card, 0x174 | 3 << 16, 0x59d2);
697 unit->LEWordOut(unit->card, 0x176 | 3 << 16, 0x59d2);
698 unit->LEWordOut(unit->card, 0x178 | 3 << 16, 0x19fa);
699 unit->LEWordOut(unit->card, 0x17a | 3 << 16, 0x19fa);
700 unit->LEWordOut(unit->card, 0x17c | 3 << 16, 0xd0);
701 unit->ByteOut(unit->card, 0x161, 0);
702 unit->ByteOut(unit->card, 0x180 | 1 << 16, 0xf);
703 unit->ByteOut(unit->card, 0x183 | 1 << 16, 3);
704 unit->ByteOut(unit->card, 0x1da, 0x10);
705 unit->ByteOut(unit->card, 0x14d | 2 << 16, 8);
707 unit->LELongOut(unit->card, 0x100 + R8180REG_HSSIPARA, 0x600321b);
709 /* Set maximum RX frame size */
711 unit->LEWordOut(unit->card, 0x1ec | 1 << 16, 0x800);
713 unit->ByteOut(unit->card, 0x100 + R8180REG_ACMCONTROL, 0);
714 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR, R8180REG_MSRF_ENEDCA);
717 if(success)
719 unit->LELongOut(unit->card, 0x100 + R8180REG_RXCONF,
720 R8180REG_RXCONFF_EARLYTHRESH
721 | R8180REG_RXCONFF_AUTORESETPHY
722 | R8180REG_RXCONFF_CHECKBSSID
723 | R8180REG_RXCONFF_MGMT
724 | R8180REG_RXCONFF_DATA
725 | 7 << R8180REG_RXCONFB_FIFOTHRESH
726 | 7 << R8180REG_RXCONFB_MAXDMA
727 | R8180REG_RXCONFF_BCAST
728 | R8180REG_RXCONFF_MCAST
729 | R8180REG_RXCONFF_UCAST);
730 unit->ByteOut(unit->card, 0x100 + R8180REG_TXAGCCTL,
731 unit->ByteIn(unit->card, 0x100 + R8180REG_TXAGCCTL)
732 & ~(R8180REG_TXAGCCTLF_PPGAINSHIFT
733 | R8180REG_TXAGCCTLF_PPANTSELSHIFT
734 | R8180REG_TXAGCCTLF_FEEDBACKANT));
735 unit->LELongOut(unit->card, 0x100 + R8180REG_TXCONF,
736 R8180REG_TXCONFF_DISREQQSIZE
737 | 7 << R8180REG_TXCONFB_MAXDMA
738 | TX_TRIES << R8180REG_TXCONFB_SHORTTRIES
739 | TX_TRIES << R8180REG_TXCONFB_LONGTRIES);
742 /* Determine features, and get offsets of certain fields within frame
743 descriptors */
745 unit->retries_offset = R8180FRM_RETRY;
746 unit->tx_desc_size = 32;
747 unit->rx_desc_size = 20;
749 /* Set IV sizes */
751 unit->iv_sizes[S2ENC_WEP] = IV_SIZE;
752 unit->iv_sizes[S2ENC_TKIP] = EIV_SIZE;
753 unit->iv_sizes[S2ENC_CCMP] = EIV_SIZE;
755 /* Set encryption functions */
757 unit->fragment_encrypt_functions[S2ENC_NONE] = WriteClearFragment;
759 if((unit->flags & UNITF_HARDWEP) != 0)
760 unit->fragment_encrypt_functions[S2ENC_WEP] = WriteWEPFragment;
761 else
762 unit->fragment_encrypt_functions[S2ENC_WEP] = EncryptWEPFragment;
764 if((unit->flags & UNITF_HARDTKIP) != 0)
765 unit->fragment_encrypt_functions[S2ENC_TKIP] = WriteTKIPFragment;
766 else
767 unit->fragment_encrypt_functions[S2ENC_TKIP] = EncryptTKIPFragment;
769 if((unit->flags & UNITF_HARDCCMP) != 0)
770 unit->fragment_encrypt_functions[S2ENC_CCMP] = WriteCCMPFragment;
771 else
772 unit->fragment_encrypt_functions[S2ENC_CCMP] = EncryptCCMPFragment;
774 /* Set decryption functions */
776 unit->fragment_decrypt_functions[S2ENC_NONE] = ReadClearFragment;
778 if((unit->flags & UNITF_HARDWEP) != 0)
779 unit->fragment_decrypt_functions[S2ENC_WEP] = ReadWEPFragment;
780 else
781 unit->fragment_decrypt_functions[S2ENC_WEP] = DecryptWEPFragment;
783 if((unit->flags & UNITF_HARDTKIP) != 0)
784 unit->fragment_decrypt_functions[S2ENC_TKIP] = ReadTKIPFragment;
785 else
786 unit->fragment_decrypt_functions[S2ENC_TKIP] = DecryptTKIPFragment;
788 if((unit->flags & UNITF_HARDCCMP) != 0)
789 unit->fragment_decrypt_functions[S2ENC_CCMP] = ReadCCMPFragment;
790 else
791 unit->fragment_decrypt_functions[S2ENC_CCMP] = DecryptCCMPFragment;
793 /* Return */
795 return success;
800 /****i* realtek8180.device/DeinitialiseAdapter *****************************
802 * NAME
803 * DeinitialiseAdapter
805 * SYNOPSIS
806 * DeinitialiseAdapter(unit)
808 * VOID DeinitialiseAdapter(struct DevUnit *);
810 * FUNCTION
812 * INPUTS
813 * unit
815 * RESULT
816 * None.
818 ****************************************************************************
822 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base)
824 /* Turn LED off */
826 unit->ByteOut(unit->card, 0x100 + R8180REG_GPIO0, 1);
827 unit->ByteOut(unit->card, 0x100 + R8180REG_GPENABLE, 1);
829 return;
834 /****i* realtek8180.device/ConfigureAdapter ********************************
836 * NAME
837 * ConfigureAdapter -- Set up card for transmission/reception.
839 * SYNOPSIS
840 * ConfigureAdapter(unit)
842 * VOID ConfigureAdapter(struct DevUnit *);
844 ****************************************************************************
848 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
850 UBYTE msr;
851 UWORD i;
853 /* Set BSSID */
855 for(i = 0; i < ETH_ADDRESSSIZE; i++)
856 unit->ByteOut(unit->card, 0x100 + R8180REG_BSSID + i, unit->bssid[i]);
858 /* Set channel and power */
860 SetPower(unit, base);
862 msr = unit->ByteIn(unit->card, 0x100 + R8180REG_MSR)
863 & ~R8180REG_MSRF_LINK;
864 if(unit->assoc_id != 0)
866 msr |= 2 << R8180REG_MSRB_LINK;
867 if(unit->generation >= RTL8187B0_GEN)
868 msr |= R8180REG_MSRF_ENEDCA;
870 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR, msr);
872 /* Set intervals */
874 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMWINDOW, 2);
875 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMTRINTERVAL, 100);
876 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL, 100);
877 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL2, 100);
879 if(unit->generation >= RTL8187B0_GEN)
881 unit->ByteOut(unit->card, 0x100 + R8180REG_SIFS, 0x22);
882 if(unit->band == S2BAND_G)
883 unit->ByteOut(unit->card, 0x100 + R8180REG_SLOT, 0x9);
884 else
885 unit->ByteOut(unit->card, 0x100 + R8180REG_SLOT, 0x14);
886 unit->ByteOut(unit->card, 0x100 + R8180REG_EIFS, 0x5b);
887 unit->ByteOut(unit->card, 0x100 + R8180REG_SENSECOUNT, 0x5b);
890 /* Return */
892 return;
897 /****i* realtek8180.device/GoOnline ****************************************
899 * NAME
900 * GoOnline -- Enable transmission/reception.
902 * SYNOPSIS
903 * GoOnline(unit)
905 * VOID GoOnline(struct DevUnit *);
907 ****************************************************************************
911 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
913 /* Enable interrupts */
915 unit->flags |= UNITF_ONLINE;
916 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMASK, INT_MASK);
918 /* Enable frame transmission and reception */
920 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
921 R8180REG_COMMANDF_TXENABLE | R8180REG_COMMANDF_RXENABLE);
923 /* Record start time and report Online event */
925 GetSysTime(&unit->stats.LastStart);
926 ReportEvents(unit, S2EVENT_ONLINE, base);
928 return;
933 /****i* realtek8180.device/GoOffline ***************************************
935 * NAME
936 * GoOffline -- Disable transmission/reception.
938 * SYNOPSIS
939 * GoOffline(unit)
941 * VOID GoOffline(struct DevUnit *);
943 * FUNCTION
945 * INPUTS
946 * unit
948 * RESULT
949 * None.
951 ****************************************************************************
955 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
957 unit->flags &= ~UNITF_ONLINE;
959 /* Flush pending read and write requests */
961 FlushUnit(unit, MGMT_QUEUE, S2ERR_OUTOFSERVICE, base);
963 /* Report Offline event and return */
965 ReportEvents(unit, S2EVENT_OFFLINE, base);
966 return;
971 /****i* realtek8180.device/SetOptions **************************************
973 * NAME
974 * SetOptions -- Set and use interface options.
976 * SYNOPSIS
977 * reconfigure = SetOptions(unit, tag_list)
979 * BOOL SetOptions(struct DevUnit *, struct TagItem *);
981 ****************************************************************************
985 BOOL SetOptions(struct DevUnit *unit, const struct TagItem *tag_list,
986 struct DevBase *base)
988 struct TagItem *tag_item, *tlist = (struct TagItem *)tag_list;
989 BOOL reconfigure = TRUE;
991 while((tag_item = NextTagItem(&tlist)) != NULL)
993 switch(tag_item->ti_Tag)
995 case S2INFO_SSID:
996 ReportEvents(unit, S2EVENT_CONNECT, base);
997 break;
999 case S2INFO_BSSID:
1000 CopyMem((APTR)tag_item->ti_Data, unit->bssid, ETH_ADDRESSSIZE);
1001 break;
1003 case S2INFO_AssocID:
1004 unit->assoc_id = tag_item->ti_Data;
1005 break;
1007 case S2INFO_Capabilities:
1008 unit->capabilities = tag_item->ti_Data;
1009 if((unit->capabilities & (1 << 5)) != 0)
1010 unit->flags |= UNITF_SHORTPREAMBLE;
1011 else
1012 unit->flags &= ~UNITF_SHORTPREAMBLE;
1013 break;
1015 case S2INFO_DefaultKeyNo:
1016 unit->tx_key_no = tag_item->ti_Data;
1017 break;
1019 case S2INFO_PortType:
1020 unit->mode = tag_item->ti_Data;
1021 break;
1023 case S2INFO_Channel:
1024 if(tag_item->ti_Data != unit->channel)
1026 unit->channel = tag_item->ti_Data;
1027 reconfigure = TRUE;
1029 break;
1031 case S2INFO_Band:
1032 unit->band = tag_item->ti_Data;
1033 if(unit->band == S2BAND_G)
1035 unit->tx_rate = 54;
1036 unit->tx_rate_code = 11; /* 54 Mbps */
1037 unit->mgmt_rate = 2;
1038 unit->mgmt_rate_code = 1; /* 2 Mbps */
1040 else if(unit->band == S2BAND_B)
1042 unit->tx_rate = 11;
1043 unit->tx_rate_code = 3; /* 11 Mbps */
1044 unit->mgmt_rate = 1;
1045 unit->mgmt_rate_code = 0; /* 1 Mbps */
1047 break;
1052 return reconfigure;
1057 /****i* realtek8180.device/SetKey ******************************************
1059 * NAME
1060 * SetKey -- Set an encryption key.
1062 * SYNOPSIS
1063 * SetKey(unit, index, type, key, key_length,
1064 * rx_counter)
1066 * VOID SetKey(struct DevUnit *, ULONG, ULONG, UBYTE *, ULONG,
1067 * UBYTE *);
1069 ****************************************************************************
1073 VOID SetKey(struct DevUnit *unit, ULONG index, ULONG type, const UBYTE *key,
1074 ULONG key_length, const UBYTE *rx_counter, struct DevBase *base)
1076 struct KeyUnion *slot;
1077 struct EClockVal eclock;
1078 UWORD i;
1080 Disable();
1081 slot = &unit->keys[index];
1082 switch(type)
1084 case S2ENC_WEP:
1085 CopyMem(key, slot->u.wep.key, key_length);
1086 slot->u.wep.length = key_length;
1088 if((unit->flags & UNITF_HARDWEP) == 0)
1090 /* Create a reasonably random IV */
1092 ReadEClock(&eclock);
1093 slot->u.wep.tx_iv = FastRand(eclock.ev_lo ^ eclock.ev_hi);
1096 break;
1098 case S2ENC_TKIP:
1099 CopyMem(key, slot->u.tkip.key, 16);
1100 CopyMem(key + 16, slot->u.tkip.tx_mic_key, MIC_SIZE);
1101 CopyMem(key + 24, slot->u.tkip.rx_mic_key, MIC_SIZE);
1102 slot->u.tkip.tx_iv_low = 0;
1103 slot->u.tkip.tx_iv_high = 0;
1104 slot->u.tkip.rx_iv_low = LEWord(*(UWORD *)rx_counter);
1105 slot->u.tkip.rx_iv_high = LELong(*(ULONG *)(rx_counter + 2));
1106 slot->u.tkip.tx_ttak_set = FALSE;
1107 slot->u.tkip.rx_ttak_set = FALSE;
1109 if((unit->flags & UNITF_HARDTKIP) != 0)
1112 else
1114 /* Convert key to native endianness */
1116 for(i = 0; i < 8; i++)
1117 slot->u.tkip.key[i] = LEWord(slot->u.tkip.key[i]);
1120 break;
1122 case S2ENC_CCMP:
1123 CopyMem(key, slot->u.ccmp.key, 16);
1124 slot->u.ccmp.tx_iv_low = 0;
1125 slot->u.ccmp.tx_iv_high = 0;
1126 slot->u.ccmp.rx_iv_low = LEWord(*(UWORD *)rx_counter);
1127 slot->u.ccmp.rx_iv_high = LELong(*(ULONG *)(rx_counter + 2));
1128 slot->u.ccmp.stream_set = FALSE;
1131 /* Update type of key in selected slot */
1133 slot->type = type;
1134 Enable();
1136 return;
1141 /****i* realtek8180.device/AddMulticastRange *******************************
1143 * NAME
1144 * AddMulticastRange
1146 * SYNOPSIS
1147 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1149 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1151 ****************************************************************************
1155 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1156 const UBYTE *upper_bound, struct DevBase *base)
1158 struct AddressRange *range;
1159 ULONG lower_bound_left, upper_bound_left;
1160 UWORD lower_bound_right, upper_bound_right;
1162 lower_bound_left = BELong(*((ULONG *)lower_bound));
1163 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1164 upper_bound_left = BELong(*((ULONG *)upper_bound));
1165 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1167 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1168 upper_bound_left, upper_bound_right, base);
1170 if(range != NULL)
1171 range->add_count++;
1172 else
1174 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1175 if(range != NULL)
1177 range->lower_bound_left = lower_bound_left;
1178 range->lower_bound_right = lower_bound_right;
1179 range->upper_bound_left = upper_bound_left;
1180 range->upper_bound_right = upper_bound_right;
1181 range->add_count = 1;
1183 Disable();
1184 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
1185 unit->range_count++;
1186 SetMulticast(unit, base);
1187 Enable();
1191 return range != NULL;
1196 /****i* realtek8180.device/RemMulticastRange *******************************
1198 * NAME
1199 * RemMulticastRange
1201 * SYNOPSIS
1202 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1204 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1206 ****************************************************************************
1210 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1211 const UBYTE *upper_bound, struct DevBase *base)
1213 struct AddressRange *range;
1214 ULONG lower_bound_left, upper_bound_left;
1215 UWORD lower_bound_right, upper_bound_right;
1217 lower_bound_left = BELong(*((ULONG *)lower_bound));
1218 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1219 upper_bound_left = BELong(*((ULONG *)upper_bound));
1220 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1222 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1223 upper_bound_left, upper_bound_right, base);
1225 if(range != NULL)
1227 if(--range->add_count == 0)
1229 Disable();
1230 Remove((APTR)range);
1231 unit->range_count--;
1232 SetMulticast(unit, base);
1233 Enable();
1234 FreeMem(range, sizeof(struct AddressRange));
1238 return range != NULL;
1243 /****i* realtek8180.device/FindMulticastRange ******************************
1245 * NAME
1246 * FindMulticastRange
1248 * SYNOPSIS
1249 * range = FindMulticastRange(unit, lower_bound_left,
1250 * lower_bound_right, upper_bound_left, upper_bound_right)
1252 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1253 * UWORD, ULONG, UWORD);
1255 ****************************************************************************
1259 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
1260 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
1261 UWORD upper_bound_right, struct DevBase *base)
1263 struct AddressRange *range, *tail;
1264 BOOL found = FALSE;
1266 range = (APTR)unit->multicast_ranges.mlh_Head;
1267 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1269 while(range != tail && !found)
1271 if(lower_bound_left == range->lower_bound_left &&
1272 lower_bound_right == range->lower_bound_right &&
1273 upper_bound_left == range->upper_bound_left &&
1274 upper_bound_right == range->upper_bound_right)
1275 found = TRUE;
1276 else
1277 range = (APTR)range->node.mln_Succ;
1280 if(!found)
1281 range = NULL;
1283 return range;
1288 /****i* realtek8180.device/SetMulticast ************************************
1290 * NAME
1291 * SetMulticast
1293 * SYNOPSIS
1294 * SetMulticast(unit)
1296 * VOID SetMulticast(struct DevUnit *);
1298 ****************************************************************************
1302 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base)
1304 return;
1309 /****i* realtek8180.device/FindTypeStats ***********************************
1311 * NAME
1312 * FindTypeStats
1314 * SYNOPSIS
1315 * stats = FindTypeStats(unit, list,
1316 * packet_type)
1318 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1319 * ULONG);
1321 ****************************************************************************
1325 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
1326 ULONG packet_type, struct DevBase *base)
1328 struct TypeStats *stats, *tail;
1329 BOOL found = FALSE;
1331 stats = (APTR)list->mlh_Head;
1332 tail = (APTR)&list->mlh_Tail;
1334 while(stats != tail && !found)
1336 if(stats->packet_type == packet_type)
1337 found = TRUE;
1338 else
1339 stats = (APTR)stats->node.mln_Succ;
1342 if(!found)
1343 stats = NULL;
1345 return stats;
1350 /****i* realtek8180.device/FlushUnit ***************************************
1352 * NAME
1353 * FlushUnit
1355 * SYNOPSIS
1356 * FlushUnit(unit, last_queue, error)
1358 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1360 ****************************************************************************
1364 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
1365 struct DevBase *base)
1367 struct IORequest *request;
1368 UBYTE i;
1369 struct Opener *opener, *tail;
1371 /* Abort queued requests */
1373 for(i = 0; i <= last_queue; i++)
1375 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
1377 request->io_Error = IOERR_ABORTED;
1378 ReplyMsg((APTR)request);
1382 #if 1
1383 opener = (APTR)unit->openers.mlh_Head;
1384 tail = (APTR)&unit->openers.mlh_Tail;
1386 /* Flush every opener's read queues */
1388 while(opener != tail)
1390 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1392 request->io_Error = error;
1393 ReplyMsg((APTR)request);
1395 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
1397 request->io_Error = error;
1398 ReplyMsg((APTR)request);
1400 opener = (APTR)opener->node.mln_Succ;
1403 #else
1404 opener = request->ios2_BufferManagement;
1405 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1407 request->io_Error = IOERR_ABORTED;
1408 ReplyMsg((APTR)request);
1410 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
1412 request->io_Error = IOERR_ABORTED;
1413 ReplyMsg((APTR)request);
1415 #endif
1417 /* Return */
1419 return;
1424 /****i* realtek8180.device/RXInt *******************************************
1426 * NAME
1427 * RXInt -- Soft interrupt for packet reception.
1429 * SYNOPSIS
1430 * RXInt(unit)
1432 * VOID RXInt(struct DevUnit *);
1434 * FUNCTION
1436 * INPUTS
1437 * unit - A unit of this device.
1439 * RESULT
1440 * None.
1442 ****************************************************************************
1446 VOID RXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
1448 UWORD ieee_length, frame_control, frame_type, slot, next_slot,
1449 frame_size, frame_subtype, encryption, key_no, buffer_no, old_length;
1450 struct DevBase *base;
1451 BOOL is_good, proceed = TRUE;
1452 LONG frag_no;
1453 ULONG status;
1454 UBYTE *rx_desc, *buffer, *p, *frame, *data, *snap_frame, *source;
1456 base = unit->device;
1457 slot = unit->rx_slot;
1458 rx_desc = unit->rx_descs[slot];
1459 next_slot = (slot + 1) % RX_SLOT_COUNT;
1461 while(proceed)
1463 is_good = TRUE;
1464 buffer = unit->rx_buffers[slot];
1466 status = LELong(*(ULONG *)(rx_desc + R8180FRM_RXSTATUS));
1467 frame_size = status & R8180FRM_RXSTATUSF_LENGTH;
1469 if((status & (R8180FRM_RXSTATUSF_DMAERR | R8180FRM_RXSTATUSF_OVERFLOW
1470 | R8180FRM_RXSTATUSF_RXERR | R8180FRM_RXSTATUSF_BADCRC)) == 0
1471 && frame_size >= WIFI_FRM_DATA + 4)
1473 /* Get fragment info */
1475 frame = buffer;
1476 ieee_length = frame_size - 4 - WIFI_FRM_DATA;
1477 data = frame + WIFI_FRM_DATA;
1478 frame_control =
1479 LEWord(*(UWORD *)(frame + WIFI_FRM_CONTROL));
1481 /* Get buffer to store fragment in */
1483 frag_no = LEWord(*(UWORD *)(frame + WIFI_FRM_SEQCONTROL));
1484 if(unit->mode == S2PORT_ADHOC)
1485 source = frame + WIFI_FRM_ADDRESS2;
1486 else
1487 source = frame + WIFI_FRM_ADDRESS3;
1488 snap_frame = GetRXBuffer(unit, source, frag_no, &buffer_no, base);
1490 /* Get location to put new data */
1492 if(snap_frame != NULL)
1494 if((frag_no & 0xf ) > 0)
1495 old_length =
1496 BEWord(*(UWORD *)(snap_frame + ETH_PACKET_IEEELEN));
1497 else
1499 /* Create new 802.3 header */
1501 CopyMem(frame + WIFI_FRM_ADDRESS1, snap_frame,
1502 ETH_ADDRESSSIZE);
1503 CopyMem(source, snap_frame + ETH_PACKET_SOURCE,
1504 ETH_ADDRESSSIZE);
1505 old_length = 0;
1507 p = snap_frame + ETH_HEADERSIZE + old_length;
1509 /* Append fragment to frame, decrypting fragment if necessary */
1511 if((frame_control & WIFI_FRM_CONTROLF_WEP) != 0)
1513 key_no = data[3] >> 6 & 0x3;
1514 encryption = unit->keys[key_no].type;
1516 else
1517 encryption = S2ENC_NONE;
1519 /* Decrypt, check and/or copy fragment */
1521 is_good = unit->fragment_decrypt_functions[encryption](unit,
1522 frame, data, &ieee_length, p, base);
1524 /* Update length in frame being built with current fragment, or
1525 increment bad frame counter if fragment is bad */
1527 if(is_good)
1529 ieee_length += old_length;
1530 *(UWORD *)(snap_frame + ETH_PACKET_IEEELEN) =
1531 MakeBEWord(ieee_length);
1533 else
1534 unit->stats.BadData++;
1536 /* If all fragments have arrived, process the complete frame */
1538 if((frame_control & WIFI_FRM_CONTROLF_MOREFRAGS) == 0)
1540 if(is_good)
1542 /* Decrypt complete frame if necessary */
1544 data = snap_frame + ETH_HEADERSIZE;
1545 if(encryption == S2ENC_TKIP
1546 && (unit->flags & UNITF_HARDTKIP) == 0)
1548 is_good = TKIPDecryptFrame(unit, snap_frame, data,
1549 ieee_length, data, key_no, base);
1550 ieee_length -= MIC_SIZE;
1551 *(UWORD *)(snap_frame + ETH_PACKET_IEEELEN) =
1552 MakeBEWord(ieee_length);
1553 if(!is_good)
1554 unit->stats.BadData++;
1558 if(is_good)
1560 /* Get frame's 802.11 type and subtype */
1562 frame_type = (frame_control & WIFI_FRM_CONTROLF_TYPE)
1563 >> WIFI_FRM_CONTROLB_TYPE;
1564 frame_subtype =
1565 (frame_control & WIFI_FRM_CONTROLF_SUBTYPE)
1566 >> WIFI_FRM_CONTROLB_SUBTYPE;
1568 /* If it's a management frame, process it separately;
1569 otherwise distribute it to clients after filtering */
1571 if(frame_type == WIFI_FRMTYPE_MGMT)
1573 if(frame_subtype != 8)
1574 DistributeMgmtFrame(unit, frame, frame_size - 4,
1575 base);
1577 else if(AddressFilter(unit, snap_frame + ETH_PACKET_DEST,
1578 base))
1580 unit->stats.PacketsReceived++;
1581 DistributeRXPacket(unit, snap_frame, base);
1586 /* Mark fragment buffer as unused for next time */
1588 unit->rx_fragment_nos[buffer_no] = -1;
1590 else
1591 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_RX, base);
1593 else
1595 is_good = FALSE;
1598 if(!is_good)
1600 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1601 base);
1604 /* Prepare descriptor for next time */
1606 unit->ReceiveFrame(unit->card, buffer,
1607 FRAME_BUFFER_SIZE + R8180_MAXDESCSIZE);
1609 /* Get next descriptor */
1611 slot = next_slot;
1612 if(unit->bus == USB_BUS)
1613 proceed = FALSE;
1616 unit->rx_slot = slot;
1618 return;
1623 /****i* realtek8180.device/GetRXBuffer *************************************
1625 * NAME
1626 * GetRXBuffer -- Find an appropriate RX frame buffer to use.
1628 * SYNOPSIS
1629 * buffer = GetRXBuffer(unit, address, frag_no)
1631 * UBYTE *GetRXBuffer(struct DevUnit *, UBYTE *, UWORD);
1633 ****************************************************************************
1637 static UBYTE *GetRXBuffer(struct DevUnit *unit, const UBYTE *address,
1638 UWORD frag_no, UWORD *buffer_no, struct DevBase *base)
1640 UWORD i;
1641 UBYTE *buffer;
1642 LONG n;
1643 BOOL found;
1645 buffer = unit->rx_frames;
1646 for(i = 0, found = FALSE; i < FRAME_BUFFER_COUNT * 2 && !found; i++)
1648 /* Throw away old buffer contents if we didn't find a free slot the
1649 first time around */
1651 if(i >= FRAME_BUFFER_COUNT)
1652 unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT] = -1;
1654 /* For a frame's first fragment, find an empty slot; for subsequent
1655 fragments, find a slot with matching source address */
1657 n = unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT];
1658 if(n == -1 && (frag_no & 0xf) == 0
1659 || *((ULONG *)(buffer + ETH_PACKET_SOURCE))
1660 == *((ULONG *)(address))
1661 && *((UWORD *)(buffer + ETH_PACKET_SOURCE + 4))
1662 == *((UWORD *)(address + 4)))
1664 found = TRUE;
1665 if(n == -1)
1666 unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT] = frag_no;
1667 *buffer_no = i;
1669 else
1670 buffer += FRAME_BUFFER_SIZE;
1673 if(!found)
1674 buffer = NULL;
1676 return buffer;
1681 /****i* realtek8180.device/DistributeRXPacket ******************************
1683 * NAME
1684 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1686 * SYNOPSIS
1687 * DistributeRXPacket(unit, frame)
1689 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1691 ****************************************************************************
1695 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *frame,
1696 struct DevBase *base)
1698 UWORD packet_size, ieee_length;
1699 BOOL is_orphan = TRUE, accepted, is_snap = FALSE;
1700 ULONG packet_type;
1701 UBYTE *buffer;
1702 const UBYTE *template = snap_template;
1703 struct IOSana2Req *request, *request_tail;
1704 struct Opener *opener, *opener_tail;
1705 struct TypeStats *tracker;
1707 buffer = unit->rx_buffer;
1708 ieee_length = BEWord(*(UWORD *)(frame + ETH_PACKET_IEEELEN));
1709 packet_size = ETH_HEADERSIZE + ieee_length;
1710 if(ieee_length >= SNAP_HEADERSIZE)
1711 is_snap = *(const ULONG *)(frame + ETH_PACKET_DATA)
1712 == *(const ULONG *)template;
1714 /* De-encapsulate SNAP packets and get packet type */
1716 if(is_snap)
1718 packet_size -= SNAP_HEADERSIZE;
1719 CopyMem(frame, buffer, ETH_PACKET_TYPE);
1720 CopyMem(frame + ETH_HEADERSIZE + SNAP_FRM_TYPE,
1721 buffer + ETH_PACKET_TYPE, packet_size - ETH_PACKET_TYPE);
1723 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1725 /* Offer packet to every opener */
1727 opener = (APTR)unit->openers.mlh_Head;
1728 opener_tail = (APTR)&unit->openers.mlh_Tail;
1730 while(opener != opener_tail)
1732 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1733 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1734 accepted = FALSE;
1736 /* Offer packet to each request until it's accepted */
1738 while(request != request_tail && !accepted)
1740 if(request->ios2_PacketType == packet_type)
1742 CopyPacket(unit, request, packet_size, packet_type,
1743 buffer, base);
1744 accepted = TRUE;
1746 request =
1747 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1750 if(accepted)
1751 is_orphan = FALSE;
1752 opener = (APTR)opener->node.mln_Succ;
1755 /* If packet was unwanted, give it to S2_READORPHAN request */
1757 if(is_orphan)
1759 unit->stats.UnknownTypesReceived++;
1760 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1762 CopyPacket(unit,
1763 (APTR)unit->request_ports[ADOPT_QUEUE]->
1764 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1765 base);
1769 /* Update remaining statistics */
1771 if(packet_type <= ETH_MTU)
1772 packet_type = ETH_MTU;
1773 tracker =
1774 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1775 if(tracker != NULL)
1777 tracker->stats.PacketsReceived++;
1778 tracker->stats.BytesReceived += packet_size;
1781 return;
1786 /****i* realtek8180.device/CopyPacket **************************************
1788 * NAME
1789 * CopyPacket -- Copy packet to client's buffer.
1791 * SYNOPSIS
1792 * CopyPacket(unit, request, packet_size, packet_type,
1793 * buffer)
1795 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1796 * UBYTE *);
1798 ****************************************************************************
1802 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1803 UWORD packet_size, UWORD packet_type, UBYTE *buffer,
1804 struct DevBase *base)
1806 struct Opener *opener;
1807 BOOL filtered = FALSE;
1809 /* Set multicast and broadcast flags */
1811 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1812 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1813 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1814 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1815 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1816 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1818 /* Set source and destination addresses and packet type */
1820 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1821 ETH_ADDRESSSIZE);
1822 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1823 ETH_ADDRESSSIZE);
1824 request->ios2_PacketType = packet_type;
1826 /* Adjust for cooked packet request */
1828 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1830 packet_size -= ETH_PACKET_DATA;
1831 buffer += ETH_PACKET_DATA;
1833 #ifdef USE_HACKS
1834 else
1835 packet_size += 4; /* Needed for Shapeshifter & Fusion? */
1836 #endif
1837 request->ios2_DataLength = packet_size;
1839 /* Filter packet */
1841 opener = request->ios2_BufferManagement;
1842 if(request->ios2_Req.io_Command == CMD_READ &&
1843 opener->filter_hook != NULL)
1844 if(!CallHookPkt(opener->filter_hook, request, buffer))
1845 filtered = TRUE;
1847 if(!filtered)
1849 /* Copy packet into opener's buffer and reply packet */
1851 if(!opener->rx_function(request->ios2_Data, buffer, packet_size))
1853 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1854 request->ios2_WireError = S2WERR_BUFF_ERROR;
1855 ReportEvents(unit,
1856 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1857 base);
1859 Remove((APTR)request);
1860 ReplyMsg((APTR)request);
1863 return;
1868 /****i* realtek8180.device/AddressFilter ***********************************
1870 * NAME
1871 * AddressFilter -- Determine if an RX packet should be accepted.
1873 * SYNOPSIS
1874 * accept = AddressFilter(unit, address)
1876 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1878 ****************************************************************************
1882 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1883 struct DevBase *base)
1885 struct AddressRange *range, *tail;
1886 BOOL accept = TRUE;
1887 ULONG address_left;
1888 UWORD address_right;
1890 /* Check whether address is unicast/broadcast or multicast */
1892 address_left = BELong(*((ULONG *)address));
1893 address_right = BEWord(*((UWORD *)(address + 4)));
1895 if(((address_left & 0x01000000) != 0) &&
1896 !((address_left == 0xffffffff) && (address_right == 0xffff)))
1898 /* Check if this multicast address is wanted */
1900 range = (APTR)unit->multicast_ranges.mlh_Head;
1901 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1902 accept = FALSE;
1904 while((range != tail) && !accept)
1906 if((address_left > range->lower_bound_left ||
1907 address_left == range->lower_bound_left &&
1908 address_right >= range->lower_bound_right) &&
1909 (address_left < range->upper_bound_left ||
1910 address_left == range->upper_bound_left &&
1911 address_right <= range->upper_bound_right))
1912 accept = TRUE;
1913 range = (APTR)range->node.mln_Succ;
1916 if(!accept)
1917 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1920 return accept;
1925 /****i* realtek8180.device/DistributeMgmtFrame *****************************
1927 * NAME
1928 * DistributeMgmtFrame -- Send a management frame to clients.
1930 * SYNOPSIS
1931 * DistributeMgmtFrame(unit, frame, frame_size)
1933 * VOID DistributeMgmtFrame(struct DevUnit *, UBYTE *, UWORD);
1935 ****************************************************************************
1939 static VOID DistributeMgmtFrame(struct DevUnit *unit, UBYTE *frame,
1940 UWORD frame_size, struct DevBase *base)
1942 struct IOSana2Req *request;
1943 struct Opener *opener, *opener_tail;
1945 /* Send packet to every opener */
1947 opener = (APTR)unit->openers.mlh_Head;
1948 opener_tail = (APTR)&unit->openers.mlh_Tail;
1950 while(opener != opener_tail)
1952 request = (APTR)RemHead(&opener->mgmt_port.mp_MsgList);
1954 if(request != NULL)
1956 /* Copy packet into opener's buffer and reply packet */
1958 if(frame_size <= request->ios2_DataLength)
1960 CopyMem(frame, request->ios2_Data, frame_size);
1961 request->ios2_DataLength = frame_size;
1963 else
1965 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1966 request->ios2_WireError = S2WERR_BUFF_ERROR;
1967 ReportEvents(unit,
1968 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1969 base);
1971 ReplyMsg((APTR)request);
1972 request =
1973 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1976 opener = (APTR)opener->node.mln_Succ;
1979 return;
1984 /****i* realtek8180.device/TXInt *******************************************
1986 * NAME
1987 * TXInt -- Soft interrupt for packet transmission.
1989 * SYNOPSIS
1990 * TXInt(unit)
1992 * VOID TXInt(struct DevUnit *);
1994 * FUNCTION
1996 * INPUTS
1997 * unit - A unit of this device.
1999 * RESULT
2000 * None.
2002 ****************************************************************************
2006 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
2008 struct DevBase *base;
2009 UWORD i, frame_size, data_size, packet_type, body_size, slot, new_slot,
2010 encryption, subtype, duration;
2011 UBYTE *buffer, *q, *plaintext, *ciphertext, *frame,
2012 mic_header[ETH_ADDRESSSIZE * 2];
2013 const UBYTE *p, *dest, *source;
2014 struct IOSana2Req *request;
2015 BOOL proceed = TRUE, is_ieee, has_bssid;
2016 struct Opener *opener;
2017 ULONG wire_error, control_value;
2018 UBYTE *tx_desc;
2019 UBYTE *(*dma_tx_function)(REG(a0, APTR));
2020 BYTE error;
2021 struct MsgPort *port;
2022 struct TypeStats *tracker;
2024 base = unit->device;
2025 port = unit->request_ports[WRITE_QUEUE];
2027 while(proceed && (!IsMsgPortEmpty(port)))
2029 slot = unit->tx_in_slot;
2030 new_slot = (slot + 1) % TX_SLOT_COUNT;
2032 if(new_slot != unit->tx_out_slot)
2034 error = 0;
2035 body_size = 0;
2037 /* Get request and DMA frame descriptor */
2039 request = (APTR)port->mp_MsgList.lh_Head;
2041 Remove((APTR)request);
2042 unit->tx_requests[slot] = request;
2043 tx_desc = unit->tx_descs[slot];
2044 frame = unit->tx_buffers[slot];
2046 /* Get packet data */
2048 opener = request->ios2_BufferManagement;
2049 dma_tx_function = opener->dma_tx_function;
2050 if(dma_tx_function != NULL)
2051 buffer = dma_tx_function(request->ios2_Data);
2052 else
2053 buffer = NULL;
2055 if(buffer == NULL)
2057 buffer = unit->tx_buffer;
2058 if(!opener->tx_function(buffer, request->ios2_Data,
2059 request->ios2_DataLength))
2061 error = S2ERR_NO_RESOURCES;
2062 wire_error = S2WERR_BUFF_ERROR;
2063 ReportEvents(unit,
2064 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
2065 | S2EVENT_TX, base);
2069 if(error == 0)
2071 /* Get packet type and/or length */
2073 data_size = request->ios2_DataLength;
2074 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) != 0)
2076 data_size -= ETH_PACKET_DATA;
2077 packet_type = BEWord(*(UWORD *)(buffer + ETH_PACKET_TYPE));
2079 else
2080 packet_type = request->ios2_PacketType;
2081 is_ieee = packet_type <= ETH_MTU;
2083 /* Determine encryption type and frame subtype */
2085 if(data_size > 0)
2087 encryption = unit->keys[unit->tx_key_no].type;
2088 subtype = 0;
2090 else
2092 encryption = S2ENC_NONE;
2093 subtype = 4;
2096 /* Get source and destination addresses */
2098 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) != 0)
2100 dest = buffer;
2101 source = buffer + ETH_ADDRESSSIZE;
2102 buffer += ETH_ADDRESSSIZE * 2 + 2;
2104 else
2106 dest = request->ios2_DstAddr;
2107 source = unit->address;
2110 /* Write 802.11 header */
2112 q = frame;
2113 *(UWORD *)q = MakeLEWord(
2114 (encryption == S2ENC_NONE ? 0 : WIFI_FRM_CONTROLF_WEP)
2115 | (unit->mode == S2PORT_ADHOC ? 0 : WIFI_FRM_CONTROLF_TODS)
2116 | subtype << WIFI_FRM_CONTROLB_SUBTYPE
2117 | WIFI_FRMTYPE_DATA << WIFI_FRM_CONTROLB_TYPE);
2118 q += 4;
2120 if(unit->mode == S2PORT_ADHOC)
2121 p = dest;
2122 else
2123 p = unit->bssid;
2124 for(i = 0; i < ETH_ADDRESSSIZE; i++)
2125 *q++ = *p++;
2127 for(i = 0, p = source; i < ETH_ADDRESSSIZE; i++)
2128 *q++ = *p++;
2130 if(unit->mode == S2PORT_ADHOC)
2131 p = unit->bssid;
2132 else
2133 p = dest;
2134 for(i = 0; i < ETH_ADDRESSSIZE; i++)
2135 *q++ = *p++;
2136 *(UWORD *)q = MakeLEWord(unit->tx_sequence);
2137 unit->tx_sequence += 0x10;
2138 q += 2;
2140 /* Leave room for encryption overhead */
2142 ciphertext = q;
2143 q += unit->iv_sizes[encryption];
2144 plaintext = q;
2146 /* Write SNAP header */
2148 if(!is_ieee)
2150 for(i = 0, p = snap_template;
2151 i < SNAP_FRM_TYPE; i++)
2152 *q++ = *p++;
2153 *(UWORD *)q = MakeBEWord(packet_type);
2154 q += 2;
2155 body_size += SNAP_HEADERSIZE;
2158 /* Copy data into frame */
2160 CopyMem(buffer, q, data_size);
2161 body_size += data_size;
2163 /* Append MIC to frame for TKIP */
2165 if(encryption == S2ENC_TKIP)
2167 q = mic_header;
2168 for(i = 0, p = dest; i < ETH_ADDRESSSIZE; i++)
2169 *q++ = *p++;
2170 for(i = 0, p = source; i < ETH_ADDRESSSIZE; i++)
2171 *q++ = *p++;
2172 TKIPEncryptFrame(unit, mic_header, plaintext, body_size,
2173 plaintext, base);
2174 body_size += MIC_SIZE;
2177 /* Encrypt fragment if applicable */
2179 unit->fragment_encrypt_functions[encryption](unit, frame,
2180 plaintext, &body_size, ciphertext, base);
2182 /* Clear frame descriptor as far as start of 802.11 header */
2184 q = tx_desc;
2185 for(i = 0; i < unit->tx_desc_size; i++)
2186 *q++ = 0;
2188 /* Set TX control field */
2190 frame_size = WIFI_FRM_DATA + body_size;
2191 control_value = R8180FRM_TXCONTROLF_NOENC
2192 | R8180FRM_TXCONTROLF_FIRSTFRAG
2193 | R8180FRM_TXCONTROLF_LASTFRAG
2194 | unit->tx_rate_code << R8180FRM_TXCONTROLB_RATE
2195 | frame_size;
2196 *(ULONG *)(tx_desc + R8180FRM_TXCONTROL) =
2197 MakeLELong(control_value);
2199 /* Set durations */
2201 has_bssid = ((frame + WIFI_FRM_ADDRESS1)[0] & 0x1) == 0;
2202 if(has_bssid)
2203 duration = SIFS_TIME + GetDuration(unit, 14,
2204 AckRate(unit, unit->tx_rate, base), FALSE, base);
2205 else
2206 duration = 0;
2207 *(UWORD *)(frame + WIFI_FRM_DURATION) = MakeLEWord(duration);
2209 if(unit->generation >= RTL8187B0_GEN)
2211 duration += GetDuration(unit, frame_size + 4,
2212 unit->tx_rate,
2213 (unit->flags & UNITF_SHORTPREAMBLE) != 0 && has_bssid,
2214 base);
2215 *(UWORD *)(tx_desc + R8180FRM_TXDUR) = MakeLEWord(duration);
2218 /* Set max number of retries */
2220 *(ULONG *)(tx_desc + unit->retries_offset) =
2221 MakeLELong((TX_TRIES - 1) << 8);
2223 /* Pass packet to adapter */
2225 unit->SendFrame(unit->card, tx_desc,
2226 R8180_MAXDESCSIZE + frame_size);
2227 unit->tx_in_slot = new_slot;
2229 else
2231 /* Reply failed request */
2233 request->ios2_Req.io_Error = error;
2234 request->ios2_WireError = wire_error;
2235 ReplyMsg((APTR)request);
2238 /* Update statistics */
2240 if(error == 0)
2242 unit->stats.PacketsSent++;
2244 tracker = FindTypeStats(unit, &unit->type_trackers,
2245 request->ios2_PacketType, base);
2246 if(tracker != NULL)
2248 tracker->stats.PacketsSent++;
2249 tracker->stats.BytesSent += ETH_HEADERSIZE + data_size;
2253 else
2254 proceed = FALSE;
2257 /* Don't try to keep sending packets if there's no space left */
2259 if(proceed)
2261 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
2262 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2264 else
2266 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_IGNORE;
2267 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2270 return;
2275 /****i* realtek8180.device/MgmtTXInt ***************************************
2277 * NAME
2278 * MgmtTXInt -- Soft interrupt for management frame transmission.
2280 * SYNOPSIS
2281 * MgmtTXInt(unit)
2283 * VOID MgmtTXInt(struct DevUnit *);
2285 * FUNCTION
2287 * INPUTS
2288 * unit - A unit of this device.
2290 * RESULT
2291 * None.
2293 ****************************************************************************
2297 static VOID MgmtTXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
2299 struct DevBase *base;
2300 UWORD frame_size, slot, new_slot, i, duration;
2301 UBYTE *desc, *frame, *q;
2302 struct IOSana2Req *request;
2303 BOOL proceed = TRUE, has_bssid;
2304 ULONG control_value;
2305 struct MsgPort *port;
2307 base = unit->device;
2308 port = unit->request_ports[MGMT_QUEUE];
2310 while(proceed && (!IsMsgPortEmpty(port)))
2312 slot = unit->tx_in_slot;
2313 new_slot = (slot + 1) % TX_SLOT_COUNT;
2315 if(new_slot != unit->tx_out_slot)
2317 /* Get request and frame descriptor */
2319 request = (APTR)port->mp_MsgList.lh_Head;
2321 Remove((APTR)request);
2322 unit->tx_requests[slot] = request;
2323 desc = unit->tx_descs[slot];
2324 frame = unit->tx_buffers[slot];
2326 /* Get packet length */
2328 frame_size = request->ios2_DataLength;
2330 /* Copy frame into transmit buffer */
2332 CopyMem(request->ios2_Data, frame, frame_size);
2334 /* Clear frame descriptor as far as start of 802.11 header */
2336 q = desc;
2337 for(i = 0; i < unit->tx_desc_size; i++)
2338 *q++ = 0;
2340 /* Set TX control field */
2342 control_value = R8180FRM_TXCONTROLF_NOENC
2343 | R8180FRM_TXCONTROLF_FIRSTFRAG
2344 | R8180FRM_TXCONTROLF_LASTFRAG
2345 | unit->mgmt_rate_code << R8180FRM_TXCONTROLB_RATE
2346 | frame_size;
2347 *(ULONG *)(desc + R8180FRM_TXCONTROL) = MakeLELong(control_value);
2349 /* Set durations */
2351 has_bssid = ((frame + WIFI_FRM_ADDRESS1)[0] & 0x1) == 0;
2352 if(has_bssid)
2353 duration = SIFS_TIME + GetDuration(unit, 14,
2354 AckRate(unit, unit->mgmt_rate, base), FALSE, base);
2355 else
2356 duration = 0;
2357 *(UWORD *)(frame + WIFI_FRM_DURATION) = MakeLEWord(duration);
2359 if(unit->generation >= RTL8187B0_GEN)
2361 duration += GetDuration(unit, frame_size + 4,
2362 unit->mgmt_rate, FALSE, base);
2363 *(UWORD *)(desc + R8180FRM_TXDUR) = MakeLEWord(duration);
2366 /* Set max number of retries */
2368 *(ULONG *)(desc + unit->retries_offset) =
2369 MakeLELong((TX_TRIES - 1) << 8);
2371 /* Set sequence number */
2373 *(UWORD *)(frame + WIFI_FRM_SEQCONTROL) =
2374 MakeLEWord(unit->tx_sequence);
2375 unit->tx_sequence += 0x10;
2377 /* Pass packet to adapter */
2379 unit->SendFrame(unit->card, desc, R8180_MAXDESCSIZE + frame_size);
2380 unit->tx_in_slot = new_slot;
2382 else
2383 proceed = FALSE;
2386 /* Don't try to keep sending packets if there's no space left */
2388 if(proceed)
2390 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2391 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
2393 else
2395 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2396 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_IGNORE;
2399 return;
2404 /****i* realtek8180.device/RetireTXSlot ************************************
2406 * NAME
2407 * RetireTXSlot -- Clean up after a frame has been sent.
2409 * SYNOPSIS
2410 * RetireTXSlot(unit)
2412 * VOID RetireTXSlot(struct DevUnit *);
2414 ****************************************************************************
2418 VOID RetireTXSlot(struct DevUnit *unit, struct DevBase *base)
2420 UWORD frame_size, slot;
2421 struct IOSana2Req *request;
2422 struct TypeStats *tracker;
2424 /* Update statistics */
2426 slot = unit->tx_out_slot;
2427 request = unit->tx_requests[slot];
2428 if(request->ios2_Req.io_Command != S2_WRITEMGMT)
2430 frame_size = request->ios2_DataLength;
2431 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2432 frame_size += ETH_HEADERSIZE;
2434 tracker = FindTypeStats(unit, &unit->type_trackers,
2435 request->ios2_PacketType, base);
2436 if(tracker != NULL)
2438 tracker->stats.PacketsSent++;
2439 tracker->stats.BytesSent += frame_size;
2443 /* Reply request */
2445 request->ios2_Req.io_Error = 0;
2446 ReplyMsg((APTR)request);
2448 unit->tx_out_slot = (slot + 1) % TX_SLOT_COUNT;
2450 /* Restart downloads if they had stopped */
2452 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
2453 Cause(&unit->tx_int);
2454 if(unit->request_ports[MGMT_QUEUE]->mp_Flags == PA_IGNORE)
2455 Cause(&unit->mgmt_int);
2457 return;
2462 /****i* realtek8180.device/ReportEvents ************************************
2464 * NAME
2465 * ReportEvents
2467 * SYNOPSIS
2468 * ReportEvents(unit, events)
2470 * VOID ReportEvents(struct DevUnit *, ULONG);
2472 * FUNCTION
2474 * INPUTS
2475 * unit - A unit of this device.
2476 * events - A mask of events to report.
2478 * RESULT
2479 * None.
2481 ****************************************************************************
2485 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
2486 struct DevBase *base)
2488 struct IOSana2Req *request, *tail, *next_request;
2489 struct List *list;
2491 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
2492 next_request = (APTR)list->lh_Head;
2493 tail = (APTR)&list->lh_Tail;
2495 Disable();
2496 while(next_request != tail)
2498 request = next_request;
2499 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2501 if((request->ios2_WireError & events) != 0)
2503 request->ios2_WireError = events;
2504 Remove((APTR)request);
2505 ReplyMsg((APTR)request);
2508 Enable();
2510 return;
2515 /****i* realtek8180.device/GetDuration *************************************
2517 * NAME
2518 * GetDuration -- Calculate a duration value.
2520 * SYNOPSIS
2521 * GetDuration(unit, length, rate, is_mgmt)
2523 * VOID GetDuration(struct DevUnit *);
2525 * FUNCTION
2526 * Calculates a duration for a frame of given length when transmitted
2527 * at a given rate. If this is a transmiss
2529 * INPUTS
2530 * unit - A unit of this device.
2531 * length - Length of frame whose duration is to be calculated.
2532 * rate - Rate frame will be transmitted at (in Mbps, rounded down).
2533 * is_short - Indicates if frame has a short preamble.
2535 * RESULT
2536 * None.
2538 ****************************************************************************
2542 static UWORD GetDuration(struct DevUnit *unit, UWORD length, UWORD rate,
2543 BOOL short_preamble, struct DevBase *base)
2545 UWORD duration, cycles;
2547 if (rate % 3 != 0)
2549 duration = 97 + (length * 8 - 1) / rate;
2550 if (!short_preamble || rate == 1)
2551 duration += 96;
2553 else
2555 cycles = rate * 4;
2556 duration = ((length + 29) / cycles + 1) * 4 + 26;
2559 return duration;
2564 /****i* realtek8180.device/AckRate *****************************************
2566 * NAME
2567 * AckRate -- Get the ACK rate corresponding to a data rate.
2569 * SYNOPSIS
2570 * ack_rate = AckRate(unit, data_rate)
2572 * UWORD AckRate(struct DevUnit *, UWORD);
2574 * FUNCTION
2575 * Calculates the rate at which the ACK frame for a data frame with the
2576 * given rate should be transmitted.
2578 * INPUTS
2579 * unit - A unit of this device.
2580 * rate - Rate data frame is transmitted at (in Mbps, rounded down).
2582 * RESULT
2583 * ack_rate - The rate for the ACK frame (Mbps, rounded down).
2585 ****************************************************************************
2589 static UWORD AckRate(struct DevUnit *unit, UWORD data_rate,
2590 struct DevBase *base)
2592 UWORD ack_rate;
2594 switch(data_rate)
2596 case 54:
2597 case 48:
2598 case 36:
2599 case 24:
2600 ack_rate = 24;
2601 break;
2602 case 18:
2603 case 12:
2604 ack_rate = 12;
2605 break;
2606 case 9:
2607 case 6:
2608 ack_rate = 6;
2609 break;
2610 case 11:
2611 case 5:
2612 case 2:
2613 ack_rate = 2;
2614 break;
2615 case 1:
2616 ack_rate = 1;
2617 break;
2620 return ack_rate;
2625 /****i* realtek8180.device/UnitTask ****************************************
2627 * NAME
2628 * UnitTask
2630 * SYNOPSIS
2631 * UnitTask(unit)
2633 * VOID UnitTask(struct DevUnit *);
2635 * FUNCTION
2636 * Completes deferred requests, and handles card insertion and removal
2637 * in conjunction with the relevant interrupts.
2639 ****************************************************************************
2643 static VOID UnitTask(struct DevUnit *unit)
2645 struct DevBase *base;
2646 struct IORequest *request;
2647 struct MsgPort *general_port;
2648 ULONG signals = 0, wait_signals, card_removed_signal,
2649 card_inserted_signal, general_port_signal;
2651 base = unit->device;
2653 /* Activate general request port */
2655 general_port = unit->request_ports[GENERAL_QUEUE];
2656 general_port->mp_SigTask = unit->task;
2657 general_port->mp_SigBit = AllocSignal(-1);
2658 general_port_signal = 1 << general_port->mp_SigBit;
2659 general_port->mp_Flags = PA_SIGNAL;
2661 /* Allocate signals for notification of card removal and insertion */
2663 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
2664 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
2665 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
2666 | card_inserted_signal | SIGBREAKF_CTRL_C;
2668 /* Tell ourselves to check port for old messages */
2670 Signal(unit->task, general_port_signal);
2672 /* Infinite loop to service requests and signals */
2674 while(TRUE)
2676 signals = Wait(wait_signals);
2678 if((signals & card_inserted_signal) != 0)
2680 if(unit->insertion_function(unit->card, base))
2682 unit->flags |= UNITF_HAVEADAPTER;
2683 if((unit->flags & UNITF_CONFIGURED) != 0)
2684 ConfigureAdapter(unit, base);
2685 if((unit->flags & UNITF_WASONLINE) != 0)
2687 GoOnline(unit, base);
2688 unit->flags &= ~UNITF_WASONLINE;
2693 if((signals & card_removed_signal) != 0)
2695 unit->removal_function(unit->card, base);
2696 if((unit->flags & UNITF_WASONLINE) != 0)
2697 GoOffline(unit, base);
2700 if((signals & general_port_signal) != 0)
2702 while((request = (APTR)GetMsg(general_port)) != NULL)
2704 /* Service the request as soon as the unit is free */
2706 ObtainSemaphore(&unit->access_lock);
2707 ServiceRequest((APTR)request, base);