home *** CD-ROM | disk | FTP | other *** search
- ;*********************************************************************
- ;* *
- ;* All changes I made are hereby in the Public Domain. Commodore *
- ;* retains its copyright, if any, of the original code in the Rom *
- ;* Kernel manuals since this is a derivative work. -Jeff Rush *
- ;* *
- ;*********************************************************************
- ;* History *
- ;* *
- ;* 20Sep89 jrr Original crib from Amiga Rom Kernel Manual. *
- ;* 23Jul90 jrr Extensive descriptive prose added. *
- ;* *
- ;*********************************************************************
- TITLE Example Device Driver for Tutorial Use
- SMALLOBJ ; Use PC-Relative Addressing
- OPTIMON ; Enable C.A.P.E. 68K Optimizations
-
- SECTION TheOnlySection
-
- ;************
- ;* Includes *
- ;************
- NOLIST
- INCLUDE "exec/types.i"
- INCLUDE "exec/devices.i"
- INCLUDE "exec/initializers.i"
- INCLUDE "exec/memory.i"
- INCLUDE "exec/resident.i"
- INCLUDE "exec/io.i"
- INCLUDE "exec/ables.i"
- INCLUDE "exec/errors.i"
- INCLUDE "exec/tasks.i"
- INCLUDE "exec/semaphores.i"
- INCLUDE "hardware/intbits.i"
-
- INCLUDE "asmsupp.i"
-
- INCLUDE "Example.i" ; Device-Specific Definitions
- LIST
-
- ;*************
- ;* Constants *
- ;*************
-
- ;******************
- ;* Public Symbols *
- ;******************
- XDEF LoadInitRoutine ; Initialization when Device First Loads into Memory
- XDEF DevOpen ; Unit Allocation for Each Time Device is Opened
- XDEF DevClose ; Unit Deallocation for Each Time Device is Opened
- XDEF DevExpunge ; Remove Device from Memory if No One is Using It
- XDEF DevNull ; Reserved for Future Expansion
- XDEF DevBeginIO ; Initiate an I/O Request either Now or Put in Queue
- XDEF DevAbortIO ; Abort an I/O Request either Active or in Queue
-
- ;********************
- ;* External Symbols *
- ;********************
- ; This Name is for Debugging Use, to Annotate Serial-Debug Output
- IFNE INFO_LEVEL ; If Any Debugging Enabled at All
- XREF subSysName
- ENDC
-
- ; Defined in Ex_Support.Asm
- XREF LockGlobal ; Obtain Exclusive Access to Device Global Data
- XREF UnlockGlobal ; Release Exclusive Access to Device Global Data
- XREF PerformIO ; Common Fork or Dispatch to Handle Device Commands
-
- ; Defined in Ex_UnitMgr.Asm
- XREF InitUnit ; Initialize a Unit Descriptor and Fire Up a Task
- XREF ExpungeUnit ; Terminate a Unit Task and Deallocate the Unit Descriptor
-
- ;*********************************************************************
- ;* Device-Just-Loaded-Into-Ram Initialization Routine *
- ;* *
- ;* This routine gets called immediately after the device has been *
- ;* loaded into Ram, in order to allow it to set up its environment. *
- ;* *
- ;* Inputs: *
- ;* D0 - Ptr to base of the newly allocated device node structure. *
- ;* A0 - BPtr to the segment list for the device's code. *
- ;* A6 - Ptr to the Exec Library. *
- ;* *
- ;* Outputs: *
- ;* D0 - Ptr to base of where the device has been loaded or NULL *
- ;* if initialization failed and the device is to be unloaded. *
- ;* *
- ;* All Original Registers Must Be Preserved Across Function Call!!!! *
- ;* *
- ;* Notes: *
- ;* The call to this routine is single-threaded by Exec, providing *
- ;* it does not perform a Wait(), either directly or indirectly. *
- ;* This means that it cannot perform any DOS calls, even to open *
- ;* a disk-based library. Libraries which are -known- to be in *
- ;* ram can be opened however, such as Exec, Expansion, etc. *
- ;* *
- ;* This function is called once per time the device is loaded into *
- ;* ram, unlike DevOpen() which is called each time the device is *
- ;* opened by a caller. An Exec device can be loaded once and *
- ;* opened multiple times, either for different units or in *
- ;* succession without an intervening expunge. *
- ;* *
- ;* At the time this function is called, the device node is -NOT- *
- ;* yet linked into the system lists. *
- ;* *
- ;* If you don't use the "RTF_AUTOINIT" feature, there is an *
- ;* additional caveat. If you allocate memory in your Open *
- ;* function, remember that allocating memory can cause an Expunge, *
- ;* including an expunge of your device. This must not be fatal. *
- ;* The easy solution is to avoid adding your device to the public *
- ;* list until after it is ready for action, to prevent your being *
- ;* on the list of expunge candidates. *
- ;* *
- ;*********************************************************************
- LoadInitRoutine:
- PUTMSG 5,<'%s/Init: called'>
-
- MOVEM.L D1-D7/A0-A5,-(SP) ; Preserve ALL modified registers
-
- ;Debug CALLSYS Debug ; Enter ROMWack Debugger to Determine My Address
-
- MOVE.L D0,A5 ; Set A5 to Base of Our Device
- MOVE.L A6,md_SysLib(A5) ; Keep a Ptr to the Exec Library
- MOVE.L A0,md_SegList(A5) ; Keep a Ptr to our Seglist
- ;
- ; Initialize the Device Global Data Arbitration Semaphore
- LEA.L md_SemLock(A5),A0 ; Pickup Ptr to the Arbitration Semaphore
- CALLSYS InitSemaphore ; Obtain Control of the Device Node
-
- MOVE.L A5,D0 ; Signal Success via Device Ptr in D0
- MOVEM.L (SP)+,D1-D7/A0-A5 ; Restore ALL modified registers
- RTS
-
- ;*********************************************************************
- ;* Open Device Routine *
- ;* *
- ;* When the user calls OpenDevice(), this eventually gets translated *
- ;* into a call to this routine. By the time this routine gets *
- ;* control, the device node has already been linked into the system *
- ;* list of known devices. *
- ;* *
- ;* Inputs: *
- ;* A6 - Ptr to our Device node. *
- ;* A1 - Ptr to the caller's I/O request block. *
- ;* D0 - Unit number desired. *
- ;* D1 - Device-Specific Flags indicating desired. *
- ;* *
- ;* Outputs: *
- ;* D0 - Error code of operation (0 if open succeeded). *
- ;* IO_ERROR - Error code of operation (another copy as a byte). *
- ;* IO_UNIT - Some unit identification information (if success). *
- ;* IO_DEVICE - Set up by Exec on behalf of device. *
- ;* LN_TYPE - Signal end of operation (unclear on requirement) *
- ;* *
- ;* All Original Registers Must Be Preserved Across Function Call!!!! *
- ;* *
- ;* Notes: *
- ;* The call to this routine is single-threaded by Exec, providing *
- ;* it does not perform a Wait(), either directly or indirectly. *
- ;* Because of this, do not take very much time. *
- ;* *
- ;*********************************************************************
- DevOpen:
- PUTMSG 20,<'%s/Open: called'>
- MOVEM.L D2/A2/A3/A4,-(SP) ; Preserve Original Registers Across Call
- MOVE.L A1,A2 ; Save Ptr to the I/O Block in A2
-
- ADDQ.W #1,LIB_OPENCNT(A6) ; Add Fake Opener to Prevent Expunge
- BSR LockGlobal ; Obtain Exclusive Access to Device Node
-
- ;
- ; Insure the Specified Unit Number is In-Range
- CMP.L #MD_NUMUNITS,D0
- BCC.S Open_Range_Error ; Unit Number is Out of Range!!
- ;
- ; See if the Specified Unit is Already Initialized
- MOVE.L D0,D2 ; Save Unit Number in D2
- LSL.L #2,D0 ; Multiply Unit Number by 4
- LEA.L md_Units(A6,D0.L),A4 ; Index into Unit Table
- MOVE.L (A4),D0 ; Pickup Ptr to Unit Descriptor
- BNE.S Open_UnitOK ; Descriptor is Non-Null, Unit is Ready!
- ;
- ; Unit is Uninitialized, Attempt to Conjure One Up
- BSR InitUnit ; Scratch:A3, Unit Number:D2, Ptr to Device:A6
- MOVE.L (A4),D0 ; Did It Initialize Ok?
- BEQ.S Open_Error ; Nope, Error!
- ;
- ; Unit is Located and Ready for Us
- Open_UnitOK:
- MOVE.L D0,A3 ; Put Ptr to Unit Descriptor into A3
- MOVE.L D0,IO_UNIT(A2)
- ;
- ; Adjust Reference Counts to Track Number of Openers
- ADDQ.W #1,LIB_OPENCNT(A6) ; One More User of the Device
- ADDQ.W #1,UNIT_OPENCNT(A3) ; One More User of the Specific Unit Too
-
- BCLR #LIBB_DELEXP,md_Flags(A6) ; Prevent Delayed Expunges
-
- MOVEQ.L #0,D0 ; Return Error Code in D0 and in IO_ERROR
- CLR.B IO_ERROR(A2) ; Signal "No Error Occurred During Open"
-
- MOVE.B #NT_REPLYMSG,LN_TYPE(A2) ; IMPORTANT: Mark IORequest as "Complete"
- Open_End:
- SUBQ.W #1,LIB_OPENCNT(A6) ; Remove Fake Opened Now¨the Open is Done
- BSR UnlockGlobal ; Release Exclusive Access to Device Node
-
- MOVEM.L (SP)+,D2/A2/A3/A4 ; Restore Original Registers
- RTS
-
- Open_Range_Error:
- Open_Error:
- MOVEQ #IOERR_OPENFAIL,D0 ; Return Error Code in D0 and in IO_ERROR
- MOVE.B D0,IO_ERROR(A2)
-
- MOVE.L D0,IO_DEVICE(A2) ; IMPORTANT: Trash IO_DEVICE on Open Failure
-
- PUTMSG 2,<'%s/Open: failed'>
- BRA.S Open_End
-
- ;*********************************************************************
- ;* Close Device Routine *
- ;* *
- ;* When the user calls CloseDevice(), this eventually gets changed *
- ;* into a call to this routine which terminates communication with *
- ;* the device. Upon closing, the device's input buffers are freed *
- ;* and the memory occupied by the device (code and data) may or may *
- ;* not be freed. *
- ;* *
- ;* Inputs: *
- ;* A6 - Ptr to our Device node. *
- ;* A1 - Ptr to the caller's I/O request block as initialized by *
- ;* OpenDevice(). *
- ;* *
- ;* Outputs: *
- ;* D0 - Device unload indicator: *
- ;* device seglist as given to Init (causes unload) *
- ;* zero (causes device to stay around in memory) *
- ;* IO_ERROR - Error code of operation (another copy as a byte). *
- ;* *
- ;* All Original Registers Must Be Preserved Across Function Call!!!! *
- ;* *
- ;* Notes: *
- ;* The call to this routine is single-threaded by Exec, providing *
- ;* it does not perform a Wait(), either directly or indirectly. *
- ;* Because of this, do not take very much time. *
- ;* *
- ;* All I/O requests -must- be complete before closing. If any are *
- ;* pending, the user's program must AbortIO() then WaitIO() for *
- ;* each one to complete it. *
- ;* *
- ;*********************************************************************
- DevClose:
- MOVEM.L D1/A2-A3,-(SP) ; Preserve Registers D1, A2 and A3 Across Call
- BSR LockGlobal ; Obtain Exclusive Access to Device Node
-
- PUTMSG 20,<'%s/Close: called'>
- ;
- ; Obtain a Ptr to the Appropriate Unit Descriptor
- MOVE.L A1,A2 ; Move IOB Ptr to A2
- MOVE.L IO_UNIT(A2),A3 ; Pickup a Ptr to the Unit Descriptor in A3
- ;
- ; Mark the IOB Closed to Prevent Accidental Reuse
- MOVEQ.L #-1,D0
- MOVE.L D0,IO_UNIT(A2) ; Scribble Over Ptr to Unit Descriptor
- MOVE.L D0,IO_DEVICE(A2) ; Scribble Over Ptr to Device Descriptor
- ;
- ; Decrement Unit Reference Count and Optionally Expunge Unit if No Users
- SUBQ.W #1,UNIT_OPENCNT(A3)
- BNE.S Close_Device ; Reference Count -not- Zero, Do Not Release Unit
- BSR ExpungeUnit ; A3:UnitPtr, A6:DevicePtr
- NOP ; Required to Handle a Null Jump to the Next Byte
- ; Do Not Expunge Ramdisks or the Contents Will Vanish!
- Close_Device:
- CLEAR D0
- ;
- ; Decrement Device Reference Count and Optionally Expunge Device if Asked
- SUBQ.W #1,LIB_OPENCNT(A6) ; Decrement Device Reference Count
- BNE.S Close_End ; Reference Count -not- Zero, Do Not Release Device
- ;
- ; See If There is a Delayed Expunge Pending
- BTST #LIBB_DELEXP,md_Flags(A6) ; Check for a Delayed Expunge Pending...
- BEQ.S Close_End ; Nope, No Request for Us to Unload is Pending
-
- BSR DevExpunge ; A6:DevicePtr
- Close_End:
- BSR UnlockGlobal ; Release Exclusive Access to Device Node
- MOVEM.L (SP)+,D1/A2-A3 ; Restore Original Registers D1, A2 and A3
- RTS ; Must Return Either Zero or Device Seglist in D0
-
- ;*********************************************************************
- ;* Expunge Device Routine *
- ;* *
- ;* This routine frees all system resources and dependencies used by *
- ;* the device by any unit. If the device is currently closed, the *
- ;* expunge takes place immediately. Otherwise, this routine sets a *
- ;* Delayed Expunge bit and returns a device unload indicator of zero *
- ;* (do not unload device at this time). *
- ;* *
- ;* Expunge() is called by the memory allocator when the system is *
- ;* low on memory. *
- ;* *
- ;* Inputs: *
- ;* A6 - Ptr to our Device node. *
- ;* A1 - Ptr to the caller's I/O request block as initialized by *
- ;* OpenDevice(). *
- ;* *
- ;* Outputs: *
- ;* D0 - Device unload indicator: *
- ;* device seglist as given to Init (causes unload) *
- ;* zero (causes device to stay around in memory) *
- ;* IO_ERROR - Error code of operation (zero means success). *
- ;* *
- ;* All Original Registers Must Be Preserved Across Function Call!!!! *
- ;* *
- ;* Notes: *
- ;* The call to this routine is single-threaded by Exec, providing *
- ;* it does not perform a Wait(), either directly or indirectly. *
- ;* Because of this, do not take very much time. *
- ;* *
- ;* Because Expunge() is called from the memory allocator, it may *
- ;* -never- Wait() or otherwise take a long time to complete. *
- ;* *
- ;*********************************************************************
- DevExpunge:
- PUTMSG 10,<'%s/Expunge: called'>
- MOVEM.L D1/D2/A5/A6,-(SP) ; Preserve ALL Modified Registers Across Call
-
- MOVE.L A6,A5 ; Move Device Ptr into A5
- MOVE.L md_SysLib(A5),A6 ; Pickup the Stashed Ptr to the Exec Library
-
- TST.W LIB_OPENCNT(A5) ; See if Device Reference Count is Zero (No Users)
- BEQ 1$ ; No Users, Device Can Be Unloaded
- ;
- ; Device is Still Open by Someone, Request Expunge in the Future
- BSET #LIBB_DELEXP,md_Flags(A5) ; Set the Delayed Expunge Flag
- CLEAR D0 ; Set up to Return Zero to Prevent Device Unload
- BRA.S Expunge_End ; Jump to Function Exit
- 1$:
- ;
- ; Device has No Users, It Can Be Unloaded
- MOVE.L md_SegList(A5),D2 ; Pickup the Device Seglist in D2
-
- MOVE.L A5,A1 ; Get Ptr to Device Node into A1 for Remove()
- CALLSYS Remove ; Remove Device Node from Global Linked List of Devices
-
- ;
- ; Device-Specific Closing Operations Here...
- ; (Do Not Break Forbid!)
- ;
-
- ;
- ; Free the Memory Occupied by the Device Node
- ; (Size Depends Upon Size of Jump Table and Device-Global Data)
- ; (The Code and Data Part will be Freed as a Seglist)
- ;------ free our memory (must calculate from LIB_POSSIZE & LIB_NEGSIZE)
- MOVE.L A5,A1 ; Get Ptr to Device Node into A1
- CLEAR D0 ; Clear Calculation Accumulator
- MOVE.W LIB_NEGSIZE(A5),D0 ; Pickup Negative Extent of Device Node
- SUBA.L D0,A1 ; Adjust Ptr to Device Node Down To Base of Device Node
- ADD.W LIB_POSSIZE(A5),D0 ; Add in Positive Extent of Device Node (Functions + Data)
- CALLSYS FreeMem ; Free Memory Occuppied by Device Node
-
- MOVE.L D2,D0 ; Set up to Return Our Device Seglist to Cause Unload
- Expunge_End:
- MOVEM.L (SP)+,D1/D2/A5/A6 ; Restore Original Registers
- RTS ; Must Return Either Zero or Device Seglist in D0
-
- ;*********************************************************************
- ;* Null Device Routine *
- ;* *
- ;* This routine handles a null entry point into the device provided *
- ;* for future expansion. It performs no function. *
- ;* *
- ;* Inputs: *
- ;* A6 - Ptr to our Device node. *
- ;* *
- ;* Outputs: *
- ;* D0 - Must return zero (NULL) for future compatibility. *
- ;* *
- ;* All Original Registers Must Be Preserved Across Function Call!!!! *
- ;* *
- ;*********************************************************************
- DevNull:
- PUTMSG 1,<'%s/Null: called'>
- CLEAR D0
- RTS
-
- ;*********************************************************************
- ;* BeginIO Device Routine *
- ;* *
- ;* BeginIO starts all incoming I/O. The I/O is either queued up for *
- ;* the unit task or processed immediately. *
- ;* *
- ;* BeginIO is often given the responsibility of making devices *
- ;* single threaded, so that two tasks sending commands at the same *
- ;* time don't cause a problem. Once this has been done, the command *
- ;* is dispatched via PerformIO to the actual implementation code. *
- ;* *
- ;* There are many ways to do the threading. This example uses the *
- ;* UNITB_ACTIVE bit. Be sure this method is good enough for your *
- ;* device before using. Any method is ok. If immediate access can *
- ;* not be obtained, the request is queued for later processing. *
- ;* *
- ;* Some I/O requests do not need single threading. These can be *
- ;* performed immediately. *
- ;* *
- ;* Inputs: *
- ;* A6 - Ptr to our Device node. *
- ;* A1 - Ptr to the caller's I/O request block as initialized by *
- ;* OpenDevice(). *
- ;* *
- ;* Within the I/O request block: *
- ;* IO_COMMAND The specific command desired by the caller. *
- ;* IO_LENGTH Depends upon the particular command issued. *
- ;* IO_DATA Depends upon the particular command issued. *
- ;* IO_MESSAGE An mn_ReplyPort is required. *
- ;* IO_DEVICE Set by the OpenDevice() function. *
- ;* IO_UNIT Set by the OpenDevice() function. *
- ;* IO_FLAGS If the IOB_QUICK bit is set, the device will *
- ;* -attempt- to handle the command on the caller's *
- ;* thread and avoid the overhead of a context *
- ;* switch when the Exec Message System is used. *
- ;* *
- ;* If the command had to be queued (and therefore *
- ;* the Exec Message System must be used), then *
- ;* IOB_QUICK bit is cleared in the request block. *
- ;* This means that the caller must use CheckIO() *
- ;* and WaitIO() calls to detect when the command *
- ;* is finished. *
- ;* *
- ;* Outputs: *
- ;* D0 - ????? *
- ;* IO_ERROR - Error code of operation (zero means success). *
- ;* *
- ;* All Original Registers Must Be Preserved Across Function Call!!!! *
- ;* *
- ;* Notes: *
- ;* The call to this routine is *NOT* single-threaded by Exec. *
- ;* *
- ;* The Exec WaitIO() function uses the IORequest node type *
- ;* (LN_TYPE) as a flag. If set to NT_MESSAGE, it assumes the *
- ;* request is still pending and will wait. If set to NT_REPLYMSG, *
- ;* it assumes the request is finished. It's the responsibility of *
- ;* the device to set the node type to NT_MESSAGE before returning *
- ;* to the user. *
- ;* *
- ;*********************************************************************
- DevBeginIO:
- IFGE INFO_LEVEL-1
- BCHG.B #1,$BFE001 ; Blink the Power LED for Debugging Purposes
- ENDC
-
- IFGE INFO_LEVEL-3
- CLR.L -(SP) ; Allocate and Clear a 32-bit Scratch Word on the Stack
- MOVE.W IO_COMMAND(A1),2(SP) ; Pickup the 16-bit Command Word
- PUTMSG 3,<'%s/BeginIO -- %ld'> ; Display a Debugging Message w/Command Code
- ADDQ.L #4,SP ; Deallocate the 32-bit Scratch Word from the Stack
- ENDC
-
- MOVEM.L D1/A0/A3,-(SP) ; Preserve Original Registers
- ;
- ; Perform Basic Operation Setup
- MOVE.B #NT_MESSAGE,LN_TYPE(A1) ; Set Node Type so WaitIO() is Happy
- MOVE.L IO_UNIT(a1),A3 ; Pick up Ptr to Unit Descriptor in A3
- MOVE.W IO_COMMAND(A1),D0 ; Pick up Desired Command Code in D0
- ;
- ; Validate the Range of the Command Code
- CMP.W #CMDRANGE_END,D0 ; Is It In Range?
- BCC BeginIO_NoCmd ; Nope, Reject It and Signal Error
- ;
- ; Check For an Immediate Command and Process Them Now
- MOVE.L #IMMEDIATES,D1 ; Pick up the Immediate Command Mask
- DISABLE A0 ; Disable Interrupts (Also Prevents Task Switches)
- BTST.L D0,D1 ; Test Command Against Classification Mask
- BNE BeginIO_Immediate ; Yes, It is an Immediate Command!
- ;
- ; Check For a Never-Immediate Command and Queue Them
- MOVE.L #NEVERIMMED,D1 ; Pick up the Never-Immediate Command Mask
- BTST.L D0,D1 ; Test Command Against Classification Mask
- BNE.S BeginIO_QueueMsg ; Yes, It is a Never-Immediate Command!
- ;
- ; See if the Unit is Stopped and Queue the Command If So
- BTST #MDUB_STOPPED,UNIT_FLAGS(A3) ; Test Unit-Stopped Flag
- BNE BeginIO_QueueMsg ; Yes, Go Queue the Command for Later
- ;
- ; This is not an immediate command. See if the device is busy.
- ; If the device is not, do the command on the user's thread,
- ; else fire up the unit task. This type of arbitration is not
- ; really needed for a ram disk, but it is essential for a device
- ; to reliably work with shared hardware.
- ;
- ; When the lines below are ";" commented out, the task gets a
- ; better workout. When the lines are active, the calling process
- ; is usually used for the operation.
- ;
- ; REMEMBER: Never Wait() on the user's thread in BeginIO()! The
- ; only exception is when the user has indicated it is ok by
- ; setting the "quick" bit.
- BSET #UNITB_ACTIVE,UNIT_FLAGS(A3) ; Set the Unit-Active Flag
- BEQ.S BeginIO_Immediate
- ;
- ; Queue I/O Request for Unit Task for Pick Up and Execute
- BeginIO_QueueMsg:
- BSET #UNITB_INTASK,UNIT_FLAGS(A3)
- BCLR #IOB_QUICK,IO_FLAGS(A1) ; Clear the I/O Quick Flag
- ENABLE A0 ; Enable Interrupts (and Task Switching)
-
- IFGE INFO_LEVEL-250
- MOVE.L A1,-(SP) ; Allocate and Store into a 32-bit Scratch Word
- MOVE.L A3,-(SP) ; Allocate and Store into a 32-bit Scratch Word
- PUTMSG 250,<'%s/PutMsg: Port=%lx Message=%lx'>
- ADDQ.L #8,SP ; Deallocate Scratch Words from Stack
- ENDC
- ;
- ; Send I/O Request Message to the Unit Task's Message Port
- MOVE.L A3,A0 ; Put Ptr to Unit Descriptor into A0 for PutMsg()
- LINKSYS PutMsg,md_SysLib(A6) ; Ptr to Port:A0, Ptr to Message:A1
- BRA.S BeginIO_End ; Command Queued for Later, Jump to Function Exit
- ;
- ; Perform the Command on the Thread of the Calling Process
- BeginIO_Immediate:
- ENABLE A0 ; Enable Interrupts (and Task Switches)
- BSR.S PerformIO
- BeginIO_End:
- PUTMSG 200,<'%s/BeginIO_End'>
- MOVEM.L (SP)+,D1/A0/A3 ; Restore Original Registers
- RTS
-
- BeginIO_NoCmd:
- MOVE.B #IOERR_NOCMD,IO_ERROR(A1) ; Signal Error - No Such Command
- BRA.S BeginIO_End ; Jump to Function Exit
-
- ;*********************************************************************
- ;* AbortIO Device Routine *
- ;* *
- ;* This function aborts an I/O request in progress. If the request *
- ;* is active, it is stopped immediately. If the request is still *
- ;* queued, it is removed from the queue. The request is returned *
- ;* in the same way as if it had normally completed. *
- ;* *
- ;* Inputs: *
- ;* A6 - Ptr to our Device node. *
- ;* A1 - Ptr to the caller's I/O request block as initialized by *
- ;* OpenDevice(). *
- ;* *
- ;* Outputs: *
- ;* D0 - Set to #IOERR_ABORTED *
- ;* IO_ERROR - ????? *
- ;* *
- ;* All Original Registers Must Be Preserved Across Function Call!!!! *
- ;* *
- ;* Notes: *
- ;* An AbortIO() is a -request- to "hurry up" processing of an I/O *
- ;* request. If the request was already complete, nothing happens. *
- ;* The message must be replied with ReplyMsg() as normal. *
- ;* *
- ;*********************************************************************
- DevAbortIO:
- MOVEQ #IOERR_NOCMD,D0 ; Return "AbortIO() Request Failed"
- RTS ; (Can't Abort I/O to Our Ramdisk)
-
- ;*********************************************************************
- ;* *
- ;*********************************************************************
- END
-
-