stoms@castor.ncgia.ucsb.edu (David Stoms) (05/31/90)
A while back I remember a lengthly discussion of the installation of drivers during start up. I need to install a driver, like ATM, with an INIT. Could someone mail or post a summery or opinion of how this should be done? Specifically, what is the algorithm to determine in which slot to install the driver into the Unit Table and once the slot is found, how to install it. Thanks, Josh.
jholt@adobe.COM (Joe Holt) (06/01/90)
Newsgroups: comp.sys.mac.programmer
Subject: Re: How do I install a driver with an INIT?
References: <5560@hub.ucsb.edu>
Reply-To: jholt@adobe.com (Joe Holt)
Organization: Adobe Systems Incorporated, Mountain View
Keywords: INITs driver
Here's a small code resource INIT I use to open a driver at startup time.
I write the guts of my "INIT" as a driver, then paste this resource into
it, and I'm off. With Think C, it even handles multi-segmented drivers.
If you have any questions, just ask.
-------- CUT HERE --------
/**
OPEN DRIVER INIT
Think C 4.0
This bit of code should be compiled as a Code Resource, Type INIT, ID 0 (or
whatever you like). Change the name DRIVER_NAME to the name of the driver
you want opened at start up. Place this compiled INIT resource in the
driver and change the driver's file type to INIT.
When this starts up, it finds an empty slot in the driver unit table and
sticks your driver there. It then opens your driver. You should write the
driver to handle whatever ref num it's assigned.
**/
/**--------------------------------------------------------------------------
**
** Compilation Flags
**
**/
/**
MULTI_SEGMENT generates code which is needed to init a multi-segmented
driver. Single-segment drivers can be inited also, so there is no logical
requirement to ever turn this off, except where code size is a concern.
**/
#define MULTI_SEGMENT 1
/**--------------------------------------------------------------------------
**
** Include Files
**
**/
/* none */
/**--------------------------------------------------------------------------
**
** Private Macros
**
**/
/**
UNIT_ENTRIES_NEEDED and FIRST_POSSIBLE_UNIT are used when determining the
driver reference number for your driver. This assigns the driver reference
number dynamically, looking at FIRST_POSSIBLE_UNIT and on up for an unused
number. It increases the unit table size to UNIT_ENTRIES_NEEDED if
there aren't that many unit numbers. This occurs on Mac Pluses and Mac SEs
with pre-System 6.0, where the unit table defaults to forty-eight entries,
which doesn't leave any room for custom drivers like ours.
**/
#define UNIT_ENTRIES_NEEDED (64)
#define FIRST_POSSIBLE_UNIT (48)
#define DRIVER_NAME "\p.your name here"
/**--------------------------------------------------------------------------
**
** Private Functions
**
**/
int main(void);
main()
{
static char driverName[] = DRIVER_NAME;
int theID;
IOParam ioPB;
asm {
movem.l D3-D4/A2-A4, -(A7)
movea.l A0, A4
/**
Change the resource attributes of our DRVR so that it will be loaded into
the System Heap and locked.
**/
clr.b -(A7)
_SetResLoad
clr.l -(A7)
move.l #'DRVR', -(A7)
pea driverName
_GetNamedResource
move.l (A7)+, D3
beq @abort
move.l D3, -(A7)
move.w #resSysHeap + resLocked, -(A7)
_SetResAttrs
move.l D3, -(A7) ; so that the res handle will be in SysHeap!
_ReleaseResource
move.b #1, -(A7)
_SetResLoad
/**
Pick an unused driver reference num for our DRVR and renumber the resource
to use this new reference number. We first increase the number of entries
in the unit table if less than UNIT_ENTRIES_NEEDED, then begin looking at
FIRST_POSSIBLE_UNIT.
**/
clr.l -(A7)
move.l #'DRVR', -(A7)
pea driverName
_GetNamedResource
move.l (A7)+, D3
beq @abort
move.l D3, A3
move.l A3, -(A7)
_DetachResource
move.w #UNIT_ENTRIES_NEEDED, D1
sub.w UnitNtryCnt, D1
ble.s @1
bsr @updrivers
bne @abort
@1: movea.l UTableBase, A1
move.w #FIRST_POSSIBLE_UNIT * 4, D4
move.w #FIRST_POSSIBLE_UNIT, D3
@2: cmp.w UnitNtryCnt, D3
bgt @abort
tst.l 0(A1, D4.w)
beq.s @3
addq.w #4, D4
addq.w #1, D3
bra.s @2
@3: move.w D3, D0
not.w D0
movea.l (A3), A0
dc.w 0xA43D ; _DrvrInstall 4
bne @abort
movea.l UTableBase, A1
movea.l 0(A1, D4.w), A0
_HLock
movea.l (A0), A2
move.l A3, (A2)
movea.l (A3), A3
move.w (A3), 4(A2)
bset #6, 5(A2)
/**
Now set the resources which THINK C uses for drivers to load into the System
Heap as locked, also. We especially want to lock down any DCOD resources
because the THINK C segment loader does a MoveHHi() on em when first loaded,
which is not a good idea in the System Heap at INIT time.
**/
clr.b -(A7)
_SetResLoad
clr.l -(A7)
move.l #'DATA', -(A7)
move.w #1, -(A7)
_Get1IndResource
move.l (A7)+, D3
beq @abort
move.l D3, -(A7)
move.w 0x18(A2), D0
not.w D0
lsl.w #5, D0
or.w #0xC000, D0 ; DATA resource is always ID 0
move.w D0, -(A7)
clr.l -(A7)
_SetResInfo
move.l D3, -(A7)
move.w #resSysHeap + resLocked, -(A7)
_SetResAttrs
move.l D3, -(A7)
_ReleaseResource
#if MULTI_SEGMENT
subq.w #2, A7
move.l #'DCOD', -(A7)
_Count1Resources
move.w (A7)+, D4
beq.s @DCODout
DCODtop: clr.l -(A7)
move.l #'DCOD', -(A7)
move.w D4, -(A7)
_Get1IndResource
move.l (A7)+, D3
beq @abort
move.l D3, -(A7)
pea theID
clr.l -(A7)
clr.l -(A7)
_GetResInfo
move.l D3, -(A7)
move.w 0x18(A2), D0
not.w D0
lsl.w #5, D0
move.w theID, D1
and.w #0xF01F, D1
add.w D1, D0
move.w D0, -(A7)
clr.l -(A7)
_SetResInfo
move.l D3, -(A7)
move.w #resSysHeap + resLocked, -(A7)
_SetResAttrs
move.l D3, -(A7)
_ReleaseResource
subq.w #1, D4
bne.s @DCODtop
#endif /* if MULTI_SEGMENT */
DCODout: move.b #1, -(A7)
_SetResLoad
bra.s @open
;**
;
; Increase the number of available entries in the unit table.
;
;**
@updrivers: move.w UnitNtryCnt, D0
add.w D1, D0
mulu #4, D0
_NewPtr SYS+CLEAR
bne.s @9
move SR, -(A7)
move #0x2600, SR
movea.l A0, A1
movea.l UTableBase, A0
move.w UnitNtryCnt, D0
mulu #4, D0
_BlockMove
_DisposPtr
move.l A1, UTableBase
add.w D1, UnitNtryCnt
move (A7)+, SR
moveq #0, D0
@9: rts
}
open:
ioPB.ioNamePtr = (StringPtr)driverName;
ioPB.ioPermssn = 0;
PBOpen(&ioPB, FALSE);
abort:
asm {
movem.l (A7)+, D3-D4/A2-A4
}
}