257 lines
8.2 KiB
C
257 lines
8.2 KiB
C
/******************************************************************************/
|
|
/* */
|
|
/* our include */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
#include "libinit.h"
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* *** FIRST *** function - prevents a crash when called from CLI! */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
LONG safefail(VOID)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* a do nothing stub (required!) */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
LONG
|
|
DevExtFunc(VOID)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* remove device from memory if possible */
|
|
/* */
|
|
/* !!! CAUTION: This function runs in a forbidden state !!! */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
LONG
|
|
DevExpunge(REG(a6,__DEV dev))
|
|
{
|
|
LONG SegList = 0;
|
|
|
|
/* set delayed expunge flag */
|
|
|
|
dev->LibNode.lib_Flags |= LIBF_DELEXP;
|
|
|
|
/* still in use? */
|
|
|
|
if (!dev->LibNode.lib_OpenCnt) {
|
|
|
|
APTR SysBase = dev->SysBase;
|
|
|
|
/* remove device from SysBase->DevList */
|
|
|
|
Remove((struct Node *)dev);
|
|
|
|
/* now call user-exit */
|
|
|
|
__UserDevCleanup(dev->DataSeg);
|
|
|
|
/* return the seglist for UnLoadSeg() */
|
|
|
|
SegList = dev->SegList;
|
|
|
|
/* free device */
|
|
|
|
FreeMem((UBYTE *)dev-dev->LibNode.lib_NegSize,dev->LibNode.lib_NegSize+dev->LibNode.lib_PosSize);
|
|
}
|
|
|
|
return SegList;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* DevClose() will be called for every CloseDevice() */
|
|
/* */
|
|
/* !!! CAUTION: This function runs in a forbidden state !!! */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
LONG
|
|
DevClose(REG(a1,APTR iorq),REG(a6,__DEV dev))
|
|
{
|
|
LONG SegList = 0;
|
|
|
|
/* call user-close */
|
|
|
|
__UserDevClose(iorq,dev->DataSeg);
|
|
|
|
/* one less user */
|
|
|
|
if (!--dev->LibNode.lib_OpenCnt && (dev->LibNode.lib_Flags&LIBF_DELEXP))
|
|
SegList = DevExpunge(dev);
|
|
|
|
/* SegList or NULL (still in use) */
|
|
|
|
return SegList;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* DevOpen() will be called for every OpenDevice() */
|
|
/* */
|
|
/* !!! CAUTION: This function runs in a forbidden state !!! */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
VOID
|
|
DevOpen(REG(d0,ULONG unit),REG(a1,APTR iorq),REG(d1,ULONG flags),REG(a6,__DEV dev))
|
|
{
|
|
/* any memory allocation can cause a call of THIS device expunge vector.
|
|
if OpenCnt is zero the library might go away ... so fake a user :-) */
|
|
|
|
++dev->LibNode.lib_OpenCnt;
|
|
|
|
/* call user-open */
|
|
|
|
if (!__UserDevOpen(iorq,unit,flags,dev->DataSeg)) {
|
|
|
|
/* clear delayed expunge flag */
|
|
|
|
dev->LibNode.lib_Flags &= ~LIBF_DELEXP;
|
|
|
|
/* one new user */
|
|
|
|
++dev->LibNode.lib_OpenCnt;
|
|
}
|
|
|
|
/* end of expunge protection */
|
|
|
|
--dev->LibNode.lib_OpenCnt;
|
|
|
|
/* exec returns io_error later */
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* initialization function called by MakeLibrary() */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
static inline APTR __GetDataSeg(void)
|
|
{ APTR res;
|
|
|
|
__asm("lea ___a4_init,%0" : "=a" (res)); return res;
|
|
}
|
|
|
|
static inline ULONG __BSize(void)
|
|
{ ULONG res;
|
|
|
|
__asm("movel #___bss_size,%0" : "=d" (res)); return res;
|
|
}
|
|
|
|
static inline APTR __GetBssStart(void)
|
|
{ APTR res;
|
|
|
|
__asm("lea __edata,%0" : "=a" (res)); return res;
|
|
}
|
|
|
|
APTR
|
|
DevInit(REG(a0,LONG SegList),REG(d0,__DEV dev),REG(a6,struct Library *SysBase))
|
|
{ ULONG size;
|
|
|
|
/* set up header data */
|
|
|
|
dev->LibNode.lib_Node.ln_Type = NT_DEVICE;
|
|
dev->LibNode.lib_Node.ln_Name = (UBYTE *)DevName;
|
|
dev->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
|
|
dev->LibNode.lib_Version = (UWORD)DevVersion;
|
|
dev->LibNode.lib_Revision = (UWORD)DevRevision;
|
|
dev->LibNode.lib_IdString = (char *)DevIdString;
|
|
|
|
/* setup private data */
|
|
|
|
dev->SegList = SegList;
|
|
dev->SysBase = SysBase;
|
|
|
|
#if 1
|
|
|
|
dev->DataSeg = __GetDataSeg();
|
|
|
|
/* clear the bss part */
|
|
|
|
if ((size=__BSize())) {
|
|
|
|
ULONG *p = __GetBssStart();
|
|
|
|
do {
|
|
*p++=0;
|
|
} while ((size-=sizeof(*p)));
|
|
}
|
|
|
|
#endif
|
|
|
|
/* now call user-init */
|
|
|
|
if (!__UserDevInit(&dev->LibNode,dev->DataSeg)) {
|
|
FreeMem((UBYTE *)dev-dev->LibNode.lib_NegSize,dev->LibNode.lib_NegSize+dev->LibNode.lib_PosSize);
|
|
dev = NULL;
|
|
}
|
|
|
|
/* this will be added to SysBase->DevList or NULL (init error) */
|
|
|
|
return dev;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* autoinit table for use with initial MakeLibrary() */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
static const APTR InitTab[4] = {
|
|
(APTR)sizeof(struct libBase),
|
|
(APTR)&__FuncTable__[1],
|
|
(APTR)NULL,
|
|
(APTR)&DevInit
|
|
};
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* resident structure */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
static const struct Resident RomTag = {
|
|
RTC_MATCHWORD,
|
|
(struct Resident *)&RomTag,
|
|
(struct Resident *)&RomTag+1,
|
|
RTF_AUTOINIT,
|
|
0,
|
|
NT_DEVICE,
|
|
0,
|
|
(char *)DevName,
|
|
(char *)DevIdString,
|
|
(APTR)&InitTab
|
|
};
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* add these functions to 'funclist' */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
ADD2LIST(DevOpen,__FuncTable__,22);
|
|
ADD2LIST(DevClose,__FuncTable__,22);
|
|
ADD2LIST(DevExpunge,__FuncTable__,22);
|
|
ADD2LIST(DevExtFunc,__FuncTable__,22);
|
|
|
|
/******************************************************************************/
|
|
/* */
|
|
/* end of devinit.c */
|
|
/* */
|
|
/******************************************************************************/
|