Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / devs / networks / intelpro100 / device.c
blobf73ce3b38a0a7d0d8aaf52045280397f7bfbbe49
1 /*
3 Copyright (C) 2000-2005 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 "pci_protos.h"
36 #include "request_protos.h"
39 /* Private prototypes */
41 static struct DevBase *DevInit(REG(d0, struct DevBase *dev_base),
42 REG(a0, APTR seg_list), REG(BASE_REG, struct DevBase *base));
43 static BYTE DevOpen(REG(a1, struct IOSana2Req *request),
44 REG(d0, ULONG unit_num), REG(d1, ULONG flags),
45 REG(BASE_REG, struct DevBase *base));
46 static APTR DevClose(REG(a1, struct IOSana2Req *request),
47 REG(BASE_REG, struct DevBase *base));
48 static APTR DevExpunge(REG(BASE_REG, struct DevBase *base));
49 static APTR DevReserved();
50 static VOID DevBeginIO(REG(a1, struct IOSana2Req *request),
51 REG(BASE_REG, struct DevBase *base));
52 static VOID DevAbortIO(REG(a1, struct IOSana2Req *request),
53 REG(BASE_REG, struct DevBase *base));
54 static VOID DeleteDevice(struct DevBase *base);
55 static struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base);
57 /* extern const APTR vectors[]; */
58 extern const APTR init_table[];
61 /* Return an error immediately if someone tries to run the device */
63 LONG Main()
65 return -1;
69 const TEXT device_name[] = DEVICE_NAME;
70 static const TEXT version_string[] =
71 DEVICE_NAME " " STR(VERSION) "." STR(REVISION) " (" DATE ")\n";
72 static const TEXT utility_name[] = UTILITYNAME;
73 static const TEXT prometheus_name[] = "prometheus.library";
74 static const TEXT powerpci_name[] = "powerpci.library";
75 static const TEXT timer_name[] = TIMERNAME;
78 const struct Resident rom_tag =
80 RTC_MATCHWORD,
81 (struct Resident *)&rom_tag,
82 (APTR)(&rom_tag + 1),
83 RTF_AUTOINIT,
84 VERSION,
85 NT_DEVICE,
87 (STRPTR)device_name,
88 (STRPTR)version_string,
89 (APTR)init_table
93 static const APTR vectors[] =
95 (APTR)DevOpen,
96 (APTR)DevClose,
97 (APTR)DevExpunge,
98 (APTR)DevReserved,
99 (APTR)DevBeginIO,
100 (APTR)DevAbortIO,
101 (APTR)-1
105 #ifdef __MORPHOS__
106 #pragma pack(2)
107 #endif
108 static const struct
110 SMALLINITBYTEDEF(type);
111 SMALLINITPINTDEF(name);
112 SMALLINITBYTEDEF(flags);
113 SMALLINITWORDDEF(version);
114 SMALLINITWORDDEF(revision);
115 SMALLINITPINTDEF(id_string);
116 INITENDDEF;
118 init_data =
120 SMALLINITBYTE(OFFSET(Node, ln_Type), NT_DEVICE),
121 SMALLINITPINT(OFFSET(Node, ln_Name), device_name),
122 SMALLINITBYTE(OFFSET(Library, lib_Flags), LIBF_SUMUSED | LIBF_CHANGED),
123 SMALLINITWORD(OFFSET(Library, lib_Version), VERSION),
124 SMALLINITWORD(OFFSET(Library, lib_Revision), REVISION),
125 SMALLINITPINT(OFFSET(Library, lib_IdString), version_string),
126 INITEND
128 #ifdef __MORPHOS__
129 #pragma pack()
130 #endif
133 const APTR init_table[] =
135 (APTR)sizeof(struct DevBase),
136 (APTR)vectors,
137 (APTR)&init_data,
138 (APTR)DevInit
142 static const ULONG rx_tags[] =
144 S2_CopyToBuff,
145 S2_CopyToBuff16,
149 static const ULONG tx_tags[] =
151 S2_CopyFromBuff,
152 S2_CopyFromBuff16,
153 S2_CopyFromBuff32
158 /****i* intelpro100.device/DevInit *****************************************
160 * NAME
161 * DevInit
163 * SYNOPSIS
164 * dev_base = DevInit(dev_base, seg_list)
166 * struct DevBase *DevInit(struct DevBase *, APTR);
168 ****************************************************************************
172 static struct DevBase *DevInit(REG(d0, struct DevBase *dev_base),
173 REG(a0, APTR seg_list), REG(BASE_REG, struct DevBase *base))
175 BOOL success = TRUE;
177 /* Initialise base structure */
179 dev_base->sys_base = (APTR)base;
180 base = dev_base;
181 base->seg_list = seg_list;
182 NewList((APTR)(&base->pci_units));
184 /* Open libraries, resources and devices */
186 base->utility_base = (APTR)OpenLibrary(utility_name, UTILITY_VERSION);
187 base->prometheus_base = OpenLibrary(prometheus_name, PROMETHEUS_VERSION);
188 if(base->prometheus_base == NULL)
189 base->powerpci_base = OpenLibrary(powerpci_name, POWERPCI_VERSION);
190 #ifdef __MORPHOS__
191 base->openpci_base = OpenLibrary(openpci_name, OPENPCI_VERSION);
192 #endif
194 if(base->utility_base == NULL || base->prometheus_base == NULL
195 && base->powerpci_base == NULL && base->openpci_base == NULL)
196 success = FALSE;
198 /* if(OpenDevice(timer_name, UNIT_ECLOCK, (APTR)&base->timer_request, 0)*/
199 if(OpenDevice(timer_name, UNIT_VBLANK, (APTR)&base->timer_request, 0)
200 != 0)
201 success = FALSE;
203 #ifdef __MORPHOS__
204 base->wrapper_int_code = (APTR)&int_trap;
205 #endif
207 if(!success)
209 DeleteDevice(base);
210 base = NULL;
213 return base;
218 /****i* intelpro100.device/DevOpen *****************************************
220 * NAME
221 * DevOpen
223 * SYNOPSIS
224 * error = DevOpen(request, unit_num, flags)
226 * BYTE DevOpen(struct IOSana2Req *, ULONG, ULONG);
228 ****************************************************************************
232 static BYTE DevOpen(REG(a1, struct IOSana2Req *request),
233 REG(d0, ULONG unit_num), REG(d1, ULONG flags),
234 REG(BASE_REG, struct DevBase *base))
236 struct DevUnit *unit;
237 BYTE error = 0;
238 struct Opener *opener;
239 struct TagItem *tag_list;
240 UWORD i;
242 base->device.dd_Library.lib_OpenCnt++;
243 base->device.dd_Library.lib_Flags &= ~LIBF_DELEXP;
245 request->ios2_Req.io_Unit = NULL;
246 tag_list = request->ios2_BufferManagement;
247 request->ios2_BufferManagement = NULL;
249 /* Check request size */
251 if(request->ios2_Req.io_Message.mn_Length < sizeof(struct IOSana2Req))
252 error = IOERR_OPENFAIL;
254 /* Get the requested unit */
256 if(error == 0)
258 request->ios2_Req.io_Unit = (APTR)(unit = GetUnit(unit_num, base));
259 if(unit == NULL)
260 error = IOERR_OPENFAIL;
263 /* Handle device sharing */
265 if(error == 0)
267 if(unit->open_count != 0 && ((unit->flags & UNITF_SHARED) == 0
268 || (flags & SANA2OPF_MINE) != 0))
269 error = IOERR_UNITBUSY;
270 unit->open_count++;
273 if(error == 0)
275 if((flags & SANA2OPF_MINE) == 0)
276 unit->flags |= UNITF_SHARED;
277 else if((flags & SANA2OPF_PROM) != 0)
278 unit->flags |= UNITF_PROM;
280 /* Set up buffer-management structure and get hooks */
282 request->ios2_BufferManagement = opener =
283 AllocVec(sizeof(struct Opener), MEMF_PUBLIC | MEMF_CLEAR);
284 if(opener == NULL)
285 error = IOERR_OPENFAIL;
288 if(error == 0)
290 NewList(&opener->read_port.mp_MsgList);
291 opener->read_port.mp_Flags = PA_IGNORE;
292 NewList((APTR)&opener->initial_stats);
294 for(i = 0; i < 2; i++)
295 opener->rx_function = (APTR)GetTagData(rx_tags[i],
296 (UPINT)opener->rx_function, tag_list);
297 for(i = 0; i < 3; i++)
298 opener->tx_function = (APTR)GetTagData(tx_tags[i],
299 (UPINT)opener->tx_function, tag_list);
301 opener->filter_hook =
302 (APTR)GetTagData(S2_PacketFilter, (UPINT)NULL, tag_list);
303 opener->dma_tx_function =
304 (APTR)GetTagData(S2_DMACopyFromBuff32, (UPINT)NULL, tag_list);
306 Disable();
307 AddTail((APTR)&unit->openers, (APTR)opener);
308 Enable();
311 /* Back out if anything went wrong */
313 if(error != 0)
314 DevClose(request, base);
316 /* Return */
318 request->ios2_Req.io_Error = error;
319 return error;
324 /****i* intelpro100.device/DevClose ****************************************
326 * NAME
327 * DevClose
329 * SYNOPSIS
330 * seg_list = DevClose(request)
332 * APTR DevClose(struct IOSana2Req *);
334 ****************************************************************************
338 static APTR DevClose(REG(a1, struct IOSana2Req *request),
339 REG(BASE_REG, struct DevBase *base))
341 struct DevUnit *unit;
342 APTR seg_list;
343 struct Opener *opener;
345 /* Free buffer-management resources */
347 opener = (APTR)request->ios2_BufferManagement;
348 if(opener != NULL)
350 Disable();
351 Remove((APTR)opener);
352 Enable();
353 FreeVec(opener);
356 /* Delete the unit if it's no longer in use */
358 unit = (APTR)request->ios2_Req.io_Unit;
359 if(unit != NULL)
361 if((--unit->open_count) == 0)
363 Remove((APTR)unit);
364 switch(unit->bus)
366 case PCI_BUS:
367 DeletePCIUnit(unit, base);
372 /* Expunge the device if a delayed expunge is pending */
374 seg_list = NULL;
376 if((--base->device.dd_Library.lib_OpenCnt) == 0)
378 if((base->device.dd_Library.lib_Flags & LIBF_DELEXP) != 0)
379 seg_list = DevExpunge(base);
382 return seg_list;
387 /****i* intelpro100.device/DevExpunge **************************************
389 * NAME
390 * DevExpunge
392 * SYNOPSIS
393 * seg_list = DevExpunge()
395 * APTR DevExpunge(VOID);
397 ****************************************************************************
401 static APTR DevExpunge(REG(BASE_REG, struct DevBase *base))
403 APTR seg_list;
405 if(base->device.dd_Library.lib_OpenCnt == 0)
407 seg_list = base->seg_list;
408 Remove((APTR)base);
409 DeleteDevice(base);
411 else
413 base->device.dd_Library.lib_Flags |= LIBF_DELEXP;
414 seg_list = NULL;
417 return seg_list;
422 /****i* intelpro100.device/DevReserved *************************************
424 * NAME
425 * DevReserved
427 * SYNOPSIS
428 * result = DevReserved()
430 * APTR DevReserved(VOID);
432 ****************************************************************************
436 static APTR DevReserved()
438 return NULL;
443 /****i* intelpro100.device/DevBeginIO **************************************
445 * NAME
446 * DevBeginIO
448 * SYNOPSIS
449 * DevBeginIO(request)
451 * VOID DevBeginIO(struct IORequest *);
453 ****************************************************************************
457 static VOID DevBeginIO(REG(a1, struct IOSana2Req *request),
458 REG(BASE_REG, struct DevBase *base))
460 struct DevUnit *unit;
462 request->ios2_Req.io_Error = 0;
463 unit = (APTR)request->ios2_Req.io_Unit;
465 if(AttemptSemaphore(&unit->access_lock))
466 ServiceRequest(request, base);
467 else
468 PutRequest(unit->request_ports[GENERAL_QUEUE], (APTR)request, base);
470 return;
475 /****i* intelpro100.device/DevAbortIO **************************************
477 * NAME
478 * DevAbortIO -- Try to stop a request.
480 * SYNOPSIS
481 * DevAbortIO(request)
483 * VOID DevAbortIO(struct IOSana2Req *);
485 * FUNCTION
486 * Do our best to halt the progress of a request.
488 ****************************************************************************
490 * Disable() used instead of a semaphore because device uses interrupts.
494 static VOID DevAbortIO(REG(a1, struct IOSana2Req *request),
495 REG(BASE_REG, struct DevBase *base))
497 struct DevUnit *unit;
499 unit = (APTR)request->ios2_Req.io_Unit;
501 Disable();
502 if(request->ios2_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE &&
503 (request->ios2_Req.io_Flags & IOF_QUICK) == 0)
505 Remove((APTR)request);
506 request->ios2_Req.io_Error = IOERR_ABORTED;
507 request->ios2_WireError = S2WERR_GENERIC_ERROR;
508 ReplyMsg((APTR)request);
510 Enable();
512 return;
517 /****i* intelpro100.device/DeleteDevice ************************************
519 * NAME
520 * DeleteDevice
522 * SYNOPSIS
523 * DeleteDevice()
525 * VOID DeleteDevice(VOID);
527 ****************************************************************************
531 VOID DeleteDevice(struct DevBase *base)
533 UWORD neg_size, pos_size;
535 /* Close devices */
537 CloseDevice((APTR)&base->timer_request);
539 /* Close libraries */
541 if(base->openpci_base != NULL)
542 CloseLibrary(base->openpci_base);
543 if(base->powerpci_base != NULL)
544 CloseLibrary(base->powerpci_base);
545 if(base->prometheus_base != NULL)
546 CloseLibrary(base->prometheus_base);
547 if(base->utility_base != NULL)
548 CloseLibrary((APTR)base->utility_base);
550 /* Free device's memory */
552 neg_size = base->device.dd_Library.lib_NegSize;
553 pos_size = base->device.dd_Library.lib_PosSize;
554 FreeMem((UBYTE *)base - neg_size, pos_size + neg_size);
556 return;
561 /****i* intelpro100.device/GetUnit *****************************************
563 * NAME
564 * GetUnit -- Get a unit by number.
566 * SYNOPSIS
567 * unit = GetUnit(unit_num)
569 * struct DevUnit *GetUnit(ULONG);
571 ****************************************************************************
575 static struct DevUnit *GetUnit(ULONG unit_num, struct DevBase *base)
577 struct DevUnit *unit;
578 ULONG pci_limit;
580 pci_limit = GetPCICount(base);
582 if(unit_num < pci_limit)
583 unit = GetPCIUnit(unit_num, base);
584 else
585 unit = NULL;
587 return unit;