revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / intelpro100 / device.c
blob504d567ab086d939181015284396ad35a56bf420
1 /*
3 Copyright (C) 2000-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/types.h>
24 #include <exec/resident.h>
25 #include <exec/errors.h>
26 #include <utility/utility.h>
27 #include "initializers.h"
29 #include <proto/exec.h>
30 #include <proto/alib.h>
31 #include <proto/utility.h>
33 #include "device.h"
35 #include "device_protos.h"
36 #include "pci_protos.h"
37 #include "request_protos.h"
40 /* Private prototypes */
42 static VOID DeleteDevice(struct DevBase *base);
43 static struct DevUnit *GetUnit(ULONG unit_num, 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 static const TEXT utility_name[] = UTILITYNAME;
58 static const TEXT prometheus_name[] = "prometheus.library";
59 static const TEXT powerpci_name[] = "powerpci.library";
60 static 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* intelpro100.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 base->seg_list = seg_list;
167 NewList((APTR)(&base->pci_units));
169 /* Open libraries, resources and devices */
171 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
172 base->prometheus_base = OpenLibrary(prometheus_name, PROMETHEUS_VERSION);
173 if(base->prometheus_base == NULL)
174 base->powerpci_base = OpenLibrary(powerpci_name, POWERPCI_VERSION);
175 #ifdef __MORPHOS__
176 base->openpci_base = OpenLibrary(openpci_name, OPENPCI_VERSION);
177 #endif
179 if(base->utility_base == NULL || base->prometheus_base == NULL
180 && base->powerpci_base == NULL && base->openpci_base == NULL)
181 success = FALSE;
183 /* if(OpenDevice(timer_name, UNIT_ECLOCK, (APTR)&base->timer_request, 0)*/
184 if(OpenDevice(timer_name, UNIT_VBLANK, (APTR)&base->timer_request, 0)
185 != 0)
186 success = FALSE;
188 #ifdef __MORPHOS__
189 base->wrapper_int_code = (APTR)&int_trap;
190 #endif
192 if(!success)
194 DeleteDevice(base);
195 base = NULL;
198 return base;
203 /****i* intelpro100.device/DevOpen *****************************************
205 * NAME
206 * DevOpen
208 * SYNOPSIS
209 * error = DevOpen(request, unit_num, flags)
211 * BYTE DevOpen(struct IOSana2Req *, ULONG, ULONG);
213 ****************************************************************************
217 BYTE DevOpen(REG(a1, struct IOSana2Req *request),
218 REG(d0, ULONG unit_num), REG(d1, ULONG flags),
219 REG(BASE_REG, struct DevBase *base))
221 struct DevUnit *unit;
222 BYTE error = 0;
223 struct Opener *opener;
224 struct TagItem *tag_list;
225 UWORD i;
227 base->device.dd_Library.lib_OpenCnt++;
228 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
230 request->ios2_Req.io_Unit = NULL;
231 tag_list = request->ios2_BufferManagement;
232 request->ios2_BufferManagement = NULL;
234 /* Check request size */
236 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
237 error = IOERR_OPENFAIL;
239 /* Get the requested unit */
241 if(error == 0)
243 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
244 if(unit == NULL)
245 error = IOERR_OPENFAIL;
248 /* Handle device sharing */
250 if(error == 0)
252 if(unit->open_count != 0 && ((unit->flags & UNITF_SHARED) == 0
253 || (flags & SANA2OPF_MINE) != 0))
254 error = IOERR_UNITBUSY;
255 unit->open_count++;
258 if(error == 0)
260 if((flags & SANA2OPF_MINE) == 0)
261 unit->flags |= UNITF_SHARED;
262 else if((flags & SANA2OPF_PROM) != 0)
263 unit->flags |= UNITF_PROM;
265 /* Set up buffer-management structure and get hooks */
267 request->ios2_BufferManagement = opener =
268 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
269 if(opener == NULL)
270 error = IOERR_OPENFAIL;
273 if(error == 0)
275 NewList(&opener->read_port.mp_MsgList);
276 opener->read_port.mp_Flags = PA_IGNORE;
277 NewList((APTR)&opener->initial_stats);
279 for(i = 0; i < 2; i++)
280 opener->rx_function = (APTR)GetTagData(rx_tags[i],
281 (UPINT)opener->rx_function, tag_list);
282 for(i = 0; i < 3; i++)
283 opener->tx_function = (APTR)GetTagData(tx_tags[i],
284 (UPINT)opener->tx_function, tag_list);
286 opener->filter_hook =
287 (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL, tag_list);
288 opener->dma_tx_function =
289 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
291 Disable();
292 AddTail((APTR)&unit->openers, (APTR)opener);
293 Enable();
296 /* Back out if anything went wrong */
298 if(error != 0)
299 DevClose(request, base);
301 /* Return */
303 request->ios2_Req.io_Error = error;
304 return error;
309 /****i* intelpro100.device/DevClose ****************************************
311 * NAME
312 * DevClose
314 * SYNOPSIS
315 * seg_list = DevClose(request)
317 * APTR DevClose(struct IOSana2Req *);
319 ****************************************************************************
323 APTR DevClose(REG(a1, struct IOSana2Req *request),
324 REG(BASE_REG, struct DevBase *base))
326 struct DevUnit *unit;
327 APTR seg_list;
328 struct Opener *opener;
330 /* Free buffer-management resources */
332 opener = (APTR)request->ios2_BufferManagement;
333 if(opener != NULL)
335 Disable();
336 Remove((APTR)opener);
337 Enable();
338 FreeVec(opener);
341 /* Delete the unit if it's no longer in use */
343 unit = (APTR)request->ios2_Req.io_Unit;
344 if(unit != NULL)
346 if((--unit->open_count) == 0)
348 Remove((APTR)unit);
349 switch(unit->bus)
351 case PCI_BUS:
352 DeletePCIUnit(unit, base);
357 /* Expunge the device if a delayed expunge is pending */
359 seg_list = NULL;
361 if((--base->device.dd_Library.lib_OpenCnt) == 0)
363 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
364 seg_list = DevExpunge(base);
367 return seg_list;
372 /****i* intelpro100.device/DevExpunge **************************************
374 * NAME
375 * DevExpunge
377 * SYNOPSIS
378 * seg_list = DevExpunge()
380 * APTR DevExpunge(VOID);
382 ****************************************************************************
386 APTR DevExpunge(REG(BASE_REG, struct DevBase *base))
388 APTR seg_list;
390 if(base->device.dd_Library.lib_OpenCnt == 0)
392 seg_list = base->seg_list;
393 Remove((APTR)base);
394 DeleteDevice(base);
396 else
398 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
399 seg_list = NULL;
402 return seg_list;
407 /****i* intelpro100.device/DevReserved *************************************
409 * NAME
410 * DevReserved
412 * SYNOPSIS
413 * result = DevReserved()
415 * APTR DevReserved(VOID);
417 ****************************************************************************
421 APTR DevReserved()
423 return NULL;
428 /****i* intelpro100.device/DevBeginIO **************************************
430 * NAME
431 * DevBeginIO
433 * SYNOPSIS
434 * DevBeginIO(request)
436 * VOID DevBeginIO(struct IORequest *);
438 ****************************************************************************
442 VOID DevBeginIO(REG(a1, struct IOSana2Req *request),
443 REG(BASE_REG, struct DevBase *base))
445 struct DevUnit *unit;
447 request->ios2_Req.io_Error = 0;
448 unit = (APTR)request->ios2_Req.io_Unit;
450 if(AttemptSemaphore(&unit->access_lock))
451 ServiceRequest(request, base);
452 else
453 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
455 return;
460 /****i* intelpro100.device/DevAbortIO **************************************
462 * NAME
463 * DevAbortIO -- Try to stop a request.
465 * SYNOPSIS
466 * DevAbortIO(request)
468 * VOID DevAbortIO(struct IOSana2Req *);
470 * FUNCTION
471 * Do our best to halt the progress of a request.
473 ****************************************************************************
475 * Disable() used instead of a semaphore because device uses interrupts.
479 VOID DevAbortIO(REG(a1, struct IOSana2Req *request),
480 REG(BASE_REG, struct DevBase *base))
482 Disable();
483 if(request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE &&
484 (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
486 Remove((APTR)request);
487 request->ios2_Req.io_Error = IOERR_ABORTED;
488 request->ios2_WireError = S2WERR_GENERIC_ERROR;
489 ReplyMsg((APTR)request);
491 Enable();
493 return;
498 /****i* intelpro100.device/DeleteDevice ************************************
500 * NAME
501 * DeleteDevice
503 * SYNOPSIS
504 * DeleteDevice()
506 * VOID DeleteDevice(VOID);
508 ****************************************************************************
512 VOID DeleteDevice(struct DevBase *base)
514 UWORD neg_size, pos_size;
516 /* Close devices */
518 CloseDevice((APTR)&base->timer_request);
520 /* Close libraries */
522 if(base->openpci_base != NULL)
523 CloseLibrary(base->openpci_base);
524 if(base->powerpci_base != NULL)
525 CloseLibrary(base->powerpci_base);
526 if(base->prometheus_base != NULL)
527 CloseLibrary(base->prometheus_base);
528 if(base->utility_base != NULL)
529 CloseLibrary((APTR)base->utility_base);
531 /* Free device's memory */
533 neg_size = base->device.dd_Library.lib_NegSize;
534 pos_size = base->device.dd_Library.lib_PosSize;
535 FreeMem((UBYTE *)base - neg_size, pos_size + neg_size);
537 return;
542 /****i* intelpro100.device/GetUnit *****************************************
544 * NAME
545 * GetUnit -- Get a unit by number.
547 * SYNOPSIS
548 * unit = GetUnit(unit_num)
550 * struct DevUnit *GetUnit(ULONG);
552 ****************************************************************************
556 static struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
558 struct DevUnit *unit;
559 ULONG pci_limit;
561 pci_limit = GetPCICount(base);
563 if(unit_num < pci_limit)
564 unit = GetPCIUnit(unit_num, base);
565 else
566 unit = NULL;
568 return unit;