New WPA-capable version of prism2.device.
[AROS.git] / workbench / devs / networks / prism2 / os4_device.c
blobf250df5038787003a33a1bbc6345400ec8bba0cc
1 /*
3 Copyright (C) 2000-2008 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/types.h>
24 #include <exec/resident.h>
25 #include <exec/errors.h>
26 #include <exec/emulation.h>
27 #include <dos/dos.h>
28 #include <utility/utility.h>
29 #include <expansion/expansion.h>
30 #include <resources/card.h>
31 #include <libraries/pccard.h>
33 #include <proto/exec.h>
34 #include <clib/alib_protos.h>
35 #include <proto/utility.h>
37 #include "device.h"
39 #include "device_protos.h"
40 #include "unit_protos.h"
41 #include "pci_protos.h"
42 #include "request_protos.h"
45 /* Private prototypes */
47 static struct DevBase *OS4DevInit(struct DevBase *dev_base, APTR seg_list,
48 struct ExecIFace *i_exec);
49 static ULONG IfaceObtain(struct Interface *self);
50 static ULONG IfaceRelease(struct Interface *self);
51 static LONG OS4DevOpen(struct Interface *self, struct IOSana2Req *request,
52 ULONG unit_num, ULONG flags);
53 static APTR OS4DevClose(struct Interface *self, struct IOSana2Req *request);
54 static APTR OS4DevExpunge(struct Interface *self);
55 static VOID OS4DevBeginIO(struct Interface *self,
56 struct IOSana2Req *request);
57 static VOID OS4DevAbortIO(struct Interface *self,
58 struct IOSana2Req *request);
59 static VOID DeleteDevice(struct DevBase *base);
60 static BOOL RXFunction(struct IOSana2Req *request, APTR buffer, ULONG size);
61 static BOOL TXFunction(APTR buffer, struct IOSana2Req *request, ULONG size);
62 static UBYTE *DMATXFunction(struct IOSana2Req *request);
63 static ULONG OS4Int(struct ExceptionContext ex_context,
64 struct ExecBase *sys_base, APTR *int_data);
67 extern const TEXT device_name[];
68 extern const TEXT version_string[];
69 extern const TEXT utility_name[];
70 extern const TEXT pccard_name[];
71 extern const TEXT card_name[];
72 extern const TEXT dos_name[];
73 extern const TEXT timer_name[];
74 extern const struct Resident rom_tag;
76 static const TEXT manager_name[] = "__device";
77 static const TEXT expansion_name[] = EXPANSIONNAME;
80 static const APTR manager_vectors[] =
82 (APTR)IfaceObtain,
83 (APTR)IfaceRelease,
84 (APTR)NULL,
85 (APTR)NULL,
86 (APTR)OS4DevOpen,
87 (APTR)OS4DevClose,
88 (APTR)OS4DevExpunge,
89 (APTR)NULL,
90 (APTR)OS4DevBeginIO,
91 (APTR)OS4DevAbortIO,
92 (APTR)-1
96 static const struct TagItem manager_tags[] =
98 {MIT_Name, (UPINT)manager_name},
99 {MIT_VectorTable, (UPINT)manager_vectors},
100 {MIT_Version, 1},
101 {TAG_END, 0}
105 static const struct TagItem *interfaces[] =
107 manager_tags,
108 NULL
112 static const struct TagItem init_tags[] =
114 {CLT_DataSize, sizeof(struct DevBase)},
115 {CLT_InitFunc, (UPINT)OS4DevInit},
116 {CLT_Interfaces, (UPINT)interfaces},
117 {TAG_END, 0}
121 const struct Resident os4_rom_tag =
123 RTC_MATCHWORD,
124 (struct Resident *)&os4_rom_tag,
125 (APTR)(&rom_tag + 1),
126 RTF_AUTOINIT | RTF_NATIVE,
127 VERSION,
128 NT_DEVICE,
130 (STRPTR)device_name,
131 (STRPTR)version_string,
132 (APTR)init_tags
136 static const ULONG rx_tags[] =
138 S2_CopyToBuff,
139 S2_CopyToBuff16,
143 static const ULONG tx_tags[] =
145 S2_CopyFromBuff,
146 S2_CopyFromBuff16,
147 S2_CopyFromBuff32
152 /****i* prism2.device/OS4DevInit *******************************************
154 * NAME
155 * OS4DevInit
157 * SYNOPSIS
158 * dev_base = OS4DevInit(dev_base, seg_list, i_exec)
160 * struct DevBase *OS4DevInit(struct DevBase *, APTR, ExecIFace *);
162 ****************************************************************************
166 static struct DevBase *OS4DevInit(struct DevBase *dev_base, APTR seg_list,
167 struct ExecIFace *i_exec)
169 struct DevBase *base;
170 BOOL success = TRUE;
172 dev_base->i_exec = i_exec;
173 base = dev_base;
174 base->seg_list = seg_list;
175 base->sys_base = (APTR)i_exec->Data.LibBase;
177 base->device.dd_Library.lib_Node.ln_Type = NT_DEVICE;
178 base->device.dd_Library.lib_Node.ln_Name = (TEXT *)device_name;
179 base->device.dd_Library.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
180 base->device.dd_Library.lib_Version = VERSION;
181 base->device.dd_Library.lib_Revision = REVISION;
182 base->device.dd_Library.lib_IdString = (TEXT *)version_string;
184 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
185 base->expansion_base = OpenLibrary(expansion_name, EXPANSION_VERSION);
186 base->dos_base = (APTR)OpenLibrary(dos_name, DOS_VERSION);
187 if(base->utility_base == NULL || base->expansion_base == NULL
188 || base->dos_base == NULL)
189 success = FALSE;
190 base->pccard_base = (APTR)OpenLibrary(pccard_name, PCCARD_VERSION);
191 if(base->pccard_base != NULL)
192 base->card_base = (APTR)OpenResource(card_name);
194 if(OpenDevice(timer_name, UNIT_VBLANK, (APTR)&base->timer_request, 0) !=
196 success = FALSE;
198 NewList((APTR)(&dev_base->pci_units));
199 NewList((APTR)(&dev_base->pccard_units));
200 base->wrapper_int_code = (APTR)OS4Int;
202 if(success)
204 base->i_utility =
205 (APTR)GetInterface((APTR)UtilityBase, "main", 1, NULL);
206 base->i_pci = (APTR)GetInterface(ExpansionBase, "pci", 1, NULL);
207 base->i_dos = (APTR)GetInterface((APTR)DOSBase, "main", 1, NULL);
208 if(CardResource != NULL)
210 base->i_pccard =
211 (APTR)GetInterface(PCCardBase, "main", 1, NULL);
212 base->i_card =
213 (APTR)GetInterface(CardResource, "main", 1, NULL);
214 // if(base->i_pccard == NULL || base->i_card == NULL)
215 if(base->i_card == NULL)
216 success = FALSE;
218 base->i_timer = (APTR)GetInterface((APTR)TimerBase, "main", 1, NULL);
219 if(base->i_utility == NULL || base->i_dos == NULL
220 || base->i_timer == NULL)
221 success = FALSE;
224 if(!success)
226 DeleteDevice(base);
227 base = NULL;
230 return base;
235 /****i* prism2.device/IfaceObtain ******************************************
237 * NAME
238 * IfaceObtain
240 * SYNOPSIS
241 * ref_count = IfaceObtain(self)
243 * ULONG IfaceObtain(struct Interface *);
245 ****************************************************************************
249 static ULONG IfaceObtain(struct Interface *self)
251 return self->Data.RefCount++;
256 /****i* prism2.device/IfaceRelease *****************************************
258 * NAME
259 * IfaceRelease
261 * SYNOPSIS
262 * ref_count = IfaceRelease(self)
264 * ULONG IfaceRelease(struct Interface *);
266 ****************************************************************************
270 static ULONG IfaceRelease(struct Interface *self)
272 return --self->Data.RefCount;
277 /****i* prism2.device/OS4DevOpen *******************************************
279 * NAME
280 * OS4DevOpen
282 * SYNOPSIS
283 * error = OS4DevOpen(self, request, unit_num,
284 * flags)
286 * LONG OS4DevOpen(struct Interface *, struct IOSana2Req *, ULONG,
287 * ULONG);
289 ****************************************************************************
293 static LONG OS4DevOpen(struct Interface *self, struct IOSana2Req *request,
294 ULONG unit_num, ULONG flags)
296 struct Opener *opener;
297 BYTE error;
299 error = DevOpen(request, unit_num, flags, (APTR)self->Data.LibBase);
301 /* Set up wrapper hooks to hide 68k emulation */
303 if(error == 0)
305 opener = request->ios2_BufferManagement;
306 opener->real_rx_function = opener->rx_function;
307 opener->real_tx_function = opener->tx_function;
308 opener->rx_function = (APTR)RXFunction;
309 opener->tx_function = (APTR)TXFunction;
310 if(opener->dma_tx_function != NULL)
312 opener->real_dma_tx_function = opener->dma_tx_function;
313 opener->dma_tx_function = (APTR)DMATXFunction;
317 return error;
322 /****i* prism2.device/OS4DevClose ******************************************
324 * NAME
325 * OS4DevClose
327 * SYNOPSIS
328 * seg_list = OS4DevClose(request)
330 * APTR OS4DevClose(struct IOSana2Req *);
332 ****************************************************************************
336 static APTR OS4DevClose(struct Interface *self, struct IOSana2Req *request)
338 struct DevBase *base;
339 APTR seg_list = NULL;
341 /* Close the unit */
343 base = (APTR)self->Data.LibBase;
344 CloseUnit(request, base);
346 /* Expunge the device if a delayed expunge is pending */
348 if(base->device.dd_Library.lib_OpenCnt == 0)
350 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
351 seg_list = OS4DevExpunge(self);
354 return seg_list;
359 /****i* prism2.device/OS4DevExpunge ****************************************
361 * NAME
362 * OS4DevExpunge
364 * SYNOPSIS
365 * seg_list = OS4DevExpunge()
367 * APTR OS4DevExpunge(VOID);
369 ****************************************************************************
373 static APTR OS4DevExpunge(struct Interface *self)
375 struct DevBase *base;
376 APTR seg_list;
378 base = (APTR)self->Data.LibBase;
379 if(base->device.dd_Library.lib_OpenCnt == 0)
381 seg_list = base->seg_list;
382 Remove((APTR)base);
383 DeleteDevice(base);
385 else
387 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
388 seg_list = NULL;
391 return seg_list;
396 /****i* prism2.device/OS4DevBeginIO ****************************************
398 * NAME
399 * OS4DevBeginIO
401 * SYNOPSIS
402 * OS4DevBeginIO(request)
404 * VOID OS4DevBeginIO(struct IORequest *);
406 ****************************************************************************
410 static VOID OS4DevBeginIO(struct Interface *self,
411 struct IOSana2Req *request)
413 /* Replace caller's cookie with our own */
415 request->ios2_Req.io_Error = 0;
416 switch(request->ios2_Req.io_Command)
418 case CMD_READ:
419 case CMD_WRITE:
420 case S2_MULTICAST:
421 case S2_BROADCAST:
422 case S2_READORPHAN:
423 request->ios2_StatData = request->ios2_Data;
424 request->ios2_Data = request;
427 /* Send request for processing */
429 DevBeginIO(request, (APTR)self->Data.LibBase);
431 return;
436 /****i* prism2.device/OS4DevAbortIO ****************************************
438 * NAME
439 * OS4DevAbortIO -- Try to stop a request.
441 * SYNOPSIS
442 * OS4DevAbortIO(request)
444 * VOID OS4DevAbortIO(struct IOSana2Req *);
446 ****************************************************************************
448 * Disable() used instead of a semaphore because device uses interrupts.
452 static VOID OS4DevAbortIO(struct Interface *self,
453 struct IOSana2Req *request)
455 DevAbortIO(request, (APTR)self->Data.LibBase);
457 return;
462 /****i* prism2.device/DeleteDevice *****************************************
464 * NAME
465 * DeleteDevice
467 * SYNOPSIS
468 * DeleteDevice()
470 * VOID DeleteDevice(VOID);
472 ****************************************************************************
476 static VOID DeleteDevice(struct DevBase *base)
478 /* Close interfaces */
480 DropInterface((APTR)base->i_timer);
481 DropInterface((APTR)base->i_card);
482 DropInterface((APTR)base->i_pccard);
483 DropInterface((APTR)base->i_dos);
484 DropInterface((APTR)base->i_pci);
485 DropInterface((APTR)base->i_utility);
487 /* Close devices */
489 CloseDevice((APTR)&base->timer_request);
491 /* Close libraries */
493 if(base->pccard_base != NULL)
494 CloseLibrary(base->pccard_base);
495 if(base->dos_base != NULL)
496 CloseLibrary((APTR)base->dos_base);
497 if(base->expansion_base != NULL)
498 CloseLibrary(base->expansion_base);
499 if(base->utility_base != NULL)
500 CloseLibrary((APTR)base->utility_base);
502 /* Free device's memory */
504 DeleteLibrary((APTR)base);
506 return;
511 /****i* prism2.device/RXFunction *******************************************
513 * NAME
514 * RXFunction
516 ****************************************************************************
520 static BOOL RXFunction(struct IOSana2Req *request, APTR buffer, ULONG size)
522 struct DevBase *base;
523 struct Opener *opener;
524 APTR cookie;
526 opener = request->ios2_BufferManagement;
527 cookie = request->ios2_StatData;
528 base = (struct DevBase *)request->ios2_Req.io_Device;
529 request->ios2_Data = cookie;
531 return EmulateTags(opener->real_rx_function,
532 ET_RegisterA0, cookie, ET_RegisterA1, buffer,
533 ET_RegisterD0, size, TAG_END);
538 /****i* prism2.device/TXFunction *******************************************
540 * NAME
541 * TXFunction
543 ****************************************************************************
547 static BOOL TXFunction(APTR buffer, struct IOSana2Req *request, ULONG size)
549 struct DevBase *base;
550 struct Opener *opener;
551 APTR cookie;
553 opener = request->ios2_BufferManagement;
554 cookie = request->ios2_StatData;
555 base = (struct DevBase *)request->ios2_Req.io_Device;
556 request->ios2_Data = cookie;
557 return EmulateTags(opener->real_tx_function,
558 ET_RegisterA0, buffer, ET_RegisterA1, cookie,
559 ET_RegisterD0, size, TAG_END);
564 /****i* prism2.device/DMATXFunction ****************************************
566 * NAME
567 * DMATXFunction
569 ****************************************************************************
573 static UBYTE *DMATXFunction(struct IOSana2Req *request)
575 struct DevBase *base;
576 struct Opener *opener;
577 APTR cookie;
579 opener = request->ios2_BufferManagement;
580 cookie = request->ios2_StatData;
581 base = (struct DevBase *)request->ios2_Req.io_Device;
582 request->ios2_Data = cookie;
583 return (UBYTE *)EmulateTags(opener->real_dma_tx_function,
584 ET_RegisterA0, cookie, TAG_END);
589 /****i* prism2.device/OS4Int ***********************************************
591 * NAME
592 * OS4Int
594 ****************************************************************************
598 static ULONG OS4Int(struct ExceptionContext ex_context,
599 struct ExecBase *sys_base, APTR *int_data)
601 BOOL (*int_code)(APTR, APTR, UBYTE);
603 int_code = int_data[0];
604 return int_code(int_data[1], int_code, 0x4);