Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / realtek8180 / unit.c
blob60e6ad21cb31b840aaefd63fb139edc7573c7dc9
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 struct TagItem *io_tags = (struct TagItem *)io_tags;
140 BOOL success = TRUE;
141 struct DevUnit *unit;
142 struct Task *task;
143 struct MsgPort *port;
144 UWORD i;
145 APTR stack;
147 unit = AllocMem(sizeof(struct DevUnit), MEMF_CLEAR | MEMF_PUBLIC);
148 if(unit == NULL)
149 success = FALSE;
151 if(success)
153 /* Initialise lists etc. */
155 NewList((APTR)&unit->openers);
156 NewList((APTR)&unit->type_trackers);
157 NewList((APTR)&unit->multicast_ranges);
159 unit->index = index;
160 unit->device = base;
161 unit->card = card;
162 unit->bus = bus;
163 unit->generation = RTL8187B1_GEN;
164 unit->tx_rate = 11;
165 unit->tx_rate_code = 3; /* 11 Mbps */
166 unit->mgmt_rate = 1;
167 unit->mgmt_rate_code = 0; /* 1 Mbps */
168 unit->channel = 1;
170 /* Store I/O hooks */
172 unit->ByteOut =
173 (APTR)GetTagData(IOTAG_ByteOut, (UPINT)NULL, io_tags);
174 unit->ByteIn =
175 (APTR)GetTagData(IOTAG_ByteIn, (UPINT)NULL, io_tags);
176 unit->LEWordIn =
177 (APTR)GetTagData(IOTAG_LEWordIn, (UPINT)NULL, io_tags);
178 unit->LELongIn =
179 (APTR)GetTagData(IOTAG_LELongIn, (UPINT)NULL, io_tags);
180 unit->LEWordOut =
181 (APTR)GetTagData(IOTAG_LEWordOut, (UPINT)NULL, io_tags);
182 unit->LELongOut =
183 (APTR)GetTagData(IOTAG_LELongOut, (UPINT)NULL, io_tags);
184 unit->AllocDMAMem =
185 (APTR)GetTagData(IOTAG_AllocDMAMem, (UPINT)NULL, io_tags);
186 unit->FreeDMAMem =
187 (APTR)GetTagData(IOTAG_FreeDMAMem, (UPINT)NULL, io_tags);
188 unit->SendFrame =
189 (APTR)GetTagData(IOTAG_SendFrame, (UPINT)NULL, io_tags);
190 unit->ReceiveFrame =
191 (APTR)GetTagData(IOTAG_ReceiveFrame, (UPINT)NULL, io_tags);
192 if(unit->ByteIn == NULL
193 || unit->ByteOut == NULL
194 || unit->LEWordIn == NULL
195 || unit->LELongIn == NULL
196 || unit->LEWordOut == NULL
197 || unit->LELongOut == NULL
198 || unit->AllocDMAMem == NULL
199 || unit->FreeDMAMem == NULL
200 || unit->SendFrame == NULL
201 || unit->ReceiveFrame == NULL)
202 success = FALSE;
205 if(success)
207 InitSemaphore(&unit->access_lock);
209 /* Create the message ports for queuing requests */
211 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
213 unit->request_ports[i] = port = AllocMem(sizeof(struct MsgPort),
214 MEMF_PUBLIC | MEMF_CLEAR);
215 if(port == NULL)
216 success = FALSE;
218 if(success)
220 NewList(&port->mp_MsgList);
221 port->mp_Flags = PA_IGNORE;
225 if(success)
227 unit->request_ports[WRITE_QUEUE]->mp_SigTask = &unit->tx_int;
228 unit->request_ports[MGMT_QUEUE]->mp_SigTask = &unit->mgmt_int;
231 /* Allocate buffers and descriptors */
233 unit->tx_buffer = AllocVec(ETH_MAXPACKETSIZE, MEMF_PUBLIC);
234 for(i = 0; i < TX_SLOT_COUNT; i++)
236 unit->tx_descs[i] = unit->AllocDMAMem(unit->card,
237 R8180_MAXDESCSIZE + FRAME_BUFFER_SIZE, 4);
238 if(unit->tx_descs[i] != NULL)
239 unit->tx_buffers[i] = unit->tx_descs[i] + R8180_MAXDESCSIZE;
240 else
241 success = FALSE;
243 unit->rx_buffer = AllocVec(FRAME_BUFFER_SIZE, MEMF_PUBLIC);
244 for(i = 0; i < RX_SLOT_COUNT; i++)
246 if(unit->bus != USB_BUS)
248 unit->rx_descs[i] = unit->AllocDMAMem(unit->card,
249 R8180_MAXDESCSIZE, 4);
250 if(unit->rx_descs[i] == NULL)
251 success = FALSE;
253 unit->rx_buffers[i] = unit->AllocDMAMem(unit->card,
254 FRAME_BUFFER_SIZE + R8180_MAXDESCSIZE, 4);
255 if(unit->rx_buffers[i] == NULL)
256 success = FALSE;
258 unit->rx_frames =
259 AllocVec(FRAME_BUFFER_SIZE * FRAME_BUFFER_COUNT, MEMF_PUBLIC);
260 for(i = 0; i < FRAME_BUFFER_COUNT; i++)
261 unit->rx_fragment_nos[i] = -1;
262 unit->tx_requests = AllocVec(sizeof(APTR) * TX_SLOT_COUNT,
263 MEMF_PUBLIC);
264 if(unit->tx_buffer == NULL
265 || unit->rx_buffer == NULL
266 || unit->rx_frames == NULL
267 || unit->tx_requests == NULL)
268 success = FALSE;
271 if(success)
273 /* Initialise network adapter hardware */
275 success = InitialiseAdapter(unit, FALSE, base);
276 unit->flags |= UNITF_HAVEADAPTER;
279 if(success)
281 /* Record maximum speed in BPS */
283 unit->speed = 54000000;
285 /* Initialise interrupts */
287 unit->rx_int.is_Node.ln_Name =
288 base->device.dd_Library.lib_Node.ln_Name;
289 unit->rx_int.is_Code = (APTR)RXInt;
290 unit->rx_int.is_Data = unit;
292 unit->tx_int.is_Node.ln_Name =
293 base->device.dd_Library.lib_Node.ln_Name;
294 unit->tx_int.is_Code = (APTR)TXInt;
295 unit->tx_int.is_Data = unit;
297 unit->mgmt_int.is_Node.ln_Name =
298 base->device.dd_Library.lib_Node.ln_Name;
299 unit->mgmt_int.is_Code = (APTR)MgmtTXInt;
300 unit->mgmt_int.is_Data = unit;
302 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
303 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
305 /* Create a new task */
307 unit->task = task =
308 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
309 if(task == NULL)
310 success = FALSE;
313 if(success)
315 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
316 if(stack == NULL)
317 success = FALSE;
320 if(success)
322 /* Initialise and start task */
324 task->tc_Node.ln_Type = NT_TASK;
325 task->tc_Node.ln_Pri = TASK_PRIORITY;
326 task->tc_Node.ln_Name = base->device.dd_Library.lib_Node.ln_Name;
327 task->tc_SPUpper = stack + STACK_SIZE;
328 task->tc_SPLower = stack;
329 task->tc_SPReg = stack + STACK_SIZE;
330 NewList(&task->tc_MemEntry);
332 if(AddTask(task, UnitTask, NULL) == NULL)
333 success = FALSE;
336 if(success)
338 /* Send the unit to the new task */
340 task->tc_UserData = unit;
342 /* Set default wireless options */
344 unit->mode = S2PORT_MANAGED;
347 if(!success)
349 DeleteUnit(unit, base);
350 unit = NULL;
353 return unit;
358 /****i* realtek8180.device/DeleteUnit **************************************
360 * NAME
361 * DeleteUnit -- Delete a unit.
363 * SYNOPSIS
364 * DeleteUnit(unit)
366 * VOID DeleteUnit(struct DevUnit *);
368 * FUNCTION
369 * Deletes a unit.
371 * INPUTS
372 * unit - Device unit (may be NULL).
374 * RESULT
375 * None.
377 ****************************************************************************
381 VOID DeleteUnit(struct DevUnit *unit, struct DevBase *base)
383 UBYTE i;
384 struct Task *task;
386 if(unit != NULL)
388 task = unit->task;
389 if(task != NULL)
391 if(task->tc_UserData != NULL)
393 RemTask(task);
394 FreeMem(task->tc_SPLower, STACK_SIZE);
396 FreeMem(task, sizeof(struct Task));
399 for(i = 0; i < REQUEST_QUEUE_COUNT; i++)
401 if(unit->request_ports[i] != NULL)
402 FreeMem(unit->request_ports[i], sizeof(struct MsgPort));
405 if((unit->flags & UNITF_ONLINE) != 0) /* Needed! */
406 GoOffline(unit, base);
408 if((unit->flags & UNITF_HAVEADAPTER) != 0)
409 DeinitialiseAdapter(unit, base);
411 for(i = 0; i < TX_SLOT_COUNT; i++)
412 unit->FreeDMAMem(unit->card, unit->tx_descs[i]);
413 for(i = 0; i < RX_SLOT_COUNT; i++)
415 unit->FreeDMAMem(unit->card, unit->rx_buffers[i]);
416 if(unit->bus != USB_BUS)
417 unit->FreeDMAMem(unit->card, unit->rx_descs[i]);
420 FreeVec(unit->tx_buffer);
421 FreeVec(unit->rx_frames);
422 FreeVec(unit->tx_requests);
423 FreeVec(unit->rx_buffer);
425 FreeMem(unit, sizeof(struct DevUnit));
428 return;
433 /****i* realtek8180.device/InitialiseAdapter *******************************
435 * NAME
436 * InitialiseAdapter
438 * SYNOPSIS
439 * success = InitialiseAdapter(unit, reinsertion)
441 * BOOL InitialiseAdapter(struct DevUnit *, BOOL);
443 * FUNCTION
445 * INPUTS
446 * unit
447 * reinsertion
449 * RESULT
450 * success - Success indicator.
452 ****************************************************************************
456 BOOL InitialiseAdapter(struct DevUnit *unit, BOOL reinsertion,
457 struct DevBase *base)
459 BOOL success = FALSE;
460 UBYTE reg_62, revision;
461 UWORD *p, i;
462 ULONG rx_conf;
464 /* Initialise EEPROM */
466 rx_conf = unit->LELongIn(unit->card, 0x100 + R8180REG_RXCONF);
467 unit->eeprom_addr_size = ((rx_conf & (1 << 6)) != 0) ? 8 : 6;
469 BusyMicroDelay(10, base);
470 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
472 /* Get default MAC address */
474 p = (UWORD *)unit->default_address;
475 for(i = 0; i < ETH_ADDRESSSIZE / sizeof(UWORD); i++)
476 *p++ = LEWord(ReadEEPROM(unit, R8180ROM_ADDRESS0 + i, base));
478 /* Refine main chip revision */
480 if(unit->generation == RTL8187B1_GEN)
482 revision = unit->ByteIn(unit->card, 0x100 + 0xe1);
483 if(revision == 1 || revision == 2)
484 unit->generation = RTL8187B2_GEN;
486 else
488 if((unit->LELongIn(unit->card, 0x100 + R8180REG_TXCONF)
489 & R8180REG_TXCONFF_HWVER) == 6 << R8180REG_TXCONFB_HWVER)
490 unit->generation = RTL8187B0_GEN;
493 /* Set up power tables */
495 GetPower(unit, base);
497 /* Tune the radio */
499 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
500 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
501 | R8180REG_CONFIG3F_ANAPARAMWRITE | R8180REG_CONFIG3F_GNTSELECT);
502 unit->LELongOut(unit->card, 0x100 + R8180REG_ANAPARAM2, 0x727f3f52);
503 unit->LELongOut(unit->card, 0x100 + R8180REG_ANAPARAM1, 0x45090658);
504 unit->ByteOut(unit->card, 0x100 + R8180REG_ANAPARAM3, 0);
506 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
507 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
508 & ~R8180REG_CONFIG3F_ANAPARAMWRITE);
510 /* Reset PLL sequence */
512 unit->ByteOut(unit->card, 0x161, 0x10);
513 reg_62 = unit->ByteIn(unit->card, 0x162);
514 unit->ByteOut(unit->card, 0x162, reg_62 & ~(1 << 5));
515 unit->ByteOut(unit->card, 0x162, reg_62 | (1 << 5));
517 /* Send reset command */
519 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
520 unit->ByteIn(unit->card, 0x100 + R8180REG_COMMAND)
521 & 0x2 | R8180REG_COMMANDF_RESET);
523 for(i = 0; i < 10 && !success; i++)
525 BusyMilliDelay(2, base);
526 if((unit->ByteIn(unit->card, 0x100 + R8180REG_COMMAND)
527 & R8180REG_COMMANDF_RESET) == 0)
528 success = TRUE;
531 if(success && unit->generation == RTL8187L_GEN)
533 /* Reload registers from EEPROM */
535 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_LOAD);
537 for(i = 0, success = FALSE; i < 10 && !success; i++)
539 BusyMilliDelay(4, base);
540 if((unit->ByteIn(unit->card, 0x100 + R8180REG_EEPROM)
541 & R8180REG_EEPROMF_COMMAND) == 0)
542 success = TRUE;
546 if(success)
548 /* Set up rates */
550 if(unit->generation == RTL8187L_GEN)
551 unit->LEWordOut(unit->card, 0x12d, 0xfff);
552 else
553 unit->LEWordOut(unit->card, 0x134, 0xfff);
554 unit->LEWordOut(unit->card, 0x12c, 0x1ff);
555 unit->ByteOut(unit->card, 0x100 + R8180REG_CWCONF,
556 unit->ByteIn(unit->card, 0x100 + R8180REG_CWCONF)
557 | R8180REG_CWCONFF_PPRETRYSHIFT);
558 unit->ByteOut(unit->card, 0x100 + R8180REG_TXAGCCTL,
559 unit->ByteIn(unit->card, 0x100 + R8180REG_TXAGCCTL)
560 | R8180REG_TXAGCCTLF_PPGAINSHIFT);
562 unit->LEWordOut(unit->card, 0x1e0 | 1 << 16, 0xfff);
563 unit->ByteOut(unit->card, 0x100 + R8180REG_RATEFALLBACK,
564 unit->ByteIn(unit->card, 0x100 + R8180REG_RATEFALLBACK)
565 | R8180REG_RATEFALLBACKF_ENABLE);
567 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR,
568 unit->ByteIn(unit->card, 0x100 + R8180REG_MSR) & 0xf3);
569 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR,
570 unit->ByteIn(unit->card, 0x100 + R8180REG_MSR)
571 | R8180REG_MSRF_ENEDCA);
572 unit->ByteOut(unit->card, 0x100 + R8180REG_ACMCONTROL, 0);
574 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMWINDOW, 2);
575 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL, 100);
576 unit->LEWordOut(unit->card, 0x1d4 | 1 << 16, 0xffff);
578 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
579 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG1,
580 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG1) & 0x3f | 0x80);
581 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, 0);
583 unit->ByteOut(unit->card, 0x100 + R8180REG_WPACONF, 0);
585 unit->ByteOut(unit->card, 0x1f0, 0x32);
586 unit->ByteOut(unit->card, 0x1f1, 0x32);
587 unit->ByteOut(unit->card, 0x1f2, 0x0);
588 unit->ByteOut(unit->card, 0x1f3, 0x0);
589 unit->ByteOut(unit->card, 0x1f4, 0x32);
590 unit->ByteOut(unit->card, 0x1f5, 0x43);
591 unit->ByteOut(unit->card, 0x1f6, 0x0);
592 unit->ByteOut(unit->card, 0x1f7, 0x0);
593 unit->ByteOut(unit->card, 0x1f8, 0x46);
594 unit->ByteOut(unit->card, 0x1f9, 0xa4);
595 unit->ByteOut(unit->card, 0x1fa, 0x0);
596 unit->ByteOut(unit->card, 0x1fb, 0x0);
597 unit->ByteOut(unit->card, 0x1fc, 0x96);
598 unit->ByteOut(unit->card, 0x1fd, 0xa4);
599 unit->ByteOut(unit->card, 0x1fe, 0x0);
600 unit->ByteOut(unit->card, 0x1ff, 0x0);
602 unit->ByteOut(unit->card, 0x158 | 1 << 16, 0x4b);
603 unit->ByteOut(unit->card, 0x159 | 1 << 16, 0x0);
604 unit->ByteOut(unit->card, 0x15a | 1 << 16, 0x4b);
605 unit->ByteOut(unit->card, 0x15b | 1 << 16, 0x0);
606 unit->ByteOut(unit->card, 0x160 | 1 << 16, 0x4b);
607 unit->ByteOut(unit->card, 0x161 | 1 << 16, 0x9);
608 unit->ByteOut(unit->card, 0x162 | 1 << 16, 0x4b);
609 unit->ByteOut(unit->card, 0x163 | 1 << 16, 0x9);
610 unit->ByteOut(unit->card, 0x1ce | 1 << 16, 0xf);
611 unit->ByteOut(unit->card, 0x1cf | 1 << 16, 0x0);
612 unit->ByteOut(unit->card, 0x1e0 | 1 << 16, 0xff);
613 unit->ByteOut(unit->card, 0x1e1 | 1 << 16, 0xf);
614 unit->ByteOut(unit->card, 0x1e2 | 1 << 16, 0x0);
615 unit->ByteOut(unit->card, 0x1f0 | 1 << 16, 0x4e);
616 unit->ByteOut(unit->card, 0x1f1 | 1 << 16, 0x1);
617 unit->ByteOut(unit->card, 0x1f2 | 1 << 16, 0x2);
618 unit->ByteOut(unit->card, 0x1f3 | 1 << 16, 0x3);
619 unit->ByteOut(unit->card, 0x1f4 | 1 << 16, 0x4);
620 unit->ByteOut(unit->card, 0x1f5 | 1 << 16, 0x5);
621 unit->ByteOut(unit->card, 0x1f6 | 1 << 16, 0x6);
622 unit->ByteOut(unit->card, 0x1f7 | 1 << 16, 0x7);
623 unit->ByteOut(unit->card, 0x1f8 | 1 << 16, 0x8);
625 unit->ByteOut(unit->card, 0x14e | 2 << 16, 0x0);
626 unit->ByteOut(unit->card, 0x10c | 2 << 16, 0x4);
627 unit->ByteOut(unit->card, 0x121 | 2 << 16, 0x61);
628 unit->ByteOut(unit->card, 0x122 | 2 << 16, 0x68);
629 unit->ByteOut(unit->card, 0x123 | 2 << 16, 0x6f);
630 unit->ByteOut(unit->card, 0x124 | 2 << 16, 0x76);
631 unit->ByteOut(unit->card, 0x125 | 2 << 16, 0x7d);
632 unit->ByteOut(unit->card, 0x126 | 2 << 16, 0x84);
633 unit->ByteOut(unit->card, 0x127 | 2 << 16, 0x8d);
634 unit->ByteOut(unit->card, 0x14d | 2 << 16, 0x8);
635 unit->ByteOut(unit->card, 0x150 | 2 << 16, 0x5);
636 unit->ByteOut(unit->card, 0x151 | 2 << 16, 0xf5);
637 unit->ByteOut(unit->card, 0x152 | 2 << 16, 0x4);
638 unit->ByteOut(unit->card, 0x153 | 2 << 16, 0xa0);
639 unit->ByteOut(unit->card, 0x154 | 2 << 16, 0x1f);
640 unit->ByteOut(unit->card, 0x155 | 2 << 16, 0x23);
641 unit->ByteOut(unit->card, 0x156 | 2 << 16, 0x45);
642 unit->ByteOut(unit->card, 0x157 | 2 << 16, 0x67);
643 unit->ByteOut(unit->card, 0x158 | 2 << 16, 0x8);
644 unit->ByteOut(unit->card, 0x159 | 2 << 16, 0x8);
645 unit->ByteOut(unit->card, 0x15a | 2 << 16, 0x8);
646 unit->ByteOut(unit->card, 0x15b | 2 << 16, 0x8);
647 unit->ByteOut(unit->card, 0x160 | 2 << 16, 0x8);
648 unit->ByteOut(unit->card, 0x161 | 2 << 16, 0x8);
649 unit->ByteOut(unit->card, 0x162 | 2 << 16, 0x8);
650 unit->ByteOut(unit->card, 0x163 | 2 << 16, 0x8);
651 unit->ByteOut(unit->card, 0x164 | 2 << 16, 0xcf);
652 unit->ByteOut(unit->card, 0x172 | 2 << 16, 0x56);
653 unit->ByteOut(unit->card, 0x173 | 2 << 16, 0x9a);
655 unit->ByteOut(unit->card, 0x134, 0xf0);
656 unit->ByteOut(unit->card, 0x135, 0xf);
657 unit->ByteOut(unit->card, 0x15b, 0x40);
658 unit->ByteOut(unit->card, 0x184, 0x88);
659 unit->ByteOut(unit->card, 0x185, 0x24);
660 unit->ByteOut(unit->card, 0x188, 0x54);
661 unit->ByteOut(unit->card, 0x18b, 0xb8);
662 unit->ByteOut(unit->card, 0x18c, 0x7);
663 unit->ByteOut(unit->card, 0x18d, 0x0);
664 unit->ByteOut(unit->card, 0x194, 0x1b);
665 unit->ByteOut(unit->card, 0x195, 0x12);
666 unit->ByteOut(unit->card, 0x196, 0x0);
667 unit->ByteOut(unit->card, 0x197, 0x6);
668 unit->ByteOut(unit->card, 0x19d, 0x1a);
669 unit->ByteOut(unit->card, 0x19f, 0x10);
670 unit->ByteOut(unit->card, 0x1b4, 0x22);
671 unit->ByteOut(unit->card, 0x1be, 0x80);
672 unit->ByteOut(unit->card, 0x1db, 0x0);
673 unit->ByteOut(unit->card, 0x1ee, 0x0);
674 unit->ByteOut(unit->card, 0x191, 0x3);
675 unit->ByteOut(unit->card, 0x14c | 2 << 16, 0x0);
677 unit->ByteOut(unit->card, 0x19f | 3 << 16, 0x0);
678 unit->ByteOut(unit->card, 0x18c, 0x1);
679 unit->ByteOut(unit->card, 0x18d, 0x10);
680 unit->ByteOut(unit->card, 0x18e, 0x8);
681 unit->ByteOut(unit->card, 0x18f, 0x0);
683 unit->LEWordOut(unit->card, 0x100 + R8180REG_TIDACMAP, 0xfa50);
684 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMIG, 0);
686 unit->LELongOut(unit->card, 0x1f0 | 1 << 16, 0);
687 unit->LELongOut(unit->card, 0x1f4 | 1 << 16, 0);
688 unit->ByteOut(unit->card, 0x1f8 | 1 << 16, 0);
690 unit->LELongOut(unit->card, 0x100 + R8180REG_RFTIMING, 0x4001);
692 unit->LEWordOut(unit->card, 0x172 | 2 << 16, 0x569a);
694 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, R8180ECMD_CONFIG);
696 unit->ByteOut(unit->card, 0x100 + R8180REG_CONFIG3,
697 unit->ByteIn(unit->card, 0x100 + R8180REG_CONFIG3)
698 | R8180REG_CONFIG3F_ANAPARAMWRITE);
699 unit->ByteOut(unit->card, 0x100 + R8180REG_EEPROM, 0);
701 /* Turn LED on */
703 unit->ByteOut(unit->card, 0x100 + R8180REG_GPIO0, 1);
704 unit->ByteOut(unit->card, 0x100 + R8180REG_GPENABLE, 0);
706 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSOUTPUT, 0x480);
707 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSSELECT, 0x2488);
708 unit->LEWordOut(unit->card, 0x100 + R8180REG_RFPINSENABLE, 0x1fff);
709 BusyMilliDelay(100, base);
711 /* Initialise radio */
713 success = InitialiseRadio(unit, base);
715 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
716 R8180REG_COMMANDF_TXENABLE | R8180REG_COMMANDF_RXENABLE);
717 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMASK, INT_MASK);
719 unit->ByteOut(unit->card, 0x41, 0xf4);
720 unit->ByteOut(unit->card, 0x40, 0);
721 unit->ByteOut(unit->card, 0x42, 0);
722 unit->ByteOut(unit->card, 0x42, 1);
723 unit->ByteOut(unit->card, 0x40, 0xf);
724 unit->ByteOut(unit->card, 0x42, 0);
725 unit->ByteOut(unit->card, 0x42, 1);
727 unit->ByteOut(unit->card, 0x1db,
728 unit->ByteIn(unit->card, 0x1db) | 1 << 2);
729 unit->LEWordOut(unit->card, 0x172 | 3 << 16, 0x59fa);
730 unit->LEWordOut(unit->card, 0x174 | 3 << 16, 0x59d2);
731 unit->LEWordOut(unit->card, 0x176 | 3 << 16, 0x59d2);
732 unit->LEWordOut(unit->card, 0x178 | 3 << 16, 0x19fa);
733 unit->LEWordOut(unit->card, 0x17a | 3 << 16, 0x19fa);
734 unit->LEWordOut(unit->card, 0x17c | 3 << 16, 0xd0);
735 unit->ByteOut(unit->card, 0x161, 0);
736 unit->ByteOut(unit->card, 0x180 | 1 << 16, 0xf);
737 unit->ByteOut(unit->card, 0x183 | 1 << 16, 3);
738 unit->ByteOut(unit->card, 0x1da, 0x10);
739 unit->ByteOut(unit->card, 0x14d | 2 << 16, 8);
741 unit->LELongOut(unit->card, 0x100 + R8180REG_HSSIPARA, 0x600321b);
743 /* Set maximum RX frame size */
745 unit->LEWordOut(unit->card, 0x1ec | 1 << 16, 0x800);
747 unit->ByteOut(unit->card, 0x100 + R8180REG_ACMCONTROL, 0);
748 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR, R8180REG_MSRF_ENEDCA);
751 if(success)
753 unit->LELongOut(unit->card, 0x100 + R8180REG_RXCONF,
754 R8180REG_RXCONFF_EARLYTHRESH
755 | R8180REG_RXCONFF_AUTORESETPHY
756 | R8180REG_RXCONFF_CHECKBSSID
757 | R8180REG_RXCONFF_MGMT
758 | R8180REG_RXCONFF_DATA
759 | 7 << R8180REG_RXCONFB_FIFOTHRESH
760 | 7 << R8180REG_RXCONFB_MAXDMA
761 | R8180REG_RXCONFF_BCAST
762 | R8180REG_RXCONFF_MCAST
763 | R8180REG_RXCONFF_UCAST);
764 unit->ByteOut(unit->card, 0x100 + R8180REG_TXAGCCTL,
765 unit->ByteIn(unit->card, 0x100 + R8180REG_TXAGCCTL)
766 & ~(R8180REG_TXAGCCTLF_PPGAINSHIFT
767 | R8180REG_TXAGCCTLF_PPANTSELSHIFT
768 | R8180REG_TXAGCCTLF_FEEDBACKANT));
769 unit->LELongOut(unit->card, 0x100 + R8180REG_TXCONF,
770 R8180REG_TXCONFF_DISREQQSIZE
771 | 7 << R8180REG_TXCONFB_MAXDMA
772 | TX_TRIES << R8180REG_TXCONFB_SHORTTRIES
773 | TX_TRIES << R8180REG_TXCONFB_LONGTRIES);
776 /* Determine features, and get offsets of certain fields within frame
777 descriptors */
779 unit->retries_offset = R8180FRM_RETRY;
780 unit->tx_desc_size = 32;
781 unit->rx_desc_size = 20;
783 /* Set IV sizes */
785 unit->iv_sizes[S2ENC_WEP] = IV_SIZE;
786 unit->iv_sizes[S2ENC_TKIP] = EIV_SIZE;
787 unit->iv_sizes[S2ENC_CCMP] = EIV_SIZE;
789 /* Set encryption functions */
791 unit->fragment_encrypt_functions[S2ENC_NONE] = WriteClearFragment;
793 if((unit->flags & UNITF_HARDWEP) != 0)
794 unit->fragment_encrypt_functions[S2ENC_WEP] = WriteWEPFragment;
795 else
796 unit->fragment_encrypt_functions[S2ENC_WEP] = EncryptWEPFragment;
798 if((unit->flags & UNITF_HARDTKIP) != 0)
799 unit->fragment_encrypt_functions[S2ENC_TKIP] = WriteTKIPFragment;
800 else
801 unit->fragment_encrypt_functions[S2ENC_TKIP] = EncryptTKIPFragment;
803 if((unit->flags & UNITF_HARDCCMP) != 0)
804 unit->fragment_encrypt_functions[S2ENC_CCMP] = WriteCCMPFragment;
805 else
806 unit->fragment_encrypt_functions[S2ENC_CCMP] = EncryptCCMPFragment;
808 /* Set decryption functions */
810 unit->fragment_decrypt_functions[S2ENC_NONE] = ReadClearFragment;
812 if((unit->flags & UNITF_HARDWEP) != 0)
813 unit->fragment_decrypt_functions[S2ENC_WEP] = ReadWEPFragment;
814 else
815 unit->fragment_decrypt_functions[S2ENC_WEP] = DecryptWEPFragment;
817 if((unit->flags & UNITF_HARDTKIP) != 0)
818 unit->fragment_decrypt_functions[S2ENC_TKIP] = ReadTKIPFragment;
819 else
820 unit->fragment_decrypt_functions[S2ENC_TKIP] = DecryptTKIPFragment;
822 if((unit->flags & UNITF_HARDCCMP) != 0)
823 unit->fragment_decrypt_functions[S2ENC_CCMP] = ReadCCMPFragment;
824 else
825 unit->fragment_decrypt_functions[S2ENC_CCMP] = DecryptCCMPFragment;
827 /* Return */
829 return success;
834 /****i* realtek8180.device/DeinitialiseAdapter *****************************
836 * NAME
837 * DeinitialiseAdapter
839 * SYNOPSIS
840 * DeinitialiseAdapter(unit)
842 * VOID DeinitialiseAdapter(struct DevUnit *);
844 * FUNCTION
846 * INPUTS
847 * unit
849 * RESULT
850 * None.
852 ****************************************************************************
856 VOID DeinitialiseAdapter(struct DevUnit *unit, struct DevBase *base)
858 /* Turn LED off */
860 unit->ByteOut(unit->card, 0x100 + R8180REG_GPIO0, 1);
861 unit->ByteOut(unit->card, 0x100 + R8180REG_GPENABLE, 1);
863 return;
868 /****i* realtek8180.device/ConfigureAdapter ********************************
870 * NAME
871 * ConfigureAdapter -- Set up card for transmission/reception.
873 * SYNOPSIS
874 * ConfigureAdapter(unit)
876 * VOID ConfigureAdapter(struct DevUnit *);
878 ****************************************************************************
882 VOID ConfigureAdapter(struct DevUnit *unit, struct DevBase *base)
884 UBYTE msr;
885 UWORD i;
887 /* Set BSSID */
889 for(i = 0; i < ETH_ADDRESSSIZE; i++)
890 unit->ByteOut(unit->card, 0x100 + R8180REG_BSSID + i, unit->bssid[i]);
892 /* Set channel and power */
894 SetPower(unit, base);
896 msr = unit->ByteIn(unit->card, 0x100 + R8180REG_MSR)
897 & ~R8180REG_MSRF_LINK;
898 if(unit->assoc_id != 0)
900 msr |= 2 << R8180REG_MSRB_LINK;
901 if(unit->generation >= RTL8187B0_GEN)
902 msr |= R8180REG_MSRF_ENEDCA;
904 unit->ByteOut(unit->card, 0x100 + R8180REG_MSR, msr);
906 /* Set intervals */
908 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMWINDOW, 2);
909 unit->LEWordOut(unit->card, 0x100 + R8180REG_ATIMTRINTERVAL, 100);
910 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL, 100);
911 unit->LEWordOut(unit->card, 0x100 + R8180REG_BEACONINTERVAL2, 100);
913 if(unit->generation >= RTL8187B0_GEN)
915 unit->ByteOut(unit->card, 0x100 + R8180REG_SIFS, 0x22);
916 if(unit->band == S2BAND_G)
917 unit->ByteOut(unit->card, 0x100 + R8180REG_SLOT, 0x9);
918 else
919 unit->ByteOut(unit->card, 0x100 + R8180REG_SLOT, 0x14);
920 unit->ByteOut(unit->card, 0x100 + R8180REG_EIFS, 0x5b);
921 unit->ByteOut(unit->card, 0x100 + R8180REG_SENSECOUNT, 0x5b);
924 /* Return */
926 return;
931 /****i* realtek8180.device/GoOnline ****************************************
933 * NAME
934 * GoOnline -- Enable transmission/reception.
936 * SYNOPSIS
937 * GoOnline(unit)
939 * VOID GoOnline(struct DevUnit *);
941 ****************************************************************************
945 VOID GoOnline(struct DevUnit *unit, struct DevBase *base)
947 /* Enable interrupts */
949 unit->flags |= UNITF_ONLINE;
950 unit->LEWordOut(unit->card, 0x100 + R8180REG_INTMASK, INT_MASK);
952 /* Enable frame transmission and reception */
954 unit->ByteOut(unit->card, 0x100 + R8180REG_COMMAND,
955 R8180REG_COMMANDF_TXENABLE | R8180REG_COMMANDF_RXENABLE);
957 /* Record start time and report Online event */
959 GetSysTime(&unit->stats.LastStart);
960 ReportEvents(unit, S2EVENT_ONLINE, base);
962 return;
967 /****i* realtek8180.device/GoOffline ***************************************
969 * NAME
970 * GoOffline -- Disable transmission/reception.
972 * SYNOPSIS
973 * GoOffline(unit)
975 * VOID GoOffline(struct DevUnit *);
977 * FUNCTION
979 * INPUTS
980 * unit
982 * RESULT
983 * None.
985 ****************************************************************************
989 VOID GoOffline(struct DevUnit *unit, struct DevBase *base)
991 unit->flags &= ~UNITF_ONLINE;
993 /* Flush pending read and write requests */
995 FlushUnit(unit, MGMT_QUEUE, S2ERR_OUTOFSERVICE, base);
997 /* Report Offline event and return */
999 ReportEvents(unit, S2EVENT_OFFLINE, base);
1000 return;
1005 /****i* realtek8180.device/SetOptions **************************************
1007 * NAME
1008 * SetOptions -- Set and use interface options.
1010 * SYNOPSIS
1011 * reconfigure = SetOptions(unit, tag_list)
1013 * BOOL SetOptions(struct DevUnit *, struct TagItem *);
1015 ****************************************************************************
1019 BOOL SetOptions(struct DevUnit *unit, const struct TagItem *tag_list,
1020 struct DevBase *base)
1022 struct TagItem *tag_item, *tlist = (struct TagItem *)tag_list;
1023 BOOL reconfigure = TRUE;
1025 while((tag_item = NextTagItem(&tlist)) != NULL)
1027 switch(tag_item->ti_Tag)
1029 case S2INFO_SSID:
1030 ReportEvents(unit, S2EVENT_CONNECT, base);
1031 break;
1033 case S2INFO_BSSID:
1034 CopyMem((APTR)tag_item->ti_Data, unit->bssid, ETH_ADDRESSSIZE);
1035 break;
1037 case S2INFO_AssocID:
1038 unit->assoc_id = tag_item->ti_Data;
1039 break;
1041 case S2INFO_Capabilities:
1042 unit->capabilities = tag_item->ti_Data;
1043 if((unit->capabilities & (1 << 5)) != 0)
1044 unit->flags |= UNITF_SHORTPREAMBLE;
1045 else
1046 unit->flags &= ~UNITF_SHORTPREAMBLE;
1047 break;
1049 case S2INFO_DefaultKeyNo:
1050 unit->tx_key_no = tag_item->ti_Data;
1051 break;
1053 case S2INFO_PortType:
1054 unit->mode = tag_item->ti_Data;
1055 break;
1057 case S2INFO_Channel:
1058 if(tag_item->ti_Data != unit->channel)
1060 unit->channel = tag_item->ti_Data;
1061 reconfigure = TRUE;
1063 break;
1065 case S2INFO_Band:
1066 unit->band = tag_item->ti_Data;
1067 if(unit->band == S2BAND_G)
1069 unit->tx_rate = 54;
1070 unit->tx_rate_code = 11; /* 54 Mbps */
1071 unit->mgmt_rate = 2;
1072 unit->mgmt_rate_code = 1; /* 2 Mbps */
1074 else if(unit->band == S2BAND_B)
1076 unit->tx_rate = 11;
1077 unit->tx_rate_code = 3; /* 11 Mbps */
1078 unit->mgmt_rate = 1;
1079 unit->mgmt_rate_code = 0; /* 1 Mbps */
1081 break;
1086 return reconfigure;
1091 /****i* realtek8180.device/SetKey ******************************************
1093 * NAME
1094 * SetKey -- Set an encryption key.
1096 * SYNOPSIS
1097 * SetKey(unit, index, type, key, key_length,
1098 * rx_counter)
1100 * VOID SetKey(struct DevUnit *, ULONG, ULONG, UBYTE *, ULONG,
1101 * UBYTE *);
1103 ****************************************************************************
1107 VOID SetKey(struct DevUnit *unit, ULONG index, ULONG type, const UBYTE *key,
1108 ULONG key_length, const UBYTE *rx_counter, struct DevBase *base)
1110 struct KeyUnion *slot;
1111 struct EClockVal eclock;
1112 UWORD i;
1114 Disable();
1115 slot = &unit->keys[index];
1116 switch(type)
1118 case S2ENC_WEP:
1119 CopyMem(key, slot->u.wep.key, key_length);
1120 slot->u.wep.length = key_length;
1122 if((unit->flags & UNITF_HARDWEP) == 0)
1124 /* Create a reasonably random IV */
1126 ReadEClock(&eclock);
1127 slot->u.wep.tx_iv = FastRand(eclock.ev_lo ^ eclock.ev_hi);
1130 break;
1132 case S2ENC_TKIP:
1133 CopyMem(key, slot->u.tkip.key, 16);
1134 CopyMem(key + 16, slot->u.tkip.tx_mic_key, MIC_SIZE);
1135 CopyMem(key + 24, slot->u.tkip.rx_mic_key, MIC_SIZE);
1136 slot->u.tkip.tx_iv_low = 0;
1137 slot->u.tkip.tx_iv_high = 0;
1138 slot->u.tkip.rx_iv_low = LEWord(*(UWORD *)rx_counter);
1139 slot->u.tkip.rx_iv_high = LELong(*(ULONG *)(rx_counter + 2));
1140 slot->u.tkip.tx_ttak_set = FALSE;
1141 slot->u.tkip.rx_ttak_set = FALSE;
1143 if((unit->flags & UNITF_HARDTKIP) != 0)
1146 else
1148 /* Convert key to native endianness */
1150 for(i = 0; i < 8; i++)
1151 slot->u.tkip.key[i] = LEWord(slot->u.tkip.key[i]);
1154 break;
1156 case S2ENC_CCMP:
1157 CopyMem(key, slot->u.ccmp.key, 16);
1158 slot->u.ccmp.tx_iv_low = 0;
1159 slot->u.ccmp.tx_iv_high = 0;
1160 slot->u.ccmp.rx_iv_low = LEWord(*(UWORD *)rx_counter);
1161 slot->u.ccmp.rx_iv_high = LELong(*(ULONG *)(rx_counter + 2));
1162 slot->u.ccmp.stream_set = FALSE;
1165 /* Update type of key in selected slot */
1167 slot->type = type;
1168 Enable();
1170 return;
1175 /****i* realtek8180.device/AddMulticastRange *******************************
1177 * NAME
1178 * AddMulticastRange
1180 * SYNOPSIS
1181 * success = AddMulticastRange(unit, lower_bound, upper_bound)
1183 * BOOL AddMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1185 ****************************************************************************
1189 BOOL AddMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1190 const UBYTE *upper_bound, struct DevBase *base)
1192 struct AddressRange *range;
1193 ULONG lower_bound_left, upper_bound_left;
1194 UWORD lower_bound_right, upper_bound_right;
1196 lower_bound_left = BELong(*((ULONG *)lower_bound));
1197 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1198 upper_bound_left = BELong(*((ULONG *)upper_bound));
1199 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1201 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1202 upper_bound_left, upper_bound_right, base);
1204 if(range != NULL)
1205 range->add_count++;
1206 else
1208 range = AllocMem(sizeof(struct AddressRange), MEMF_PUBLIC);
1209 if(range != NULL)
1211 range->lower_bound_left = lower_bound_left;
1212 range->lower_bound_right = lower_bound_right;
1213 range->upper_bound_left = upper_bound_left;
1214 range->upper_bound_right = upper_bound_right;
1215 range->add_count = 1;
1217 Disable();
1218 AddTail((APTR)&unit->multicast_ranges, (APTR)range);
1219 unit->range_count++;
1220 SetMulticast(unit, base);
1221 Enable();
1225 return range != NULL;
1230 /****i* realtek8180.device/RemMulticastRange *******************************
1232 * NAME
1233 * RemMulticastRange
1235 * SYNOPSIS
1236 * found = RemMulticastRange(unit, lower_bound, upper_bound)
1238 * BOOL RemMulticastRange(struct DevUnit *, UBYTE *, UBYTE *);
1240 ****************************************************************************
1244 BOOL RemMulticastRange(struct DevUnit *unit, const UBYTE *lower_bound,
1245 const UBYTE *upper_bound, struct DevBase *base)
1247 struct AddressRange *range;
1248 ULONG lower_bound_left, upper_bound_left;
1249 UWORD lower_bound_right, upper_bound_right;
1251 lower_bound_left = BELong(*((ULONG *)lower_bound));
1252 lower_bound_right = BEWord(*((UWORD *)(lower_bound + 4)));
1253 upper_bound_left = BELong(*((ULONG *)upper_bound));
1254 upper_bound_right = BEWord(*((UWORD *)(upper_bound + 4)));
1256 range = FindMulticastRange(unit, lower_bound_left, lower_bound_right,
1257 upper_bound_left, upper_bound_right, base);
1259 if(range != NULL)
1261 if(--range->add_count == 0)
1263 Disable();
1264 Remove((APTR)range);
1265 unit->range_count--;
1266 SetMulticast(unit, base);
1267 Enable();
1268 FreeMem(range, sizeof(struct AddressRange));
1272 return range != NULL;
1277 /****i* realtek8180.device/FindMulticastRange ******************************
1279 * NAME
1280 * FindMulticastRange
1282 * SYNOPSIS
1283 * range = FindMulticastRange(unit, lower_bound_left,
1284 * lower_bound_right, upper_bound_left, upper_bound_right)
1286 * struct AddressRange *FindMulticastRange(struct DevUnit *, ULONG,
1287 * UWORD, ULONG, UWORD);
1289 ****************************************************************************
1293 static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
1294 ULONG lower_bound_left, UWORD lower_bound_right, ULONG upper_bound_left,
1295 UWORD upper_bound_right, struct DevBase *base)
1297 struct AddressRange *range, *tail;
1298 BOOL found = FALSE;
1300 range = (APTR)unit->multicast_ranges.mlh_Head;
1301 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1303 while(range != tail && !found)
1305 if(lower_bound_left == range->lower_bound_left &&
1306 lower_bound_right == range->lower_bound_right &&
1307 upper_bound_left == range->upper_bound_left &&
1308 upper_bound_right == range->upper_bound_right)
1309 found = TRUE;
1310 else
1311 range = (APTR)range->node.mln_Succ;
1314 if(!found)
1315 range = NULL;
1317 return range;
1322 /****i* realtek8180.device/SetMulticast ************************************
1324 * NAME
1325 * SetMulticast
1327 * SYNOPSIS
1328 * SetMulticast(unit)
1330 * VOID SetMulticast(struct DevUnit *);
1332 ****************************************************************************
1336 static VOID SetMulticast(struct DevUnit *unit, struct DevBase *base)
1338 return;
1343 /****i* realtek8180.device/FindTypeStats ***********************************
1345 * NAME
1346 * FindTypeStats
1348 * SYNOPSIS
1349 * stats = FindTypeStats(unit, list,
1350 * packet_type)
1352 * struct TypeStats *FindTypeStats(struct DevUnit *, struct MinList *,
1353 * ULONG);
1355 ****************************************************************************
1359 struct TypeStats *FindTypeStats(struct DevUnit *unit, struct MinList *list,
1360 ULONG packet_type, struct DevBase *base)
1362 struct TypeStats *stats, *tail;
1363 BOOL found = FALSE;
1365 stats = (APTR)list->mlh_Head;
1366 tail = (APTR)&list->mlh_Tail;
1368 while(stats != tail && !found)
1370 if(stats->packet_type == packet_type)
1371 found = TRUE;
1372 else
1373 stats = (APTR)stats->node.mln_Succ;
1376 if(!found)
1377 stats = NULL;
1379 return stats;
1384 /****i* realtek8180.device/FlushUnit ***************************************
1386 * NAME
1387 * FlushUnit
1389 * SYNOPSIS
1390 * FlushUnit(unit, last_queue, error)
1392 * VOID FlushUnit(struct DevUnit *, UBYTE, BYTE);
1394 ****************************************************************************
1398 VOID FlushUnit(struct DevUnit *unit, UBYTE last_queue, BYTE error,
1399 struct DevBase *base)
1401 struct IORequest *request;
1402 UBYTE i;
1403 struct Opener *opener, *tail;
1405 /* Abort queued requests */
1407 for(i = 0; i <= last_queue; i++)
1409 while((request = (APTR)GetMsg(unit->request_ports[i])) != NULL)
1411 request->io_Error = IOERR_ABORTED;
1412 ReplyMsg((APTR)request);
1416 #if 1
1417 opener = (APTR)unit->openers.mlh_Head;
1418 tail = (APTR)&unit->openers.mlh_Tail;
1420 /* Flush every opener's read queues */
1422 while(opener != tail)
1424 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1426 request->io_Error = error;
1427 ReplyMsg((APTR)request);
1429 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
1431 request->io_Error = error;
1432 ReplyMsg((APTR)request);
1434 opener = (APTR)opener->node.mln_Succ;
1437 #else
1438 opener = request->ios2_BufferManagement;
1439 while((request = (APTR)GetMsg(&opener->read_port)) != NULL)
1441 request->io_Error = IOERR_ABORTED;
1442 ReplyMsg((APTR)request);
1444 while((request = (APTR)GetMsg(&opener->mgmt_port)) != NULL)
1446 request->io_Error = IOERR_ABORTED;
1447 ReplyMsg((APTR)request);
1449 #endif
1451 /* Return */
1453 return;
1458 /****i* realtek8180.device/RXInt *******************************************
1460 * NAME
1461 * RXInt -- Soft interrupt for packet reception.
1463 * SYNOPSIS
1464 * RXInt(unit)
1466 * VOID RXInt(struct DevUnit *);
1468 * FUNCTION
1470 * INPUTS
1471 * unit - A unit of this device.
1473 * RESULT
1474 * None.
1476 ****************************************************************************
1480 VOID RXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
1482 UWORD ieee_length, frame_control, frame_type, slot, next_slot,
1483 frame_size, frame_subtype, encryption, key_no, buffer_no, old_length;
1484 struct DevBase *base;
1485 BOOL is_good, proceed = TRUE;
1486 LONG frag_no;
1487 ULONG status;
1488 UBYTE *rx_desc, *buffer, *p, *frame, *data, *snap_frame, *source;
1490 base = unit->device;
1491 slot = unit->rx_slot;
1492 rx_desc = unit->rx_descs[slot];
1493 next_slot = (slot + 1) % RX_SLOT_COUNT;
1495 while(proceed)
1497 is_good = TRUE;
1498 buffer = unit->rx_buffers[slot];
1500 status = LELong(*(ULONG *)(rx_desc + R8180FRM_RXSTATUS));
1501 frame_size = status & R8180FRM_RXSTATUSF_LENGTH;
1503 if((status & (R8180FRM_RXSTATUSF_DMAERR | R8180FRM_RXSTATUSF_OVERFLOW
1504 | R8180FRM_RXSTATUSF_RXERR | R8180FRM_RXSTATUSF_BADCRC)) == 0
1505 && frame_size >= WIFI_FRM_DATA + 4)
1507 /* Get fragment info */
1509 frame = buffer;
1510 ieee_length = frame_size - 4 - WIFI_FRM_DATA;
1511 data = frame + WIFI_FRM_DATA;
1512 frame_control =
1513 LEWord(*(UWORD *)(frame + WIFI_FRM_CONTROL));
1515 /* Get buffer to store fragment in */
1517 frag_no = LEWord(*(UWORD *)(frame + WIFI_FRM_SEQCONTROL));
1518 if(unit->mode == S2PORT_ADHOC)
1519 source = frame + WIFI_FRM_ADDRESS2;
1520 else
1521 source = frame + WIFI_FRM_ADDRESS3;
1522 snap_frame = GetRXBuffer(unit, source, frag_no, &buffer_no, base);
1524 /* Get location to put new data */
1526 if(snap_frame != NULL)
1528 if((frag_no & 0xf ) > 0)
1529 old_length =
1530 BEWord(*(UWORD *)(snap_frame + ETH_PACKET_IEEELEN));
1531 else
1533 /* Create new 802.3 header */
1535 CopyMem(frame + WIFI_FRM_ADDRESS1, snap_frame,
1536 ETH_ADDRESSSIZE);
1537 CopyMem(source, snap_frame + ETH_PACKET_SOURCE,
1538 ETH_ADDRESSSIZE);
1539 old_length = 0;
1541 p = snap_frame + ETH_HEADERSIZE + old_length;
1543 /* Append fragment to frame, decrypting fragment if necessary */
1545 if((frame_control & WIFI_FRM_CONTROLF_WEP) != 0)
1547 key_no = data[3] >> 6 & 0x3;
1548 encryption = unit->keys[key_no].type;
1550 else
1551 encryption = S2ENC_NONE;
1553 /* Decrypt, check and/or copy fragment */
1555 is_good = unit->fragment_decrypt_functions[encryption](unit,
1556 frame, data, &ieee_length, p, base);
1558 /* Update length in frame being built with current fragment, or
1559 increment bad frame counter if fragment is bad */
1561 if(is_good)
1563 ieee_length += old_length;
1564 *(UWORD *)(snap_frame + ETH_PACKET_IEEELEN) =
1565 MakeBEWord(ieee_length);
1567 else
1568 unit->stats.BadData++;
1570 /* If all fragments have arrived, process the complete frame */
1572 if((frame_control & WIFI_FRM_CONTROLF_MOREFRAGS) == 0)
1574 if(is_good)
1576 /* Decrypt complete frame if necessary */
1578 data = snap_frame + ETH_HEADERSIZE;
1579 if(encryption == S2ENC_TKIP
1580 && (unit->flags & UNITF_HARDTKIP) == 0)
1582 is_good = TKIPDecryptFrame(unit, snap_frame, data,
1583 ieee_length, data, key_no, base);
1584 ieee_length -= MIC_SIZE;
1585 *(UWORD *)(snap_frame + ETH_PACKET_IEEELEN) =
1586 MakeBEWord(ieee_length);
1587 if(!is_good)
1588 unit->stats.BadData++;
1592 if(is_good)
1594 /* Get frame's 802.11 type and subtype */
1596 frame_type = (frame_control & WIFI_FRM_CONTROLF_TYPE)
1597 >> WIFI_FRM_CONTROLB_TYPE;
1598 frame_subtype =
1599 (frame_control & WIFI_FRM_CONTROLF_SUBTYPE)
1600 >> WIFI_FRM_CONTROLB_SUBTYPE;
1602 /* If it's a management frame, process it separately;
1603 otherwise distribute it to clients after filtering */
1605 if(frame_type == WIFI_FRMTYPE_MGMT)
1607 if(frame_subtype != 8)
1608 DistributeMgmtFrame(unit, frame, frame_size - 4,
1609 base);
1611 else if(AddressFilter(unit, snap_frame + ETH_PACKET_DEST,
1612 base))
1614 unit->stats.PacketsReceived++;
1615 DistributeRXPacket(unit, snap_frame, base);
1620 /* Mark fragment buffer as unused for next time */
1622 unit->rx_fragment_nos[buffer_no] = -1;
1624 else
1625 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_RX, base);
1627 else
1629 is_good = FALSE;
1632 if(!is_good)
1634 ReportEvents(unit, S2EVENT_ERROR | S2EVENT_HARDWARE | S2EVENT_RX,
1635 base);
1638 /* Prepare descriptor for next time */
1640 unit->ReceiveFrame(unit->card, buffer,
1641 FRAME_BUFFER_SIZE + R8180_MAXDESCSIZE);
1643 /* Get next descriptor */
1645 slot = next_slot;
1646 if(unit->bus == USB_BUS)
1647 proceed = FALSE;
1650 unit->rx_slot = slot;
1652 return;
1657 /****i* realtek8180.device/GetRXBuffer *************************************
1659 * NAME
1660 * GetRXBuffer -- Find an appropriate RX frame buffer to use.
1662 * SYNOPSIS
1663 * buffer = GetRXBuffer(unit, address, frag_no)
1665 * UBYTE *GetRXBuffer(struct DevUnit *, UBYTE *, UWORD);
1667 ****************************************************************************
1671 static UBYTE *GetRXBuffer(struct DevUnit *unit, const UBYTE *address,
1672 UWORD frag_no, UWORD *buffer_no, struct DevBase *base)
1674 UWORD i;
1675 UBYTE *buffer;
1676 LONG n;
1677 BOOL found;
1679 buffer = unit->rx_frames;
1680 for(i = 0, found = FALSE; i < FRAME_BUFFER_COUNT * 2 && !found; i++)
1682 /* Throw away old buffer contents if we didn't find a free slot the
1683 first time around */
1685 if(i >= FRAME_BUFFER_COUNT)
1686 unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT] = -1;
1688 /* For a frame's first fragment, find an empty slot; for subsequent
1689 fragments, find a slot with matching source address */
1691 n = unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT];
1692 if(n == -1 && (frag_no & 0xf) == 0
1693 || *((ULONG *)(buffer + ETH_PACKET_SOURCE))
1694 == *((ULONG *)(address))
1695 && *((UWORD *)(buffer + ETH_PACKET_SOURCE + 4))
1696 == *((UWORD *)(address + 4)))
1698 found = TRUE;
1699 if(n == -1)
1700 unit->rx_fragment_nos[i % FRAME_BUFFER_COUNT] = frag_no;
1701 *buffer_no = i;
1703 else
1704 buffer += FRAME_BUFFER_SIZE;
1707 if(!found)
1708 buffer = NULL;
1710 return buffer;
1715 /****i* realtek8180.device/DistributeRXPacket ******************************
1717 * NAME
1718 * DistributeRXPacket -- Send a packet to all appropriate destinations.
1720 * SYNOPSIS
1721 * DistributeRXPacket(unit, frame)
1723 * VOID DistributeRXPacket(struct DevUnit *, UBYTE *);
1725 ****************************************************************************
1729 static VOID DistributeRXPacket(struct DevUnit *unit, const UBYTE *frame,
1730 struct DevBase *base)
1732 UWORD packet_size, ieee_length;
1733 BOOL is_orphan = TRUE, accepted, is_snap = FALSE;
1734 ULONG packet_type;
1735 UBYTE *buffer;
1736 const UBYTE *template = snap_template;
1737 struct IOSana2Req *request, *request_tail;
1738 struct Opener *opener, *opener_tail;
1739 struct TypeStats *tracker;
1741 buffer = unit->rx_buffer;
1742 ieee_length = BEWord(*(UWORD *)(frame + ETH_PACKET_IEEELEN));
1743 packet_size = ETH_HEADERSIZE + ieee_length;
1744 if(ieee_length >= SNAP_HEADERSIZE)
1745 is_snap = *(const ULONG *)(frame + ETH_PACKET_DATA)
1746 == *(const ULONG *)template;
1748 /* De-encapsulate SNAP packets and get packet type */
1750 if(is_snap)
1752 packet_size -= SNAP_HEADERSIZE;
1753 CopyMem(frame, buffer, ETH_PACKET_TYPE);
1754 CopyMem(frame + ETH_HEADERSIZE + SNAP_FRM_TYPE,
1755 buffer + ETH_PACKET_TYPE, packet_size - ETH_PACKET_TYPE);
1757 packet_type = BEWord(*((UWORD *)(buffer + ETH_PACKET_TYPE)));
1759 /* Offer packet to every opener */
1761 opener = (APTR)unit->openers.mlh_Head;
1762 opener_tail = (APTR)&unit->openers.mlh_Tail;
1764 while(opener != opener_tail)
1766 request = (APTR)opener->read_port.mp_MsgList.lh_Head;
1767 request_tail = (APTR)&opener->read_port.mp_MsgList.lh_Tail;
1768 accepted = FALSE;
1770 /* Offer packet to each request until it's accepted */
1772 while(request != request_tail && !accepted)
1774 if(request->ios2_PacketType == packet_type)
1776 CopyPacket(unit, request, packet_size, packet_type,
1777 buffer, base);
1778 accepted = TRUE;
1780 request =
1781 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
1784 if(accepted)
1785 is_orphan = FALSE;
1786 opener = (APTR)opener->node.mln_Succ;
1789 /* If packet was unwanted, give it to S2_READORPHAN request */
1791 if(is_orphan)
1793 unit->stats.UnknownTypesReceived++;
1794 if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
1796 CopyPacket(unit,
1797 (APTR)unit->request_ports[ADOPT_QUEUE]->
1798 mp_MsgList.lh_Head, packet_size, packet_type, buffer,
1799 base);
1803 /* Update remaining statistics */
1805 if(packet_type <= ETH_MTU)
1806 packet_type = ETH_MTU;
1807 tracker =
1808 FindTypeStats(unit, &unit->type_trackers, packet_type, base);
1809 if(tracker != NULL)
1811 tracker->stats.PacketsReceived++;
1812 tracker->stats.BytesReceived += packet_size;
1815 return;
1820 /****i* realtek8180.device/CopyPacket **************************************
1822 * NAME
1823 * CopyPacket -- Copy packet to client's buffer.
1825 * SYNOPSIS
1826 * CopyPacket(unit, request, packet_size, packet_type,
1827 * buffer)
1829 * VOID CopyPacket(struct DevUnit *, struct IOSana2Req *, UWORD, UWORD,
1830 * UBYTE *);
1832 ****************************************************************************
1836 static VOID CopyPacket(struct DevUnit *unit, struct IOSana2Req *request,
1837 UWORD packet_size, UWORD packet_type, UBYTE *buffer,
1838 struct DevBase *base)
1840 struct Opener *opener;
1841 BOOL filtered = FALSE;
1843 /* Set multicast and broadcast flags */
1845 request->ios2_Req.io_Flags &= ~(SANA2IOF_BCAST | SANA2IOF_MCAST);
1846 if((*((ULONG *)(buffer + ETH_PACKET_DEST)) == 0xffffffff) &&
1847 (*((UWORD *)(buffer + ETH_PACKET_DEST + 4)) == 0xffff))
1848 request->ios2_Req.io_Flags |= SANA2IOF_BCAST;
1849 else if((buffer[ETH_PACKET_DEST] & 0x1) != 0)
1850 request->ios2_Req.io_Flags |= SANA2IOF_MCAST;
1852 /* Set source and destination addresses and packet type */
1854 CopyMem(buffer + ETH_PACKET_SOURCE, request->ios2_SrcAddr,
1855 ETH_ADDRESSSIZE);
1856 CopyMem(buffer + ETH_PACKET_DEST, request->ios2_DstAddr,
1857 ETH_ADDRESSSIZE);
1858 request->ios2_PacketType = packet_type;
1860 /* Adjust for cooked packet request */
1862 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
1864 packet_size -= ETH_PACKET_DATA;
1865 buffer += ETH_PACKET_DATA;
1867 #ifdef USE_HACKS
1868 else
1869 packet_size += 4; /* Needed for Shapeshifter & Fusion? */
1870 #endif
1871 request->ios2_DataLength = packet_size;
1873 /* Filter packet */
1875 opener = request->ios2_BufferManagement;
1876 if(request->ios2_Req.io_Command == CMD_READ &&
1877 opener->filter_hook != NULL)
1878 if(!CallHookPkt(opener->filter_hook, request, buffer))
1879 filtered = TRUE;
1881 if(!filtered)
1883 /* Copy packet into opener's buffer and reply packet */
1885 if(!opener->rx_function(request->ios2_Data, buffer, packet_size))
1887 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
1888 request->ios2_WireError = S2WERR_BUFF_ERROR;
1889 ReportEvents(unit,
1890 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
1891 base);
1893 Remove((APTR)request);
1894 ReplyMsg((APTR)request);
1897 return;
1902 /****i* realtek8180.device/AddressFilter ***********************************
1904 * NAME
1905 * AddressFilter -- Determine if an RX packet should be accepted.
1907 * SYNOPSIS
1908 * accept = AddressFilter(unit, address)
1910 * BOOL AddressFilter(struct DevUnit *, UBYTE *);
1912 ****************************************************************************
1916 static BOOL AddressFilter(struct DevUnit *unit, UBYTE *address,
1917 struct DevBase *base)
1919 struct AddressRange *range, *tail;
1920 BOOL accept = TRUE;
1921 ULONG address_left;
1922 UWORD address_right;
1924 /* Check whether address is unicast/broadcast or multicast */
1926 address_left = BELong(*((ULONG *)address));
1927 address_right = BEWord(*((UWORD *)(address + 4)));
1929 if(((address_left & 0x01000000) != 0) &&
1930 !((address_left == 0xffffffff) && (address_right == 0xffff)))
1932 /* Check if this multicast address is wanted */
1934 range = (APTR)unit->multicast_ranges.mlh_Head;
1935 tail = (APTR)&unit->multicast_ranges.mlh_Tail;
1936 accept = FALSE;
1938 while((range != tail) && !accept)
1940 if((address_left > range->lower_bound_left ||
1941 address_left == range->lower_bound_left &&
1942 address_right >= range->lower_bound_right) &&
1943 (address_left < range->upper_bound_left ||
1944 address_left == range->upper_bound_left &&
1945 address_right <= range->upper_bound_right))
1946 accept = TRUE;
1947 range = (APTR)range->node.mln_Succ;
1950 if(!accept)
1951 unit->special_stats[S2SS_ETHERNET_BADMULTICAST & 0xffff]++;
1954 return accept;
1959 /****i* realtek8180.device/DistributeMgmtFrame *****************************
1961 * NAME
1962 * DistributeMgmtFrame -- Send a management frame to clients.
1964 * SYNOPSIS
1965 * DistributeMgmtFrame(unit, frame, frame_size)
1967 * VOID DistributeMgmtFrame(struct DevUnit *, UBYTE *, UWORD);
1969 ****************************************************************************
1973 static VOID DistributeMgmtFrame(struct DevUnit *unit, UBYTE *frame,
1974 UWORD frame_size, struct DevBase *base)
1976 struct IOSana2Req *request;
1977 struct Opener *opener, *opener_tail;
1979 /* Send packet to every opener */
1981 opener = (APTR)unit->openers.mlh_Head;
1982 opener_tail = (APTR)&unit->openers.mlh_Tail;
1984 while(opener != opener_tail)
1986 request = (APTR)RemHead(&opener->mgmt_port.mp_MsgList);
1988 if(request != NULL)
1990 /* Copy packet into opener's buffer and reply packet */
1992 if(frame_size <= request->ios2_DataLength)
1994 CopyMem(frame, request->ios2_Data, frame_size);
1995 request->ios2_DataLength = frame_size;
1997 else
1999 request->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
2000 request->ios2_WireError = S2WERR_BUFF_ERROR;
2001 ReportEvents(unit,
2002 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF | S2EVENT_RX,
2003 base);
2005 ReplyMsg((APTR)request);
2006 request =
2007 (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2010 opener = (APTR)opener->node.mln_Succ;
2013 return;
2018 /****i* realtek8180.device/TXInt *******************************************
2020 * NAME
2021 * TXInt -- Soft interrupt for packet transmission.
2023 * SYNOPSIS
2024 * TXInt(unit)
2026 * VOID TXInt(struct DevUnit *);
2028 * FUNCTION
2030 * INPUTS
2031 * unit - A unit of this device.
2033 * RESULT
2034 * None.
2036 ****************************************************************************
2040 static VOID TXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
2042 struct DevBase *base;
2043 UWORD i, frame_size, data_size, packet_type, body_size, slot, new_slot,
2044 encryption, subtype, duration;
2045 UBYTE *buffer, *q, *plaintext, *ciphertext, *frame,
2046 mic_header[ETH_ADDRESSSIZE * 2];
2047 const UBYTE *p, *dest, *source;
2048 struct IOSana2Req *request;
2049 BOOL proceed = TRUE, is_ieee, has_bssid;
2050 struct Opener *opener;
2051 ULONG wire_error, control_value;
2052 UBYTE *tx_desc;
2053 UBYTE *(*dma_tx_function)(REG(a0, APTR));
2054 BYTE error;
2055 struct MsgPort *port;
2056 struct TypeStats *tracker;
2058 base = unit->device;
2059 port = unit->request_ports[WRITE_QUEUE];
2061 while(proceed && (!IsMsgPortEmpty(port)))
2063 slot = unit->tx_in_slot;
2064 new_slot = (slot + 1) % TX_SLOT_COUNT;
2066 if(new_slot != unit->tx_out_slot)
2068 error = 0;
2069 body_size = 0;
2071 /* Get request and DMA frame descriptor */
2073 request = (APTR)port->mp_MsgList.lh_Head;
2075 Remove((APTR)request);
2076 unit->tx_requests[slot] = request;
2077 tx_desc = unit->tx_descs[slot];
2078 frame = unit->tx_buffers[slot];
2080 /* Get packet data */
2082 opener = request->ios2_BufferManagement;
2083 dma_tx_function = opener->dma_tx_function;
2084 if(dma_tx_function != NULL)
2085 buffer = dma_tx_function(request->ios2_Data);
2086 else
2087 buffer = NULL;
2089 if(buffer == NULL)
2091 buffer = unit->tx_buffer;
2092 if(!opener->tx_function(buffer, request->ios2_Data,
2093 request->ios2_DataLength))
2095 error = S2ERR_NO_RESOURCES;
2096 wire_error = S2WERR_BUFF_ERROR;
2097 ReportEvents(unit,
2098 S2EVENT_ERROR | S2EVENT_SOFTWARE | S2EVENT_BUFF
2099 | S2EVENT_TX, base);
2103 if(error == 0)
2105 /* Get packet type and/or length */
2107 data_size = request->ios2_DataLength;
2108 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) != 0)
2110 data_size -= ETH_PACKET_DATA;
2111 packet_type = BEWord(*(UWORD *)(buffer + ETH_PACKET_TYPE));
2113 else
2114 packet_type = request->ios2_PacketType;
2115 is_ieee = packet_type <= ETH_MTU;
2117 /* Determine encryption type and frame subtype */
2119 if(data_size > 0)
2121 encryption = unit->keys[unit->tx_key_no].type;
2122 subtype = 0;
2124 else
2126 encryption = S2ENC_NONE;
2127 subtype = 4;
2130 /* Get source and destination addresses */
2132 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) != 0)
2134 dest = buffer;
2135 source = buffer + ETH_ADDRESSSIZE;
2136 buffer += ETH_ADDRESSSIZE * 2 + 2;
2138 else
2140 dest = request->ios2_DstAddr;
2141 source = unit->address;
2144 /* Write 802.11 header */
2146 q = frame;
2147 *(UWORD *)q = MakeLEWord(
2148 (encryption == S2ENC_NONE ? 0 : WIFI_FRM_CONTROLF_WEP)
2149 | (unit->mode == S2PORT_ADHOC ? 0 : WIFI_FRM_CONTROLF_TODS)
2150 | subtype << WIFI_FRM_CONTROLB_SUBTYPE
2151 | WIFI_FRMTYPE_DATA << WIFI_FRM_CONTROLB_TYPE);
2152 q += 4;
2154 if(unit->mode == S2PORT_ADHOC)
2155 p = dest;
2156 else
2157 p = unit->bssid;
2158 for(i = 0; i < ETH_ADDRESSSIZE; i++)
2159 *q++ = *p++;
2161 for(i = 0, p = source; i < ETH_ADDRESSSIZE; i++)
2162 *q++ = *p++;
2164 if(unit->mode == S2PORT_ADHOC)
2165 p = unit->bssid;
2166 else
2167 p = dest;
2168 for(i = 0; i < ETH_ADDRESSSIZE; i++)
2169 *q++ = *p++;
2170 *(UWORD *)q = MakeLEWord(unit->tx_sequence);
2171 unit->tx_sequence += 0x10;
2172 q += 2;
2174 /* Leave room for encryption overhead */
2176 ciphertext = q;
2177 q += unit->iv_sizes[encryption];
2178 plaintext = q;
2180 /* Write SNAP header */
2182 if(!is_ieee)
2184 for(i = 0, p = snap_template;
2185 i < SNAP_FRM_TYPE; i++)
2186 *q++ = *p++;
2187 *(UWORD *)q = MakeBEWord(packet_type);
2188 q += 2;
2189 body_size += SNAP_HEADERSIZE;
2192 /* Copy data into frame */
2194 CopyMem(buffer, q, data_size);
2195 body_size += data_size;
2197 /* Append MIC to frame for TKIP */
2199 if(encryption == S2ENC_TKIP)
2201 q = mic_header;
2202 for(i = 0, p = dest; i < ETH_ADDRESSSIZE; i++)
2203 *q++ = *p++;
2204 for(i = 0, p = source; i < ETH_ADDRESSSIZE; i++)
2205 *q++ = *p++;
2206 TKIPEncryptFrame(unit, mic_header, plaintext, body_size,
2207 plaintext, base);
2208 body_size += MIC_SIZE;
2211 /* Encrypt fragment if applicable */
2213 unit->fragment_encrypt_functions[encryption](unit, frame,
2214 plaintext, &body_size, ciphertext, base);
2216 /* Clear frame descriptor as far as start of 802.11 header */
2218 q = tx_desc;
2219 for(i = 0; i < unit->tx_desc_size; i++)
2220 *q++ = 0;
2222 /* Set TX control field */
2224 frame_size = WIFI_FRM_DATA + body_size;
2225 control_value = R8180FRM_TXCONTROLF_NOENC
2226 | R8180FRM_TXCONTROLF_FIRSTFRAG
2227 | R8180FRM_TXCONTROLF_LASTFRAG
2228 | unit->tx_rate_code << R8180FRM_TXCONTROLB_RATE
2229 | frame_size;
2230 *(ULONG *)(tx_desc + R8180FRM_TXCONTROL) =
2231 MakeLELong(control_value);
2233 /* Set durations */
2235 has_bssid = ((frame + WIFI_FRM_ADDRESS1)[0] & 0x1) == 0;
2236 if(has_bssid)
2237 duration = SIFS_TIME + GetDuration(unit, 14,
2238 AckRate(unit, unit->tx_rate, base), FALSE, base);
2239 else
2240 duration = 0;
2241 *(UWORD *)(frame + WIFI_FRM_DURATION) = MakeLEWord(duration);
2243 if(unit->generation >= RTL8187B0_GEN)
2245 duration += GetDuration(unit, frame_size + 4,
2246 unit->tx_rate,
2247 (unit->flags & UNITF_SHORTPREAMBLE) != 0 && has_bssid,
2248 base);
2249 *(UWORD *)(tx_desc + R8180FRM_TXDUR) = MakeLEWord(duration);
2252 /* Set max number of retries */
2254 *(ULONG *)(tx_desc + unit->retries_offset) =
2255 MakeLELong((TX_TRIES - 1) << 8);
2257 /* Pass packet to adapter */
2259 unit->SendFrame(unit->card, tx_desc,
2260 R8180_MAXDESCSIZE + frame_size);
2261 unit->tx_in_slot = new_slot;
2263 else
2265 /* Reply failed request */
2267 request->ios2_Req.io_Error = error;
2268 request->ios2_WireError = wire_error;
2269 ReplyMsg((APTR)request);
2272 /* Update statistics */
2274 if(error == 0)
2276 unit->stats.PacketsSent++;
2278 tracker = FindTypeStats(unit, &unit->type_trackers,
2279 request->ios2_PacketType, base);
2280 if(tracker != NULL)
2282 tracker->stats.PacketsSent++;
2283 tracker->stats.BytesSent += ETH_HEADERSIZE + data_size;
2287 else
2288 proceed = FALSE;
2291 /* Don't try to keep sending packets if there's no space left */
2293 if(proceed)
2295 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
2296 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2298 else
2300 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_IGNORE;
2301 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2304 return;
2309 /****i* realtek8180.device/MgmtTXInt ***************************************
2311 * NAME
2312 * MgmtTXInt -- Soft interrupt for management frame transmission.
2314 * SYNOPSIS
2315 * MgmtTXInt(unit)
2317 * VOID MgmtTXInt(struct DevUnit *);
2319 * FUNCTION
2321 * INPUTS
2322 * unit - A unit of this device.
2324 * RESULT
2325 * None.
2327 ****************************************************************************
2331 static VOID MgmtTXInt(REG(a1, struct DevUnit *unit), REG(a6, APTR int_code))
2333 struct DevBase *base;
2334 UWORD frame_size, slot, new_slot, i, duration;
2335 UBYTE *desc, *frame, *q;
2336 struct IOSana2Req *request;
2337 BOOL proceed = TRUE, has_bssid;
2338 ULONG control_value;
2339 struct MsgPort *port;
2341 base = unit->device;
2342 port = unit->request_ports[MGMT_QUEUE];
2344 while(proceed && (!IsMsgPortEmpty(port)))
2346 slot = unit->tx_in_slot;
2347 new_slot = (slot + 1) % TX_SLOT_COUNT;
2349 if(new_slot != unit->tx_out_slot)
2351 /* Get request and frame descriptor */
2353 request = (APTR)port->mp_MsgList.lh_Head;
2355 Remove((APTR)request);
2356 unit->tx_requests[slot] = request;
2357 desc = unit->tx_descs[slot];
2358 frame = unit->tx_buffers[slot];
2360 /* Get packet length */
2362 frame_size = request->ios2_DataLength;
2364 /* Copy frame into transmit buffer */
2366 CopyMem(request->ios2_Data, frame, frame_size);
2368 /* Clear frame descriptor as far as start of 802.11 header */
2370 q = desc;
2371 for(i = 0; i < unit->tx_desc_size; i++)
2372 *q++ = 0;
2374 /* Set TX control field */
2376 control_value = R8180FRM_TXCONTROLF_NOENC
2377 | R8180FRM_TXCONTROLF_FIRSTFRAG
2378 | R8180FRM_TXCONTROLF_LASTFRAG
2379 | unit->mgmt_rate_code << R8180FRM_TXCONTROLB_RATE
2380 | frame_size;
2381 *(ULONG *)(desc + R8180FRM_TXCONTROL) = MakeLELong(control_value);
2383 /* Set durations */
2385 has_bssid = ((frame + WIFI_FRM_ADDRESS1)[0] & 0x1) == 0;
2386 if(has_bssid)
2387 duration = SIFS_TIME + GetDuration(unit, 14,
2388 AckRate(unit, unit->mgmt_rate, base), FALSE, base);
2389 else
2390 duration = 0;
2391 *(UWORD *)(frame + WIFI_FRM_DURATION) = MakeLEWord(duration);
2393 if(unit->generation >= RTL8187B0_GEN)
2395 duration += GetDuration(unit, frame_size + 4,
2396 unit->mgmt_rate, FALSE, base);
2397 *(UWORD *)(desc + R8180FRM_TXDUR) = MakeLEWord(duration);
2400 /* Set max number of retries */
2402 *(ULONG *)(desc + unit->retries_offset) =
2403 MakeLELong((TX_TRIES - 1) << 8);
2405 /* Set sequence number */
2407 *(UWORD *)(frame + WIFI_FRM_SEQCONTROL) =
2408 MakeLEWord(unit->tx_sequence);
2409 unit->tx_sequence += 0x10;
2411 /* Pass packet to adapter */
2413 unit->SendFrame(unit->card, desc, R8180_MAXDESCSIZE + frame_size);
2414 unit->tx_in_slot = new_slot;
2416 else
2417 proceed = FALSE;
2420 /* Don't try to keep sending packets if there's no space left */
2422 if(proceed)
2424 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_SOFTINT;
2425 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_SOFTINT;
2427 else
2429 unit->request_ports[WRITE_QUEUE]->mp_Flags = PA_IGNORE;
2430 unit->request_ports[MGMT_QUEUE]->mp_Flags = PA_IGNORE;
2433 return;
2438 /****i* realtek8180.device/RetireTXSlot ************************************
2440 * NAME
2441 * RetireTXSlot -- Clean up after a frame has been sent.
2443 * SYNOPSIS
2444 * RetireTXSlot(unit)
2446 * VOID RetireTXSlot(struct DevUnit *);
2448 ****************************************************************************
2452 VOID RetireTXSlot(struct DevUnit *unit, struct DevBase *base)
2454 UWORD frame_size, slot;
2455 struct IOSana2Req *request;
2456 struct TypeStats *tracker;
2458 /* Update statistics */
2460 slot = unit->tx_out_slot;
2461 request = unit->tx_requests[slot];
2462 if(request->ios2_Req.io_Command != S2_WRITEMGMT)
2464 frame_size = request->ios2_DataLength;
2465 if((request->ios2_Req.io_Flags & SANA2IOF_RAW) == 0)
2466 frame_size += ETH_HEADERSIZE;
2468 tracker = FindTypeStats(unit, &unit->type_trackers,
2469 request->ios2_PacketType, base);
2470 if(tracker != NULL)
2472 tracker->stats.PacketsSent++;
2473 tracker->stats.BytesSent += frame_size;
2477 /* Reply request */
2479 request->ios2_Req.io_Error = 0;
2480 ReplyMsg((APTR)request);
2482 unit->tx_out_slot = (slot + 1) % TX_SLOT_COUNT;
2484 /* Restart downloads if they had stopped */
2486 if(unit->request_ports[WRITE_QUEUE]->mp_Flags == PA_IGNORE)
2487 Cause(&unit->tx_int);
2488 if(unit->request_ports[MGMT_QUEUE]->mp_Flags == PA_IGNORE)
2489 Cause(&unit->mgmt_int);
2491 return;
2496 /****i* realtek8180.device/ReportEvents ************************************
2498 * NAME
2499 * ReportEvents
2501 * SYNOPSIS
2502 * ReportEvents(unit, events)
2504 * VOID ReportEvents(struct DevUnit *, ULONG);
2506 * FUNCTION
2508 * INPUTS
2509 * unit - A unit of this device.
2510 * events - A mask of events to report.
2512 * RESULT
2513 * None.
2515 ****************************************************************************
2519 static VOID ReportEvents(struct DevUnit *unit, ULONG events,
2520 struct DevBase *base)
2522 struct IOSana2Req *request, *tail, *next_request;
2523 struct List *list;
2525 list = &unit->request_ports[EVENT_QUEUE]->mp_MsgList;
2526 next_request = (APTR)list->lh_Head;
2527 tail = (APTR)&list->lh_Tail;
2529 Disable();
2530 while(next_request != tail)
2532 request = next_request;
2533 next_request = (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
2535 if((request->ios2_WireError & events) != 0)
2537 request->ios2_WireError = events;
2538 Remove((APTR)request);
2539 ReplyMsg((APTR)request);
2542 Enable();
2544 return;
2549 /****i* realtek8180.device/GetDuration *************************************
2551 * NAME
2552 * GetDuration -- Calculate a duration value.
2554 * SYNOPSIS
2555 * GetDuration(unit, length, rate, is_mgmt)
2557 * VOID GetDuration(struct DevUnit *);
2559 * FUNCTION
2560 * Calculates a duration for a frame of given length when transmitted
2561 * at a given rate. If this is a transmiss
2563 * INPUTS
2564 * unit - A unit of this device.
2565 * length - Length of frame whose duration is to be calculated.
2566 * rate - Rate frame will be transmitted at (in Mbps, rounded down).
2567 * is_short - Indicates if frame has a short preamble.
2569 * RESULT
2570 * None.
2572 ****************************************************************************
2576 static UWORD GetDuration(struct DevUnit *unit, UWORD length, UWORD rate,
2577 BOOL short_preamble, struct DevBase *base)
2579 UWORD duration, cycles;
2581 if (rate % 3 != 0)
2583 duration = 97 + (length * 8 - 1) / rate;
2584 if (!short_preamble || rate == 1)
2585 duration += 96;
2587 else
2589 cycles = rate * 4;
2590 duration = ((length + 29) / cycles + 1) * 4 + 26;
2593 return duration;
2598 /****i* realtek8180.device/AckRate *****************************************
2600 * NAME
2601 * AckRate -- Get the ACK rate corresponding to a data rate.
2603 * SYNOPSIS
2604 * ack_rate = AckRate(unit, data_rate)
2606 * UWORD AckRate(struct DevUnit *, UWORD);
2608 * FUNCTION
2609 * Calculates the rate at which the ACK frame for a data frame with the
2610 * given rate should be transmitted.
2612 * INPUTS
2613 * unit - A unit of this device.
2614 * rate - Rate data frame is transmitted at (in Mbps, rounded down).
2616 * RESULT
2617 * ack_rate - The rate for the ACK frame (Mbps, rounded down).
2619 ****************************************************************************
2623 static UWORD AckRate(struct DevUnit *unit, UWORD data_rate,
2624 struct DevBase *base)
2626 UWORD ack_rate;
2628 switch(data_rate)
2630 case 54:
2631 case 48:
2632 case 36:
2633 case 24:
2634 ack_rate = 24;
2635 break;
2636 case 18:
2637 case 12:
2638 ack_rate = 12;
2639 break;
2640 case 9:
2641 case 6:
2642 ack_rate = 6;
2643 break;
2644 case 11:
2645 case 5:
2646 case 2:
2647 ack_rate = 2;
2648 break;
2649 case 1:
2650 ack_rate = 1;
2651 break;
2654 return ack_rate;
2659 /****i* realtek8180.device/UnitTask ****************************************
2661 * NAME
2662 * UnitTask
2664 * SYNOPSIS
2665 * UnitTask()
2667 * VOID UnitTask();
2669 * FUNCTION
2670 * Completes deferred requests, and handles card insertion and removal
2671 * in conjunction with the relevant interrupts.
2673 ****************************************************************************
2677 #ifdef __MORPHOS__
2678 #undef UnitTask
2679 #endif
2681 static VOID UnitTask(struct ExecBase *sys_base)
2683 struct Task *task;
2684 struct IORequest *request;
2685 struct DevUnit *unit;
2686 struct DevBase *base;
2687 struct MsgPort *general_port;
2688 ULONG signals = 0, wait_signals, card_removed_signal,
2689 card_inserted_signal, general_port_signal;
2691 /* Get parameters */
2693 task = AbsExecBase->ThisTask;
2694 unit = task->tc_UserData;
2695 base = unit->device;
2697 /* Activate general request port */
2699 general_port = unit->request_ports[GENERAL_QUEUE];
2700 general_port->mp_SigTask = task;
2701 general_port->mp_SigBit = AllocSignal(-1);
2702 general_port_signal = 1 << general_port->mp_SigBit;
2703 general_port->mp_Flags = PA_SIGNAL;
2705 /* Allocate signals for notification of card removal and insertion */
2707 card_removed_signal = unit->card_removed_signal = 1 << AllocSignal(-1);
2708 card_inserted_signal = unit->card_inserted_signal = 1 << AllocSignal(-1);
2709 wait_signals = (1 << general_port->mp_SigBit) | card_removed_signal
2710 | card_inserted_signal | SIGBREAKF_CTRL_C;
2712 /* Tell ourselves to check port for old messages */
2714 Signal(task, general_port_signal);
2716 /* Infinite loop to service requests and signals */
2718 while(TRUE)
2720 signals = Wait(wait_signals);
2722 if((signals & card_inserted_signal) != 0)
2724 if(unit->insertion_function(unit->card, base))
2726 unit->flags |= UNITF_HAVEADAPTER;
2727 if((unit->flags & UNITF_CONFIGURED) != 0)
2728 ConfigureAdapter(unit, base);
2729 if((unit->flags & UNITF_WASONLINE) != 0)
2731 GoOnline(unit, base);
2732 unit->flags &= ~UNITF_WASONLINE;
2737 if((signals & card_removed_signal) != 0)
2739 unit->removal_function(unit->card, base);
2740 if((unit->flags & UNITF_WASONLINE) != 0)
2741 GoOffline(unit, base);
2744 if((signals & general_port_signal) != 0)
2746 while((request = (APTR)GetMsg(general_port)) != NULL)
2748 /* Service the request as soon as the unit is free */
2750 ObtainSemaphore(&unit->access_lock);
2751 ServiceRequest((APTR)request, base);