revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / networks / rhine / device.c
blobcd33eed8116140b6ed867e5041b7010aeae6bcb8
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 <utility/utility.h>
27 #include "initializers.h"
29 #include <proto/exec.h>
30 #include <clib/alib_protos.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);
45 /* Return an error immediately if someone tries to run the device */
47 LONG Main()
49 return -1;
53 const TEXT device_name[] = DEVICE_NAME;
54 const TEXT version_string[] =
55 DEVICE_NAME " " STR(VERSION) "." STR(REVISION) " (" DATE ")\n";
56 const TEXT utility_name[] = UTILITYNAME;
57 static const TEXT prometheus_name[] = "prometheus.library";
58 const TEXT timer_name[] = TIMERNAME;
61 static const APTR vectors[] =
63 (APTR)DevOpen,
64 (APTR)DevClose,
65 (APTR)DevExpunge,
66 (APTR)DevReserved,
67 (APTR)DevBeginIO,
68 (APTR)DevAbortIO,
69 (APTR)-1
73 const struct
75 SMALLINITBYTEDEF(type);
76 SMALLINITPINTDEF(name);
77 SMALLINITBYTEDEF(flags);
78 SMALLINITWORDDEF(version);
79 SMALLINITWORDDEF(revision);
80 SMALLINITPINTDEF(id_string);
81 INITENDDEF;
83 init_data =
85 SMALLINITBYTE(OFFSET(Node, ln_Type), NT_DEVICE),
86 SMALLINITPINT(OFFSET(Node, ln_Name), device_name),
87 SMALLINITBYTE(OFFSET(Library, lib_Flags), LIBF_SUMUSED | LIBF_CHANGED),
88 SMALLINITWORD(OFFSET(Library, lib_Version), VERSION),
89 SMALLINITWORD(OFFSET(Library, lib_Revision), REVISION),
90 SMALLINITPINT(OFFSET(Library, lib_IdString), version_string),
91 INITEND
95 static const APTR init_table[] =
97 (APTR)sizeof(struct DevBase),
98 (APTR)vectors,
99 (APTR)&init_data,
100 (APTR)DevInit
104 const struct Resident rom_tag =
106 RTC_MATCHWORD,
107 (struct Resident *)&rom_tag,
108 (APTR)(&rom_tag + 1),
109 RTF_AUTOINIT,
110 VERSION,
111 NT_DEVICE,
113 (STRPTR)device_name,
114 (STRPTR)version_string,
115 (APTR)init_table
119 static const ULONG rx_tags[] =
121 S2_CopyToBuff,
122 S2_CopyToBuff16,
126 static const ULONG tx_tags[] =
128 S2_CopyFromBuff,
129 S2_CopyFromBuff16,
130 S2_CopyFromBuff32
135 /****i* rhine.device/DevInit ***********************************************
137 * NAME
138 * DevInit
140 * SYNOPSIS
141 * dev_base = DevInit(dev_base, seg_list)
143 * struct DevBase *DevInit(struct DevBase *, APTR);
145 ****************************************************************************
149 struct DevBase *DevInit(REG(d0, struct DevBase *dev_base),
150 REG(a0, APTR seg_list), REG(BASE_REG, struct DevBase *base))
152 BOOL success = TRUE;
154 /* Initialise base structure */
156 dev_base->sys_base = (APTR)base;
157 base = dev_base;
158 base->seg_list = seg_list;
159 NewList((APTR)(&base->pci_units));
161 /* Open libraries, resources and devices */
163 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
164 base->prometheus_base = OpenLibrary(prometheus_name, PROMETHEUS_VERSION);
166 if(base->utility_base == NULL)
167 success = FALSE;
169 if(OpenDevice(timer_name, UNIT_ECLOCK, (APTR)&base->timer_request, 0)
170 != 0)
171 success = FALSE;
173 if(!success)
175 DeleteDevice(base);
176 base = NULL;
179 return base;
184 /****i* rhine.device/DevOpen ***********************************************
186 * NAME
187 * DevOpen
189 * SYNOPSIS
190 * error = DevOpen(request, unit_num, flags)
192 * BYTE DevOpen(struct IOSana2Req *, ULONG, ULONG);
194 ****************************************************************************
198 BYTE DevOpen(REG(a1, struct IOSana2Req *request),
199 REG(d0, ULONG unit_num), REG(d1, ULONG flags),
200 REG(BASE_REG, struct DevBase *base))
202 struct DevUnit *unit;
203 BYTE error = 0;
204 struct Opener *opener;
205 struct TagItem *tag_list;
206 UWORD i;
208 base->device.dd_Library.lib_OpenCnt++;
209 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
211 request->ios2_Req.io_Unit = NULL;
212 tag_list = request->ios2_BufferManagement;
213 request->ios2_BufferManagement = NULL;
215 /* Check request size */
217 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
218 error = IOERR_OPENFAIL;
220 /* Get the requested unit */
222 if(error == 0)
224 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
225 if(unit == NULL)
226 error = IOERR_OPENFAIL;
229 /* Handle device sharing */
231 if(error == 0)
233 if(unit->open_count != 0 && ((unit->flags & UNITF_SHARED) == 0
234 || (flags & SANA2OPF_MINE) != 0))
235 error = IOERR_UNITBUSY;
236 unit->open_count++;
239 if(error == 0)
241 if((flags & SANA2OPF_MINE) == 0)
242 unit->flags |= UNITF_SHARED;
243 else if((flags & SANA2OPF_PROM) != 0)
244 unit->flags |= UNITF_PROM;
246 /* Set up buffer-management structure and get hooks */
248 request->ios2_BufferManagement = opener =
249 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
250 if(opener == NULL)
251 error = IOERR_OPENFAIL;
254 if(error == 0)
256 NewList(&opener->read_port.mp_MsgList);
257 opener->read_port.mp_Flags = PA_IGNORE;
258 NewList(&opener->mgmt_port.mp_MsgList);
259 opener->mgmt_port.mp_Flags = PA_IGNORE;
260 NewList((APTR)&opener->initial_stats);
262 for(i = 0; i < 2; i++)
263 opener->rx_function = (APTR)GetTagData(rx_tags[i],
264 (UPINT)opener->rx_function, tag_list);
265 for(i = 0; i < 3; i++)
266 opener->tx_function = (APTR)GetTagData(tx_tags[i],
267 (UPINT)opener->tx_function, tag_list);
269 opener->filter_hook = (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL,
270 tag_list);
271 opener->dma_tx_function =
272 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
274 Disable();
275 AddTail((APTR)&unit->openers, (APTR)opener);
276 Enable();
279 /* Back out if anything went wrong */
281 if(error != 0)
282 CloseUnit(request, base);
284 /* Return */
286 request->ios2_Req.io_Error = error;
287 return error;
292 /****i* rhine.device/DevClose **********************************************
294 * NAME
295 * DevClose
297 * SYNOPSIS
298 * seg_list = DevClose(request)
300 * APTR DevClose(struct IOSana2Req *);
302 ****************************************************************************
306 APTR DevClose(REG(a1, struct IOSana2Req *request),
307 REG(BASE_REG, struct DevBase *base))
309 APTR seg_list = NULL;
311 /* Close the unit */
313 CloseUnit(request, base);
315 /* Expunge the device if a delayed expunge is pending */
317 if(base->device.dd_Library.lib_OpenCnt == 0)
319 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
320 seg_list = DevExpunge(base);
323 return seg_list;
328 /****i* rhine.device/DevExpunge ********************************************
330 * NAME
331 * DevExpunge
333 * SYNOPSIS
334 * seg_list = DevExpunge()
336 * APTR DevExpunge(VOID);
338 ****************************************************************************
342 APTR DevExpunge(REG(BASE_REG, struct DevBase *base))
344 APTR seg_list;
346 if(base->device.dd_Library.lib_OpenCnt == 0)
348 seg_list = base->seg_list;
349 Remove((APTR)base);
350 DeleteDevice(base);
352 else
354 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
355 seg_list = NULL;
358 return seg_list;
363 /****i* rhine.device/DevReserved *******************************************
365 * NAME
366 * DevReserved
368 * SYNOPSIS
369 * result = DevReserved()
371 * APTR DevReserved(VOID);
373 ****************************************************************************
377 APTR DevReserved()
379 return NULL;
384 /****i* rhine.device/DevBeginIO ********************************************
386 * NAME
387 * DevBeginIO
389 * SYNOPSIS
390 * DevBeginIO(request)
392 * VOID DevBeginIO(struct IORequest *);
394 ****************************************************************************
398 VOID DevBeginIO(REG(a1, struct IOSana2Req *request),
399 REG(BASE_REG, struct DevBase *base))
401 struct DevUnit *unit;
403 request->ios2_Req.io_Error = 0;
404 unit = (APTR)request->ios2_Req.io_Unit;
406 if(AttemptSemaphore(&unit->access_lock))
407 ServiceRequest(request, base);
408 else
409 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
411 return;
416 /****i* rhine.device/DevAbortIO ********************************************
418 * NAME
419 * DevAbortIO -- Try to stop a request.
421 * SYNOPSIS
422 * DevAbortIO(request)
424 * VOID DevAbortIO(struct IOSana2Req *);
426 * FUNCTION
427 * Do our best to halt the progress of a request.
429 ****************************************************************************
433 VOID DevAbortIO(REG(a1, struct IOSana2Req *request),
434 REG(BASE_REG, struct DevBase *base))
436 Disable();
437 if(request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE &&
438 (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
440 Remove((APTR)request);
441 request->ios2_Req.io_Error = IOERR_ABORTED;
442 request->ios2_WireError = S2WERR_GENERIC_ERROR;
443 ReplyMsg((APTR)request);
445 Enable();
447 return;
452 /****i* rhine.device/DeleteDevice ******************************************
454 * NAME
455 * DeleteDevice
457 * SYNOPSIS
458 * DeleteDevice()
460 * VOID DeleteDevice(VOID);
462 ****************************************************************************
466 VOID DeleteDevice(struct DevBase *base)
468 UWORD neg_size, pos_size;
470 /* Close devices */
472 CloseDevice((APTR)&base->timer_request);
474 /* Close libraries */
476 if(base->prometheus_base != NULL)
477 CloseLibrary(base->prometheus_base);
478 if(base->utility_base != NULL)
479 CloseLibrary((APTR)base->utility_base);
481 /* Free device's memory */
483 neg_size = base->device.dd_Library.lib_NegSize;
484 pos_size = base->device.dd_Library.lib_PosSize;
485 FreeMem((UBYTE *)base - neg_size, pos_size + neg_size);
487 return;
492 /****i* rhine.device/CloseUnit *********************************************
494 * NAME
495 * CloseUnit
497 * SYNOPSIS
498 * CloseUnit(request)
500 * VOID CloseUnit(struct IOSana2Req *);
502 ****************************************************************************
506 VOID CloseUnit(struct IOSana2Req *request, struct DevBase *base)
508 struct DevUnit *unit;
509 struct Opener *opener;
511 /* Decrement device usage count and free buffer-management resources */
513 base->device.dd_Library.lib_OpenCnt--;
514 opener = (APTR)request->ios2_BufferManagement;
515 if(opener != NULL)
517 Disable();
518 Remove((APTR)opener);
519 Enable();
520 FreeVec(opener);
523 /* Delete the unit if it's no longer in use */
525 unit = (APTR)request->ios2_Req.io_Unit;
526 if(unit != NULL)
528 if((--unit->open_count) == 0)
530 Remove((APTR)unit);
531 switch(unit->bus)
533 case PCI_BUS:
534 DeletePCIUnit(unit, base);
535 break;
540 return;
545 /****i* rhine.device/GetUnit ***********************************************
547 * NAME
548 * GetUnit -- Get a unit by number.
550 * SYNOPSIS
551 * unit = GetUnit(unit_num)
553 * struct DevUnit *GetUnit(ULONG);
555 ****************************************************************************
559 struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
561 struct DevUnit *unit;
562 ULONG pci_limit;
564 pci_limit = GetPCICount(base);
566 if(unit_num < pci_limit)
567 unit = GetPCIUnit(unit_num, base);
568 else
569 unit = NULL;
571 return unit;
576 /****i* rhine.device/WrapInt ***********************************************
578 * NAME
579 * WrapInt
581 ****************************************************************************
585 BOOL WrapInt(struct Interrupt *interrupt, struct DevBase *base)
587 BOOL success = TRUE;
588 APTR *int_data;
590 if(base->wrapper_int_code != NULL)
592 int_data = AllocMem(2 * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
593 if(int_data != NULL)
595 int_data[0] = interrupt->is_Code;
596 int_data[1] = interrupt->is_Data;
597 interrupt->is_Code = base->wrapper_int_code;
598 interrupt->is_Data = int_data;
600 else
601 success = FALSE;
604 return success;
609 /****i* rhine.device/UnwrapInt *********************************************
611 * NAME
612 * UnwrapInt
614 ****************************************************************************
618 VOID UnwrapInt(struct Interrupt *interrupt, struct DevBase *base)
620 if(interrupt->is_Code == base->wrapper_int_code)
621 FreeMem(interrupt->is_Data, 2 * sizeof(APTR));
623 return;