diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/Config.in linux-2.4.20-20.9.ashuaria3/drivers/scsi/Config.in *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/Config.in 2003-12-03 00:50:56.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/Config.in 2003-12-03 00:34:32.000000000 +0900 *************** *** 205,210 **** --- 205,216 ---- if [ "$CONFIG_X86" = "y" ]; then dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI fi + if [ "$CONFIG_X86" = "y" ]; then + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_tristate 'Ultima RAID 100 support (EXPERIMENTAL)' CONFIG_SCSI_ULTIMARAID100 $CONFIG_SCSI + dep_tristate 'Ultima RAID 133 support (EXPERIMENTAL)' CONFIG_SCSI_ULTIMARAID133 $CONFIG_SCSI + fi + fi dep_tristate 'Workbit NinjaSCSI-32Bi/UDE support' CONFIG_SCSI_NSP32 $CONFIG_SCSI # # Note - this is a very special 'host' adapter that simulates the presence of some disks. diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/Makefile linux-2.4.20-20.9.ashuaria3/drivers/scsi/Makefile *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/Makefile 2003-12-03 00:50:59.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/Makefile 2003-12-03 00:34:32.000000000 +0900 *************** *** 30,35 **** --- 30,37 ---- subdir-m += aic7xxx subdir-$(CONFIG_SCSI_NEWISP) += isp subdir-$(CONFIG_PCMCIA) += pcmcia + subdir-$(CONFIG_SCSI_ULTIMARAID100) += ultimaraid100 + subdir-$(CONFIG_SCSI_ULTIMARAID133) += ultimaraid133 obj-$(CONFIG_SCSI) += scsi_mod.o *************** *** 76,81 **** --- 78,89 ---- ifeq ($(CONFIG_SCSI_AIC79XX),y) obj-$(CONFIG_SCSI_AIC79XX) += aic7xxx/aic79xx.o endif + ifeq ($(CONFIG_SCSI_ULTIMARAID100),y) + obj-$(CONFIG_SCSI_ULTIMARAID100) += ultimaraid100/ultimaraid100.o + endif + ifeq ($(CONFIG_SCSI_ULTIMARAID133),y) + obj-$(CONFIG_SCSI_ULTIMARAID133) += ultimaraid133/ultimaraid133.o + endif obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o obj-$(CONFIG_SCSI_IPS) += ips.o ifeq ($(CONFIG_SCSI_NEWISP),y) diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/Makefile linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/Makefile *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/Makefile 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/Makefile 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,16 ---- + # File: drivers/ultimaraid100/Makefile + # Makefile for the Ultima RAID 100 PCI controllers driver. + + list-multi := ultimaraid100.o + ultima100-objs := ultima.o + obj-$(CONFIG_SCSI_ULTIMARAID100) := ultimaraid100.o + + EXTRA_CFLAGS += -I. + + ultimaraid100.o: $(ultima100-objs) + $(LD) -r -o $@ $(ultima100-objs) + + include $(TOPDIR)/Rules.make + + clean: + rm -f *.o diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/README linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/README *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/README 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/README 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,26 ---- + Ultima RAID 100 Driver for Linux + + Introduction + ------------------------- + Original Driver was supported by Aralion(http://www.aralion.co.kr) + + Supported Cards/Chipsets + ------------------------- + Ultima RAID 100(ARS106S) + + People + ------------------------- + Aralion Linux Dev. (Original ATA ONLY Driver source) + Ashuaria Lee (Patch for Linux Kernel Tree) + + Original Driver + ------------------------- + Aralion Linux Development + + Mailing List + ------------------------- + mailto:aralion0303-user@lists.kldp.net + mailto:aralion0303-news@lists.kldp.net + mailto:aralion0303-develop@lists.kldp.net + mailto:aralion0303-tester@lists.kldp.net + diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/TODO linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/TODO *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/TODO 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/TODO 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,3 ---- + o Testing + o More testing + o Many more diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/atapi.h linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/atapi.h *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/atapi.h 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/atapi.h 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,300 ---- + #ifndef _ATAPI_H + #define _ATAPI_H + + #ifndef UCHAR + #define UCHAR unsigned char + #define USHORT unsigned short + #define ULONG unsigned long + #endif + + #define IDE_STATUS_ERROR 0x01 + #define IDE_STATUS_INDEX 0x02 + #define IDE_STATUS_CORRECTED_ERROR 0x04 + #define IDE_STATUS_DRQ 0x08 + #define IDE_STATUS_DSC 0x10 + #define IDE_STATUS_DRDY 0x40 + #define IDE_STATUS_IDLE 0x50 + #define IDE_STATUS_BUSY 0x80 + + + #define IDE_ERROR_BAD_BLOCK 0x80 // ICRC :Crc error + #define IDE_ERROR_DATA_ERROR 0x40 // UNC :data error + #define IDE_ERROR_MEDIA_CHANGE 0x20 + #define IDE_ERROR_ID_NOT_FOUND 0x10 // IDNF :sector's ID field error + #define IDE_ERROR_MEDIA_CHANGE_REQ 0x08 + #define IDE_ERROR_COMMAND_ABORTED 0x04 // ABRT :command error + #define IDE_ERROR_END_OF_MEDIA 0x02 + #define IDE_ERROR_ILLEGAL_LENGTH 0x01 + // + // IDE command definitions + // + #define IDE_COMMAND_ATAPI_RESET 0x08 // Don't use! + #define IDE_COMMAND_RECALIBRATE 0x10 + #define IDE_COMMAND_READ 0x20 // <--- + #define IDE_COMMAND_WRITE 0x30 // <--- + #define IDE_COMMAND_VERIFY 0x40 // <--- + #define IDE_COMMAND_SEEK 0x70 + #define IDE_COMMAND_SET_DRIVE_PARAMETERS 0x91 + #define IDE_COMMAND_ATAPI_PACKET 0xA0 // Don't use! + #define IDE_COMMAND_ATAPI_IDENTIFY 0xA1 // Don't use! + #define IDE_COMMAND_READ_MULTIPLE 0xC4 // <--- + #define IDE_COMMAND_WRITE_MULTIPLE 0xC5 // <--- + #define IDE_COMMAND_SET_MULTIPLE 0xC6 + #define IDE_COMMAND_READ_DMA 0xC8 // <--- + #define IDE_COMMAND_WRITE_DMA 0xCA // <--- + #define IDE_COMMAND_GET_MEDIA_STATUS 0xDA + #define IDE_COMMAND_ENABLE_MEDIA_STATUS 0xEF // Feature Set + #define IDE_COMMAND_IDENTIFY 0xEC // <--- + #define IDE_COMMAND_MEDIA_EJECT 0xED + + + //////////////////////////////////KHG133s_Big////////////////////////////////////// + #define IDE_COMMAND_READ_DMA_EXT 0x25 + #define IDE_COMMAND_WRITE_DMA_EXT 0x35 + #define IDE_COMMAND_READ_SECTORS 0x20 + #define IDE_COMMAND_WRITE_SECTORS 0x30 + #define IDE_COMMAND_READ_SECTORS_EXT 0x24 + #define IDE_COMMAND_WRITE_SECTORS_EXT 0x34 + /////////////////////////////////////////////////////////////////////////////////// + // + //DmaCommand bits definition + // + #define DMA_READ 0x07 + #define DMA_WRITE 0x06 + + // + // Mode Register bit definotion + // + #define MODE_PIO 0x00 + #define MODE_DMA 0x01 + #define MODE_UDMA 0x03 + + // + // HDD DMA Mode Support + // + #define DMA_0 0x01 + #define DMA_1 0x03 + #define DMA_2 0x07 + #define UDMA_0 0x08 + #define UDMA_1 0x18 + #define UDMA_2 0x38 + + // + // Multiple sector setting is valid by HBA. + // + #define MULTIPLE_SET 0x0100 + + // + // Device Extension Device Flags + // + #define DFLAGS_DEVICE_PRESENT 0x0001 // Indicates that some device is present. + #define DFLAGS_DMA_DEVICE 0x0002 // Device is a DMA or UDMA device. + #define DFLAGS_PIO_DEVICE 0x0004 // Device is a PIO device. + + // + // Used to disable 'advanced' features. + // + #define MAX_ERRORS 4 // FOR IDE ERROR in MapError() + + #ifdef XXX + typedef struct _IDENTIFY_DATA { + USHORT GeneralConfiguration; // 00 00 + USHORT NumberOfCylinders; // 02 1 + USHORT Reserved1; // 04 2 + USHORT NumberOfHeads; // 06 3 + USHORT UnformattedBytesPerTrack; // 08 4 + USHORT UnformattedBytesPerSector; // 0A 5 + USHORT SectorsPerTrack; // 0C 6 + USHORT VendorUnique1[3]; // 0E 7-9 + USHORT SerialNumber[10]; // 14 10-19 + USHORT BufferType; // 28 20 + USHORT BufferSectorSize; // 2A 21 + USHORT NumberOfEccBytes; // 2C 22 + USHORT FirmwareRevision[4]; // 2E 23-26 + USHORT ModelNumber[20]; // 36 27-46 + UCHAR MaximumBlockTransfer; // 5E 47 + UCHAR VendorUnique2; // 5F + USHORT DoubleWordIo; // 60 48 + USHORT Capabilities; // 62 49 + USHORT Reserved2; // 64 50 + UCHAR VendorUnique3; // 66 51 + UCHAR PioCycleTimingMode; // 67 + UCHAR VendorUnique4; // 68 52 + UCHAR DmaCycleTimingMode; // 69 + USHORT TranslationFieldsValid:1; // 6A 53 + USHORT Reserved3:15; + USHORT NumberOfCurrentCylinders; // 6C 54 + USHORT NumberOfCurrentHeads; // 6E 55 + USHORT CurrentSectorsPerTrack; // 70 56 + ULONG CurrentSectorCapacity; // 72 57-58 + USHORT CurrentMultiSectorSetting; // 59 + ULONG UserAddressableSectors; // 60-61 + USHORT SingleWordDMASupport : 8; // 62 + USHORT SingleWordDMAActive : 8; + USHORT MultiWordDMASupport : 8; // 63 + USHORT MultiWordDMAActive : 8; + USHORT AdvancedPIOModes : 8; // 64 + USHORT Reserved4 : 8; + USHORT MinimumMWXferCycleTime; // 65 + USHORT RecommendedMWXferCycleTime; // 66 + USHORT MinimumPIOCycleTime; // 67 + USHORT MinimumPIOCycleTimeIORDY; // 68 + USHORT Reserved5[2]; // 69-70 + USHORT ReleaseTimeOverlapped; // 71 + USHORT ReleaseTimeServiceCommand; // 72 + USHORT MajorRevision; // 73 + USHORT MinorRevision; // 74 + USHORT Reserved6[11]; // 75-126 + USHORT DmaMode[6]; + USHORT Reserved7[33]; // 75-126 + USHORT SpecialFunctionsEnabled; // 127 + USHORT Reserved8[128]; // 128-255 + } IDENTIFY_DATA, *PIDENTIFY_DATA; + #endif + + // + // IDENTIFY data + // + typedef struct _IDENTIFY_DATA { + USHORT GeneralConfiguration; // 00 00 + USHORT NumberOfCylinders; // 02 1 + USHORT Reserved1; // 04 2 + USHORT NumberOfHeads; // 06 3 + USHORT UnformattedBytesPerTrack; // 08 4 + USHORT UnformattedBytesPerSector; // 0A 5 + USHORT SectorsPerTrack; // 0C 6 + USHORT VendorUnique1[3]; // 0E 7-9 + USHORT SerialNumber[10]; // 14 10-19 + USHORT BufferType; // 28 20 + USHORT BufferSectorSize; // 2A 21 + USHORT NumberOfEccBytes; // 2C 22 + USHORT FirmwareRevision[4]; // 2E 23-26 + USHORT ModelNumber[20]; // 36 27-46 + UCHAR MaximumBlockTransfer; // 5E 47 + UCHAR VendorUnique2; // 5F + USHORT DoubleWordIo; // 60 48 + USHORT Capabilities; // 62 49 + USHORT Reserved2; // 64 50 + UCHAR VendorUnique3; // 66 51 + UCHAR PioCycleTimingMode; // 67 + UCHAR VendorUnique4; // 68 52 + UCHAR DmaCycleTimingMode; // 69 + + UCHAR TranslationFieldsValid; // 6A 53 + UCHAR Reserved3; + /* + USHORT TranslationFieldsValid:3; // 6A 53 + USHORT Reserved3:13; + */ + + USHORT NumberOfCurrentCylinders; // 6C 54 + USHORT NumberOfCurrentHeads; // 6E 55 + USHORT CurrentSectorsPerTrack; // 70 56 + USHORT CurrentSectorCapacity[2]; // 72 57-58 + + /////// Out of spec! //////////// + USHORT CurrentMultiSectorSetting; // 59 + USHORT UserAddressableSectors[2]; // 60-61 + + UCHAR SingleWordDMASupport; // 62 Low + UCHAR SingleWordDMAActive; // High + /* + USHORT SingleWordDMASupport:8; // 62 Low + USHORT SingleWordDMAActive:8; // High + */ + + UCHAR MultiWordDMASupport; // 63 Low + UCHAR MultiWordDMAActive; // High + /* + USHORT MultiWordDMASupport:3; // 63 Low + USHORT MultiWordDMAActive:13; // High + */ + + UCHAR AdvancedPIOModes; // 64 + UCHAR Reserved4; + /* + USHORT AdvancedPIOModes:8; // 64 + USHORT Reserved4:8; + */ + + USHORT MinimumMWXferCycleTime; // 65 + USHORT RecommendedMWXferCycleTime; // 66 + USHORT MinimumPIOCycleTime; // 67 + USHORT MinimumPIOCycleTimeIORDY; // 68 + USHORT Reserved5[2]; // 69-70 + USHORT ReleaseTimeOverlapped; // 71 + USHORT ReleaseTimeServiceCommand; // 72 + USHORT MajorRevision; // 73 + USHORT MinorRevision; // 74 + + //////////////////////////////////KHG-133s_Big//////////////////////////////// + USHORT Reserved6[8]; // 75-82 + USHORT BIT48; // 83 + USHORT Reserved6_1[4]; // 84-87 + ////////////////////////////////////////////////////////////////////////////// + + UCHAR UDMASupport; // 88 + UCHAR UDMASelected; // + /* + USHORT UDMASupport:3; // 88 + USHORT UDMASelected:13; // + */ + + USHORT Reserved7[38]; // 89-126 + USHORT SpecialFunctionsEnabled; // 127 + USHORT Reserved8[128]; // 128-255 + } IDENTIFY_DATA, *PIDENTIFY_DATA; + typedef struct _INQUIRYDATA { + UCHAR DeviceType : 5; + UCHAR DeviceTypeQualifier : 3; + UCHAR DeviceTypeModifier : 7; + UCHAR RemovableMedia : 1; + UCHAR Versions; + UCHAR ResponseDataFormat; + UCHAR AdditionalLength; + UCHAR Reserved[2]; + UCHAR SoftReset : 1; + UCHAR CommandQueue : 1; + UCHAR Reserved2 : 1; + UCHAR LinkedCommands : 1; + UCHAR Synchronous : 1; + UCHAR Wide16Bit : 1; + UCHAR Wide32Bit : 1; + UCHAR RelativeAddressing : 1; + UCHAR VendorId[8]; + UCHAR ProductId[16]; + UCHAR ProductRevisionLevel[4]; + UCHAR VendorSpecific[20]; + UCHAR Reserved3[40]; + } INQUIRYDATA, *PINQUIRYDATA; + + #define DIRECT_ACCESS_DEVICE 0x00 // disks + #define SEQUENTIAL_ACCESS_DEVICE 0x01 // tapes + #define PRINTER_DEVICE 0x02 // printers + #define PROCESSOR_DEVICE 0x03 // scanners, printers, etc + #define WRITE_ONCE_READ_MULTIPLE_DEVICE 0x04 // worms + #define READ_ONLY_DIRECT_ACCESS_DEVICE 0x05 // cdroms + #define SCANNER_DEVICE 0x06 // scanners + #define OPTICAL_DEVICE 0x07 // optical disks + #define MEDIUM_CHANGER 0x08 // jukebox + #define COMMUNICATION_DEVICE 0x09 // network + #define LOGICAL_UNIT_NOT_PRESENT_DEVICE 0x7F + #define DEVICE_QUALIFIER_NOT_SUPPORTED 0x03 + + #define PDTLAR 0X00 + #define PDTHAR 0x02 + #define CMDR 0x04 + #define DMAMODE 0x06 + #define PIO_TIM 0x08 + #define MDM_TIM 0x0a + #define UDM_TIM 0x0c + #define CONSR 0x0e + + #define INTSRC 0x00 + #define CBL_ID 0x02 + #define INTENA 0x04 + #define RAIDSTAT 0x06 + + #endif + + diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/ultima.c linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/ultima.c *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/ultima.c 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/ultima.c 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,2134 ---- + /******************************************************************* + + Aralion Ultima ATA100 IDE Raid Controller + Linux Device Driver source, programmed by soonsoo@hitel.net + + *******************************************************************/ + //#define __BOOT_KERNEL_BOOT 1 + + //#define DEBUG1 1 + //#define DEBUG2 1 + //#define DEBUG3 1 + //#define DEBUG4 1 + + #include + #include + #include + #include + #include + #include "../scsi.h" + #include "../hosts.h" + #include "../sd.h" + #include "ultima.h" + #include "atapi.h" + #include + #include + #include + #include + #include + #include + #include + #include + #include /* for CONFIG_PCI */ + #include + #include /* for put_user_byte */ + #include + #include + #include + #include + //#include "iocontrol.h" + //#include "flash.h" + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + #define KERNEL240 + #else + #define KERNEL220 + #endif + + #define S_BOARD(x) (DiskID[x].DiskStatus.BoardID) + #define S_CHAN(x) (DiskID[x].DiskStatus.Channel) + #define S_DRV(x) (DiskID[x].DiskStatus.Drive) + #define RAID(x) (DiskID[x].RaidStatus) + + //////////////////////////////////////////////////////////////////////////////////////// + + static void print_banner(struct Scsi_Host *shpnt); + char * GetCmdName(char code); + static void print_banner(struct Scsi_Host *shpnt); + static void do_pause(ULONG amount); + static int aralion_pci_bios_detect(int *irq); + ULONG GetBlockCount(int BoardID,int channel,int drive); + void SetBlockCount(int BoardID,int channel,int drive,ULONG nCount); + int RequestAllIrq(void); + int PutOneDriveToDiskSet(int board,int disk,_DiskIDTable *DiskID,V6BDISKINFO *DiskInfo); + void PutLBAvalue( + ULONG IOPort1, + ULONG lba, + ULONG numsectors, + ULONG DriveSelect); + void DisableInterrupt(int BoardID); + void EnableInterrupt(int BoardID); + ULONG SetBoardInterruptFlag(int BoardID,int Channel,DWORD Status); + ULONG SetScatterList( + Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors, + ULONG ReadWrite); + void SetIOPort(DISKLIST *pList,USHORT DmaRW,DWORD OrderFlag); + void SetIOInformation(int tid,USHORT DmaRW,DWORD OrderFlag); + ULONG PutOneScatterList( + ULONG CurrentID, + DWORD PrimaryDiskArrayCount, + DISKLIST *PrimaryDiskArray, + ULONG lba, + ULONG buffer, + USHORT length); + void SetIDECommand(DWORD Command, DWORD order); + DWORD BigDiskCommand (DWORD cmnd); + void SetDMACommand(USHORT DmaRW,DWORD OrderFlag); + void FillDump( Scsi_Cmnd * SCpnt); + static int ReadDMA( + Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors); + static int WriteDMA( + Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors); + void GetUDMAMode( + USHORT *mode, + USHORT *Timing, + IDENTIFY_DATA * IdentifyData); + void SetUDMAMode( + int BoardID, + int Channel, + int DriveSelect, + IDENTIFY_DATA * IdentifyData); + static int IdentifyDisk( + int BoardID, + int Channel, + int DriveSelect, + IDENTIFY_DATA * IdentifyData); + static void my_done(int error); + int CheckScsiError(ULONG Channel,ULONG IOPort1,UCHAR statusByte); + void CheckJobFinished(ULONG BoardID,ULONG Channel); + int IsSplitter(char c); + int ultima_1cardreset(int BoardID); + int ultima_cardreset(void); + void do_ultima_intr(int irq, void *dev_id, struct pt_regs *regs); + void internal_done(Scsi_Cmnd * SCpnt); + void print_info(Scsi_Cmnd * SCpnt); + + //////////////////////////////////////////////////////////////////////////////////////// + + struct proc_dir_entry proc_scsi_aralion = { + 0x10, 7, "aralion", + S_IFDIR | S_IRUGO | S_IXUGO, 2 + }; + + Scsi_Host_Template driver_template = ULTIMA_DMA100; + + #define VERSION "$Revision: LV2.01X-X86-ATA $" + + + enum { + in_arbitration = 0x02, + in_selection = 0x04, + in_other = 0x08, + disconnect = 0x10, + aborted = 0x20, + sent_ident = 0x40, + }; + + typedef struct { + char name[23]; + char code; + } CMDNAME; + + CMDNAME CmdName[] = + { + {"TEST_UNIT_READY",0x00}, + {"REZERO_UNIT",0x01}, + {"REQUEST_SENSE",0x03}, + {"FORMAT_UNIT",0x04}, + {"READ_BLOCK_LIMITS",0x05}, + {"REASSIGN_BLOCKS",0x07}, + {"READ_6",0x08}, + {"WRITE_6",0x0a}, + {"SEEK_6",0x0b}, + {"READ_REVERSE",0x0f}, + {"WRITE_FILEMARKS",0x10}, + {"SPACE",0x11}, + {"INQUIRY",0x12}, + {"RECOVER_BUFFERED_DATA",0x14}, + {"MODE_SELECT",0x15}, + {"RESERVE",0x16}, + {"RELEASE",0x17}, + {"COPY",0x18}, + {"ERASE",0x19}, + {"MODE_SENSE",0x1a}, + {"START_STOP",0x1b}, + {"RECEIVE_DIAGNOSTIC",0x1c}, + {"SEND_DIAGNOSTIC",0x1d}, + {"ALLOW_MEDIUM_REMOVAL",0x1e}, + {"SET_WINDOW",0x24}, + {"READ_CAPACITY",0x25}, + {"READ_10",0x28}, + {"WRITE_10",0x2a}, + {"SEEK_10",0x2b}, + {"WRITE_VERIFY",0x2e}, + {"VERIFY",0x2f}, + {"SEARCH_HIGH",0x30}, + {"SEARCH_EQUAL",0x31}, + {"SEARCH_LOW",0x32}, + {"SET_LIMITS",0x33}, + {"PRE_FETCH",0x34}, + {"READ_POSITION",0x34}, + {"SYNCHRONIZE_CACHE",0x35}, + {"LOCK_UNLOCK_CACHE",0x36}, + {"READ_DEFECT_DATA",0x37}, + {"MEDIUM_SCAN",0x38}, + {"COMPARE",0x39}, + {"COPY_VERIFY",0x3a}, + {"WRITE_BUFFER",0x3b}, + {"READ_BUFFER",0x3c}, + {"UPDATE_BLOCK",0x3d}, + {"READ_LONG",0x3e}, + {"WRITE_LONG",0x3f}, + {"CHANGE_DEFINITION",0x40}, + {"WRITE_SAME",0x41}, + {"READ_TOC",0x43}, + {"LOG_SELECT",0x4c}, + {"LOG_SENSE",0x4d}, + {"MODE_SELECT_10",0x55}, + {"RESERVE_10",0x56}, + {"RELEASE_10",0x57}, + {"MODE_SENSE_10",0x5a}, + {"PERSISTENT_RESERVE_IN",0x5e}, + {"PERSISTENT_RESERVE_OUT",0x5f}, + {"MOVE_MEDIUM",0xa5}, + {"READ_12",0xa8}, + {"WRITE_12",0xaa}, + {"WRITE_VERIFY_12",0xae}, + {"SEARCH_HIGH_12",0xb0}, + {"SEARCH_EQUAL_12",0xb1}, + {"SEARCH_LOW_12",0xb2}, + {"READ_ELEMENT_STATUS",0xb8}, + {"SEND_VOLUME_TAG",0xb6}, + {"WRITE_LONG_2",0xea} + }; + + /////////////////////////////////////////////////////////////////////// + static volatile int internal_done_flag = 0; + static volatile int internal_done_errcode = 0; + static Scsi_Cmnd *current_SC = NULL; + static int this_id = 31; + V6INTERFACEB V6; + static _DiskIDTable DiskID[16]; + static DISKRWINFO DiskRWInfo[MAXBOARD][2][2]; + static IDENTIFY_DATA DiskIdentifyData[MAXBOARD][2][2]; + static int gBoardCount = 0; + IrqID ultimaID[MAXBOARD]; + BOARDTABLE BoardInfo[MAXBOARD]; + static int IrqFlag[16] = {0,}; + static int DriverInit = 0; + static int DiskCount = 0; + ULONG LastErrorBlock,LastErrorCode; + static ULONG RWStatus; + static ULONG OrderStatus; + static ULONG CurrentDisk; + static int interrupt_level = 0; + ///////////////////////////////////////////////// + #define IOCTL_LOCK 1 + static int in_ioctl = 0; + static int ClearReady = 0; + static int in_command = 0; + unsigned long LockValue = 0; + static DECLARE_WAIT_QUEUE_HEAD (WaitingQ); + static int HddConnected[MAXBOARD][2][2]; + ///////////////////////////////////////////////// + DWORD gResetFlag = 0; + char * GetCmdName(char code) + { + int i; + int count; + char *s = "unknown function"; + + count = sizeof(CmdName) / sizeof(CMDNAME); + + for(i=0;ithis_id); + + if (interrupt_level) + printk(" int %d", interrupt_level); + else + printk(""); + + printk("\n"); + } + + static void aralion_setup(char *str, int *ints) + { + this_id = 31; + } + + + /* Pause for amount*10 milliseconds */ + static void do_pause(ULONG amount) + { + do + { + udelay(10 * 1000); + } + while (--amount); + } + + inline static void aralion_make_bus_idle(void) + { + } + + static int aralion_is_valid_port(int port) + { + return 0; + } + + static int aralion_test_loopback(void) + { + return 0; + } + + static int aralion_pci_bios_detect(int *irq) + { + struct pci_dev *pdev = NULL; + + if (!pci_present()) + return 0; + + memset(BoardInfo,0,sizeof(BoardInfo)); + + do { + if ((pdev = pci_find_device(ARALION_VENDOR, ULTIMA_DEVICE, pdev)) != NULL) { + #ifdef KERNEL240 + BoardInfo[gBoardCount].PrimaryIO + = (ULONG) pci_resource_start(pdev,0); + BoardInfo[gBoardCount].SecondaryIO + = (ULONG) pci_resource_start(pdev,1); + BoardInfo[gBoardCount].PrimaryDmaIO + = (ULONG) pci_resource_start(pdev,2); + BoardInfo[gBoardCount].SecondaryDmaIO + = (ULONG) pci_resource_start(pdev,3); + BoardInfo[gBoardCount].ControlRegister + = (ULONG) pci_resource_start(pdev,4); + #else + BoardInfo[gBoardCount].PrimaryIO + = (ULONG) pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + BoardInfo[gBoardCount].SecondaryIO + = (ULONG) pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; + BoardInfo[gBoardCount].PrimaryDmaIO + = (ULONG) pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK; + BoardInfo[gBoardCount].SecondaryDmaIO + = (ULONG) pdev->base_address[3] & PCI_BASE_ADDRESS_IO_MASK; + BoardInfo[gBoardCount].ControlRegister + = (ULONG) pdev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; + #endif + BoardInfo[gBoardCount].interrupt_level = pdev->irq; + + request_region(BoardInfo[gBoardCount].PrimaryIO, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].SecondaryIO, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].PrimaryDmaIO, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].SecondaryDmaIO, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].ControlRegister, 0x10, "aralion"); + if (!gBoardCount) + *irq = pdev->irq; + + gBoardCount++; + } + } while(pdev != NULL); + + + if (!gBoardCount) { + printk("Ultima Board not found\n"); + return 0; + } + + interrupt_level = BoardInfo[0].interrupt_level; + + // printk("%d's Board found :",gBoardCount); + + return 1; + } + + ULONG GetBlockCount(int BoardID,int channel,int drive) + { + int i; + ULONG nCount; + UCHAR *p; + p = (char *) &(DiskIdentifyData[BoardID][channel][drive]); + if(DiskIdentifyData[BoardID][channel][drive].BIT48 & 0x0400) + nCount = *((ULONG *) (p + 200)); + else + nCount = *((ULONG *) (p + 120)); + // printk("BCD=%d,%d,%d Size = %u \n",BoardID,channel,drive,nCount); + return nCount; + } + + + void SetBlockCount(int BoardID,int channel,int drive,ULONG nCount) + { + UCHAR *p; + + p = (char *) &(DiskIdentifyData[BoardID][channel][drive]); + if(DiskIdentifyData[BoardID][channel][drive].BIT48 & 0x0400) + *((ULONG *) (p + 200)) = nCount; + else + *((ULONG *) (p + 120)) = nCount; + } + + ////////////////// + int RequestAllIrq(void) + { + int i; + int irq; + int retcode; + + for(i=0;i IRQ %d is bad!\n", irq); + printk(" This shouldn't happen!\n"); + printk(" Send mail to faith@acm.org\n"); + } else if (retcode == -EBUSY) { + printk("scsi: IRQ %d is already in use!\n",irq); + printk(" Please use another IRQ!\n"); + } else { + printk("scsi: Error getting IRQ %d\n",irq); + printk(" This shouldn't happen!\n"); + printk(" Send mail to faith@acm.org\n"); + } + printk("scsi: Detected, but driver not loaded (IRQ)\n"); + + return retcode; + } + } + } + return 0; + } + + + int ultima_detect(Scsi_Host_Template * tpnt) + { + int retcode; + struct Scsi_Host *shpnt; + int i, j; + int flag = 0; + + tpnt->proc_dir = &proc_scsi_aralion; + + flag = aralion_pci_bios_detect(&interrupt_level); + + if (!flag) { + printk("scsi: Ultima not found\n"); + return 0; + } + + + memset(&DiskID,0,sizeof(DiskID)); + memset(&DiskRWInfo,0,sizeof(DiskRWInfo)); + memset(&DiskIdentifyData,0,sizeof(DiskIdentifyData)); + DiskCount = 0; + + + for(i=0;ithis_id = (this_id & 0x1f); + + /* Print out a banner here in case we can't + get resources. */ + shpnt = scsi_register(tpnt, 0); + shpnt->irq = interrupt_level; + shpnt->io_port = BoardInfo[0].ControlRegister; + shpnt->n_io_port = 0x10; + // print_banner(shpnt); + + if (!interrupt_level) + { + printk("scsi: " + " Card Detected, but driver not loaded (no IRQ)\n"); + return 0; + } else + { + /* Register the IRQ with the kernel */ + if (RequestAllIrq()) + return 0; + } + DriverInit = 0; + + for(i=0;i ",i,d1); + } + printk("\n"); + } + #endif + + inline DISKRWINFO *GetRWInfoPointer(DISKLIST *pDiskList) + { + return (DISKRWINFO *) &DiskRWInfo[pDiskList->BoardID][pDiskList->Channel][pDiskList->Drive]; + } + + void PutLBAvalue(ULONG IOPort1,ULONG lba,ULONG numsectors, + ULONG DriveSelect) + { + UCHAR Data[4]; + if(lba >= 0x10000000){ + Data[0] = (lba & 0xff000000 ) >> 24; + Data[1] = 0; + Data[2] = 0; + outb(0,IOPort1 + BlockCountPort); + outb(Data[0],IOPort1 + BlockNumberPort); + outb(Data[1],IOPort1 + CylinderLowPort); + outb(Data[2],IOPort1 + CylinderHighPort); + Data[0] = (lba & 0x000000ff); + Data[1] = (lba & 0x0000ff00) >> 8; + Data[2] = (lba & 0x00ff0000) >> 16; + Data[3] = (DriveSelect << 4) | 0xe0; + outb(numsectors,IOPort1 + BlockCountPort); + outb(Data[0],IOPort1 + BlockNumberPort); + outb(Data[1],IOPort1 + CylinderLowPort); + outb(Data[2],IOPort1 + CylinderHighPort); + outb(Data[3],IOPort1 + DriveSelectPort); + } + else{ + Data[0] = (lba & 0x000000ff); + Data[1] = (lba & 0x0000ff00) >> 8; + Data[2] = (lba & 0x00ff0000) >> 16; + Data[3] = (lba & 0x0f000000) >> 24; + Data[3] = Data[3] | 0x40 | (DriveSelect << 4) | 0xa0; + + outb(numsectors,IOPort1 + BlockCountPort); + outb(Data[0],IOPort1 + BlockNumberPort); + outb(Data[1],IOPort1 + CylinderLowPort); + outb(Data[2],IOPort1 + CylinderHighPort); + outb(Data[3],IOPort1 + DriveSelectPort); + } + } + + void DisableInterrupt(int BoardID) + { + USHORT Intena; + Intena = 0; + outw(Intena,BoardInfo[BoardID].ControlRegister + INTENA); + } + + void EnableInterrupt(int BoardID) + { + USHORT Intena; + Intena = 0x03; + outw(Intena,BoardInfo[BoardID].ControlRegister + INTENA); + } + + ULONG SetBoardInterruptFlag(int BoardID,int Channel,DWORD Status) + { + ULONG TempStatus; + + if (BoardInfo[BoardID].InterruptFlag[Channel] & Status) { + TempStatus = BoardInfo[BoardID].InterruptFlag[Channel] & 0x00001111; + if(TempStatus & 0x00001100){ + BoardInfo[BoardID].InterruptFlag[Channel] |= 0x00001000; + return 0x00001000; + } + else if(TempStatus & 0x00000010){ + BoardInfo[BoardID].InterruptFlag[Channel] |= 0x00000100; + return 0x00000100; + } + else { + BoardInfo[BoardID].InterruptFlag[Channel] |= 0x00000010; + return 0x000000010; + } + + + #ifdef DEBUG1 + printk("SL:[%d,%d] - %08x ", + BoardID,Channel, + BoardInfo[BoardID].InterruptFlag[Channel]); + #endif + } + else { + BoardInfo[BoardID].InterruptFlag[Channel] = (Status | ORDER_ONE); + + #ifdef DEBUG1 + printk("SF:[%d,%d] - %08x ", + BoardID,Channel, + BoardInfo[BoardID].InterruptFlag[Channel]); + #endif + return 0; + } + } + + ULONG SetScatterList( Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors, + ULONG ReadWrite) + { + struct scatterlist *slp; + int i,j; + PPDT_TABLE pPDTTable; + DISKRWINFO *pRWInfo,*pRWInfo2; + int tid = SCpnt->target; + DWORD RaidStatus; + ULONG TempFlag; + + RaidStatus = RAID(tid); + + pRWInfo = (DISKRWINFO *) &DiskRWInfo[S_BOARD(tid)][S_CHAN(tid)][S_DRV(tid)]; + pRWInfo->StartLba = lba; + pRWInfo->ListCount = 0; + pRWInfo->NumSectors = 0; + pPDTTable = pRWInfo->ScatterList; + + if (SCpnt->use_sg) + { + slp = (struct scatterlist *) SCpnt->request_buffer; + for(i=0;iuse_sg;i++,slp++) { + pPDTTable[i].address = virt_to_bus(slp->address); + pPDTTable[i].length = slp->length; + pPDTTable[i].EndOfChain = 0; + pRWInfo->NumSectors += slp->length; + } + pPDTTable[i - 1].EndOfChain = 0x80; + pRWInfo->ListCount = SCpnt->use_sg; + } + else + { + pPDTTable[0].address = virt_to_bus(SCpnt->request_buffer); + pPDTTable[0].length = SCpnt->request_bufflen; + pPDTTable[0].EndOfChain = 0x80; + pRWInfo->NumSectors = SCpnt->request_bufflen; + pRWInfo->ListCount = 1; + } + + pRWInfo->NumSectors /= 512; + + pRWInfo->InterruptFlag = ReadWrite | ORDER_ONE; + SetBoardInterruptFlag(S_BOARD(tid),S_CHAN(tid),ReadWrite); + + } + + void PrintPDT(PPDT_TABLE pPDTTable,int count) + { + int i; + + for(i=0;iBoardID; + Channel = pList->Channel; + Drive = pList->Drive; + + pRWInfo = (DISKRWINFO *) &DiskRWInfo[pList->BoardID][pList->Channel][pList->Drive]; + + + #ifdef DEBUG1 + /* + printk("SetIOPort : [B:%d,C:%d,D:%d,F:%08x,O:%08x]\n", + BoardID, + Channel, + Drive, + pRWInfo->InterruptFlag, + OrderFlag); + */ + #endif + + + if (!(OrderFlag & pRWInfo->InterruptFlag)) { + #ifdef DEBUG1 + printk("Order Invalid\n"); + #endif + return ; + } + + if (Channel == 0) + { + pPDTTable = BoardInfo[BoardID].PriScatterList; + IOPort1 = BoardInfo[BoardID].PrimaryIO; + DmaIO = BoardInfo[BoardID].PrimaryDmaIO; + } + else + { + pPDTTable = BoardInfo[BoardID].SecScatterList; + IOPort1 = BoardInfo[BoardID].SecondaryIO; + DmaIO = BoardInfo[BoardID].SecondaryDmaIO; + } + memcpy(pPDTTable,pRWInfo->ScatterList,pRWInfo->ListCount * sizeof(PDT_TABLE)); + BoardInfo[BoardID].ListCount = pRWInfo->ListCount; + BoardInfo[BoardID].NumSectors = pRWInfo->NumSectors; + BoardInfo[BoardID].StartLba = pRWInfo->StartLba; + + AddressLow = virt_to_bus(pPDTTable) & 0x0000ffff; + AddressHi = (virt_to_bus(pPDTTable) & 0xffff0000) >> 16; + + outw(AddressLow,DmaIO + PDTLAR); + outw(AddressHi,DmaIO + PDTHAR); + PutLBAvalue( + IOPort1, + BoardInfo[BoardID].StartLba, + BoardInfo[BoardID].NumSectors, + Drive); + + } + + void SetIOInformation(int tid,USHORT DmaRW,DWORD OrderFlag) + { + struct scatterlist *slp; + int i,j,k; + PPDT_TABLE pPDTTable; + DISKRWINFO *pRWInfo = GetRWInfoPointer(&DiskID[tid].DiskStatus); + if (pRWInfo->ListCount) { + SetIOPort(&DiskID[tid].DiskStatus,DmaRW,OrderFlag); + } + + } + + void SetIDECommand(DWORD Command, DWORD OrderFlag) + { + int i,j; + + for(i=0;i= 0x10000000) + Command=BigDiskCommand(Command); + outb(Command,BoardInfo[i].PrimaryIO + CommandPort); + } + if (BoardInfo[i].InterruptFlag[1] & OrderFlag) { + if(BoardInfo[i].StartLba >= 0x10000000) + Command=BigDiskCommand(Command); + outb(Command,BoardInfo[i].SecondaryIO + CommandPort); + } + + } + } + + DWORD BigDiskCommand (DWORD cmnd) + { + switch(cmnd){ + case IDE_COMMAND_READ_DMA: + return IDE_COMMAND_READ_DMA_EXT; + case IDE_COMMAND_WRITE_DMA: + return IDE_COMMAND_WRITE_DMA_EXT; + } + } + + void SetDMACommand(USHORT DmaRW,DWORD OrderFlag) + { + ULONG DmaIO; + int i,j,k; + + for(i=0;itarget].RaidStatus) { + case NORMALIDE: + SetScatterList(SCpnt,lba,numsectors,READ_STATUS); + break; + default: + printk("Not Supported Mode!!\n"); + return -1; + } + SetIOInformation(SCpnt->target,DMA_READ,ORDER_ONE); + RWStatus = READ_STATUS; + OrderStatus = ORDER_ONE; + SetIDECommand(IDE_COMMAND_READ_DMA,ORDER_ONE); + SetDMACommand(DMA_READ,ORDER_ONE); + return 0; + } + + static int WriteDMA( + Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors) + { + int i; + unsigned long flags; + + if (numsectors == 0) { + my_done(DID_ABORT << 16); + return ERROR_INVALID_SECTORCOUNT; + } + + switch(DiskID[SCpnt->target].RaidStatus) { + case NORMALIDE: + SetScatterList(SCpnt,lba,numsectors,WRITE_STATUS); + break; + default: + printk("Not Supported Mode!!\n"); + return -1; + + } + SetIOInformation(SCpnt->target,DMA_WRITE,ORDER_ONE); + RWStatus = WRITE_STATUS; + OrderStatus = ORDER_ONE; + SetIDECommand(IDE_COMMAND_WRITE_DMA,ORDER_ONE); + SetDMACommand(DMA_WRITE,ORDER_ONE); + return 0; + } + + void GetUDMAMode(USHORT *mode,USHORT *Timing, + IDENTIFY_DATA * IdentifyData) + { + + if(IdentifyData->UDMASupport & 0x20){ + *mode = 0x45; // mode 5 + *Timing = 0xff22; // mode 5 + } + else if(IdentifyData->UDMASupport & 0x10){ + *mode = 0x44; // mode 4 + *Timing = 0xff33; // mode 4 + } + else if(IdentifyData->UDMASupport & 0x08){ + *mode = 0x43; // mode 3 + *Timing = 0xff55; // mode 3 + } + else if(IdentifyData->UDMASupport & 0x04){ + *mode = 0x42; // mode 2 + *Timing = 0xff66; // mode 2 + } + else if(IdentifyData->UDMASupport & 0x02){ + *mode = 0x41; // mode 1 + *Timing = 0xff88; // mode 1 + } + else if(IdentifyData->UDMASupport & 0x01){ + *mode = 0x40; // mode 0 + *Timing = 0xffcc; // mode 0 + } + #ifdef _7878_ + *mode = 0x44; // mode 4 + *Timing = 0x7878; // safe mode + #endif + } + + void SetUDMAMode( int BoardID, + int Channel, + int DriveSelect, + IDENTIFY_DATA * IdentifyData) + { + USHORT mode[2],Timing[2]; + ULONG IOPort1; + ULONG DmaIO; + char statusByte; + int i; + if (Channel == 0) { + IOPort1 = BoardInfo[BoardID].PrimaryIO; + DmaIO = BoardInfo[BoardID].PrimaryDmaIO; + } + else { + IOPort1 = BoardInfo[BoardID].SecondaryIO; + DmaIO = BoardInfo[BoardID].SecondaryDmaIO; + } + outb(0x03,IOPort1 + ErrorPort); + + for(i=0;i<4;i++) + { + mode[i] = 0xffff; + } + + if (HddConnected[BoardID][Channel][0]) + GetUDMAMode(&mode[0],&Timing[0],&DiskIdentifyData[BoardID][Channel][0]); + if (HddConnected[BoardID][Channel][1]) + GetUDMAMode(&mode[1],&Timing[1],&DiskIdentifyData[BoardID][Channel][1]); + if(mode[0] > mode[1]) + { + mode[0] = mode[1]; + Timing[0] = Timing[1]; + } + + outw(0x0001,DmaIO + DMAMODE); + + outb(mode[0],IOPort1 + BlockCountPort); + if (HddConnected[BoardID][Channel][0]) + { + outb(0xA0,IOPort1 + DriveSelectPort); + outb(IDE_COMMAND_ENABLE_MEDIA_STATUS,IOPort1 + CommandPort); + outw(Timing[0],DmaIO + UDM_TIM); + } + if (HddConnected[BoardID][Channel][1]) + { + outb(0xB0,IOPort1 + DriveSelectPort); + outb(IDE_COMMAND_ENABLE_MEDIA_STATUS,IOPort1 + CommandPort); + outw(Timing[0],DmaIO + UDM_TIM); + } + + statusByte = 0; + mdelay(5); + while(!(statusByte & IDE_STATUS_IDLE)) + { + GetBaseStatus(IOPort1, statusByte); + } + } + + static int IdentifyDisk( + int BoardID, + int Channel, + int DriveSelect, + IDENTIFY_DATA * IdentifyData) + { + ULONG IOPort1,DmaIO,ControlRegister; + UCHAR statusByte; + USHORT *pIdentifyData; + int i, j; + int flag = 0; + + HddConnected[BoardID][Channel][DriveSelect] = 0; + mdelay(100); + + if (Channel == 0) + { + IOPort1 = BoardInfo[BoardID].PrimaryIO; + DmaIO = BoardInfo[BoardID].PrimaryDmaIO; + } + else + { + IOPort1 = BoardInfo[BoardID].SecondaryIO; + DmaIO = BoardInfo[BoardID].SecondaryDmaIO; + } + + ControlRegister = BoardInfo[BoardID].ControlRegister; + + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + + for (i=0;i<100;i++) { + udelay(10); + GetBaseStatus(IOPort1, statusByte); + + if (!(statusByte & 0x80)) + break; + } + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + mdelay(50); + GetBaseStatus(IOPort1, statusByte); + + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + mdelay(50); + GetBaseStatus(IOPort1, statusByte); + + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + mdelay(50); + GetBaseStatus(IOPort1, statusByte); + mdelay(50); + if(statusByte != 0x50) + { + if((statusByte & 0xF0) != 0x50) + return 0; + outb(0x08,IOPort1+CommandPort); + mdelay(100); + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + GetBaseStatus(IOPort1, statusByte); + for(i=0;i<3;i++) + { + mdelay(100); + outb(0x04, IOPort1 + 0x0E); + mdelay(100); + outb(0x00, IOPort1 + 0x0E); + GetBaseStatus(IOPort1, statusByte); + if(statusByte == 0x50) + break; + } + if(i >= 3) + return 0; + } + + + statusByte = statusByte & 0xc9; + + // printk("Identify: After Masking with 0xC9! Status == %x\n", + // statusByte); + + if (statusByte != IDE_STATUS_DRDY) + { + // printk(" ---- Identify: DRDY is NOT asserted!\n"); + // printk(" ---- Identify: return FALSE.\n"); + // printk("IdentifyDisk Fail bd=%d,ch=%d, drv=%d :\n",BoardID,Channel,DriveSelect); + return 0; + } + + + label1: + for (j = 0; j < 2; j++) + { + + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + mdelay(10); + GetBaseStatus(IOPort1, statusByte); + + // printk("Status3 = %x\n", (UCHAR) statusByte); + + WaitOnBusy(IOPort1, statusByte); + outb(IDE_COMMAND_IDENTIFY, IOPort1 + CommandPort); + + for (i = 0; i < 4; i++) + { + WaitForDrq(IOPort1, statusByte); + if (statusByte & IDE_STATUS_DRQ) + { + // Read status to acknowledge any interrupts generated. + GetBaseStatus(IOPort1, statusByte); + break; + } + + WaitOnBusy(IOPort1, statusByte); + } // end of for (i = 0; i < 4; i++) + + if (i == 4 && j == 0) + { + // printk(" ---- Identify: DRQ never asserted (%x). Error reg (%x)\n", + // statusByte, inb(IOPort1 + 1)); + // printk(" ---- Identify: return FALSE.\n"); + return 0; + } else + { + break; + } + } // end of for (j = 0; j < 2; j++) + + + if (statusByte & IDE_STATUS_ERROR) + { + // printk(" ---- Identify: Status %x\n", statusByte); + // printk(" ---- Identify: return FALSE.\n"); + return 0; + } + + WaitOnBusy(IOPort1, statusByte); + + + if (!(statusByte & IDE_STATUS_DRQ)) + { + // printk(" ---- Identify: DRQ is NOT asserted!\n"); + // printk(" ---- Identify: return FALSE.\n"); + return 0; + } + + // DiskPresent |= (1 << (Channel * 2 + DriveSelect + 4)); + pIdentifyData = (USHORT *) IdentifyData; + + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + mdelay(50); + GetBaseStatus(IOPort1, statusByte); + // printk("S3=%02x ", (UCHAR) statusByte); + // printk("IdentifyDisk bd=%d,ch=%d, drv=%d \n",BoardID,Channel,DriveSelect); + for (i = 0; i < 256; i++) + { + pIdentifyData[i] = inw(IOPort1 + DataPort); + } + + // printk("\n"); + + for(i=0; i<256; i++) + { + // printk("%0.4x ",pIdentifyData[i]); + } + // printk("\n"); + + { + char *p,c; + p = (char *) &(IdentifyData->VendorUnique1); + + for (i = 0; i < 26; i+=2) + { + c = p[i]; + p[i] = p[i+1]; + p[i+1] = c; + // printk("[%02x]<%02x>",(unsigned char)p[i],(unsigned char)p[i+1]); + } + // printk("\n"); + + p = (char *) &(IdentifyData->ModelNumber); + + for (i = 0; i < 40; i+=2) + { + c = p[i]; + p[i] = p[i+1]; + p[i+1] = c; + // printk("%c",c); + } + } + HddConnected[BoardID][Channel][DriveSelect] = 1; + SetUDMAMode(BoardID,Channel,DriveSelect,IdentifyData); + + { + int mm = 0; + + for (i = 0; i < 0x1000; i++) + { + + GetStatus(IOPort1, statusByte); + + if ((statusByte & IDE_STATUS_DRQ) + || (statusByte & IDE_STATUS_BUSY) + || (statusByte & 1) ) + { + inw(IOPort1 + DataPort); + } else + break; + } // end of for + } + // printk("IdentifyDisk Success!\n"); + return 1; + } + + char *ultima_info(struct Scsi_Host *ignore) + { + static char buffer[128]; + char *pt; + + // printk("[ ultima_info ]\n"); + strcpy(buffer, "Aralion Ultima ATA100 IDE RAID MultiCard Driver Version"); + if (strchr(VERSION, ':')) + { /* Assume VERSION is an RCS Revision string */ + strcat(buffer, strchr(VERSION, ':') + 1); + pt = strrchr(buffer, '$') - 1; + if (!pt) /* Stripped RCS Revision string? */ + pt = buffer + strlen(buffer) - 1; + if (*pt != ' ') + ++pt; + *pt = '\0'; + } else + { /* Assume VERSION is a number */ + strcat(buffer, " " VERSION); + } + + return buffer; + } + + + + int ultima_ioctl (Scsi_Device *dev, int cmd, void *arg) + { + return 0; + } + + int init_module(void) { + driver_template.module = &__this_module; + scsi_register_module(MODULE_SCSI_HA, &driver_template); + if (driver_template.present) { + return 0; + } + + scsi_unregister_module(MODULE_SCSI_HA, &driver_template); + return -1; + } + + void cleanup_module( void) { + scsi_unregister_module(MODULE_SCSI_HA, &driver_template); + } + /* First pass at /proc information routine. */ + + int ultima_proc_info(char *buffer, char **start, off_t offset, + int length, int hostno, int inout) + { + const char *info = ultima_info(NULL); + int len; + int pos; + int begin; + + if (inout) + return (-ENOSYS); + + begin = 0; + strcpy(buffer, info); + strcat(buffer, "\n"); + + pos = len = strlen(buffer); + + if (pos < offset) + { + len = 0; + begin = pos; + } + + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); + if (len > length) + len = length; + + return (len); + } + + static int aralion_arbitrate(void) + { + int status = 0; + ULONG timeout; + + printk("[ aralion_arbitrate ]\n"); + + return 0; + } + + static int aralion_select(int target) + { + int status; + ULONG timeout; + static int flag = 0; + + + printk("[ aralion_select - %d ]\n",target); + return 0; + } + + static void my_done(int error) + { + if (in_command) + { + in_command = 0; + // printk("{C}"); + if (test_and_clear_bit(IOCTL_LOCK,&LockValue) == 0) + printk("misc clear...\n"); + current_SC->result = error; + if (current_SC->scsi_done) { + current_SC->scsi_done(current_SC); + } + else + panic("scsi: current_SC->scsi_done() == NULL"); + } else + { + panic("scsi: my_done() called outside of command\n"); + } + } + + int CheckScsiError(ULONG Channel,ULONG IOPort1,UCHAR statusByte) + { + ULONG lba; + UCHAR Data[4]; + UCHAR errorByte; + ULONG scsiStatus = 0; + + if (statusByte & 0x1) { + + errorByte = inb(IOPort1 + ErrorPort); + + if (errorByte & IDE_ERROR_BAD_BLOCK) + scsiStatus = DID_PARITY; + else if (errorByte & IDE_ERROR_DATA_ERROR) + scsiStatus = DID_ERROR; + else if (errorByte & IDE_ERROR_ID_NOT_FOUND) + scsiStatus = DID_NO_CONNECT; + else if (errorByte & IDE_ERROR_COMMAND_ABORTED) + scsiStatus = DID_ABORT; + else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH ) + scsiStatus = DID_ERROR; + + Data[3] = inb(IOPort1 + BlockNumberPort); + Data[2] = inb(IOPort1 + CylinderLowPort); + Data[1] = inb(IOPort1 + CylinderHighPort); + Data[0] = inb(IOPort1 + DriveSelectPort) & 0x0f; + + lba = (Data[0] << 24) + (Data[1] << 16) + + (Data[2] << 8) + Data[0]; + + LastErrorBlock = lba; + LastErrorCode = errorByte & 0x000f; + + printk("Error! Ch:%d, %02x , %0d\n",Channel, + (UCHAR) errorByte,lba); + + // my_done(scsiStatus << 16); + return scsiStatus; + } + else + return 0; + } + + void CheckJobFinished(ULONG BoardID,ULONG Channel) + { + ULONG DmaIO; + USHORT Stat; + DWORD i = 0; + + // printk("CheckJobFinished = <%d,%d>\n",BoardID,Channel); + + if (Channel == 1) { + DmaIO = BoardInfo[BoardID].PrimaryDmaIO; + } + else + DmaIO = BoardInfo[BoardID].SecondaryDmaIO; + + do { + Stat = inw(DmaIO + CONSR); + i++; + } while ((Stat & 0x01) && (i < 80000000)); + // printk("Check End : %u\n",i); + } + void ClearAllIrq(void) + { + ULONG Channel; + UCHAR statusByte = 0; + UCHAR statusByte2 = 0; + ULONG IOPort1,IOPort2; + ULONG scsiStatus = 0; + int i; + + for(i=0;i\n"); + + if (!pIntID) { + #ifdef DEBUG + printk("It is not ultima_irq1\n"); + #endif + spin_unlock_irqrestore(&io_request_lock, flags); + return ; + } + + if (gResetFlag) { + for (i=0;iresult; + ++internal_done_flag; + } + + int IsSplitter(char c) + { + if (c == ' ' || c == '-' || c == '_') + return 1; + else if (c >= '0' && c <= '9') + return 1; + + return 0; + } + + int ultima_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) + { + char *buf; + int board,channel,drive; + ULONG result; + /* + printk("[c=%x : %s,I=%x],DiskCount = %d\n", + (UCHAR) SCpnt->cmnd[0], + GetCmdName((UCHAR) SCpnt->cmnd[0]), + SCpnt->target, + DiskCount); + */ + if (in_command) { + printk("[ ultima_queue c=%x : %s,I=%x]\n", + (UCHAR) SCpnt->cmnd[0], + GetCmdName((UCHAR) SCpnt->cmnd[0]), + SCpnt->target); + panic("Error! in_command == 1\n"); + return ; + } + + while(test_and_set_bit(IOCTL_LOCK,&LockValue) != 0) { + printk("QW "); + schedule(); + udelay(1); + } + while(in_ioctl) { + // printk("in_ioctl = 1\n"); + udelay(1); + } + in_command = 1; + current_SC = SCpnt; + current_SC->scsi_done = done; + + current_SC->SCp.Status = 0; + current_SC->SCp.Message = 0; + current_SC->SCp.have_data_in = 0; + current_SC->SCp.sent_command = 0; + current_SC->SCp.phase = in_arbitration; + + if ( SCpnt->lun > 0) { + my_done(DID_ABORT << 16); + return 0; + } + board = DiskID[current_SC->target].DiskStatus.BoardID; + channel = DiskID[current_SC->target].DiskStatus.Channel; + drive = DiskID[current_SC->target].DiskStatus.Drive; + + + switch(current_SC->cmnd[0]) { + case TEST_UNIT_READY: + case REQUEST_SENSE : + my_done(0); + return 0; + + case MODE_SENSE : + buf = (char *) current_SC->buffer; + buf[2] = 0x0; + my_done(0); + break; + + case INQUIRY : + if(hotplug_check(current_SC->target) == 0) + { + my_done(DID_ABORT << 16); + return 0; + } + + board = DiskID[current_SC->target].DiskStatus.BoardID; + channel = DiskID[current_SC->target].DiskStatus.Channel; + drive = DiskID[current_SC->target].DiskStatus.Drive; + buf = (char *) current_SC->buffer; + { + PINQUIRYDATA inquiryData + = (PINQUIRYDATA) current_SC->buffer; + PIDENTIFY_DATA identifyData = + &DiskIdentifyData[board][channel][drive]; + int i; + + memset(buf,0,current_SC->bufflen); + + buf[4] = sizeof(INQUIRYDATA); + + // + // Standard IDE interface only supports disks. + inquiryData->DeviceType = DIRECT_ACCESS_DEVICE; + + // + // Fill in vendor identification fields. + { + unsigned char *p; + int i,j; + + for (i = 0; i < 24; i ++) { + inquiryData->VendorId[i] = 0; + } + p = (UCHAR *) identifyData->ModelNumber; + i = 0; + + while(!IsSplitter(p[i])) { + inquiryData->VendorId[i] = p[i++]; + } + inquiryData->VendorId[i] = 0; + + i++; + j = 0; + while (p[i] != ' ' && i < 24) + inquiryData->ProductId[j++] = p[i++]; + inquiryData->ProductId[j] = 0; + + } + // + // Initialize unused portion of product id. + for (i = 0; i < 4; i++) { + inquiryData->ProductId[12+i] = ' '; + } + + // + // Move firmware revision from IDENTIFY data to + // product revision in INQUIRY data. + for (i = 0; i < 4; i += 2) { + inquiryData->ProductRevisionLevel[i] = + ((UCHAR *)identifyData->FirmwareRevision)[i+1]; + inquiryData->ProductRevisionLevel[i+1] = + ((UCHAR *)identifyData->FirmwareRevision)[i]; + } + } + // printk("Inquiry Success!"); + my_done(0); + break; + case READ_6 : + case READ_10 : + case WRITE_6 : + case WRITE_10 : + + { + ULONG numsectors,lba,i ; + + // SDptr->disconnect = 0; + if (*current_SC->cmnd == READ_6 || *current_SC->cmnd == WRITE_6) { + numsectors = (u_long) current_SC->cmnd[4]; + lba = ((u_long) current_SC->cmnd[1] << 16) | + ((u_long) current_SC->cmnd[2] << 8) | + (u_long) current_SC->cmnd[3]; + lba &= 0x1FFFFF; + } + if (*current_SC->cmnd == READ_10 || *current_SC->cmnd == WRITE_10) { + numsectors = (u_long) current_SC->cmnd[8] | + ((u_long) current_SC->cmnd[7] << 8); + lba = ((u_long) current_SC->cmnd[2] << 24) | + ((u_long) current_SC->cmnd[3] << 16) | + ((u_long) current_SC->cmnd[4] << 8) | + (u_long) current_SC->cmnd[5]; + } + + memset(DiskRWInfo,0,sizeof(DiskRWInfo)); + for(i=0;itarget; + + if (*current_SC->cmnd == READ_6 || *current_SC->cmnd == READ_10) { + + // printk("R:[%03d,%08x]", numsectors,lba); + ReadDMA(current_SC,lba,numsectors); + } + else { + // printk("W:[%03d,%08x]", numsectors,lba); + WriteDMA(current_SC,lba,numsectors); + } + } + // printk("RW Success!\n"); + break; + + case READ_CAPACITY : + { + ULONG block,size; + IDENTIFY_DATA * IdentifyData; + + block = DiskID[current_SC->target].DiskStatus.Size; + // printk("Block Size = %x\n",block); + buf = (char *) current_SC->buffer; + size = 512; + + *((ULONG *) buf) = htonl(block - 1); + *((ULONG *) (buf + 4)) = htonl(size); + } + + my_done(0); + // printk("Read_Cap Success!\n"); + break; + default: + my_done(0); + break; + + } + return 0; + } + + + void FillDump( Scsi_Cmnd * SCpnt) + { + struct scatterlist *slp; + int i,j; + ULONG TempFlag; + + if (SCpnt->use_sg) + { + slp = (struct scatterlist *) SCpnt->request_buffer; + for(i=0;iuse_sg;i++,slp++) { + memset(&(slp->address),0,slp->length); + } + } + else + { + memset(&(slp->address),0,SCpnt->request_bufflen); + } + } + + int hotplug_check(int target) + { + int i, j, k; + UCHAR statusByte; + ULONG IOPort1; + // printk("targetID=%d, DiskCount=%d\n",target,DiskCount); + if(target == DiskCount) + { + for(i=0;ihost) + { + printk("scsi: Cannot provide detailed information\n"); + return; + } + + printk("%s\n", ultima_info(SCpnt->host)); + return ; + print_banner(SCpnt->host); + + printk("(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", + SCpnt->SCp.phase, + SCpnt->target, + *(UCHAR *) SCpnt->cmnd, + SCpnt->use_sg, SCpnt->request_bufflen); + printk("sent_command = %d, have_data_in = %d, timeout = %d\n", + SCpnt->SCp.sent_command, + SCpnt->SCp.have_data_in, SCpnt->timeout); + } + + int ultima_handle(Scsi_Cmnd * SCpnt) + { + // printk("\n"); + } + + int ultima_abort(Scsi_Cmnd * SCpnt) + { + ULONG flags; + + // printk("ultima_abort ---- \n"); + if (!in_command) + { + return SCSI_ABORT_NOT_RUNNING; + } + ultima_cardreset(); + + //#if DEBUG + print_info(SCpnt); + //#endif + + current_SC->SCp.phase |= aborted; + + current_SC->result = DID_ABORT << 16; + // current_SC->result = DID_BUS_BUSY << 16; + + /* Aborts are not done well. . . */ + if (in_command) + my_done(DID_ABORT << 16); + // my_done(DID_BUS_BUSY << 16); + + return SCSI_ABORT_SUCCESS; + } + + int ultima_reset(Scsi_Cmnd * SCpnt, unsigned int ignored) + { + // printk("ultima_reset ---- \n"); + ultima_cardreset(); + + return SCSI_RESET_WAKEUP; + } + + // + // KHG-20020719 + // + + int ultima_1channelreset(int BoardID, int Channel) + { + int i; + UCHAR statusByte,statusByte2; + // printk("%d board reset\n",BoardID); + if(Channel == 0) + { + outw(0x8000,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x4000,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x0,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0xff8f,BoardInfo[BoardID].ControlRegister + 0x0c); + /* + for (i=0;i<200;i++) + { + mdelay(5); + outb(0xA0, BoardInfo[BoardID].PrimaryIO + DriveSelectPort); + GetBaseStatus(BoardInfo[BoardID].PrimaryIO, statusByte); + outb(0xB0, BoardInfo[BoardID].PrimaryIO + DriveSelectPort); + GetBaseStatus(BoardInfo[BoardID].PrimaryIO, statusByte2); + if (!(statusByte & 0x80) && !(statusByte2 & 0x80)) + break; + } + */ + } + else + { + outw(0x8000,BoardInfo[BoardID].SecondaryDmaIO + 0x0e); + mdelay(20); + outw(0x4000,BoardInfo[BoardID].SecondaryDmaIO + 0x0e); + mdelay(20); + outw(0x0,BoardInfo[BoardID].SecondaryDmaIO + 0x0e); + mdelay(20); + outw(0xff8f,BoardInfo[BoardID].ControlRegister + 0x0e); + /* + for (i=0;i<200;i++) + { + mdelay(5); + outb(0xA0, BoardInfo[BoardID].SecondaryIO + DriveSelectPort); + GetBaseStatus(BoardInfo[BoardID].SecondaryIO, statusByte); + outb(0xB0, BoardInfo[BoardID].SecondaryIO + DriveSelectPort); + GetBaseStatus(BoardInfo[BoardID].SecondaryIO, statusByte2); + if (!(statusByte & 0x80) && !(statusByte2 & 0x80)) + break; + } + */ + } + for(i=0;i<125;i++) + { + mdelay(10); + } + } + + int ultima_1cardreset(int BoardID) + { + int i,j; + UCHAR statusByte,statusByte2; + UCHAR statusByte3,statusByte4; + + mdelay(20); + outw(0x8000,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x4000,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x0,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x8000,BoardInfo[BoardID].SecondaryDmaIO + 0x0e); + mdelay(20); + outw(0x4000,BoardInfo[BoardID].SecondaryDmaIO + 0x0e); + mdelay(20); + outw(0x0,BoardInfo[BoardID].SecondaryDmaIO + 0x0e); + for(i=0;i<125;i++) + { + mdelay(20); + } + } + + + int ultima_cardreset(void) + { + int i,j,k; + + RWStatus = RESET_STATUS; + // printk("ultima cardreset\n"); + gResetFlag = 1; + for(i=0;i> 4; + // printk("BiosParam = %d,%d\n",board,channel); + + info_array[0] = 16; + info_array[1] = 63; + + // size = info_array[0] * info_array[1] * info_array[2]; + + size = DiskID[target].DiskStatus.Size; + info_array[2] = size / (info_array[0] * info_array[1]); + + if (info_array[2] > 1024) { + info_array[0] = 0xff; + info_array[2] = + (ULONG) size / (info_array[0] * info_array[1]); + } + + return 0; + } + diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/ultima.h linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/ultima.h *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid100/ultima.h 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid100/ultima.h 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,248 ---- + #ifndef _ULTIMA_H + #define _ULTIMA_H + + #ifndef UCHAR + #define UCHAR unsigned char + #define USHORT unsigned short + #define ULONG unsigned long + #define DWORD unsigned long + #define BYTE unsigned char + #define WORD unsigned short + #endif + + #define ARALION_VENDOR 0x1538 + #define ULTIMA_DEVICE 0x0301 + + #define READ_STATUS 0x10000000 + #define WRITE_STATUS 0x20000000 + #define RESET_STATUS 0x40000000 + #define REBUILD_STATUS 0x80000000 + #define MIRRORWRITE_STATUS 0x01000000 + /* + #define ORDER_FIRST 0x00000001 + #define ORDER_LAST 0x00000010 + */ + + #define ORDER_ONE 0x00000001 + #define ORDER_TWO 0x00000010 + #define ORDER_THREE 0x00000100 + #define ORDER_FOUR 0x00001000 + + + #define DataPort 0x00 + #define ErrorPort 0x01 + #define BlockCountPort 0x02 + #define BlockNumberPort 0x03 + #define CylinderLowPort 0x04 + #define CylinderHighPort 0x05 + #define DriveSelectPort 0x06 + #define CommandPort 0x07 + #define AlternateStatusPort 0x0E + + #define FLASH_ADDRESS 0x02 + #define FLASH_COMMAND 0x04 + #define FLASH_STATUS 0x06 + + #define SCATTERLISTSIZE 4096 + + #define NODISK 0x00000000 + #define NORMALIDE 0x00000001 + #define STRIPING_2S 0x00000002 + #define STRIPING_4S 0x00000003 + #define MIRRORING 0x00000004 + #define STRIPMIRRORING_2S 0x00000005 + #define STRIPMIRRORING_4S 0x00000006 + #define JBOD 0x00000007 + //#define STRIPMIRRORING2 + + #define NOTAVAILABLE 0x0000ffff + #define ERROR_INVALID_SECTORCOUNT 0x00000001 + #define ERROR_DISK_NOTAVAILABLE 0x00000002 + #define ERROR_INVALID_CHANNEL 0x00000003 + + #define MAXBOARD 4 + + #define NORMALSTATUS 0x00000000 + #define DISKSWAPPED 0x00000001 + #define MIRRORDISABLED 0x00000002 + #define REBUILDING 0x00000010 + #define REBUILDED 0x00000020 + #define DISKNOTAVAILABLE 0x80000000 + + extern int ultima_detect( Scsi_Host_Template * ); + extern int ultima_release( struct Scsi_Host * tpnt); + extern int ultima_command( Scsi_Cmnd * ); + extern int ultima_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); + extern int ultima_abort( Scsi_Cmnd * ); + extern int ultima_reset( Scsi_Cmnd *, unsigned int ); + extern int ultima_biosparam( Disk *, kdev_t, int * ); + extern int ultima_handle( Scsi_Cmnd * ); + extern char * ultima_info( struct Scsi_Host * ); + extern int ultima_cardreset(void); + extern int ultima_proc_info( char *buffer, char **start, off_t offset, + int length, int hostno, int inout ); + extern int ultima_ioctl(Scsi_Device *dev, int cmd, void *arg); + + extern struct proc_dir_entry proc_scsi_aralion; + + #define ULTIMA_REVID "Aralion ATA133 IDE Raid Controller driver; Revision: LH1.00BCS" + + #define ULTIMA_DMA100 { \ + next: NULL, \ + module: NULL, \ + proc_dir: NULL, \ + proc_name: "Aralion", \ + proc_info: ultima_proc_info, \ + name: "Ultima RAID 100", \ + detect: ultima_detect, \ + release: ultima_release, \ + info : NULL, \ + ioctl: ultima_ioctl, \ + command: NULL, \ + queuecommand: ultima_queue, \ + abort: ultima_abort, \ + reset: ultima_reset, \ + slave_attach: NULL, \ + bios_param: ultima_biosparam, \ + can_queue: 1, \ + this_id: 15, \ + present: 0, \ + sg_tablesize: 16, \ + cmd_per_lun: 0, /* cmds per lun */\ + use_clustering: DISABLE_CLUSTERING, \ + use_new_eh_code: 0}; + + typedef struct + { + char *buffer; + unsigned long bufferlen; + } IoctlParam; + + typedef struct + { + char signature[8]; + unsigned long IOPort1; + unsigned long irq; + } IrqID; + + typedef struct { + DWORD BoardID; + DWORD Channel; + DWORD Drive; + DWORD Size; + } DISKLIST; + + typedef struct { + DWORD RaidStatus; + DWORD BlockSize; + DISKLIST DiskStatus; + } _DiskIDTable; + + typedef struct _PDT_TABLE { + ULONG address; + USHORT length; + UCHAR Reserved; + UCHAR EndOfChain; + } PDT_TABLE, *PPDT_TABLE; + + typedef struct + { + PDT_TABLE ScatterList[128]; + ULONG ListCount; + ULONG NumSectors; + ULONG StartLba; + ULONG InterruptFlag; + } DISKRWINFO; + + typedef struct _BOARDTABLE { + ULONG PrimaryIO; + ULONG SecondaryIO; + ULONG PrimaryDmaIO; + ULONG SecondaryDmaIO; + ULONG ControlRegister; + ULONG FlashMemory; + ULONG interrupt_level; + + PPDT_TABLE PriScatterList; + PPDT_TABLE SecScatterList; + + ULONG ListCount; + ULONG NumSectors; + ULONG StartLba; + ULONG InterruptFlag[2]; + } BOARDTABLE,*PBOARDsTABLE; + + typedef struct _V6BDISKINFO + { + UCHAR Mode; + UCHAR PhysicalDrive; + UCHAR Order; + }V6BDISKINFO,*PV6BDISK; + + typedef struct _V6InterfaceB + { + ULONG TagField; + USHORT Version; + UCHAR Reserved; + UCHAR StructSize; + USHORT RebuildBit; + UCHAR Mode; + UCHAR IsSafeMode; + ULONG Reserved1; + ULONG BaseHddSize[8]; + V6BDISKINFO DiskInfo[4][4]; + UCHAR Reserved2[5]; + UCHAR ProcInfo[4]; + UCHAR Reserved3[151]; + }V6INTERFACEB,*PV6INTERFACEB; + + typedef struct _REBUILDBUFFER + { + UCHAR *buffer; + ULONG physicalbuffer; + } REBUILDBUFFER; + + + #define GetStatus(BaseIoAddress, Status) Status = inb((BaseIoAddress) + AlternateStatusPort); + + #define GetBaseStatus(BaseIoAddress, Status) \ + Status = inb(BaseIoAddress + CommandPort); + + #define Delayed_Time(delay) { \ + ULONG j = jiffies + delay * HZ; \ + struct wait_queue *wait = NULL; \ + current->timeout = j; \ + interruptible_sleep_on(&wait); } + + #define WaitOnBusy(BaseIoAddress, Status) {ULONG i; \ + for (i=0; i<5; i++) { \ + GetStatus((BaseIoAddress), Status); \ + if (Status & IDE_STATUS_BUSY) { \ + udelay(1); \ + continue; \ + } else { \ + break; \ + } \ + } \ + } + + #define WaitForDrq(BaseIoAddress, Status) \ + { \ + ULONG i; \ + for (i=0; i<1000; i++) { \ + GetStatus(BaseIoAddress, Status); \ + if (Status & IDE_STATUS_BUSY) { \ + udelay(150); \ + } else if (Status & IDE_STATUS_DRQ) { \ + break; \ + } else { \ + udelay(200); \ + } \ + } \ + } + + #endif + + #define SelectFirstChannel(BoardID) outb(0xA0,BoardInfo[BoardID].SecondaryIO+DriveSelectPort); + #define SelectSecondChannel(BoardID) outb(0xB0,BoardInfo[BoardID].SecondaryIO+DriveSelectPort); + diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/Makefile linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/Makefile *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/Makefile 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/Makefile 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,16 ---- + # File: drivers/ultimaraid133/Makefile + # Makefile for the Ultima RAID 133 PCI controllers driver. + + list-multi := ultimaraid133.o + ultima133-objs := ultima.o + obj-$(CONFIG_SCSI_ULTIMARAID133) := ultimaraid133.o + + EXTRA_CFLAGS += -I. + + ultimaraid133.o: $(ultima133-objs) + $(LD) -r -o $@ $(ultima133-objs) + + include $(TOPDIR)/Rules.make + + clean: + rm -f *.o diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/README linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/README *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/README 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/README 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,25 ---- + Ultima RAID 133 Driver for Linux + + Introduction + ------------------------- + Original Driver was supported by Aralion(http://www.aralion.co.kr) + + Supported Cards/Chipsets + ------------------------- + Ultima RAID 133(ARS0303S) + + People + ------------------------- + Aralion Linux Dev. (Original ATA ONLY Driver source) + Ashuaria Lee (Patch for Linux Kernel Tree) + + Original Driver + ------------------------- + Aralion Linux Development + + Mailing List + ------------------------- + mailto:aralion0303-user@lists.kldp.net + mailto:aralion0303-news@lists.kldp.net + mailto:aralion0303-develop@lists.kldp.net + mailto:aralion0303-tester@lists.kldp.net diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/TODO linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/TODO *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/TODO 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/TODO 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,3 ---- + o Testing + o More testing + o Many more diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/atapi.h linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/atapi.h *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/atapi.h 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/atapi.h 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,300 ---- + #ifndef _ATAPI_H + #define _ATAPI_H + + #ifndef UCHAR + #define UCHAR unsigned char + #define USHORT unsigned short + #define ULONG unsigned long + #endif + + #define IDE_STATUS_ERROR 0x01 + #define IDE_STATUS_INDEX 0x02 + #define IDE_STATUS_CORRECTED_ERROR 0x04 + #define IDE_STATUS_DRQ 0x08 + #define IDE_STATUS_DSC 0x10 + #define IDE_STATUS_DRDY 0x40 + #define IDE_STATUS_IDLE 0x50 + #define IDE_STATUS_BUSY 0x80 + + + #define IDE_ERROR_BAD_BLOCK 0x80 // ICRC :Crc error + #define IDE_ERROR_DATA_ERROR 0x40 // UNC :data error + #define IDE_ERROR_MEDIA_CHANGE 0x20 + #define IDE_ERROR_ID_NOT_FOUND 0x10 // IDNF :sector's ID field error + #define IDE_ERROR_MEDIA_CHANGE_REQ 0x08 + #define IDE_ERROR_COMMAND_ABORTED 0x04 // ABRT :command error + #define IDE_ERROR_END_OF_MEDIA 0x02 + #define IDE_ERROR_ILLEGAL_LENGTH 0x01 + // + // IDE command definitions + // + #define IDE_COMMAND_ATAPI_RESET 0x08 // Don't use! + #define IDE_COMMAND_RECALIBRATE 0x10 + #define IDE_COMMAND_READ 0x20 // <--- + #define IDE_COMMAND_WRITE 0x30 // <--- + #define IDE_COMMAND_VERIFY 0x40 // <--- + #define IDE_COMMAND_SEEK 0x70 + #define IDE_COMMAND_SET_DRIVE_PARAMETERS 0x91 + #define IDE_COMMAND_ATAPI_PACKET 0xA0 // Don't use! + #define IDE_COMMAND_ATAPI_IDENTIFY 0xA1 // Don't use! + #define IDE_COMMAND_READ_MULTIPLE 0xC4 // <--- + #define IDE_COMMAND_WRITE_MULTIPLE 0xC5 // <--- + #define IDE_COMMAND_SET_MULTIPLE 0xC6 + #define IDE_COMMAND_READ_DMA 0xC8 // <--- + #define IDE_COMMAND_WRITE_DMA 0xCA // <--- + #define IDE_COMMAND_GET_MEDIA_STATUS 0xDA + #define IDE_COMMAND_ENABLE_MEDIA_STATUS 0xEF // Feature Set + #define IDE_COMMAND_IDENTIFY 0xEC // <--- + #define IDE_COMMAND_MEDIA_EJECT 0xED + + + //////////////////////////////////KHG133s_Big////////////////////////////////////// + #define IDE_COMMAND_READ_DMA_EXT 0x25 + #define IDE_COMMAND_WRITE_DMA_EXT 0x35 + #define IDE_COMMAND_READ_SECTORS 0x20 + #define IDE_COMMAND_WRITE_SECTORS 0x30 + #define IDE_COMMAND_READ_SECTORS_EXT 0x24 + #define IDE_COMMAND_WRITE_SECTORS_EXT 0x34 + /////////////////////////////////////////////////////////////////////////////////// + // + //DmaCommand bits definition + // + #define DMA_READ 0x07 + #define DMA_WRITE 0x06 + + // + // Mode Register bit definotion + // + #define MODE_PIO 0x00 + #define MODE_DMA 0x01 + #define MODE_UDMA 0x03 + + // + // HDD DMA Mode Support + // + #define DMA_0 0x01 + #define DMA_1 0x03 + #define DMA_2 0x07 + #define UDMA_0 0x08 + #define UDMA_1 0x18 + #define UDMA_2 0x38 + + // + // Multiple sector setting is valid by HBA. + // + #define MULTIPLE_SET 0x0100 + + // + // Device Extension Device Flags + // + #define DFLAGS_DEVICE_PRESENT 0x0001 // Indicates that some device is present. + #define DFLAGS_DMA_DEVICE 0x0002 // Device is a DMA or UDMA device. + #define DFLAGS_PIO_DEVICE 0x0004 // Device is a PIO device. + + // + // Used to disable 'advanced' features. + // + #define MAX_ERRORS 4 // FOR IDE ERROR in MapError() + + #ifdef XXX + typedef struct _IDENTIFY_DATA { + USHORT GeneralConfiguration; // 00 00 + USHORT NumberOfCylinders; // 02 1 + USHORT Reserved1; // 04 2 + USHORT NumberOfHeads; // 06 3 + USHORT UnformattedBytesPerTrack; // 08 4 + USHORT UnformattedBytesPerSector; // 0A 5 + USHORT SectorsPerTrack; // 0C 6 + USHORT VendorUnique1[3]; // 0E 7-9 + USHORT SerialNumber[10]; // 14 10-19 + USHORT BufferType; // 28 20 + USHORT BufferSectorSize; // 2A 21 + USHORT NumberOfEccBytes; // 2C 22 + USHORT FirmwareRevision[4]; // 2E 23-26 + USHORT ModelNumber[20]; // 36 27-46 + UCHAR MaximumBlockTransfer; // 5E 47 + UCHAR VendorUnique2; // 5F + USHORT DoubleWordIo; // 60 48 + USHORT Capabilities; // 62 49 + USHORT Reserved2; // 64 50 + UCHAR VendorUnique3; // 66 51 + UCHAR PioCycleTimingMode; // 67 + UCHAR VendorUnique4; // 68 52 + UCHAR DmaCycleTimingMode; // 69 + USHORT TranslationFieldsValid:1; // 6A 53 + USHORT Reserved3:15; + USHORT NumberOfCurrentCylinders; // 6C 54 + USHORT NumberOfCurrentHeads; // 6E 55 + USHORT CurrentSectorsPerTrack; // 70 56 + ULONG CurrentSectorCapacity; // 72 57-58 + USHORT CurrentMultiSectorSetting; // 59 + ULONG UserAddressableSectors; // 60-61 + USHORT SingleWordDMASupport : 8; // 62 + USHORT SingleWordDMAActive : 8; + USHORT MultiWordDMASupport : 8; // 63 + USHORT MultiWordDMAActive : 8; + USHORT AdvancedPIOModes : 8; // 64 + USHORT Reserved4 : 8; + USHORT MinimumMWXferCycleTime; // 65 + USHORT RecommendedMWXferCycleTime; // 66 + USHORT MinimumPIOCycleTime; // 67 + USHORT MinimumPIOCycleTimeIORDY; // 68 + USHORT Reserved5[2]; // 69-70 + USHORT ReleaseTimeOverlapped; // 71 + USHORT ReleaseTimeServiceCommand; // 72 + USHORT MajorRevision; // 73 + USHORT MinorRevision; // 74 + USHORT Reserved6[11]; // 75-126 + USHORT DmaMode[6]; + USHORT Reserved7[33]; // 75-126 + USHORT SpecialFunctionsEnabled; // 127 + USHORT Reserved8[128]; // 128-255 + } IDENTIFY_DATA, *PIDENTIFY_DATA; + #endif + + // + // IDENTIFY data + // + typedef struct _IDENTIFY_DATA { + USHORT GeneralConfiguration; // 00 00 + USHORT NumberOfCylinders; // 02 1 + USHORT Reserved1; // 04 2 + USHORT NumberOfHeads; // 06 3 + USHORT UnformattedBytesPerTrack; // 08 4 + USHORT UnformattedBytesPerSector; // 0A 5 + USHORT SectorsPerTrack; // 0C 6 + USHORT VendorUnique1[3]; // 0E 7-9 + USHORT SerialNumber[10]; // 14 10-19 + USHORT BufferType; // 28 20 + USHORT BufferSectorSize; // 2A 21 + USHORT NumberOfEccBytes; // 2C 22 + USHORT FirmwareRevision[4]; // 2E 23-26 + USHORT ModelNumber[20]; // 36 27-46 + UCHAR MaximumBlockTransfer; // 5E 47 + UCHAR VendorUnique2; // 5F + USHORT DoubleWordIo; // 60 48 + USHORT Capabilities; // 62 49 + USHORT Reserved2; // 64 50 + UCHAR VendorUnique3; // 66 51 + UCHAR PioCycleTimingMode; // 67 + UCHAR VendorUnique4; // 68 52 + UCHAR DmaCycleTimingMode; // 69 + + UCHAR TranslationFieldsValid; // 6A 53 + UCHAR Reserved3; + /* + USHORT TranslationFieldsValid:3; // 6A 53 + USHORT Reserved3:13; + */ + + USHORT NumberOfCurrentCylinders; // 6C 54 + USHORT NumberOfCurrentHeads; // 6E 55 + USHORT CurrentSectorsPerTrack; // 70 56 + USHORT CurrentSectorCapacity[2]; // 72 57-58 + + /////// Out of spec! //////////// + USHORT CurrentMultiSectorSetting; // 59 + USHORT UserAddressableSectors[2]; // 60-61 + + UCHAR SingleWordDMASupport; // 62 Low + UCHAR SingleWordDMAActive; // High + /* + USHORT SingleWordDMASupport:8; // 62 Low + USHORT SingleWordDMAActive:8; // High + */ + + UCHAR MultiWordDMASupport; // 63 Low + UCHAR MultiWordDMAActive; // High + /* + USHORT MultiWordDMASupport:3; // 63 Low + USHORT MultiWordDMAActive:13; // High + */ + + UCHAR AdvancedPIOModes; // 64 + UCHAR Reserved4; + /* + USHORT AdvancedPIOModes:8; // 64 + USHORT Reserved4:8; + */ + + USHORT MinimumMWXferCycleTime; // 65 + USHORT RecommendedMWXferCycleTime; // 66 + USHORT MinimumPIOCycleTime; // 67 + USHORT MinimumPIOCycleTimeIORDY; // 68 + USHORT Reserved5[2]; // 69-70 + USHORT ReleaseTimeOverlapped; // 71 + USHORT ReleaseTimeServiceCommand; // 72 + USHORT MajorRevision; // 73 + USHORT MinorRevision; // 74 + + //////////////////////////////////KHG-133s_Big//////////////////////////////// + USHORT Reserved6[8]; // 75-82 + USHORT BIT48; // 83 + USHORT Reserved6_1[4]; // 84-87 + ////////////////////////////////////////////////////////////////////////////// + + UCHAR UDMASupport; // 88 + UCHAR UDMASelected; // + /* + USHORT UDMASupport:3; // 88 + USHORT UDMASelected:13; // + */ + + USHORT Reserved7[38]; // 89-126 + USHORT SpecialFunctionsEnabled; // 127 + USHORT Reserved8[128]; // 128-255 + } IDENTIFY_DATA, *PIDENTIFY_DATA; + typedef struct _INQUIRYDATA { + UCHAR DeviceType : 5; + UCHAR DeviceTypeQualifier : 3; + UCHAR DeviceTypeModifier : 7; + UCHAR RemovableMedia : 1; + UCHAR Versions; + UCHAR ResponseDataFormat; + UCHAR AdditionalLength; + UCHAR Reserved[2]; + UCHAR SoftReset : 1; + UCHAR CommandQueue : 1; + UCHAR Reserved2 : 1; + UCHAR LinkedCommands : 1; + UCHAR Synchronous : 1; + UCHAR Wide16Bit : 1; + UCHAR Wide32Bit : 1; + UCHAR RelativeAddressing : 1; + UCHAR VendorId[8]; + UCHAR ProductId[16]; + UCHAR ProductRevisionLevel[4]; + UCHAR VendorSpecific[20]; + UCHAR Reserved3[40]; + } INQUIRYDATA, *PINQUIRYDATA; + + #define DIRECT_ACCESS_DEVICE 0x00 // disks + #define SEQUENTIAL_ACCESS_DEVICE 0x01 // tapes + #define PRINTER_DEVICE 0x02 // printers + #define PROCESSOR_DEVICE 0x03 // scanners, printers, etc + #define WRITE_ONCE_READ_MULTIPLE_DEVICE 0x04 // worms + #define READ_ONLY_DIRECT_ACCESS_DEVICE 0x05 // cdroms + #define SCANNER_DEVICE 0x06 // scanners + #define OPTICAL_DEVICE 0x07 // optical disks + #define MEDIUM_CHANGER 0x08 // jukebox + #define COMMUNICATION_DEVICE 0x09 // network + #define LOGICAL_UNIT_NOT_PRESENT_DEVICE 0x7F + #define DEVICE_QUALIFIER_NOT_SUPPORTED 0x03 + + #define PDTLAR 0X00 + #define PDTHAR 0x02 + #define CMDR 0x04 + #define DMAMODE 0x06 + #define PIO_TIM 0x08 + #define MDM_TIM 0x0a + #define UDM_TIM 0x0c + #define CONSR 0x0e + + #define INTSRC 0x00 + #define CBL_ID 0x02 + #define INTENA 0x04 + #define RAIDSTAT 0x06 + + #endif + + diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/flash.h linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/flash.h *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/flash.h 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/flash.h 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,64 ---- + #ifndef __FLASH_H__ + #define __FLASH_H__ + + #define VID 0x1538 + #define DID133 0x0303 + #define DID100 0x0301 + + #define F_DATA F_BASE + 0 + #define F_ADDR F_BASE + 2 + #define F_CMDR F_BASE + 4 + #define F_STAT F_BASE + 6 + + #define FCMD_RD 0x86 + #define FCMD_WR 0x87 + + #define FST_SIG 0xAA + #define SND_SIG 0x55 + #define TRD_SIG 0xA0 + #define FTH_SIG 0xf0 + + #define FST_ADR 0x0555 /*0x5555 */ + #define SND_ADR 0x0AAA /*0x2aaa */ + #define TRD_ADR 0x0555 + + #define SECTORCNT 512 + #define BUFFERCNT 128 + + #define MXMANUFAC 0xC2 + #define MXDEVIC 0x19 /* 29F001B */ + #define MXDEVIC1 0x18 /* 29F001T */ + + #define SMMANUFAC 0x40 + #define SMDEVIC 0x01 /* F295001T */ + #define SMDEVIC1 0xA1 /* F295001B */ /* must be lock or unlock */ + + #define AMICMANUFAC 0x37 + #define AMICDEVICE 0xa1 + //#define AMICDEVICE 0xa1 + + #define MPFMANUFAC 0xbf + #define MPFDEVICE1 0xb6 /*SST39SF020A*/ + #define MPFDEVICE 0xb5 /*SST39SF010*/ + + #define AMDMANUFAC 0x01 + #define AMDDEVICE 0x20 /* AM29F010B */ + + + #define ATMANUFAC 0x1F + #define ATDEVIC 0x5D /* AT29C512 */ + #define ATDEVIC1 0x3D /* AT29LV512 */ + #define ATDEVIC2 0xD5 /* AT29C001 */ + #define ATDEVIC3 0x35 /* AT29LV001 */ + #define ATDEVIC4 0xDC /* AT29C256 */ + + #define WIMANUFAC 0xDA + #define WIDEVIC 0xc8 /* W29C512 */ + #define WIDEVIC1 0xC1 /* W29C010 */ + #define WIDEVIC2 0x45 /* W29C020 */ + + #define RAIDTYPE 0x06 + #define CARDCOUNT 0X08 + + #endif + diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/iocontrol.h linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/iocontrol.h *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/iocontrol.h 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/iocontrol.h 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,146 ---- + ///////////////////////// Ioctl start + /* IoControl.h */ + /* + This header is defined for RAID monitor Util and + should be shared with the App's header. + */ + + // REQUESTs to ULTIMA from GUI. + #define IOCTL_ULTIMA_PRESENT 0x80018001 // ~ ~ ~ ~ 1000 0000 0000 0001 + #define IOCTL_GET_ULTIMA_STATUS 0x80018002 // ~ ~ ~ ~ 1000 0000 0000 0010 + #define IOCTL_EXECUTIVE_COMMAND 0x80018004 // ~ ~ ~ ~ 1000 0000 0000 0100 + #define IOCTL_GET_HDD_FLAGS 0x80018008 // ~ ~ ~ ~ 1000 0000 0000 1000 + #define IOCTL_ULTIMA_RESET 0x80018010 // ~ ~ ~ ~ 1000 0000 0001 0000 + #define IOCTL_GET_ERROR_STATUS 0x80018020 // ~ ~ ~ ~ 1000 0000 0010 0000 + #define IOCTL_UPDATE_IDENTIFY 0x80018040 // ~ ~ ~ ~ 1000 0000 0010 0000 ~~ 2000/06/20 + #define IOCTL_ULTIMA_REBUILD_COMPLETE 0x80018080 // ~~2000/08/02 + #define IOCTL_ULTIMA_REBUILD_CANCEL 0x80018100 // ~~2000/08/11 + #define IOCTL_ULTIMA_MOVE_DATA 0x80018101 // ~~2000/08/11 + #define IOCTL_FLASH_READ 0x80018200 // ~~2000/08/11 + #define IOCTL_FLASH_WRITE 0x80018400 // ~~2000/08/11 + #define IOCTL_TEST_EVENT 0x80018800 + + + typedef struct _SRB_IO_CONTROL { + ULONG HeaderLength; + UCHAR Signature[8]; + ULONG Timeout; + ULONG ControlCode; + ULONG ReturnCode; + ULONG Length; + } SRB_IO_CONTROL, *PSRB_IO_CONTROL; + + typedef struct _SRB_BUFFER { + SRB_IO_CONTROL sic; + UCHAR ucDataBuffer[512]; // Extended DATA BUFFER + } SRB_BUFFER, *PSRB_BUFFER; + + typedef struct _REBUILDSIZE { + DWORD DiskID; + DWORD Size; + } REBUILDSIZE; + + typedef struct _HDD_STATUS { + + USHORT NumberOfCylinders; + USHORT NumberOfHeads; + USHORT SectorsPerTrack; + USHORT VendorUnique1[3]; + USHORT SerialNumber[10]; + USHORT FirmwareRevision[4]; + USHORT ModelNumber[20]; + // USHORT UserAddressableSectors[2]; + DWORD BlockSize; + UCHAR UDMASupport; + UCHAR UDMAPresentMode; + + } HDD_STATUS, *PHDD_STATUS; + + typedef struct _GUI_INTERFACE_B + { + V6INTERFACEB Interface; + HDD_STATUS HddStatus[4][4]; + UCHAR BiosDeviceNum; + UCHAR BiosManufacNum; + } GuiInterface, *PGuiInterface; + + + typedef struct _GUI_INTERFACE_B2 + { + SRB_IO_CONTROL sic; + V6INTERFACEB Interface; + HDD_STATUS HddStatus[4][4]; + UCHAR BiosDeviceNum; + UCHAR BiosManufacNum; + + } GuiInterface2, *PGuiInterface2; + + typedef struct _GUI_FLAG + { + UCHAR IsActingHdd[4][2][2]; + UCHAR IsHereHdd[4][2][2]; + UCHAR RemovedHdd[4][2][2]; + UCHAR RebuildHdd[4][2][2]; + UCHAR SourceHdd[4][2][2]; + ULONG DiskID[4][2][2]; + ULONG Order[4][2][2]; + ULONG RunRebuildTime[16]; + ULONG Reserved; + } GUI_FLAG,*PGUI_FLAG; + + /* + UI Interface´Â À§ ±¸Á¶Ã¼·Î Àü´ÞÇÕ´Ï´Ù.(1Ãʸ¶´Ù °»½Å) + + UCHAR IsActingHdd[CardNumber][TargerId] : Hdd Read/Write Working status + UCHAR IsHereHdd[CardNumber][TargerId] : Hdd Á¸Àç À¯¹« Ç÷¡±×. + UCHAR RebuildHdd[CardNumber][TargerId] : Rebuild´çÇÏ´Â Hdd + UCHAR SourceHdd[CardNumber][TargerId] : Source Hdd + ULONG RunRebuildTime; : RebuildÇØ¾ßÇÒ ½ÃÁ¡¿¡ TRUE¼ÂÆÃ. + */ + + + typedef struct _GUI_FLAG2 + { + SRB_IO_CONTROL sic; + UCHAR IsActingHdd[4][4]; + UCHAR IsHereHdd[4][4]; + UCHAR RebuildHdd[4][4]; + UCHAR SourceHdd[4][4]; + ULONG RunRebuildTime; + ULONG Reserved; + } GUI_FLAG2,*PGUI_FLAG2; + + typedef struct _MOVEDATA_ + { + DWORD DiskID; + UCHAR SourceCard; + UCHAR SourceTargetId; + UCHAR TargetCard; + UCHAR TargetTargetId; + ULONG LbaAddress; + ULONG Size; + }MOVEDATA,*PMOVEDATA; + + + // + // Define SCSI maximum configuration parameters. + // + + #define SCSI_MAXIMUM_LOGICAL_UNITS 8 + #define SCSI_MAXIMUM_TARGETS_PER_BUS 32 + #define SCSI_MAXIMUM_BUSES 8 + #define SCSI_MINIMUM_PHYSICAL_BREAKS 16 + #define SCSI_MAXIMUM_PHYSICAL_BREAKS 255 + + // + // This constant is for backward compatibility. + // This use to be the maximum number of targets supported. + // + + #define SCSI_MAXIMUM_TARGETS 8 + + // begin_ntminitape + + #define MAXIMUM_CDB_SIZE 12 + + // end_ntminitape diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/ultima.c linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/ultima.c *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/ultima.c 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/ultima.c 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,1931 ---- + /******************************************************************* + + Aralion Ultima ATA133 IDE Raid Controller + Linux Device Driver source, programmed by soonsoo@hitel.net + + *******************************************************************/ + //#define __BOOT_KERNEL_BOOT 1 + + //#define DEBUG1 1 + //#define DEBUG2 1 + //#define DEBUG3 1 + //#define DEBUG4 1 + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "../scsi.h" + #include "../hosts.h" + #include "../sd.h" + #include "ultima.h" + #include "atapi.h" + #include + #include + #include + #include /* for CONFIG_PCI */ + #include + #include /* for put_user_byte */ + #include + #include + #include "iocontrol.h" + #include "flash.h" + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + #define KERNEL240 + #else + #define KERNEL220 + #endif + + #define S_BOARD(x,y) (DiskID[x].DiskStatus.BoardID) + #define S_CHAN(x,y) (DiskID[x].DiskStatus.Channel) + #define S_DRV(x,y) (DiskID[x].DiskStatus.Drive) + #define RAID(x) (DiskID[x].RaidStatus) + #define DEG printk("<1> "__FUNCTION__": %d\n",__LINE__) + //////////////////////////////////////////////////////////////////////////////// + + static void print_banner(struct Scsi_Host *shpnt); + char * GetCmdName(char code); + static void print_banner(struct Scsi_Host *shpnt); + static void do_pause(ULONG amount); + static int aralion_pci_bios_detect(int *irq); + ULONG GetBlockCount(int BoardID,int channel,int drive); + int RequestAllIrq(void); + void PutLBAvalue(ULONG IOPort1, + ULONG lba, + ULONG numsectors, + ULONG DriveSelect); + void DisableInterrupt(int BoardID); + void EnableInterrupt(int BoardID); + ULONG SetBoardInterruptFlag(int BoardID,int Channel,DWORD Status); + ULONG SetScatterList(Scsi_Cmnd *SCpnt, + ULONG lba, + ULONG numsectors, + ULONG ReadWrite); + void SetIOPort(DISKLIST *pList,USHORT DmaRW,DWORD OrderFlag); + void SetIOInformation(int tid,USHORT DmaRW,DWORD OrderFlag); + ULONG PutOneScatterList(ULONG CurrentID, + DWORD PrimaryDiskArrayCount, + DISKLIST *PrimaryDiskArray, + ULONG lba, + ULONG buffer, + USHORT length); + void SetIDECommand(DWORD Command, DWORD order); + DWORD BigDiskCommand (DWORD cmnd); + void SetDMACommand(USHORT DmaRW,DWORD OrderFlag); + static int ReadDMA(Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors); + static int WriteDMA(Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors); + void GetUDMAMode(USHORT *mode, + USHORT *Timing, + IDENTIFY_DATA * IdentifyData); + void SetUDMAMode(int BoardID, int Channel, int Drive); + static int IdentifyDisk(int BoardID, + int Channel, + int DriveSelect, + IDENTIFY_DATA * IdentifyData); + static void my_done(int error); + int CheckScsiError(ULONG Channel,ULONG IOPort1,UCHAR statusByte); + void CheckJobFinished(ULONG BoardID,ULONG Channel); + int IsSplitter(char c); + int ultima_1cardreset(int BoardID); + int ultima_cardreset(void); + void do_ultima_intr(int irq, void *dev_id, struct pt_regs *regs); + void internal_done(Scsi_Cmnd * SCpnt); + void print_info(Scsi_Cmnd * SCpnt); + + //////////////////////////////////////////////////////////////////////////////// + + struct proc_dir_entry proc_scsi_aralion = { + 0x10, 7, "aralion", + S_IFDIR | S_IRUGO | S_IXUGO, 2 + }; + + Scsi_Host_Template driver_template = ULTIMA_DMA133; + + #define VERSION "$Revision: LH 1.11BCS $" + + enum { + in_arbitration = 0x02, + in_selection = 0x04, + in_other = 0x08, + disconnect = 0x10, + aborted = 0x20, + sent_ident = 0x40, + }; + + typedef struct { + char name[23]; + char code; + } CMDNAME; + + CMDNAME CmdName[] = + { + {"TEST_UNIT_READY",0x00}, + {"REZERO_UNIT",0x01}, + {"REQUEST_SENSE",0x03}, + {"FORMAT_UNIT",0x04}, + {"READ_BLOCK_LIMITS",0x05}, + {"REASSIGN_BLOCKS",0x07}, + {"READ_6",0x08}, + {"WRITE_6",0x0a}, + {"SEEK_6",0x0b}, + {"READ_REVERSE",0x0f}, + {"WRITE_FILEMARKS",0x10}, + {"SPACE",0x11}, + {"INQUIRY",0x12}, + {"RECOVER_BUFFERED_DATA",0x14}, + {"MODE_SELECT",0x15}, + {"RESERVE",0x16}, + {"RELEASE",0x17}, + {"COPY",0x18}, + {"ERASE",0x19}, + {"MODE_SENSE",0x1a}, + {"START_STOP",0x1b}, + {"RECEIVE_DIAGNOSTIC",0x1c}, + {"SEND_DIAGNOSTIC",0x1d}, + {"ALLOW_MEDIUM_REMOVAL",0x1e}, + {"SET_WINDOW",0x24}, + {"READ_CAPACITY",0x25}, + {"READ_10",0x28}, + {"WRITE_10",0x2a}, + {"SEEK_10",0x2b}, + {"WRITE_VERIFY",0x2e}, + {"VERIFY",0x2f}, + {"SEARCH_HIGH",0x30}, + {"SEARCH_EQUAL",0x31}, + {"SEARCH_LOW",0x32}, + {"SET_LIMITS",0x33}, + {"PRE_FETCH",0x34}, + {"READ_POSITION",0x34}, + {"SYNCHRONIZE_CACHE",0x35}, + {"LOCK_UNLOCK_CACHE",0x36}, + {"READ_DEFECT_DATA",0x37}, + {"MEDIUM_SCAN",0x38}, + {"COMPARE",0x39}, + {"COPY_VERIFY",0x3a}, + {"WRITE_BUFFER",0x3b}, + {"READ_BUFFER",0x3c}, + {"UPDATE_BLOCK",0x3d}, + {"READ_LONG",0x3e}, + {"WRITE_LONG",0x3f}, + {"CHANGE_DEFINITION",0x40}, + {"WRITE_SAME",0x41}, + {"READ_TOC",0x43}, + {"LOG_SELECT",0x4c}, + {"LOG_SENSE",0x4d}, + {"MODE_SELECT_10",0x55}, + {"RESERVE_10",0x56}, + {"RELEASE_10",0x57}, + {"MODE_SENSE_10",0x5a}, + {"PERSISTENT_RESERVE_IN",0x5e}, + {"PERSISTENT_RESERVE_OUT",0x5f}, + {"MOVE_MEDIUM",0xa5}, + {"READ_12",0xa8}, + {"WRITE_12",0xaa}, + {"WRITE_VERIFY_12",0xae}, + {"SEARCH_HIGH_12",0xb0}, + {"SEARCH_EQUAL_12",0xb1}, + {"SEARCH_LOW_12",0xb2}, + {"READ_ELEMENT_STATUS",0xb8}, + {"SEND_VOLUME_TAG",0xb6}, + {"WRITE_LONG_2",0xea} + }; + + //////////////////////////////////////////////////////////////////////////////// + static volatile int internal_done_flag = 0; + static volatile int internal_done_errcode = 0; + static Scsi_Cmnd *current_SC = NULL; + static int this_id = 31; + V6INTERFACEB V6; + static _DiskIDTable DiskID[16]; + static DISKRWINFO DiskRWInfo[MAXBOARD][2][2]; + static IDENTIFY_DATA DiskIdentifyData[MAXBOARD][2][2]; + static int gBoardCount = 0; + IrqID ultimaID[MAXBOARD]; + BOARDTABLE BoardInfo[MAXBOARD]; + static int IrqFlag[32] = {0,}; + static int DiskCount = 0; + ULONG LastErrorBlock,LastErrorCode; + static ULONG RWStatus; + static ULONG OrderStatus; + static ULONG CurrentDisk; + static int interrupt_level = 0; + static int HddConnected[MAXBOARD][2][2]; + static int HddSupportMode[MAXBOARD][2][2]; + + ///////////////////////////////////////////////// + #define IOCTL_LOCK 1 + static int in_ioctl = 0; + static int in_command = 0; + unsigned long LockValue = 0; + static DECLARE_WAIT_QUEUE_HEAD (WaitingQ); + + ///////////////////////////////////////////////// + UCHAR BiosManufacture = 0; + UCHAR cDeviceCode = 0; + UCHAR cFlashFlag = 0; + UCHAR *Buffer; + char *GetCmdName(char code) + { + int i; + int count; + char *s = "unknown function"; + + count = sizeof(CmdName) / sizeof(CMDNAME); + + for(i=0;ithis_id); + + if (interrupt_level) + printk(" int %d", interrupt_level); + else + printk(""); + + printk("\n"); + } + + static void aralion_setup(char *str, int *ints) + { + this_id = 31; + } + + + /* Pause for amount*10 milliseconds */ + static void do_pause(ULONG amount) + { + do + { + udelay(10 * 1000); + } + while (--amount); + } + + inline static void aralion_make_bus_idle(void) + { + } + + static int aralion_is_valid_port(int port) + { + return 0; + } + + static int aralion_test_loopback(void) + { + return 0; + } + + static int aralion_pci_bios_detect(int *irq) + { + struct pci_dev *pdev = NULL; + + if (!pci_present()) + return 0; + + memset(BoardInfo,0,sizeof(BoardInfo)); + + do { + if ((pdev = pci_find_device(ARALION_VENDOR, ULTIMA_DEVICE, pdev)) != NULL) { + // printk("Find %d device\n",gBoardCount); + // BoardInfo[gBoardCount].BoardExist = 1; + + #ifdef KERNEL240 + BoardInfo[gBoardCount].PrimaryIO + = (ULONG) pci_resource_start(pdev,0); + BoardInfo[gBoardCount].SecondaryIO + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x10; + BoardInfo[gBoardCount].PrimaryDmaIO + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x20; + BoardInfo[gBoardCount].SecondaryDmaIO + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x30; + BoardInfo[gBoardCount].ControlRegister + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x40; + BoardInfo[gBoardCount].FlashMemory + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x50; + #else + BoardInfo[gBoardCount].PrimaryIO + = (ULONG) pdev->base_address[0] & PCI_BASE_SDDRESS_IO_MASK; + BoardInfo[gBoardCount].SecondaryIO + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x10; + BoardInfo[gBoardCount].PrimaryDmaIO + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x20; + BoardInfo[gBoardCount].SecondaryDmaIO + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x30; + BoardInfo[gBoardCount].ControlRegister + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x40; + BoardInfo[gBoardCount].FlashMemory + = (ULONG) (BoardInfo[gBoardCount].PrimaryIO)+0x50; + #endif + + BoardInfo[gBoardCount].interrupt_level = pdev->irq; + + request_region(BoardInfo[gBoardCount].PrimaryIO, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].SecondaryIO, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].PrimaryDmaIO, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].SecondaryDmaIO, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].ControlRegister, 0x10, "aralion"); + request_region(BoardInfo[gBoardCount].FlashMemory,0x8, "aralion"); + + if (!gBoardCount) + *irq = pdev->irq; + + gBoardCount++; + } + } while(pdev != NULL); + + + if (!gBoardCount) { + printk("Ultima Board not found\n"); + return 0; + } + + interrupt_level = BoardInfo[0].interrupt_level; + return 1; + } + + ULONG GetBlockCount(int BoardID,int channel,int drive) + { + int i; + ULONG nCount; + UCHAR *p; + p = (char *) &(DiskIdentifyData[BoardID][channel][drive]); + if(DiskIdentifyData[BoardID][channel][drive].BIT48 & 0x0400) + nCount = *((ULONG *) (p + 200)); + else + nCount = *((ULONG *) (p + 120)); + return nCount; + } + + int RequestAllIrq(void) + { + int i; + int irq; + int retcode; + + for(i=0;i IRQ %d is bad!\n", irq); + printk(" This shouldn't happen!\n"); + printk(" Send mail to faith@acm.org\n"); + } + else if (retcode == -EBUSY) { + printk("scsi: IRQ %d is already in use!\n",irq); + printk(" Please use another IRQ!\n"); + } + else { + printk("scsi: Error getting IRQ %d\n",irq); + printk(" This shouldn't happen!\n"); + printk(" Send mail to faith@acm.org\n"); + } + printk("scsi: Detected, but driver not loaded (IRQ)\n"); + + return retcode; + } + } + } + return 0; + } + + int ultima_detect(Scsi_Host_Template * tpnt) + { + int retcode; + struct Scsi_Host *shpnt; + int i, j, statusByte; + int flag = 0; + ULONG IOPort; + + tpnt->proc_dir = &proc_scsi_aralion; + flag = aralion_pci_bios_detect(&interrupt_level); + + if (!flag) { + printk("scsi: Ultima not found\n"); + return 0; + } + + memset(&DiskID,0,sizeof(DiskID)); + memset(&DiskRWInfo,0,sizeof(DiskRWInfo)); + memset(&DiskIdentifyData,0,sizeof(DiskIdentifyData)); + DiskCount = 0; + + for(i=0;ithis_id = (this_id & 0x1f); + + /* Print out a banner here in case we can't + get resources. */ + shpnt = scsi_register(tpnt, 0); + shpnt->irq = interrupt_level; + shpnt->io_port = BoardInfo[0].ControlRegister; + shpnt->n_io_port = 0x10; + // print_banner(shpnt); + + if (!interrupt_level) + { + printk("scsi: " + " Card Detected, but driver not loaded (no IRQ)\n"); + return 0; + } + else + { + /* Register the IRQ with the kernel */ + if (RequestAllIrq()) + return 0; + } + + for(i=0;i ",i,d1); + } + printk("\n"); + } + #endif + + inline DISKRWINFO *GetRWInfoPointer(DISKLIST *pDiskList) + { + return (DISKRWINFO *) &DiskRWInfo[pDiskList->BoardID][pDiskList->Channel][pDiskList->Drive]; + } + + void PutLBAvalue(ULONG IOPort1,ULONG lba,ULONG numsectors, + ULONG DriveSelect) + { + UCHAR Data[4]; + /////////////////////////////KHG-133s_Big//////////////////////////////// + if(lba >= 0x10000000){ + Data[0] = (lba & 0xff000000 ) >> 24; + Data[1] = 0; + Data[2] = 0; + outb(0,IOPort1 + BlockCountPort); + outb(Data[0],IOPort1 + BlockNumberPort); + outb(Data[1],IOPort1 + CylinderLowPort); + outb(Data[2],IOPort1 + CylinderHighPort); + Data[0] = (lba & 0x000000ff); + Data[1] = (lba & 0x0000ff00) >> 8; + Data[2] = (lba & 0x00ff0000) >> 16; + Data[3] = (DriveSelect << 4) | 0xe0; + outb(numsectors,IOPort1 + BlockCountPort); + outb(Data[0],IOPort1 + BlockNumberPort); + outb(Data[1],IOPort1 + CylinderLowPort); + outb(Data[2],IOPort1 + CylinderHighPort); + outb(Data[3],IOPort1 + DriveSelectPort); + } + else{ + Data[0] = (lba & 0x000000ff); + Data[1] = (lba & 0x0000ff00) >> 8; + Data[2] = (lba & 0x00ff0000) >> 16; + Data[3] = (lba & 0x0f000000) >> 24; + Data[3] = Data[3] | 0x40 | (DriveSelect << 4) | 0xa0; + + outb(numsectors,IOPort1 + BlockCountPort); + outb(Data[0],IOPort1 + BlockNumberPort); + outb(Data[1],IOPort1 + CylinderLowPort); + outb(Data[2],IOPort1 + CylinderHighPort); + outb(Data[3],IOPort1 + DriveSelectPort); + } + ///////////////////////////////////////////////////////////////////////// + } + + void DisableInterrupt(int BoardID) + { + USHORT Intena; + + // Intena = inw(BoardInfo[BoardID].ControlRegister + INTENA); + // Intena = Intena & 0xfe; + Intena = 0; + outw(Intena,BoardInfo[BoardID].ControlRegister + INTENA); + } + + void EnableInterrupt(int BoardID) + { + USHORT Intena; + + // Intena = inw(BoardInfo[BoardID].ControlRegister + INTENA); + // Intena = Intena | 0x01; + Intena = 0x03; //KHG + + // printk("EI : %d\n",BoardID); + outw(Intena,BoardInfo[BoardID].ControlRegister + INTENA); + // printk("EI2 : %d\n",BoardID); + } + + // int SetBoardInterruptFlag(int BoardID,int Channel,DWORD Status) + ULONG SetBoardInterruptFlag(int BoardID,int Channel,DWORD Status) + { + ////////////////////////////////////KHG-133s//////////////////////////////////// + ULONG TempStatus; + Channel = 0; + + if (BoardInfo[BoardID].InterruptFlag[Channel] & Status) { + TempStatus = BoardInfo[BoardID].InterruptFlag[Channel] & 0x00001111; + if(TempStatus & 0x00001100){ + BoardInfo[BoardID].InterruptFlag[Channel] |= 0x00001000; + return 0x00001000; + } + else if(TempStatus & 0x00000010){ + BoardInfo[BoardID].InterruptFlag[Channel] |= 0x00000100; + return 0x00000100; + } + else { + BoardInfo[BoardID].InterruptFlag[Channel] |= 0x00000010; + return 0x000000010; + } + } + else { + BoardInfo[BoardID].InterruptFlag[Channel] = (Status | ORDER_ONE); + return 0; + } + } + + ULONG SetScatterList( Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors, + ULONG ReadWrite) + { + struct scatterlist *slp; + int i,j; + PPDT_TABLE pPDTTable; + DISKRWINFO *pRWInfo,*pRWInfo2; + int tid = SCpnt->target; + DWORD RaidStatus; + ULONG TempFlag; + + RaidStatus = RAID(tid); + + pRWInfo = (DISKRWINFO *) &DiskRWInfo[S_BOARD(tid,0)][S_CHAN(tid,0)][S_DRV(tid,0)]; + + pRWInfo->StartLba = lba; + pRWInfo->ListCount = 0; + pRWInfo->NumSectors = 0; + pPDTTable = pRWInfo->ScatterList; + if (SCpnt->use_sg) { + slp = (struct scatterlist *) SCpnt->request_buffer; + for(i=0;iuse_sg;i++,slp++) { + pPDTTable[i].address = virt_to_bus(slp->address); + pPDTTable[i].length = slp->length; + pPDTTable[i].EndOfChain = 0; + pRWInfo->NumSectors += slp->length; + } + pPDTTable[i - 1].EndOfChain = 0x80; + pRWInfo->ListCount = SCpnt->use_sg; + } + else { + pPDTTable[0].address = virt_to_bus(SCpnt->request_buffer); + pPDTTable[0].length = SCpnt->request_bufflen; + pPDTTable[0].EndOfChain = 0x80; + pRWInfo->NumSectors = SCpnt->request_bufflen; + pRWInfo->ListCount = 1; + } + + pRWInfo->NumSectors /= 512; + + pRWInfo->InterruptFlag = ReadWrite | ORDER_ONE; + SetBoardInterruptFlag(S_BOARD(tid,0),S_CHAN(tid,0),ReadWrite); + } + + void PrintPDT(PPDT_TABLE pPDTTable,int count) + { + int i; + + for(i=0;iBoardID; + Channel = pList->Channel; + Drive = pList->Drive; + + pRWInfo = (DISKRWINFO *) &DiskRWInfo[pList->BoardID][pList->Channel][pList->Drive]; + if (!(OrderFlag & pRWInfo->InterruptFlag)) { + return ; + } + + if(Channel == 0) + { + SelectFirstChannel(BoardID); + } + else + { + SelectSecondChannel(BoardID); + } + pPDTTable = BoardInfo[BoardID].PriScatterList; + IOPort1 = BoardInfo[BoardID].PrimaryIO; + DmaIO = BoardInfo[BoardID].PrimaryDmaIO; + memcpy(pPDTTable,pRWInfo->ScatterList,pRWInfo->ListCount * sizeof(PDT_TABLE)); + BoardInfo[BoardID].ListCount = pRWInfo->ListCount; + BoardInfo[BoardID].NumSectors = pRWInfo->NumSectors; + BoardInfo[BoardID].StartLba = pRWInfo->StartLba; + + AddressLow = virt_to_bus(pPDTTable) & 0x0000ffff; + AddressHi = (virt_to_bus(pPDTTable) & 0xffff0000) >> 16; + + outw(AddressLow,DmaIO + PDTLAR); + outw(AddressHi,DmaIO + PDTHAR); + + PutLBAvalue( + IOPort1, + BoardInfo[BoardID].StartLba, + BoardInfo[BoardID].NumSectors, + Drive); + } + + void SetIOInformation(int tid,USHORT DmaRW,DWORD OrderFlag) + { + DISKRWINFO *pRWInfo = GetRWInfoPointer(&DiskID[tid].DiskStatus); + if (pRWInfo->ListCount) { + SetIOPort(&DiskID[tid].DiskStatus,DmaRW,OrderFlag); + } + } + + + void SetIDECommand(DWORD Command, DWORD OrderFlag) + { + int i,j; + + for(i=0;i= 0x10000000) + Command=BigDiskCommand(Command); + outb(Command,BoardInfo[i].PrimaryIO + CommandPort); + } + /* + if (BoardInfo[i].InterruptFlag[1] & OrderFlag) { + if(BoardInfo[i].StartLba >= 0x10000000) + Command=BigDiskCommand(Command); + outb(Command,BoardInfo[i].SecondaryIO + CommandPort); + } + */ + } + } + + DWORD BigDiskCommand (DWORD cmnd) + { + switch(cmnd){ + case IDE_COMMAND_READ_DMA: + return IDE_COMMAND_READ_DMA_EXT; + case IDE_COMMAND_WRITE_DMA: + return IDE_COMMAND_WRITE_DMA_EXT; + } + // Added 2003/11/09 by Ashuaria Lee + #warning I dont know what to do... + return cmnd; + } + + void SetDMACommand(USHORT DmaRW,DWORD OrderFlag) + { + ULONG DmaIO; + int i,j,k; + + for(i=0;itarget,DMA_READ,ORDER_ONE); + RWStatus = READ_STATUS; + OrderStatus = ORDER_ONE; + SetIDECommand(IDE_COMMAND_READ_DMA,ORDER_ONE); + SetDMACommand(DMA_READ,ORDER_ONE); + return 0; + } + + static int WriteDMA( + Scsi_Cmnd * SCpnt, + ULONG lba, + ULONG numsectors) + { + int i; + unsigned long flags; + + if (numsectors == 0) { + my_done(DID_ABORT << 16); + return ERROR_INVALID_SECTORCOUNT; + } + SetScatterList(SCpnt,lba,numsectors,WRITE_STATUS); + SetIOInformation(SCpnt->target,DMA_WRITE,ORDER_ONE); + RWStatus = WRITE_STATUS; + OrderStatus = ORDER_ONE; + + SetIDECommand(IDE_COMMAND_WRITE_DMA,ORDER_ONE); + SetDMACommand(DMA_WRITE,ORDER_ONE); + + return 0; + } + + void GetUDMAMode(USHORT *mode,USHORT *Timing, + IDENTIFY_DATA * IdentifyData) + { + + if(IdentifyData->UDMASupport & 0x40){ + *mode = 0x46; // mode 6 + *Timing = 0xff22; // mode 6 + } + else if(IdentifyData->UDMASupport & 0x20){ + *mode = 0x45; // mode 5 + *Timing = 0xff33; // mode 5 + } + else if(IdentifyData->UDMASupport & 0x10){ + *mode = 0x44; // mode 4 + *Timing = 0xff44; // mode 4 + } + else if(IdentifyData->UDMASupport & 0x08){ + *mode = 0x43; // mode 3 + *Timing = 0xff55; // mode 3 + } + else if(IdentifyData->UDMASupport & 0x04){ + *mode = 0x42; // mode 2 + *Timing = 0xff66; // mode 2 + } + else if(IdentifyData->UDMASupport & 0x02){ + *mode = 0x41; // mode 1 + *Timing = 0xff77; // mode 1 + } + else if(IdentifyData->UDMASupport & 0x01){ + *mode = 0x40; // mode 0 + *Timing = 0xff88; // mode 0 + } + #ifdef _7878_ + *mode = 0x44; // mode 4 + *Timing = 0x7878; // safe mode + #endif + } + + void SetUDMAMode(int BoardID, int Channel, int Drive) + { + USHORT mode[3],Timing[3]; + ULONG IOPort1; + ULONG DmaIO; + char statusByte=0; + int i; + + if(Channel == 0) + { + SelectFirstChannel(BoardID); + } + else + { + SelectSecondChannel(BoardID); + } + IOPort1 = BoardInfo[BoardID].PrimaryIO; + DmaIO = BoardInfo[BoardID].PrimaryDmaIO; + + + if(HddConnected[BoardID][Channel][Drive]>0) + { + mode[0] = 0xffff; + Timing[0] = 0xffff; + GetUDMAMode(&mode[0],&Timing[0],&DiskIdentifyData[BoardID][Channel][Drive]); + // printk("udma mode value = %x\n",mode[0]); + if(mode[0] == 0xffff) + return; + outb(0xA0 + (Drive << 4),IOPort1 + DriveSelectPort); + for(i=0;i<10000;i++) + { + GetBaseStatus(IOPort1, statusByte); + udelay(100); + if(statusByte & IDE_STATUS_BUSY) + continue; + else + break; + } + outb(0xA0 + (Drive << 4),IOPort1 + DriveSelectPort); + outb(mode[0],IOPort1 + BlockCountPort); + outb(0x03,IOPort1 + ErrorPort); + outb(IDE_COMMAND_ENABLE_MEDIA_STATUS,IOPort1 + CommandPort); + for(i=0;i<10000;i++) + { + GetBaseStatus(IOPort1, statusByte); + udelay(100); + if(statusByte & IDE_STATUS_BUSY) + continue; + else + break; + } + if(statusByte == 0x50 || statusByte == 0x40) + { + HddSupportMode[BoardID][Channel][Drive] = (((mode[0] << 8) | 0xff) & Timing[0]); + // printk("SetUDMA: SupportMode = %0.4x\n", HddSupportMode[BoardID][Channel][Drive]); + } + } + mdelay(5); + for(i=0;i<10;i++) + { + GetBaseStatus(IOPort1, statusByte); + if(statusByte & IDE_STATUS_IDLE) + break; + else + mdelay(2); + } + } + + static int IdentifyDisk( + int BoardID, + int Channel, + int DriveSelect, + IDENTIFY_DATA * IdentifyData) + { + ULONG IOPort1,DmaIO,ControlRegister; + UCHAR statusByte; + USHORT *pIdentifyData; + int i, j; + int flag = 0; + + if(Channel == 0) + { + SelectFirstChannel(BoardID); + } + else + { + SelectSecondChannel(BoardID); + } + IOPort1 = BoardInfo[BoardID].PrimaryIO; + DmaIO = BoardInfo[BoardID].PrimaryDmaIO; + ControlRegister = BoardInfo[BoardID].ControlRegister; + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + + for (i=0;i<1000;i++) + { + udelay(10); + GetBaseStatus(IOPort1, statusByte); + if (!(statusByte & 0x80)) + break; + } + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + mdelay(50); + GetBaseStatus(IOPort1, statusByte); + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + mdelay(50); + GetBaseStatus(IOPort1, statusByte); + if(statusByte != 0x50) + { + outb(0x08, IOPort1 + CommandPort); //Device reset + for(i=0; i<3; i++) // KHG_20020731 + { + mdelay(100); + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + GetBaseStatus(IOPort1, statusByte); + if(statusByte != 0x50) + { + outb(0x04, IOPort1 + 0x0e); + mdelay(100); + outb(0x00, IOPort1 + 0x0e); + } + else + { + break; + } + } + } + mdelay(50); + statusByte = statusByte & 0xc9; + if (statusByte != IDE_STATUS_DRDY) + { + return 0; + } + + + label1: + for (j = 0; j < 2; j++) + { + WaitOnBusy(IOPort1, statusByte); + outb(IDE_COMMAND_IDENTIFY, IOPort1 + CommandPort); + + for (i = 0; i < 4; i++) + { + WaitForDrq(IOPort1, statusByte); + if (statusByte & IDE_STATUS_DRQ) + { + GetBaseStatus(IOPort1, statusByte); + break; + } + WaitOnBusy(IOPort1, statusByte); + } + if (i == 4 && j == 0) + { + return 0; + } + else + { + break; + } + } // end of for (j = 0; j < 2; j++) + + + if (statusByte & IDE_STATUS_ERROR) + { + return 0; + } + + WaitOnBusy(IOPort1, statusByte); + + + if (!(statusByte & IDE_STATUS_DRQ)) + { + return 0; + } + + pIdentifyData = (USHORT *) IdentifyData; + + outb(((DriveSelect << 4) | 0xA0), IOPort1 + DriveSelectPort); + mdelay(50); + GetBaseStatus(IOPort1, statusByte); + for (i = 0; i < 256; i++) + { + pIdentifyData[i] = inw(IOPort1 + DataPort); + } + { + char *p,c; + p = (char *) &(IdentifyData->VendorUnique1); + + for (i = 0; i < 26; i+=2) + { + c = p[i]; + p[i] = p[i+1]; + p[i+1] = c; + } + p = (char *) &(IdentifyData->ModelNumber); + + for (i = 0; i < 40; i+=2) + { + c = p[i]; + p[i] = p[i+1]; + p[i+1] = c; + } + } + + { + int mm = 0; + + for (i = 0; i < 0x1000; i++) + { + + GetStatus(IOPort1, statusByte); + + if ((statusByte & IDE_STATUS_DRQ) + || (statusByte & IDE_STATUS_BUSY) + || (statusByte & 1) ) + { + inw(IOPort1 + DataPort); + } + else + { + break; + } + } // end of for + } + return 1; + } + + char *ultima_info(struct Scsi_Host *ignore) + { + static char buffer[128]; + char *pt; + + strcpy(buffer, "Aralion Ultima ATA133 IDE RAID MultiCard Driver Version"); + if (strchr(VERSION, ':')) + { /* Assume VERSION is an RCS Revision string */ + strcat(buffer, strchr(VERSION, ':') + 1); + pt = strrchr(buffer, '$') - 1; + if (!pt) /* Stripped RCS Revision string? */ + pt = buffer + strlen(buffer) - 1; + if (*pt != ' ') + ++pt; + *pt = '\0'; + } + else + { /* Assume VERSION is a number */ + strcat(buffer, " " VERSION); + } + + return buffer; + } + + + int init_module(void) { + driver_template.module = &__this_module; + scsi_register_module(MODULE_SCSI_HA, &driver_template); + if (driver_template.present) { + return 0; + } + + scsi_unregister_module(MODULE_SCSI_HA, &driver_template); + return -1; + } + + void cleanup_module( void) { + scsi_unregister_module(MODULE_SCSI_HA, &driver_template); + } + + int ultima_proc_info(char *buffer, char **start, off_t offset, + int length, int hostno, int inout) + { + const char *info = ultima_info(NULL); + int len; + int pos; + int begin; + + if (inout) + return (-ENOSYS); + + begin = 0; + strcpy(buffer, info); + strcat(buffer, "\n"); + + pos = len = strlen(buffer); + + if (pos < offset) + { + len = 0; + begin = pos; + } + + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); + if (len > length) + len = length; + + return (len); + } + + static int aralion_arbitrate(void) + { + int status = 0; + ULONG timeout; + + printk("[ aralion_arbitrate ]\n"); + + return 0; + } + + static int aralion_select(int target) + { + int status; + ULONG timeout; + static int flag = 0; + + + printk("[ aralion_select - %d ]\n",target); + return 0; + } + + static void my_done(int error) + { + if (in_command) + { + in_command = 0; + // printk("my_done\n"); + if (test_and_clear_bit(IOCTL_LOCK,&LockValue) == 0) + printk("misc clear...\n"); + current_SC->result = error; + if (current_SC->scsi_done) { + current_SC->scsi_done(current_SC); + } + else + panic("scsi: current_SC->scsi_done() == NULL"); + } + else + { + panic("scsi: my_done() called outside of command\n"); + } + } + + int CheckScsiError(ULONG Channel,ULONG IOPort1,UCHAR statusByte) + { + ULONG lba; + UCHAR Data[4]; + UCHAR errorByte; + ULONG scsiStatus = 0; + + if (statusByte & 0x1) { + + errorByte = inb(IOPort1 + ErrorPort); + printk("error byte = %x",ErrorPort); + if (errorByte & IDE_ERROR_BAD_BLOCK) + scsiStatus = DID_PARITY; + else if (errorByte & IDE_ERROR_DATA_ERROR) + scsiStatus = DID_ERROR; + else if (errorByte & IDE_ERROR_ID_NOT_FOUND) + scsiStatus = DID_NO_CONNECT; + else if (errorByte & IDE_ERROR_COMMAND_ABORTED) + scsiStatus = DID_ABORT; + else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH ) + scsiStatus = DID_ERROR; + + Data[3] = inb(IOPort1 + BlockNumberPort); + Data[2] = inb(IOPort1 + CylinderLowPort); + Data[1] = inb(IOPort1 + CylinderHighPort); + Data[0] = inb(IOPort1 + DriveSelectPort) & 0x0f; + + lba = (Data[0] << 24) + (Data[1] << 16) + + (Data[2] << 8) + Data[0]; + + LastErrorBlock = lba; + LastErrorCode = errorByte & 0x000f; + + printk("Error! Ch:%d, %02x , %0d\n",Channel, + (UCHAR) errorByte,lba); + return scsiStatus; + } + else + return 0; + } + + void CheckJobFinished(ULONG BoardID,ULONG Channel) + { + ULONG DmaIO; + USHORT Stat; + DWORD i = 0; + + if (Channel == 1) { + DmaIO = BoardInfo[BoardID].PrimaryDmaIO; + } + else + { + DmaIO = BoardInfo[BoardID].SecondaryDmaIO; + } + do { + Stat = inw(DmaIO + CONSR); + i++; + } while ((Stat & 0x01) && (i < 1000)); + if(i>100) + { + printk("CheckJobFinished Error\n"); + } + } + + void ClearAllIrq(void) + { + ULONG Channel; + UCHAR statusByte = 0; + UCHAR statusByte2 = 0; + ULONG IOPort1,IOPort2; + ULONG scsiStatus = 0; + int i; + + for(i=0;i\n"); + + if (!pIntID) { + spin_unlock_irqrestore(&io_request_lock, flags); + return ; + } + /* + if (gResetFlag) { + for (i=0;iresult; + ++internal_done_flag; + } + + int IsSplitter(char c) + { + if (c == ' ' || c == '-' || c == '_') + return 1; + else if (c >= '0' && c <= '9') + return 1; + + return 0; + } + + int ultima_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) + { + char *buf; + int board,channel,drive; + ULONG result; + /* + printk("[c=%x : %s,I=%x]\n", + (UCHAR) SCpnt->cmnd[0], + GetCmdName((UCHAR) SCpnt->cmnd[0]), + SCpnt->target); + */ + if (in_command) { + printk("[ ultima_queue c=%x : %s,I=%x]\n", + (UCHAR) SCpnt->cmnd[0], + GetCmdName((UCHAR) SCpnt->cmnd[0]), + SCpnt->target); + panic("Error! in_command == 1\n"); + // Added 2003/11/09 by Ashuaria Lee + #warning I dont know what to do... + return -1; + } + while(test_and_set_bit(IOCTL_LOCK,&LockValue) != 0) { + // printk("QW "); + schedule(); + udelay(1); + } + while(in_ioctl) { + printk("in_ioctl = 1\n"); + udelay(1); + } + in_command = 1; + current_SC = SCpnt; + current_SC->scsi_done = done; + + current_SC->SCp.Status = 0; + current_SC->SCp.Message = 0; + current_SC->SCp.have_data_in = 0; + current_SC->SCp.sent_command = 0; + current_SC->SCp.phase = in_arbitration; + + if (SCpnt->target >= DiskCount || SCpnt->lun > 0) { + my_done(DID_ABORT << 16); + return 0; + } + + if (SCpnt->target >= DiskCount) { + my_done(DID_ABORT << 16); + return 0; + } + + board = DiskID[current_SC->target].DiskStatus.BoardID; + channel = DiskID[current_SC->target].DiskStatus.Channel; + drive = DiskID[current_SC->target].DiskStatus.Drive; + switch(current_SC->cmnd[0]) { + case TEST_UNIT_READY: + case REQUEST_SENSE : + my_done(0); + return 0; + + case MODE_SENSE : + buf = (char *) current_SC->buffer; + buf[2] = 0x0; + my_done(0); + break; + + case INQUIRY : + buf = (char *) current_SC->buffer; + { + PINQUIRYDATA inquiryData + = (PINQUIRYDATA) current_SC->buffer; + PIDENTIFY_DATA identifyData = + &DiskIdentifyData[board][channel][drive]; + int i; + + memset(buf,0,current_SC->bufflen); + + buf[4] = sizeof(INQUIRYDATA); + + // + // Standard IDE interface only supports disks. + inquiryData->DeviceType = DIRECT_ACCESS_DEVICE; + + // + // Fill in vendor identification fields. + { + unsigned char *p; + int i,j; + + for (i = 0; i < 24; i ++) { + inquiryData->VendorId[i] = 0; + } + p = (UCHAR *) identifyData->ModelNumber; + i = 0; + + while(!IsSplitter(p[i])) { + inquiryData->VendorId[i] = p[i++]; + } + inquiryData->VendorId[i] = 0; + + i++; + j = 0; + while (p[i] != ' ' && i < 24) + inquiryData->ProductId[j++] = p[i++]; + inquiryData->ProductId[j] = 0; + + } + // + // Initialize unused portion of product id. + for (i = 0; i < 4; i++) { + inquiryData->ProductId[12+i] = ' '; + } + + // + // Move firmware revision from IDENTIFY data to + // product revision in INQUIRY data. + for (i = 0; i < 4; i += 2) { + inquiryData->ProductRevisionLevel[i] = + ((UCHAR *)identifyData->FirmwareRevision)[i+1]; + inquiryData->ProductRevisionLevel[i+1] = + ((UCHAR *)identifyData->FirmwareRevision)[i]; + } + } + // printk("Inquiry Success!"); + my_done(0); + break; + case READ_6 : + case READ_10 : + case WRITE_6 : + case WRITE_10 : + { + ULONG numsectors,lba,i ; + + if (*current_SC->cmnd == READ_6 || *current_SC->cmnd == WRITE_6) { + numsectors = (u_long) current_SC->cmnd[4]; + lba = ((u_long) current_SC->cmnd[1] << 16) | + ((u_long) current_SC->cmnd[2] << 8) | + (u_long) current_SC->cmnd[3]; + lba &= 0x1FFFFF; + } + if (*current_SC->cmnd == READ_10 || *current_SC->cmnd == WRITE_10) { + numsectors = (u_long) current_SC->cmnd[8] | + ((u_long) current_SC->cmnd[7] << 8); + lba = ((u_long) current_SC->cmnd[2] << 24) | + ((u_long) current_SC->cmnd[3] << 16) | + ((u_long) current_SC->cmnd[4] << 8) | + (u_long) current_SC->cmnd[5]; + } + + memset(DiskRWInfo,0,sizeof(DiskRWInfo)); + for(i=0;itarget; + + if (*current_SC->cmnd == READ_6 || *current_SC->cmnd == READ_10) { + + // printk("R:[%03d,%08x]\n", numsectors,lba); + ReadDMA(current_SC,lba,numsectors); + } + else { + // printk("W:[%03d,%08x]\n", numsectors,lba); + WriteDMA(current_SC,lba,numsectors); + } + } + break; + + case READ_CAPACITY : + { + ULONG block,size; + IDENTIFY_DATA * IdentifyData; + + block = DiskID[current_SC->target].DiskStatus.Size; + buf = (char *) current_SC->buffer; + size = 512; + + *((ULONG *) buf) = htonl(block - 1); + *((ULONG *) (buf + 4)) = htonl(size); + } + + my_done(0); + break; + default: + my_done(0); + break; + + } + return 0; + } + + int ultima_command(Scsi_Cmnd * SCpnt) + { + ultima_queue(SCpnt, internal_done); + while (!internal_done_flag) + ; + internal_done_flag = 0; + return internal_done_errcode; + } + + + void print_info(Scsi_Cmnd * SCpnt) + { + ULONG imr; + ULONG irr; + ULONG isr; + + + if (!SCpnt || !SCpnt->host) + { + printk("scsi: Cannot provide detailed information\n"); + return; + } + + printk("%s\n", ultima_info(SCpnt->host)); + return ; + print_banner(SCpnt->host); + + printk("(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", + SCpnt->SCp.phase, + SCpnt->target, + *(UCHAR *) SCpnt->cmnd, + SCpnt->use_sg, SCpnt->request_bufflen); + printk("sent_command = %d, have_data_in = %d, timeout = %d\n", + SCpnt->SCp.sent_command, + SCpnt->SCp.have_data_in, SCpnt->timeout); + } + + int ultima_handle(Scsi_Cmnd * SCpnt) + { + // Added 2003/11/09 by Ashuaria Lee + #warning I dont know what to do... + return 0; + } + + int ultima_abort(Scsi_Cmnd * SCpnt) + { + ULONG flags; + + if (!in_command) + { + return SCSI_ABORT_NOT_RUNNING; + } + ultima_cardreset(); + print_info(SCpnt); + current_SC->SCp.phase |= aborted; + current_SC->result = DID_ABORT << 16; + + /* Aborts are not done well. . . */ + if (in_command) + my_done(DID_ABORT << 16); + + return SCSI_ABORT_SUCCESS; + } + + int ultima_reset(Scsi_Cmnd * SCpnt, unsigned int ignored) + { + ultima_cardreset(); + return SCSI_RESET_WAKEUP; + } + + int ultima_1cardreset(int BoardID) + { + int i,k; + UCHAR statusByte,statusByte2; + + + SelectFirstChannel(BoardID); + mdelay(20); + outw(0x8000,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x4000,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x0,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + + SelectSecondChannel(BoardID); + outw(0x8000,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x4000,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + outw(0x0,BoardInfo[BoardID].PrimaryDmaIO + 0x0e); + mdelay(20); + /* + for (i=0;i<200;i++) + { + SelectFirstChannel(BoardID); + mdelay(1); + outb(0xA0, BoardInfo[BoardID].PrimaryIO + DriveSelectPort); + mdelay(5); + GetBaseStatus(BoardInfo[BoardID].PrimaryIO, statusByte); + mdelay(5); + + SelectSecondChannel(BoardID); + mdelay(1); + outb(0xA0, BoardInfo[BoardID].PrimaryIO + DriveSelectPort); + mdelay(5); + GetBaseStatus(BoardInfo[BoardID].PrimaryIO, statusByte2); + mdelay(5); + + if (!(statusByte & 0x80) && !(statusByte2 & 0x80)) + break; + } + + for (i=0;i<500;i++) { + mdelay(1); + } + */ + for (i=0;i<200;i++) { + mdelay(20); + } + /* + if (HddConnected[BoardID][0][0]) + { + IdentifyDisk(BoardID, + 0, + 0, + &DiskIdentifyData[BoardID][0][0]); + } + if (HddConnected[BoardID][0][1]) + { + IdentifyDisk(BoardID, + 0, + 1, + &DiskIdentifyData[BoardID][0][1]); + } + if (HddConnected[BoardID][1][0]) + { + IdentifyDisk(BoardID, + 1, + 0, + &DiskIdentifyData[BoardID][1][0]); + } + if (HddConnected[BoardID][1][1]) + { + IdentifyDisk(BoardID, + 1, + 1, + &DiskIdentifyData[BoardID][1][1]); + } + */ + // Added 2003/11/09 by Ashuaria Lee + #warning I dont know what to do... + return 0; + } + + + int ultima_cardreset(void) + { + int i,j; + + RWStatus = RESET_STATUS; + + for(i=0;i> 4; + + info_array[0] = 16; + info_array[1] = 63; + + size = DiskID[target].DiskStatus.Size; + info_array[2] = size / (info_array[0] * info_array[1]); + + if (info_array[2] > 1024) { + info_array[0] = 0xff; + info_array[2] = + (ULONG) size / (info_array[0] * info_array[1]); + } + return 0; + } diff -Ncr linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/ultima.h linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/ultima.h *** linux-2.4.20-20.9.ashuaria0/drivers/scsi/ultimaraid133/ultima.h 1970-01-01 09:00:00.000000000 +0900 --- linux-2.4.20-20.9.ashuaria3/drivers/scsi/ultimaraid133/ultima.h 2003-12-03 00:34:32.000000000 +0900 *************** *** 0 **** --- 1,239 ---- + #ifndef _ULTIMA_H + #define _ULTIMA_H + #include + + #ifndef UCHAR + #define UCHAR unsigned char + #define USHORT unsigned short + #define ULONG unsigned long + #define DWORD unsigned long + #define BYTE unsigned char + #define WORD unsigned short + #endif + + #define ARALION_VENDOR 0x1538 + #define ULTIMA_DEVICE 0x0303 + + #define READ_STATUS 0x10000000 + #define WRITE_STATUS 0x20000000 + #define RESET_STATUS 0x40000000 + #define REBUILD_STATUS 0x80000000 + #define MIRRORWRITE_STATUS 0x01000000 + /* + #define ORDER_FIRST 0x00000001 + #define ORDER_LAST 0x00000010 + */ + + #define ORDER_ONE 0x00000001 + #define ORDER_TWO 0x00000010 + #define ORDER_THREE 0x00000100 + #define ORDER_FOUR 0x00001000 + + + #define DataPort 0x00 + #define ErrorPort 0x01 + #define BlockCountPort 0x02 + #define BlockNumberPort 0x03 + #define CylinderLowPort 0x04 + #define CylinderHighPort 0x05 + #define DriveSelectPort 0x06 + #define CommandPort 0x07 + #define AlternateStatusPort 0x0E + + #define FLASH_ADDRESS 0x02 + #define FLASH_COMMAND 0x04 + #define FLASH_STATUS 0x06 + + #define SCATTERLISTSIZE 4096 + + #define NODISK 0x00000000 + #define NORMALIDE 0x00000001 + #define STRIPING_2S 0x00000002 + #define STRIPING_4S 0x00000003 + #define MIRRORING 0x00000004 + #define STRIPMIRRORING_2S 0x00000005 + #define STRIPMIRRORING_4S 0x00000006 + #define JBOD 0x00000007 + //#define STRIPMIRRORING2 + + #define NOTAVAILABLE 0x0000ffff + #define ERROR_INVALID_SECTORCOUNT 0x00000001 + #define ERROR_DISK_NOTAVAILABLE 0x00000002 + #define ERROR_INVALID_CHANNEL 0x00000003 + + #define MAXBOARD 4 + + #define NORMALSTATUS 0x00000000 + #define DISKSWAPPED 0x00000001 + #define MIRRORDISABLED 0x00000002 + #define REBUILDING 0x00000010 + #define REBUILDED 0x00000020 + #define DISKNOTAVAILABLE 0x80000000 + + extern int ultima_detect( Scsi_Host_Template * ); + extern int ultima_release( struct Scsi_Host * tpnt); + extern int ultima_command( Scsi_Cmnd * ); + extern int ultima_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); + extern int ultima_abort( Scsi_Cmnd * ); + extern int ultima_reset( Scsi_Cmnd *, unsigned int ); + extern int ultima_biosparam( Disk *, kdev_t, int * ); + extern int ultima_handle( Scsi_Cmnd * ); + extern char * ultima_info( struct Scsi_Host * ); + extern int ultima_cardreset( void ); + extern int ultima_proc_info( char *buffer, char **start, off_t offset, + int length, int hostno, int inout ); + + extern struct proc_dir_entry proc_scsi_aralion; + + #define ULTIMA_REVID "Aralion ATA133 IDE Raid Controller driver; Revision: LH1.00BCS" + + #define ULTIMA_DMA133 { \ + next: NULL, \ + module: NULL, \ + proc_dir: NULL, \ + proc_name: "Aralion", \ + proc_info: ultima_proc_info, \ + name: "Ultima RAID 133", \ + detect: ultima_detect, \ + release: ultima_release, \ + info : NULL, \ + ioctl: NULL, \ + command: NULL, \ + queuecommand: ultima_queue, \ + abort: ultima_abort, \ + reset: ultima_reset, \ + slave_attach: NULL, \ + bios_param: ultima_biosparam, \ + can_queue: 1, \ + this_id: 15, \ + present: 0, \ + sg_tablesize: 16, \ + cmd_per_lun: 0, /* cmds per lun */\ + use_clustering: DISABLE_CLUSTERING, \ + use_new_eh_code: 0}; + + typedef struct + { + char *buffer; + unsigned long bufferlen; + } IoctlParam; + + typedef struct + { + char signature[8]; + unsigned long IOPort1; + unsigned long irq; + } IrqID; + + typedef struct { + DWORD BoardID; + DWORD Channel; + DWORD Drive; + DWORD Size; + } DISKLIST; + + typedef struct { + DWORD RaidStatus; + DISKLIST DiskStatus; + } _DiskIDTable; + + typedef struct _PDT_TABLE { + ULONG address; + USHORT length; + UCHAR Reserved; + UCHAR EndOfChain; + } PDT_TABLE, *PPDT_TABLE; + + typedef struct + { + PDT_TABLE ScatterList[128]; + ULONG ListCount; + ULONG NumSectors; + ULONG StartLba; + ULONG InterruptFlag; + } DISKRWINFO; + + typedef struct _BOARDTABLE { + ULONG PrimaryIO; + ULONG SecondaryIO; + ULONG PrimaryDmaIO; + ULONG SecondaryDmaIO; + ULONG ControlRegister; + ULONG FlashMemory; + ULONG interrupt_level; + + PPDT_TABLE PriScatterList; + PPDT_TABLE SecScatterList; + + ULONG ListCount; + ULONG NumSectors; + ULONG StartLba; + ULONG InterruptFlag[2]; + } BOARDTABLE,*PBOARDsTABLE; + + typedef struct _V6BDISKINFO + { + UCHAR Mode; + UCHAR PhysicalDrive; + UCHAR Order; + }V6BDISKINFO,*PV6BDISK; + + typedef struct _V6InterfaceB + { + ULONG TagField; + USHORT Version; + UCHAR Reserved; + UCHAR StructSize; + USHORT RebuildBit; + UCHAR Mode; + UCHAR IsSafeMode; + ULONG Reserved1; + ULONG BaseHddSize[8]; + V6BDISKINFO DiskInfo[4][4]; + UCHAR Reserved2[5]; + UCHAR ProcInfo[4]; + UCHAR Reserved3[151]; + }V6INTERFACEB,*PV6INTERFACEB; + + #define GetStatus(BaseIoAddress, Status) Status = inb((BaseIoAddress) + AlternateStatusPort); + + #define GetBaseStatus(BaseIoAddress, Status) \ + Status = inb(BaseIoAddress + CommandPort); + + #define Delayed_Time(delay) { \ + ULONG j = jiffies + delay * HZ; \ + struct wait_queue *wait = NULL; \ + current->timeout = j; \ + interruptible_sleep_on(&wait); } + + #define WaitOnBusy(BaseIoAddress, Status) {ULONG i; \ + for (i=0; i<5; i++) { \ + GetStatus((BaseIoAddress), Status); \ + if (Status & IDE_STATUS_BUSY) { \ + udelay(1); \ + continue; \ + } else { \ + break; \ + } \ + } \ + } + + #define WaitForDrq(BaseIoAddress, Status) \ + { \ + ULONG i; \ + for (i=0; i<1000; i++) { \ + GetStatus(BaseIoAddress, Status); \ + if (Status & IDE_STATUS_BUSY) { \ + udelay(150); \ + } else if (Status & IDE_STATUS_DRQ) { \ + break; \ + } else { \ + udelay(200); \ + } \ + } \ + } + + #endif + #define SelectFirstChannel(BoardID) outb(0xA0,BoardInfo[BoardID].SecondaryIO+DriveSelectPort); + #define SelectSecondChannel(BoardID) outb(0xB0,BoardInfo[BoardID].SecondaryIO+DriveSelectPort); +