From 3bb05289d448a811770f915aa6d20928083f1e79 Mon Sep 17 00:00:00 2001 From: neil Date: Thu, 23 Apr 2009 20:36:47 +0000 Subject: [PATCH] - Interrupt flag in DMA Status register is now cleared after every interrupt. This allows more SATA buses to work. - Detect which buses are in legacy mode based on PCI Interface byte rather than base addresses. - Always use legacy IRQ for buses in legacy mode. - Use a maximum of two PCI buses in compatiblity mode, as per specs. - Disable UDMA modes above 2 if 80-wire cable not detected (SATA should be unaffected). - Corrected detection of slave devices. - Disable DMA if DMA-capability bit is cleared in PCI Interface byte. - Corrected detection of available PIO and MDMA modes. - Now attempts to use all subclasses of mass storage PCI class except SCSI and serial SCSI. Hence removed nosubclass bootloader option and separate check for SiI3114/3512. - We now handle all interrupts generated during a Packet command. - Eliminated known unhandled interrupts. - Now reads and discards excess data provided by buggy drive firmwares in packet responses, allowing such drives to be used again. - Increased timeout in ata_exec_cmd() from 3 seconds to 30 to allow for drives that need to spin up before responding. - Check ATAPIF_WRITE instead of ATAPIF_READ in ata_IRQPIOWriteAtapi(), which should fix PIO ATAPI writes (untested). - Removed definitions for invalid PIO and DMA modes. - DMADIR bit was opposite of what it should be. Fixed. - Warn user about simplex DMA. git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@31147 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- arch/common/ata.device/ata.c | 23 +-- arch/common/ata.device/ata.conf | 2 +- arch/common/ata.device/ata.h | 23 +-- arch/common/ata.device/ata_init.c | 268 +++++++++++++--------------------- arch/common/ata.device/dma_generic.c | 16 +- arch/common/ata.device/lowlevel.c | 274 +++++++++++++++++------------------ arch/common/ata.device/timer.c | 6 +- arch/common/ata.device/timer.h | 8 +- 8 files changed, 256 insertions(+), 364 deletions(-) diff --git a/arch/common/ata.device/ata.c b/arch/common/ata.device/ata.c index 8660ee4fd..adffac19f 100644 --- a/arch/common/ata.device/ata.c +++ b/arch/common/ata.device/ata.c @@ -6,7 +6,7 @@ Lang: English */ /* - * CHANGELOG: + * PARTIAL CHANGELOG: * DATE NAME ENTRY * ---------- ------------------ ------------------------------------------------------------------- * 2008-01-25 T. Wiszkowski Rebuilt, rearranged and partially fixed 60% of the code here @@ -827,7 +827,7 @@ void DaemonCode(LIBBASETYPEPTR LIBBASE) * Prepare message ports and timer.device's request */ myport = CreateMsgPort(); - timer = ata_OpenTimer(); + timer = ata_OpenTimer(); bus = (struct ata_Bus*)LIBBASE->ata_Buses.mlh_Head; /* @@ -886,9 +886,6 @@ void DaemonCode(LIBBASETYPEPTR LIBBASE) D(bug("[ATA++] Starting sweep medium presence detection\n")); -// if (count) - if (1) - { /* * Endless loop */ @@ -922,17 +919,8 @@ void DaemonCode(LIBBASETYPEPTR LIBBASE) /* * And then hide and wait for 1 second */ - ata_WaitTO(timer, 1, 0, 0); + ata_WaitTO(timer, 1, 0, 0); } - } - else - { - /* - * Well, when there are no ATAPI devices, daemon is useless. Say goodbye and quit then - */ - D(bug("[%s] Deamon useless (no ATAPI devices in system). Bye\n",FindTask(NULL)->tc_Node.ln_Name)); - ata_CloseTimer(timer); - } } static void TaskCode(struct ata_Bus *, struct Task*, struct SignalSemaphore*); @@ -977,8 +965,7 @@ int ata_InitBusTask(struct ata_Bus *bus, struct SignalSemaphore *ready) bus->ab_MsgPort->mp_SigTask = t; bus->ab_MsgPort->mp_Node.ln_Name = "ATA[PI] Subsystem"; - - /* Tell the System, which memory regions are to be freed upon a task completion */ + /* Tell the System which memory regions are to be freed upon a task completion */ ml->ml_NumEntries = 3; ml->ml_ME[0].me_Addr = t; ml->ml_ME[0].me_Length = sizeof(struct Task); @@ -1024,7 +1011,7 @@ static int CreateInterrupt(struct ata_Bus *bus) struct pHidd_IRQ_AddHandler __msg__ = { mID: OOP_GetMethodID(IID_Hidd_IRQ, moHidd_IRQ_AddHandler), handlerinfo: bus->ab_IntHandler, - id: bus->ab_Irq, + id: bus->ab_IRQ, }, *msg = &__msg__; if (OOP_DoMethod((OOP_Object *)o, (OOP_Msg)msg)) diff --git a/arch/common/ata.device/ata.conf b/arch/common/ata.device/ata.conf index 12c8e538b..30e54f99a 100644 --- a/arch/common/ata.device/ata.conf +++ b/arch/common/ata.device/ata.conf @@ -1,6 +1,6 @@ ##begin config basename ata -version 41.7 +version 41.8 libbasetype struct ataBase residentpri 4 beginio_func BeginIO diff --git a/arch/common/ata.device/ata.h b/arch/common/ata.device/ata.h index feee781e9..dd392fac2 100644 --- a/arch/common/ata.device/ata.h +++ b/arch/common/ata.device/ata.h @@ -9,7 +9,7 @@ Desc: ata.device main private include file Lang: English */ /* - * CHANGELOG: + * PARTIAL CHANGELOG: * DATE NAME ENTRY * ---------- ------------------ ------------------------------------------------------------------- * 2008-01-25 T. Wiszkowski Rebuilt, rearranged and partially fixed 60% of the code here @@ -132,13 +132,12 @@ struct ata_Bus struct ataBase *ab_Base; /* device self */ ULONG ab_Port; /* IO port used */ ULONG ab_Alt; /* alternate io port */ - UBYTE ab_Irq; /* IRQ used */ + UBYTE ab_IRQ; /* IRQ number used */ UBYTE ab_Dev[2]; /* Master/Slave type, see below */ UBYTE ab_Flags; /* Bus flags similar to unit flags */ BYTE ab_SleepySignal; /* Signal used to wake the task up, when it's waiting */ /* for data requests/DMA */ UBYTE ab_BusNum; /* bus id - used to calculate device id */ - BOOL ab_IRQ; /* set if IRQ is enabled */ LONG ab_Timeout; /* in seconds; please note that resolution is low (1sec) */ struct ata_Unit *ab_Units[MAX_BUSUNITS]; /* Units on the bus */ @@ -191,7 +190,7 @@ struct DriveIdent { UWORD pad6[2]; // 57-58 UWORD id_RWMultipleTrans; // 59 ULONG id_LBASectors; // 60-61 - UWORD pad7; // 62 + UWORD id_DMADir; // 62 UWORD id_MWDMASupport; // 63 UWORD id_PIOSupport; // 64 UWORD id_MWDMA_MinCycleTime; // 65 @@ -211,8 +210,8 @@ struct DriveIdent { UWORD id_Commands6; // 87 UWORD id_UDMASupport; // 88 UWORD id_SecurityEraseTime; // 89 - UWORD id_EnchSecurityEraseTime; // 90 - UWORD id_CurrentAdvowerMode; // 91 + UWORD id_ESecurityEraseTime; // 90 + UWORD id_CurrentAdvPowerMode; // 91 UWORD id_MasterPwdRevision; // 92 UWORD id_HWResetResult; // 93 UWORD id_AcousticManagement; // 94 @@ -330,18 +329,10 @@ typedef enum AB_XFER_PIO2, AB_XFER_PIO3, AB_XFER_PIO4, - AB_XFER_PIO5, - AB_XFER_PIO6, - AB_XFER_PIO7, AB_XFER_MDMA0, AB_XFER_MDMA1, AB_XFER_MDMA2, - AB_XFER_MDMA3, - AB_XFER_MDMA4, - AB_XFER_MDMA5, - AB_XFER_MDMA6, - AB_XFER_MDMA7, AB_XFER_UDMA0, AB_XFER_UDMA1, @@ -350,7 +341,6 @@ typedef enum AB_XFER_UDMA4, AB_XFER_UDMA5, AB_XFER_UDMA6, - AB_XFER_UDMA7, AB_XFER_48BIT, AB_XFER_RWMULTI, @@ -373,10 +363,12 @@ typedef enum #define AB_DiscPresent 30 /* disc now in drive */ #define AB_DiscChanged 29 /* disc changed */ #define AB_Removable 28 /* media removable */ +#define AB_80Wire 27 /* has an 80-wire cable */ #define AF_DiscPresent (1 << AB_DiscPresent) #define AF_DiscChanged (1 << AB_DiscChanged) #define AF_Removable (1 << AB_Removable) +#define AF_80Wire (1 << AB_80Wire) /* ATA/ATAPI registers */ #define ata_Error 1 @@ -497,7 +489,6 @@ ULONG ata_Identify(struct ata_Unit*); ULONG atapi_DirectSCSI(struct ata_Unit*, struct SCSICmd *); ULONG atapi_RequestSense(struct ata_Unit* unit, UBYTE* sense, ULONG senselen); -void ata_EnableIRQ(struct ata_Bus *bus, BOOL enable); int ata_InitBusTask(struct ata_Bus *, struct SignalSemaphore*); int ata_InitDaemonTask(struct ataBase *); diff --git a/arch/common/ata.device/ata_init.c b/arch/common/ata.device/ata_init.c index 377b2248d..6c602cd80 100644 --- a/arch/common/ata.device/ata_init.c +++ b/arch/common/ata.device/ata_init.c @@ -6,7 +6,7 @@ Lang: English */ /* - * CHANGELOG: + * PARTIAL CHANGELOG: * DATE NAME ENTRY * ---------- ------------------ ------------------------------------------------------------------- * 2008-04-25 P. Fedin Brought back device discovery for old machines without PCI IDE controllers @@ -78,7 +78,6 @@ typedef struct { struct ataBase *ATABase; UWORD CurrentBus; - UWORD PredefBus; } EnumeratorArgs; struct ata_ProbedBus @@ -88,8 +87,8 @@ struct ata_ProbedBus IPTR atapb_IOAlt; IPTR atapb_INTLine; IPTR atapb_DMABase; - int atapb_x; EnumeratorArgs *atapb_a; + BOOL atapb_Has80Wire; }; struct ata_LegacyBus @@ -107,6 +106,9 @@ struct ata_LegacyBus #define ATABUSNODEPRI_PROBEDLEGACY 100 #define ATABUSNODEPRI_LEGACY 50 +#define RANGESIZE0 8 +#define RANGESIZE1 4 + /* static list of io/irqs that we can handle */ static struct ata__legacybus { @@ -212,14 +214,14 @@ BOOL ata_RegisterVolume(ULONG StartCyl, ULONG EndCyl, struct ata_Unit *unit) } static void ata_RegisterBus(IPTR IOBase, IPTR IOAlt, IPTR INTLine, - IPTR DMABase, int x, EnumeratorArgs *a) + IPTR DMABase, BOOL has80Wire, EnumeratorArgs *a) { /* * ata bus - this is going to be created and linked to the master list here */ struct ata_Bus *ab; - D(bug("[ATA>>] ata_RegisterBus: IRQ %d, IO: %x:%x, DMA: %x\n", INTLine, IOBase, IOAlt, DMABase)); + UWORD i; /* * initialize structure @@ -231,20 +233,21 @@ static void ata_RegisterBus(IPTR IOBase, IPTR IOAlt, IPTR INTLine, ab->ab_Base = a->ATABase; ab->ab_Port = IOBase; ab->ab_Alt = IOAlt; - ab->ab_Irq = INTLine; + ab->ab_IRQ = INTLine; ab->ab_Dev[0] = DEV_NONE; ab->ab_Dev[1] = DEV_NONE; ab->ab_Flags = 0; ab->ab_SleepySignal = 0; ab->ab_BusNum = a->CurrentBus++; ab->ab_Timeout = 0; - ab->ab_Units[0] = 0; - ab->ab_Units[1] = 0; + ab->ab_Units[0] = NULL; + ab->ab_Units[1] = NULL; ab->ab_IntHandler = (HIDDT_IRQ_Handler *)AllocVecPooled(a->ATABase->ata_MemPool, sizeof(HIDDT_IRQ_Handler)); - ab->ab_Task = 0; - ab->ab_HandleIRQ = 0; + ab->ab_Task = NULL; + ab->ab_HandleIRQ = NULL; D(bug("[ATA>>] ata_RegisterBus: Analysing bus %d, units %d and %d\n", ab->ab_BusNum, ab->ab_BusNum<<1, (ab->ab_BusNum<<1)+1)); + D(bug("[ATA>>] ata_RegisterBus: IRQ %d, IO: %x:%x, DMA: %x\n", INTLine, IOBase, IOAlt, DMABase)); /* * allocate DMA PRD @@ -257,17 +260,16 @@ static void ata_RegisterBus(IPTR IOBase, IPTR IOAlt, IPTR INTLine, * scan bus - try to locate all devices (disables irq) */ ata_InitBus(ab); - if (ab->ab_Dev[0] > DEV_UNKNOWN) - { - ab->ab_Units[0] = AllocVecPooled(a->ATABase->ata_MemPool, sizeof(struct ata_Unit)); - ab->ab_Units[0]->au_DMAPort = (DMABase != 0 ? DMABase + (x<<3) : 0); - ata_init_unit(ab, 0); - } - if (ab->ab_Dev[1] > DEV_UNKNOWN) + for (i = 0; i < MAX_BUSUNITS; i++) { - ab->ab_Units[1] = AllocVecPooled(a->ATABase->ata_MemPool, sizeof(struct ata_Unit)); - ab->ab_Units[1]->au_DMAPort = (DMABase != 0 ? DMABase + (x<<3) : 0); - ata_init_unit(ab, 1); + if (ab->ab_Dev[i] > DEV_UNKNOWN) + { + ab->ab_Units[i] = AllocVecPooled(a->ATABase->ata_MemPool, + sizeof(struct ata_Unit)); + ab->ab_Units[i]->au_DMAPort = DMABase; + ab->ab_Units[i]->au_Flags = has80Wire ? AF_80Wire : 0; + ata_init_unit(ab, i); + } } D(bug("[ATA>>] ata_RegisterBus: Bus %ld: Unit 0 - %x, Unit 1 - %x\n", ab->ab_BusNum, ab->ab_Dev[0], ab->ab_Dev[1])); @@ -280,33 +282,10 @@ static void ata_RegisterBus(IPTR IOBase, IPTR IOAlt, IPTR INTLine, AddTail((struct List*)&a->ATABase->ata_Buses, (struct Node*)ab); } -static BOOL ata_IsLegacyPort(IPTR _ioport) -{ - int i; - for (i = 0; LegacyBuses[i].lb_Port != 0 ; i++) - { - if (_ioport == (IPTR)LegacyBuses[i].lb_Port) - { - return TRUE; - } - } - return FALSE; -} - -static struct ata_LegacyBus *ata_FindLegacyBus(struct ataBase * _atadevbase, IPTR _ioport) -{ - struct Node * __legacybusNode; - ForeachNode(&_atadevbase->ata__legacybuses, __legacybusNode) - { - if (((struct ata_LegacyBus *)__legacybusNode)->atalb_IOBase == _ioport) - return (struct ata_LegacyBus *)__legacybusNode; - } - return (struct ata_LegacyBus *)NULL; -} - /* * PCI BUS ENUMERATOR - * collect ALL ata/ide capable devices (including SATA and other) and spawn consecutive tasks + * collect ALL ata/ide capable devices (including SATA and other) and + * spawn concurrent tasks. * * This function is growing too large. It will shorten drasticly once this whole mess gets converted into c++ */ @@ -322,13 +301,17 @@ AROS_UFH3(void, ata_PCIEnumerator_h, /* * parameters we will want to acquire */ - IPTR ProductID, + IPTR ProductID, VendorID, DMABase, INTLine, IOBase, - IOBaseOrig, - IOAlt; + IOAlt, + IOSize, + AltSize, + SubClass, + Interface, + ATAIOConfig; BOOL _usablebus = FALSE; @@ -338,10 +321,13 @@ AROS_UFH3(void, ata_PCIEnumerator_h, OOP_AttrBase HiddPCIDeviceAttrBase = OOP_ObtainAttrBase(IID_Hidd_PCIDevice); /* - * new parameters for every device: - * - allow bus mastering + * message to get 80-wire cable report */ - + struct pHidd_PCIDevice_ReadConfigLong ataioconfigmsg = + { + OOP_GetMethodID(IID_Hidd_PCIDevice, moHidd_PCIDevice_ReadConfigLong), + 0x54, + }; /* * enumerator params @@ -356,78 +342,72 @@ AROS_UFH3(void, ata_PCIEnumerator_h, /* * obtain more or less useful data */ - OOP_GetAttr(Device, aHidd_PCIDevice_ProductID, &ProductID); OOP_GetAttr(Device, aHidd_PCIDevice_VendorID, &VendorID); + OOP_GetAttr(Device, aHidd_PCIDevice_ProductID, &ProductID); OOP_GetAttr(Device, aHidd_PCIDevice_Base4, &DMABase); - if (a->ATABase->ata_NoDMA) + OOP_GetAttr(Device, aHidd_PCIDevice_SubClass, &SubClass); + OOP_GetAttr(Device, aHidd_PCIDevice_Interface, &Interface); + + if (a->ATABase->ata_NoDMA || !(Interface & 0x80)) DMABase = 0; + ATAIOConfig = OOP_DoMethod(Device, (OOP_Msg)&ataioconfigmsg); + /* - * we can have as many as four ports assigned to this device + * we can have up to two buses assigned to this device */ - for (x = 0; x < MAX_DEVICEBUSES; x++) + for (x = 0; SubClass != 0 && SubClass != 7 && x < MAX_DEVICEBUSES; x++) { struct ata_LegacyBus *_legacyBus = NULL; - int h = 0; + BOOL isLegacy = FALSE; + + if (x == 0) + { + bug("[ATA ] ata_PCIEnumerator_h: Found IDE device %04x:%04x\n", VendorID, ProductID); + } + /* - * obtain base and interrupt + * obtain I/O bases and interrupt line */ - switch (x) + if ((Interface & (1 << (x << 1))) || SubClass != 1) { - case 0: - OOP_GetAttr(Device, aHidd_PCIDevice_Base0, &IOBase); - OOP_GetAttr(Device, aHidd_PCIDevice_Base1, &IOAlt); - break; - case 1: - OOP_GetAttr(Device, aHidd_PCIDevice_Base2, &IOBase); - OOP_GetAttr(Device, aHidd_PCIDevice_Base3, &IOAlt); + switch (x) + { + case 0: + OOP_GetAttr(Device, aHidd_PCIDevice_Base0, &IOBase); + OOP_GetAttr(Device, aHidd_PCIDevice_Size0, &IOSize); + OOP_GetAttr(Device, aHidd_PCIDevice_Base1, &IOAlt); + OOP_GetAttr(Device, aHidd_PCIDevice_Size1, &AltSize); + break; + case 1: + OOP_GetAttr(Device, aHidd_PCIDevice_Base2, &IOBase); + OOP_GetAttr(Device, aHidd_PCIDevice_Size2, &IOSize); + OOP_GetAttr(Device, aHidd_PCIDevice_Base3, &IOAlt); + OOP_GetAttr(Device, aHidd_PCIDevice_Size3, &AltSize); break; + } + OOP_GetAttr(Device, aHidd_PCIDevice_INTLine, &INTLine); } - OOP_GetAttr(Device, aHidd_PCIDevice_INTLine, &INTLine); - IOBaseOrig = IOBase; - - if (IOBase == (IPTR)NULL) - { - if ((_legacyBus = (struct ata_LegacyBus *)RemHead(&a->ATABase->ata__legacybuses)) != NULL) - { - IOBase = _legacyBus->atalb_IOBase; - IOAlt = _legacyBus->atalb_IOAlt; - if ((INTLine == (IPTR)0x00) || (INTLine == (IPTR)0xFF)) - INTLine = _legacyBus->atalb_INTLine; - FreeMem(_legacyBus, sizeof(struct ata_LegacyBus)); - h = 1; - } - } - else + else if ((_legacyBus = (struct ata_LegacyBus *) + a->ATABase->ata__legacybuses.lh_Head)->atalb_ControllerID == 0) { - /* - Sanity Check! some devices have reportedly - returned the actual legacy port rather than 0 - make sure we arent one of those .. - */ - if ((ata_IsLegacyPort(IOBase))) - { - if ((_legacyBus = ata_FindLegacyBus(a->ATABase, IOBase)) != NULL) - { - Remove(&_legacyBus->atalb_Node); - if ((INTLine == (IPTR)0x00) || (INTLine == (IPTR)0xFF)) - INTLine = _legacyBus->atalb_INTLine; - FreeMem(_legacyBus, sizeof(struct ata_LegacyBus)); - h = 1; - } - else - { - IOBase = (IPTR)NULL; - } - } - } - - if (x == 0) - { - bug("[ATA ] ata_PCIEnumerator_h: Found IDE device %04x:%04x\n", VendorID, ProductID); - } + Remove((struct Node *)_legacyBus); + IOBase = _legacyBus->atalb_IOBase; + IOAlt = _legacyBus->atalb_IOAlt; + INTLine = _legacyBus->atalb_INTLine; + FreeMem(_legacyBus, sizeof(struct ata_LegacyBus)); + isLegacy = TRUE; + IOSize = RANGESIZE0; + AltSize = RANGESIZE1; + } + else + { + bug("[ATA ] ata_PCIEnumerator_h: Ran out of legacy buses\n"); + IOBase = 0; + } - if (IOBase != (IPTR)NULL) + if (IOBase != (IPTR)NULL && IOSize == RANGESIZE0 + && AltSize == RANGESIZE1) { struct ata_ProbedBus *probedbus; D(bug("[ATA ] ata_PCIEnumerator_h: Adding Bus %d - IRQ %d, IO: %x:%x, DMA: %x\n", x, INTLine, IOBase, IOAlt, DMABase)); @@ -436,31 +416,24 @@ AROS_UFH3(void, ata_PCIEnumerator_h, probedbus->atapb_IOBase = IOBase; probedbus->atapb_IOAlt = IOAlt; probedbus->atapb_INTLine = INTLine; - probedbus->atapb_DMABase = DMABase; - probedbus->atapb_x = x; + if (DMABase != 0) + probedbus->atapb_DMABase = DMABase + (x << 3); probedbus->atapb_a = a; + probedbus->atapb_Has80Wire = + (ATAIOConfig & (0x30 << (x << 1))) || SubClass != 0x1; - if (h == 0) - probedbus->atapb_Node.ln_Pri = ATABUSNODEPRI_PROBED - (a->ATABase->ata__buscount++); - else + if (isLegacy) { D(bug("[ATA ] ata_PCIEnumerator_h: Device using Legacy-Bus IOPorts\n")); probedbus->atapb_Node.ln_Pri = ATABUSNODEPRI_PROBEDLEGACY - (a->ATABase->ata__buscount++); } + else + probedbus->atapb_Node.ln_Pri = ATABUSNODEPRI_PROBED - (a->ATABase->ata__buscount++); Enqueue((struct List *)&a->ATABase->ata__probedbuses, (struct Node *)probedbus); _usablebus = TRUE; } } - else - { - D(bug("[ATA ] ata_PCIEnumerator_h: Device uses UNAVAILABLE Legacy-Bus IOPort\n")); - if (IOBaseOrig != (IPTR)NULL) - { - D(bug("[ATA ] ata_PCIEnumerator_h: Legacy-Bus IOPort %x requested\n", IOBaseOrig)); - } - /* Disable Bus? */ - } } if (_usablebus) @@ -468,7 +441,7 @@ AROS_UFH3(void, ata_PCIEnumerator_h, struct TagItem attrs[] = { { aHidd_PCIDevice_isIO, TRUE }, - { aHidd_PCIDevice_isMaster, TRUE }, + { aHidd_PCIDevice_isMaster, DMABase != 0 }, { TAG_DONE, 0UL } }; OOP_SetAttrs(Device, attrs); @@ -494,7 +467,6 @@ void ata_Scan(struct ataBase *base) EnumeratorArgs Args= { base, - 0, 0 }; @@ -513,18 +485,9 @@ void ata_Scan(struct ataBase *base) struct TagItem Requirements[] = { {tHidd_PCI_Class, 0x01}, - {tHidd_PCI_SubClass, 0x01}, {TAG_DONE, 0x00} }; - /* - * Do not chech the subclass if the proper kernel option was given. It may - * It will let AROS use SATA controllers on some architectures, like eg. the - * Intel ICH8. - */ - if (base->ata_NoSubclass) - Requirements[1].ti_Tag = TAG_IGNORE; - struct pHidd_PCI_EnumDevices enummsg = { mID: OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_EnumDevices), callback: &FindHook, @@ -533,29 +496,6 @@ void ata_Scan(struct ataBase *base) OOP_DoMethod(pci, (OOP_Msg)msg); - if (!base->ata_NoSubclass) - { - /* - * The SiL3114 chip yields Class 0x01 and SubClass 0x80. Therefore it will not be found - * with the enumeration above. Do an explicit search now since ata.device may handle it - * in legacy mode without any issues. - * - * Note: This chip is used on Sam440 board. - */ - Requirements[0].ti_Tag = tHidd_PCI_VendorID; - Requirements[0].ti_Data = 0x1095; - Requirements[1].ti_Tag = tHidd_PCI_ProductID; - Requirements[1].ti_Data = 0x3114; - - OOP_DoMethod(pci, (OOP_Msg)msg); - - Requirements[0].ti_Tag = tHidd_PCI_VendorID; - Requirements[0].ti_Data = 0x1095; - Requirements[1].ti_Tag = tHidd_PCI_ProductID; - Requirements[1].ti_Data = 0x3512; - - OOP_DoMethod(pci, (OOP_Msg)msg); - } OOP_DisposeObject(pci); } } @@ -571,9 +511,11 @@ void ata_Scan(struct ataBase *base) probedbus->atapb_IOAlt = legacybus->atalb_IOAlt; probedbus->atapb_INTLine = legacybus->atalb_INTLine; probedbus->atapb_DMABase = (IPTR)NULL; - probedbus->atapb_x = legacybus->atalb_BusID; + probedbus->atapb_Has80Wire = FALSE; probedbus->atapb_a = &Args; probedbus->atapb_Node.ln_Pri = ATABUSNODEPRI_LEGACY - (base->ata__buscount++); + D(bug("[ATA--] ata_Scan: Adding Legacy Bus - IO: %x:%x\n", + probedbus->atapb_IOBase, probedbus->atapb_IOAlt)); Enqueue((struct List *)&base->ata__probedbuses, (struct Node *)&probedbus->atapb_Node); } } @@ -589,7 +531,7 @@ void ata_Scan(struct ataBase *base) probedbus->atapb_IOAlt, probedbus->atapb_INTLine, probedbus->atapb_DMABase, - probedbus->atapb_x, + probedbus->atapb_Has80Wire, probedbus->atapb_a); FreeMem(probedbus, sizeof(struct ata_ProbedBus)); @@ -602,10 +544,10 @@ void ata_Scan(struct ataBase *base) ata_InitBusTask((struct ata_Bus*)node, &ssem); } - D(bug("[ATA--] ata_Scan: Waiting for Buses to finish Initialising\n")); /* * wait for all buses to complete their init */ + D(bug("[ATA--] ata_Scan: Waiting for Buses to finish Initialising\n")); ObtainSemaphore(&ssem); /* @@ -646,7 +588,7 @@ static int ata_init(LIBBASETYPEPTR LIBBASE) { if ((_legacybus = AllocMem(sizeof(struct ata_LegacyBus), MEMF_CLEAR | MEMF_PUBLIC)) != NULL) { - D(bug("[ATA--] ata_init: Prepair Legacy-Bus %d:%d entry [IOPorts %x:%x IRQ %d]\n", LegacyBuses[i].lb_ControllerID, LegacyBuses[i].lb_Bus, LegacyBuses[i].lb_Port, LegacyBuses[i].lb_Alt, LegacyBuses[i].lb_IRQ)); + D(bug("[ATA--] ata_init: Prepare Legacy Bus %d:%d entry [IOPorts %x:%x IRQ %d]\n", LegacyBuses[i].lb_ControllerID, LegacyBuses[i].lb_Bus, LegacyBuses[i].lb_Port, LegacyBuses[i].lb_Alt, LegacyBuses[i].lb_IRQ)); _legacybus->atalb_IOBase = (IPTR)LegacyBuses[i].lb_Port; _legacybus->atalb_IOAlt = (IPTR)LegacyBuses[i].lb_Alt; @@ -662,7 +604,6 @@ static int ata_init(LIBBASETYPEPTR LIBBASE) LIBBASE->ata_32bit = FALSE; LIBBASE->ata_NoMulti = FALSE; LIBBASE->ata_NoDMA = FALSE; - LIBBASE->ata_NoSubclass = FALSE; /* * start initialization: @@ -707,11 +648,6 @@ static int ata_init(LIBBASETYPEPTR LIBBASE) D(bug("[ATA ] ata_init: Disabled DMA transfers\n")); LIBBASE->ata_NoDMA = TRUE; } - if (strstr(node->ln_Name, "nosubclass")) - { - D(bug("[ATA ] ata_init: Disabling Subclass check during PCI scan\n")); - LIBBASE->ata_NoSubclass = TRUE; - } } } } diff --git a/arch/common/ata.device/dma_generic.c b/arch/common/ata.device/dma_generic.c index 38940c12f..535a7ebda 100644 --- a/arch/common/ata.device/dma_generic.c +++ b/arch/common/ata.device/dma_generic.c @@ -1,12 +1,12 @@ /* - Copyright © 2004-2008, The AROS Development Team. All rights reserved + Copyright © 2004-2009, The AROS Development Team. All rights reserved $Id$ Desc: Lang: English */ /* - * CHANGELOG: + * PARTIAL CHANGELOG: * DATE NAME ENTRY * ---------- ------------------ ------------------------------------------------------------------- * 2008-01-25 T. Wiszkowski Rebuilt, rearranged and partially fixed 60% of the code here @@ -141,8 +141,7 @@ BOOL dma_SetupPRDSize(struct ata_Unit *unit, APTR buffer, ULONG size, BOOL read) CacheClearE(unit->au_Bus->ab_PRD, items * sizeof(struct PRDEntry), CACRF_ClearD); ata_outl((ULONG)unit->au_Bus->ab_PRD, dma_PRD, unit->au_DMAPort); - ata_out(ata_in(dma_Status, unit->au_DMAPort) | DMAF_Error | DMAF_Interrupt, dma_Status, unit->au_DMAPort); - + if (read) ata_out(DMA_WRITE, dma_Command, unit->au_DMAPort); /* inverse logic */ else @@ -170,21 +169,12 @@ VOID dma_Cleanup(APTR addr, ULONG len, BOOL read) VOID dma_StartDMA(struct ata_Unit *unit) { D(bug("[ATA%02ld] dma_StartDMA()\n", unit->au_UnitNum)); - ata_in(dma_Command, unit->au_DMAPort); - ata_in(dma_Status, unit->au_DMAPort); ata_out(ata_in(dma_Command, unit->au_DMAPort) | DMA_START, dma_Command, unit->au_DMAPort); - ata_in(dma_Command, unit->au_DMAPort); - ata_in(dma_Status, unit->au_DMAPort); } VOID dma_StopDMA(struct ata_Unit *unit) { D(bug("[ATA%02ld] dma_StopDMA()\n", unit->au_UnitNum)); - ata_in(dma_Command, unit->au_DMAPort); - ata_in(dma_Status, unit->au_DMAPort); ata_out(ata_in(dma_Command, unit->au_DMAPort) & ~DMA_START, dma_Command, unit->au_DMAPort); - ata_in(dma_Command, unit->au_DMAPort); - ata_in(dma_Status, unit->au_DMAPort); - ata_out(ata_in(dma_Status, unit->au_DMAPort) | DMAF_Error | DMAF_Interrupt, dma_Status, unit->au_DMAPort); } diff --git a/arch/common/ata.device/lowlevel.c b/arch/common/ata.device/lowlevel.c index 2e87e376a..44154400c 100644 --- a/arch/common/ata.device/lowlevel.c +++ b/arch/common/ata.device/lowlevel.c @@ -7,7 +7,7 @@ */ /* - * CHANGELOG: + * PARTIAL CHANGELOG: * DATE NAME ENTRY * ---------- ------------------ ------------------------------------------------------------------- * 2006-12-20 T. Wiszkowski Updated ATA Packet Interface to handle ATAPI/SCSI Commands @@ -76,8 +76,6 @@ #include #include -#include - #include #include @@ -268,16 +266,9 @@ UBYTE ata_ReadStatus(struct ata_Bus *bus) return ata_in(ata_Status, bus->ab_Port); } -/* - * enable / disable IRQ; this manages interrupt requests more effectively in case of legacy emulation - * as little code as there can be. and keep it that way. - */ -void ata_EnableIRQ(struct ata_Bus *bus, BOOL enable) +UBYTE ata_ReadAltStatus(struct ata_Bus *bus) { - enable &= (bus->ab_Dev[0] > DEV_UNKNOWN) || (bus->ab_Dev[1] > DEV_UNKNOWN); - bug("[ATA ] IRQ: Setting IRQ flag for bus %ld to %s\n", bus->ab_BusNum, enable ? "ENABLED" : "DISABLED"); - bus->ab_IRQ = enable; - ata_out(enable ? 0x0 : 0x02, ata_AltControl, bus->ab_Alt); + return ata_in(ata_AltStatus, bus->ab_Alt); } /* @@ -292,20 +283,30 @@ void ata_IRQSignalTask(struct ata_Bus *bus) void ata_HandleIRQ(struct ata_Bus *bus) { - struct ata_Unit *u = ata_GetSelectedUnit(bus); + struct ata_Unit *unit = ata_GetSelectedUnit(bus); UBYTE status = ata_ReadStatus(bus); + /* * don't waste your time on checking other devices. * pass irq ONLY if task is expecting one; */ - - if ((u != NULL) && (0 != bus->ab_HandleIRQ)) + if ((unit != NULL) && (0 != bus->ab_HandleIRQ) + && ((status & ATAF_BUSY) == 0)) { /* * ok, we have a routine to handle any form of transmission etc. */ DIRQ(bug("[ATA ] IRQ: Calling dedicated handler... \n")); - bus->ab_HandleIRQ(u, status); + bus->ab_HandleIRQ(unit, status); + + /* + * Acknowledge DMA interrupt bit (some controllers require this for + * all interrupt types) + */ + if (unit->au_DMAPort != 0) + ata_out(ata_in(dma_Status, unit->au_DMAPort) | + DMAF_Error | DMAF_Interrupt, dma_Status, unit->au_DMAPort); + return; } @@ -313,7 +314,7 @@ void ata_HandleIRQ(struct ata_Bus *bus) /* * if we got *here* then device is most likely not expected to have an irq. */ - bug("[ATA%02ld] IRQ: Checking busy flag: ", u->au_UnitNum); + bug("[ATA%02ld] IRQ: Checking busy flag: ", unit->au_UnitNum); if (0 == (ATAF_BUSY & status)) { @@ -429,6 +430,7 @@ void ata_IRQPIOReadAtapi(struct ata_Unit *unit, UBYTE status) { ULONG port = unit->au_Bus->ab_Port; ULONG size = 0; + LONG remainder = 0; UBYTE reason = ata_in(atapi_Reason, port); DIRQ(bug("[DSCSI] Current status: %ld during READ\n", reason)); @@ -436,7 +438,10 @@ void ata_IRQPIOReadAtapi(struct ata_Unit *unit, UBYTE status) if (0 == (status & (ATAF_BUSY | ATAF_DATAREQ))) ata_IRQNoData(unit, status); if (status & ATAF_ERROR) + { ata_IRQNoData(unit, status); + return; + } /* anything for us please? */ if (ATAPIF_READ != (reason & ATAPIF_MASK)) @@ -448,6 +453,7 @@ void ata_IRQPIOReadAtapi(struct ata_Unit *unit, UBYTE status) if (size > unit->au_cmd_total) { bug("[ATAPI] IRQ: CRITICAL! MORE DATA OFFERED THAN STORAGE CAN TAKE: %ld bytes vs %ld bytes left!\n", size, unit->au_cmd_total); + remainder = size - unit->au_cmd_total; size = unit->au_cmd_total; } @@ -457,8 +463,11 @@ void ata_IRQPIOReadAtapi(struct ata_Unit *unit, UBYTE status) DIRQ(bug("[ATAPI] IRQ: %lu bytes read.\n", size)); + for (; remainder > 0; remainder -= 2) + unit->au_ins(&size, port, 2); + if (unit->au_cmd_total == 0) - ata_IRQNoData(unit, status); + ata_IRQSetHandler(unit, &ata_IRQNoData, NULL, 0, 0); } void ata_IRQPIOWriteAtapi(struct ata_Unit *unit, UBYTE status) @@ -472,10 +481,13 @@ void ata_IRQPIOWriteAtapi(struct ata_Unit *unit, UBYTE status) if (0 == (status & (ATAF_BUSY | ATAF_DATAREQ))) ata_IRQNoData(unit, status); if (status & ATAF_ERROR) + { ata_IRQNoData(unit, status); + return; + } /* anything for us please? */ - if (ATAPIF_READ != (reason & ATAPIF_MASK)) + if (ATAPIF_WRITE != (reason & ATAPIF_MASK)) return; size = ata_in(atapi_ByteCntH, port) << 8 | ata_in(atapi_ByteCntL, port); @@ -494,7 +506,7 @@ void ata_IRQPIOWriteAtapi(struct ata_Unit *unit, UBYTE status) DIRQ(bug("[ATAPI] IRQ: %lu bytes written.\n", size)); if (unit->au_cmd_total == 0) - ata_IRQNoData(unit, status); + ata_IRQSetHandler(unit, &ata_IRQNoData, NULL, 0, 0); } /* @@ -508,12 +520,6 @@ BOOL ata_WaitBusyTO(struct ata_Unit *unit, UWORD tout, BOOL irq, UBYTE *stout) ULONG step = 0; BOOL res = TRUE; - if (irq && !unit->au_Bus->ab_IRQ) - { - bug("[ATA ] Requested IRQ wait, but IRQ is not enabled\n"); - } - - irq &= unit->au_Bus->ab_IRQ; sigs |= (irq ? (1 << unit->au_Bus->ab_SleepySignal) : 0); /* @@ -522,7 +528,7 @@ BOOL ata_WaitBusyTO(struct ata_Unit *unit, UWORD tout, BOOL irq, UBYTE *stout) SetSignal(0, sigs); /* - * set up bus timeout and irq + * set up bus timeout */ Disable(); unit->au_Bus->ab_Timeout = tout; @@ -537,7 +543,6 @@ BOOL ata_WaitBusyTO(struct ata_Unit *unit, UWORD tout, BOOL irq, UBYTE *stout) do { - /* * delay the check - this was found needed for some hardware */ @@ -628,6 +633,11 @@ BOOL ata_WaitBusyTO(struct ata_Unit *unit, UWORD tout, BOOL irq, UBYTE *stout) Enable(); /* + * clear any interrupt (may be neccessary if we were polling, for example) + */ + ata_in(ata_Status, unit->au_Bus->ab_Port); + + /* * release old junk */ SetSignal(0, sigs); @@ -641,20 +651,6 @@ BOOL ata_WaitBusyTO(struct ata_Unit *unit, UWORD tout, BOOL irq, UBYTE *stout) } /* - * just wait for timeout - */ -void ata_Wait(struct ata_Unit *unit, UWORD tout) -{ - SetSignal(0, SIGBREAKF_CTRL_C); - - Disable(); - unit->au_Bus->ab_Timeout = tout; - Enable(); - - Wait(SIGBREAKF_CTRL_C); -} - -/* * Procedure for sending ATA command blocks * it appears LARGE but there's a lot of COMMENTS here :) * handles *all* ata commands (no data, pio and dma) @@ -794,7 +790,7 @@ static ULONG ata_exec_cmd(struct ata_Unit* au, ata_CommandBlock *block) * block upon request. */ if (block->method == CM_PIOWrite) { - if (FALSE == ata_WaitBusyTO(au, 300, FALSE, &status)) { + if (FALSE == ata_WaitBusyTO(au, 30, FALSE, &status)) { D(bug("[ATA%02ld] ata_exec_cmd: PIOWrite - no response from device\n", au->au_UnitNum)); return IOERR_UNITBUSY; } @@ -812,7 +808,7 @@ static ULONG ata_exec_cmd(struct ata_Unit* au, ata_CommandBlock *block) /* * wait for drive to complete what it has to do */ - if (FALSE == ata_WaitBusyTO(au, 3, TRUE, NULL)) + if (FALSE == ata_WaitBusyTO(au, 30, TRUE, NULL)) { bug("[ATA%02ld] ata_exec_cmd: Device is late - no response\n", au->au_UnitNum); err = IOERR_UNITBUSY; @@ -883,19 +879,19 @@ int atapi_SendPacket(struct ata_Unit *unit, APTR packet, APTR data, LONG datalen ++l; } - D({ - bug("[ATA%02lx] Sending %s ATA packet: ", unit->au_UnitNum, (*dma) ? "DMA" : "PIO"); - l=0; - while (l<=t) - { + DATAPI({ + bug("[ATA%02lx] Sending %s ATA packet: ", unit->au_UnitNum, (*dma) ? "DMA" : "PIO"); + l=0; + while (l<=t) + { bug("%02lx ", ((UBYTE*)cmd)[l]); ++l; - } - bug("\n"); + } + bug("\n"); - if (datalen & 1) + if (datalen & 1) bug("[ATAPI] ERROR: DATA LENGTH NOT EVEN! Rounding Up! (%ld bytes requested)\n", datalen); - }); + }); datalen = (datalen+1)&~1; @@ -908,7 +904,9 @@ int atapi_SendPacket(struct ata_Unit *unit, APTR packet, APTR data, LONG datalen /* * tell device whether we want to read or write and if we want a dma transfer */ - ata_out(((*dma) ? 1 : 0) | ((write) ? 4 : 0), atapi_Features, port); + ata_out(((*dma) ? 1 : 0) | + (((unit->au_Drive->id_DMADir & 0x8000) && !write) ? 4 : 0), + atapi_Features, port); ata_out((datalen & 0xff), atapi_ByteCntL, port); ata_out((datalen >> 8) & 0xff, atapi_ByteCntH, port); @@ -921,12 +919,12 @@ int atapi_SendPacket(struct ata_Unit *unit, APTR packet, APTR data, LONG datalen ata_WaitNano(400); //ata_WaitTO(unit->au_Bus->ab_Timer, 0, 1, 0); - ata_WaitBusyTO(unit, 30, FALSE, NULL); + ata_WaitBusyTO(unit, 30, (unit->au_Drive->id_General & 0x60) == 0x20, NULL); if (0 == (ata_ReadStatus(unit->au_Bus) & ATAF_DATAREQ)) return HFERR_BadStatus; /* - * setup appropriate hooks. not really the best way. + * setup appropriate hooks */ if (datalen == 0) ata_IRQSetHandler(unit, &ata_IRQNoData, 0, 0, 0); @@ -937,39 +935,24 @@ int atapi_SendPacket(struct ata_Unit *unit, APTR packet, APTR data, LONG datalen else ata_IRQSetHandler(unit, &ata_IRQPIOReadAtapi, data, 0, datalen); - DATAPI(bug("[ATAPI] Sending packet\n")); - unit->au_outs(cmd, unit->au_Bus->ab_Port, 12); - ata_WaitNano(400); - //ata_WaitTO(unit->au_Bus->ab_Timer, 0, 1, 0); /* give drive time to think about what we just said, then move on */ - /* how much time could it take for drive to raise DMARQ signal?? */ - - DATAPI(bug("[ATAPI] Status after packet: %lx\n", ata_ReadStatus(unit->au_Bus))); - if (*dma) { - DATAPI(bug("[ATAPI] Preparing for DMA\n")); - while (0 == ((t = ata_ReadStatus(unit->au_Bus)) & (ATAF_BUSY | ATAF_DATAREQ))) - { - if (t & ATAF_ERROR) - { - err = HFERR_DMA; - break; - } - DATAPI(bug("[ATAPI] status %02lx\n", ata_ReadStatus(unit->au_Bus))); - ata_WaitNano(400); - //ata_WaitTO(unit->au_Bus->ab_Timer, 0, 1, 0); - } - - DATAPI(bug("[ATAPI] status %02lx\n", ata_ReadStatus(unit->au_Bus))); - - if (0 == err) - { - DATAPI(bug("[ATAPI] Starting DMA\n")); - dma_StartDMA(unit); - } + DATAPI(bug("[ATAPI] Starting DMA\n")); + dma_StartDMA(unit); } - if ((0 == err) && (ata_WaitBusyTO(unit, 3, TRUE, NULL) == FALSE)) + DATAPI(bug("[ATAPI] Sending packet\n")); + unit->au_outs(cmd, unit->au_Bus->ab_Port, 12); + ata_WaitNano(400); + DATAPI(bug("[ATAPI] Status after packet: %lx\n", + ata_ReadAltStatus(unit->au_Bus))); + + /* + * Wait for command to complete. Note that two interrupts will occur + * before we wake up if this is a PIO data transfer + */ + if (ata_WaitTO(unit->au_Bus->ab_Timer, 30, 0, + 1 << unit->au_Bus->ab_SleepySignal) == 0) { DATAPI(bug("[DSCSI] Command timed out.\n")); err = IOERR_UNITBUSY; @@ -983,7 +966,7 @@ int atapi_SendPacket(struct ata_Unit *unit, APTR packet, APTR data, LONG datalen dma_Cleanup(data, datalen, !write); } - D(bug("[ATAPI] IO error code %ld\n", err)); + DATAPI(bug("[ATAPI] IO error code %ld\n", err)); return err; } @@ -1097,7 +1080,6 @@ BOOL ata_init_unit(struct ata_Bus *bus, UBYTE u) unit->au_outs = ata_outsw; } unit->au_SectorShift= 9; /* this really has to be set here. */ - unit->au_Flags = 0; NEWLIST(&unit->au_SoftList); @@ -1123,7 +1105,7 @@ BOOL ata_setup_unit(struct ata_Bus *bus, UBYTE u) * this stuff always goes along the same way * WARNING: NO INTERRUPTS AT THIS POINT! */ - DINIT(bug("[ATA ] ata_setup_unit(%ld)\n", u)); + DINIT(bug("[ATA ] ata_setup_unit(%ld,%ld)\n", bus->ab_BusNum, u)); unit = bus->ab_Units[u]; if (NULL == unit) @@ -1131,6 +1113,12 @@ BOOL ata_setup_unit(struct ata_Bus *bus, UBYTE u) ata_SelectUnit(unit); + if (unit->au_DMAPort != 0 + && (ata_in(dma_Status, unit->au_DMAPort) & 0x80) != 0) + bug("[ATA%02ld] ata_setup_unit: WARNING: Controller only supports " + "DMA on one bus at a time. DMAStatus=%lx\n", unit->au_UnitNum, + ata_in(dma_Status, unit->au_DMAPort)); + if (FALSE == ata_WaitBusyTO(unit, 1, FALSE, NULL)) { DINIT(bug("[ATA%02ld] ata_setup_unit: ERROR: Drive not ready for use. Keeping functions stubbed\n", unit->au_UnitNum)); @@ -1154,7 +1142,6 @@ BOOL ata_setup_unit(struct ata_Bus *bus, UBYTE u) unit->au_Identify = ata_Identify; break; - default: DINIT(bug("[ATA%02ld] ata_setup_unit: Unsupported device %lx. All functions will remain stubbed.\n", unit->au_UnitNum, bus->ab_Dev[u])); FreePooled(bus->ab_Base->ata_MemPool, unit->au_Drive, sizeof(struct DriveIdent)); @@ -1162,8 +1149,9 @@ BOOL ata_setup_unit(struct ata_Bus *bus, UBYTE u) return FALSE; } - bug("[ATA ] ata_setup_unit: Enabling Bus IRQs\n"); - ata_EnableIRQ(bus, TRUE); + D(bug("[ATA ] ata_setup_unit: Enabling IRQs\n")); + ata_out(0x0, ata_AltControl, bus->ab_Alt); + /* * now make unit self diagnose */ @@ -1177,8 +1165,6 @@ BOOL ata_setup_unit(struct ata_Bus *bus, UBYTE u) return TRUE; } - - /* * ata[pi] identify */ @@ -1188,7 +1174,7 @@ static void common_SetXferMode(struct ata_Unit* unit, ata_XferMode mode) BOOL dma=FALSE; ata_CommandBlock acb = { - 0xef, + ATA_SET_FEATURES, 0x03, 0x01, 0x00, @@ -1202,7 +1188,7 @@ static void common_SetXferMode(struct ata_Unit* unit, ata_XferMode mode) }; DINIT(bug("[ATA%02ld] common_SetXferMode: Trying to set mode %d\n", unit->au_UnitNum, mode)); - if ((unit->au_DMAPort == 0) && (mode > AB_XFER_PIO7)) + if ((unit->au_DMAPort == 0) && (mode >= AB_XFER_MDMA0)) { DINIT(bug("[ATA%02ld] common_SetXferMode: This controller does not own DMA port! Will set best PIO\n", unit->au_UnitNum)); common_SetBestXferMode(unit); @@ -1214,13 +1200,14 @@ static void common_SetXferMode(struct ata_Unit* unit, ata_XferMode mode) */ if (0 == (unit->au_XferModes & AF_XFER_PACKET)) { - if ((mode >= AB_XFER_PIO0) & (mode <= AB_XFER_PIO7)) + if ((mode >= AB_XFER_PIO0) && (mode <= AB_XFER_PIO4)) { if ((!unit->au_Bus->ab_Base->ata_NoMulti) && (unit->au_XferModes & AF_XFER_RWMULTI)) { + ata_IRQSetHandler(unit, ata_IRQNoData, NULL, 0, 0); ata_out(unit->au_Drive->id_RWMultipleSize & 0xFF, ata_Count, unit->au_Bus->ab_Port); ata_out(ATA_SET_MULTIPLE, ata_Command, unit->au_Bus->ab_Port); - ata_WaitBusyTO(unit, -1, FALSE, NULL); + ata_WaitBusyTO(unit, -1, TRUE, NULL); unit->au_Read32 = ata_ReadMultiple32; unit->au_Write32 = ata_WriteMultiple32; @@ -1241,7 +1228,7 @@ static void common_SetXferMode(struct ata_Unit* unit, ata_XferMode mode) } } } - else if ((mode >= AB_XFER_MDMA0) & (mode <= AB_XFER_MDMA7)) + else if ((mode >= AB_XFER_MDMA0) && (mode <= AB_XFER_MDMA2)) { unit->au_Read32 = ata_ReadDMA32; unit->au_Write32 = ata_WriteDMA32; @@ -1251,7 +1238,7 @@ static void common_SetXferMode(struct ata_Unit* unit, ata_XferMode mode) unit->au_Write64 = ata_WriteDMA64; } } - else if ((mode >= AB_XFER_UDMA0) & (mode <= AB_XFER_UDMA7)) + else if ((mode >= AB_XFER_UDMA0) && (mode <= AB_XFER_UDMA6)) { unit->au_Read32 = ata_ReadDMA32; unit->au_Write32 = ata_WriteDMA32; @@ -1273,16 +1260,16 @@ static void common_SetXferMode(struct ata_Unit* unit, ata_XferMode mode) } } - if ((mode >= AB_XFER_PIO0) & (mode <= AB_XFER_PIO7)) + if ((mode >= AB_XFER_PIO0) && (mode <= AB_XFER_PIO4)) { type = 8 + (mode - AB_XFER_PIO0); } - else if ((mode >= AB_XFER_MDMA0) & (mode <= AB_XFER_MDMA7)) + else if ((mode >= AB_XFER_MDMA0) && (mode <= AB_XFER_MDMA2)) { type = 32 + (mode - AB_XFER_MDMA0); dma=TRUE; } - else if ((mode >= AB_XFER_UDMA0) & (mode <= AB_XFER_UDMA7)) + else if ((mode >= AB_XFER_UDMA0) && (mode <= AB_XFER_UDMA6)) { type = 64 + (mode - AB_XFER_UDMA0); dma=TRUE; @@ -1335,7 +1322,7 @@ static void common_SetXferMode(struct ata_Unit* unit, ata_XferMode mode) static void common_SetBestXferMode(struct ata_Unit* unit) { int iter; - int max = AB_XFER_UDMA7; + int max = AB_XFER_UDMA6; if (unit->au_DMAPort == 0) { @@ -1344,7 +1331,14 @@ static void common_SetBestXferMode(struct ata_Unit* unit) * otherwise this and above function will fall into infinite loop */ DINIT(bug("[ATA%02ld] common_SetBestXferMode: This controller does not own DMA port\n", unit->au_UnitNum)); - max = AB_XFER_PIO7; + max = AB_XFER_PIO4; + } + else if (!(unit->au_Flags & AF_80Wire)) + { + bug("[ATA%02ld] common_SetBestXferMode: " + "An 80-wire cable has not been detected for this drive. " + "Disabling modes above UDMA2.\n", unit->au_UnitNum); + max = AB_XFER_UDMA2; } for (iter=max; iter>=AB_XFER_PIO0; --iter) @@ -1394,31 +1388,34 @@ void common_DetectXferModes(struct ata_Unit* unit) unit->au_XferModes |= AF_XFER_RWMULTI; } - if (unit->au_Drive->id_PIOSupport & 0xff) + DINIT(bug("[ATA%02ld] common_DetectXferModes: - PIO0 PIO1 PIO2 ", + unit->au_UnitNum)); + unit->au_XferModes |= AF_XFER_PIO(0) | AF_XFER_PIO(1) | AF_XFER_PIO(2); + if (unit->au_Drive->id_ConfigAvailable & (1 << 1)) { - DINIT(bug("[ATA%02ld] common_DetectXferModes: - ", unit->au_UnitNum)); - for (iter=0; iter<8; iter++) + for (iter = 0; iter < 2; iter++) { - if (unit->au_Drive->id_MWDMASupport & (1 << iter)) + if (unit->au_Drive->id_PIOSupport & (1 << iter)) { - DINIT(bug("PIO%ld ", iter)); - unit->au_XferModes |= AF_XFER_PIO(iter);; + DINIT(bug("PIO%ld ", 3 + iter)); + unit->au_XferModes |= AF_XFER_PIO(3 + iter); } } DINIT(bug("\n")); } - if (unit->au_Drive->id_Capabilities & (1<<8)) + if ((unit->au_Drive->id_ConfigAvailable & (1 << 1)) && + (unit->au_Drive->id_Capabilities & (1<<8))) { DINIT(bug("[ATA%02ld] common_DetectXferModes: DMA:\n", unit->au_UnitNum)); if (unit->au_Drive->id_MWDMASupport & 0xff) { DINIT(bug("[ATA%02ld] common_DetectXferModes: - ", unit->au_UnitNum)); - for (iter=0; iter<8; iter++) + for (iter = 0; iter < 3; iter++) { if (unit->au_Drive->id_MWDMASupport & (1 << iter)) { - unit->au_XferModes |= AF_XFER_MDMA(iter);; + unit->au_XferModes |= AF_XFER_MDMA(iter); if (unit->au_Drive->id_MWDMASupport & (256 << iter)) { DINIT(bug("[MDMA%ld] ", iter)); @@ -1435,11 +1432,11 @@ void common_DetectXferModes(struct ata_Unit* unit) if (unit->au_Drive->id_UDMASupport & 0xff) { DINIT(bug("[ATA%02ld] common_DetectXferModes: - ", unit->au_UnitNum)); - for (iter=0; iter<8; iter++) + for (iter = 0; iter < 7; iter++) { if (unit->au_Drive->id_UDMASupport & (1 << iter)) { - unit->au_XferModes |= AF_XFER_UDMA(iter);; + unit->au_XferModes |= AF_XFER_UDMA(iter); if (unit->au_Drive->id_UDMASupport & (256 << iter)) { DINIT(bug("[UDMA%ld] ", iter)); @@ -1543,7 +1540,7 @@ ULONG atapi_Identify(struct ata_Unit* unit) unit->au_Write32 = atapi_Write; unit->au_DirectSCSI = atapi_DirectSCSI; unit->au_Eject = atapi_Eject; - unit->au_Flags = AF_DiscChanged; + unit->au_Flags |= AF_DiscChanged; unit->au_DevType = (unit->au_Drive->id_General >>8) & 0x1f; unit->au_XferModes = AF_XFER_PACKET; @@ -2311,28 +2308,34 @@ ULONG ata_ReadSignature(struct ata_Bus *bus, int unit) DINIT(bug("[ATA ] ata_ReadSignature: Subtype check returned %02lx:%02lx (%04lx)\n", tmp1, tmp2, (tmp1 << 8) | tmp2)); - switch ((tmp1 << 8) | tmp2) { case 0x0000: if (0 == (ata_ReadStatus(bus) & 0xfe)) return DEV_NONE; - ata_out(0xa0 | (unit << 4), ata_DevHead, port); ata_out(ATA_EXECUTE_DIAG, ata_Command, port); - ata_out(0xa0 | (unit << 4), ata_DevHead, port); + ata_WaitTO(bus->ab_Timer, 0, 2000, 0); while (ata_ReadStatus(bus) & ATAF_BUSY) ata_WaitNano(400); //ata_WaitTO(bus->ab_Timer, 0, 1, 0); - DINIT(bug("[ATA ] ata_ReadSignature: Further validating ATA signature: %lx & 0x7f = 1, %lx & 0x10 = unit\n", ata_in(ata_Error, port), ata_in(ata_DevHead, port))); + ata_out(0xa0 | (unit << 4), ata_DevHead, port); + do + { + ata_WaitNano(400); + //ata_WaitTO(unit->au_Bus->ab_Timer, 0, 1, 0); + } + while (0 != (ATAF_BUSY & ata_ReadStatus(bus))); + DINIT(bug("[ATA ] ata_ReadSignature: Further validating ATA signature: %lx & 0x7f = 1, %lx & 0x10 = unit\n", ata_in(ata_Error, port), ata_in(ata_DevHead, port))); - if ((1 == (0x7f & ata_in(ata_Error, port))) && - (unit == ((ata_in(ata_DevHead, port) >> 4) & 1))) + if ((ata_in(ata_Error, port) & 0x7f) == 1) { DINIT(bug("[ATA ] ata_ReadSignature: Found *valid* signature for ATA device\n")); return DEV_ATA; } + bug("[ATA ] ata_ReadSignature: Found signature for ATA " + "device, but further validation failed\n"); return DEV_NONE; case 0x14eb: @@ -2443,20 +2446,6 @@ void ata_ResetBus(struct ata_Bus *bus) bus->ab_Dev[1] = ata_ReadSignature(bus, 1); } -/* - * -------------------------------------------------------------- - * - here ends the code that makes any sense. rest to be removed - - * -------------------------------------------------------------- - */ - - -/* - Device scan routines - TO BE REPLACED - Note: This code checks if a drive "shadows" non existent drive's registers -*/ -/* - * same here - */ void ata_InitBus(struct ata_Bus *bus) { ULONG port = bus->ab_Port; @@ -2467,17 +2456,15 @@ void ata_InitBus(struct ata_Bus *bus) */ bus->ab_Timer = ata_OpenTimer(); - bug("[ATA ] ata_InitBus(%d)\n", bus->ab_BusNum); + D(bug("[ATA ] ata_InitBus(%d)\n", bus->ab_BusNum)); bus->ab_Dev[0] = DEV_NONE; bus->ab_Dev[1] = DEV_NONE; - /* Disable IDE IRQ */ - ata_EnableIRQ(bus, FALSE); - - /* Select device 0 */ + /* Select device 0 and disable IRQs */ ata_out(0xa0, ata_DevHead, port); ata_WaitTO(bus->ab_Timer, 0, 100, 0); + ata_out(0x2, ata_AltControl, bus->ab_Alt); /* Write some pattern to registers */ ata_out(0x55, ata_Count, port); @@ -2494,9 +2481,10 @@ void ata_InitBus(struct ata_Bus *bus) bus->ab_Dev[0] = DEV_UNKNOWN; D(bug("[ATA%02ld] ata_InitBus: Device type = %x\n", (bus->ab_BusNum << 1 ) + 0, bus->ab_Dev[0])); - /* Select device 1 */ + /* Select device 1 and disable IRQs */ ata_out(0xb0, ata_DevHead, port); ata_WaitTO(bus->ab_Timer, 0, 100, 0); + ata_out(0x2, ata_AltControl, bus->ab_Alt); /* Write some pattern to registers */ ata_out(0x55, ata_Count, port); @@ -2515,7 +2503,7 @@ void ata_InitBus(struct ata_Bus *bus) ata_ResetBus(bus); ata_CloseTimer(bus->ab_Timer); - bug("[ATA ] ata_InitBus: Finished\n"); + D(bug("[ATA ] ata_InitBus: Finished\n")); } /* diff --git a/arch/common/ata.device/timer.c b/arch/common/ata.device/timer.c index a02d461db..6817f1e8c 100644 --- a/arch/common/ata.device/timer.c +++ b/arch/common/ata.device/timer.c @@ -1,12 +1,12 @@ /* - Copyright © 2009, The AROS Development Team. All rights reserved - $Id: timer.c + Copyright © 2009, The AROS Development Team. All rights reserved + $Id$ Desc: Lang: English */ /* - * CHANGELOG: + * PARTIAL CHANGELOG: * DATE NAME ENTRY * ---------- ------------------ ------------------------------------------------------------------- * 2005-03-06 T. Wiszkowski few corrections (thanks, Georg) diff --git a/arch/common/ata.device/timer.h b/arch/common/ata.device/timer.h index b4d6a4863..9f4ed250f 100644 --- a/arch/common/ata.device/timer.h +++ b/arch/common/ata.device/timer.h @@ -1,12 +1,12 @@ /* - Copyright © 2009, The AROS Development Team. All rights reserved - $Id: aoeui + Copyright © 2009, The AROS Development Team. All rights reserved + $Id$ Desc: Lang: English */ /* - * CHANGELOG: + * PARTIAL CHANGELOG: * DATE NAME ENTRY * ---------- ------------------ ------------------------------------------------------------------- * 2005-03-05 T. Wiszkowski created file; initial benchmarked nanowait and timer-based micro/sec wait @@ -53,7 +53,7 @@ ULONG ata_WaitTO(struct IORequest* tmr, ULONG secs, ULONG micro, ULONG sigs); * result * none * note - * rounds up ns to nearest multiply of 100 + * rounds up ns to nearest multiple of 100 */ void ata_WaitNano(ULONG ns); -- 2.11.4.GIT