2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
6 #include <aros/debug.h>
9 #include <utility/tagitem.h>
10 #include <proto/exec.h>
11 #include <proto/oop.h>
12 #include <proto/utility.h>
19 static void Hidd_ATABus_HandleIRQ(UBYTE status
, struct ata_Bus
*bus
)
21 struct ata_Unit
*unit
= bus
->ab_SelectedUnit
;
24 * don't waste your time on checking other devices.
25 * pass irq ONLY if task is expecting one;
27 if (unit
&& bus
->ab_HandleIRQ
)
29 /* ok, we have a routine to handle any form of transmission etc. */
30 DIRQ(bug("[ATA%02d] IRQ: Calling dedicated handler 0x%p... \n",
31 unit
->au_UnitNum
, bus
->ab_HandleIRQ
));
32 bus
->ab_HandleIRQ(unit
, status
);
39 * if we got *here* then device is most likely not expected to have an irq.
41 bug("[ATA%02d] Spurious IRQ\n", unit
? unit
->au_UnitNum
: -1);
43 if (0 == (ATAF_BUSY
& status
))
45 bug("[ATA ] STATUS: %02lx\n" , status
);
46 bug("[ATA ] ALT STATUS: %02lx\n" , PIO_InAlt(bus
, ata_AltStatus
));
47 bug("[ATA ] ERROR: %02lx\n" , PIO_In(bus
, ata_Error
));
48 bug("[ATA ] IRQ: REASON: %02lx\n", PIO_In(bus
, atapi_Reason
));
53 static AROS_INTH1(ataBus_Reset
, struct ata_Bus
*, bus
)
57 struct ataBase
*ATABase
= bus
->ab_Base
;
58 OOP_Object
*obj
= (void *)bus
- ATABase
->busClass
->InstOffset
;
60 HIDD_ATABus_Shutdown(obj
);
67 /*****************************************************************************************
76 This class serves as a base class for implementing IDE (ATA) bus drivers.
77 One particularity of this class is that IDE bus is very speed-critical.
78 At the other hand, the driver implements very lowlevel operations which
79 are called quite often. OOP_DoMethod() call is not fast enough, and in
80 order to circumvent this limitation, additionally to normal OOP API
81 IDE bus drivers offer two additional non-standard interfaces. Internally
82 they are implemented as library-alike function table plus driver-specific
83 data. For the purpose of some performance optimizations the function
84 table is private to ata.device and managed entirely by the base class.
85 Driver classes have access only to data portion.
87 These interfaces are documented below.
89 *****************************************************************************************/
90 /*****************************************************************************************
99 PIO interface is responsible for accessing I/O registers on the IDE
100 bus, as well as performing PIO-mode 16- and 32-bit data transfers.
101 This interface is mandatory and must be implemented by the driver,
102 however some functions are optional. They can be either omitted
103 entirely from the function table, or set to NULL pointers.
105 Control functions table for the interface consists of the following
106 functions (listed in their order in the array):
108 VOID ata_out(void *obj, UBYTE val, UWORD offset)
109 - Write byte into primary register bank with the given offset.
111 UBYTE ata_in(void *obj, UWORD offset)
112 - Read byte from primary register bank with the given offset.
114 VOID ata_out_alt(void *obj, UBYTE val, UWORD offset)
115 - Write byte into alternate register bank with the given offset.
116 This function is optional.
118 UBYTE ata_in_alt(void *obj, UWORD offset)
119 - Read byte from alternate register bank with the given offset.
120 This function is optional.
122 Transfer functions table for the interface consists of the following
123 functions (listed in their order in the array):
125 VOID ata_outsw(void *obj, APTR address, ULONG count)
126 - Perform 16-bit PIO data write operation from the given memory
127 region of the given size.
129 VOID ata_insw(void *obj, APTR address, ULONG count)
130 - Perform 16-bit PIO data read operation into the given memory
131 region of the given size.
133 VOID ata_outsl(void *obj, APTR address, ULONG count)
134 - Perform 32-bit PIO data write operation from the given memory
135 region of the given size. This function is optional.
137 UBYTE ata_insl(void *obj, APTR address, ULONG count)
138 - Perform 32-bit PIO data read operation into the given memory
139 region of the given size. This function is optional.
141 *****************************************************************************************/
142 /*****************************************************************************************
151 DMA interface is optional, and is needed in order to support DMA data
154 Function table for the interface consists of the following functions:
156 BOOL dma_Setup(void *obj, APTR buffer, IPTR size, BOOL read)
157 - Prepare the controller to DMA data transfer. The last argument is
158 TRUE for read operation and FALSE for write. The function should
159 return TRUE for success or FALSE for failure.
161 VOID dma_Start(void *obj)
162 - Start DMA transfer.
164 VOID dma_End(void *obj, APTR buffer, IPTR size, BOOL read)
165 - End DMA transfer and perform post-transfer cleanup of the given region.
167 ULONG dma_Result(void *obj)
168 - Get resulting status of the operation. The function should return 0
169 for successful completion or error code to be passed up to ata.device
170 caller in io_Result field of the IORequest.
172 *****************************************************************************************/
173 /*****************************************************************************************
176 aoHidd_ATABus_Use80Wire
185 Tells whether the bus currently uses 80-conductor cable.
188 This attribute actually makes difference only for DMA modes. If
189 your bus driver returns FALSE, ata.device will not use modes
190 higher than UDMA2 on the bus.
200 *****************************************************************************************/
201 /*****************************************************************************************
204 aoHidd_ATABus_Use32Bit
213 When queried, tells whether the bus supports 32-bit PIO data transfers.
214 When set, enables or disables 32-bit mode for PIO data transfers.
226 *****************************************************************************************/
227 /*****************************************************************************************
239 Tells whether the bus supports DMA transfers.
250 Default implementation in base class returns value depending on whether
251 the subclass provided DMA interface function table during object creation.
253 *****************************************************************************************/
254 /*****************************************************************************************
257 aoHidd_ATABus_PIODataSize
266 Specifies size of PIO interface data structure.
278 *****************************************************************************************/
279 /*****************************************************************************************
282 aoHidd_ATABus_DMADataSize
291 Specifies size of DMA interface data structure.
303 *****************************************************************************************/
304 /*****************************************************************************************
307 aoHidd_ATABus_BusVectors
316 Specifies control functions table for building PIO interface object.
317 The function table is an array of function pointers terminated
318 by -1 value. The terminator must be present for purpose of
319 binary compatibility with future extensions.
322 This function table is mandatory to be implemented by the driver.
332 *****************************************************************************************/
333 /*****************************************************************************************
336 aoHidd_ATABus_PIOVectors
345 Specifies transfers function table for building PIO interface object.
346 The function table is an array of function pointers terminated
347 by -1 value. The terminator must be present for purpose of
348 binary compatibility with future extensions.
351 This function table is mandatory to be implemented by the driver.
361 *****************************************************************************************/
362 /*****************************************************************************************
365 aoHidd_ATABus_DMAVectors
374 Specifies function table for building DMA interface object. If not supplied,
375 the bus is considered not DMA-capable.
384 aoHidd_ATABus_PIOVectors
388 *****************************************************************************************/
389 /*****************************************************************************************
392 aoHidd_ATABus_IRQHandler
401 Specifies IRQ handler function to be called when bus interrupt arrives.
402 The function should be called using "C" calling convention and has the
405 void ata_HandleIRQ(UBYTE status, APTR userdata);
407 Your driver should pass the following arguments to this function:
408 status - value read from ATA main status register.
409 userdata - value of aoHidd_ATABus_IRQData attribute.
412 Reading the drive status register is part of the interrupt acknowledge
413 process, and therefore has to be done by the driver.
415 It is driver's job to check whether the interrupt really belongs to
416 the IDE bus. A generic way to do this is to test ATAF_BUSY bit of
417 the status register for being zero. However, this may not work
418 reliably with IRQ sharing, so advanced IDE controllers may offer
419 different, better way to do this.
426 aoHidd_ATABus_IRQData
430 *****************************************************************************************/
431 /*****************************************************************************************
434 aoHidd_ATABus_IRQData
443 Caller's private data to be supplied to IRQ handler function.
452 aoHidd_ATABus_IRQData
456 *****************************************************************************************/
457 /*****************************************************************************************
460 aoHidd_ATABus_UseIOAlt
469 Tells whether the bus supports alternate registers bank
470 (ata_AltControl and ata_AltStatus).
481 Default implementation in base class returns value depending on whether
482 the subclass provided respective I/O functions in bus interface vector
483 table during object creation.
485 *****************************************************************************************/
486 /*****************************************************************************************
489 aoHidd_ATABus_KeepEmpty
498 If this attribute is set to FALSE during object creation, the object
499 will be destroyed if no devices are detected on the bus.
501 This can be useful for optional buses like legacy ISA controllers,
502 which have no other way to detect their presence.
514 *****************************************************************************************/
515 /*****************************************************************************************
527 Returns a pointer to OOP object of private unit class, representing
528 a master drive on the bus, or NULL if there's no master device.
541 *****************************************************************************************/
542 /*****************************************************************************************
554 Returns a pointer to OOP object of private unit class, representing
555 a slave drive on the bus, or NULL if there's no master device.
568 *****************************************************************************************/
569 /*****************************************************************************************
572 aoHidd_ATABus_CanSetXferMode
581 Tells whether the bus driver implements moHidd_ATABus_SetXferMode method.
588 Current version of ata.device does not use this attribute, and it is
592 moHidd_ATABus_SetXferMode
596 *****************************************************************************************/
598 OOP_Object
*ATABus__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
600 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
603 struct ataBase
*ATABase
= cl
->UserData
;
604 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
605 struct TagItem
*tstate
= msg
->attrList
;
609 data
->keepEmpty
= TRUE
;
611 while ((tag
= NextTagItem(&tstate
)))
615 Hidd_ATABus_Switch(tag
->ti_Tag
, idx
)
617 case aoHidd_ATABus_PIODataSize
:
618 data
->pioDataSize
= tag
->ti_Data
;
621 case aoHidd_ATABus_DMADataSize
:
622 data
->dmaDataSize
= tag
->ti_Data
;
625 case aoHidd_ATABus_BusVectors
:
626 data
->busVectors
= (struct ATA_BusInterface
*)tag
->ti_Data
;
629 case aoHidd_ATABus_PIOVectors
:
630 data
->pioVectors
= (struct ATA_PIOInterface
*)tag
->ti_Data
;
633 case aoHidd_ATABus_DMAVectors
:
634 data
->dmaVectors
= (APTR
*)tag
->ti_Data
;
637 case aoHidd_ATABus_KeepEmpty
:
638 data
->keepEmpty
= tag
->ti_Data
;
643 /* Cache device base pointer. Useful. */
644 data
->ab_Base
= ATABase
;
646 /* Install reset callback */
647 data
->ab_ResetInt
.is_Node
.ln_Name
= ATABase
->ata_Device
.dd_Library
.lib_Node
.ln_Name
;
648 data
->ab_ResetInt
.is_Code
= (VOID_FUNC
)ataBus_Reset
;
649 data
->ab_ResetInt
.is_Data
= data
;
650 AddResetCallback(&data
->ab_ResetInt
);
655 void ATABus__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
657 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
659 RemResetCallback(&data
->ab_ResetInt
);
661 if (data
->dmaInterface
)
663 void *ptr
= data
->dmaInterface
- sizeof(struct ATA_DMAInterface
);
665 FreeMem(ptr
, sizeof(struct ATA_DMAInterface
) + data
->dmaDataSize
);
667 if (data
->pioInterface
)
669 void *ptr
= data
->pioInterface
- sizeof(struct ATA_BusInterface
);
671 FreeMem(ptr
, sizeof(struct ATA_BusInterface
) + data
->pioDataSize
);
674 OOP_DoSuperMethod(cl
, o
, msg
);
678 * Here we take into account that the table can be either
679 * terminated early, or have NULL entries.
681 #define HAVE_VECTOR(x) (x && (x != (APTR)-1))
683 void ATABus__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
685 struct ataBase
*ATABase
= cl
->UserData
;
686 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
689 Hidd_ATABus_Switch (msg
->attrID
, idx
)
691 case aoHidd_ATABus_Use80Wire
:
692 *msg
->storage
= FALSE
;
695 case aoHidd_ATABus_Use32Bit
:
696 *msg
->storage
= (HAVE_VECTOR(data
->pioVectors
->ata_outsl
) &&
697 HAVE_VECTOR(data
->pioVectors
->ata_insl
)) ?
701 case aoHidd_ATABus_UseDMA
:
702 *msg
->storage
= data
->dmaVectors
? TRUE
: FALSE
;
705 case aoHidd_ATABus_UseIOAlt
:
706 *msg
->storage
= (HAVE_VECTOR(data
->busVectors
->ata_out_alt
) &&
707 HAVE_VECTOR(data
->busVectors
->ata_in_alt
)) ?
711 case aoHidd_ATABus_Master
:
712 *msg
->storage
= (IPTR
)data
->ab_Units
[0];
715 case aoHidd_ATABus_Slave
:
716 *msg
->storage
= (IPTR
)data
->ab_Units
[1];
719 case aoHidd_ATABus_CanSetXferMode
:
720 *msg
->storage
= FALSE
;
724 OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
727 /* Default ata_out_alt does nothing */
728 static void default_out_alt(void *obj
, UBYTE val
, UWORD offset
)
733 /* Default ata_in_alt wraps AltStatus to status */
734 static UBYTE
default_in_alt(void *obj
, UWORD offset
)
736 struct ATA_BusInterface
*vec
= obj
- sizeof(struct ATA_BusInterface
);
738 return vec
->ata_in(obj
, ata_Status
);
741 static void CopyVectors(APTR
*dest
, APTR
*src
, unsigned int num
)
745 for (i
= 0; i
< num
; i
++)
747 if (src
[i
] == (APTR
*)-1)
754 /*****************************************************************************************
757 moHidd_ATABus_GetPIOInterface
760 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_GetPIOInterface *Msg);
762 APTR HIDD_ATABus_GetPIOInterface(void);
768 Instantiates encapsulated PIO interface object and returns its
775 A pointer to opaque PIO interface object or NULL in case of failure.
778 This method should be overloaded by driver subclasses in order to
779 initialize data portion of the interface object.
786 moHidd_ATABus_GetDMAInterface
789 Interface objects contain not only driver-specific data, but also
790 a private vector table. Because of this you cannot just AllocMem()
791 the necessary structure in your driver. Always call OOP_DoSuperMethod()
792 in order for the base class to instantiate the interface correctly.
794 *****************************************************************************************/
796 APTR
ATABus__Hidd_ATABus__GetPIOInterface(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
798 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
799 struct ATA_BusInterface
*vec
;
801 vec
= AllocMem(sizeof(struct ATA_BusInterface
) + data
->pioDataSize
,
802 MEMF_PUBLIC
|MEMF_CLEAR
);
805 /* Some default vectors for simplicity */
806 vec
->ata_out_alt
= default_out_alt
;
807 vec
->ata_in_alt
= default_in_alt
;
809 CopyVectors((APTR
*)vec
, (APTR
*)data
->busVectors
,
810 sizeof(struct ATA_BusInterface
) / sizeof(APTR
));
812 data
->pioInterface
= &vec
[1];
813 return data
->pioInterface
;
819 /*****************************************************************************************
822 moHidd_ATABus_GetDMAInterface
825 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_GetDMAInterface *Msg);
827 APTR HIDD_ATABus_GetDMAInterface(void);
833 Instantiates encapsulated DMA interface object and returns its
840 A pointer to opaque DMA interface object or NULL upon failure or
841 if DMA is not supported by this bus.
844 This method should be overloaded by driver subclasses in order to
845 initialize data portion of the interface object.
852 moHidd_ATABus_GetPIOInterface
855 Interface objects contain not only driver-specific data, but also
856 a private vector table. Because of this you cannot just AllocMem()
857 the necessary structure in your driver. Always call OOP_DoSuperMethod()
858 in order for the base class to instantiate the interface correctly.
860 *****************************************************************************************/
862 APTR
ATABus__Hidd_ATABus__GetDMAInterface(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
864 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
865 struct ATA_DMAInterface
*vec
;
867 if (!data
->dmaVectors
)
870 vec
= AllocMem(sizeof(struct ATA_DMAInterface
) + data
->dmaDataSize
,
871 MEMF_PUBLIC
|MEMF_CLEAR
);
874 CopyVectors((APTR
*)vec
, data
->dmaVectors
,
875 sizeof(struct ATA_DMAInterface
) / sizeof(APTR
));
877 data
->dmaInterface
= &vec
[1];
878 return data
->dmaInterface
;
884 /*****************************************************************************************
887 moHidd_ATABus_SetXferMode
890 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_SetXferMode *Msg);
892 APTR HIDD_ATABus_SetXferMode(UBYTE unit, ata_XferMode mode);
898 Sets the desired transfer mode for the given drive on the bus controller.
901 unit - drive number (0 for master and 1 for slave)
902 mode - Mode number (see hidd/ata.h)
905 TRUE if successful or FALSE if the desired mode is not supported
909 The default implementation is provided for drivers not supporting
910 DMA and always returns FALSE if the caller attempts to set any of
916 Current version of ata.device does not use this method, and it is
920 aoHidd_ATABus_CanSetXferMode
924 *****************************************************************************************/
926 BOOL
ATABus__Hidd_ATABus__SetXferMode(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_ATABus_SetXferMode
*msg
)
928 if ((msg
->mode
>= AB_XFER_MDMA0
) && (msg
->mode
<= AB_XFER_UDMA6
))
930 /* DMA is not supported, we cannot set DMA modes */
937 /*****************************************************************************************
940 moHidd_ATABus_Shutdown
943 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_Shutdown *Msg);
945 APTR HIDD_ATABus_Shutdown(void);
951 Instantly shutdown all activity on the bus.
960 This method is called by ata.device during system reset handler execution.
969 Default implementation disables interrupt using AltControl register.
971 *****************************************************************************************/
973 void ATABus__Hidd_ATABus__Shutdown(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg
*msg
)
975 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
977 if (data
->pioInterface
)
979 struct ATA_BusInterface
*vec
= data
->pioInterface
- sizeof(struct ATA_BusInterface
);
981 vec
->ata_out_alt(data
->pioInterface
, ATACTLF_INT_DISABLE
, ata_AltControl
);
985 /***************** Private nonvirtual methods follow *****************/
987 BOOL
Hidd_ATABus_Start(OOP_Object
*o
, struct ataBase
*ATABase
)
989 struct ata_Bus
*ab
= OOP_INST_DATA(ATABase
->busClass
, o
);
991 /* Attach IRQ handler */
992 OOP_SetAttrsTags(o
, aHidd_ATABus_IRQHandler
, Hidd_ATABus_HandleIRQ
,
993 aHidd_ATABus_IRQData
, ab
,
996 /* scan bus - try to locate all devices (disables irq) */
999 if ((ab
->ab_Dev
[0] == DEV_NONE
) && (ab
->ab_Dev
[1] == DEV_NONE
) &&
1003 * If there are no devices, and KeepEmpty is not set
1004 * the bus will be thrown away.
1010 * Assign bus number.
1012 * 1. This does not take into account possibility to
1013 * unload drivers. In this case existing units will disappear,
1014 * freeing up their numbers. These numbers should be reused.
1015 * 2. We REALLY need modify-and-fetch atomics.
1018 ab
->ab_BusNum
= ATABase
->ata__buscount
++;
1021 if ((ab
->ab_Dev
[0] < DEV_ATA
) && (ab
->ab_Dev
[1] < DEV_ATA
))
1023 /* Do not start up task if there are no usable devices. */
1028 * This small trick is based on the fact that shared semaphores
1029 * have no specific owner. You can obtain and release them from
1030 * within any task. It will block only on attempt to re-lock it
1031 * in exclusive mode.
1032 * So instead of complex handshake we obtain the semaphore before
1033 * starting bus task. It will release the semaphore when done.
1035 ObtainSemaphoreShared(&ATABase
->DetectionSem
);
1038 * Start up bus task. It will perform scanning asynchronously, and
1039 * then, if successful, insert units. This allows to keep things parallel.
1041 D(bug("[ATA>>] Start: Bus %u: Unit 0 - %d, Unit 1 - %d\n", ab
->ab_BusNum
, ab
->ab_Dev
[0], ab
->ab_Dev
[1]));
1042 return NewCreateTask(TASKTAG_PC
, BusTaskCode
,
1043 TASKTAG_NAME
, "ATA[PI] Subsystem",
1044 TASKTAG_STACKSIZE
, STACK_SIZE
,
1045 TASKTAG_PRI
, TASK_PRI
,
1046 TASKTAG_TASKMSGPORT
, &ab
->ab_MsgPort
,
1048 TASKTAG_ARG2
, ATABase
,
1049 TAG_DONE
) ? TRUE
: FALSE
;
1052 AROS_UFH3(BOOL
, Hidd_ATABus_Open
,
1053 AROS_UFHA(struct Hook
*, h
, A0
),
1054 AROS_UFHA(OOP_Object
*, obj
, A2
),
1055 AROS_UFHA(IPTR
, reqUnit
, A1
))
1059 struct IORequest
*req
= h
->h_Data
;
1060 struct ataBase
*ATABase
= (struct ataBase
*)req
->io_Device
;
1061 struct ata_Bus
*b
= (struct ata_Bus
*)OOP_INST_DATA(ATABase
->busClass
, obj
);
1062 ULONG bus
= reqUnit
>> 1;
1063 UBYTE dev
= reqUnit
& 1;
1065 D(bug("[ATA%02ld] Checking bus %u dev %u\n", reqUnit
, bus
, dev
));
1067 if ((b
->ab_BusNum
== bus
) && b
->ab_Units
[dev
])
1070 req
->io_Unit
= &b
->ab_Units
[dev
]->au_Unit
;
1073 b
->ab_Units
[dev
]->au_Unit
.unit_OpenCnt
++;