Added a test for MUIA_Listview_SelectChange.
[AROS.git] / arch / m68k-amiga / hidd / gayle_ata / probe.c
bloba9e63606c0be3c54a9bc5c0c9146492220cbc966
1 /*
2 Copyright © 2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: A600/A1200/A4000 ATA HIDD hardware detection routine
6 Lang: English
7 */
9 #define DEBUG 1
11 #define __OOP_NOMETHODBASES__
13 #include <aros/asmcall.h>
14 #include <aros/debug.h>
15 #include <aros/symbolsets.h>
16 #include <asm/io.h>
17 #include <exec/lists.h>
18 #include <exec/rawfmt.h>
19 #include <hidd/ata.h>
20 #include <hidd/hidd.h>
21 #include <oop/oop.h>
22 #include <proto/exec.h>
23 #include <proto/oop.h>
25 #include <hardware/custom.h>
26 #include <graphics/gfxbase.h>
27 #include <hardware/ata.h>
29 #include <string.h>
31 #include "bus_class.h"
32 #include "interface_pio.h"
34 static BOOL custom_check(APTR addr)
36 volatile struct Custom *custom = (struct Custom*)0xdff000;
37 volatile struct Custom *maybe_custom = (struct Custom*)addr;
38 UWORD intena;
39 BOOL iscustom = TRUE;
41 intena = custom->intenar;
42 custom->intena = 0x7fff;
43 custom->intena = 0xc000;
44 maybe_custom->intena = 0x7fff;
45 if (custom->intenar == 0x4000) {
46 maybe_custom->intena = 0x7fff;
47 if (custom->intenar == 0x4000)
48 iscustom = FALSE;
50 custom->intena = 0x7fff;
51 custom->intena = intena | 0x8000;
52 return iscustom;
55 static UBYTE *getport(struct ata_ProbedBus *ddata)
57 volatile struct Custom *custom = (struct Custom*)0xdff000;
58 UBYTE id, status1, status2;
59 volatile UBYTE *port, *altport;
60 struct GfxBase *gfx;
62 port = NULL;
63 gfx = (struct GfxBase*)TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS);
64 Disable();
65 id = ReadGayle();
66 if (id) {
67 port = (UBYTE*)GAYLE_BASE_1200;
68 ddata->gayleirqbase = (UBYTE*)GAYLE_IRQ_1200;
69 } else {
70 // AGA does not have custom mirror here but lets make sure..
71 if (!custom_check((APTR)0xdd4000) && (custom->vposr & 0x7f00) >= 0x2200) {
72 port = (UBYTE*)GAYLE_BASE_4000;
73 ddata->a4000 = TRUE;
74 ddata->gayleirqbase = (UBYTE*)GAYLE_IRQ_4000;
77 Enable();
78 CloseLibrary((struct Library*)gfx);
80 D(bug("[ATA] Gayle ID=%02x. Possible IDE port=%08x.\n", id, (ULONG)port & ~3));
81 if (port == NULL)
82 return NULL;
84 ddata->port = (UBYTE*)port;
85 altport = port + 0x1010;
86 ddata->altport = (UBYTE*)altport;
87 Disable();
88 port[ata_DevHead * 4] = ATAF_ERROR;
89 /* If nothing connected, we get back what we wrote, ATAF_ERROR set */
90 status1 = port[ata_Status * 4];
91 port[ata_DevHead * 4] = ATAF_DATAREQ;
92 status2 = port[ata_Status * 4];
93 port[ata_DevHead * 4] = 0;
94 Enable();
95 D(bug("[ATA] Status=%02x,%02x\n", status1, status2));
96 // BUSY and DRDY both active or ERROR/DATAREQ = no drive(s) = do not install driver
97 if ( (((status1 | status2) & (ATAF_BUSY | ATAF_DRDY)) == (ATAF_BUSY | ATAF_DRDY))
98 || ((status1 | status2) & (ATAF_ERROR | ATAF_DATAREQ)))
100 D(bug("[ATA] Drives not detected\n"));
101 return NULL;
103 if (ddata->doubler) {
104 UBYTE v1, v2;
105 /* check if AltControl is both readable and writable
106 * It is either floating or DevHead if IDE doubler is connected.
107 * AltControl = DevHead (R)
108 * Device Control = DevHead (W)
110 Disable();
111 altport[ata_AltControl * 4] = 0;
112 port[ata_DevHead * 4] = 1;
113 v1 = altport[ata_AltControl * 4];
114 altport[ata_AltControl * 4] = 2;
115 port[ata_DevHead * 4] = 4;
116 v2 = altport[ata_AltControl * 4];
117 altport[ata_AltControl * 4] = 0;
118 port[ata_DevHead * 4] = 0;
119 Enable();
120 if ((v1 == 0 && v2 == 2) || (v1 == 1 && v2 == 4) || (v1 == 0xff && v2 == 0xff)) {
121 ddata->doubler = 2;
122 } else {
123 ddata->doubler = 0;
125 D(bug("[ATA] IDE doubler check (%02X, %02X) = %d\n", v1, v2, ddata->doubler));
126 ddata->altport = NULL;
128 /* we may have connected drives */
129 return (UBYTE*)port;
132 static int ata_Scan(struct ataBase *base)
134 struct ata_ProbedBus *probedbus;
136 probedbus = AllocVec(sizeof(struct ata_ProbedBus), MEMF_ANY | MEMF_CLEAR);
137 if (probedbus && getport(probedbus)) {
138 OOP_Object *ata = OOP_NewObject(NULL, CLID_HW_ATA, NULL);
139 if (ata) {
140 HWBase = OOP_GetMethodID(IID_HW, 0);
141 struct TagItem attrs[] =
143 {aHidd_DriverData , (IPTR)probedbus },
144 {aHidd_ATABus_PIODataSize , sizeof(struct pio_data) },
145 {aHidd_ATABus_BusVectors , (IPTR)bus_FuncTable },
146 {aHidd_ATABus_PIOVectors , (IPTR)pio_FuncTable },
147 {aHidd_ATABus_KeepEmpty , FALSE },
148 {TAG_DONE , 0 }
150 OOP_Object *bus;
153 * We use this field as ownership indicator.
154 * The trick is that HW_AddDriver() fails if either object creation fails
155 * or subsystem-side setup fails. In the latter case our object will be
156 * disposed.
157 * We need to know whether OOP_DisposeObject() or we should deallocate
158 * this structure on failure.
160 probedbus->atapb_Node.ln_Succ = NULL;
162 bus = HW_AddDriver(ata, base->busClass, attrs);
163 if (bus)
164 return TRUE;
165 D(bug("[GAYLE-ATA] Failed to create object for device IO: %x:%x IRQ: %x\n",
166 probedbus->port, probedbus->altport, probedbus->gayleirqbase));
169 * Free the structure only upon object creation failure!
170 * In case of success it becomes owned by the driver object!
172 if (!probedbus->atapb_Node.ln_Succ)
173 FreeVec(probedbus);
174 return TRUE;
177 FreeVec(probedbus);
179 return TRUE;
182 ADD2INITLIB(ata_Scan, 30)