3 Copyright (C) 2000-2006 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,
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 <clib/alib_protos.h>
32 #include <proto/utility.h>
36 #include "device_protos.h"
37 #include "pci_protos.h"
38 #include "pccard_protos.h"
39 #include "request_protos.h"
42 /* Private prototypes */
44 static struct DevBase
*DevInit(REG(d0
, struct DevBase
*dev_base
),
45 REG(a0
, APTR seg_list
), REG(BASE_REG
, struct DevBase
*base
));
46 static APTR
DevExpunge(REG(BASE_REG
, struct DevBase
*base
));
47 static APTR
DevReserved();
48 static VOID
DeleteDevice(struct DevBase
*base
);
51 /* Return an error immediately if someone tries to run the device */
59 const TEXT device_name
[] = DEVICE_NAME
;
60 const TEXT version_string
[] =
61 DEVICE_NAME
" " STR(VERSION
) "." STR(REVISION
) " (" DATE
")\n";
62 const TEXT utility_name
[] = UTILITYNAME
;
63 static const TEXT prometheus_name
[] = "prometheus.library";
64 static const TEXT powerpci_name
[] = "powerpci.library";
65 const TEXT pccard_name
[] = "pccard.library";
66 const TEXT card_name
[] = "card.resource";
67 const TEXT timer_name
[] = TIMERNAME
;
70 static const APTR vectors
[] =
87 SMALLINITBYTEDEF(type
);
88 SMALLINITPINTDEF(name
);
89 SMALLINITBYTEDEF(flags
);
90 SMALLINITWORDDEF(version
);
91 SMALLINITWORDDEF(revision
);
92 SMALLINITPINTDEF(id_string
);
97 SMALLINITBYTE(OFFSET(Node
, ln_Type
), NT_DEVICE
),
98 SMALLINITPINT(OFFSET(Node
, ln_Name
), device_name
),
99 SMALLINITBYTE(OFFSET(Library
, lib_Flags
), LIBF_SUMUSED
| LIBF_CHANGED
),
100 SMALLINITWORD(OFFSET(Library
, lib_Version
), VERSION
),
101 SMALLINITWORD(OFFSET(Library
, lib_Revision
), REVISION
),
102 SMALLINITPINT(OFFSET(Library
, lib_IdString
), version_string
),
110 static const APTR init_table
[] =
112 (APTR
)sizeof(struct DevBase
),
119 const struct Resident rom_tag
=
122 (struct Resident
*)&rom_tag
,
123 (APTR
)(&rom_tag
+ 1),
129 (STRPTR
)version_string
,
134 static const ULONG rx_tags
[] =
141 static const ULONG tx_tags
[] =
150 /****i* etherlink3.device/DevInit ******************************************
156 * dev_base = DevInit(dev_base, seg_list)
158 * struct DevBase *DevInit(struct DevBase *, APTR);
160 ****************************************************************************
164 static struct DevBase
*DevInit(REG(d0
, struct DevBase
*dev_base
),
165 REG(a0
, APTR seg_list
), REG(BASE_REG
, struct DevBase
*base
))
169 /* Initialise base structure */
171 dev_base
->sys_base
= (APTR
)base
;
173 base
->seg_list
= seg_list
;
174 NewList((APTR
)(&base
->pci_units
));
175 NewList((APTR
)(&base
->isa_units
));
176 NewList((APTR
)(&base
->pccard_units
));
178 /* Open libraries, resources and devices */
180 base
->utility_base
= (APTR
)OpenLibrary(utility_name
, UTILITY_VERSION
);
181 base
->prometheus_base
= OpenLibrary(prometheus_name
, PROMETHEUS_VERSION
);
182 if(base
->prometheus_base
== NULL
)
183 base
->powerpci_base
= OpenLibrary(powerpci_name
, POWERPCI_VERSION
);
185 base
->openpci_base
= OpenLibrary(openpci_name
, OPENPCI_VERSION
);
187 base
->pccard_base
= OpenLibrary(pccard_name
, PCCARD_VERSION
);
188 if(base
->pccard_base
!= NULL
)
189 base
->card_base
= OpenResource(card_name
);
191 if(base
->utility_base
== NULL
|| base
->prometheus_base
== NULL
192 && base
->powerpci_base
== NULL
&& base
->openpci_base
== NULL
193 && (base
->pccard_base
== NULL
|| base
->card_base
== NULL
))
196 if(OpenDevice(timer_name
, UNIT_ECLOCK
, (APTR
)&base
->timer_request
, 0)
201 base
->wrapper_int_code
= (APTR
)&int_trap
;
215 /****i* etherlink3.device/DevOpen ******************************************
221 * error = DevOpen(request, unit_num, flags)
223 * BYTE DevOpen(struct IOSana2Req *, ULONG, ULONG);
225 ****************************************************************************
229 BYTE
DevOpen(REG(a1
, struct IOSana2Req
*request
),
230 REG(d0
, ULONG unit_num
), REG(d1
, ULONG flags
),
231 REG(BASE_REG
, struct DevBase
*base
))
233 struct DevUnit
*unit
;
235 struct Opener
*opener
;
236 struct TagItem
*tag_list
;
239 base
->device
.dd_Library
.lib_OpenCnt
++;
240 base
->device
.dd_Library
.lib_Flags
&= ~LIBF_DELEXP
;
242 request
->ios2_Req
.io_Unit
= NULL
;
243 tag_list
= request
->ios2_BufferManagement
;
244 request
->ios2_BufferManagement
= NULL
;
246 /* Check request size */
248 if(request
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
))
249 error
= IOERR_OPENFAIL
;
251 /* Get the requested unit */
255 request
->ios2_Req
.io_Unit
= (APTR
)(unit
= GetUnit(unit_num
, base
));
257 error
= IOERR_OPENFAIL
;
260 /* Handle device sharing */
264 if(unit
->open_count
!= 0 && ((unit
->flags
& UNITF_SHARED
) == 0
265 || (flags
& SANA2OPF_MINE
) != 0))
266 error
= IOERR_UNITBUSY
;
272 if((flags
& SANA2OPF_MINE
) == 0)
273 unit
->flags
|= UNITF_SHARED
;
274 else if((flags
& SANA2OPF_PROM
) != 0)
275 unit
->flags
|= UNITF_PROM
;
277 /* Set up buffer-management structure and get hooks */
279 request
->ios2_BufferManagement
= opener
=
280 AllocVec(sizeof(struct Opener
), MEMF_PUBLIC
| MEMF_CLEAR
);
282 error
= IOERR_OPENFAIL
;
287 NewList(&opener
->read_port
.mp_MsgList
);
288 opener
->read_port
.mp_Flags
= PA_IGNORE
;
289 NewList((APTR
)&opener
->initial_stats
);
291 for(i
= 0; i
< 2; i
++)
292 opener
->rx_function
= (APTR
)GetTagData(rx_tags
[i
],
293 (UPINT
)opener
->rx_function
, tag_list
);
294 for(i
= 0; i
< 3; i
++)
295 opener
->tx_function
= (APTR
)GetTagData(tx_tags
[i
],
296 (UPINT
)opener
->tx_function
, tag_list
);
298 opener
->filter_hook
= (APTR
)GetTagData(S2_PacketFilter
, (UPINT
)NULL
,
300 opener
->dma_tx_function
=
301 (APTR
)GetTagData(S2_DMACopyFromBuff32
, (UPINT
)NULL
, tag_list
);
304 AddTail((APTR
)&unit
->openers
, (APTR
)opener
);
308 /* Back out if anything went wrong */
311 CloseUnit(request
, base
);
315 request
->ios2_Req
.io_Error
= error
;
321 /****i* etherlink3.device/DevClose *****************************************
327 * seg_list = DevClose(request)
329 * APTR DevClose(struct IOSana2Req *);
331 ****************************************************************************
335 APTR
DevClose(REG(a1
, struct IOSana2Req
*request
),
336 REG(BASE_REG
, struct DevBase
*base
))
338 APTR seg_list
= NULL
;
342 CloseUnit(request
, base
);
344 /* Expunge the device if a delayed expunge is pending */
346 if(base
->device
.dd_Library
.lib_OpenCnt
== 0)
348 if((base
->device
.dd_Library
.lib_Flags
& LIBF_DELEXP
) != 0)
349 seg_list
= DevExpunge(base
);
357 /****i* etherlink3.device/DevExpunge ***************************************
363 * seg_list = DevExpunge()
365 * APTR DevExpunge(VOID);
367 ****************************************************************************
371 static APTR
DevExpunge(REG(BASE_REG
, struct DevBase
*base
))
375 if(base
->device
.dd_Library
.lib_OpenCnt
== 0)
377 seg_list
= base
->seg_list
;
383 base
->device
.dd_Library
.lib_Flags
|= LIBF_DELEXP
;
392 /****i* etherlink3.device/DevReserved **************************************
398 * result = DevReserved()
400 * APTR DevReserved(VOID);
402 ****************************************************************************
406 static APTR
DevReserved()
413 /****i* etherlink3.device/DevBeginIO ***************************************
419 * DevBeginIO(request)
421 * VOID DevBeginIO(struct IORequest *);
423 ****************************************************************************
427 VOID
DevBeginIO(REG(a1
, struct IOSana2Req
*request
),
428 REG(BASE_REG
, struct DevBase
*base
))
430 struct DevUnit
*unit
;
432 request
->ios2_Req
.io_Error
= 0;
433 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
435 if(AttemptSemaphore(&unit
->access_lock
))
436 ServiceRequest(request
, base
);
438 PutRequest(unit
->request_ports
[GENERAL_QUEUE
], (APTR
)request
, base
);
445 /****i* etherlink3.device/DevAbortIO ***************************************
448 * DevAbortIO -- Try to stop a request.
451 * DevAbortIO(request)
453 * VOID DevAbortIO(struct IOSana2Req *);
456 * Do our best to halt the progress of a request.
458 ****************************************************************************
460 * Disable() used instead of a semaphore because device uses interrupts.
464 VOID
DevAbortIO(REG(a1
, struct IOSana2Req
*request
),
465 REG(BASE_REG
, struct DevBase
*base
))
467 struct DevUnit
*unit
;
469 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
472 if(request
->ios2_Req
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
&&
473 (request
->ios2_Req
.io_Flags
& IOF_QUICK
) == 0)
475 Remove((APTR
)request
);
476 request
->ios2_Req
.io_Error
= IOERR_ABORTED
;
477 request
->ios2_WireError
= S2WERR_GENERIC_ERROR
;
478 ReplyMsg((APTR
)request
);
487 /****i* etherlink3.device/DeleteDevice *************************************
495 * VOID DeleteDevice(VOID);
497 ****************************************************************************
501 VOID
DeleteDevice(struct DevBase
*base
)
503 UWORD neg_size
, pos_size
;
507 CloseDevice((APTR
)&base
->timer_request
);
509 /* Close libraries */
511 if(base
->openpci_base
!= NULL
)
512 CloseLibrary(base
->openpci_base
);
513 if(base
->pccard_base
!= NULL
)
514 CloseLibrary(base
->pccard_base
);
515 if(base
->powerpci_base
!= NULL
)
516 CloseLibrary(base
->powerpci_base
);
517 if(base
->prometheus_base
!= NULL
)
518 CloseLibrary(base
->prometheus_base
);
519 if(base
->utility_base
!= NULL
)
520 CloseLibrary((APTR
)base
->utility_base
);
522 /* Free device's memory */
524 neg_size
= base
->device
.dd_Library
.lib_NegSize
;
525 pos_size
= base
->device
.dd_Library
.lib_PosSize
;
526 FreeMem((UBYTE
*)base
- neg_size
, pos_size
+ neg_size
);
533 /****i* etherlink3.device/CloseUnit ****************************************
541 * VOID CloseUnit(struct IOSana2Req *);
543 ****************************************************************************
547 VOID
CloseUnit(struct IOSana2Req
*request
, struct DevBase
*base
)
549 struct DevUnit
*unit
;
550 struct Opener
*opener
;
552 /* Free buffer-management resources */
554 base
->device
.dd_Library
.lib_OpenCnt
--;
555 opener
= (APTR
)request
->ios2_BufferManagement
;
559 Remove((APTR
)opener
);
564 /* Delete the unit if it's no longer in use */
566 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
569 if((--unit
->open_count
) == 0)
575 DeletePCIUnit(unit
, base
);
579 DeletePCCardUnit(unit
, base
);
591 /****i* etherlink3.device/GetUnit ******************************************
594 * GetUnit -- Get a unit by number.
597 * unit = GetUnit(unit_num)
599 * struct DevUnit *GetUnit(ULONG);
601 ****************************************************************************
605 struct DevUnit
*GetUnit(ULONG unit_num
, struct DevBase
*base
)
607 struct DevUnit
*unit
;
608 ULONG pci_limit
, pccard_limit
;
610 pci_limit
= GetPCICount(base
);
612 pccard_limit
= pci_limit
+ GetPCCardCount(base
);
615 if(unit_num
< pci_limit
)
616 unit
= GetPCIUnit(unit_num
, base
);
618 else if(unit_num
< pccard_limit
)
619 unit
= GetPCCardUnit(unit_num
- pci_limit
, base
);
629 /****i* etherlink3.device/WrapInt ******************************************
634 ****************************************************************************
638 BOOL
WrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
)
641 #if defined(__amigaos4__) || defined(__MORPHOS__)
644 int_data
= AllocMem(2 * sizeof(APTR
), MEMF_PUBLIC
| MEMF_CLEAR
);
647 int_data
[0] = interrupt
->is_Code
;
648 int_data
[1] = interrupt
->is_Data
;
649 interrupt
->is_Code
= base
->wrapper_int_code
;
650 interrupt
->is_Data
= int_data
;
661 /****i* etherlink3.device/UnwrapInt ****************************************
666 ****************************************************************************
670 VOID
UnwrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
)
672 if(interrupt
->is_Code
== base
->wrapper_int_code
)
673 FreeMem(interrupt
->is_Data
, 2 * sizeof(APTR
));