;__________________________________________________________________________________________________ ; ; File: IntModemMgr.a ; ; Contains: Internal modem manager initialization code ; ; Written by: Steven Swenson ; ; Copyright © 1994-1994 by Apple Computer, Inc. All rights reserved. ; ; Change History (most recent first): ; ; 1/27/94 rab Removed padForOverpatch stuff from the end of this file ; (SuperMario does not use it…). ;

5/23/93 SES Made changes from code review, 5/19/93. ;

5/4/93 SES Removed machine primitives and replaced them with the dispatch ; functions in the IntModemMgr.a file. ;

4/27/93 SES Altered modem manager to enhance it somewhat per code review on ; 4/22/93. Added dispatcher in this file (from ImmgPrimitives.a). ; Split primitives into machine primitives and modem primitives. ; <1> 4/8/93 SES first checked in ;__________________________________________________________________________________________________ LOAD 'StandardEqu.d' INCLUDE 'HardwarePrivateEqu.a' INCLUDE 'UniversalEqu.a' INCLUDE 'ROMEqu.a' INCLUDE 'IntModemMgrEqu.a' INCLUDE 'IntModemMgrPrivEqu.a' MACHINE MC68020 ;---------------------------------------------------------------------------------------- ; ImmgInit ; ; Entry: none ; ; Exit: none ; ; Trashes: none ; ; Uses: ; ; A1: pointer to head of modem primitive table list ; A2: pointer to modem manager globals ; A3: pointer to machine primitives table ; A4: pointer to individual modem primitives tables ; ; Sets up the internal modem manager if it should be set up. The manager will not be ; installed if the pointer in the product info record is NULL. The manager will attempt to ; install any primitives that the root table points to (see IntModemMgrPrivEqu.a). ;---------------------------------------------------------------------------------------- ImmgInit PROC EXPORT @savedRegs REG d0-d2/a0-a4 movem.l @SavedRegs,-(sp) ; save away registers ; First check to see if the modem manager should be installed. WITH ProductInfo movea.l UnivInfoPtr,a0 ; get the product info table move.l ImmgPrimPtr(a0),d0 ; get the internal modem manager primitives offset beq.w @exit ; exit if null pointer lea (a0,d0.l),a1 ; A1 -> immgMdmList: head of modem prim list ENDWITH ; set up modem manager globals move.l #immgGlobals.size,d0 ; size of globals _NewPtr ,SYS,CLEAR ; pointer to globals -> A0 tst.w d0 ; check pointer for validity bne.w @exit ; bad, bad, bad... movea.l a0,a2 ; A2 -> globals pointer ; set up the machine dispatch table WITH immgGlobals move.l #immgDispTable.size,d0 ; size of dispatch table _NewPtr ,SYS,CLEAR ; pointer to dispatch table -> A0 tst.w d0 ; check pointer for validity bne.w @error1 ; bad, bad, bad... move.l a0,dispTable(a2) ; store pointer to dispatch table in globals movea.l a0,a3 ; A3 -> machine prim table ptr ENDWITH WITH immgDispTable lea immgDispatchTable,a0 ; A0 -> pointer to ROM based dispatch table move.l a0,d2 ; D2 -> ROM based dispatch table base for offset to absolute conversion move.l (a0)+,(a3)+ ; copy flags and number of primitives move.l #size,d0 ; D0 -> size of dispatch table, in bytes, including storage sub.l #dispOffset,d0 ; D0 -> size of dispatch table in bytes ;

lsr.l #2,d0 ; D0 -> number of dispatch routines move.w d0,-2(a3) ; put number of dispatch routines into RAM based table bra.s @startLoop ; for DBRA loop ;

@machPrimLoop move.l (a0)+,d1 ; D1 -> offset to dispatch routine add.l d2,d1 ; D1 -> absolute address of dispatch routine move.l d1,(a3)+ ; copy absolute address into RAM based dispatch table @startLoop dbra d0,@machPrimLoop ; copy all dispatch functions ENDWITH ; set up the modem manager modem queue WITH immgGlobals moveq #qHeadSize,d0 ; size of a OS queue header _NewPtr ,SYS,CLEAR ; A0 -> pointer to modem queue header tst.w d0 ; check for valid pointer bne.w @error2 ; bad, bad, bad... move.l a0,mdmQ(a2) ; store pointer to modem queue in globals ENDWITH ; save modem globals in expand mem WITH ExpandMemRec move.l a2,([ExpandMem],emIMdmMgrGlobs) ENDWITH ; install the dispatcher lea ImmgDispatch,a0 ; address of dispatcher for the trap move.w #IntMdmMgrTrap,d0 ; internal modem manager trap number _SetTrapAddress ,NEWTOOL ; call modem manager init to initialize any future modem manager specific things _IModemInit tst.w d0 ; check for modem manager init errors bne.s @error3 ; bad, bad, bad... ; for each root table entry, attempt to install the modem primitives WITH immgMdmList moveq #0,d0 ; first time around, A1 is already a pointer @modemInstall adda.l d0,a1 ; A1 -> pointer to next modem list element move.l primTable(a1),d0 ; D0 -> offset to modem primitives table beq.s @skipModemPrims ; no install if NULL lea (a1,d0.l),a4 ; A4 -> pointer to modem primitives table bsr CopyModemPrims ; copy modem primitives table into RAM bne.s @error4 ; bad, bad, bad... ;

_IModemInstall ; install the primitives @skipModemPrims move.l mdmListPtr(a1),d0 ; D0 -> offset to next modem list bne.s @modemInstall ; continue installing modems until NULL pointer ENDWITH ; install the gestalt trap lea ImmgGestalt,a0 ; get address of gestalt code move.l #gestaltIntModemType,d0 ; internal modem manager selector code _NewGestalt ; install the selector @exit movem.l (sp)+,@SavedRegs ; restore registers rts ;---------------------------------------------------------------------------------------- ; Error conditions from the modem init code above ;---------------------------------------------------------------------------------------- ; have allocated an unknown number of modem primitive queue blocks and modem primitive tables ; and also have done modem manager init @error4 move.l immgGlobals.mdmQ(a2),a1 ; A1 -> pointer to modem queue header movea.l qHead(a1),a1 ; A1 -> pointer to first modem queue element tst.l a1 ; check if pointer is real beq.s @error3 ; no more modem queue elements to deallocate WITH immgQEl @cleanUpMdms move.l qMdmPrimPtr(a1),d0 ; D0 -> pointer to modem primitives table beq.s @nextMdmQEl ; no pointer to deallocate movea.l d0,a0 ; A0 -> pointer to modem primitives table _DisposPtr ; get rid of it @nextMdmQEl movea.l a1,a0 ; A0 -> pointer to this modem queue element move.l qLink(a1),a1 ; A1 -> pointer to next modem queue element _DisposPtr ; get rid of previous modem queue element tst.l a1 ; check if the end of the list bne.s @cleanUpMdms ; no more modem queue elements to deallocate ; call modem manager close to clean up anything done in modem manager init _IModemClose ; have already set trap address of modem manager @error3 move.l #UnimplTrap,d0 ; D0 -> trap word of unimplemented trap _GetTrapAddress ,NEWTOOL ; A0 -> address of unimplemented trap move.l #IntMdmMgrTrap,d0 ; D0 -> trap word of internal modem manager _SetTrapAddress ,NEWTOOL ; make modem manager unimplemented ; have already allocated machine primitive table pointer @error2 movea.l a3,a0 ; A0 -> pointer to machine primitves table _DisposPtr ; get rid of it ; have already allocated globals pointer @error1 movea.l a2,a0 ; A0 -> pointer to globals _DisposPtr ; get rid of it bra.s @exit ;---------------------------------------------------------------------------------------- ; CopyModemPrims ; ; Entry: A4: pointer to ROM based modem primitives table ; ; Exit: A0: pointer to RAM based copy of modem primitives table, with absolute addresses ; D0: zero if no error, -1 if error ; ; Trashes: none ; ; Copies ROM based modem primitives table into RAM, converting addresses to primitives ; into absolute addresses. Leaves the condition codes register set to ZERO on memory ; allocation error. ;---------------------------------------------------------------------------------------- CopyModemPrims movem.l d1-d3,-(sp) ; save registers WITH immgPrimTable move.l #size,d0 ; size of modem primitives table beq.s @errorExit ; if the size of the thing is ever zero ;

_NewPtr ,SYS,CLEAR ; pointer to machine primitives table -> A0 tst.w d0 ; check pointer for validity bne.s @errorExit ; bad, bad, bad... move.l a0,d2 ; D2 -> pointer to RAM based modem prim table move.l a4,d3 ; D3 -> ROM based modem table base for offset to absolute conversion move.l (a4)+,(a0)+ ; copy flags and number of primitives move.l #size,d0 ; D0 -> size of modem primitives table, in bytes, including storage sub.l #primOffset,d0 ; D0 -> size of modem primitives table in bytes ;

lsr.l #2,d0 ; D0 -> number of modem primtives move.w d0,-2(a0) ; put number of primitives into RAM based table bra.s @startLoop ; for DBRA loop ;

@mdmPrimLoop move.l (a4)+,d1 ; D1 -> offset to primitive add.l d3,d1 ; D1 -> absolute address of primitive move.l d1,(a0)+ ; copy absolute address into RAM based primtive table @startLoop dbra d0,@mdmPrimLoop ; copy all primitives ENDWITH movea.l d2,a0 ; A0 -> pointer to RAM based modem prims moveq #0,d0 ; indicate no error @exit movem.l (sp)+,d1-d3 ; restore registers rts @errorExit move.b #$FF,d0 ; indicate an error occurred bra.s @exit ;---------------------------------------------------------------------------------------- ; ImmgDispatch ; ; Entry: D0: high word: modem ID; low word: trap selector ; A0: may hold a pointer or data ; ; Exit: D0: result code ; ; Trashes: none ; ; Uses: ; ; A1: pointer to modem manager globals ; A2: pointer to machine primitives table ; ; Handles a modem manager call. Jumps through the machine primitives table and returns ; the result code. ;---------------------------------------------------------------------------------------- ImmgDispatch @saveRegs REG d1/a1-a2 ; registers to save in this routine movem.l @saveRegs,-(sp) ; save registers ; Get machine primitives table WITH ExpandMemRec move.l ([ExpandMem],emIMdmMgrGlobs),a1 tst.l a1 ; check for valid pointer, this should never happen beq.s @errorNoBoard ; bad, bad, bad... ENDWITH ; range check trap selector WITH immgGlobals move.l dispTable(a1),a2 ; A2 -> pointer to machine primitives tst.l a2 ; check for valid primitives pointer beq.s @errorInvalid ; bad, bad, bad... ENDWITH WITH immgDispTable cmp.w numDisp(a2),d0 ; is the selector < number of dispatch functions bcc.s @errorInvalid ; invalid selector adda.l #dispOffset,a2 ; A2 -> pointer to beginning of dispatch functions ENDWITH ; call the dispatch function to do the work move.w d0,d1 ; D1 -> trap selector lsl.w #2,d1 ; D1 -> offset to dispatch function address jsr ([a2,d1.w]) ; do dispatch function @exit movem.l (sp)+,@saveRegs ; restore registers rts @errorNoBoard move.w #immgNoBoardErr,d0 ; D0 -> no board error result bra.s @exit @errorInvalid move.w #immgInvalidSelector,d0 ; D0 -> invalid selector error result bra.s @exit ;---------------------------------------------------------------------------------------- ; ImmgGestalt ; ; Entry: D0: gestaltIntModemType ; A0: pointer for return data ; ; Exit: D0: gestalt result code ; ; Trashes: A0 ; ; Finds out about the internal modem manager by calling IModemInfo. ;---------------------------------------------------------------------------------------- ImmgGestalt _IModemInfo ; get the modem mgr information (in d0) move.l a0,d0 ; D0 -> num modems and version movea.l 4(sp),a0 ; get a pointer to the response longword move.l d0,(a0) ; return type of modem move.l (sp)+,a0 ; get the return address add.l #8,sp ; remove paramters move.w #noErr,(sp) ; set return error code jmp (a0) ; return ;---------------------------------------------------------------------------------------- ; Dispatch table for internal modem manager. ;---------------------------------------------------------------------------------------- immgDispatchTable DC.W 0 ; flags DC.W 0 ; number of primitives (filled in at init time) DC.L mdmInit-immgDispatchTable ; offset to modem manager init routine DC.L mdmPower-immgDispatchTable ; offset to modem manager power routine DC.L mdmWakeUp-immgDispatchTable ; offset to modem manager wake up routine DC.L mdmStatus-immgDispatchTable ; offset to modem manager status routine DC.L mdmPrime-immgDispatchTable ; offset to modem manager prime routine DC.L mdmSndCtl-immgDispatchTable ; offset to modem manager sound control routine DC.L mdmGetInd-immgDispatchTable ; offset to modem manager get indexed routine DC.L mdmFind-immgDispatchTable ; offset to modem manager find routine DC.L mdmInstall-immgDispatchTable ; offset to modem manager install routine DC.L mdmRemove-immgDispatchTable ; offset to modem manager remove routine DC.L mdmGetName-immgDispatchTable ; offset to modem manager get name routine DC.L mdmInfo-immgDispatchTable ; offset to modem manager info routine DC.L mdmClose-immgDispatchTable ; offset to modem manager close routine DC.L mdmSndVol-immgDispatchTable ; offset to modem sound volume routine DC.L mdmSndHW-immgDispatchTable ; offset to system sound HW arbitration routine ;---------------------------------------------------------------------------------------- ; mdmInit ; ; Entry: a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: none ; ; Sets up private storage for the machine primitives. ;---------------------------------------------------------------------------------------- mdmInit move.w #immgVersion,immgGlobals.version(a1) ; store modem manager version number move.w #noErr,d0 @exit rts ;---------------------------------------------------------------------------------------- ; mdmPower ; ; Entry: d0 = high word: modem ID ; a0 = pointer to modem parameter block ; a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: none ; ; Calls modem primitive for modem power. ;---------------------------------------------------------------------------------------- mdmPower move.w #selMPPower,d0 ; select modem power bra.w CallMdmPrim ; make the call ;---------------------------------------------------------------------------------------- ; mdmWakeUp ; ; Entry: d0 = high word: modem ID ; a0 = pointer to modem parameter block ; a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: none ; ; Calls modem primitive for wake up on ring. ;---------------------------------------------------------------------------------------- mdmWakeUp move.w #selMPWakeUp,d0 ; select modem power bra.w CallMdmPrim ; make the call ;---------------------------------------------------------------------------------------- ; mdmStatus ; ; Entry: d0 = high word: modem ID ; a0 = pointer to modem parameter block ; a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: none ; ; Calls modem primitive for status. ;---------------------------------------------------------------------------------------- mdmStatus move.w #selMPStatus,d0 ; select modem power bra.w CallMdmPrim ; make the call ;---------------------------------------------------------------------------------------- ; mdmPrime ; ; Entry: d0 = high word: modem ID ; a0 = pointer to modem parameter block ; a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: none ; ; Calls modem primitive for prime. ;---------------------------------------------------------------------------------------- mdmPrime move.w #selMPPrime,d0 ; select modem power bra.w CallMdmPrim ; make the call ;---------------------------------------------------------------------------------------- ; mdmSndCtl ; ; Entry: d0 = high word: modem ID ; a0 = pointer to modem parameter block ; a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: A0, A1 ; ; Set machine up to be enable/disable sound, then Calls modem primitive for sound control. ;---------------------------------------------------------------------------------------- mdmSndCtl move.w #selMPSndCtl,d0 ; select modem power bra.w CallMdmPrim ; make the call ;---------------------------------------------------------------------------------------- ; mdmGetInd ; ; Entry: d0 = high word: modem ID ; a1 = modem manager global pointer ; ; Exit: d0 = high word: modem ID; low word: result code ; a0 = modem type (longword) ; ; Trashes: none ; ; Checks to see if the modem with index given in the high word of D0 is installed. If it ; is, the mdmType primitive for the modem is called to get the modem type, and the modem ; ID, modem type, and result code are returned. ;---------------------------------------------------------------------------------------- mdmGetInd move.w d1,-(sp) ; save registers swap d0 ; put modem index in low word bsr GetIndMdm ; A0 -> pointer to the modem queue element beq.s @noModem ; if no modem, report it move.w immgQEl.qMdmId(a0),d0 ; D0 -> modem ID move.w d0,d1 ; D1 -> modem ID swap d0 ; D0: high word -> modem ID move.w #selMPType,d0 ; select modem type primitive bsr CallMdmPrim ; make the call, A0 -> modem type, D0 -> result code swap d0 move.w d1,d0 ; D0 -> modem ID swap d0 ; DO: high word -> modem ID, low word -> result code @exit move.w (sp)+,d1 ; restore registers rts @noModem move.w #immgNoBoardErr,d0 ; report error bra.s @exit ;---------------------------------------------------------------------------------------- ; mdmFind ; ; Entry: A0: pointer to modem primitives table ; ; Exit: D0: result code of modem primitive MdmExists ; ; Trashes: none ; ; Calls the modem primitive MdmExists to determine if the modem that the primitives ; apply to physically exists in the machine. ;---------------------------------------------------------------------------------------- mdmFind jsr ([immgPrimTable.mdmExists,a0]) ; call primitive rts ;---------------------------------------------------------------------------------------- ; mdmInstall ; ; Entry: A0: pointer to modem primitives table ; A1: pointer to modem manager globals ; ; Exit: D0: high word: modem ID; low word: result code ; ; Trashes: none ; ; Calls mdmFind to ensure that the modem to be installed is in the machine. If the ; modem is physically present, a new queue element is allocated and enqueued in the ; modem queue. Finally, the modem setup primitive is called, the returned A1 is stored ; in the modem queue element, and the pointer to the queue element is returned in A1. ;---------------------------------------------------------------------------------------- mdmInstall @saveRegs REG d2/a1-a4 ; registers to save movem.l @saveRegs,-(sp) ; save registers movea.l a0,a2 ; A2 -> pointer to modem primitives bsr mdmFind ; let primitives check if modem is in box tst.w d0 ; check result bne.s @noModem ; no modem found, report error ; create the new modem queue element move.l #immgQEl.size,d0 ; D0 -> size of modem queue element _NewPtr ,SYS,CLEAR ; A0 -> pointer to new modem queue element tst.w d0 ; check pointer validity bne.s @noModem ; no more memory, UNLUCKY! movea.l a0,a4 ; A4 -> pointer to modem queue element ; fill in the fields of the modem queue element WITH immgQEl ; type is already set up (from CLEAR) bsr GetNewMdmID ; D0 -> new modem ID move.w d0,qMdmID(a0) ; store modem ID move.w d0,d2 ; save modem ID for mdmSetUp later move.l a2,qMdmPrimPtr(a0) ; store modem primitives table pointer ENDWITH ; optionalA1 will wait 'til after SetUp call ; install the modem queue element into the modem queue movea.l a1,a3 ; A3 -> pointer to modem globals move.l immgGlobals.mdmQ(a3),a1 ; A1 -> pointer to modem queue header _Enqueue ; place new modem queue element into queue ; call the modem primitive MdmSetUp move.w d2,d0 ; D0 -> modem ID swap d0 ; put modem ID into high word movea.l a3,a1 ; A1 -> pointer to modem manager globals move.w #selMPSetUp,d0 ; call the MdmSetUp primitive bsr CallMdmPrim ; this calls the modem primitive tst.w d0 ; check returned error result bne.s @primError ; there was an error in the primitive ; store the optional A1 pointer in the queue element move.l a0,immgQEl.optionalA1(a4) ; save the value returned by the primitive ; return the modem ID in the high word of D0, and no error in low word swap d0 move.w d2,d0 ; D0 -> modem ID swap d0 @exit movem.l (sp)+,@saveRegs ; restore registers rts @noModem move.w #immgNoBoardErr,d0 ; report no board bra.s @exit @primError move.w d2,d0 ; D0 -> modem ID swap d0 ; put modem ID into high word bsr mdmRemove ; remove the modem from the queue bra.s @exit ;---------------------------------------------------------------------------------------- ; mdmRemove ; ; Entry: D0: high word: modem ID ; A1: pointer to modem manager globals ; ; Exit: D0: noErr ; ; Trashes: none ; ; Calls FindInstalledMdm to get the modem queue element for the modem with the ID passed ; in the high word of D0. Calls the CallMdmPrim routine to call the mdmTearDown primitive. ; Dequeues the modem queue element and deallocates it. ;---------------------------------------------------------------------------------------- mdmRemove @saveRegs REG a1-a2 ; registers to save movem.l @saveRegs,-(sp) ; save registers ; get the modem queue element to remove movea.l a1,a2 ; A2 -> pointer to modem globals bsr FindInstalledMdm ; A1 -> pointer to modem queue element beq.s @noModem ; no modem found, report error exg a1,a2 ; A1 -> modem globals, A2 -> modem Q El ; call the modem tear down primitive move.w #selMPTearDown,d0 ; select modem tear down bsr CallMdmPrim ; make the call, don't care about errors ; dequeue the modem movea.l a2,a0 ; A0 -> modem queue element movea.l immgGlobals.mdmQ(a1),a1 ; A1 -> pointer to modem queue header _Dequeue ; don't care about errors ; deallocate the modem queue element movea.l a2,a0 ; A0 -> modem queue element _DisposPtr ; get rid of it @noModem move.w #noErr,d0 ; D0 -> no error @exit movem.l (sp)+,@saveRegs ; restore registers rts ;---------------------------------------------------------------------------------------- ; mdmGetName ; ; Entry: a0 = pointer to string buffer ; a1 = modem manager global pointer ; ; Exit: d0 = result code ; a0 = pointer to null terminated c string ; ; Trashes: none ; ; Gets the name of an installed modem by calling the get modem name primitive. ;---------------------------------------------------------------------------------------- mdmGetName move.w #selMPName,d0 ; select mdmGetName primitive bra.w CallMdmPrim ; make the call ;---------------------------------------------------------------------------------------- ; mdmInfo ; ; Entry: a1 = modem manager global pointer ; ; Exit: d0 = valid gestalt result code ; a0 = high word: modem manager version; low word: number of modems ; ; Trashes: none ; ; Counts the number of installed modems, and returns the count and the modem manager ; version number. ;---------------------------------------------------------------------------------------- mdmInfo bsr CountMdms ; D0.L -> number of installed modems swap d0 move.w immgGlobals.version(a1),d0 ; D0 -> modem manager version number swap d0 move.l d0,a0 ; A0 -> return result move.w #noErr,d0 @exit rts ;---------------------------------------------------------------------------------------- ; mdmClose ; ; Entry: a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: none ; ; Cleans up any initialization done by mdmInit. ;---------------------------------------------------------------------------------------- mdmClose move.w #noErr,d0 @exit rts ;---------------------------------------------------------------------------------------- ; mdmSndVol ; ; Entry: d0 = high word: modem ID ; a0 = pointer to modem parameter block ; a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: A0, A1 ; ; Set machine up to set modem sound volume, then Calls modem primitive for sound control. ;---------------------------------------------------------------------------------------- mdmSndVol move.w #selMPSndVol,d0 ; select modem power bra.w CallMdmPrim ; make the call ;---------------------------------------------------------------------------------------- ; mdmSndHW ; ; Entry: d0 = high word: modem ID ; a0 = pointer to modem parameter block ; a1 = modem manager global pointer ; ; Exit: d0 = result code ; ; Trashes: A0, A1 ; ; Arbitrate for the system sound hardware via the appropriate primitive. ;---------------------------------------------------------------------------------------- mdmSndHW move.w #selMPSndHW,d0 ; select modem power bra.w CallMdmPrim ; make the call ; ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ; Useful utility routines ; ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ;---------------------------------------------------------------------------------------- ; FindInstalledMdm ; ; Entry: D0: high word: modem ID ; A1: pointer to modem manager globals ; ; Exit: A1: pointer to modem queue element for modem with ID passed in D0 ; Condition codes set to zero if modem not found, otherwise not zero ; ; Trashes: none ; ; Looks up the modem with ID given in high word of D0 and returns the modem queue ; element. ;---------------------------------------------------------------------------------------- FindInstalledMdm move.l immgGlobals.mdmQ(a1),a1 ; A1 -> pointer to modem Q header swap d0 ; D0: low word -> modem ID move.l qHead(a1),a1 ; A1 -> first modem queue element WITH immgQEl @nextModem tst.l a1 ; check pointer for validity beq.s @exit ; Oops! out of modems and not found! cmp.w qMdmID(a1),d0 ; check modem ID against the one we want beq.s @exit ; found it! move.l qLink(a1),a1 ; A1 -> pointer to next modem queue element bra.s @nextModem ; keep checking... ENDWITH @exit swap d0 ; put things back the way they were tst.l a1 ; set condition codes rts ;---------------------------------------------------------------------------------------- ; CallMdmPrim ; ; Entry: D0: high word: modem ID; low word: primitive selector ; A1: pointer to modem manager globals ; ; Exit: A0: whatever is returned by the modem primitive ; D0: result code returned by modem primitive, or no board found err ; if the modem ID was not valid. ; ; Trashes: none ; ; Calls FindInstalledMdm to get the modem queue element desired, then calls the modem ; primitive selected by the low word of D0. ;---------------------------------------------------------------------------------------- CallMdmPrim @saveRegs REG d1/a1-a2 ; registers to save over routine movem.l @saveRegs,-(sp) ; save registers bsr FindInstalledMdm ; A1 -> pointer to modem queue element beq.s @noModem ; no modem found, report error ; get data from the queue element that will be used WITH immgQEl move.l qMdmPrimPtr(a1),a2 ; A2 -> pointer to modem primitives move.l optionalA1(a1),a1 ; A1 -> pointer to optional A1 parameter ENDWITH ; range check the primitive selector against the number of prims in the prim table WITH immgPrimTable cmp.w numPrims(a2),d0 ; is the prim selector < num prims? bcc.s @invalidSel ; nope, report error... adda.l #primOffset,a2 ; A2 -> pointer to primitives move.w d0,d1 ; D1 -> primitive selector lsl.w #2,d1 ; D1 -> offset to primitive jsr ([a2,d1.w]) ; do the primitive ENDWITH @exit movem.l (sp)+,@saveRegs ; restore registers rts @noModem move.w #immgNoBoardErr,d0 ; report no board bra.s @exit @invalidSel move.w #immgInvalidSelector,d0 ; report invalid primitive selector bra.s @exit ;---------------------------------------------------------------------------------------- ; GetIndMdm ; ; Entry: D0: index of modem to retrieve (zero based) ; A1: pointer to modem manager globals ; ; Exit: A0: pointer to modem queue element for modem at index in D0 ; Condition codes set to zero if modem not found, otherwise not zero ; ; Trashes: D0, A0 ; ; Looks up the modem with index given in D0 and returns a pointer to the modem queue ; element. ;---------------------------------------------------------------------------------------- GetIndMdm move.l immgGlobals.mdmQ(a1),a0 ; A0 -> pointer to modem Q header move.l qHead(a0),a0 ; A0 -> first modem queue element tst.l a0 ; check pointer for validity beq.s @exit ; Oops! out of modems and not found! tst.w d0 ; check if we want first (0) modem beq.s @exit ; yep! leave... WITH immgQEl subq #1,d0 ; for dbeq loop @nextModem move.l qLink(a0),a0 ; A1 -> pointer to next modem queue element tst.l a0 ; set condition codes dbeq d0,@nextModem ; keep checking... ENDWITH @exit tst.l a0 ; set condition codes rts ;---------------------------------------------------------------------------------------- ; CountMdms ; ; Entry: A1: pointer to modem manager globals ; ; Exit: D0: number of modems ; ; Trashes: A0 ; ; Counts the number of installed modems in the modem queue. ;---------------------------------------------------------------------------------------- CountMdms moveq #0,d0 ; clear counter move.l immgGlobals.mdmQ(a1),a0 ; A0 -> pointer to modem Q header move.l qHead(a0),a0 ; A0 -> first modem queue element tst.l a0 ; check pointer for validity beq.s @exit ; Zero modems WITH immgQEl @nextModem addq #1,d0 ; counting... move.l qLink(a0),a0 ; A1 -> pointer to next modem queue element tst.l a0 ; set condition codes bne.s @nextModem ; keep counting... ENDWITH @exit rts ;---------------------------------------------------------------------------------------- ; GetNewMdmID ; ; Entry: A1: pointer to modem globals ; ; Exit: D0: modem ID ; ; Trashes: none ; ; Comes up with a new modem ID. Right now, all it does is increment the number in the ; modem manager globals and returns it. ;---------------------------------------------------------------------------------------- GetNewMdmID WITH immgGlobals add.w #1,lastMdmID(a1) ; increment last modem ID move.w lastMdmID(a1),d0 ; get the modem ID ENDWITH rts End