add place-holder directory for the a3000 wd533c93 scsi controller implementation.
[AROS.git] / rom / devs / scsi / lowlevel.c
blob15bce219b4c26e129481e176ccc2f553fe296b41
1 /*
2 Copyright © 2004-2018, The AROS Development Team. All rights reserved.
3 $Id: lowlevel.c 55802 2019-03-08 21:47:59Z wawa $
5 Desc:
6 Lang: English
7 */
9 /*
10 * TODO:
11 * - put a critical section around DMA transfers (shared dma channels)
14 #include <aros/debug.h>
16 #include <proto/exec.h>
18 #include <exec/types.h>
19 #include <exec/exec.h>
20 #include <exec/resident.h>
21 #include <utility/utility.h>
22 #include <oop/oop.h>
24 #include <devices/timer.h>
26 #include "scsi.h"
27 #include "scsi_bus.h"
28 #include "timer.h"
30 // use #define xxx(a) D(a) to enable particular sections.
31 #if DEBUG
32 #define DIRQ(a) D(a)
33 #define DIRQ_MORE(a)
34 #define DUMP(a) D(a)
35 #define DUMP_MORE(a)
36 #define DSCSI(a) D(a)
37 #define DATAPI(a) D(a)
38 #define DINIT(a) D(a)
39 #else
40 #define DIRQ(a) do { } while (0)
41 #define DIRQ_MORE(a) do { } while (0)
42 #define DUMP(a) do { } while (0)
43 #define DUMP_MORE(a) do { } while (0)
44 #define DSCSI(a) do { } while (0)
45 #define DATAPI(a) do { } while (0)
46 #define DINIT(a)
47 #endif
48 /* Errors that shouldn't happen */
49 #define DERROR(a) a
52 * Initial device configuration that suits *all* cases
54 void scsi_init_unit(struct scsi_Bus *bus, struct scsi_Unit *unit, UBYTE u)
56 struct scsiBase *SCSIBase = bus->sb_Base;
57 OOP_Object *obj = OOP_OBJECT(SCSIBase->busClass, bus);
59 unit->su_Bus = bus;
60 unit->pioInterface = bus->pioInterface;
61 unit->su_UnitNum = bus->sb_BusNum << 1 | u; // b << 8 | u
62 unit->su_DevMask = 0xa0 | (u << 4);
64 DINIT(bug("[SCSI%02u] scsi_init_unit: bus %u unit %d\n", unit->su_UnitNum, bus->sb_BusNum, u));
66 #if (0)
67 /* Set PIO transfer functions, either 16 or 32 bits */
68 if (SCSIBase->scsi_32bit && OOP_GET(obj, aHidd_SCSIBus_Use32Bit))
69 Unit_Enable32Bit(unit);
70 else
71 Unit_Disable32Bit(unit);
72 #endif
75 BOOL scsi_setup_unit(struct scsi_Bus *bus, struct scsi_Unit *unit)
78 * this stuff always goes along the same way
79 * WARNING: NO INTERRUPTS AT THIS POINT!
81 UBYTE u;
83 DINIT(bug("[SCSI ] scsi_setup_unit(%d)\n", unit->su_UnitNum));
84 #if (0)
85 scsi_SelectUnit(unit);
87 if (FALSE == scsi_WaitBusyTO(unit, 1, FALSE, FALSE, NULL))
89 DINIT(bug("[SCSI%02ld] scsi_setup_unit: ERROR: Drive not ready for use. Keeping functions stubbed\n", unit->su_UnitNum));
90 return FALSE;
93 u = unit->su_UnitNum & 1;
94 switch (bus->sb_Dev[u])
97 * safe fallback settings
99 case DEV_SATAPI:
100 case DEV_ATAPI:
101 case DEV_SATA:
102 case DEV_ATA:
103 unit->su_Identify = scsi_Identify;
104 break;
106 default:
107 DINIT(bug("[SCSI%02ld] scsi_setup_unit: Unsupported device %lx. All functions will remain stubbed.\n", unit->su_UnitNum, bus->sb_Dev[u]));
108 return FALSE;
111 DINIT(bug("[SCSI ] scsi_setup_unit: Enabling IRQs\n"));
112 PIO_OutAlt(bus, 0x0, scsi_AltControl);
115 * now make unit self diagnose
117 if (unit->su_Identify(unit) != 0)
119 return FALSE;
121 #endif
123 return TRUE;
126 void scsi_InitBus(struct scsi_Bus *bus)
128 struct scsiBase *SCSIBase = bus->sb_Base;
129 OOP_Object *obj = OOP_OBJECT(SCSIBase->busClass, bus);
130 IPTR haveAltIO;
131 UBYTE tmp1, tmp2;
132 UWORD i;
135 * initialize timer for the sake of scanning
137 bus->sb_Timer = scsi_OpenTimer(bus->sb_Base);
139 #if (0)
140 OOP_GetAttr(obj, aHidd_SCSIBus_UseIOAlt, &haveAltIO);
141 bus->haveAltIO = haveAltIO != 0;
142 #endif
144 DINIT(bug("[SCSI ] scsi_InitBus(%p)\n", bus));
146 bus->sb_Dev[0] = DEV_NONE;
147 bus->sb_Dev[1] = DEV_NONE;
149 /* Check if device 0 and/or 1 is present on this bus. It may happen that
150 a single drive answers for both device addresses, but the phantom
151 drive will be filtered out later */
152 for (i = 0; i < MAX_BUSUNITS; i++)
154 /* Select device and disable IRQs */
155 #if (0)
156 PIO_Out(bus, DEVHEAD_VAL | (i << 4), scsi_DevHead);
157 #endif
158 scsi_WaitTO(bus->sb_Timer, 0, 400, 0);
159 PIO_OutAlt(bus, SCSICTLF_INT_DISABLE, scsi_AltControl);
161 /* Write some pattern to registers. This is a variant of a more
162 common technique, with the difference that we don't use the
163 sector count register because some bad ATAPI drives disallow
164 writing to it */
165 PIO_Out(bus, 0x55, scsi_LBALow);
166 PIO_Out(bus, 0xaa, scsi_LBAMid);
167 PIO_Out(bus, 0xaa, scsi_LBALow);
168 PIO_Out(bus, 0x55, scsi_LBAMid);
169 PIO_Out(bus, 0x55, scsi_LBALow);
170 PIO_Out(bus, 0xaa, scsi_LBAMid);
172 tmp1 = PIO_In(bus, scsi_LBALow);
173 tmp2 = PIO_In(bus, scsi_LBAMid);
174 DB2(bug("[SCSI ] scsi_InitBus: Reply 0x%02X 0x%02X\n", tmp1, tmp2));
176 if ((tmp1 == 0x55) && (tmp2 == 0xaa))
177 bus->sb_Dev[i] = DEV_UNKNOWN;
178 DINIT(bug("[SCSI ] scsi_InitBus: Device type = 0x%02X\n", bus->sb_Dev[i]));
180 #if (0)
181 scsi_ResetBus(bus);
182 #endif
183 scsi_CloseTimer(bus->sb_Timer);
184 DINIT(bug("[SCSI ] scsi_InitBus: Finished\n"));