Use correct structures
[AROS.git] / rom / devs / ata / bus_class.c
blobcace3ccfd8e7213ed008f0855b1c47ccfec566a8
1 #include <aros/debug.h>
2 #include <hidd/ata.h>
3 #include <hidd/pci.h>
4 #include <oop/oop.h>
5 #include <utility/tagitem.h>
6 #include <proto/exec.h>
7 #include <proto/oop.h>
8 #include <proto/utility.h>
10 #include "ata.h"
12 #define DIRQ(x)
14 static void Hidd_ATABus_HandleIRQ(UBYTE status, struct ata_Bus *bus)
16 struct ata_Unit *unit = bus->ab_SelectedUnit;
19 * don't waste your time on checking other devices.
20 * pass irq ONLY if task is expecting one;
22 if (unit && bus->ab_HandleIRQ)
24 /* ok, we have a routine to handle any form of transmission etc. */
25 DIRQ(bug("[ATA%02d] IRQ: Calling dedicated handler 0x%p... \n",
26 unit->au_UnitNum, bus->ab_HandleIRQ));
27 bus->ab_HandleIRQ(unit, status);
29 return;
32 DIRQ({
34 * if we got *here* then device is most likely not expected to have an irq.
36 bug("[ATA%02d] Spurious IRQ\n", unit ? unit->au_UnitNum : -1);
38 if (0 == (ATAF_BUSY & status))
40 bug("[ATA ] STATUS: %02lx\n" , status);
41 bug("[ATA ] ALT STATUS: %02lx\n" , PIO_InAlt(bus, ata_AltStatus));
42 bug("[ATA ] ERROR: %02lx\n" , PIO_In(bus, ata_Error));
43 bug("[ATA ] IRQ: REASON: %02lx\n", PIO_In(bus, atapi_Reason));
45 });
48 static AROS_INTH1(ataBus_Reset, struct ata_Bus *, bus)
50 AROS_INTFUNC_INIT
52 struct ataBase *ATABase = bus->ab_Base;
53 OOP_Object *obj = (void *)bus - ATABase->ataClass->InstOffset;
55 HIDD_ATABus_Shutdown(obj);
56 return FALSE;
58 AROS_INTFUNC_EXIT
61 /*****************************************************************************************
63 NAME
64 --background--
66 LOCATION
67 CLID_Hidd_ATABus
69 NOTES
70 This class serves as a base class for implementing IDE (ATA) bus drivers.
71 One particularity of this class is that IDE bus is very speed-critical.
72 At the other hand, the driver implements very lowlevel operations which
73 are called quite often. OOP_DoMethod() call is not fast enough, and in
74 order to curcumvent this limitation, additionally to normal OOP API
75 IDE bus drivers offer two additional non-standard interfaces. Internally
76 they are implemented as library-alike function table plus driver-specific
77 data. For the purpose of some performance optimizations the function
78 table is private to ata.device and managed entirely by the base class.
79 Driver classes have access only to data portion.
81 These interfaces are documented below.
83 *****************************************************************************************/
84 /*****************************************************************************************
86 NAME
87 --PIO interface--
89 LOCATION
90 CLID_Hidd_ATABus
92 NOTES
93 PIO interface is responsible for accessing I/O registers on the IDE
94 bus, as well as performing PIO-mode 16- and 32-bit data transfers.
95 This interface is mandatory and must be implemented by the driver,
96 however some functions are optional. They can be either omitted
97 entirely from the function table, or set to NULL pointers.
99 Control functions table for the interface consists of the following
100 functions (listed in their order in the array):
102 VOID ata_out(void *obj, UBYTE val, UWORD offset)
103 - Write byte into primary register bank with the given offset.
105 UBYTE ata_in(void *obj, UWORD offset)
106 - Read byte from primary register bank with the given offset.
108 VOID ata_out_alt(void *obj, UBYTE val, UWORD offset)
109 - Write byte into alternate register bank with the given offset.
110 This function is optional.
112 UBYTE ata_in_alt(void *obj, UWORD offset)
113 - Read byte from alternate register bank with the given offset.
114 This function is optional.
116 Transfer functions table for the interface consists of the following
117 functions (listed in their order in the array):
119 VOID ata_outsw(void *obj, APTR address, ULONG count)
120 - Perform 16-bit PIO data write operation from the given memory
121 region of the given size.
123 VOID ata_insw(void *obj, APTR address, ULONG count)
124 - Perform 16-bit PIO data read operation into the given memory
125 region of the given size.
127 VOID ata_outsl(void *obj, APTR address, ULONG count)
128 - Perform 32-bit PIO data write operation from the given memory
129 region of the given size. This function is optional.
131 UBYTE ata_insl(void *obj, APTR address, ULONG count)
132 - Perform 32-bit PIO data read operation into the given memory
133 region of the given size. This function is optional.
135 *****************************************************************************************/
136 /*****************************************************************************************
138 NAME
139 --DMA interface--
141 LOCATION
142 CLID_Hidd_ATABus
144 NOTES
145 DMA interface is optional, and is needed in order to support DMA data
146 transfers.
148 Function table for the interface consists of the following functions:
150 BOOL dma_Setup(void *obj, APTR buffer, IPTR size, BOOL read)
151 - Prepare the controller to DMA data transfer. The last argument is
152 TRUE for read operation and FALSE for write. The function should
153 return TRUE for success or FALSE for failure.
155 VOID dma_Start(void *obj)
156 - Start DMA transfer.
158 VOID dma_End(void *obj, APTR buffer, IPTR size, BOOL read)
159 - End DMA transfer and perform post-transfer cleanup of the given region.
161 ULONG dma_Result(void *obj)
162 - Get resulting status of the operation. The function should return 0
163 for succesful completion or error code to be passed up to ata.device
164 caller in io_Result field of the IORequest.
166 *****************************************************************************************/
167 /*****************************************************************************************
169 NAME
170 aoHidd_ATABus_Use80Wire
172 SYNOPSIS
173 [..G], BOOL
175 LOCATION
176 CLID_Hidd_ATABus
178 FUNCTION
179 Tells whether the bus currently uses 80-conductor cable.
181 NOTES
183 EXAMPLE
185 BUGS
187 SEE ALSO
189 INTERNALS
191 *****************************************************************************************/
192 /*****************************************************************************************
194 NAME
195 aoHidd_ATABus_Use32Bit
197 SYNOPSIS
198 [.SG], BOOL
200 LOCATION
201 CLID_Hidd_ATABus
203 FUNCTION
204 When queried, tells whether the bus supports 32-bit PIO data transfers.
205 When set, enables or disables 32-bit mode for PIO data transfers.
207 NOTES
209 EXAMPLE
211 BUGS
213 SEE ALSO
215 INTERNALS
217 *****************************************************************************************/
218 /*****************************************************************************************
220 NAME
221 aoHidd_ATABus_UseDMA
223 SYNOPSIS
224 [..G], BOOL
226 LOCATION
227 CLID_Hidd_ATABus
229 FUNCTION
230 Tells whether the bus supports DMA transfers.
232 NOTES
234 EXAMPLE
236 BUGS
238 SEE ALSO
240 INTERNALS
241 Default implementation in base class returns value depending on whether
242 the subclass provided DMA interface function table during object creation.
244 *****************************************************************************************/
245 /*****************************************************************************************
247 NAME
248 aoHidd_ATABus_PIODataSize
250 SYNOPSIS
251 [I..], BOOL
253 LOCATION
254 CLID_Hidd_ATABus
256 FUNCTION
257 Specifies size of PIO interface data structure.
259 NOTES
261 EXAMPLE
263 BUGS
265 SEE ALSO
267 INTERNALS
269 *****************************************************************************************/
270 /*****************************************************************************************
272 NAME
273 aoHidd_ATABus_DMADataSize
275 SYNOPSIS
276 [I..], BOOL
278 LOCATION
279 CLID_Hidd_ATABus
281 FUNCTION
282 Specifies size of DMA interface data structure.
284 NOTES
286 EXAMPLE
288 BUGS
290 SEE ALSO
292 INTERNALS
294 *****************************************************************************************/
295 /*****************************************************************************************
297 NAME
298 aoHidd_ATABus_BusVectors
300 SYNOPSIS
301 [I..], APTR *
303 LOCATION
304 CLID_Hidd_ATABus
306 FUNCTION
307 Specifies control functions table for building PIO interface object.
308 The function table is an array of function pointers terminated
309 by -1 value. The terminator must be present for purpose of
310 binary compatibility with future extensions.
312 NOTES
313 This function table is mandatory to be implemented by the driver.
315 EXAMPLE
317 BUGS
319 SEE ALSO
321 INTERNALS
323 *****************************************************************************************/
324 /*****************************************************************************************
326 NAME
327 aoHidd_ATABus_PIOVectors
329 SYNOPSIS
330 [I..], APTR *
332 LOCATION
333 CLID_Hidd_ATABus
335 FUNCTION
336 Specifies transfers function table for building PIO interface object.
337 The function table is an array of function pointers terminated
338 by -1 value. The terminator must be present for purpose of
339 binary compatibility with future extensions.
341 NOTES
342 This function table is mandatory to be implemented by the driver.
344 EXAMPLE
346 BUGS
348 SEE ALSO
350 INTERNALS
352 *****************************************************************************************/
353 /*****************************************************************************************
355 NAME
356 aoHidd_ATABus_DMAVectors
358 SYNOPSIS
359 [I..], APTR *
361 LOCATION
362 CLID_Hidd_ATABus
364 FUNCTION
365 Specifies function table for building DMA interface object. If not supplied,
366 the bus is considered not DMA-capable.
368 NOTES
370 EXAMPLE
372 BUGS
374 SEE ALSO
375 aoHidd_ATABus_PIOVectors
377 INTERNALS
379 *****************************************************************************************/
380 /*****************************************************************************************
382 NAME
383 aoHidd_ATABus_IRQHandler
385 SYNOPSIS
386 [.S.], APTR
388 LOCATION
389 CLID_Hidd_ATABus
391 FUNCTION
392 Specifies IRQ handler function to be called when bus interrupt arrives.
393 The function shoule be called using "C" calling convention and has the
394 following prototype:
396 void ata_HandleIRQ(UBYTE status, APTR userdata);
398 Your driver should pass the following arguments to this function:
399 status - value read from ATA main status register.
400 userdata - value of aoHidd_ATABus_IRQData attribute.
402 NOTES
403 Reading drive status register is a part of interrupt acknowledge
404 process, thus it has to be done by the driver.
406 It is driver's job to check whether the interrupt really belongs to
407 the IDE bus. A generic way to do this is to test ATAF_BUSY bit of
408 the status register for being zero. However, this may not work
409 reliably with IRQ sharing, so advanced IDE controllers may offer
410 different, better way to do this.
412 EXAMPLE
414 BUGS
416 SEE ALSO
417 aoHidd_ATABus_IRQData
419 INTERNALS
421 *****************************************************************************************/
422 /*****************************************************************************************
424 NAME
425 aoHidd_ATABus_IRQData
427 SYNOPSIS
428 [.S.], APTR
430 LOCATION
431 CLID_Hidd_ATABus
433 FUNCTION
434 Caller's private data to be supplied to IRQ handler function.
436 NOTES
438 EXAMPLE
440 BUGS
442 SEE ALSO
443 aoHidd_ATABus_IRQData
445 INTERNALS
447 *****************************************************************************************/
449 OOP_Object *ATABus__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
451 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, &msg->mID);
452 if (o)
454 struct ataBase *ATABase = cl->UserData;
455 struct ata_Bus *data = OOP_INST_DATA(cl, o);
456 struct TagItem *tstate = msg->attrList;
457 struct TagItem *tag;
459 while ((tag = NextTagItem(&tstate)))
461 ULONG idx;
463 Hidd_ATABus_Switch(tag->ti_Tag, idx)
465 case aoHidd_ATABus_PIODataSize:
466 data->pioDataSize = tag->ti_Data;
467 break;
469 case aoHidd_ATABus_DMADataSize:
470 data->dmaDataSize = tag->ti_Data;
471 break;
473 case aoHidd_ATABus_BusVectors:
474 data->busVectors = (APTR *)tag->ti_Data;
475 break;
477 case aoHidd_ATABus_PIOVectors:
478 data->pioVectors = (struct ATA_PIOInterface *)tag->ti_Data;
479 break;
481 case aoHidd_ATABus_DMAVectors:
482 data->dmaVectors = (APTR *)tag->ti_Data;
483 break;
487 /* Cache device base pointer. Useful. */
488 data->ab_Base = ATABase;
490 /* Install reset callback */
491 data->ab_ResetInt.is_Node.ln_Name = ATABase->ata_Device.dd_Library.lib_Node.ln_Name;
492 data->ab_ResetInt.is_Code = (VOID_FUNC)ataBus_Reset;
493 data->ab_ResetInt.is_Data = data;
494 AddResetCallback(&data->ab_ResetInt);
496 return o;
499 void ATABus__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
501 struct ata_Bus *data = OOP_INST_DATA(cl, o);
503 RemResetCallback(&data->ab_ResetInt);
505 if (data->dmaInterface)
507 void *ptr = data->dmaInterface - sizeof(struct ATA_DMAInterface);
509 FreeMem(ptr, sizeof(struct ATA_DMAInterface) + data->dmaDataSize);
511 if (data->pioInterface)
513 void *ptr = data->pioInterface - sizeof(struct ATA_BusInterface);
515 FreeMem(ptr, sizeof(struct ATA_BusInterface) + data->pioDataSize);
518 OOP_DoSuperMethod(cl, o, msg);
521 void ATABus__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
523 struct ataBase *ATABase = cl->UserData;
524 struct ata_Bus *data = OOP_INST_DATA(cl, o);
525 ULONG idx;
527 Hidd_ATABus_Switch (msg->attrID, idx)
529 case aoHidd_ATABus_Use80Wire:
530 /* CHECKME: Is there any generic way to check this ? */
531 *msg->storage = FALSE;
532 return;
534 case aoHidd_ATABus_Use32Bit:
535 *msg->storage = (data->pioVectors->ata_outsl &&
536 data->pioVectors->ata_insl) ? TRUE : FALSE;
537 return;
539 case aoHidd_ATABus_UseDMA:
540 *msg->storage = data->dmaVectors ? TRUE : FALSE;
541 return;
544 OOP_DoSuperMethod(cl, o, &msg->mID);
547 /* Default ata_out_alt does nothing */
548 static void default_out_alt(void *obj, UBYTE val, UWORD offset)
553 /* Default ata_in_alt wraps AltStatus to status */
554 static UBYTE default_in_alt(void *obj, UWORD offset)
556 struct ATA_BusInterface *vec = obj - sizeof(struct ATA_BusInterface);
558 return vec->ata_in(obj, ata_Status);
561 static void CopyVectors(APTR *dest, APTR *src, unsigned int num)
563 unsigned int i;
565 for (i = 0; i < num; i++)
567 if (src[i] == (APTR *)-1)
568 return;
569 if (src[i])
570 dest[i] = src[i];
574 /*****************************************************************************************
576 NAME
577 moHidd_ATABus_GetPIOInterface
579 SYNOPSIS
580 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_GetPIOInterface *Msg);
582 APTR HIDD_ATABus_GetPIOInterface(void);
584 LOCATION
585 CLID_Hidd_ATABus
587 FUNCTION
588 Instantiates encapsulated PIO interface object and returns its
589 pointer.
591 INPUTS
592 None
594 RESULT
595 A pointer to opaque PIO interface object or NULL in case of failure.
597 NOTES
598 This method should be overloaded by driver subclasses in order to
599 initialize data portion of the interface object.
601 EXAMPLE
603 BUGS
605 SEE ALSO
606 moHidd_ATABus_GetDMAInterface
608 INTERNALS
609 Interface objects contain not only driver-specific data, but also
610 a private vector table. Because of this you cannot just AllocMem()
611 the necessary structure in your driver. Always call OOP_DoSuperMethod()
612 in order for the base class to instantiate the interface correctly.
614 *****************************************************************************************/
616 APTR ATABus__Hidd_ATABus__GetPIOInterface(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
618 struct ata_Bus *data = OOP_INST_DATA(cl, o);
619 struct ATA_BusInterface *vec;
621 vec = AllocMem(sizeof(struct ATA_BusInterface) + data->pioDataSize,
622 MEMF_PUBLIC|MEMF_CLEAR);
623 if (vec)
625 /* Some default vectors for simplicity */
626 vec->ata_out_alt = default_out_alt;
627 vec->ata_in_alt = default_in_alt;
629 CopyVectors((APTR *)vec, data->busVectors,
630 sizeof(struct ATA_BusInterface) / sizeof(APTR));
632 data->pioInterface = &vec[1];
633 return data->pioInterface;
636 return NULL;
639 /*****************************************************************************************
641 NAME
642 moHidd_ATABus_GetDMAInterface
644 SYNOPSIS
645 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_GetDMAInterface *Msg);
647 APTR HIDD_ATABus_GetDMAInterface(void);
649 LOCATION
650 CLID_Hidd_ATABus
652 FUNCTION
653 Instantiates encapsulated DMA interface object and returns its
654 pointer.
656 INPUTS
657 None
659 RESULT
660 A pointer to opaque DMA interface object or NULL upon failure or
661 if DMA is not supported by this bus.
663 NOTES
664 This method should be overloaded by driver subclasses in order to
665 initialize data portion of the interface object.
667 EXAMPLE
669 BUGS
671 SEE ALSO
672 moHidd_ATABus_GetPIOInterface
674 INTERNALS
675 Interface objects contain not only driver-specific data, but also
676 a private vector table. Because of this you cannot just AllocMem()
677 the necessary structure in your driver. Always call OOP_DoSuperMethod()
678 in order for the base class to instantiate the interface correctly.
680 *****************************************************************************************/
682 APTR ATABus__Hidd_ATABus__GetDMAInterface(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
684 struct ata_Bus *data = OOP_INST_DATA(cl, o);
685 struct ATA_DMAInterface *vec;
687 if (!data->dmaVectors)
688 return NULL;
690 vec = AllocMem(sizeof(struct ATA_DMAInterface) + data->dmaDataSize,
691 MEMF_PUBLIC|MEMF_CLEAR);
692 if (vec)
694 CopyVectors((APTR *)vec, data->dmaVectors,
695 sizeof(struct ATA_DMAInterface) / sizeof(APTR));
697 data->dmaInterface = &vec[1];
698 return data->dmaInterface;
701 return NULL;
704 /*****************************************************************************************
706 NAME
707 moHidd_ATABus_SetXferMode
709 SYNOPSIS
710 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_SetXferMode *Msg);
712 APTR HIDD_ATABus_SetXferMode(UBYTE unit, ata_XferMode mode);
714 LOCATION
715 CLID_Hidd_ATABus
717 FUNCTION
718 Sets the desired transfer mode for the given drive on the bus controller.
720 INPUTS
721 unit - drive number (0 for master and 1 for slave)
722 mode - Mode number (see hidd/ata.h)
724 RESULT
725 TRUE if succesful or FALSE if the desired mode is not supported
726 by the hardware.
728 NOTES
729 The default implementation is provided for drivers not supporting
730 DMA and always returns FALSE if the caller attempts to set any of
731 DMA modes.
733 EXAMPLE
735 BUGS
737 SEE ALSO
739 INTERNALS
741 *****************************************************************************************/
743 BOOL ATABus__Hidd_ATABus__SetXferMode(OOP_Class *cl, OOP_Object *o, struct pHidd_ATABus_SetXferMode *msg)
745 if ((msg->mode >= AB_XFER_MDMA0) && (msg->mode <= AB_XFER_UDMA6))
747 /* DMA is not supported, we cannot set DMA modes */
748 return FALSE;
751 return TRUE;
754 /*****************************************************************************************
756 NAME
757 moHidd_ATABus_Shutdown
759 SYNOPSIS
760 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_Shutdown *Msg);
762 APTR HIDD_ATABus_Shutdown(void);
764 LOCATION
765 CLID_Hidd_ATABus
767 FUNCTION
768 Instantly shutdown all activity on the bus.
770 INPUTS
771 None
773 RESULT
774 None
776 NOTES
777 This method is called by ata.device during system reset handler execution.
779 EXAMPLE
781 BUGS
783 SEE ALSO
785 INTERNALS
786 Default implementation disables interrupt using AltControl register.
788 *****************************************************************************************/
790 void ATABus__Hidd_ATABus__Shutdown(OOP_Class *cl, OOP_Object *o, OOP_Msg *msg)
792 struct ata_Bus *data = OOP_INST_DATA(cl, o);
794 if (data->pioInterface)
796 struct ATA_BusInterface *vec = data->pioInterface - sizeof(struct ATA_BusInterface);
798 vec->ata_out_alt(data->pioInterface, ATACTLF_INT_DISABLE, ata_AltControl);
802 /***************** Private nonvirtual methods follow *****************/
804 BOOL Hidd_ATABus_Start(OOP_Object *o, struct ataBase *ATABase)
806 struct ata_Bus *ab = OOP_INST_DATA(ATABase->busClass, o);
808 /* Attach IRQ handler */
809 OOP_SetAttrsTags(o, aHidd_ATABus_IRQHandler, Hidd_ATABus_HandleIRQ,
810 aHidd_ATABus_IRQData , ab,
811 TAG_DONE);
814 * Assign bus number.
815 * TODO: This does not take into account possibility to
816 * unload drivers. In this case existing units will disappear,
817 * freeing up their numbers. These numbers should be reused.
819 ab->ab_BusNum = ATABase->ata__buscount++;
821 /* scan bus - try to locate all devices (disables irq) */
822 ata_InitBus(ab);
825 * Start up bus task. It will perform scanning asynchronously, and
826 * then, if succesful, insert units. This allows to keep things parallel.
828 D(bug("[ATA>>] Start: Bus %u: Unit 0 - %d, Unit 1 - %d\n", ab->ab_BusNum, ab->ab_Dev[0], ab->ab_Dev[1]));
829 return NewCreateTask(TASKTAG_PC , BusTaskCode,
830 TASKTAG_NAME , "ATA[PI] Subsystem",
831 TASKTAG_STACKSIZE , STACK_SIZE,
832 TASKTAG_PRI , TASK_PRI,
833 TASKTAG_TASKMSGPORT, &ab->ab_MsgPort,
834 TASKTAG_ARG1 , ab,
835 TASKTAG_ARG2 , ATABase,
836 TAG_DONE) ? TRUE : FALSE;
839 AROS_UFH3(BOOL, Hidd_ATABus_Open,
840 AROS_UFHA(struct Hook *, h, A0),
841 AROS_UFHA(OOP_Object *, obj, A2),
842 AROS_UFHA(IPTR, reqUnit, A1))
844 AROS_USERFUNC_INIT
846 struct IORequest *req = h->h_Data;
847 struct ataBase *ATABase = (struct ataBase *)req->io_Device;
848 struct ata_Bus *b = (struct ata_Bus *)OOP_INST_DATA(ATABase->busClass, obj);
849 ULONG bus = reqUnit >> 1;
850 UBYTE dev = reqUnit & 1;
852 D(bug("[ATA%02ld] Checking bus %u dev %u\n", reqUnit, bus, dev));
854 if ((b->ab_BusNum == bus) && b->ab_Units[dev])
856 /* Got the unit */
857 req->io_Unit = &b->ab_Units[dev]->au_Unit;
858 req->io_Error = 0;
860 b->ab_Units[dev]->au_Unit.unit_OpenCnt++;
861 return TRUE;
864 return FALSE;
866 AROS_USERFUNC_EXIT
869 AROS_UFH3(BOOL, Hidd_ATABus_Tick,
870 AROS_UFHA(struct Hook *, h, A0),
871 AROS_UFHA(OOP_Object *, obj, A2),
872 AROS_UFHA(struct ataBase *, ATABase, A1))
874 AROS_USERFUNC_INIT
876 struct ata_Bus *bus = (struct ata_Bus *)OOP_INST_DATA(ATABase->busClass, obj);
877 LONG timeout = 0;
880 * This compare-decrement-fetch should be atomic, so we
881 * use Forbid() here.
882 * Not a good design, can anybody invent better one ?
884 Forbid();
885 if (bus->ab_Timeout >= 0)
886 timeout = --bus->ab_Timeout;
887 Permit();
889 if (timeout < 0)
890 Signal(bus->ab_Task, SIGBREAKF_CTRL_C);
892 return FALSE;
894 AROS_USERFUNC_EXIT