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,
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>
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 */
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
=
81 (struct Resident
*)&rom_tag
,
88 (STRPTR
)version_string
,
93 static const APTR vectors
[] =
110 SMALLINITBYTEDEF(type
);
111 SMALLINITPINTDEF(name
);
112 SMALLINITBYTEDEF(flags
);
113 SMALLINITWORDDEF(version
);
114 SMALLINITWORDDEF(revision
);
115 SMALLINITPINTDEF(id_string
);
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
),
133 const APTR init_table
[] =
135 (APTR
)sizeof(struct DevBase
),
142 static const ULONG rx_tags
[] =
149 static const ULONG tx_tags
[] =
158 /****i* intelpro100.device/DevInit *****************************************
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
))
177 /* Initialise base structure */
179 dev_base
->sys_base
= (APTR
)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
);
191 base
->openpci_base
= OpenLibrary(openpci_name
, OPENPCI_VERSION
);
194 if(base
->utility_base
== NULL
|| base
->prometheus_base
== NULL
195 && base
->powerpci_base
== NULL
&& base
->openpci_base
== NULL
)
198 /* if(OpenDevice(timer_name, UNIT_ECLOCK, (APTR)&base->timer_request, 0)*/
199 if(OpenDevice(timer_name
, UNIT_VBLANK
, (APTR
)&base
->timer_request
, 0)
204 base
->wrapper_int_code
= (APTR
)&int_trap
;
218 /****i* intelpro100.device/DevOpen *****************************************
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
;
238 struct Opener
*opener
;
239 struct TagItem
*tag_list
;
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 */
258 request
->ios2_Req
.io_Unit
= (APTR
)(unit
= GetUnit(unit_num
, base
));
260 error
= IOERR_OPENFAIL
;
263 /* Handle device sharing */
267 if(unit
->open_count
!= 0 && ((unit
->flags
& UNITF_SHARED
) == 0
268 || (flags
& SANA2OPF_MINE
) != 0))
269 error
= IOERR_UNITBUSY
;
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
);
285 error
= IOERR_OPENFAIL
;
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
);
307 AddTail((APTR
)&unit
->openers
, (APTR
)opener
);
311 /* Back out if anything went wrong */
314 DevClose(request
, base
);
318 request
->ios2_Req
.io_Error
= error
;
324 /****i* intelpro100.device/DevClose ****************************************
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
;
343 struct Opener
*opener
;
345 /* Free buffer-management resources */
347 opener
= (APTR
)request
->ios2_BufferManagement
;
351 Remove((APTR
)opener
);
356 /* Delete the unit if it's no longer in use */
358 unit
= (APTR
)request
->ios2_Req
.io_Unit
;
361 if((--unit
->open_count
) == 0)
367 DeletePCIUnit(unit
, base
);
372 /* Expunge the device if a delayed expunge is pending */
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
);
387 /****i* intelpro100.device/DevExpunge **************************************
393 * seg_list = DevExpunge()
395 * APTR DevExpunge(VOID);
397 ****************************************************************************
401 static APTR
DevExpunge(REG(BASE_REG
, struct DevBase
*base
))
405 if(base
->device
.dd_Library
.lib_OpenCnt
== 0)
407 seg_list
= base
->seg_list
;
413 base
->device
.dd_Library
.lib_Flags
|= LIBF_DELEXP
;
422 /****i* intelpro100.device/DevReserved *************************************
428 * result = DevReserved()
430 * APTR DevReserved(VOID);
432 ****************************************************************************
436 static APTR
DevReserved()
443 /****i* intelpro100.device/DevBeginIO **************************************
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
);
468 PutRequest(unit
->request_ports
[GENERAL_QUEUE
], (APTR
)request
, base
);
475 /****i* intelpro100.device/DevAbortIO **************************************
478 * DevAbortIO -- Try to stop a request.
481 * DevAbortIO(request)
483 * VOID DevAbortIO(struct IOSana2Req *);
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
;
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
);
517 /****i* intelpro100.device/DeleteDevice ************************************
525 * VOID DeleteDevice(VOID);
527 ****************************************************************************
531 VOID
DeleteDevice(struct DevBase
*base
)
533 UWORD neg_size
, pos_size
;
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
);
561 /****i* intelpro100.device/GetUnit *****************************************
564 * GetUnit -- Get a unit by number.
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
;
580 pci_limit
= GetPCICount(base
);
582 if(unit_num
< pci_limit
)
583 unit
= GetPCIUnit(unit_num
, base
);