2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
6 #include <aros/debug.h>
8 #include <proto/exec.h>
10 /* We want all other bases obtained from our base */
13 #include <proto/oop.h>
14 #include <proto/utility.h>
16 #include <hidd/storage.h>
19 #include <utility/tagitem.h>
26 static void Hidd_ATABus_HandleIRQ(UBYTE status
, struct ata_Bus
*bus
)
28 struct ata_Unit
*unit
= bus
->ab_SelectedUnit
;
31 * don't waste your time on checking other devices.
32 * pass irq ONLY if task is expecting one;
34 if (unit
&& bus
->ab_HandleIRQ
)
36 /* ok, we have a routine to handle any form of transmission etc. */
37 DIRQ(bug("[ATA%02d] IRQ: Calling dedicated handler 0x%p... \n",
38 unit
->au_UnitNum
, bus
->ab_HandleIRQ
));
39 bus
->ab_HandleIRQ(unit
, status
);
46 * if we got *here* then device is most likely not expected to have an irq.
48 bug("[ATA%02d] Spurious IRQ\n", unit
? unit
->au_UnitNum
: -1);
50 if (0 == (ATAF_BUSY
& status
))
52 bug("[ATA ] STATUS: %02lx\n" , status
);
53 bug("[ATA ] ALT STATUS: %02lx\n" , PIO_InAlt(bus
, ata_AltStatus
));
54 bug("[ATA ] ERROR: %02lx\n" , PIO_In(bus
, ata_Error
));
55 bug("[ATA ] IRQ: REASON: %02lx\n", PIO_In(bus
, atapi_Reason
));
60 static AROS_INTH1(ataBus_Reset
, struct ata_Bus
*, bus
)
64 struct ataBase
*ATABase
= bus
->ab_Base
;
65 OOP_Object
*obj
= (void *)bus
- ATABase
->busClass
->InstOffset
;
67 D(bug("[ATA:Bus] %s()\n", __PRETTY_FUNCTION__
));
69 HIDD_ATABus_Shutdown(obj
);
76 /*****************************************************************************************
85 This class serves as a base class for implementing IDE (ATA) bus drivers.
86 One particularity of this class is that IDE bus is very speed-critical.
87 At the other hand, the driver implements very lowlevel operations which
88 are called quite often. OOP_DoMethod() call is not fast enough, and in
89 order to circumvent this limitation, additionally to normal OOP API
90 IDE bus drivers offer two additional non-standard interfaces. Internally
91 they are implemented as library-alike function table plus driver-specific
92 data. For the purpose of some performance optimizations the function
93 table is private to ata.device and managed entirely by the base class.
94 Driver classes have access only to data portion.
96 These interfaces are documented below.
98 *****************************************************************************************/
99 /*****************************************************************************************
108 PIO interface is responsible for accessing I/O registers on the IDE
109 bus, as well as performing PIO-mode 16- and 32-bit data transfers.
110 This interface is mandatory and must be implemented by the driver,
111 however some functions are optional. They can be either omitted
112 entirely from the function table, or set to NULL pointers.
114 Control functions table for the interface consists of the following
115 functions (listed in their order in the array):
117 VOID ata_out(void *obj, UBYTE val, UWORD offset)
118 - Write byte into primary register bank with the given offset.
120 UBYTE ata_in(void *obj, UWORD offset)
121 - Read byte from primary register bank with the given offset.
123 VOID ata_out_alt(void *obj, UBYTE val, UWORD offset)
124 - Write byte into alternate register bank with the given offset.
125 This function is optional.
127 UBYTE ata_in_alt(void *obj, UWORD offset)
128 - Read byte from alternate register bank with the given offset.
129 This function is optional.
131 Transfer functions table for the interface consists of the following
132 functions (listed in their order in the array):
134 VOID ata_outsw(void *obj, APTR address, ULONG count)
135 - Perform 16-bit PIO data write operation from the given memory
136 region of the given size.
138 VOID ata_insw(void *obj, APTR address, ULONG count)
139 - Perform 16-bit PIO data read operation into the given memory
140 region of the given size.
142 VOID ata_outsl(void *obj, APTR address, ULONG count)
143 - Perform 32-bit PIO data write operation from the given memory
144 region of the given size. This function is optional.
146 UBYTE ata_insl(void *obj, APTR address, ULONG count)
147 - Perform 32-bit PIO data read operation into the given memory
148 region of the given size. This function is optional.
150 *****************************************************************************************/
151 /*****************************************************************************************
160 DMA interface is optional, and is needed in order to support DMA data
163 Function table for the interface consists of the following functions:
165 BOOL dma_Setup(void *obj, APTR buffer, IPTR size, BOOL read)
166 - Prepare the controller to DMA data transfer. The last argument is
167 TRUE for read operation and FALSE for write. The function should
168 return TRUE for success or FALSE for failure.
170 VOID dma_Start(void *obj)
171 - Start DMA transfer.
173 VOID dma_End(void *obj, APTR buffer, IPTR size, BOOL read)
174 - End DMA transfer and perform post-transfer cleanup of the given region.
176 ULONG dma_Result(void *obj)
177 - Get resulting status of the operation. The function should return 0
178 for successful completion or error code to be passed up to ata.device
179 caller in io_Result field of the IORequest.
181 *****************************************************************************************/
182 /*****************************************************************************************
185 aoHidd_ATABus_Use80Wire
194 Tells whether the bus currently uses 80-conductor cable.
197 This attribute actually makes difference only for DMA modes. If
198 your bus driver returns FALSE, ata.device will not use modes
199 higher than UDMA2 on the bus.
209 *****************************************************************************************/
210 /*****************************************************************************************
213 aoHidd_ATABus_Use32Bit
222 When queried, tells whether the bus supports 32-bit PIO data transfers.
223 When set, enables or disables 32-bit mode for PIO data transfers.
235 *****************************************************************************************/
236 /*****************************************************************************************
248 Tells whether the bus supports DMA transfers.
259 Default implementation in base class returns value depending on whether
260 the subclass provided DMA interface function table during object creation.
262 *****************************************************************************************/
263 /*****************************************************************************************
266 aoHidd_ATABus_PIODataSize
275 Specifies size of PIO interface data structure.
287 *****************************************************************************************/
288 /*****************************************************************************************
291 aoHidd_ATABus_DMADataSize
300 Specifies size of DMA interface data structure.
312 *****************************************************************************************/
313 /*****************************************************************************************
316 aoHidd_ATABus_BusVectors
325 Specifies control functions table for building PIO interface object.
326 The function table is an array of function pointers terminated
327 by -1 value. The terminator must be present for purpose of
328 binary compatibility with future extensions.
331 This function table is mandatory to be implemented by the driver.
341 *****************************************************************************************/
342 /*****************************************************************************************
345 aoHidd_ATABus_PIOVectors
354 Specifies transfers function table for building PIO interface object.
355 The function table is an array of function pointers terminated
356 by -1 value. The terminator must be present for purpose of
357 binary compatibility with future extensions.
360 This function table is mandatory to be implemented by the driver.
370 *****************************************************************************************/
371 /*****************************************************************************************
374 aoHidd_ATABus_DMAVectors
383 Specifies function table for building DMA interface object. If not supplied,
384 the bus is considered not DMA-capable.
393 aoHidd_ATABus_PIOVectors
397 *****************************************************************************************/
398 /*****************************************************************************************
401 aoHidd_ATABus_IRQHandler
410 Specifies IRQ handler function to be called when bus interrupt arrives.
411 The function should be called using "C" calling convention and has the
414 void ata_HandleIRQ(UBYTE status, APTR userdata);
416 Your driver should pass the following arguments to this function:
417 status - value read from ATA main status register.
418 userdata - value of aoHidd_ATABus_IRQData attribute.
421 Reading the drive status register is part of the interrupt acknowledge
422 process, and therefore has to be done by the driver.
424 It is driver's job to check whether the interrupt really belongs to
425 the IDE bus. A generic way to do this is to test ATAF_BUSY bit of
426 the status register for being zero. However, this may not work
427 reliably with IRQ sharing, so advanced IDE controllers may offer
428 different, better way to do this.
435 aoHidd_ATABus_IRQData
439 *****************************************************************************************/
440 /*****************************************************************************************
443 aoHidd_ATABus_IRQData
452 Caller's private data to be supplied to IRQ handler function.
461 aoHidd_ATABus_IRQData
465 *****************************************************************************************/
466 /*****************************************************************************************
469 aoHidd_ATABus_UseIOAlt
478 Tells whether the bus supports alternate registers bank
479 (ata_AltControl and ata_AltStatus).
490 Default implementation in base class returns value depending on whether
491 the subclass provided respective I/O functions in bus interface vector
492 table during object creation.
494 *****************************************************************************************/
495 /*****************************************************************************************
498 aoHidd_ATABus_KeepEmpty
507 If this attribute is set to FALSE during object creation, the object
508 will be destroyed if no devices are detected on the bus.
510 This can be useful for optional buses like legacy ISA controllers,
511 which have no other way to detect their presence.
523 *****************************************************************************************/
524 /*****************************************************************************************
536 Returns a pointer to OOP object of private unit class, representing
537 a master drive on the bus, or NULL if there's no master device.
550 *****************************************************************************************/
551 /*****************************************************************************************
563 Returns a pointer to OOP object of private unit class, representing
564 a slave drive on the bus, or NULL if there's no master device.
577 *****************************************************************************************/
578 /*****************************************************************************************
581 aoHidd_ATABus_CanSetXferMode
590 Tells whether the bus driver implements moHidd_ATABus_SetXferMode method.
597 Current version of ata.device does not use this attribute, and it is
601 moHidd_ATABus_SetXferMode
605 *****************************************************************************************/
607 OOP_Object
*ATABus__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
609 struct ataBase
*ATABase
= cl
->UserData
;
610 D(bug("[ATA:Bus] %s()\n", __PRETTY_FUNCTION__
));
611 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
614 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
615 struct TagItem
*tstate
= msg
->attrList
;
618 D(bug("[ATA:Bus] %s: instance @ 0x%p\n", __PRETTY_FUNCTION__
, o
));
621 data
->keepEmpty
= TRUE
;
623 while ((tag
= NextTagItem(&tstate
)))
627 Hidd_ATABus_Switch(tag
->ti_Tag
, idx
)
629 case aoHidd_ATABus_PIODataSize
:
630 data
->pioDataSize
= tag
->ti_Data
;
633 case aoHidd_ATABus_DMADataSize
:
634 data
->dmaDataSize
= tag
->ti_Data
;
637 case aoHidd_ATABus_BusVectors
:
638 data
->busVectors
= (struct ATA_BusInterface
*)tag
->ti_Data
;
641 case aoHidd_ATABus_PIOVectors
:
642 data
->pioVectors
= (struct ATA_PIOInterface
*)tag
->ti_Data
;
645 case aoHidd_ATABus_DMAVectors
:
646 data
->dmaVectors
= (APTR
*)tag
->ti_Data
;
649 case aoHidd_ATABus_KeepEmpty
:
650 data
->keepEmpty
= tag
->ti_Data
;
655 /* Cache device base pointer. Useful. */
656 data
->ab_Base
= ATABase
;
658 /* Install reset callback */
659 data
->ab_ResetInt
.is_Node
.ln_Name
= ATABase
->ata_Device
.dd_Library
.lib_Node
.ln_Name
;
660 data
->ab_ResetInt
.is_Code
= (VOID_FUNC
)ataBus_Reset
;
661 data
->ab_ResetInt
.is_Data
= data
;
662 AddResetCallback(&data
->ab_ResetInt
);
667 void ATABus__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
669 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
671 RemResetCallback(&data
->ab_ResetInt
);
673 if (data
->dmaInterface
)
675 void *ptr
= data
->dmaInterface
- sizeof(struct ATA_DMAInterface
);
677 FreeMem(ptr
, sizeof(struct ATA_DMAInterface
) + data
->dmaDataSize
);
679 if (data
->pioInterface
)
681 void *ptr
= data
->pioInterface
- sizeof(struct ATA_BusInterface
);
683 FreeMem(ptr
, sizeof(struct ATA_BusInterface
) + data
->pioDataSize
);
686 OOP_DoSuperMethod(cl
, o
, msg
);
690 * Here we take into account that the table can be either
691 * terminated early, or have NULL entries.
693 #define HAVE_VECTOR(x) (x && (x != (APTR)-1))
695 void ATABus__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
697 struct ataBase
*ATABase
= cl
->UserData
;
698 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
701 Hidd_Bus_Switch (msg
->attrID
, idx
)
703 case aoHidd_Bus_MaxUnits
:
704 *msg
->storage
= MAX_BUSUNITS
;
708 Hidd_ATABus_Switch (msg
->attrID
, idx
)
710 case aoHidd_ATABus_Use80Wire
:
711 *msg
->storage
= FALSE
;
714 case aoHidd_ATABus_Use32Bit
:
715 *msg
->storage
= (HAVE_VECTOR(data
->pioVectors
->ata_outsl
) &&
716 HAVE_VECTOR(data
->pioVectors
->ata_insl
)) ?
720 case aoHidd_ATABus_UseDMA
:
721 *msg
->storage
= data
->dmaVectors
? TRUE
: FALSE
;
724 case aoHidd_ATABus_UseIOAlt
:
725 *msg
->storage
= (HAVE_VECTOR(data
->busVectors
->ata_out_alt
) &&
726 HAVE_VECTOR(data
->busVectors
->ata_in_alt
)) ?
730 case aoHidd_ATABus_CanSetXferMode
:
731 *msg
->storage
= FALSE
;
735 OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
738 void ATABus__Hidd_StorageBus__EnumUnits(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_StorageBus_EnumUnits
*msg
)
740 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
743 D(bug ("[ATA:Bus] Hidd_StorageBus__EnumUnits()\n");)
745 if (data
->ab_Units
[0])
746 stop
= CALLHOOKPKT(msg
->callback
, data
->ab_Units
[0], msg
->hookMsg
);
747 if ((!stop
) && (data
->ab_Units
[1]))
748 stop
= CALLHOOKPKT(msg
->callback
, data
->ab_Units
[1], msg
->hookMsg
);
751 /* Default ata_out_alt does nothing */
752 static void default_out_alt(void *obj
, UBYTE val
, UWORD offset
)
757 /* Default ata_in_alt wraps AltStatus to status */
758 static UBYTE
default_in_alt(void *obj
, UWORD offset
)
760 struct ATA_BusInterface
*vec
= obj
- sizeof(struct ATA_BusInterface
);
762 return vec
->ata_in(obj
, ata_Status
);
765 static void CopyVectors(APTR
*dest
, APTR
*src
, unsigned int num
)
769 for (i
= 0; i
< num
; i
++)
771 if (src
[i
] == (APTR
*)-1)
778 /*****************************************************************************************
781 moHidd_ATABus_GetPIOInterface
784 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_GetPIOInterface *Msg);
786 APTR HIDD_ATABus_GetPIOInterface(void);
792 Instantiates encapsulated PIO interface object and returns its
799 A pointer to opaque PIO interface object or NULL in case of failure.
802 This method should be overloaded by driver subclasses in order to
803 initialize data portion of the interface object.
810 moHidd_ATABus_GetDMAInterface
813 Interface objects contain not only driver-specific data, but also
814 a private vector table. Because of this you cannot just AllocMem()
815 the necessary structure in your driver. Always call OOP_DoSuperMethod()
816 in order for the base class to instantiate the interface correctly.
818 *****************************************************************************************/
820 APTR
ATABus__Hidd_ATABus__GetPIOInterface(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
822 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
823 struct ATA_BusInterface
*vec
;
825 D(bug("[ATA:Bus] %s()\n", __PRETTY_FUNCTION__
));
827 vec
= AllocMem(sizeof(struct ATA_BusInterface
) + data
->pioDataSize
,
828 MEMF_PUBLIC
|MEMF_CLEAR
);
831 /* Some default vectors for simplicity */
832 vec
->ata_out_alt
= default_out_alt
;
833 vec
->ata_in_alt
= default_in_alt
;
835 CopyVectors((APTR
*)vec
, (APTR
*)data
->busVectors
,
836 sizeof(struct ATA_BusInterface
) / sizeof(APTR
));
838 data
->pioInterface
= &vec
[1];
839 return data
->pioInterface
;
845 /*****************************************************************************************
848 moHidd_ATABus_GetDMAInterface
851 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_GetDMAInterface *Msg);
853 APTR HIDD_ATABus_GetDMAInterface(void);
859 Instantiates encapsulated DMA interface object and returns its
866 A pointer to opaque DMA interface object or NULL upon failure or
867 if DMA is not supported by this bus.
870 This method should be overloaded by driver subclasses in order to
871 initialize data portion of the interface object.
878 moHidd_ATABus_GetPIOInterface
881 Interface objects contain not only driver-specific data, but also
882 a private vector table. Because of this you cannot just AllocMem()
883 the necessary structure in your driver. Always call OOP_DoSuperMethod()
884 in order for the base class to instantiate the interface correctly.
886 *****************************************************************************************/
888 APTR
ATABus__Hidd_ATABus__GetDMAInterface(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
890 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
891 struct ATA_DMAInterface
*vec
;
893 D(bug("[ATA:Bus] %s()\n", __PRETTY_FUNCTION__
));
895 if (!data
->dmaVectors
)
898 vec
= AllocMem(sizeof(struct ATA_DMAInterface
) + data
->dmaDataSize
,
899 MEMF_PUBLIC
|MEMF_CLEAR
);
902 CopyVectors((APTR
*)vec
, data
->dmaVectors
,
903 sizeof(struct ATA_DMAInterface
) / sizeof(APTR
));
905 data
->dmaInterface
= &vec
[1];
906 return data
->dmaInterface
;
912 /*****************************************************************************************
915 moHidd_ATABus_SetXferMode
918 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_SetXferMode *Msg);
920 APTR HIDD_ATABus_SetXferMode(UBYTE unit, ata_XferMode mode);
926 Sets the desired transfer mode for the given drive on the bus controller.
929 unit - drive number (0 for master and 1 for slave)
930 mode - Mode number (see hidd/ata.h)
933 TRUE if successful or FALSE if the desired mode is not supported
937 The default implementation is provided for drivers not supporting
938 DMA and always returns FALSE if the caller attempts to set any of
944 Current version of ata.device does not use this method, and it is
948 aoHidd_ATABus_CanSetXferMode
952 *****************************************************************************************/
954 BOOL
ATABus__Hidd_ATABus__SetXferMode(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_ATABus_SetXferMode
*msg
)
956 D(bug("[ATA:Bus] %s()\n", __PRETTY_FUNCTION__
));
958 if ((msg
->mode
>= AB_XFER_MDMA0
) && (msg
->mode
<= AB_XFER_UDMA6
))
960 /* DMA is not supported, we cannot set DMA modes */
967 /*****************************************************************************************
970 moHidd_ATABus_Shutdown
973 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_ATABus_Shutdown *Msg);
975 APTR HIDD_ATABus_Shutdown(void);
981 Instantly shutdown all activity on the bus.
990 This method is called by ata.device during system reset handler execution.
999 Default implementation disables interrupt using AltControl register.
1001 *****************************************************************************************/
1003 void ATABus__Hidd_ATABus__Shutdown(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg
*msg
)
1005 struct ata_Bus
*data
= OOP_INST_DATA(cl
, o
);
1007 D(bug("[ATA:Bus] %s()\n", __PRETTY_FUNCTION__
));
1009 if (data
->pioInterface
)
1011 struct ATA_BusInterface
*vec
= data
->pioInterface
- sizeof(struct ATA_BusInterface
);
1013 vec
->ata_out_alt(data
->pioInterface
, ATACTLF_INT_DISABLE
, ata_AltControl
);
1017 /***************** Private nonvirtual methods follow *****************/
1019 BOOL
Hidd_ATABus_Start(OOP_Object
*o
, struct ataBase
*ATABase
)
1021 struct ata_Bus
*ab
= OOP_INST_DATA(ATABase
->busClass
, o
);
1023 D(bug("[ATA:Bus] %s()\n", __PRETTY_FUNCTION__
));
1025 /* Attach IRQ handler */
1026 OOP_SetAttrsTags(o
, aHidd_ATABus_IRQHandler
, Hidd_ATABus_HandleIRQ
,
1027 aHidd_ATABus_IRQData
, ab
,
1030 /* scan bus - try to locate all devices (disables irq) */
1033 if ((ab
->ab_Dev
[0] == DEV_NONE
) && (ab
->ab_Dev
[1] == DEV_NONE
) &&
1037 * If there are no devices, and KeepEmpty is not set
1038 * the bus will be thrown away.
1044 * Assign bus number.
1046 * 1. This does not take into account possibility to
1047 * unload drivers. In this case existing units will disappear,
1048 * freeing up their numbers. These numbers should be reused.
1049 * 2. We REALLY need modify-and-fetch atomics.
1052 ab
->ab_BusNum
= ATABase
->ata__buscount
++;
1055 if ((ab
->ab_Dev
[0] < DEV_ATA
) && (ab
->ab_Dev
[1] < DEV_ATA
))
1057 /* Do not start up task if there are no usable devices. */
1062 * This small trick is based on the fact that shared semaphores
1063 * have no specific owner. You can obtain and release them from
1064 * within any task. It will block only on attempt to re-lock it
1065 * in exclusive mode.
1066 * So instead of complex handshake we obtain the semaphore before
1067 * starting bus task. It will release the semaphore when done.
1069 ObtainSemaphoreShared(&ATABase
->DetectionSem
);
1072 * Start up bus task. It will perform scanning asynchronously, and
1073 * then, if successful, insert units. This allows to keep things parallel.
1075 D(bug("[ATA>>] Start: Bus %u: Unit 0 - %d, Unit 1 - %d\n", ab
->ab_BusNum
, ab
->ab_Dev
[0], ab
->ab_Dev
[1]));
1076 return NewCreateTask(TASKTAG_PC
, BusTaskCode
,
1077 TASKTAG_NAME
, "ATA[PI] Subsystem",
1078 TASKTAG_STACKSIZE
, STACK_SIZE
,
1079 TASKTAG_PRI
, TASK_PRI
,
1080 TASKTAG_TASKMSGPORT
, &ab
->ab_MsgPort
,
1082 TASKTAG_ARG2
, ATABase
,
1083 TAG_DONE
) ? TRUE
: FALSE
;
1086 AROS_UFH3(BOOL
, Hidd_ATABus_Open
,
1087 AROS_UFHA(struct Hook
*, h
, A0
),
1088 AROS_UFHA(OOP_Object
*, obj
, A2
),
1089 AROS_UFHA(IPTR
, reqUnit
, A1
))
1093 struct IORequest
*req
= h
->h_Data
;
1094 struct ataBase
*ATABase
= (struct ataBase
*)req
->io_Device
;
1095 struct ata_Bus
*b
= (struct ata_Bus
*)OOP_INST_DATA(ATABase
->busClass
, obj
);
1096 ULONG bus
= reqUnit
>> 1;
1097 UBYTE dev
= reqUnit
& 1;
1099 D(bug("[ATA:Bus] %s()\n", __PRETTY_FUNCTION__
));
1100 D(bug("[ATA%02ld] Checking bus %u dev %u\n", reqUnit
, bus
, dev
));
1102 if ((b
->ab_BusNum
== bus
) && b
->ab_Units
[dev
])
1104 struct ata_Unit
*unit
= (struct ata_Unit
*)OOP_INST_DATA(ATABase
->unitClass
, b
->ab_Units
[dev
]);
1107 req
->io_Unit
= &unit
->au_Unit
;
1110 unit
->au_Unit
.unit_OpenCnt
++;