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,
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>
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 */
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
[] =
75 SMALLINITBYTEDEF(type
);
76 SMALLINITPINTDEF(name
);
77 SMALLINITBYTEDEF(flags
);
78 SMALLINITWORDDEF(version
);
79 SMALLINITWORDDEF(revision
);
80 SMALLINITPINTDEF(id_string
);
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
),
95 static const APTR init_table
[] =
97 (APTR
)sizeof(struct DevBase
),
104 const struct Resident rom_tag
=
107 (struct Resident
*)&rom_tag
,
108 (APTR
)(&rom_tag
+ 1),
114 (STRPTR
)version_string
,
119 static const ULONG rx_tags
[] =
126 static const ULONG tx_tags
[] =
135 /****i* rhine.device/DevInit ***********************************************
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
))
154 /* Initialise base structure */
156 dev_base
->sys_base
= (APTR
)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
)
169 if(OpenDevice(timer_name
, UNIT_ECLOCK
, (APTR
)&base
->timer_request
, 0)
184 /****i* rhine.device/DevOpen ***********************************************
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
;
204 struct Opener
*opener
;
205 struct TagItem
*tag_list
;
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 */
224 request
->ios2_Req
.io_Unit
= (APTR
)(unit
= GetUnit(unit_num
, base
));
226 error
= IOERR_OPENFAIL
;
229 /* Handle device sharing */
233 if(unit
->open_count
!= 0 && ((unit
->flags
& UNITF_SHARED
) == 0
234 || (flags
& SANA2OPF_MINE
) != 0))
235 error
= IOERR_UNITBUSY
;
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
);
251 error
= IOERR_OPENFAIL
;
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
,
271 opener
->dma_tx_function
=
272 (APTR
)GetTagData(S2_DMACopyFromBuff32
, (UPINT
)NULL
, tag_list
);
275 AddTail((APTR
)&unit
->openers
, (APTR
)opener
);
279 /* Back out if anything went wrong */
282 CloseUnit(request
, base
);
286 request
->ios2_Req
.io_Error
= error
;
292 /****i* rhine.device/DevClose **********************************************
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
;
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
);
328 /****i* rhine.device/DevExpunge ********************************************
334 * seg_list = DevExpunge()
336 * APTR DevExpunge(VOID);
338 ****************************************************************************
342 APTR
DevExpunge(REG(BASE_REG
, struct DevBase
*base
))
346 if(base
->device
.dd_Library
.lib_OpenCnt
== 0)
348 seg_list
= base
->seg_list
;
354 base
->device
.dd_Library
.lib_Flags
|= LIBF_DELEXP
;
363 /****i* rhine.device/DevReserved *******************************************
369 * result = DevReserved()
371 * APTR DevReserved(VOID);
373 ****************************************************************************
384 /****i* rhine.device/DevBeginIO ********************************************
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
);
409 PutRequest(unit
->request_ports
[GENERAL_QUEUE
], (APTR
)request
, base
);
416 /****i* rhine.device/DevAbortIO ********************************************
419 * DevAbortIO -- Try to stop a request.
422 * DevAbortIO(request)
424 * VOID DevAbortIO(struct IOSana2Req *);
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
))
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
);
452 /****i* rhine.device/DeleteDevice ******************************************
460 * VOID DeleteDevice(VOID);
462 ****************************************************************************
466 VOID
DeleteDevice(struct DevBase
*base
)
468 UWORD neg_size
, pos_size
;
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
);
492 /****i* rhine.device/CloseUnit *********************************************
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
;
518 Remove((APTR
)opener
);
523 /* Delete the unit if it's no longer in use */
525 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
528 if((--unit
->open_count
) == 0)
534 DeletePCIUnit(unit
, base
);
545 /****i* rhine.device/GetUnit ***********************************************
548 * GetUnit -- Get a unit by number.
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
;
564 pci_limit
= GetPCICount(base
);
566 if(unit_num
< pci_limit
)
567 unit
= GetPCIUnit(unit_num
, base
);
576 /****i* rhine.device/WrapInt ***********************************************
581 ****************************************************************************
585 BOOL
WrapInt(struct Interrupt
*interrupt
, struct DevBase
*base
)
590 if(base
->wrapper_int_code
!= NULL
)
592 int_data
= AllocMem(2 * sizeof(APTR
), MEMF_PUBLIC
| MEMF_CLEAR
);
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
;
609 /****i* rhine.device/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
));