add place-holder directory for the a3000 wd533c93 scsi controller implementation.
[AROS.git] / rom / devs / scsi / scsi_busclass.c
blob4a808ff4f80672a9d634da666bcac91488585ad2
1 /*
2 Copyright © 2019, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/debug.h>
8 #include <proto/exec.h>
10 /* We want all other bases obtained from our base */
11 #define __NOLIBBASE__
13 #include <proto/oop.h>
14 #include <proto/utility.h>
16 #include <hidd/storage.h>
17 #include <hidd/bus.h>
18 #include <hidd/scsi.h>
19 #include <oop/oop.h>
20 #include <utility/tagitem.h>
22 #include "scsi.h"
23 #include "scsi_Bus.h"
25 #define DIRQ(x)
26 #define DATTR(x)
28 static void Hidd_SCSIBus_HandleIRQ(UBYTE status, struct scsi_Bus *bus)
30 struct scsi_Unit *unit = bus->sb_SelectedUnit;
33 * don't waste your time on checking other devices.
34 * pass irq ONLY if task is expecting one;
36 if (unit && bus->sb_HandleIRQ)
38 /* ok, we have a routine to handle any form of transmission etc. */
39 DIRQ(bug("[SCSI%02d] IRQ: Calling dedicated handler 0x%p... \n",
40 unit->su_UnitNum, bus->sb_HandleIRQ));
41 bus->sb_HandleIRQ(unit, status);
43 return;
46 DIRQ({
48 * if we got *here* then device is most likely not expected to have an irq.
50 bug("[SCSI%02d] Spurious IRQ\n", unit ? unit->su_UnitNum : -1);
52 if (0 == (ATAF_BUSY & status))
54 bug("[SCSI ] STATUS: %02lx\n" , status);
55 bug("[SCSI ] ALT STATUS: %02lx\n" , PIO_InAlt(bus, scsi_AltStatus));
56 bug("[SCSI ] ERROR: %02lx\n" , PIO_In(bus, scsi_Error));
57 bug("[SCSI ] IRQ: REASON: %02lx\n", PIO_In(bus, atapi_Reason));
59 });
62 static AROS_INTH1(ataBus_Reset, struct scsi_Bus *, bus)
64 AROS_INTFUNC_INIT
66 struct scsiBase *SCSIBase = bus->sb_Base;
67 OOP_Object *obj = (void *)bus - SCSIBase->busClass->InstOffset;
69 D(bug("[SCSI:Bus] %s()\n", __func__));
71 HIDD_SCSIBus_Shutdown(obj);
73 return FALSE;
75 AROS_INTFUNC_EXIT
78 /*****************************************************************************************
80 NAME
81 --background--
83 LOCATION
84 CLID_Hidd_SCSIBus
86 NOTES
87 This class serves as a base class for implementing IDE (ATA) bus drivers.
88 One particularity of this class is that IDE bus is very speed-critical.
89 At the other hand, the driver implements very lowlevel operations which
90 are called quite often. OOP_DoMethod() call is not fast enough, and in
91 order to circumvent this limitation, additionally to normal OOP API
92 IDE bus drivers offer two additional non-standard interfaces. Internally
93 they are implemented as library-alike function table plus driver-specific
94 data. For the purpose of some performance optimizations the function
95 table is private to ata.device and managed entirely by the base class.
96 Driver classes have access only to data portion.
98 These interfaces are documented below.
100 *****************************************************************************************/
101 /*****************************************************************************************
103 NAME
104 --PIO interface--
106 LOCATION
107 CLID_Hidd_SCSIBus
109 NOTES
110 PIO interface is responsible for accessing I/O registers on the IDE
111 bus, as well as performing PIO-mode 16- and 32-bit data transfers.
112 This interface is mandatory and must be implemented by the driver,
113 however some functions are optional. They can be either omitted
114 entirely from the function table, or set to NULL pointers.
116 Control functions table for the interface consists of the following
117 functions (listed in their order in the array):
119 VOID scsi_out(void *obj, UBYTE val, UWORD offset)
120 - Write byte into primary register bank with the given offset.
122 UBYTE scsi_in(void *obj, UWORD offset)
123 - Read byte from primary register bank with the given offset.
125 VOID scsi_out_alt(void *obj, UBYTE val, UWORD offset)
126 - Write byte into alternate register bank with the given offset.
127 This function is optional.
129 UBYTE scsi_in_alt(void *obj, UWORD offset)
130 - Read byte from alternate register bank with the given offset.
131 This function is optional.
133 Transfer functions table for the interface consists of the following
134 functions (listed in their order in the array):
136 VOID scsi_outsw(void *obj, APTR address, ULONG count)
137 - Perform 16-bit PIO data write operation from the given memory
138 region of the given size.
140 VOID scsi_insw(void *obj, APTR address, ULONG count)
141 - Perform 16-bit PIO data read operation into the given memory
142 region of the given size.
144 VOID scsi_outsl(void *obj, APTR address, ULONG count)
145 - Perform 32-bit PIO data write operation from the given memory
146 region of the given size. This function is optional.
148 UBYTE scsi_insl(void *obj, APTR address, ULONG count)
149 - Perform 32-bit PIO data read operation into the given memory
150 region of the given size. This function is optional.
152 *****************************************************************************************/
153 /*****************************************************************************************
155 NAME
156 --DMA interface--
158 LOCATION
159 CLID_Hidd_SCSIBus
161 NOTES
162 DMA interface is optional, and is needed in order to support DMA data
163 transfers.
165 Function table for the interface consists of the following functions:
167 BOOL dma_Setup(void *obj, APTR buffer, IPTR size, BOOL read)
168 - Prepare the controller to DMA data transfer. The last argument is
169 TRUE for read operation and FALSE for write. The function should
170 return TRUE for success or FALSE for failure.
172 VOID dma_Start(void *obj)
173 - Start DMA transfer.
175 VOID dma_End(void *obj, APTR buffer, IPTR size, BOOL read)
176 - End DMA transfer and perform post-transfer cleanup of the given region.
178 ULONG dma_Result(void *obj)
179 - Get resulting status of the operation. The function should return 0
180 for successful completion or error code to be passed up to ata.device
181 caller in io_Result field of the IORequest.
183 *****************************************************************************************/
184 /*****************************************************************************************
186 NAME
187 aoHidd_SCSIBus_Use80Wire
189 SYNOPSIS
190 [..G], BOOL
192 LOCATION
193 CLID_Hidd_SCSIBus
195 FUNCTION
196 Tells whether the bus currently uses 80-conductor cable.
198 NOTES
199 This attribute actually makes difference only for DMA modes. If
200 your bus driver returns FALSE, ata.device will not use modes
201 higher than UDMA2 on the bus.
203 EXAMPLE
205 BUGS
207 SEE ALSO
209 INTERNALS
211 *****************************************************************************************/
212 /*****************************************************************************************
214 NAME
215 aoHidd_SCSIBus_Use32Bit
217 SYNOPSIS
218 [.SG], BOOL
220 LOCATION
221 CLID_Hidd_SCSIBus
223 FUNCTION
224 When queried, tells whether the bus supports 32-bit PIO data transfers.
225 When set, enables or disables 32-bit mode for PIO data transfers.
227 NOTES
229 EXAMPLE
231 BUGS
233 SEE ALSO
235 INTERNALS
237 *****************************************************************************************/
238 /*****************************************************************************************
240 NAME
241 aoHidd_SCSIBus_UseDMA
243 SYNOPSIS
244 [..G], BOOL
246 LOCATION
247 CLID_Hidd_SCSIBus
249 FUNCTION
250 Tells whether the bus supports DMA transfers.
252 NOTES
254 EXAMPLE
256 BUGS
258 SEE ALSO
260 INTERNALS
261 Default implementation in base class returns value depending on whether
262 the subclass provided DMA interface function table during object creation.
264 *****************************************************************************************/
265 /*****************************************************************************************
267 NAME
268 aoHidd_SCSIBus_PIODataSize
270 SYNOPSIS
271 [I..], BOOL
273 LOCATION
274 CLID_Hidd_SCSIBus
276 FUNCTION
277 Specifies size of PIO interface data structure.
279 NOTES
281 EXAMPLE
283 BUGS
285 SEE ALSO
287 INTERNALS
289 *****************************************************************************************/
290 /*****************************************************************************************
292 NAME
293 aoHidd_SCSIBus_DMADataSize
295 SYNOPSIS
296 [I..], BOOL
298 LOCATION
299 CLID_Hidd_SCSIBus
301 FUNCTION
302 Specifies size of DMA interface data structure.
304 NOTES
306 EXAMPLE
308 BUGS
310 SEE ALSO
312 INTERNALS
314 *****************************************************************************************/
315 /*****************************************************************************************
317 NAME
318 aoHidd_SCSIBus_BusVectors
320 SYNOPSIS
321 [I..], APTR *
323 LOCATION
324 CLID_Hidd_SCSIBus
326 FUNCTION
327 Specifies control functions table for building PIO interface object.
328 The function table is an array of function pointers terminated
329 by -1 value. The terminator must be present for purpose of
330 binary compatibility with future extensions.
332 NOTES
333 This function table is mandatory to be implemented by the driver.
335 EXAMPLE
337 BUGS
339 SEE ALSO
341 INTERNALS
343 *****************************************************************************************/
344 /*****************************************************************************************
346 NAME
347 aoHidd_SCSIBus_PIOVectors
349 SYNOPSIS
350 [I..], APTR *
352 LOCATION
353 CLID_Hidd_SCSIBus
355 FUNCTION
356 Specifies transfers function table for building PIO interface object.
357 The function table is an array of function pointers terminated
358 by -1 value. The terminator must be present for purpose of
359 binary compatibility with future extensions.
361 NOTES
362 This function table is mandatory to be implemented by the driver.
364 EXAMPLE
366 BUGS
368 SEE ALSO
370 INTERNALS
372 *****************************************************************************************/
373 /*****************************************************************************************
375 NAME
376 aoHidd_SCSIBus_DMAVectors
378 SYNOPSIS
379 [I..], APTR *
381 LOCATION
382 CLID_Hidd_SCSIBus
384 FUNCTION
385 Specifies function table for building DMA interface object. If not supplied,
386 the bus is considered not DMA-capable.
388 NOTES
390 EXAMPLE
392 BUGS
394 SEE ALSO
395 aoHidd_SCSIBus_PIOVectors
397 INTERNALS
399 *****************************************************************************************/
400 /*****************************************************************************************
402 NAME
403 aoHidd_SCSIBus_UseIOAlt
405 SYNOPSIS
406 [..G], BOOL
408 LOCATION
409 CLID_Hidd_SCSIBus
411 FUNCTION
412 Tells whether the bus supports alternate registers bank
413 (scsi_AltControl and scsi_AltStatus).
415 NOTES
417 EXAMPLE
419 BUGS
421 SEE ALSO
423 INTERNALS
424 Default implementation in base class returns value depending on whether
425 the subclass provided respective I/O functions in bus interface vector
426 table during object creation.
428 *****************************************************************************************/
429 /*****************************************************************************************
431 NAME
432 aoHidd_SCSIBus_Master
434 SYNOPSIS
435 [..G], OOP_Object *
437 LOCATION
438 CLID_Hidd_SCSIBus
440 FUNCTION
441 Returns a pointer to OOP object of private unit class, representing
442 a master drive on the bus, or NULL if there's no master device.
444 NOTES
446 EXAMPLE
448 BUGS
450 SEE ALSO
451 aoHidd_SCSIBus_Slave
453 INTERNALS
455 *****************************************************************************************/
456 /*****************************************************************************************
458 NAME
459 aoHidd_SCSIBus_Slave
461 SYNOPSIS
462 [..G], OOP_Object *
464 LOCATION
465 CLID_Hidd_SCSIBus
467 FUNCTION
468 Returns a pointer to OOP object of private unit class, representing
469 a slave drive on the bus, or NULL if there's no master device.
471 NOTES
473 EXAMPLE
475 BUGS
477 SEE ALSO
478 aoHidd_SCSIBus_Master
480 INTERNALS
482 *****************************************************************************************/
483 /*****************************************************************************************
485 NAME
486 aoHidd_SCSIBus_CanSetXferMode
488 SYNOPSIS
489 [..G], BOOL
491 LOCATION
492 CLID_Hidd_SCSIBus
494 FUNCTION
495 Tells whether the bus driver implements moHidd_SCSIBus_SetXferMode method.
497 NOTES
499 EXAMPLE
501 BUGS
502 Current version of ata.device does not use this attribute, and it is
503 considered reserved.
505 SEE ALSO
506 moHidd_SCSIBus_SetXferMode
508 INTERNALS
510 *****************************************************************************************/
512 OOP_Object *SCSIBus__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
514 struct scsiBase *SCSIBase = cl->UserData;
515 D(bug("[SCSI:Bus] %s()\n", __func__));
517 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, &msg->mID);
518 if (o)
520 struct scsi_Bus *data = OOP_INST_DATA(cl, o);
521 struct TagItem *tstate = msg->attrList;
522 struct TagItem *tag;
525 bug("[SCSI:Bus] %s: instance @ 0x%p\n", __func__, o);
526 bug("[SCSI:Bus] %s: scsi_Bus @ 0x%p\n", __func__, data);
529 /* Defaults */
530 data->keepEmpty = TRUE;
532 while ((tag = NextTagItem(&tstate)))
534 ULONG idx;
536 Hidd_SCSIBus_Switch(tag->ti_Tag, idx)
538 case aoHidd_SCSIBus_PIODataSize:
539 data->pioDataSize = tag->ti_Data;
540 D(bug("[SCSI:Bus] %s: PIODataSize = %d\n", __func__, data->pioDataSize);)
541 break;
543 case aoHidd_SCSIBus_DMADataSize:
544 data->dmaDataSize = tag->ti_Data;
545 DATTR(bug("[SCSI:Bus] %s: DMADataSize = %d\n", __func__, data->dmaDataSize);)
546 break;
548 case aoHidd_SCSIBus_BusVectors:
549 data->busVectors = (struct SCSI_BusInterface *)tag->ti_Data;
550 DATTR(bug("[SCSI:Bus] %s: BusVectors @ 0x%p\n", __func__, data->busVectors);)
551 break;
553 case aoHidd_SCSIBus_PIOVectors:
554 data->pioVectors = (struct SCSI_PIOInterface *)tag->ti_Data;
555 DATTR(bug("[SCSI:Bus] %s: PIOVectors @ 0x%p\n", __func__, data->pioVectors);)
556 break;
558 case aoHidd_SCSIBus_DMAVectors:
559 data->dmaVectors = (APTR *)tag->ti_Data;
560 DATTR(bug("[SCSI:Bus] %s: DMAVectors @ 0x%p\n", __func__, data->dmaVectors);)
561 break;
563 Hidd_Bus_Switch(tag->ti_Tag, idx)
565 case aoHidd_Bus_KeepEmpty:
566 data->keepEmpty = tag->ti_Data;
567 break;
571 /* Cache device base pointer. Useful. */
572 data->sb_Base = SCSIBase;
574 /* Install reset callback */
575 data->sb_ResetInt.is_Node.ln_Name = SCSIBase->scsi_Device.dd_Library.lib_Node.ln_Name;
576 data->sb_ResetInt.is_Code = (VOID_FUNC)ataBus_Reset;
577 data->sb_ResetInt.is_Data = data;
578 AddResetCallback(&data->sb_ResetInt);
580 return o;
583 void SCSIBus__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
585 struct scsi_Bus *data = OOP_INST_DATA(cl, o);
587 RemResetCallback(&data->sb_ResetInt);
589 if (data->dmaInterface)
591 void *ptr = data->dmaInterface - sizeof(struct SCSI_DMAInterface);
593 FreeMem(ptr, sizeof(struct SCSI_DMAInterface) + data->dmaDataSize);
595 if (data->pioInterface)
597 void *ptr = data->pioInterface - sizeof(struct SCSI_BusInterface);
599 FreeMem(ptr, sizeof(struct SCSI_BusInterface) + data->pioDataSize);
602 OOP_DoSuperMethod(cl, o, msg);
606 * Here we take into account that the table can be either
607 * terminated early, or have NULL entries.
609 #define HAVE_VECTOR(x) (x && (x != (APTR)-1))
611 void SCSIBus__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
613 struct scsiBase *SCSIBase = cl->UserData;
614 struct scsi_Bus *data = OOP_INST_DATA(cl, o);
615 ULONG idx;
617 Hidd_Bus_Switch (msg->attrID, idx)
619 case aoHidd_Bus_MaxUnits:
620 *msg->storage = MAX_BUSUNITS;
621 return;
624 Hidd_SCSIBus_Switch (msg->attrID, idx)
626 case aoHidd_SCSIBus_Use80Wire:
627 *msg->storage = FALSE;
628 return;
630 case aoHidd_SCSIBus_Use32Bit:
631 *msg->storage = (HAVE_VECTOR(data->pioVectors->scsi_outsl) &&
632 HAVE_VECTOR(data->pioVectors->scsi_insl)) ?
633 TRUE : FALSE;
634 return;
636 case aoHidd_SCSIBus_UseDMA:
637 *msg->storage = data->dmaVectors ? TRUE : FALSE;
638 return;
640 case aoHidd_SCSIBus_UseIOAlt:
641 *msg->storage = (HAVE_VECTOR(data->busVectors->scsi_out_alt) &&
642 HAVE_VECTOR(data->busVectors->scsi_in_alt)) ?
643 TRUE : FALSE;
644 return;
646 case aoHidd_SCSIBus_CanSetXferMode:
647 *msg->storage = FALSE;
648 return;
651 OOP_DoSuperMethod(cl, o, &msg->mID);
654 void SCSIBus__Hidd_StorageBus__EnumUnits(OOP_Class *cl, OOP_Object *o, struct pHidd_StorageBus_EnumUnits *msg)
656 struct scsi_Bus *data = OOP_INST_DATA(cl, o);
657 BOOL stop = FALSE;
659 D(bug ("[SCSI:Bus] Hidd_StorageBus__EnumUnits()\n");)
661 if (data->sb_Units[0])
662 stop = CALLHOOKPKT(msg->callback, data->sb_Units[0], msg->hookMsg);
663 if ((!stop) && (data->sb_Units[1]))
664 stop = CALLHOOKPKT(msg->callback, data->sb_Units[1], msg->hookMsg);
667 /* Default scsi_out_alt does nothing */
668 static void default_out_alt(void *obj, UBYTE val, UWORD offset)
673 /* Default scsi_in_alt wraps AltStatus to status */
674 static UBYTE default_in_alt(void *obj, UWORD offset)
676 struct SCSI_BusInterface *vec = obj - sizeof(struct SCSI_BusInterface);
678 return vec->scsi_in(obj, scsi_Status);
681 static void CopyVectors(APTR *dest, APTR *src, unsigned int num)
683 unsigned int i;
685 for (i = 0; i < num; i++)
687 if (src[i] == (APTR *)-1)
688 return;
689 if (src[i])
690 dest[i] = src[i];
694 /*****************************************************************************************
696 NAME
697 moHidd_SCSIBus_GetPIOInterface
699 SYNOPSIS
700 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_SCSIBus_GetPIOInterface *Msg);
702 APTR HIDD_SCSIBus_GetPIOInterface(void);
704 LOCATION
705 CLID_Hidd_SCSIBus
707 FUNCTION
708 Instantiates encapsulated PIO interface object and returns its
709 pointer.
711 INPUTS
712 None
714 RESULT
715 A pointer to opaque PIO interface object or NULL in case of failure.
717 NOTES
718 This method should be overloaded by driver subclasses in order to
719 initialize data portion of the interface object.
721 EXAMPLE
723 BUGS
725 SEE ALSO
726 moHidd_SCSIBus_GetDMAInterface
728 INTERNALS
729 Interface objects contain not only driver-specific data, but also
730 a private vector table. Because of this you cannot just AllocMem()
731 the necessary structure in your driver. Always call OOP_DoSuperMethod()
732 in order for the base class to instantiate the interface correctly.
734 *****************************************************************************************/
736 APTR SCSIBus__Hidd_SCSIBus__GetPIOInterface(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
738 struct scsi_Bus *data = OOP_INST_DATA(cl, o);
739 struct SCSI_BusInterface *vec;
742 bug("[SCSI:Bus] %s()\n", __func__);
743 bug("[SCSI:Bus] %s: scsi_Bus @ 0x%p\n", __func__, data);
746 vec = AllocMem(sizeof(struct SCSI_BusInterface) + data->pioDataSize,
747 MEMF_PUBLIC|MEMF_CLEAR);
748 if (vec)
750 D(bug("[SCSI:Bus] %s: SCSI_BusInterface @ 0x%p (%d bytes + %d)\n", __func__, vec, sizeof(struct SCSI_BusInterface), data->pioDataSize);)
752 /* Some default vectors for simplicity */
753 vec->scsi_out_alt = default_out_alt;
754 vec->scsi_in_alt = default_in_alt;
756 CopyVectors((APTR *)vec, (APTR *)data->busVectors,
757 sizeof(struct SCSI_BusInterface) / sizeof(APTR));
759 data->pioInterface = &vec[1];
760 return data->pioInterface;
763 return NULL;
766 /*****************************************************************************************
768 NAME
769 moHidd_SCSIBus_GetDMAInterface
771 SYNOPSIS
772 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_SCSIBus_GetDMAInterface *Msg);
774 APTR HIDD_SCSIBus_GetDMAInterface(void);
776 LOCATION
777 CLID_Hidd_SCSIBus
779 FUNCTION
780 Instantiates encapsulated DMA interface object and returns its
781 pointer.
783 INPUTS
784 None
786 RESULT
787 A pointer to opaque DMA interface object or NULL upon failure or
788 if DMA is not supported by this bus.
790 NOTES
791 This method should be overloaded by driver subclasses in order to
792 initialize data portion of the interface object.
794 EXAMPLE
796 BUGS
798 SEE ALSO
799 moHidd_SCSIBus_GetPIOInterface
801 INTERNALS
802 Interface objects contain not only driver-specific data, but also
803 a private vector table. Because of this you cannot just AllocMem()
804 the necessary structure in your driver. Always call OOP_DoSuperMethod()
805 in order for the base class to instantiate the interface correctly.
807 *****************************************************************************************/
809 APTR SCSIBus__Hidd_SCSIBus__GetDMAInterface(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
811 struct scsi_Bus *data = OOP_INST_DATA(cl, o);
812 struct SCSI_DMAInterface *vec;
814 D(bug("[SCSI:Bus] %s()\n", __func__));
816 if (!data->dmaVectors)
817 return NULL;
819 vec = AllocMem(sizeof(struct SCSI_DMAInterface) + data->dmaDataSize,
820 MEMF_PUBLIC|MEMF_CLEAR);
821 if (vec)
823 CopyVectors((APTR *)vec, data->dmaVectors,
824 sizeof(struct SCSI_DMAInterface) / sizeof(APTR));
826 data->dmaInterface = &vec[1];
827 return data->dmaInterface;
830 return NULL;
833 /*****************************************************************************************
835 NAME
836 moHidd_SCSIBus_SetXferMode
838 SYNOPSIS
839 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_SCSIBus_SetXferMode *Msg);
841 APTR HIDD_SCSIBus_SetXferMode(UBYTE unit, scsi_XferMode mode);
843 LOCATION
844 CLID_Hidd_SCSIBus
846 FUNCTION
847 Sets the desired transfer mode for the given drive on the bus controller.
849 INPUTS
850 unit - drive number (0 for master and 1 for slave)
851 mode - Mode number (see hidd/ata.h)
853 RESULT
854 TRUE if successful or FALSE if the desired mode is not supported
855 by the hardware.
857 NOTES
858 The default implementation is provided for drivers not supporting
859 DMA and always returns FALSE if the caller attempts to set any of
860 DMA modes.
862 EXAMPLE
864 BUGS
865 Current version of ata.device does not use this method, and it is
866 considered reserved.
868 SEE ALSO
869 aoHidd_SCSIBus_CanSetXferMode
871 INTERNALS
873 *****************************************************************************************/
875 BOOL SCSIBus__Hidd_SCSIBus__SetXferMode(OOP_Class *cl, OOP_Object *o, struct pHidd_SCSIBus_SetXferMode *msg)
877 D(bug("[SCSI:Bus] %s()\n", __func__));
879 if ((msg->mode >= AB_XFER_MDMA0) && (msg->mode <= AB_XFER_UDMA6))
881 /* DMA is not supported, we cannot set DMA modes */
882 return FALSE;
885 return TRUE;
888 /*****************************************************************************************
890 NAME
891 moHidd_SCSIBus_Shutdown
893 SYNOPSIS
894 APTR OOP_DoMethod(OOP_Object *obj, struct pHidd_SCSIBus_Shutdown *Msg);
896 APTR HIDD_SCSIBus_Shutdown(void);
898 LOCATION
899 CLID_Hidd_SCSIBus
901 FUNCTION
902 Instantly shutdown all activity on the bus.
904 INPUTS
905 None
907 RESULT
908 None
910 NOTES
911 This method is called by ata.device during system reset handler execution.
913 EXAMPLE
915 BUGS
917 SEE ALSO
919 INTERNALS
920 Default implementation disables interrupt using AltControl register.
922 *****************************************************************************************/
924 void SCSIBus__Hidd_SCSIBus__Shutdown(OOP_Class *cl, OOP_Object *o, OOP_Msg *msg)
926 struct scsi_Bus *data = OOP_INST_DATA(cl, o);
928 D(bug("[SCSI:Bus] %s()\n", __func__));
930 if (data->pioInterface)
932 struct SCSI_BusInterface *vec = data->pioInterface - sizeof(struct SCSI_BusInterface);
934 vec->scsi_out_alt(data->pioInterface, SCSICTLF_INT_DISABLE, scsi_AltControl);
938 /***************** Private nonvirtual methods follow *****************/
940 BOOL Hidd_SCSIBus_Start(OOP_Object *o, struct scsiBase *SCSIBase)
942 struct scsi_Bus *sb = OOP_INST_DATA(SCSIBase->busClass, o);
944 D(bug("[SCSI:Bus] %s()\n", __func__));
946 /* Attach IRQ handler */
947 OOP_SetAttrsTags(o, aHidd_Bus_IRQHandler, Hidd_SCSIBus_HandleIRQ,
948 aHidd_Bus_IRQData , sb,
949 TAG_DONE);
951 /* scan bus - try to locate all devices (disables irq) */
952 scsi_InitBus(sb);
954 if ((sb->sb_Dev[0] == DEV_NONE) && (sb->sb_Dev[1] == DEV_NONE) &&
955 (!sb->keepEmpty))
958 * If there are no devices, and KeepEmpty is not set
959 * the bus will be thrown away.
961 return FALSE;
965 * Assign bus number.
966 * TODO:
967 * 1. This does not take into account possibility to
968 * unload drivers. In this case existing units will disappear,
969 * freeing up their numbers. These numbers should be reused.
970 * 2. We REALLY need modify-and-fetch atomics.
972 Forbid();
973 sb->sb_BusNum = SCSIBase->scsi__buscount++;
974 Permit();
976 if ((sb->sb_Dev[0] < DEV_ATA) && (sb->sb_Dev[1] < DEV_ATA))
978 /* Do not start up task if there are no usable devices. */
979 return TRUE;
983 * This small trick is based on the fact that shared semaphores
984 * have no specific owner. You can obtain and release them from
985 * within any task. It will block only on attempt to re-lock it
986 * in exclusive mode.
987 * So instead of complex handshake we obtain the semaphore before
988 * starting bus task. It will release the semaphore when done.
990 ObtainSemaphoreShared(&SCSIBase->DetectionSem);
993 * Start up bus task. It will perform scanning asynchronously, and
994 * then, if successful, insert units. This allows to keep things parallel.
996 D(bug("[SCSI>>] Start: Bus %u: Unit 0 - %d, Unit 1 - %d\n", sb->sb_BusNum, sb->sb_Dev[0], sb->sb_Dev[1]));
997 return NewCreateTask(TASKTAG_PC , BusTaskCode,
998 TASKTAG_NAME , "ATA[PI] Subsystem",
999 TASKTAG_STACKSIZE , STACK_SIZE,
1000 TASKTAG_PRI , TASK_PRI,
1001 TASKTAG_TASKMSGPORT, &sb->sb_MsgPort,
1002 TASKTAG_ARG1 , sb,
1003 TASKTAG_ARG2 , SCSIBase,
1004 TAG_DONE) ? TRUE : FALSE;
1007 AROS_UFH3(BOOL, Hidd_SCSIBus_Open,
1008 AROS_UFHA(struct Hook *, h, A0),
1009 AROS_UFHA(OOP_Object *, obj, A2),
1010 AROS_UFHA(IPTR, reqUnit, A1))
1012 AROS_USERFUNC_INIT
1014 struct IORequest *req = h->h_Data;
1015 struct scsiBase *SCSIBase = (struct scsiBase *)req->io_Device;
1016 struct scsi_Bus *sb = (struct scsi_Bus *)OOP_INST_DATA(SCSIBase->busClass, obj);
1017 ULONG bus = reqUnit >> 1;
1018 UBYTE dev = reqUnit & 1;
1020 D(bug("[SCSI:Bus] %s()\n", __func__));
1021 D(bug("[SCSI%02ld] Checking bus %u dev %u\n", reqUnit, bus, dev));
1023 if ((sb->sb_BusNum == bus) && sb->sb_Units[dev])
1025 struct scsi_Unit *unit = (struct scsi_Unit *)OOP_INST_DATA(SCSIBase->unitClass, sb->sb_Units[dev]);
1027 /* Got the unit */
1028 req->io_Unit = &unit->su_Unit;
1029 req->io_Error = 0;
1031 unit->su_Unit.unit_OpenCnt++;
1032 return TRUE;
1035 return FALSE;
1037 AROS_USERFUNC_EXIT