AHI: build Alsa driver when alsa-bridge link lib is detected
[AROS.git] / workbench / devs / networks / atheros5000 / device.c
blob22a049e1b3023d5a4d566ed5e109a13594a015c7
1 /*
3 Copyright (C) 2000-2011 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 <dos/dos.h>
27 #include <utility/utility.h>
28 #include "initializers.h"
30 #include <proto/exec.h>
31 #include <clib/alib_protos.h>
32 #include <proto/utility.h>
34 #include "device.h"
36 #include "device_protos.h"
37 #include "pci_protos.h"
38 #include "request_protos.h"
41 /* Private prototypes */
43 static VOID DeleteDevice(struct DevBase *base);
46 /* Return an error immediately if someone tries to run the device */
48 LONG Main()
50 return -1;
54 const TEXT device_name[] = DEVICE_NAME;
55 const TEXT version_string[] =
56 DEVICE_NAME " " STR(VERSION) "." STR(REVISION) " (" DATE ")\n";
57 const TEXT utility_name[] = UTILITYNAME;
58 static const TEXT prometheus_name[] = "prometheus.library";
59 const TEXT dos_name[] = DOSNAME;
60 const TEXT timer_name[] = TIMERNAME;
63 static const APTR vectors[] =
65 (APTR)DevOpen,
66 (APTR)DevClose,
67 (APTR)DevExpunge,
68 (APTR)DevReserved,
69 (APTR)DevBeginIO,
70 (APTR)DevAbortIO,
71 (APTR)-1
75 #ifdef __MORPHOS__
76 #pragma pack(2)
77 #endif
78 const struct
80 SMALLINITBYTEDEF(type);
81 SMALLINITPINTDEF(name);
82 SMALLINITBYTEDEF(flags);
83 SMALLINITWORDDEF(version);
84 SMALLINITWORDDEF(revision);
85 SMALLINITPINTDEF(id_string);
86 INITENDDEF;
88 init_data =
90 SMALLINITBYTE(OFFSET(Node, ln_Type), NT_DEVICE),
91 SMALLINITPINT(OFFSET(Node, ln_Name), device_name),
92 SMALLINITBYTE(OFFSET(Library, lib_Flags), LIBF_SUMUSED | LIBF_CHANGED),
93 SMALLINITWORD(OFFSET(Library, lib_Version), VERSION),
94 SMALLINITWORD(OFFSET(Library, lib_Revision), REVISION),
95 SMALLINITPINT(OFFSET(Library, lib_IdString), version_string),
96 INITEND
98 #ifdef __MORPHOS__
99 #pragma pack()
100 #endif
103 static const APTR init_table[] =
105 (APTR)sizeof(struct DevBase),
106 (APTR)vectors,
107 (APTR)&init_data,
108 (APTR)DevInit
112 const struct Resident rom_tag =
114 RTC_MATCHWORD,
115 (struct Resident *)&rom_tag,
116 (APTR)(&rom_tag + 1),
117 RTF_AUTOINIT,
118 VERSION,
119 NT_DEVICE,
121 (STRPTR)device_name,
122 (STRPTR)version_string,
123 (APTR)init_table
127 static const ULONG rx_tags[] =
129 S2_CopyToBuff,
130 S2_CopyToBuff16,
134 static const ULONG tx_tags[] =
136 S2_CopyFromBuff,
137 S2_CopyFromBuff16,
138 S2_CopyFromBuff32
143 /****i* atheros5000.device/DevInit *****************************************
145 * NAME
146 * DevInit
148 * SYNOPSIS
149 * dev_base = DevInit(dev_base, seg_list)
151 * struct DevBase *DevInit(struct DevBase *, APTR);
153 ****************************************************************************
157 struct DevBase *DevInit(REG(d0, struct DevBase *dev_base),
158 REG(a0, APTR seg_list), REG(BASE_REG, struct DevBase *base))
160 BOOL success = TRUE;
162 /* Initialise base structure */
164 dev_base->sys_base = (APTR)base;
165 base = dev_base;
166 hal_dev_base = dev_base;
167 base->seg_list = seg_list;
168 NewList((APTR)(&base->pci_units));
170 /* Open libraries, resources and devices */
172 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
173 base->prometheus_base = OpenLibrary(prometheus_name, PROMETHEUS_VERSION);
174 base->dos_base = (APTR)OpenLibrary(dos_name, DOS_VERSION);
176 if(base->utility_base == NULL || base->dos_base == NULL)
177 success = FALSE;
179 if(OpenDevice(timer_name, UNIT_VBLANK, (APTR)&base->timer_request, 0)
180 != 0)
181 success = FALSE;
183 if(!success)
185 DeleteDevice(base);
186 base = NULL;
189 return base;
194 /****i* atheros5000.device/DevOpen *****************************************
196 * NAME
197 * DevOpen
199 * SYNOPSIS
200 * error = DevOpen(request, unit_num, flags)
202 * BYTE DevOpen(struct IOSana2Req *, ULONG, ULONG);
204 ****************************************************************************
208 BYTE DevOpen(REG(a1, struct IOSana2Req *request),
209 REG(d0, ULONG unit_num), REG(d1, ULONG flags),
210 REG(BASE_REG, struct DevBase *base))
212 struct DevUnit *unit;
213 BYTE error = 0;
214 struct Opener *opener;
215 struct TagItem *tag_list;
216 UWORD i;
218 base->device.dd_Library.lib_OpenCnt++;
219 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
221 request->ios2_Req.io_Unit = NULL;
222 tag_list = request->ios2_BufferManagement;
223 request->ios2_BufferManagement = NULL;
225 /* Check request size */
227 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
228 error = IOERR_OPENFAIL;
230 /* Get the requested unit */
232 if(error == 0)
234 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
235 if(unit == NULL)
236 error = IOERR_OPENFAIL;
239 /* Handle device sharing */
241 if(error == 0)
243 if(unit->open_count != 0 && ((unit->flags & UNITF_SHARED) == 0
244 || (flags & SANA2OPF_MINE) != 0))
245 error = IOERR_UNITBUSY;
246 unit->open_count++;
249 if(error == 0)
251 if((flags & SANA2OPF_MINE) == 0)
252 unit->flags |= UNITF_SHARED;
253 else if((flags & SANA2OPF_PROM) != 0)
254 unit->flags |= UNITF_PROM;
256 /* Set up buffer-management structure and get hooks */
258 request->ios2_BufferManagement = opener =
259 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
260 if(opener == NULL)
261 error = IOERR_OPENFAIL;
264 if(error == 0)
266 NewList(&opener->read_port.mp_MsgList);
267 opener->read_port.mp_Flags = PA_IGNORE;
268 NewList(&opener->mgmt_port.mp_MsgList);
269 opener->mgmt_port.mp_Flags = PA_IGNORE;
270 NewList((APTR)&opener->initial_stats);
272 for(i = 0; i < 2; i++)
273 opener->rx_function = (APTR)GetTagData(rx_tags[i],
274 (UPINT)opener->rx_function, tag_list);
275 for(i = 0; i < 3; i++)
276 opener->tx_function = (APTR)GetTagData(tx_tags[i],
277 (UPINT)opener->tx_function, tag_list);
279 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL,
280 tag_list);
281 opener->dma_tx_function =
282 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
284 Disable();
285 AddTail((APTR)&unit->openers, (APTR)opener);
286 Enable();
289 /* Back out if anything went wrong */
291 if(error != 0)
292 CloseUnit(request, base);
294 /* Return */
296 request->ios2_Req.io_Error = error;
297 return error;
302 /****i* atheros5000.device/DevClose ****************************************
304 * NAME
305 * DevClose
307 * SYNOPSIS
308 * seg_list = DevClose(request)
310 * APTR DevClose(struct IOSana2Req *);
312 ****************************************************************************
316 APTR DevClose(REG(a1, struct IOSana2Req *request),
317 REG(BASE_REG, struct DevBase *base))
319 APTR seg_list = NULL;
321 /* Close the unit */
323 CloseUnit(request, base);
325 /* Expunge the device if a delayed expunge is pending */
327 if(base->device.dd_Library.lib_OpenCnt == 0)
329 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
330 seg_list = DevExpunge(base);
333 return seg_list;
338 /****i* atheros5000.device/DevExpunge **************************************
340 * NAME
341 * DevExpunge
343 * SYNOPSIS
344 * seg_list = DevExpunge()
346 * APTR DevExpunge(VOID);
348 ****************************************************************************
352 APTR DevExpunge(REG(BASE_REG, struct DevBase *base))
354 APTR seg_list;
356 if(base->device.dd_Library.lib_OpenCnt == 0)
358 seg_list = base->seg_list;
359 Remove((APTR)base);
360 DeleteDevice(base);
362 else
364 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
365 seg_list = NULL;
368 return seg_list;
373 /****i* atheros5000.device/DevReserved *************************************
375 * NAME
376 * DevReserved
378 * SYNOPSIS
379 * result = DevReserved()
381 * APTR DevReserved(VOID);
383 ****************************************************************************
387 APTR DevReserved()
389 return NULL;
394 /****i* atheros5000.device/DevBeginIO **************************************
396 * NAME
397 * DevBeginIO
399 * SYNOPSIS
400 * DevBeginIO(request)
402 * VOID DevBeginIO(struct IORequest *);
404 ****************************************************************************
408 VOID DevBeginIO(REG(a1, struct IOSana2Req *request),
409 REG(BASE_REG, struct DevBase *base))
411 struct DevUnit *unit;
413 request->ios2_Req.io_Error = 0;
414 unit = (APTR)request->ios2_Req.io_Unit;
416 if(AttemptSemaphore(&unit->access_lock))
417 ServiceRequest(request, base);
418 else
419 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
421 return;
426 /****i* atheros5000.device/DevAbortIO **************************************
428 * NAME
429 * DevAbortIO -- Try to stop a request.
431 * SYNOPSIS
432 * DevAbortIO(request)
434 * VOID DevAbortIO(struct IOSana2Req *);
436 * FUNCTION
437 * Do our best to halt the progress of a request.
439 ****************************************************************************
443 VOID DevAbortIO(REG(a1, struct IOSana2Req *request),
444 REG(BASE_REG, struct DevBase *base))
446 Disable();
447 if(request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE &&
448 (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
450 Remove((APTR)request);
451 request->ios2_Req.io_Error = IOERR_ABORTED;
452 request->ios2_WireError = S2WERR_GENERIC_ERROR;
453 ReplyMsg((APTR)request);
455 Enable();
457 return;
462 /****i* atheros5000.device/DeleteDevice ************************************
464 * NAME
465 * DeleteDevice
467 * SYNOPSIS
468 * DeleteDevice()
470 * VOID DeleteDevice(VOID);
472 ****************************************************************************
476 VOID DeleteDevice(struct DevBase *base)
478 UWORD neg_size, pos_size;
480 /* Close devices */
482 CloseDevice((APTR)&base->timer_request);
484 /* Close libraries */
486 if(base->dos_base != NULL)
487 CloseLibrary((APTR)base->dos_base);
488 if(base->openpci_base != NULL)
489 CloseLibrary(base->openpci_base);
490 if(base->prometheus_base != NULL)
491 CloseLibrary(base->prometheus_base);
492 if(base->utility_base != NULL)
493 CloseLibrary((APTR)base->utility_base);
495 /* Free device's memory */
497 neg_size = base->device.dd_Library.lib_NegSize;
498 pos_size = base->device.dd_Library.lib_PosSize;
499 FreeMem((UBYTE *)base - neg_size, pos_size + neg_size);
501 return;
506 /****i* atheros5000.device/CloseUnit ***************************************
508 * NAME
509 * CloseUnit
511 * SYNOPSIS
512 * CloseUnit(request)
514 * VOID CloseUnit(struct IOSana2Req *);
516 ****************************************************************************
520 VOID CloseUnit(struct IOSana2Req *request, struct DevBase *base)
522 struct DevUnit *unit;
523 struct Opener *opener;
525 /* Decrement device usage count and free buffer-management resources */
527 base->device.dd_Library.lib_OpenCnt--;
528 opener = (APTR)request->ios2_BufferManagement;
529 if(opener != NULL)
531 Disable();
532 Remove((APTR)opener);
533 Enable();
534 FreeVec(opener);
537 /* Delete the unit if it's no longer in use */
539 unit = (APTR)request->ios2_Req.io_Unit;
540 if(unit != NULL)
542 if((--unit->open_count) == 0)
544 Remove((APTR)unit);
545 switch(unit->bus)
547 case PCI_BUS:
548 DeletePCIUnit(unit, base);
549 break;
554 return;
559 /****i* atheros5000.device/GetUnit *****************************************
561 * NAME
562 * GetUnit -- Get a unit by number.
564 * SYNOPSIS
565 * unit = GetUnit(unit_num)
567 * struct DevUnit *GetUnit(ULONG);
569 ****************************************************************************
573 struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
575 struct DevUnit *unit;
576 ULONG pci_limit;
578 pci_limit = GetPCICount(base);
580 if(unit_num < pci_limit)
581 unit = GetPCIUnit(unit_num, base);
582 else
583 unit = NULL;
585 return unit;
590 /****i* atheros5000.device/WrapInt *****************************************
592 * NAME
593 * WrapInt
595 ****************************************************************************
599 BOOL WrapInt(struct Interrupt *interrupt, struct DevBase *base)
601 BOOL success = TRUE;
602 APTR *int_data;
604 if(base->wrapper_int_code != NULL)
606 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
607 if(int_data != NULL)
609 int_data[0] = interrupt->is_Code;
610 int_data[1] = interrupt->is_Data;
611 interrupt->is_Code = base->wrapper_int_code;
612 interrupt->is_Data = int_data;
614 else
615 success = FALSE;
618 return success;
623 /****i* atheros5000.device/UnwrapInt ***************************************
625 * NAME
626 * UnwrapInt
628 ****************************************************************************
632 VOID UnwrapInt(struct Interrupt *interrupt, struct DevBase *base)
634 if(interrupt->is_Code == base->wrapper_int_code)
635 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
637 return;