Reverted buggy compiler delint from r50794. It isn't needed now that most
[AROS.git] / workbench / devs / networks / realtek8180 / unit.c
blob505c3281fa15e085f27fa6b7ae89bfa85f13f58e
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 #if !defined(__AROS__)
87 static const UBYTE broadcast_address[] =
88 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
89 #endif
91 #ifdef __amigaos4__
92 #undef AddTask
93 #define AddTask(task, initial_pc, final_pc) \
94 IExec->AddTask(task, initial_pc, final_pc, NULL)
95 #endif
96 #ifdef __MORPHOS__
97 static const struct EmulLibEntry mos_task_trap =
99 TRAP_LIB,
101 (APTR)UnitTask
103 #define UnitTask &mos_task_trap
104 #endif
105 #ifdef __AROS__
106 #undef AddTask
107 #define AddTask(task, initial_pc, final_pc) \
108 ({ \
109 struct TagItem _task_tags[] = \
110 {{TASKTAG_ARG1, (IPTR)SysBase}, {TAG_END, 0}}; \
111 NewAddTask(task, initial_pc, final_pc, _task_tags); \
113 #endif
117 /****i* realtek8180.device/CreateUnit **************************************
119 * NAME
120 * CreateUnit -- Create a unit.
122 * SYNOPSIS
123 * unit = CreateUnit(index, io_base, id, card,
124 * io_tags, bus)
126 * struct DevUnit *CreateUnit(ULONG, APTR, UWORD, APTR,
127 * struct TagItem *, UWORD);
129 * FUNCTION
130 * Creates a new unit.
132 ****************************************************************************
136 struct DevUnit *CreateUnit(ULONG index, APTR card,
137 const struct TagItem *io_tags, UWORD bus, struct DevBase *base)
139 BOOL success = TRUE;
140 struct DevUnit *unit;
141 struct Task *task;
142 struct MsgPort *port;
143 UWORD i;
144 APTR stack;
146 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
147 if(unit == NULL)
148 success = FALSE;
150 if(success)
152 /* Initialise lists etc. */
154 NewList((APTR)&unit->openers);
155 NewList((APTR)&unit->type_trackers);
156 NewList((APTR)&unit->multicast_ranges);
158 unit->index = index;
159 unit->device = base;
160 unit->card = card;
161 unit->bus = bus;
162 unit->generation = RTL8187B1_GEN;
163 unit->tx_rate = 11;
164 unit->tx_rate_code = 3; /* 11 Mbps */
165 unit->mgmt_rate = 1;
166 unit->mgmt_rate_code = 0; /* 1 Mbps */
167 unit->channel = 1;
169 /* Store I/O hooks */
171 unit->ByteOut =
172 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
173 unit->ByteIn =
174 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
175 unit->LEWordIn =
176 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
177 unit->LELongIn =
178 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
179 unit->LEWordOut =
180 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
181 unit->LELongOut =
182 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
183 unit->AllocDMAMem =
184 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
185 unit->FreeDMAMem =
186 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
187 unit->SendFrame =
188 (APTR)GetTagData(IOTAG_SendFrame, (UPINT)NULL, io_tags);
189 unit->ReceiveFrame =
190 (APTR)GetTagData(IOTAG_ReceiveFrame, (UPINT)NULL, io_tags);
191 if(unit->ByteIn == NULL
192 || unit->ByteOut == NULL
193 || unit->LEWordIn == NULL
194 || unit->LELongIn == NULL
195 || unit->LEWordOut == NULL
196 || unit->LELongOut == NULL
197 || unit->AllocDMAMem == NULL
198 || unit->FreeDMAMem == NULL
199 || unit->SendFrame == NULL
200 || unit->ReceiveFrame == NULL)
201 success = FALSE;
204 if(success)
206 InitSemaphore(&unit->access_lock);
208 /* Create the message ports for queuing requests */
210 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
212 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
213 MEMF_PUBLIC | MEMF_CLEAR);
214 if(port == NULL)
215 success = FALSE;
217 if(success)
219 NewList(&port->mp_MsgList);
220 port->mp_Flags = PA_IGNORE;
224 if(success)
226 unit->request_ports[WRITE_QUEUE]->mp_SigTask = &unit->tx_int;
227 unit->request_ports[MGMT_QUEUE]->mp_SigTask = &unit->mgmt_int;
230 /* Allocate buffers and descriptors */
232 unit->tx_buffer = AllocVec(ETH_MAXPACKETSIZE, MEMF_PUBLIC);
233 for(i = 0; i < TX_SLOT_COUNT; i++)
235 unit->tx_descs[i] = unit->AllocDMAMem(unit->card,
236 R8180_MAXDESCSIZE + FRAME_BUFFER_SIZE, 4);
237 if(unit->tx_descs[i] != NULL)
238 unit->tx_buffers[i] = unit->tx_descs[i] + R8180_MAXDESCSIZE;
239 else
240 success = FALSE;
242 unit->rx_buffer = AllocVec(FRAME_BUFFER_SIZE, MEMF_PUBLIC);
243 for(i = 0; i < RX_SLOT_COUNT; i++)
245 if(unit->bus != USB_BUS)
247 unit->rx_descs[i] = unit->AllocDMAMem(unit->card,
248 R8180_MAXDESCSIZE, 4);
249 if(unit->rx_descs[i] == NULL)
250 success = FALSE;
252 unit->rx_buffers[i] = unit->AllocDMAMem(unit->card,
253 FRAME_BUFFER_SIZE + R8180_MAXDESCSIZE, 4);
254 if(unit->rx_buffers[i] == NULL)
255 success = FALSE;
257 unit->rx_frames =
258 AllocVec(FRAME_BUFFER_SIZE * FRAME_BUFFER_COUNT, MEMF_PUBLIC);
259 for(i = 0; i < FRAME_BUFFER_COUNT; i++)
260 unit->rx_fragment_nos[i] = -1;
261 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
262 MEMF_PUBLIC);
263 if(unit->tx_buffer == NULL
264 || unit->rx_buffer == NULL
265 || unit->rx_frames == NULL
266 || unit->tx_requests == NULL)
267 success = FALSE;
270 if(success)
272 /* Initialise network adapter hardware */
274 success = InitialiseAdapter(unit, FALSE, base);
275 unit->flags |= UNITF_HAVEADAPTER;
278 if(success)
280 /* Record maximum speed in BPS */
282 unit->speed = 54000000;
284 /* Initialise interrupts */
286 unit->rx_int.is_Node.ln_Name =
287 base->device.dd_Library.lib_Node.ln_Name;
288 unit->rx_int.is_Code = (APTR)RXInt;
289 unit->rx_int.is_Data = unit;
291 unit->tx_int.is_Node.ln_Name =
292 base->device.dd_Library.lib_Node.ln_Name;
293 unit->tx_int.is_Code = (APTR)TXInt;
294 unit->tx_int.is_Data = unit;
296 unit->mgmt_int.is_Node.ln_Name =
297 base->device.dd_Library.lib_Node.ln_Name;
298 unit->mgmt_int.is_Code = (APTR)MgmtTXInt;
299 unit->mgmt_int.is_Data = unit;
301 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
302 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
304 /* Create a new task */
306 unit->task = task =
307 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
308 if(task == NULL)
309 success = FALSE;
312 if(success)
314 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
315 if(stack == NULL)
316 success = FALSE;
319 if(success)
321 /* Initialise and start task */
323 task->tc_Node.ln_Type = NT_TASK;
324 task->tc_Node.ln_Pri = TASK_PRIORITY;
325 task->tc_Node.ln_Name = base->device.dd_Library.lib_Node.ln_Name;
326 task->tc_SPUpper = stack + STACK_SIZE;
327 task->tc_SPLower = stack;
328 task->tc_SPReg = stack + STACK_SIZE;
329 NewList(&task->tc_MemEntry);
331 if(AddTask(task, UnitTask, NULL) == NULL)
332 success = FALSE;
335 if(success)
337 /* Send the unit to the new task */
339 task->tc_UserData = unit;
341 /* Set default wireless options */
343 unit->mode = S2PORT_MANAGED;
346 if(!success)
348 DeleteUnit(unit, base);
349 unit = NULL;
352 return unit;
357 /****i* realtek8180.device/DeleteUnit **************************************
359 * NAME
360 * DeleteUnit -- Delete a unit.
362 * SYNOPSIS
363 * DeleteUnit(unit)
365 * VOID DeleteUnit(struct DevUnit *);
367 * FUNCTION
368 * Deletes a unit.
370 * INPUTS
371 * unit - Device unit (may be NULL).
373 * RESULT
374 * None.
376 ****************************************************************************
380 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
382 UBYTE i;
383 struct Task *task;
385 if(unit != NULL)
387 task = unit->task;
388 if(task != NULL)
390 if(task->tc_UserData != NULL)
392 RemTask(task);
393 FreeMem(task->tc_SPLower, STACK_SIZE);
395 FreeMem(task, sizeof(struct Task));
398 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
400 if(unit->request_ports[i] != NULL)
401 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
404 if((unit->flags & UNITF_ONLINE) != 0) /* Needed! */
405 GoOffline(unit, base);
407 if((unit->flags & UNITF_HAVEADAPTER) != 0)
408 DeinitialiseAdapter(unit, base);
410 for(i = 0; i < TX_SLOT_COUNT; i++)
411 unit->FreeDMAMem(unit->card, unit->tx_descs[i]);
412 for(i = 0; i < RX_SLOT_COUNT; i++)
414 unit->FreeDMAMem(unit->card, unit->rx_buffers[i]);
415 if(unit->bus != USB_BUS)
416 unit->FreeDMAMem(unit->card, unit->rx_descs[i]);
419 FreeVec(unit->tx_buffer);
420 FreeVec(unit->rx_frames);
421 FreeVec(unit->tx_requests);
422 FreeVec(unit->rx_buffer);
424 FreeMem(unit, sizeof(struct DevUnit));
427 return;
432 /****i* realtek8180.device/InitialiseAdapter *******************************
434 * NAME
435 * InitialiseAdapter
437 * SYNOPSIS
438 * success = InitialiseAdapter(unit, reinsertion)
440 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
442 * FUNCTION
444 * INPUTS
445 * unit
446 * reinsertion
448 * RESULT
449 * success - Success indicator.
451 ****************************************************************************
455 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
456 struct DevBase *base)
458 BOOL success = FALSE;
459 UBYTE reg_62, revision;
460 UWORD *p, i;
461 ULONG rx_conf;
463 /* Initialise EEPROM */
465 rx_conf = unit->LELongIn(unit->card, 0x100 + R8180REG_RXCONF);
466 unit->eeprom_addr_size = ((rx_conf & (1 << 6)) != 0) ? 8 : 6;
468 BusyMicroDelay(10, base);
469 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
471 /* Get default MAC address */
473 p = (UWORD *)unit->default_address;
474 for(i = 0; i < ETH_ADDRESSSIZE / sizeof(UWORD); i++)
475 *p++ = LEWord(ReadEEPROM(unit, R8180ROM_ADDRESS0 + i, base));
477 /* Refine main chip revision */
479 if(unit->generation == RTL8187B1_GEN)
481 revision = unit->ByteIn(unit->card, 0x100 + 0xe1);
482 if(revision == 1 || revision == 2)
483 unit->generation = RTL8187B2_GEN;
485 else
487 if((unit->LELongIn(unit->card, 0x100 + R8180REG_TXCONF)
488 & R8180REG_TXCONFF_HWVER) == 6 << R8180REG_TXCONFB_HWVER)
489 unit->generation = RTL8187B0_GEN;
492 /* Set up power tables */
494 GetPower(unit, base);
496 /* Tune the radio */
498 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
499 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
500 | R8180REG_CONFIG3F_ANAPARAMWRITE | R8180REG_CONFIG3F_GNTSELECT);
501 unit->LELongOut(unit->card, 0x100 + R8180REG_ANAPARAM2, 0x727f3f52);
502 unit->LELongOut(unit->card, 0x100 + R8180REG_ANAPARAM1, 0x45090658);
503 unit->ByteOut(unit->card, 0x100 + R8180REG_ANAPARAM3, 0);
505 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
506 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
507 & ~R8180REG_CONFIG3F_ANAPARAMWRITE);
509 /* Reset PLL sequence */
511 unit->ByteOut(unit->card, 0x161, 0x10);
512 reg_62 = unit->ByteIn(unit->card, 0x162);
513 unit->ByteOut(unit->card, 0x162, reg_62 & ~(1 << 5));
514 unit->ByteOut(unit->card, 0x162, reg_62 | (1 << 5));
516 /* Send reset command */
518 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
519 unit->ByteIn(unit->card, 0x100 + R8180REG_COMMAND)
520 & 0x2 | R8180REG_COMMANDF_RESET);
522 for(i = 0; i < 10 && !success; i++)
524 BusyMilliDelay(2, base);
525 if((unit->ByteIn(unit->card, 0x100 + R8180REG_COMMAND)
526 & R8180REG_COMMANDF_RESET) == 0)
527 success = TRUE;
530 if(success && unit->generation == RTL8187L_GEN)
532 /* Reload registers from EEPROM */
534 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_LOAD);
536 for(i = 0, success = FALSE; i < 10 && !success; i++)
538 BusyMilliDelay(4, base);
539 if((unit->ByteIn(unit->card, 0x100 + R8180REG_EEPROM)
540 & R8180REG_EEPROMF_COMMAND) == 0)
541 success = TRUE;
545 if(success)
547 /* Set up rates */
549 if(unit->generation == RTL8187L_GEN)
550 unit->LEWordOut(unit->card, 0x12d, 0xfff);
551 else
552 unit->LEWordOut(unit->card, 0x134, 0xfff);
553 unit->LEWordOut(unit->card, 0x12c, 0x1ff);
554 unit->ByteOut(unit->card, 0x100 + R8180REG_CWCONF,
555 unit->ByteIn(unit->card, 0x100 + R8180REG_CWCONF)
556 | R8180REG_CWCONFF_PPRETRYSHIFT);
557 unit->ByteOut(unit->card, 0x100 + R8180REG_TXAGCCTL,
558 unit->ByteIn(unit->card, 0x100 + R8180REG_TXAGCCTL)
559 | R8180REG_TXAGCCTLF_PPGAINSHIFT);
561 unit->LEWordOut(unit->card, 0x1e0 | 1 << 16, 0xfff);
562 unit->ByteOut(unit->card, 0x100 + R8180REG_RATEFALLBACK,
563 unit->ByteIn(unit->card, 0x100 + R8180REG_RATEFALLBACK)
564 | R8180REG_RATEFALLBACKF_ENABLE);
566 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR,
567 unit->ByteIn(unit->card, 0x100 + R8180REG_MSR) & 0xf3);
568 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR,
569 unit->ByteIn(unit->card, 0x100 + R8180REG_MSR)
570 | R8180REG_MSRF_ENEDCA);
571 unit->ByteOut(unit->card, 0x100 + R8180REG_ACMCONTROL, 0);
573 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMWINDOW, 2);
574 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL, 100);
575 unit->LEWordOut(unit->card, 0x1d4 | 1 << 16, 0xffff);
577 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
578 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG1,
579 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG1) & 0x3f | 0x80);
580 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, 0);
582 unit->ByteOut(unit->card, 0x100 + R8180REG_WPACONF, 0);
584 unit->ByteOut(unit->card, 0x1f0, 0x32);
585 unit->ByteOut(unit->card, 0x1f1, 0x32);
586 unit->ByteOut(unit->card, 0x1f2, 0x0);
587 unit->ByteOut(unit->card, 0x1f3, 0x0);
588 unit->ByteOut(unit->card, 0x1f4, 0x32);
589 unit->ByteOut(unit->card, 0x1f5, 0x43);
590 unit->ByteOut(unit->card, 0x1f6, 0x0);
591 unit->ByteOut(unit->card, 0x1f7, 0x0);
592 unit->ByteOut(unit->card, 0x1f8, 0x46);
593 unit->ByteOut(unit->card, 0x1f9, 0xa4);
594 unit->ByteOut(unit->card, 0x1fa, 0x0);
595 unit->ByteOut(unit->card, 0x1fb, 0x0);
596 unit->ByteOut(unit->card, 0x1fc, 0x96);
597 unit->ByteOut(unit->card, 0x1fd, 0xa4);
598 unit->ByteOut(unit->card, 0x1fe, 0x0);
599 unit->ByteOut(unit->card, 0x1ff, 0x0);
601 unit->ByteOut(unit->card, 0x158 | 1 << 16, 0x4b);
602 unit->ByteOut(unit->card, 0x159 | 1 << 16, 0x0);
603 unit->ByteOut(unit->card, 0x15a | 1 << 16, 0x4b);
604 unit->ByteOut(unit->card, 0x15b | 1 << 16, 0x0);
605 unit->ByteOut(unit->card, 0x160 | 1 << 16, 0x4b);
606 unit->ByteOut(unit->card, 0x161 | 1 << 16, 0x9);
607 unit->ByteOut(unit->card, 0x162 | 1 << 16, 0x4b);
608 unit->ByteOut(unit->card, 0x163 | 1 << 16, 0x9);
609 unit->ByteOut(unit->card, 0x1ce | 1 << 16, 0xf);
610 unit->ByteOut(unit->card, 0x1cf | 1 << 16, 0x0);
611 unit->ByteOut(unit->card, 0x1e0 | 1 << 16, 0xff);
612 unit->ByteOut(unit->card, 0x1e1 | 1 << 16, 0xf);
613 unit->ByteOut(unit->card, 0x1e2 | 1 << 16, 0x0);
614 unit->ByteOut(unit->card, 0x1f0 | 1 << 16, 0x4e);
615 unit->ByteOut(unit->card, 0x1f1 | 1 << 16, 0x1);
616 unit->ByteOut(unit->card, 0x1f2 | 1 << 16, 0x2);
617 unit->ByteOut(unit->card, 0x1f3 | 1 << 16, 0x3);
618 unit->ByteOut(unit->card, 0x1f4 | 1 << 16, 0x4);
619 unit->ByteOut(unit->card, 0x1f5 | 1 << 16, 0x5);
620 unit->ByteOut(unit->card, 0x1f6 | 1 << 16, 0x6);
621 unit->ByteOut(unit->card, 0x1f7 | 1 << 16, 0x7);
622 unit->ByteOut(unit->card, 0x1f8 | 1 << 16, 0x8);
624 unit->ByteOut(unit->card, 0x14e | 2 << 16, 0x0);
625 unit->ByteOut(unit->card, 0x10c | 2 << 16, 0x4);
626 unit->ByteOut(unit->card, 0x121 | 2 << 16, 0x61);
627 unit->ByteOut(unit->card, 0x122 | 2 << 16, 0x68);
628 unit->ByteOut(unit->card, 0x123 | 2 << 16, 0x6f);
629 unit->ByteOut(unit->card, 0x124 | 2 << 16, 0x76);
630 unit->ByteOut(unit->card, 0x125 | 2 << 16, 0x7d);
631 unit->ByteOut(unit->card, 0x126 | 2 << 16, 0x84);
632 unit->ByteOut(unit->card, 0x127 | 2 << 16, 0x8d);
633 unit->ByteOut(unit->card, 0x14d | 2 << 16, 0x8);
634 unit->ByteOut(unit->card, 0x150 | 2 << 16, 0x5);
635 unit->ByteOut(unit->card, 0x151 | 2 << 16, 0xf5);
636 unit->ByteOut(unit->card, 0x152 | 2 << 16, 0x4);
637 unit->ByteOut(unit->card, 0x153 | 2 << 16, 0xa0);
638 unit->ByteOut(unit->card, 0x154 | 2 << 16, 0x1f);
639 unit->ByteOut(unit->card, 0x155 | 2 << 16, 0x23);
640 unit->ByteOut(unit->card, 0x156 | 2 << 16, 0x45);
641 unit->ByteOut(unit->card, 0x157 | 2 << 16, 0x67);
642 unit->ByteOut(unit->card, 0x158 | 2 << 16, 0x8);
643 unit->ByteOut(unit->card, 0x159 | 2 << 16, 0x8);
644 unit->ByteOut(unit->card, 0x15a | 2 << 16, 0x8);
645 unit->ByteOut(unit->card, 0x15b | 2 << 16, 0x8);
646 unit->ByteOut(unit->card, 0x160 | 2 << 16, 0x8);
647 unit->ByteOut(unit->card, 0x161 | 2 << 16, 0x8);
648 unit->ByteOut(unit->card, 0x162 | 2 << 16, 0x8);
649 unit->ByteOut(unit->card, 0x163 | 2 << 16, 0x8);
650 unit->ByteOut(unit->card, 0x164 | 2 << 16, 0xcf);
651 unit->ByteOut(unit->card, 0x172 | 2 << 16, 0x56);
652 unit->ByteOut(unit->card, 0x173 | 2 << 16, 0x9a);
654 unit->ByteOut(unit->card, 0x134, 0xf0);
655 unit->ByteOut(unit->card, 0x135, 0xf);
656 unit->ByteOut(unit->card, 0x15b, 0x40);
657 unit->ByteOut(unit->card, 0x184, 0x88);
658 unit->ByteOut(unit->card, 0x185, 0x24);
659 unit->ByteOut(unit->card, 0x188, 0x54);
660 unit->ByteOut(unit->card, 0x18b, 0xb8);
661 unit->ByteOut(unit->card, 0x18c, 0x7);
662 unit->ByteOut(unit->card, 0x18d, 0x0);
663 unit->ByteOut(unit->card, 0x194, 0x1b);
664 unit->ByteOut(unit->card, 0x195, 0x12);
665 unit->ByteOut(unit->card, 0x196, 0x0);
666 unit->ByteOut(unit->card, 0x197, 0x6);
667 unit->ByteOut(unit->card, 0x19d, 0x1a);
668 unit->ByteOut(unit->card, 0x19f, 0x10);
669 unit->ByteOut(unit->card, 0x1b4, 0x22);
670 unit->ByteOut(unit->card, 0x1be, 0x80);
671 unit->ByteOut(unit->card, 0x1db, 0x0);
672 unit->ByteOut(unit->card, 0x1ee, 0x0);
673 unit->ByteOut(unit->card, 0x191, 0x3);
674 unit->ByteOut(unit->card, 0x14c | 2 << 16, 0x0);
676 unit->ByteOut(unit->card, 0x19f | 3 << 16, 0x0);
677 unit->ByteOut(unit->card, 0x18c, 0x1);
678 unit->ByteOut(unit->card, 0x18d, 0x10);
679 unit->ByteOut(unit->card, 0x18e, 0x8);
680 unit->ByteOut(unit->card, 0x18f, 0x0);
682 unit->LEWordOut(unit->card, 0x100 + R8180REG_TIDACMAP, 0xfa50);
683 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMIG, 0);
685 unit->LELongOut(unit->card, 0x1f0 | 1 << 16, 0);
686 unit->LELongOut(unit->card, 0x1f4 | 1 << 16, 0);
687 unit->ByteOut(unit->card, 0x1f8 | 1 << 16, 0);
689 unit->LELongOut(unit->card, 0x100 + R8180REG_RFTIMING, 0x4001);
691 unit->LEWordOut(unit->card, 0x172 | 2 << 16, 0x569a);
693 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
695 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
696 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
697 | R8180REG_CONFIG3F_ANAPARAMWRITE);
698 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, 0);
700 /* Turn LED on */
702 unit->ByteOut(unit->card, 0x100 + R8180REG_GPIO0, 1);
703 unit->ByteOut(unit->card, 0x100 + R8180REG_GPENABLE, 0);
705 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSOUTPUT, 0x480);
706 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSSELECT, 0x2488);
707 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSENABLE, 0x1fff);
708 BusyMilliDelay(100, base);
710 /* Initialise radio */
712 success = InitialiseRadio(unit, base);
714 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
715 R8180REG_COMMANDF_TXENABLE | R8180REG_COMMANDF_RXENABLE);
716 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMASK, INT_MASK);
718 unit->ByteOut(unit->card, 0x41, 0xf4);
719 unit->ByteOut(unit->card, 0x40, 0);
720 unit->ByteOut(unit->card, 0x42, 0);
721 unit->ByteOut(unit->card, 0x42, 1);
722 unit->ByteOut(unit->card, 0x40, 0xf);
723 unit->ByteOut(unit->card, 0x42, 0);
724 unit->ByteOut(unit->card, 0x42, 1);
726 unit->ByteOut(unit->card, 0x1db,
727 unit->ByteIn(unit->card, 0x1db) | 1 << 2);
728 unit->LEWordOut(unit->card, 0x172 | 3 << 16, 0x59fa);
729 unit->LEWordOut(unit->card, 0x174 | 3 << 16, 0x59d2);
730 unit->LEWordOut(unit->card, 0x176 | 3 << 16, 0x59d2);
731 unit->LEWordOut(unit->card, 0x178 | 3 << 16, 0x19fa);
732 unit->LEWordOut(unit->card, 0x17a | 3 << 16, 0x19fa);
733 unit->LEWordOut(unit->card, 0x17c | 3 << 16, 0xd0);
734 unit->ByteOut(unit->card, 0x161, 0);
735 unit->ByteOut(unit->card, 0x180 | 1 << 16, 0xf);
736 unit->ByteOut(unit->card, 0x183 | 1 << 16, 3);
737 unit->ByteOut(unit->card, 0x1da, 0x10);
738 unit->ByteOut(unit->card, 0x14d | 2 << 16, 8);
740 unit->LELongOut(unit->card, 0x100 + R8180REG_HSSIPARA, 0x600321b);
742 /* Set maximum RX frame size */
744 unit->LEWordOut(unit->card, 0x1ec | 1 << 16, 0x800);
746 unit->ByteOut(unit->card, 0x100 + R8180REG_ACMCONTROL, 0);
747 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR, R8180REG_MSRF_ENEDCA);
750 if(success)
752 unit->LELongOut(unit->card, 0x100 + R8180REG_RXCONF,
753 R8180REG_RXCONFF_EARLYTHRESH
754 | R8180REG_RXCONFF_AUTORESETPHY
755 | R8180REG_RXCONFF_CHECKBSSID
756 | R8180REG_RXCONFF_MGMT
757 | R8180REG_RXCONFF_DATA
758 | 7 << R8180REG_RXCONFB_FIFOTHRESH
759 | 7 << R8180REG_RXCONFB_MAXDMA
760 | R8180REG_RXCONFF_BCAST
761 | R8180REG_RXCONFF_MCAST
762 | R8180REG_RXCONFF_UCAST);
763 unit->ByteOut(unit->card, 0x100 + R8180REG_TXAGCCTL,
764 unit->ByteIn(unit->card, 0x100 + R8180REG_TXAGCCTL)
765 & ~(R8180REG_TXAGCCTLF_PPGAINSHIFT
766 | R8180REG_TXAGCCTLF_PPANTSELSHIFT
767 | R8180REG_TXAGCCTLF_FEEDBACKANT));
768 unit->LELongOut(unit->card, 0x100 + R8180REG_TXCONF,
769 R8180REG_TXCONFF_DISREQQSIZE
770 | 7 << R8180REG_TXCONFB_MAXDMA
771 | TX_TRIES << R8180REG_TXCONFB_SHORTTRIES
772 | TX_TRIES << R8180REG_TXCONFB_LONGTRIES);
775 /* Determine features, and get offsets of certain fields within frame
776 descriptors */
778 unit->retries_offset = R8180FRM_RETRY;
779 unit->tx_desc_size = 32;
780 unit->rx_desc_size = 20;
782 /* Set IV sizes */
784 unit->iv_sizes[S2ENC_WEP] = IV_SIZE;
785 unit->iv_sizes[S2ENC_TKIP] = EIV_SIZE;
786 unit->iv_sizes[S2ENC_CCMP] = EIV_SIZE;
788 /* Set encryption functions */
790 unit->fragment_encrypt_functions[S2ENC_NONE] = WriteClearFragment;
792 if((unit->flags & UNITF_HARDWEP) != 0)
793 unit->fragment_encrypt_functions[S2ENC_WEP] = WriteWEPFragment;
794 else
795 unit->fragment_encrypt_functions[S2ENC_WEP] = EncryptWEPFragment;
797 if((unit->flags & UNITF_HARDTKIP) != 0)
798 unit->fragment_encrypt_functions[S2ENC_TKIP] = WriteTKIPFragment;
799 else
800 unit->fragment_encrypt_functions[S2ENC_TKIP] = EncryptTKIPFragment;
802 if((unit->flags & UNITF_HARDCCMP) != 0)
803 unit->fragment_encrypt_functions[S2ENC_CCMP] = WriteCCMPFragment;
804 else
805 unit->fragment_encrypt_functions[S2ENC_CCMP] = EncryptCCMPFragment;
807 /* Set decryption functions */
809 unit->fragment_decrypt_functions[S2ENC_NONE] = ReadClearFragment;
811 if((unit->flags & UNITF_HARDWEP) != 0)
812 unit->fragment_decrypt_functions[S2ENC_WEP] = ReadWEPFragment;
813 else
814 unit->fragment_decrypt_functions[S2ENC_WEP] = DecryptWEPFragment;
816 if((unit->flags & UNITF_HARDTKIP) != 0)
817 unit->fragment_decrypt_functions[S2ENC_TKIP] = ReadTKIPFragment;
818 else
819 unit->fragment_decrypt_functions[S2ENC_TKIP] = DecryptTKIPFragment;
821 if((unit->flags & UNITF_HARDCCMP) != 0)
822 unit->fragment_decrypt_functions[S2ENC_CCMP] = ReadCCMPFragment;
823 else
824 unit->fragment_decrypt_functions[S2ENC_CCMP] = DecryptCCMPFragment;
826 /* Return */
828 return success;
833 /****i* realtek8180.device/DeinitialiseAdapter *****************************
835 * NAME
836 * DeinitialiseAdapter
838 * SYNOPSIS
839 * DeinitialiseAdapter(unit)
841 * VOID DeinitialiseAdapter(struct DevUnit *);
843 * FUNCTION
845 * INPUTS
846 * unit
848 * RESULT
849 * None.
851 ****************************************************************************
855 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base)
857 /* Turn LED off */
859 unit->ByteOut(unit->card, 0x100 + R8180REG_GPIO0, 1);
860 unit->ByteOut(unit->card, 0x100 + R8180REG_GPENABLE, 1);
862 return;
867 /****i* realtek8180.device/ConfigureAdapter ********************************
869 * NAME
870 * ConfigureAdapter -- Set up card for transmission/reception.
872 * SYNOPSIS
873 * ConfigureAdapter(unit)
875 * VOID ConfigureAdapter(struct DevUnit *);
877 ****************************************************************************
881 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
883 UBYTE msr;
884 UWORD i;
886 /* Set BSSID */
888 for(i = 0; i < ETH_ADDRESSSIZE; i++)
889 unit->ByteOut(unit->card, 0x100 + R8180REG_BSSID + i, unit->bssid[i]);
891 /* Set channel and power */
893 SetPower(unit, base);
895 msr = unit->ByteIn(unit->card, 0x100 + R8180REG_MSR)
896 & ~R8180REG_MSRF_LINK;
897 if(unit->assoc_id != 0)
899 msr |= 2 << R8180REG_MSRB_LINK;
900 if(unit->generation >= RTL8187B0_GEN)
901 msr |= R8180REG_MSRF_ENEDCA;
903 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR, msr);
905 /* Set intervals */
907 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMWINDOW, 2);
908 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMTRINTERVAL, 100);
909 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL, 100);
910 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL2, 100);
912 if(unit->generation >= RTL8187B0_GEN)
914 unit->ByteOut(unit->card, 0x100 + R8180REG_SIFS, 0x22);
915 if(unit->band == S2BAND_G)
916 unit->ByteOut(unit->card, 0x100 + R8180REG_SLOT, 0x9);
917 else
918 unit->ByteOut(unit->card, 0x100 + R8180REG_SLOT, 0x14);
919 unit->ByteOut(unit->card, 0x100 + R8180REG_EIFS, 0x5b);
920 unit->ByteOut(unit->card, 0x100 + R8180REG_SENSECOUNT, 0x5b);
923 /* Return */
925 return;
930 /****i* realtek8180.device/GoOnline ****************************************
932 * NAME
933 * GoOnline -- Enable transmission/reception.
935 * SYNOPSIS
936 * GoOnline(unit)
938 * VOID GoOnline(struct DevUnit *);
940 ****************************************************************************
944 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
946 /* Enable interrupts */
948 unit->flags |= UNITF_ONLINE;
949 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMASK, INT_MASK);
951 /* Enable frame transmission and reception */
953 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
954 R8180REG_COMMANDF_TXENABLE | R8180REG_COMMANDF_RXENABLE);
956 /* Record start time and report Online event */
958 GetSysTime(&unit->stats.LastStart);
959 ReportEvents(unit, S2EVENT_ONLINE, base);
961 return;
966 /****i* realtek8180.device/GoOffline ***************************************
968 * NAME
969 * GoOffline -- Disable transmission/reception.
971 * SYNOPSIS
972 * GoOffline(unit)
974 * VOID GoOffline(struct DevUnit *);
976 * FUNCTION
978 * INPUTS
979 * unit
981 * RESULT
982 * None.
984 ****************************************************************************
988 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
990 unit->flags &= ~UNITF_ONLINE;
992 /* Flush pending read and write requests */
994 FlushUnit(unit, MGMT_QUEUE, S2ERR_OUTOFSERVICE, base);
996 /* Report Offline event and return */
998 ReportEvents(unit, S2EVENT_OFFLINE, base);
999 return;
1004 /****i* realtek8180.device/SetOptions **************************************
1006 * NAME
1007 * SetOptions -- Set and use interface options.
1009 * SYNOPSIS
1010 * reconfigure = SetOptions(unit, tag_list)
1012 * BOOL SetOptions(struct DevUnit *, struct TagItem *);
1014 ****************************************************************************
1018 BOOL SetOptions(struct DevUnit *unit, const struct TagItem *tag_list,
1019 struct DevBase *base)
1021 struct TagItem *tag_item, *tlist = (struct TagItem *)tag_list;
1022 BOOL reconfigure = TRUE;
1024 while((tag_item = NextTagItem(&tlist)) != NULL)
1026 switch(tag_item->ti_Tag)
1028 case S2INFO_SSID:
1029 ReportEvents(unit, S2EVENT_CONNECT, base);
1030 break;
1032 case S2INFO_BSSID:
1033 CopyMem((APTR)tag_item->ti_Data, unit->bssid, ETH_ADDRESSSIZE);
1034 break;
1036 case S2INFO_AssocID:
1037 unit->assoc_id = tag_item->ti_Data;
1038 break;
1040 case S2INFO_Capabilities:
1041 unit->capabilities = tag_item->ti_Data;
1042 if((unit->capabilities & (1 << 5)) != 0)
1043 unit->flags |= UNITF_SHORTPREAMBLE;
1044 else
1045 unit->flags &= ~UNITF_SHORTPREAMBLE;
1046 break;
1048 case S2INFO_DefaultKeyNo:
1049 unit->tx_key_no = tag_item->ti_Data;
1050 break;
1052 case S2INFO_PortType:
1053 unit->mode = tag_item->ti_Data;
1054 break;
1056 case S2INFO_Channel:
1057 if(tag_item->ti_Data != unit->channel)
1059 unit->channel = tag_item->ti_Data;
1060 reconfigure = TRUE;
1062 break;
1064 case S2INFO_Band:
1065 unit->band = tag_item->ti_Data;
1066 if(unit->band == S2BAND_G)
1068 unit->tx_rate = 54;
1069 unit->tx_rate_code = 11; /* 54 Mbps */
1070 unit->mgmt_rate = 2;
1071 unit->mgmt_rate_code = 1; /* 2 Mbps */
1073 else if(unit->band == S2BAND_B)
1075 unit->tx_rate = 11;
1076 unit->tx_rate_code = 3; /* 11 Mbps */
1077 unit->mgmt_rate = 1;
1078 unit->mgmt_rate_code = 0; /* 1 Mbps */
1080 break;
1085 return reconfigure;
1090 /****i* realtek8180.device/SetKey ******************************************
1092 * NAME
1093 * SetKey -- Set an encryption key.
1095 * SYNOPSIS
1096 * SetKey(unit, index, type, key, key_length,
1097 * rx_counter)
1099 * VOID SetKey(struct DevUnit *, ULONG, ULONG, UBYTE *, ULONG,
1100 * UBYTE *);
1102 ****************************************************************************
1106 VOID SetKey(struct DevUnit *unit, ULONG index, ULONG type, const UBYTE *key,
1107 ULONG key_length, const UBYTE *rx_counter, struct DevBase *base)
1109 struct KeyUnion *slot;
1110 struct EClockVal eclock;
1111 UWORD i;
1113 Disable();
1114 slot = &unit->keys[index];
1115 switch(type)
1117 case S2ENC_WEP:
1118 CopyMem(key, slot->u.wep.key, key_length);
1119 slot->u.wep.length = key_length;
1121 if((unit->flags & UNITF_HARDWEP) == 0)
1123 /* Create a reasonably random IV */
1125 ReadEClock(&eclock);
1126 slot->u.wep.tx_iv = FastRand(eclock.ev_lo ^ eclock.ev_hi);
1129 break;
1131 case S2ENC_TKIP:
1132 CopyMem(key, slot->u.tkip.key, 16);
1133 CopyMem(key + 16, slot->u.tkip.tx_mic_key, MIC_SIZE);
1134 CopyMem(key + 24, slot->u.tkip.rx_mic_key, MIC_SIZE);
1135 slot->u.tkip.tx_iv_low = 0;
1136 slot->u.tkip.tx_iv_high = 0;
1137 slot->u.tkip.rx_iv_low = LEWord(*(UWORD *)rx_counter);
1138 slot->u.tkip.rx_iv_high = LELong(*(ULONG *)(rx_counter + 2));
1139 slot->u.tkip.tx_ttak_set = FALSE;
1140 slot->u.tkip.rx_ttak_set = FALSE;
1142 if((unit->flags & UNITF_HARDTKIP) != 0)
1145 else
1147 /* Convert key to native endianness */
1149 for(i = 0; i < 8; i++)
1150 slot->u.tkip.key[i] = LEWord(slot->u.tkip.key[i]);
1153 break;
1155 case S2ENC_CCMP:
1156 CopyMem(key, slot->u.ccmp.key, 16);
1157 slot->u.ccmp.tx_iv_low = 0;
1158 slot->u.ccmp.tx_iv_high = 0;
1159 slot->u.ccmp.rx_iv_low = LEWord(*(UWORD *)rx_counter);
1160 slot->u.ccmp.rx_iv_high = LELong(*(ULONG *)(rx_counter + 2));
1161 slot->u.ccmp.stream_set = FALSE;
1164 /* Update type of key in selected slot */
1166 slot->type = type;
1167 Enable();
1169 return;
1174 /****i* realtek8180.device/AddMulticastRange *******************************
1176 * NAME
1177 * AddMulticastRange
1179 * SYNOPSIS
1180 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1182 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1184 ****************************************************************************
1188 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1189 const UBYTE *upper_bound, struct DevBase *base)
1191 struct AddressRange *range;
1192 ULONG lower_bound_left, upper_bound_left;
1193 UWORD lower_bound_right, upper_bound_right;
1195 lower_bound_left = BELong(*((ULONG *)lower_bound));
1196 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1197 upper_bound_left = BELong(*((ULONG *)upper_bound));
1198 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1200 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1201 upper_bound_left, upper_bound_right, base);
1203 if(range != NULL)
1204 range->add_count++;
1205 else
1207 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1208 if(range != NULL)
1210 range->lower_bound_left = lower_bound_left;
1211 range->lower_bound_right = lower_bound_right;
1212 range->upper_bound_left = upper_bound_left;
1213 range->upper_bound_right = upper_bound_right;
1214 range->add_count = 1;
1216 Disable();
1217 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
1218 unit->range_count++;
1219 SetMulticast(unit, base);
1220 Enable();
1224 return range != NULL;
1229 /****i* realtek8180.device/RemMulticastRange *******************************
1231 * NAME
1232 * RemMulticastRange
1234 * SYNOPSIS
1235 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1237 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1239 ****************************************************************************
1243 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1244 const UBYTE *upper_bound, struct DevBase *base)
1246 struct AddressRange *range;
1247 ULONG lower_bound_left, upper_bound_left;
1248 UWORD lower_bound_right, upper_bound_right;
1250 lower_bound_left = BELong(*((ULONG *)lower_bound));
1251 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1252 upper_bound_left = BELong(*((ULONG *)upper_bound));
1253 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1255 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1256 upper_bound_left, upper_bound_right, base);
1258 if(range != NULL)
1260 if(--range->add_count == 0)
1262 Disable();
1263 Remove((APTR)range);
1264 unit->range_count--;
1265 SetMulticast(unit, base);
1266 Enable();
1267 FreeMem(range, sizeof(struct AddressRange));
1271 return range != NULL;
1276 /****i* realtek8180.device/FindMulticastRange ******************************
1278 * NAME
1279 * FindMulticastRange
1281 * SYNOPSIS
1282 * range = FindMulticastRange(unit, lower_bound_left,
1283 * lower_bound_right, upper_bound_left, upper_bound_right)
1285 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1286 * UWORD, ULONG, UWORD);
1288 ****************************************************************************
1292 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
1293 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
1294 UWORD upper_bound_right, struct DevBase *base)
1296 struct AddressRange *range, *tail;
1297 BOOL found = FALSE;
1299 range = (APTR)unit->multicast_ranges.mlh_Head;
1300 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1302 while(range != tail && !found)
1304 if(lower_bound_left == range->lower_bound_left &&
1305 lower_bound_right == range->lower_bound_right &&
1306 upper_bound_left == range->upper_bound_left &&
1307 upper_bound_right == range->upper_bound_right)
1308 found = TRUE;
1309 else
1310 range = (APTR)range->node.mln_Succ;
1313 if(!found)
1314 range = NULL;
1316 return range;
1321 /****i* realtek8180.device/SetMulticast ************************************
1323 * NAME
1324 * SetMulticast
1326 * SYNOPSIS
1327 * SetMulticast(unit)
1329 * VOID SetMulticast(struct DevUnit *);
1331 ****************************************************************************
1335 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base)
1337 return;
1342 /****i* realtek8180.device/FindTypeStats ***********************************
1344 * NAME
1345 * FindTypeStats
1347 * SYNOPSIS
1348 * stats = FindTypeStats(unit, list,
1349 * packet_type)
1351 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1352 * ULONG);
1354 ****************************************************************************
1358 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
1359 ULONG packet_type, struct DevBase *base)
1361 struct TypeStats *stats, *tail;
1362 BOOL found = FALSE;
1364 stats = (APTR)list->mlh_Head;
1365 tail = (APTR)&list->mlh_Tail;
1367 while(stats != tail && !found)
1369 if(stats->packet_type == packet_type)
1370 found = TRUE;
1371 else
1372 stats = (APTR)stats->node.mln_Succ;
1375 if(!found)
1376 stats = NULL;
1378 return stats;
1383 /****i* realtek8180.device/FlushUnit ***************************************
1385 * NAME
1386 * FlushUnit
1388 * SYNOPSIS
1389 * FlushUnit(unit, last_queue, error)
1391 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1393 ****************************************************************************
1397 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
1398 struct DevBase *base)
1400 struct IORequest *request;
1401 UBYTE i;
1402 struct Opener *opener, *tail;
1404 /* Abort queued requests */
1406 for(i = 0; i <= last_queue; i++)
1408 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
1410 request->io_Error = IOERR_ABORTED;
1411 ReplyMsg((APTR)request);
1415 #if 1
1416 opener = (APTR)unit->openers.mlh_Head;
1417 tail = (APTR)&unit->openers.mlh_Tail;
1419 /* Flush every opener's read queues */
1421 while(opener != tail)
1423 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1425 request->io_Error = error;
1426 ReplyMsg((APTR)request);
1428 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
1430 request->io_Error = error;
1431 ReplyMsg((APTR)request);
1433 opener = (APTR)opener->node.mln_Succ;
1436 #else
1437 opener = request->ios2_BufferManagement;
1438 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1440 request->io_Error = IOERR_ABORTED;
1441 ReplyMsg((APTR)request);
1443 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
1445 request->io_Error = IOERR_ABORTED;
1446 ReplyMsg((APTR)request);
1448 #endif
1450 /* Return */
1452 return;
1457 /****i* realtek8180.device/RXInt *******************************************
1459 * NAME
1460 * RXInt -- Soft interrupt for packet reception.
1462 * SYNOPSIS
1463 * RXInt(unit)
1465 * VOID RXInt(struct DevUnit *);
1467 * FUNCTION
1469 * INPUTS
1470 * unit - A unit of this device.
1472 * RESULT
1473 * None.
1475 ****************************************************************************
1479 VOID RXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
1481 UWORD ieee_length, frame_control, frame_type, slot, next_slot,
1482 frame_size, frame_subtype, encryption, key_no, buffer_no, old_length;
1483 struct DevBase *base;
1484 BOOL is_good, proceed = TRUE;
1485 LONG frag_no;
1486 ULONG status;
1487 UBYTE *rx_desc, *buffer, *p, *frame, *data, *snap_frame, *source;
1489 base = unit->device;
1490 slot = unit->rx_slot;
1491 rx_desc = unit->rx_descs[slot];
1492 next_slot = (slot + 1) % RX_SLOT_COUNT;
1494 while(proceed)
1496 is_good = TRUE;
1497 buffer = unit->rx_buffers[slot];
1499 status = LELong(*(ULONG *)(rx_desc + R8180FRM_RXSTATUS));
1500 frame_size = status & R8180FRM_RXSTATUSF_LENGTH;
1502 if((status & (R8180FRM_RXSTATUSF_DMAERR | R8180FRM_RXSTATUSF_OVERFLOW
1503 | R8180FRM_RXSTATUSF_RXERR | R8180FRM_RXSTATUSF_BADCRC)) == 0
1504 && frame_size >= WIFI_FRM_DATA + 4)
1506 /* Get fragment info */
1508 frame = buffer;
1509 ieee_length = frame_size - 4 - WIFI_FRM_DATA;
1510 data = frame + WIFI_FRM_DATA;
1511 frame_control =
1512 LEWord(*(UWORD *)(frame + WIFI_FRM_CONTROL));
1514 /* Get buffer to store fragment in */
1516 frag_no = LEWord(*(UWORD *)(frame + WIFI_FRM_SEQCONTROL));
1517 if(unit->mode == S2PORT_ADHOC)
1518 source = frame + WIFI_FRM_ADDRESS2;
1519 else
1520 source = frame + WIFI_FRM_ADDRESS3;
1521 snap_frame = GetRXBuffer(unit, source, frag_no, &buffer_no, base);
1523 /* Get location to put new data */
1525 if(snap_frame != NULL)
1527 if((frag_no & 0xf ) > 0)
1528 old_length =
1529 BEWord(*(UWORD *)(snap_frame + ETH_PACKET_IEEELEN));
1530 else
1532 /* Create new 802.3 header */
1534 CopyMem(frame + WIFI_FRM_ADDRESS1, snap_frame,
1535 ETH_ADDRESSSIZE);
1536 CopyMem(source, snap_frame + ETH_PACKET_SOURCE,
1537 ETH_ADDRESSSIZE);
1538 old_length = 0;
1540 p = snap_frame + ETH_HEADERSIZE + old_length;
1542 /* Append fragment to frame, decrypting fragment if necessary */
1544 if((frame_control & WIFI_FRM_CONTROLF_WEP) != 0)
1546 key_no = data[3] >> 6 & 0x3;
1547 encryption = unit->keys[key_no].type;
1549 else
1550 encryption = S2ENC_NONE;
1552 /* Decrypt, check and/or copy fragment */
1554 is_good = unit->fragment_decrypt_functions[encryption](unit,
1555 frame, data, &ieee_length, p, base);
1557 /* Update length in frame being built with current fragment, or
1558 increment bad frame counter if fragment is bad */
1560 if(is_good)
1562 ieee_length += old_length;
1563 *(UWORD *)(snap_frame + ETH_PACKET_IEEELEN) =
1564 MakeBEWord(ieee_length);
1566 else
1567 unit->stats.BadData++;
1569 /* If all fragments have arrived, process the complete frame */
1571 if((frame_control & WIFI_FRM_CONTROLF_MOREFRAGS) == 0)
1573 if(is_good)
1575 /* Decrypt complete frame if necessary */
1577 data = snap_frame + ETH_HEADERSIZE;
1578 if(encryption == S2ENC_TKIP
1579 && (unit->flags & UNITF_HARDTKIP) == 0)
1581 is_good = TKIPDecryptFrame(unit, snap_frame, data,
1582 ieee_length, data, key_no, base);
1583 ieee_length -= MIC_SIZE;
1584 *(UWORD *)(snap_frame + ETH_PACKET_IEEELEN) =
1585 MakeBEWord(ieee_length);
1586 if(!is_good)
1587 unit->stats.BadData++;
1591 if(is_good)
1593 /* Get frame's 802.11 type and subtype */
1595 frame_type = (frame_control & WIFI_FRM_CONTROLF_TYPE)
1596 >> WIFI_FRM_CONTROLB_TYPE;
1597 frame_subtype =
1598 (frame_control & WIFI_FRM_CONTROLF_SUBTYPE)
1599 >> WIFI_FRM_CONTROLB_SUBTYPE;
1601 /* If it's a management frame, process it separately;
1602 otherwise distribute it to clients after filtering */
1604 if(frame_type == WIFI_FRMTYPE_MGMT)
1606 if(frame_subtype != 8)
1607 DistributeMgmtFrame(unit, frame, frame_size - 4,
1608 base);
1610 else if(AddressFilter(unit, snap_frame + ETH_PACKET_DEST,
1611 base))
1613 unit->stats.PacketsReceived++;
1614 DistributeRXPacket(unit, snap_frame, base);
1619 /* Mark fragment buffer as unused for next time */
1621 unit->rx_fragment_nos[buffer_no] = -1;
1623 else
1624 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_RX, base);
1626 else
1628 is_good = FALSE;
1631 if(!is_good)
1633 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1634 base);
1637 /* Prepare descriptor for next time */
1639 unit->ReceiveFrame(unit->card, buffer,
1640 FRAME_BUFFER_SIZE + R8180_MAXDESCSIZE);
1642 /* Get next descriptor */
1644 slot = next_slot;
1645 if(unit->bus == USB_BUS)
1646 proceed = FALSE;
1649 unit->rx_slot = slot;
1651 return;
1656 /****i* realtek8180.device/GetRXBuffer *************************************
1658 * NAME
1659 * GetRXBuffer -- Find an appropriate RX frame buffer to use.
1661 * SYNOPSIS
1662 * buffer = GetRXBuffer(unit, address, frag_no)
1664 * UBYTE *GetRXBuffer(struct DevUnit *, UBYTE *, UWORD);
1666 ****************************************************************************
1670 static UBYTE *GetRXBuffer(struct DevUnit *unit, const UBYTE *address,
1671 UWORD frag_no, UWORD *buffer_no, struct DevBase *base)
1673 UWORD i;
1674 UBYTE *buffer;
1675 LONG n;
1676 BOOL found;
1678 buffer = unit->rx_frames;
1679 for(i = 0, found = FALSE; i < FRAME_BUFFER_COUNT * 2 && !found; i++)
1681 /* Throw away old buffer contents if we didn't find a free slot the
1682 first time around */
1684 if(i >= FRAME_BUFFER_COUNT)
1685 unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT] = -1;
1687 /* For a frame's first fragment, find an empty slot; for subsequent
1688 fragments, find a slot with matching source address */
1690 n = unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT];
1691 if(n == -1 && (frag_no & 0xf) == 0
1692 || *((ULONG *)(buffer + ETH_PACKET_SOURCE))
1693 == *((ULONG *)(address))
1694 && *((UWORD *)(buffer + ETH_PACKET_SOURCE + 4))
1695 == *((UWORD *)(address + 4)))
1697 found = TRUE;
1698 if(n == -1)
1699 unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT] = frag_no;
1700 *buffer_no = i;
1702 else
1703 buffer += FRAME_BUFFER_SIZE;
1706 if(!found)
1707 buffer = NULL;
1709 return buffer;
1714 /****i* realtek8180.device/DistributeRXPacket ******************************
1716 * NAME
1717 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1719 * SYNOPSIS
1720 * DistributeRXPacket(unit, frame)
1722 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1724 ****************************************************************************
1728 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *frame,
1729 struct DevBase *base)
1731 UWORD packet_size, ieee_length;
1732 BOOL is_orphan = TRUE, accepted, is_snap = FALSE;
1733 ULONG packet_type;
1734 UBYTE *buffer;
1735 const UBYTE *template = snap_template;
1736 struct IOSana2Req *request, *request_tail;
1737 struct Opener *opener, *opener_tail;
1738 struct TypeStats *tracker;
1740 buffer = unit->rx_buffer;
1741 ieee_length = BEWord(*(UWORD *)(frame + ETH_PACKET_IEEELEN));
1742 packet_size = ETH_HEADERSIZE + ieee_length;
1743 if(ieee_length >= SNAP_HEADERSIZE)
1744 is_snap = *(const ULONG *)(frame + ETH_PACKET_DATA)
1745 == *(const ULONG *)template;
1747 /* De-encapsulate SNAP packets and get packet type */
1749 if(is_snap)
1751 packet_size -= SNAP_HEADERSIZE;
1752 CopyMem(frame, buffer, ETH_PACKET_TYPE);
1753 CopyMem(frame + ETH_HEADERSIZE + SNAP_FRM_TYPE,
1754 buffer + ETH_PACKET_TYPE, packet_size - ETH_PACKET_TYPE);
1756 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1758 /* Offer packet to every opener */
1760 opener = (APTR)unit->openers.mlh_Head;
1761 opener_tail = (APTR)&unit->openers.mlh_Tail;
1763 while(opener != opener_tail)
1765 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1766 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1767 accepted = FALSE;
1769 /* Offer packet to each request until it's accepted */
1771 while(request != request_tail && !accepted)
1773 if(request->ios2_PacketType == packet_type)
1775 CopyPacket(unit, request, packet_size, packet_type,
1776 buffer, base);
1777 accepted = TRUE;
1779 request =
1780 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1783 if(accepted)
1784 is_orphan = FALSE;
1785 opener = (APTR)opener->node.mln_Succ;
1788 /* If packet was unwanted, give it to S2_READORPHAN request */
1790 if(is_orphan)
1792 unit->stats.UnknownTypesReceived++;
1793 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1795 CopyPacket(unit,
1796 (APTR)unit->request_ports[ADOPT_QUEUE]->
1797 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1798 base);
1802 /* Update remaining statistics */
1804 if(packet_type <= ETH_MTU)
1805 packet_type = ETH_MTU;
1806 tracker =
1807 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1808 if(tracker != NULL)
1810 tracker->stats.PacketsReceived++;
1811 tracker->stats.BytesReceived += packet_size;
1814 return;
1819 /****i* realtek8180.device/CopyPacket **************************************
1821 * NAME
1822 * CopyPacket -- Copy packet to client's buffer.
1824 * SYNOPSIS
1825 * CopyPacket(unit, request, packet_size, packet_type,
1826 * buffer)
1828 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1829 * UBYTE *);
1831 ****************************************************************************
1835 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1836 UWORD packet_size, UWORD packet_type, UBYTE *buffer,
1837 struct DevBase *base)
1839 struct Opener *opener;
1840 BOOL filtered = FALSE;
1842 /* Set multicast and broadcast flags */
1844 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1845 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1846 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1847 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1848 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1849 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1851 /* Set source and destination addresses and packet type */
1853 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1854 ETH_ADDRESSSIZE);
1855 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1856 ETH_ADDRESSSIZE);
1857 request->ios2_PacketType = packet_type;
1859 /* Adjust for cooked packet request */
1861 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1863 packet_size -= ETH_PACKET_DATA;
1864 buffer += ETH_PACKET_DATA;
1866 #ifdef USE_HACKS
1867 else
1868 packet_size += 4; /* Needed for Shapeshifter & Fusion? */
1869 #endif
1870 request->ios2_DataLength = packet_size;
1872 /* Filter packet */
1874 opener = request->ios2_BufferManagement;
1875 if(request->ios2_Req.io_Command == CMD_READ &&
1876 opener->filter_hook != NULL)
1877 if(!CallHookPkt(opener->filter_hook, request, buffer))
1878 filtered = TRUE;
1880 if(!filtered)
1882 /* Copy packet into opener's buffer and reply packet */
1884 if(!opener->rx_function(request->ios2_Data, buffer, packet_size))
1886 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1887 request->ios2_WireError = S2WERR_BUFF_ERROR;
1888 ReportEvents(unit,
1889 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1890 base);
1892 Remove((APTR)request);
1893 ReplyMsg((APTR)request);
1896 return;
1901 /****i* realtek8180.device/AddressFilter ***********************************
1903 * NAME
1904 * AddressFilter -- Determine if an RX packet should be accepted.
1906 * SYNOPSIS
1907 * accept = AddressFilter(unit, address)
1909 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1911 ****************************************************************************
1915 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1916 struct DevBase *base)
1918 struct AddressRange *range, *tail;
1919 BOOL accept = TRUE;
1920 ULONG address_left;
1921 UWORD address_right;
1923 /* Check whether address is unicast/broadcast or multicast */
1925 address_left = BELong(*((ULONG *)address));
1926 address_right = BEWord(*((UWORD *)(address + 4)));
1928 if(((address_left & 0x01000000) != 0) &&
1929 !((address_left == 0xffffffff) && (address_right == 0xffff)))
1931 /* Check if this multicast address is wanted */
1933 range = (APTR)unit->multicast_ranges.mlh_Head;
1934 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1935 accept = FALSE;
1937 while((range != tail) && !accept)
1939 if((address_left > range->lower_bound_left ||
1940 address_left == range->lower_bound_left &&
1941 address_right >= range->lower_bound_right) &&
1942 (address_left < range->upper_bound_left ||
1943 address_left == range->upper_bound_left &&
1944 address_right <= range->upper_bound_right))
1945 accept = TRUE;
1946 range = (APTR)range->node.mln_Succ;
1949 if(!accept)
1950 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1953 return accept;
1958 /****i* realtek8180.device/DistributeMgmtFrame *****************************
1960 * NAME
1961 * DistributeMgmtFrame -- Send a management frame to clients.
1963 * SYNOPSIS
1964 * DistributeMgmtFrame(unit, frame, frame_size)
1966 * VOID DistributeMgmtFrame(struct DevUnit *, UBYTE *, UWORD);
1968 ****************************************************************************
1972 static VOID DistributeMgmtFrame(struct DevUnit *unit, UBYTE *frame,
1973 UWORD frame_size, struct DevBase *base)
1975 struct IOSana2Req *request;
1976 struct Opener *opener, *opener_tail;
1978 /* Send packet to every opener */
1980 opener = (APTR)unit->openers.mlh_Head;
1981 opener_tail = (APTR)&unit->openers.mlh_Tail;
1983 while(opener != opener_tail)
1985 request = (APTR)RemHead(&opener->mgmt_port.mp_MsgList);
1987 if(request != NULL)
1989 /* Copy packet into opener's buffer and reply packet */
1991 if(frame_size <= request->ios2_DataLength)
1993 CopyMem(frame, request->ios2_Data, frame_size);
1994 request->ios2_DataLength = frame_size;
1996 else
1998 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1999 request->ios2_WireError = S2WERR_BUFF_ERROR;
2000 ReportEvents(unit,
2001 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
2002 base);
2004 ReplyMsg((APTR)request);
2005 request =
2006 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2009 opener = (APTR)opener->node.mln_Succ;
2012 return;
2017 /****i* realtek8180.device/TXInt *******************************************
2019 * NAME
2020 * TXInt -- Soft interrupt for packet transmission.
2022 * SYNOPSIS
2023 * TXInt(unit)
2025 * VOID TXInt(struct DevUnit *);
2027 * FUNCTION
2029 * INPUTS
2030 * unit - A unit of this device.
2032 * RESULT
2033 * None.
2035 ****************************************************************************
2039 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
2041 struct DevBase *base;
2042 UWORD i, frame_size, data_size, packet_type, body_size, slot, new_slot,
2043 encryption, subtype, duration;
2044 UBYTE *buffer, *q, *plaintext, *ciphertext, *frame,
2045 mic_header[ETH_ADDRESSSIZE * 2];
2046 const UBYTE *p, *dest, *source;
2047 struct IOSana2Req *request;
2048 BOOL proceed = TRUE, is_ieee, has_bssid;
2049 struct Opener *opener;
2050 ULONG wire_error, control_value;
2051 UBYTE *tx_desc;
2052 UBYTE *(*dma_tx_function)(REG(a0, APTR));
2053 BYTE error;
2054 struct MsgPort *port;
2055 struct TypeStats *tracker;
2057 base = unit->device;
2058 port = unit->request_ports[WRITE_QUEUE];
2060 while(proceed && (!IsMsgPortEmpty(port)))
2062 slot = unit->tx_in_slot;
2063 new_slot = (slot + 1) % TX_SLOT_COUNT;
2065 if(new_slot != unit->tx_out_slot)
2067 error = 0;
2068 body_size = 0;
2070 /* Get request and DMA frame descriptor */
2072 request = (APTR)port->mp_MsgList.lh_Head;
2074 Remove((APTR)request);
2075 unit->tx_requests[slot] = request;
2076 tx_desc = unit->tx_descs[slot];
2077 frame = unit->tx_buffers[slot];
2079 /* Get packet data */
2081 opener = request->ios2_BufferManagement;
2082 dma_tx_function = opener->dma_tx_function;
2083 if(dma_tx_function != NULL)
2084 buffer = dma_tx_function(request->ios2_Data);
2085 else
2086 buffer = NULL;
2088 if(buffer == NULL)
2090 buffer = unit->tx_buffer;
2091 if(!opener->tx_function(buffer, request->ios2_Data,
2092 request->ios2_DataLength))
2094 error = S2ERR_NO_RESOURCES;
2095 wire_error = S2WERR_BUFF_ERROR;
2096 ReportEvents(unit,
2097 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
2098 | S2EVENT_TX, base);
2102 if(error == 0)
2104 /* Get packet type and/or length */
2106 data_size = request->ios2_DataLength;
2107 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) != 0)
2109 data_size -= ETH_PACKET_DATA;
2110 packet_type = BEWord(*(UWORD *)(buffer + ETH_PACKET_TYPE));
2112 else
2113 packet_type = request->ios2_PacketType;
2114 is_ieee = packet_type <= ETH_MTU;
2116 /* Determine encryption type and frame subtype */
2118 if(data_size > 0)
2120 encryption = unit->keys[unit->tx_key_no].type;
2121 subtype = 0;
2123 else
2125 encryption = S2ENC_NONE;
2126 subtype = 4;
2129 /* Get source and destination addresses */
2131 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) != 0)
2133 dest = buffer;
2134 source = buffer + ETH_ADDRESSSIZE;
2135 buffer += ETH_ADDRESSSIZE * 2 + 2;
2137 else
2139 dest = request->ios2_DstAddr;
2140 source = unit->address;
2143 /* Write 802.11 header */
2145 q = frame;
2146 *(UWORD *)q = MakeLEWord(
2147 (encryption == S2ENC_NONE ? 0 : WIFI_FRM_CONTROLF_WEP)
2148 | (unit->mode == S2PORT_ADHOC ? 0 : WIFI_FRM_CONTROLF_TODS)
2149 | subtype << WIFI_FRM_CONTROLB_SUBTYPE
2150 | WIFI_FRMTYPE_DATA << WIFI_FRM_CONTROLB_TYPE);
2151 q += 4;
2153 if(unit->mode == S2PORT_ADHOC)
2154 p = dest;
2155 else
2156 p = unit->bssid;
2157 for(i = 0; i < ETH_ADDRESSSIZE; i++)
2158 *q++ = *p++;
2160 for(i = 0, p = source; i < ETH_ADDRESSSIZE; i++)
2161 *q++ = *p++;
2163 if(unit->mode == S2PORT_ADHOC)
2164 p = unit->bssid;
2165 else
2166 p = dest;
2167 for(i = 0; i < ETH_ADDRESSSIZE; i++)
2168 *q++ = *p++;
2169 *(UWORD *)q = MakeLEWord(unit->tx_sequence);
2170 unit->tx_sequence += 0x10;
2171 q += 2;
2173 /* Leave room for encryption overhead */
2175 ciphertext = q;
2176 q += unit->iv_sizes[encryption];
2177 plaintext = q;
2179 /* Write SNAP header */
2181 if(!is_ieee)
2183 for(i = 0, p = snap_template;
2184 i < SNAP_FRM_TYPE; i++)
2185 *q++ = *p++;
2186 *(UWORD *)q = MakeBEWord(packet_type);
2187 q += 2;
2188 body_size += SNAP_HEADERSIZE;
2191 /* Copy data into frame */
2193 CopyMem(buffer, q, data_size);
2194 body_size += data_size;
2196 /* Append MIC to frame for TKIP */
2198 if(encryption == S2ENC_TKIP)
2200 q = mic_header;
2201 for(i = 0, p = dest; i < ETH_ADDRESSSIZE; i++)
2202 *q++ = *p++;
2203 for(i = 0, p = source; i < ETH_ADDRESSSIZE; i++)
2204 *q++ = *p++;
2205 TKIPEncryptFrame(unit, mic_header, plaintext, body_size,
2206 plaintext, base);
2207 body_size += MIC_SIZE;
2210 /* Encrypt fragment if applicable */
2212 unit->fragment_encrypt_functions[encryption](unit, frame,
2213 plaintext, &body_size, ciphertext, base);
2215 /* Clear frame descriptor as far as start of 802.11 header */
2217 q = tx_desc;
2218 for(i = 0; i < unit->tx_desc_size; i++)
2219 *q++ = 0;
2221 /* Set TX control field */
2223 frame_size = WIFI_FRM_DATA + body_size;
2224 control_value = R8180FRM_TXCONTROLF_NOENC
2225 | R8180FRM_TXCONTROLF_FIRSTFRAG
2226 | R8180FRM_TXCONTROLF_LASTFRAG
2227 | unit->tx_rate_code << R8180FRM_TXCONTROLB_RATE
2228 | frame_size;
2229 *(ULONG *)(tx_desc + R8180FRM_TXCONTROL) =
2230 MakeLELong(control_value);
2232 /* Set durations */
2234 has_bssid = ((frame + WIFI_FRM_ADDRESS1)[0] & 0x1) == 0;
2235 if(has_bssid)
2236 duration = SIFS_TIME + GetDuration(unit, 14,
2237 AckRate(unit, unit->tx_rate, base), FALSE, base);
2238 else
2239 duration = 0;
2240 *(UWORD *)(frame + WIFI_FRM_DURATION) = MakeLEWord(duration);
2242 if(unit->generation >= RTL8187B0_GEN)
2244 duration += GetDuration(unit, frame_size + 4,
2245 unit->tx_rate,
2246 (unit->flags & UNITF_SHORTPREAMBLE) != 0 && has_bssid,
2247 base);
2248 *(UWORD *)(tx_desc + R8180FRM_TXDUR) = MakeLEWord(duration);
2251 /* Set max number of retries */
2253 *(ULONG *)(tx_desc + unit->retries_offset) =
2254 MakeLELong((TX_TRIES - 1) << 8);
2256 /* Pass packet to adapter */
2258 unit->SendFrame(unit->card, tx_desc,
2259 R8180_MAXDESCSIZE + frame_size);
2260 unit->tx_in_slot = new_slot;
2262 else
2264 /* Reply failed request */
2266 request->ios2_Req.io_Error = error;
2267 request->ios2_WireError = wire_error;
2268 ReplyMsg((APTR)request);
2271 /* Update statistics */
2273 if(error == 0)
2275 unit->stats.PacketsSent++;
2277 tracker = FindTypeStats(unit, &unit->type_trackers,
2278 request->ios2_PacketType, base);
2279 if(tracker != NULL)
2281 tracker->stats.PacketsSent++;
2282 tracker->stats.BytesSent += ETH_HEADERSIZE + data_size;
2286 else
2287 proceed = FALSE;
2290 /* Don't try to keep sending packets if there's no space left */
2292 if(proceed)
2294 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
2295 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2297 else
2299 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_IGNORE;
2300 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2303 return;
2308 /****i* realtek8180.device/MgmtTXInt ***************************************
2310 * NAME
2311 * MgmtTXInt -- Soft interrupt for management frame transmission.
2313 * SYNOPSIS
2314 * MgmtTXInt(unit)
2316 * VOID MgmtTXInt(struct DevUnit *);
2318 * FUNCTION
2320 * INPUTS
2321 * unit - A unit of this device.
2323 * RESULT
2324 * None.
2326 ****************************************************************************
2330 static VOID MgmtTXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
2332 struct DevBase *base;
2333 UWORD frame_size, slot, new_slot, i, duration;
2334 UBYTE *desc, *frame, *q;
2335 struct IOSana2Req *request;
2336 BOOL proceed = TRUE, has_bssid;
2337 ULONG control_value;
2338 struct MsgPort *port;
2340 base = unit->device;
2341 port = unit->request_ports[MGMT_QUEUE];
2343 while(proceed && (!IsMsgPortEmpty(port)))
2345 slot = unit->tx_in_slot;
2346 new_slot = (slot + 1) % TX_SLOT_COUNT;
2348 if(new_slot != unit->tx_out_slot)
2350 /* Get request and frame descriptor */
2352 request = (APTR)port->mp_MsgList.lh_Head;
2354 Remove((APTR)request);
2355 unit->tx_requests[slot] = request;
2356 desc = unit->tx_descs[slot];
2357 frame = unit->tx_buffers[slot];
2359 /* Get packet length */
2361 frame_size = request->ios2_DataLength;
2363 /* Copy frame into transmit buffer */
2365 CopyMem(request->ios2_Data, frame, frame_size);
2367 /* Clear frame descriptor as far as start of 802.11 header */
2369 q = desc;
2370 for(i = 0; i < unit->tx_desc_size; i++)
2371 *q++ = 0;
2373 /* Set TX control field */
2375 control_value = R8180FRM_TXCONTROLF_NOENC
2376 | R8180FRM_TXCONTROLF_FIRSTFRAG
2377 | R8180FRM_TXCONTROLF_LASTFRAG
2378 | unit->mgmt_rate_code << R8180FRM_TXCONTROLB_RATE
2379 | frame_size;
2380 *(ULONG *)(desc + R8180FRM_TXCONTROL) = MakeLELong(control_value);
2382 /* Set durations */
2384 has_bssid = ((frame + WIFI_FRM_ADDRESS1)[0] & 0x1) == 0;
2385 if(has_bssid)
2386 duration = SIFS_TIME + GetDuration(unit, 14,
2387 AckRate(unit, unit->mgmt_rate, base), FALSE, base);
2388 else
2389 duration = 0;
2390 *(UWORD *)(frame + WIFI_FRM_DURATION) = MakeLEWord(duration);
2392 if(unit->generation >= RTL8187B0_GEN)
2394 duration += GetDuration(unit, frame_size + 4,
2395 unit->mgmt_rate, FALSE, base);
2396 *(UWORD *)(desc + R8180FRM_TXDUR) = MakeLEWord(duration);
2399 /* Set max number of retries */
2401 *(ULONG *)(desc + unit->retries_offset) =
2402 MakeLELong((TX_TRIES - 1) << 8);
2404 /* Set sequence number */
2406 *(UWORD *)(frame + WIFI_FRM_SEQCONTROL) =
2407 MakeLEWord(unit->tx_sequence);
2408 unit->tx_sequence += 0x10;
2410 /* Pass packet to adapter */
2412 unit->SendFrame(unit->card, desc, R8180_MAXDESCSIZE + frame_size);
2413 unit->tx_in_slot = new_slot;
2415 else
2416 proceed = FALSE;
2419 /* Don't try to keep sending packets if there's no space left */
2421 if(proceed)
2423 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2424 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
2426 else
2428 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2429 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_IGNORE;
2432 return;
2437 /****i* realtek8180.device/RetireTXSlot ************************************
2439 * NAME
2440 * RetireTXSlot -- Clean up after a frame has been sent.
2442 * SYNOPSIS
2443 * RetireTXSlot(unit)
2445 * VOID RetireTXSlot(struct DevUnit *);
2447 ****************************************************************************
2451 VOID RetireTXSlot(struct DevUnit *unit, struct DevBase *base)
2453 UWORD frame_size, slot;
2454 struct IOSana2Req *request;
2455 struct TypeStats *tracker;
2457 /* Update statistics */
2459 slot = unit->tx_out_slot;
2460 request = unit->tx_requests[slot];
2461 if(request->ios2_Req.io_Command != S2_WRITEMGMT)
2463 frame_size = request->ios2_DataLength;
2464 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2465 frame_size += ETH_HEADERSIZE;
2467 tracker = FindTypeStats(unit, &unit->type_trackers,
2468 request->ios2_PacketType, base);
2469 if(tracker != NULL)
2471 tracker->stats.PacketsSent++;
2472 tracker->stats.BytesSent += frame_size;
2476 /* Reply request */
2478 request->ios2_Req.io_Error = 0;
2479 ReplyMsg((APTR)request);
2481 unit->tx_out_slot = (slot + 1) % TX_SLOT_COUNT;
2483 /* Restart downloads if they had stopped */
2485 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
2486 Cause(&unit->tx_int);
2487 if(unit->request_ports[MGMT_QUEUE]->mp_Flags == PA_IGNORE)
2488 Cause(&unit->mgmt_int);
2490 return;
2495 /****i* realtek8180.device/ReportEvents ************************************
2497 * NAME
2498 * ReportEvents
2500 * SYNOPSIS
2501 * ReportEvents(unit, events)
2503 * VOID ReportEvents(struct DevUnit *, ULONG);
2505 * FUNCTION
2507 * INPUTS
2508 * unit - A unit of this device.
2509 * events - A mask of events to report.
2511 * RESULT
2512 * None.
2514 ****************************************************************************
2518 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
2519 struct DevBase *base)
2521 struct IOSana2Req *request, *tail, *next_request;
2522 struct List *list;
2524 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
2525 next_request = (APTR)list->lh_Head;
2526 tail = (APTR)&list->lh_Tail;
2528 Disable();
2529 while(next_request != tail)
2531 request = next_request;
2532 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2534 if((request->ios2_WireError & events) != 0)
2536 request->ios2_WireError = events;
2537 Remove((APTR)request);
2538 ReplyMsg((APTR)request);
2541 Enable();
2543 return;
2548 /****i* realtek8180.device/GetDuration *************************************
2550 * NAME
2551 * GetDuration -- Calculate a duration value.
2553 * SYNOPSIS
2554 * GetDuration(unit, length, rate, is_mgmt)
2556 * VOID GetDuration(struct DevUnit *);
2558 * FUNCTION
2559 * Calculates a duration for a frame of given length when transmitted
2560 * at a given rate. If this is a transmiss
2562 * INPUTS
2563 * unit - A unit of this device.
2564 * length - Length of frame whose duration is to be calculated.
2565 * rate - Rate frame will be transmitted at (in Mbps, rounded down).
2566 * is_short - Indicates if frame has a short preamble.
2568 * RESULT
2569 * None.
2571 ****************************************************************************
2575 static UWORD GetDuration(struct DevUnit *unit, UWORD length, UWORD rate,
2576 BOOL short_preamble, struct DevBase *base)
2578 UWORD duration, cycles;
2580 if (rate % 3 != 0)
2582 duration = 97 + (length * 8 - 1) / rate;
2583 if (!short_preamble || rate == 1)
2584 duration += 96;
2586 else
2588 cycles = rate * 4;
2589 duration = ((length + 29) / cycles + 1) * 4 + 26;
2592 return duration;
2597 /****i* realtek8180.device/AckRate *****************************************
2599 * NAME
2600 * AckRate -- Get the ACK rate corresponding to a data rate.
2602 * SYNOPSIS
2603 * ack_rate = AckRate(unit, data_rate)
2605 * UWORD AckRate(struct DevUnit *, UWORD);
2607 * FUNCTION
2608 * Calculates the rate at which the ACK frame for a data frame with the
2609 * given rate should be transmitted.
2611 * INPUTS
2612 * unit - A unit of this device.
2613 * rate - Rate data frame is transmitted at (in Mbps, rounded down).
2615 * RESULT
2616 * ack_rate - The rate for the ACK frame (Mbps, rounded down).
2618 ****************************************************************************
2622 static UWORD AckRate(struct DevUnit *unit, UWORD data_rate,
2623 struct DevBase *base)
2625 UWORD ack_rate;
2627 switch(data_rate)
2629 case 54:
2630 case 48:
2631 case 36:
2632 case 24:
2633 ack_rate = 24;
2634 break;
2635 case 18:
2636 case 12:
2637 ack_rate = 12;
2638 break;
2639 case 9:
2640 case 6:
2641 ack_rate = 6;
2642 break;
2643 case 11:
2644 case 5:
2645 case 2:
2646 ack_rate = 2;
2647 break;
2648 case 1:
2649 ack_rate = 1;
2650 break;
2653 return ack_rate;
2658 /****i* realtek8180.device/UnitTask ****************************************
2660 * NAME
2661 * UnitTask
2663 * SYNOPSIS
2664 * UnitTask()
2666 * VOID UnitTask();
2668 * FUNCTION
2669 * Completes deferred requests, and handles card insertion and removal
2670 * in conjunction with the relevant interrupts.
2672 ****************************************************************************
2676 #ifdef __MORPHOS__
2677 #undef UnitTask
2678 #endif
2680 static VOID UnitTask(struct ExecBase *sys_base)
2682 struct Task *task;
2683 struct IORequest *request;
2684 struct DevUnit *unit;
2685 struct DevBase *base;
2686 struct MsgPort *general_port;
2687 ULONG signals = 0, wait_signals, card_removed_signal,
2688 card_inserted_signal, general_port_signal;
2690 /* Get parameters */
2692 task = AbsExecBase->ThisTask;
2693 unit = task->tc_UserData;
2694 base = unit->device;
2696 /* Activate general request port */
2698 general_port = unit->request_ports[GENERAL_QUEUE];
2699 general_port->mp_SigTask = task;
2700 general_port->mp_SigBit = AllocSignal(-1);
2701 general_port_signal = 1 << general_port->mp_SigBit;
2702 general_port->mp_Flags = PA_SIGNAL;
2704 /* Allocate signals for notification of card removal and insertion */
2706 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
2707 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
2708 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
2709 | card_inserted_signal | SIGBREAKF_CTRL_C;
2711 /* Tell ourselves to check port for old messages */
2713 Signal(task, general_port_signal);
2715 /* Infinite loop to service requests and signals */
2717 while(TRUE)
2719 signals = Wait(wait_signals);
2721 if((signals & card_inserted_signal) != 0)
2723 if(unit->insertion_function(unit->card, base))
2725 unit->flags |= UNITF_HAVEADAPTER;
2726 if((unit->flags & UNITF_CONFIGURED) != 0)
2727 ConfigureAdapter(unit, base);
2728 if((unit->flags & UNITF_WASONLINE) != 0)
2730 GoOnline(unit, base);
2731 unit->flags &= ~UNITF_WASONLINE;
2736 if((signals & card_removed_signal) != 0)
2738 unit->removal_function(unit->card, base);
2739 if((unit->flags & UNITF_WASONLINE) != 0)
2740 GoOffline(unit, base);
2743 if((signals & general_port_signal) != 0)
2745 while((request = (APTR)GetMsg(general_port)) != NULL)
2747 /* Service the request as soon as the unit is free */
2749 ObtainSemaphore(&unit->access_lock);
2750 ServiceRequest((APTR)request, base);