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