leh@otter.cis.ufl.edu (Les Hill) (05/21/91)
I have run into a situation which is not clearly documented (to me anyways) in the RKM's (v1.2 ?). Below I have included the relevant fragments of code: ... struct MsgPort *read_port, *write_port; struct IOExtSer *read_req, *write_req; ... BYTE dev_error; struct Message *read_msg; ... /* Clean up */ if (!CheckIO(read_req)) { AbortIO(read_req); if (dev_error = WaitIO(read_req)) { printf("Error waiting for aborted read -- %d\n", dev_error); goto cleanup_8; } read_msg = GetMsg(read_port); // not necessary? } ... The situation is this: a CMD_READ request *should* be queued at the device (the CheckIO() should confirm this), the CMD_READ request is then aborted and a WaitIO() follows as recommended in the RKMs; the WaitIO() returns a -2 (aborted request.) The question that comes to mind is: does WaitIO() dequeue the reply at read_port (read_port is the reply port for read_req) regardless of the error? Additionally, do I need the GetMsg()? Thanks in advance, Les -- Extraordinary crimes against the people and the state have to be avenged by agents extraordinary. Two such people are John Steed -- top professional, and his partner, Emma Peel -- talented amateur; otherwise known as "The Avengers." INTERNET: leh@ufl.edu UUCP: ...!gatech!uflorida!leh BITNET: vishnu@UFPINE
carolyn@cbmvax.commodore.com (Carolyn Scheppner - CATS) (05/21/91)
In article <28630@uflorida.cis.ufl.EDU> leh@otter.cis.ufl.edu (Les Hill) writes: >I have run into a situation which is not clearly documented (to me anyways) in the >RKM's (v1.2 ?). Below I have included the relevant fragments of code: >... > struct MsgPort *read_port, *write_port; > struct IOExtSer *read_req, *write_req; >... > BYTE dev_error; > struct Message *read_msg; >... > /* Clean up */ > if (!CheckIO(read_req)) { > AbortIO(read_req); > if (dev_error = WaitIO(read_req)) { > printf("Error waiting for aborted read -- %d\n", dev_error); > goto cleanup_8; > } > read_msg = GetMsg(read_port); // not necessary? > } >... > >The situation is this: a CMD_READ request *should* be queued at the device >(the CheckIO() should confirm this), the CMD_READ request is then aborted and >a WaitIO() follows as recommended in the RKMs; the WaitIO() returns a -2 >(aborted request.) > >The question that comes to mind is: does WaitIO() dequeue the reply at read_port (read_port is the reply port for read_req) regardless of the error? >Additionally, do I need the GetMsg()? NAME WaitIO -- wait for completion of an I/O request SYNOPSIS error = WaitIO(iORequest) D0 A1 BYTE WaitIO(struct IORequest *); FUNCTION This function waits for the specified I/O request to complete, then removes it from the replyport. If the I/O has already completed, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this function will return immediately. If you KNOW there is an outstanding request, I believe the best action is: if(!CheckIO(ioreq)) AbortIO(ioreq); WaitIO(ioreq); Then regardless of whether the request had already completed, it any signal it generated will be cleared and it will be removed from the port. -- ========================================================================== Carolyn Scheppner -- Tech. Mgr. CATS - Commodore Amiga Technical Support PHONE 215-431-9180 {uunet,rutgers}!cbmvax!carolyn carolyn@commodore.com Spice up old code with a dazzling array of pointers to void functions. ==========================================================================
efp90@ecs.soton.ac.uk (Pritchard EF) (05/21/91)
leh@otter.cis.ufl.edu (Les Hill) writes: >I have run into a situation which is not clearly documented (to me anyways) in the >RKM's (v1.2 ?). Below I have included the relevant fragments of code: >... > struct MsgPort *read_port, *write_port; > struct IOExtSer *read_req, *write_req; >... > BYTE dev_error; > struct Message *read_msg; >... > /* Clean up */ > if (!CheckIO(read_req)) { > AbortIO(read_req); > if (dev_error = WaitIO(read_req)) { > printf("Error waiting for aborted read -- %d\n", dev_error); > goto cleanup_8; > } > read_msg = GetMsg(read_port); // not necessary? > } >... >The situation is this: a CMD_READ request *should* be queued at the device >(the CheckIO() should confirm this), the CMD_READ request is then aborted and >a WaitIO() follows as recommended in the RKMs; the WaitIO() returns a -2 >(aborted request.) >The question that comes to mind is: does WaitIO() dequeue the reply at >read_port (read_port is the reply port for read_req) regardless of the error? >Additionally, do I need the GetMsg()? Look in the Revised and Updated RKM Libraries and Devices, page 292 under AbortIO(), it states that: The AbortIO() command may fail; if it succeeds, the device will stop processing the IORequest, and ** reply to it earlier than it may have done otherwise. AbortIO() does not ** remove the IORequest from your replyport... your program must wait for the ** reply message before actually reusing the IORequest... ** If a request has already completed... no action is taken. So YES, GetMsg() is required Hope that helps! >Thanks in advance, >Les >-- >Extraordinary crimes against the people and the state have to be avenged by >agents extraordinary. Two such people are John Steed -- top professional, and >his partner, Emma Peel -- talented amateur; otherwise known as "The Avengers." >INTERNET: leh@ufl.edu UUCP: ...!gatech!uflorida!leh BITNET: vishnu@UFPINE E.F.Pritchard. efp90@uk.ac.soton.ecs Department of Computer Science, Southampton University, Southampton, Hampshire, England.
bj@cbmvax.commodore.com (Brian Jackson) (05/22/91)
In article <7753@ecs.soton.ac.uk> efp90@ecs.soton.ac.uk (Pritchard EF) writes: >leh@otter.cis.ufl.edu (Les Hill) writes: > >>I have run into a situation which is not clearly documented (to me anyways) in the >>RKM's (v1.2 ?). Below I have included the relevant fragments of code: >>... >> struct MsgPort *read_port, *write_port; >> struct IOExtSer *read_req, *write_req; >>... >> BYTE dev_error; >> struct Message *read_msg; >>... >> /* Clean up */ >> if (!CheckIO(read_req)) { >> AbortIO(read_req); >> if (dev_error = WaitIO(read_req)) { ^^^^^^^^^^^^^^^^^ >> printf("Error waiting for aborted read -- %d\n", dev_error); >> goto cleanup_8; >> } >> read_msg = GetMsg(read_port); // not necessary? >> } >>... > >>The situation is this: a CMD_READ request *should* be queued at the device >>(the CheckIO() should confirm this), the CMD_READ request is then aborted and >>a WaitIO() follows as recommended in the RKMs; the WaitIO() returns a -2 >>(aborted request.) > >>The question that comes to mind is: does WaitIO() dequeue the reply at >>read_port (read_port is the reply port for read_req) regardless of the error? >>Additionally, do I need the GetMsg()? > >Look in the Revised and Updated RKM Libraries and Devices, page 292 >under AbortIO(), it states that: > >The AbortIO() command may fail; if it succeeds, the device will stop >processing the IORequest, and >** reply to it earlier than it may have done otherwise. AbortIO() does not >** remove the IORequest from your replyport... your program must wait for the >** reply message before actually reusing the IORequest... >** If a request has already completed... no action is taken. > >So YES, GetMsg() is required >Hope that helps! The GetMsg() is *not* required. He is (properly) doing a WaitIO() after the AbortIO() call and WaitIO() *does* remove the message. >E.F.Pritchard. Brian ----------------------------------------------------------------------- | Brian Jackson Software Engineer, Commodore-Amiga Inc. GEnie: B.J. | | bj@cbmvax.cbm.commodore.com or ...{uunet|rutgers}!cbmvax!bj | | "Sometimes the hamster falls asleep inside the little wheel..." | -----------------------------------------------------------------------
dillon@overload.Berkeley.CA.US (Matthew Dillon) (05/23/91)
In article <7753@ecs.soton.ac.uk> efp90@ecs.soton.ac.uk (Pritchard EF) writes: >leh@otter.cis.ufl.edu (Les Hill) writes: > >>I have run into a situation which is not clearly documented (to me anyways) in the >>.. >> >>The question that comes to mind is: does WaitIO() dequeue the reply at >>read_port (read_port is the reply port for read_req) regardless of the error? >>Additionally, do I need the GetMsg()? AbortIO(): Request IO device to abort an IO. The IO device will attempt to abort the IO as soon as possible. The result is that, sometime in the future, the IO device will return the IO request normally. If the IO request has already been returned no action will occur WaitIO(): This call WAITs for the IO request to be returned to its replyport, THEN REMOVES THE REQUEST FROM THE REPLY PORT. Thus, you do NOT MIX GetMsg() and WaitIO(). WaitIO() automatically removes the request from the replyport after waiting for it to be returned to the reply port. WaitIO() correctly handles the case where the request might have already been returned to the port and the case where the signal state may be random. The proper method to abort a queued IO request is: AbortIO(io); WaitIO(io); You do NOT need to CheckIO() before AbortIO()ing, though this does not hurt. I.E. if (!CheckIO(io)) // CheckIO() is unnecessary AbortIO(io); There are generally two methods to handle returned IO requests in your main loop: (1) Use Wait() and GetMsg(): mask = Wait(signals); if (mask & MyMsgPortSignalMask) { IORequest *io; while (io = GetMsg(MyMsgPort)) { if (io == (IORequest *)&MySerReadReq) { MySerReadReqInProgress = 0; ... } else if (io == (IORequest *)&MyTimerReq) { MyTimerReqInProgress = 0; ... } ... } } ... somewhere in your code ... SendIO(&MyTimerReq); MyTimerReqInProgress = 1; ... in your exit routine ... if (MyTimerReqInProgress) { AbortIO(&MyTimerReq); WaitIO(&MyTimerReq); MyTimerReqInProgress = 0; } This case assumes that you drain MyMsgPort completely before looping back to the Wait(). Note that in this case you DO NOT USE CHECKIO() OR WAITIO() on the messages returned by GetMsg(), since GetMsg() returning an IO request both unlinks it from the replyport and guarentees that the request had completed (by virtue of it having been returned to the replyport). If you are waiting on only one port, you can use WaitPort() instead of Wait(), in which case you can loop back up to the WaitPort() without having to drain *all* the messages on the message port (WaitPort() does not wait if there are messages already on the port). (2) Use Wait(), CheckIO(), and WaitIO() mask = Wait(signals); if (mask & MyMsgPortSignalMask) { /* * If in your loop certain requests are not always 'in progress', * you need another variable to tell your main loop whether * a given request is in progress or not, i.e. queued. */ if (MySerWriteReqIsInProgress) { if (CheckIO(&MySerWriteReq)) { WaitIO(&MySerWriteReq); MySerWriteReqIsInProgress = 0; ... } } /* * note, no else-if, must check ALL possible pending IO's. * * If the request is always in progress... say you ALWAYS * have your timer request queued so you get interval times * (e.g. once a second or something like that), then you * do not need a flag. */ if (CheckIO(&MyTimerReq)) { WaitIO(&MyTimerReq); ... MyTimerReq.tr_time.tv_secs = 1; MyTimerReq.tr_time.tv_micro= 0; SendIO(&MyTimerReq); } } ... In this case, you can also use WaitPort() instead of Wait() if you are waiting on only one signal. Here, we almost entirely ignore the message port itself. However, IO requests are still returned to the port and queued to its list so after we CheckIO() that it has been returned, we must WaitIO() to remove it from the message port's list. In the case of AbortIO(), if you know you previously queued a request, say our timer request above, then you can AbortIO() it as follows: AbortIO(io); WaitIO(io); Again, remember that AbortIO() is really only a 'hurry-up' request to the IO device and does NOT guarentee that the IO request will be immediately returned. WARNING: Many people make the mistake of using WaitIO() and AbortIO() on requests THEY HAVE ALREADY DEQUEUED OR NEVER SENT IN THE FIRST PLACE. THIS IS ILLEGAL. You can ONLY use WaitIO() and AbortIO() on requests that are currently in-progress or have been returned (but not dequeued) to the reply port. If you have an IO request -- say an asynchronous CMD_WRITE request to the serial.device that you do not always have queued, you need some kind of flag in your program to indicate its state so, for example, your myexit() routine doesn't attempt to AbortIO()/WaitIO() a request that was never queued or already dequeued via GetMsg() or WaitIO(). -Matt -- Matthew Dillon dillon@Overload.Berkeley.CA.US 891 Regal Rd. uunet.uu.net!overload!dillon Berkeley, Ca. 94708 USA
valentin@public.BTR.COM (Valentin Pepelea) (05/23/91)
In article <28630@uflorida.cis.ufl.EDU> leh@otter.cis.ufl.edu (Les Hill) writes: > > /* Clean up */ > if (!CheckIO(read_req)) { > AbortIO(read_req); > if (dev_error = WaitIO(read_req)) { > printf("Error waiting for aborted read -- %d\n", dev_error); > goto cleanup_8; > } > read_msg = GetMsg(read_port); // not necessary? > } >... > >The situation is this: a CMD_READ request *should* be queued at the device >(the CheckIO() should confirm this), Not really. The IO request could have been processed between the time ChechIO was called and AbortIO is about to be. >The question that comes to mind is: does WaitIO() dequeue the reply at >read_port (read_port is the reply port for read_req) regardless of the error? Yes, WaitIO() makes sure the message is dequeued. >Additionally, do I need the GetMsg()? No you don't. This is a bug. The line: > read_msg = GetMsg(read_port); // not necessary? should have read > else read_msg = GetMsg(read_port) However, you should note the the best method to perform the given operation is simply: AbortIO(IORequest); WaitIO(IORequest); If the IORequest had already completed, then AbortIO does nothing. Valentin -- "An operating system without virtual memory Name: Valentin Pepelea is an operating system without virtue." Phone: (408) 985-1700 Usenet: mips!btr!valentin - Ancient Inca Proverb Internet: valentin@btr.com
efp90@ecs.soton.ac.uk (Pritchard EF) (05/23/91)
In <21785@cbmvax.commodore.com> bj@cbmvax.commodore.com (Brian Jackson) writes: >The GetMsg() is *not* required. He is (properly) doing a WaitIO() >after the AbortIO() call and WaitIO() *does* remove the message. Oops! Thanks for picking me up on that, Brain! >Brian > ----------------------------------------------------------------------- > | Brian Jackson Software Engineer, Commodore-Amiga Inc. GEnie: B.J. | > | bj@cbmvax.cbm.commodore.com or ...{uunet|rutgers}!cbmvax!bj | > | "Sometimes the hamster falls asleep inside the little wheel..." | > ----------------------------------------------------------------------- E.F.Pritchard. efp90
oliphant@telepro.UUCP (Mike Oliphant) (05/24/91)
In article <21757@cbmvax.commodore.com> carolyn@cbmvax.commodore.com (Carolyn Scheppner - CATS) writes: >If you KNOW there is an outstanding request, I believe the best >action is: > >if(!CheckIO(ioreq)) AbortIO(ioreq); >WaitIO(ioreq); The CheckIO() is EXTREMELY important with the A2232 serial card - it doesn't like you aborting requests that have been satisfied. In fact, it seems that even the CheckIO() safety measure is not enough with this card. I've found this method solves the problem: NiceAbort(ioreq) struct IORequest *ioreq; { Forbid(); if(!CheckIO(ioreq)) AbortIO(ioreq); Permit(); WaitIO(ioreq); } A program called 'A2232Patch' by Reid Bishop uses SetFunction() to turn all AbortIO() calls into NiceAborts. Without this patch, doing complex things with the serial port (such as spawning a BBS from a front-end FidoNet mailer) is likely to fail miserably on the A2232 (unless the software in question does NiceAborts itself). Hopefully, this bug in the A2232 will be fixed (the standard serial.device has no such problem) and these contortions will be rendered unneccesary. -- Mike Oliphant telepro!oliphant@herald.usask.ca or herald!telepro!oliphant FidoNet: (1:140/91) - ZMH only * * Call TelePro, the development system for DLG Professional * * Phone: +1 306 249 2352 2400/9600/14400 bps HST - FidoNet: (1:140/90) * +1 306 652 2084 300/1200/2400 bps *
valentin@public.BTR.COM (Valentin Pepelea) (05/25/91)
In article <oliphant.8324@telepro.UUCP> oliphant@telepro.UUCP (Mike Oliphant) writes: > >The CheckIO() is EXTREMELY important with the A2232 serial card - it doesn't >like you aborting requests that have been satisfied. Definitely a bug in the A2232 device driver. It seems like every other CBM device driver has a problem with AbortIO(). Make sure you report the bug to bugs@cbmvax.commodore.com. With luck and prayers, you will even receive an acknowledgement. Valentin -- "An operating system without virtual memory Name: Valentin Pepelea is an operating system without virtue." Phone: (408) 985-1700 Usenet: mips!btr!valentin - Ancient Inca Proverb Internet: valentin@btr.com
dillon@overload.Berkeley.CA.US (Matthew Dillon) (05/29/91)
In article <oliphant.8324@telepro.UUCP> oliphant@telepro.UUCP (Mike Oliphant) writes: >In article <21757@cbmvax.commodore.com> carolyn@cbmvax.commodore.com (Carolyn Scheppner - CATS) writes: >.. >>If you KNOW there is an outstanding request, I believe the best >>action is: >> >>if(!CheckIO(ioreq)) AbortIO(ioreq); >>WaitIO(ioreq); > >The CheckIO() is EXTREMELY important with the A2232 serial card - it doesn't >like you aborting requests that have been satisfied. In fact, it seems that This is a bug in the A2232 serial.device It *has* been fixed in alphas of the next release, along with a few other bugs. >even the CheckIO() safety measure is not enough with this card. I've found >this method solves the problem: > > NiceAbort(ioreq) > struct IORequest *ioreq; > { > Forbid(); > if(!CheckIO(ioreq)) AbortIO(ioreq); > Permit(); > WaitIO(ioreq); > } I'm not sure this will work. If the A2232 serial.device uses a SoftInt instead of a process to handle returning requests, then all the Forbid()/Permit() does is reduce the window of oportunity. But it does sound like a good temporary solution to the problem! You need to use Disable/Enable though, however bad that may sound. >-- >Mike Oliphant telepro!oliphant@herald.usask.ca or herald!telepro!oliphant > FidoNet: (1:140/91) - ZMH only >* >* Call TelePro, the development system for DLG Professional >* >* Phone: +1 306 249 2352 2400/9600/14400 bps HST - FidoNet: (1:140/90) >* +1 306 652 2084 300/1200/2400 bps >* -Matt -- Matthew Dillon dillon@Overload.Berkeley.CA.US 891 Regal Rd. uunet.uu.net!overload!dillon Berkeley, Ca. 94708 USA
oliphant@telepro.UUCP (Mike Oliphant) (05/30/91)
In article <dillon.8069@overload.Berkeley.CA.US> dillon@overload.Berkeley.CA.US (Matthew Dillon) writes: >>The CheckIO() is EXTREMELY important with the A2232 serial card - it doesn't >>like you aborting requests that have been satisfied. In fact, it seems that > > This is a bug in the A2232 serial.device > > It *has* been fixed in alphas of the next release, along with a few > other bugs. Great! We've been living with this bug for over 6 months now... >>even the CheckIO() safety measure is not enough with this card. I've found >>this method solves the problem: >> >> NiceAbort(ioreq) >> struct IORequest *ioreq; >> { >> Forbid(); >> if(!CheckIO(ioreq)) AbortIO(ioreq); >> Permit(); >> WaitIO(ioreq); >> } > > I'm not sure this will work. If the A2232 serial.device uses a SoftInt > instead of a process to handle returning requests, then all the > Forbid()/Permit() does is reduce the window of oportunity. It seems to work fairly well - well enough to keep things held together until we can get our hands on the fixed device. -- Mike Oliphant telepro!oliphant@herald.usask.ca or herald!telepro!oliphant FidoNet: (1:140/91) - ZMH only * * Call TelePro, the development system for DLG Professional * * Phone: +1 306 249 2352 2400/9600/14400 bps HST - FidoNet: (1:140/90) * +1 306 652 2084 300/1200/2400 bps *