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 } }