Index: oldkernel/linux/Documentation/README.DAC960 diff -u linux/Documentation/README.DAC960:1.1.1.1 linux/Documentation/README.DAC960:1.2 --- linux/Documentation/README.DAC960:1.1.1.1 Wed May 31 12:33:54 2000 +++ linux/Documentation/README.DAC960 Wed May 31 14:57:57 2000 @@ -1,17 +1,17 @@ Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux - Version 2.2.4 for Linux 2.2.11 - Version 2.0.4 for Linux 2.0.37 + Version 2.2.5 for Linux 2.2.14 + Version 2.0.5 for Linux 2.0.38 PRODUCTION RELEASE - 23 August 1999 + 23 January 2000 Leonard N. Zubkoff Dandelion Digital lnz@dandelion.com - Copyright 1998-1999 by Leonard N. Zubkoff + Copyright 1998-2000 by Leonard N. Zubkoff INTRODUCTION @@ -87,7 +87,9 @@ The following list comprises the supported DAC960 and DAC1100 PCI RAID Controllers as of the date of this document. It is recommended that anyone purchasing a Mylex PCI RAID Controller not in the following table contact the -author beforehand to verify that it is or will be supported. +author beforehand to verify that it is or will be supported. The eXtremeRAID +2000, eXtremeRAID 3000, and AcceleRAID 352 have an entirely new firmware +interface and are not yet supported by this driver. eXtremeRAID 1100 (DAC1164P) 3 Wide Ultra-2/LVD SCSI channels @@ -163,16 +165,16 @@ DRIVER INSTALLATION -This distribution was prepared for Linux kernel version 2.2.11 or 2.0.37. +This distribution was prepared for Linux kernel version 2.2.14 or 2.0.38. To install the DAC960 RAID driver, you may use the following commands, replacing "/usr/src" with wherever you keep your Linux kernel source tree: cd /usr/src - tar -xvzf DAC960-2.2.4.tar.gz (or DAC960-2.0.4.tar.gz) + tar -xvzf DAC960-2.2.5.tar.gz (or DAC960-2.0.5.tar.gz) mv README.DAC960 linux/Documentation mv DAC960.[ch] linux/drivers/block - patch -p0 < DAC960.patch + patch -p0 < DAC960.patch (driver 2.0.5 only) cd linux make config make depend Index: oldkernel/linux/drivers/block/DAC960.c diff -u linux/drivers/block/DAC960.c:1.1.1.1 linux/drivers/block/DAC960.c:1.2 --- linux/drivers/block/DAC960.c:1.1.1.1 Wed May 31 12:33:50 2000 +++ linux/drivers/block/DAC960.c Wed May 31 14:57:57 2000 @@ -19,8 +19,8 @@ */ -#define DAC960_DriverVersion "2.2.4" -#define DAC960_DriverDate "23 August 1999" +#define DAC960_DriverVersion "2.2.5" +#define DAC960_DriverDate "23 January 2000" #include @@ -120,7 +120,7 @@ DAC960_Announce("***** DAC960 RAID Driver Version " DAC960_DriverVersion " of " DAC960_DriverDate " *****\n", Controller); - DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff " + DAC960_Announce("Copyright 1998-2000 by Leonard N. Zubkoff " "\n", Controller); } @@ -194,6 +194,23 @@ /* + DAC960_WaitForCommand waits for a wake_up on Controller's Command Wait Queue. +*/ + +static void DAC960_WaitForCommand(DAC960_Controller_T *Controller) +{ + WaitQueue_T WaitQueueEntry = { current, NULL }; + add_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry); + current->state = TASK_UNINTERRUPTIBLE; + spin_unlock(&io_request_lock); + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry); + spin_lock_irq(&io_request_lock); +} + + +/* DAC960_QueueCommand queues Command. */ @@ -317,6 +334,62 @@ /* + DAC960_ReportErrorStatus reports Controller BIOS Messages passed through + the Error Status Register when the driver performs the BIOS handshaking. + It returns true for fatal errors and false otherwise. +*/ + +static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller, + unsigned char ErrorStatus, + unsigned char Parameter0, + unsigned char Parameter1) +{ + switch (ErrorStatus) + { + case 0x00: + DAC960_Notice("Physical Drive %d:%d Not Responding\n", + Controller, Parameter1, Parameter0); + break; + case 0x08: + if (Controller->DriveSpinUpMessageDisplayed) break; + DAC960_Notice("Spinning Up Drives\n", Controller); + Controller->DriveSpinUpMessageDisplayed = true; + break; + case 0x30: + DAC960_Notice("Configuration Checksum Error\n", Controller); + break; + case 0x60: + DAC960_Notice("Mirror Race Recovery Failed\n", Controller); + break; + case 0x70: + DAC960_Notice("Mirror Race Recovery In Progress\n", Controller); + break; + case 0x90: + DAC960_Notice("Physical Drive %d:%d COD Mismatch\n", + Controller, Parameter1, Parameter0); + break; + case 0xA0: + DAC960_Notice("Logical Drive Installation Aborted\n", Controller); + break; + case 0xB0: + DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller); + break; + case 0xD0: + DAC960_Notice("New Controller Configuration Found\n", Controller); + break; + case 0xF0: + DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller); + return true; + default: + DAC960_Error("Unknown Initialization Error %02X for Controller at\n", + Controller, ErrorStatus); + return true; + } + return false; +} + + +/* DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface. */ @@ -382,7 +455,7 @@ case DAC960_V5_Controller: while (--TimeoutCounter >= 0) { - if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress)) + if (!DAC960_V5_HardwareMailboxFullP(ControllerBaseAddress)) break; udelay(10); } @@ -474,11 +547,13 @@ unsigned char DeviceFunction = PCI_Device->devfn; unsigned char Device = DeviceFunction >> 3; unsigned char Function = DeviceFunction & 0x7; + unsigned char ErrorStatus, Parameter0, Parameter1; unsigned int IRQ_Channel = PCI_Device->irq; unsigned long BaseAddress0 = PCI_Device->base_address[0]; unsigned long BaseAddress1 = PCI_Device->base_address[1]; unsigned short SubsystemVendorID, SubsystemDeviceID; int CommandIdentifier; + void *BaseAddress; pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID, &SubsystemVendorID); pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_ID, @@ -524,24 +599,6 @@ Controller->Function = Function; sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); /* - Acquire shared access to the IRQ Channel. - */ - if (IRQ_Channel == 0) - { - DAC960_Error("IRQ Channel %d illegal for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - strcpy(Controller->FullModelName, "DAC960"); - if (request_irq(IRQ_Channel, DAC960_InterruptHandler, - SA_SHIRQ, Controller->FullModelName, Controller) < 0) - { - DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - Controller->IRQ_Channel = IRQ_Channel; - /* Map the Controller Register Window. */ if (MemoryWindowSize < PAGE_SIZE) @@ -556,34 +613,87 @@ "Controller at\n", Controller); goto Failure; } + BaseAddress = Controller->BaseAddress; switch (ControllerType) { case DAC960_V5_Controller: - DAC960_V5_DisableInterrupts(Controller->BaseAddress); + DAC960_V5_DisableInterrupts(BaseAddress); + DAC960_V5_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_V5_InitializationInProgressP(BaseAddress)) + { + if (DAC960_V5_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } if (!DAC960_EnableMemoryMailboxInterface(Controller)) { DAC960_Error("Unable to Enable Memory Mailbox Interface " "for Controller at\n", Controller); goto Failure; } - DAC960_V5_EnableInterrupts(Controller->BaseAddress); + DAC960_V5_EnableInterrupts(BaseAddress); break; case DAC960_V4_Controller: - DAC960_V4_DisableInterrupts(Controller->BaseAddress); + DAC960_V4_DisableInterrupts(BaseAddress); + DAC960_V4_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_V4_InitializationInProgressP(BaseAddress)) + { + if (DAC960_V4_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } if (!DAC960_EnableMemoryMailboxInterface(Controller)) { DAC960_Error("Unable to Enable Memory Mailbox Interface " "for Controller at\n", Controller); goto Failure; } - DAC960_V4_EnableInterrupts(Controller->BaseAddress); + DAC960_V4_EnableInterrupts(BaseAddress); break; case DAC960_V3_Controller: request_region(Controller->IO_Address, 0x80, Controller->FullModelName); - DAC960_V3_EnableInterrupts(Controller->BaseAddress); + DAC960_V3_DisableInterrupts(BaseAddress); + DAC960_V3_AcknowledgeStatus(BaseAddress); + udelay(1000); + while (DAC960_V3_InitializationInProgressP(BaseAddress)) + { + if (DAC960_V3_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + DAC960_V3_EnableInterrupts(BaseAddress); break; } + /* + Acquire shared access to the IRQ Channel. + */ + if (IRQ_Channel == 0) + { + DAC960_Error("IRQ Channel %d illegal for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + strcpy(Controller->FullModelName, "DAC960"); + if (request_irq(IRQ_Channel, DAC960_InterruptHandler, + SA_SHIRQ, Controller->FullModelName, Controller) < 0) + { + DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + Controller->IRQ_Channel = IRQ_Channel; DAC960_ActiveControllerCount++; for (CommandIdentifier = 0; CommandIdentifier < DAC960_MaxChannels; @@ -604,11 +714,11 @@ "0x%X PCI Address 0x%X\n", Controller, Bus, Device, Function, IO_Address, PCI_Address); if (Controller == NULL) break; - if (Controller->IRQ_Channel > 0) - free_irq(IRQ_Channel, Controller); if (Controller->MemoryMappedAddress != NULL) iounmap(Controller->MemoryMappedAddress); DAC960_Controllers[Controller->ControllerNumber] = NULL; + if (Controller->IRQ_Channel > 0) + free_irq(IRQ_Channel, Controller); Ignore: kfree(Controller); } @@ -1282,9 +1392,7 @@ Command = DAC960_AllocateCommand(Controller); if (Command != NULL) break; if (!WaitForCommand) return false; - spin_unlock(&io_request_lock); - sleep_on(&Controller->CommandWaitQueue); - spin_lock_irq(&io_request_lock); + DAC960_WaitForCommand(Controller); } DAC960_ClearCommand(Command); if (Request->cmd == READ) @@ -1836,6 +1944,20 @@ } else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) Controller->NeedConsistencyCheckProgress = true; + if (CommandType != DAC960_MonitoringCommand && + Controller->RebuildFlagPending) + { + DAC960_Enquiry_T *Enquiry = (DAC960_Enquiry_T *) + Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress); + Enquiry->RebuildFlag = Controller->PendingRebuildFlag; + Controller->RebuildFlagPending = false; + } + else if (CommandType == DAC960_MonitoringCommand && + NewEnquiry->RebuildFlag > DAC960_BackgroundCheckInProgress) + { + Controller->PendingRebuildFlag = NewEnquiry->RebuildFlag; + Controller->RebuildFlagPending = true; + } } else if (CommandOpcode == DAC960_PerformEventLogOperation) { @@ -2019,6 +2141,9 @@ Controller->RebuildProgress.LogicalDriveSize; unsigned int BlocksCompleted = LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_NoRebuildOrCheckInProgress && + Controller->LastRebuildStatus == DAC960_NormalCompletion) + CommandStatus = DAC960_RebuildSuccessful; switch (CommandStatus) { case DAC960_NormalCompletion: @@ -2046,13 +2171,28 @@ "Failure of Drive Being Rebuilt\n", Controller); break; case DAC960_NoRebuildOrCheckInProgress: - if (Controller->LastRebuildStatus != DAC960_NormalCompletion) - break; + break; case DAC960_RebuildSuccessful: DAC960_Progress("Rebuild Completed Successfully\n", Controller); break; + case DAC960_RebuildSuccessfullyTerminated: + DAC960_Progress("Rebuild Successfully Terminated\n", Controller); + break; } Controller->LastRebuildStatus = CommandStatus; + if (CommandType != DAC960_MonitoringCommand && + Controller->RebuildStatusPending) + { + Command->CommandStatus = Controller->PendingRebuildStatus; + Controller->RebuildStatusPending = false; + } + else if (CommandType == DAC960_MonitoringCommand && + CommandStatus != DAC960_NormalCompletion && + CommandStatus != DAC960_NoRebuildOrCheckInProgress) + { + Controller->PendingRebuildStatus = CommandStatus; + Controller->RebuildStatusPending = true; + } } else if (CommandOpcode == DAC960_RebuildStat) { @@ -2267,7 +2407,7 @@ if (CommandType == DAC960_QueuedCommand) { DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand; - KernelCommand->CommandStatus = CommandStatus; + KernelCommand->CommandStatus = Command->CommandStatus; Command->KernelCommand = NULL; if (CommandOpcode == DAC960_DCDB) Controller->DirectCommandActive[KernelCommand->DCDB->Channel] @@ -2288,9 +2428,12 @@ return; } /* - Deallocate the Command, and wake up any processes waiting on a free Command. + Deallocate the Command. */ DAC960_DeallocateCommand(Command); + /* + Wake up any processes waiting on a free Command. + */ wake_up(&Controller->CommandWaitQueue); } @@ -2696,19 +2839,14 @@ } if (CommandOpcode == DAC960_DCDB) { - while (true) - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - if (!Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID]) - Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) - Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] = true; - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (Command != NULL) break; - sleep_on(&Controller->CommandWaitQueue); - } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while (Controller->DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] || + (Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + Controller->DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = true; + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); DAC960_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, @@ -2718,14 +2856,10 @@ } else { - while (true) - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - Command = DAC960_AllocateCommand(Controller); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (Command != NULL) break; - sleep_on(&Controller->CommandWaitQueue); - } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); DAC960_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, @@ -3127,14 +3261,10 @@ DAC960_CommandMailbox_T *CommandMailbox; ProcessorFlags_T ProcessorFlags; unsigned char Channel, TargetID, LogicalDriveNumber; - while (true) - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - Command = DAC960_AllocateCommand(Controller); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (Command != NULL) break; - sleep_on(&Controller->CommandWaitQueue); - } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); Controller->UserStatusLength = 0; DAC960_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; Index: oldkernel/linux/drivers/block/DAC960.h diff -u linux/drivers/block/DAC960.h:1.1.1.1 linux/drivers/block/DAC960.h:1.2 --- linux/drivers/block/DAC960.h:1.1.1.1 Wed May 31 12:33:50 2000 +++ linux/drivers/block/DAC960.h Wed May 31 14:57:57 2000 @@ -55,17 +55,17 @@ /* - Define a 32 bit I/O Address data type. + Define a 32/64 bit I/O Address data type. */ -typedef unsigned int DAC960_IO_Address_T; +typedef unsigned long DAC960_IO_Address_T; /* - Define a 32 bit PCI Bus Address data type. + Define a 32/64 bit PCI Bus Address data type. */ -typedef unsigned int DAC960_PCI_Address_T; +typedef unsigned long DAC960_PCI_Address_T; /* @@ -196,6 +196,7 @@ #define DAC960_RebuildFailed_BadBlocksOnOther 0x0003 /* Consistency */ #define DAC960_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */ #define DAC960_RebuildSuccessful 0x0100 /* Consistency */ +#define DAC960_RebuildSuccessfullyTerminated 0x0107 /* Consistency */ #define DAC960_AddCapacityInProgress 0x0004 /* Consistency */ #define DAC960_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */ #define DAC960_Config2ChecksumError 0x0002 /* Configuration */ @@ -513,7 +514,7 @@ unsigned char SynchronousMultiplier; /* Byte 4 */ unsigned char SynchronousOffset:5; /* Byte 5 Bits 0-4 */ unsigned char :3; /* Byte 5 Bits 5-7 */ - unsigned long DiskSize __attribute__ ((packed)); /* Bytes 6-9 */ + unsigned int DiskSize __attribute__ ((packed)); /* Bytes 6-9 */ } DAC960_DeviceState_T; @@ -1212,6 +1213,7 @@ unsigned char LogicalDriveCount; unsigned char GeometryTranslationHeads; unsigned char GeometryTranslationSectors; + unsigned char PendingRebuildFlag; unsigned short ControllerQueueDepth; unsigned short DriverQueueDepth; unsigned short MaxBlocksPerCommand; @@ -1247,6 +1249,9 @@ boolean NeedRebuildProgress; boolean NeedConsistencyCheckProgress; boolean EphemeralProgressMessage; + boolean RebuildFlagPending; + boolean RebuildStatusPending; + boolean DriveSpinUpMessageDisplayed; Timer_T MonitoringTimer; GenericDiskInfo_T GenericDiskInfo; DAC960_Command_T *FreeCommands; @@ -1269,6 +1274,7 @@ DAC960_EventLogEntry_T EventLogEntry; DAC960_RebuildProgress_T RebuildProgress; DAC960_CommandStatus_T LastRebuildStatus; + DAC960_CommandStatus_T PendingRebuildStatus; DAC960_LogicalDriveInformation_T LogicalDriveInformation[2][DAC960_MaxLogicalDrives]; DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives]; @@ -1393,7 +1399,8 @@ DAC960_V5_MailboxRegister11Offset = 0x5B, DAC960_V5_MailboxRegister12Offset = 0x5C, DAC960_V5_StatusCommandIdentifierRegOffset = 0x5D, - DAC960_V5_StatusRegisterOffset = 0x5E + DAC960_V5_StatusRegisterOffset = 0x5E, + DAC960_V5_ErrorStatusRegisterOffset = 0x63 } DAC960_V5_RegisterOffsets_T; @@ -1415,7 +1422,8 @@ } Write; struct { boolean HardwareMailboxEmpty:1; /* Bit 0 */ - unsigned char :7; /* Bits 1-7 */ + boolean InitializationNotInProgress:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ } Read; } DAC960_V5_InboundDoorBellRegister_T; @@ -1459,6 +1467,22 @@ /* + Define the structure of the DAC960 V5 Error Status Register. +*/ + +typedef union DAC960_V5_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_V5_ErrorStatusRegister_T; + + +/* Define inline functions to provide an abstraction for reading and writing the DAC960 V5 Controller Interface Registers. */ @@ -1514,15 +1538,24 @@ } static inline -boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress) +boolean DAC960_V5_HardwareMailboxFullP(void *ControllerBaseAddress) { DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); - return InboundDoorBellRegister.Read.HardwareMailboxEmpty; + return !InboundDoorBellRegister.Read.HardwareMailboxEmpty; } static inline +boolean DAC960_V5_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + return !InboundDoorBellRegister.Read.InitializationNotInProgress; +} + +static inline void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) { DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; @@ -1575,7 +1608,7 @@ void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress) { DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; - InterruptMaskRegister.All = 0; + InterruptMaskRegister.All = 0xFF; InterruptMaskRegister.Bits.DisableInterrupts = false; writeb(InterruptMaskRegister.All, ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); @@ -1585,7 +1618,7 @@ void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress) { DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; - InterruptMaskRegister.All = 0; + InterruptMaskRegister.All = 0xFF; InterruptMaskRegister.Bits.DisableInterrupts = true; writeb(InterruptMaskRegister.All, ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); @@ -1607,7 +1640,9 @@ NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; + wmb(); NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; + mb(); } static inline @@ -1637,6 +1672,26 @@ return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset); } +static inline boolean +DAC960_V5_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_V5_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_V5_CommandIdentifierRegisterOffset); + writeb(0xFF, ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset); + return true; +} + static inline void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) { @@ -1695,7 +1750,8 @@ DAC960_V4_MailboxRegister11Offset = 0x100B, DAC960_V4_MailboxRegister12Offset = 0x100C, DAC960_V4_StatusCommandIdentifierRegOffset = 0x1018, - DAC960_V4_StatusRegisterOffset = 0x101A + DAC960_V4_StatusRegisterOffset = 0x101A, + DAC960_V4_ErrorStatusRegisterOffset = 0x103F } DAC960_V4_RegisterOffsets_T; @@ -1717,7 +1773,8 @@ } Write; struct { boolean HardwareMailboxFull:1; /* Bit 0 */ - unsigned int :31; /* Bits 1-31 */ + boolean InitializationInProgress:1; /* Bit 1 */ + unsigned int :30; /* Bits 2-31 */ } Read; } DAC960_V4_InboundDoorBellRegister_T; @@ -1762,6 +1819,22 @@ /* + Define the structure of the DAC960 V4 Error Status Register. +*/ + +typedef union DAC960_V4_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_V4_ErrorStatusRegister_T; + + +/* Define inline functions to provide an abstraction for reading and writing the DAC960 V4 Controller Interface Registers. */ @@ -1826,6 +1899,15 @@ } static inline +boolean DAC960_V4_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.InitializationInProgress; +} + +static inline void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) { DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; @@ -1914,7 +1996,9 @@ NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; + wmb(); NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; + mb(); } static inline @@ -1944,11 +2028,31 @@ return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset); } +static inline boolean +DAC960_V4_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_V4_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_V4_CommandIdentifierRegisterOffset); + writeb(0, ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset); + return true; +} + static inline void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; - writel(0xAABBFFFF, + writel(0x743C485E, ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); writel((unsigned long) Controller->FirstCommandMailbox, ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); @@ -1966,7 +2070,7 @@ { void *ControllerBaseAddress = Controller->BaseAddress; if (readl(ControllerBaseAddress - + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF) + + DAC960_V4_CommandOpcodeRegisterOffset) != 0x743C485E) return; *MemoryMailboxAddress = (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); @@ -2000,6 +2104,7 @@ DAC960_V3_MailboxRegister12Offset = 0x0C, DAC960_V3_StatusCommandIdentifierRegOffset = 0x0D, DAC960_V3_StatusRegisterOffset = 0x0E, + DAC960_V3_ErrorStatusRegisterOffset = 0x3F, DAC960_V3_InboundDoorBellRegisterOffset = 0x40, DAC960_V3_OutboundDoorBellRegisterOffset = 0x41, DAC960_V3_InterruptEnableRegisterOffset = 0x43 @@ -2023,7 +2128,8 @@ } Write; struct { boolean MailboxFull:1; /* Bit 0 */ - unsigned char :7; /* Bits 1-7 */ + boolean InitializationInProgress:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ } Read; } DAC960_V3_InboundDoorBellRegister_T; @@ -2064,6 +2170,22 @@ /* + Define the structure of the DAC960 V3 Error Status Register. +*/ + +typedef union DAC960_V3_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_V3_ErrorStatusRegister_T; + + +/* Define inline functions to provide an abstraction for reading and writing the DAC960 V3 Controller Interface Registers. */ @@ -2118,6 +2240,15 @@ } static inline +boolean DAC960_V3_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.InitializationInProgress; +} + +static inline void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress) { DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister; @@ -2190,6 +2321,26 @@ DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset); +} + +static inline boolean +DAC960_V3_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_V3_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_V3_CommandIdentifierRegisterOffset); + writeb(0, ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset); + return true; }