[comp.sys.amiga] HOW THE IO-DEVICE CALLS WORK .... Need Help? Read this!

dillon@CORY.BERKELEY.EDU (Matt Dillon) (12/24/87)

>	A first step: dump the GetMsg and CheckIO, just WaitIO (if you don't
>mind waiting, and know it'll be sent back.)  Next step, if it still doesn't
>work, triple-check everything, make sure you're not playing with it anywhere
>you shouldn't, snapshot the list before and after the WaitIO (Note: the
	
	People are still arguing about this?  I agree that device IO could
be better documented, but lets get it straight!  Here is a rundown of 
the device interface.

	(1) NEVER GetMsg() an iorequest... you GetMsg() the port the request
	    gets replied to, and even that is rarely done.

	(2) NEVER GetMsg() the reply port and assume the request has been
	    returned without looking at the return value of GetMsg()... if
	    it is your request, it's done, if it is NULL, it's not done.  If
	    CheckIO() returns TRUE and the request is the only thing using
	    the reply port, then you CAN GetMsg() it... but generally WaitIO()
	    would be used in that case rather than GetMsg().

	(3) You can Remove() the request from the reply port IF CheckIO()
	    return TRUE, or you can simply WaitIO() the request.  WaitIO()
	    automatically removes the request for you.

	(4) AbortIO() DOES NOT END A REQUEST!  You still need to WaitIO()
	    the request.  AbortIO() simply tells the device driver to abort
	    the request as soon as possible... the device driver might not
	    be able to abort the request, or the request might already be
	    returned.

	DoIO()		syncronous request, no reply port required, request
			is sent and the call does not return until the request
			returns.  

			DoIO() has its own internal replyport which is used
			if the device is unable to do the request syncronously.

	SendIO()	Asyncronout request, you MUST supply a reply port
			in the request structure.  The request does not 
			complete until it is returned to the reply port.

	BeginIO()	Syncronous OR Asyncronous request.. DIRECT CALL INTO
			THE DEVICE.  DO NOT USE UNLESS YOU ARE KNOW WHAT
			YOU'RE DOING!!!  

			Asyncronous/Syncronous operation depends on the 
			IOF_QUICK bit in the flags field.  If SET, the 
			operation is SYNCRONOUS, otherwise ASYNCRONOUS.  
			NOTE that the IO device can CHANGE the operation from
			syncronous to asyncronous if it cannot accomplish it
			syncronously.  Thus, if you set the IOF_QUICK flag,
			you must check it after the BeginIO() call and WaitIO()
			the request if IOF_QUICK has been cleared.

			the IORequest must therefore ALWAYS have a valid 
			ReplyPort... no matter what!  DoIO(), on the otherhand,
			handles this complex operation for you and should be
			used in most cases.

			Some devices, like the serial.device, depend on 
			certain fields in the Flags to be cleared, and thus
			assumes DoIO()/SendIO() are used.  Other devices, 
			like the audio.device, depend on certain fields in
			the Flags NOT to be cleared, and thus the more 
			complicated BeginIO() MUST be used for proper
			operation.

	AbortIO()	ADVISES the device driver to abort the request if
			possible.  The device driver may or may not be able
			to abort the request (that is, this may be a NOP to
			some devices).  Alternately, the device driver may
			not be able to abort the request immediately.

			This does NOT cause the request to be returned!!!
	
	CheckIO()	Checks if a request has completed or not.  Used with
			asyncronous (SendIO()'d) requests.  Returns TRUE if
			the request has completed, and you can then Remove() the
			request from the reply port.  Calling WaitIO() instead
			of Remove() accomplishes the same feat with about the
			same overhead.

			in this case, you may only Remove() the request 
			(assume it has completed) if CheckIO() returns TRUE.

	WaitIO()	WAITS for the request to complete, then REMOVES the
			request from the reply port for you.  It does not
			matter if the request has already completed by the
			time you make this call.  The request should have been
			started as an asyncronous request (with exception to
			BeginIO()d requests that got changed by the device
			driver to asyncronous from syncronous).

			The request MUST have a replyport.  The ROM code does
			the following:

				-check if request syncronous by looking at
				 IOF_QUICK.  If syncronous, return immediately.
				-while the mn_Type field in the message port 
				 is not 7 (REPLYMSG), do a Wait() on the 
				 signal bits and loop.
				-Remove() the request from the message port
			

	UNDER NO CIRCUMSTANCES SHOULD YOU WaitIO() OR Remove() A REQUEST 
	TWICE IN A ROW!  Although WaitIO() is generally robust enough,
	Removing() a request twice without an intervening asyncronous
	operation (SendIO()) will cause havoc!

	UNDER NO CIRCUMSTANCES SHOULD YOU EVER MAKE ASSUMPTIONS ABOUT THE
	STATE OF A REQUEST.  Never assume a request has completed until
	either after a WaitIO(), until a GetMsg() returns the request, or
	until a CheckIO() tells you the request has completed.

FURTHER READING:	
	Look at the DIO.C module in my SUPLIB support library in sources.

					-Matt

P.S. Written at 3:30a.m., with several DB's and DME reference windows running
to double check items of interest