diff -Ncr /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/Config.in /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/Config.in
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/Config.in	2003-11-20 01:22:48.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/Config.in	2003-11-25 18:09:28.000000000 +0900
***************
*** 207,212 ****
--- 207,213 ----
  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
diff -Ncr /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/Makefile /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/Makefile
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/Makefile	2003-11-20 01:22:50.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/Makefile	2003-11-25 18:10:36.000000000 +0900
***************
*** 30,35 ****
--- 30,36 ----
  subdir-m			+= aic7xxx
  subdir-$(CONFIG_SCSI_NEWISP)	+= isp
  subdir-$(CONFIG_PCMCIA)		+= pcmcia
+ subdir-$(CONFIG_SCSI_ULTIMARAID100)	+= ultimaraid100
  subdir-$(CONFIG_SCSI_ULTIMARAID133)	+= ultimaraid133
  
  
***************
*** 77,82 ****
--- 78,86 ----
  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
diff -Ncr /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/Makefile /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/Makefile
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/Makefile	1970-01-01 09:00:00.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/Makefile	2003-11-25 18:12:48.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 /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/README /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/README
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/README	1970-01-01 09:00:00.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/README	2003-11-25 18:07:56.000000000 +0900
***************
*** 0 ****
--- 1,22 ----
+ 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. <www.aralion.co.kr>	(Original ATA ONLY Driver source)
+ Ashuaria Lee <ashuaria@intizen.com>	(Patch for Linux Kernel Tree)
+ 
+ Original Driver
+ -------------------------
+ Aralion Linux Development
+ 
+ Mailing List
+ -------------------------
+ None yet!
diff -Ncr /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/TODO /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/TODO
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/TODO	1970-01-01 09:00:00.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/TODO	2003-11-24 17:03:07.000000000 +0900
***************
*** 0 ****
--- 1,3 ----
+ o	Testing
+ o	More testing
+ o	Many more
diff -Ncr /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/atapi.h /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/atapi.h
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/atapi.h	1970-01-01 09:00:00.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/atapi.h	2002-08-21 15:26:50.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 /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/scsi_module.c /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/scsi_module.c
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/scsi_module.c	1970-01-01 09:00:00.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/scsi_module.c	2002-08-21 15:26:50.000000000 +0900
***************
*** 0 ****
--- 1,71 ----
+ /*
+  *  scsi_module.c Copyright (1994, 1995) Eric Youngdale.
+  *
+  * Support for loading low-level scsi drivers using the linux kernel loadable
+  * module interface.
+  *
+  * To use, the host adapter should first define and initialize the variable
+  * driver_template (datatype Scsi_Host_Template), and then include this file.
+  * This should also be wrapped in a #ifdef MODULE/#endif.
+  *
+  * The low -level driver must also define a release function which will
+  * free any irq assignments, release any dma channels, release any I/O
+  * address space that might be reserved, and otherwise clean up after itself.
+  * The idea is that the same driver should be able to be reloaded without
+  * any difficulty.  This makes debugging new drivers easier, as you should
+  * be able to load the driver, test it, unload, modify and reload.
+  *
+  * One *very* important caveat.  If the driver may need to do DMA on the
+  * ISA bus, you must have unchecked_isa_dma set in the device template,
+  * even if this might be changed during the detect routine.  This is
+  * because the shpnt structure will be allocated in a special way so that
+  * it will be below the appropriate DMA limit - thus if your driver uses
+  * the hostdata field of shpnt, and the board must be able to access this
+  * via DMA, the shpnt structure must be in a DMA accessible region of
+  * memory.  This comment would be relevant for something like the buslogic
+  * driver where there are many boards, only some of which do DMA onto the
+  * ISA bus.  There is no convenient way of specifying whether the host
+  * needs to be in a ISA DMA accessible region of memory when you call
+  * scsi_register.
+  */
+ 
+ #include <linux/module.h>
+ #include <linux/init.h>
+ 
+ static int __init init_this_scsi_driver(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 -ENODEV;
+ }
+ 
+ static void __exit exit_this_scsi_driver(void)
+ {
+ 	scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
+ }
+ 
+ module_init(init_this_scsi_driver);
+ module_exit(exit_this_scsi_driver);
+ 
+ /*
+  * Overrides for Emacs so that we almost follow Linus's tabbing style.
+  * Emacs will notice this stuff at the end of the file and automatically
+  * adjust the settings for this buffer only.  This must remain at the end
+  * of the file.
+  * ---------------------------------------------------------------------------
+  * Local variables:
+  * c-indent-level: 4
+  * c-brace-imaginary-offset: 0
+  * c-brace-offset: -4
+  * c-argdecl-indent: 4
+  * c-label-offset: -4
+  * c-continued-statement-offset: 4
+  * c-continued-brace-offset: 0
+  * indent-tabs-mode: nil
+  * tab-width: 8
+  * End:
+  */
diff -Ncr /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/scsi_obsolete.h /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/scsi_obsolete.h
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/scsi_obsolete.h	1970-01-01 09:00:00.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/scsi_obsolete.h	2002-08-21 15:26:50.000000000 +0900
***************
*** 0 ****
--- 1,106 ----
+ /*
+  *  scsi_obsolete.h Copyright (C) 1997 Eric Youngdale
+  *
+  */
+ 
+ #ifndef _SCSI_OBSOLETE_H
+ #define _SCSI_OBSOLETE_H
+ 
+ /*
+  * These are the return codes for the abort and reset functions.  The mid-level
+  * code uses these to decide what to do next.  Each of the low level abort
+  * and reset functions must correctly indicate what it has done.
+  * The descriptions are written from the point of view of the mid-level code,
+  * so that the return code is telling the mid-level drivers exactly what
+  * the low level driver has already done, and what remains to be done.
+  */
+ 
+ /* We did not do anything.  
+  * Wait some more for this command to complete, and if this does not work, 
+  * try something more serious. */
+ #define SCSI_ABORT_SNOOZE 0
+ 
+ /* This means that we were able to abort the command.  We have already
+  * called the mid-level done function, and do not expect an interrupt that 
+  * will lead to another call to the mid-level done function for this command */
+ #define SCSI_ABORT_SUCCESS 1
+ 
+ /* We called for an abort of this command, and we should get an interrupt 
+  * when this succeeds.  Thus we should not restore the timer for this
+  * command in the mid-level abort function. */
+ #define SCSI_ABORT_PENDING 2
+ 
+ /* Unable to abort - command is currently on the bus.  Grin and bear it. */
+ #define SCSI_ABORT_BUSY 3
+ 
+ /* The command is not active in the low level code. Command probably
+  * finished. */
+ #define SCSI_ABORT_NOT_RUNNING 4
+ 
+ /* Something went wrong.  The low level driver will indicate the correct
+  * error condition when it calls scsi_done, so the mid-level abort function
+  * can simply wait until this comes through */
+ #define SCSI_ABORT_ERROR 5
+ 
+ /* We do not know how to reset the bus, or we do not want to.  Bummer.
+  * Anyway, just wait a little more for the command in question, and hope that
+  * it eventually finishes.  If it never finishes, the SCSI device could
+  * hang, so use this with caution. */
+ #define SCSI_RESET_SNOOZE 0
+ 
+ /* We do not know how to reset the bus, or we do not want to.  Bummer.
+  * We have given up on this ever completing.  The mid-level code will
+  * request sense information to decide how to proceed from here. */
+ #define SCSI_RESET_PUNT 1
+ 
+ /* This means that we were able to reset the bus.  We have restarted all of
+  * the commands that should be restarted, and we should be able to continue
+  * on normally from here.  We do not expect any interrupts that will return
+  * DID_RESET to any of the other commands in the host_queue, and the mid-level
+  * code does not need to do anything special to keep the commands alive. 
+  * If a hard reset was performed then all outstanding commands on the
+  * bus have been restarted. */
+ #define SCSI_RESET_SUCCESS 2
+ 
+ /* We called for a reset of this bus, and we should get an interrupt 
+  * when this succeeds.  Each command should get its own status
+  * passed up to scsi_done, but this has not happened yet. 
+  * If a hard reset was performed, then we expect an interrupt
+  * for *each* of the outstanding commands that will have the
+  * effect of restarting the commands.
+  */
+ #define SCSI_RESET_PENDING 3
+ 
+ /* We did a reset, but do not expect an interrupt to signal DID_RESET.
+  * This tells the upper level code to request the sense info, and this
+  * should keep the command alive. */
+ #define SCSI_RESET_WAKEUP 4
+ 
+ /* The command is not active in the low level code. Command probably
+    finished. */
+ #define SCSI_RESET_NOT_RUNNING 5
+ 
+ /* Something went wrong, and we do not know how to fix it. */
+ #define SCSI_RESET_ERROR 6
+ 
+ #define SCSI_RESET_SYNCHRONOUS		0x01
+ #define SCSI_RESET_ASYNCHRONOUS		0x02
+ #define SCSI_RESET_SUGGEST_BUS_RESET	0x04
+ #define SCSI_RESET_SUGGEST_HOST_RESET	0x08
+ /*
+  * This is a bitmask that is ored with one of the above codes.
+  * It tells the mid-level code that we did a hard reset.
+  */
+ #define SCSI_RESET_BUS_RESET 0x100
+ /*
+  * This is a bitmask that is ored with one of the above codes.
+  * It tells the mid-level code that we did a host adapter reset.
+  */
+ #define SCSI_RESET_HOST_RESET 0x200
+ /*
+  * Used to mask off bits and to obtain the basic action that was
+  * performed.  
+  */
+ #define SCSI_RESET_ACTION   0xff
+ 
+ #endif				/* SCSI_OBSOLETE_H */
diff -Ncr /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/ultima.c /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/ultima.c
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/ultima.c	1970-01-01 09:00:00.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/ultima.c	2002-09-04 15:41: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 <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/sched.h>
+ #include <asm/io.h>
+ #include <linux/blk.h>
+ #include "/usr/src/linux-2.4/drivers/scsi/scsi.h"
+ #include "/usr/src/linux-2.4/drivers/scsi/hosts.h"
+ #include "ultima.h"
+ #include "atapi.h"
+ #include <asm/system.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/ioport.h>
+ #include <linux/proc_fs.h>
+ #include <linux/pci.h>
+ #include <linux/stat.h>
+ #include <linux/delay.h>
+ #include <linux/config.h>	/* for CONFIG_PCI */
+ #include <linux/fs.h>
+ #include <asm/segment.h> /* for put_user_byte */
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/bitops.h>
+ #include <asm/atomic.h>
+ //#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();
+  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 			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;i<count;i++) {
+ 		if (CmdName[i].code == code)
+ 			return CmdName[i].name;
+ 	}
+ 	return s;
+ }
+ 
+ static void     print_banner(struct Scsi_Host *shpnt)
+ {
+     if (!shpnt)
+ 	return;			/* This won't ever happen */
+ 
+     printk("using scsi id %d\n", shpnt->this_id);
+ 
+     if (interrupt_level)
+ 	printk(" int %d", interrupt_level);
+     else
+ 	printk("<none>");
+ 
+     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() 
+ {
+ 	int			i;
+ 	int			irq;
+ 	int			retcode;
+ 	
+ 	for(i=0;i<gBoardCount;i++) {
+ 		irq = BoardInfo[i].interrupt_level;
+ 		
+ 		if (!IrqFlag[irq]) {
+ 			IrqFlag[irq] = 1;
+ 			memset(ultimaID[i].signature,0,8);
+ 			memcpy(ultimaID[i].signature,"Ultima",6);
+ 			ultimaID[i].IOPort1 = BoardInfo[i].PrimaryDmaIO;
+ 			ultimaID[i].irq = irq;
+ 
+ //			if (i == 0) 
+ 			{
+ //				printk("Int = %d\n",irq);
+ 			    retcode = request_irq(irq,
+ 						  do_ultima_intr, 
+ 						  SA_INTERRUPT | SA_SHIRQ, 
+ 						  "aralion", 
+ 						  &ultimaID[i]);
+ 			}
+ #ifdef DEBUG											  
+ //    		printk("retcode = %d,%d\n", i,retcode);
+ #endif
+ 		    if (retcode < 0)
+ 			{
+ 				printk("%d's Board IRQ Failure\n",i);
+ 				
+ 			    if (retcode == -EINVAL)	{
+ 				    printk("scsi: <aralion> 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: <aralion> IRQ %d is already in use!\n",irq);
+ 				    printk("                Please use another IRQ!\n");
+ 			    } else {
+ 				    printk("scsi: <aralion> Error getting IRQ %d\n",irq);
+ 				    printk("                This shouldn't happen!\n");
+ 				    printk("                Send mail to faith@acm.org\n");
+ 				}
+ 			    printk("scsi: <aralion> 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;i<gBoardCount;i++)
+ 	{
+ 		gResetFlag = 1;
+ 		DisableInterrupt(i);
+ 		ultima_1cardreset(i);
+ 		for(j=0;j<4;j++)
+ 		{
+ 			if(IdentifyDisk(i,j/2,j%2,&DiskIdentifyData[i][j/2][j%2]) == 1)
+ 			{	
+ 				DiskID[DiskCount].DiskStatus.BoardID = i;
+ 				DiskID[DiskCount].DiskStatus.Channel = j/2;
+ 				DiskID[DiskCount].DiskStatus.Drive = j%2;
+ 				DiskID[DiskCount].DiskStatus.Size = GetBlockCount(i,j/2,j%2);
+ 				DiskID[DiskCount].RaidStatus = NORMALIDE;
+ 				DiskCount++;
+ 			}
+ 		}
+ 		mdelay(100);
+ 		EnableInterrupt(i);
+ 		gResetFlag = 0;
+ 	}
+ 
+ ////////////////////////////////////////////////////////////////////////////
+ 	
+ 	DriverInit = 1;
+ 
+     tpnt->this_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: <aralion>"
+ 		   " 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<gBoardCount;i++) {
+ 		BoardInfo[i].PriScatterList = kmalloc(SCATTERLISTSIZE,GFP_ATOMIC);
+ 		BoardInfo[i].SecScatterList = kmalloc(SCATTERLISTSIZE,GFP_ATOMIC);
+ 	}			
+ //	printk("ultima_detect End..\n");
+ 	return 1;			/* Maximum of one adapter will be detected. */
+ }
+ 
+ int             ultima_release(struct Scsi_Host * tpnt)
+ {
+ 	int		i;
+ 	int		irq;
+ 	
+ 	for(i=0;i<gBoardCount;i++) {
+ 		irq = BoardInfo[i].interrupt_level;
+ 		if (IrqFlag[irq]) {
+ 			free_irq(irq,&ultimaID[i]);
+ 			IrqFlag[irq] = 0;
+ 		}
+ 		release_region(BoardInfo[i].PrimaryIO,0x10);
+ 		release_region(BoardInfo[i].SecondaryIO,0x10);
+ 		release_region(BoardInfo[i].PrimaryDmaIO,0x10);
+ 		release_region(BoardInfo[i].SecondaryDmaIO,0x10);
+ 		release_region(BoardInfo[i].ControlRegister,0x10);
+ 
+ 		kfree(BoardInfo[i].PriScatterList);
+ 		kfree(BoardInfo[i].SecScatterList);
+ 	}
+ 	scsi_unregister(tpnt);
+ 	
+ 	return 0;
+ }
+ 
+ #ifdef DEBUG
+  void printDMARegister(int BoardID)
+ {
+ 	int i;
+ 	USHORT d1;
+ 
+ 	for(i=0;i<0x10;i++) {
+ 		d1 = inw(BoardInfo[BoardID].ControlRegister + i*2);
+ 		printk("<%02x:%04x> ",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;i<SCpnt->use_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;i<count;i++) {
+ 		printk("%04d : [%08x,%04x,%02x]\n",i,
+ 				pPDTTable[i].address,
+ 				pPDTTable[i].length,
+ 				pPDTTable[i].EndOfChain);
+ 	}	
+ }
+ 
+  void SetIOPort(DISKLIST *pList,USHORT DmaRW,DWORD OrderFlag)
+ {
+ 	USHORT		AddressLow,AddressHi;
+ 	PPDT_TABLE  pPDTTable;
+ 	long		i;
+ 	DISKRWINFO	*pRWInfo;
+ 	ULONG		BoardID,Channel,Drive;
+ 	ULONG		IOPort1,DmaIO;
+ 
+ 	BoardID = pList->BoardID;
+ 	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<MAXBOARD;i++) {
+ 		if (BoardInfo[i].InterruptFlag[0] & OrderFlag) {
+ 			if(BoardInfo[i].StartLba >= 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;i<gBoardCount;i++) {
+         for(j=0;j<2;j++) {
+             for(k=0;k<2;k++) {
+                 if ((OrderFlag & DiskRWInfo[i][j][k].InterruptFlag)) 
+ 				{
+                     if (j == 0) 
+ 					{
+ 						DmaIO = BoardInfo[i].PrimaryDmaIO;
+ 					}
+ 					else 
+ 					{
+ 						DmaIO = BoardInfo[i].SecondaryDmaIO;
+ 					}
+                 	outw(DmaRW,DmaIO + CMDR);
+                  }
+             }
+         }
+     }
+ }
+ 
+ 
+ static int			ReadDMA(
+ 						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(RaidStatus) {
+ 	switch(DiskID[SCpnt->target].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: <aralion> current_SC->scsi_done() == NULL");
+     } else
+ 	{
+ 	    panic("scsi: <aralion> 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 <BoardID,Channel> = <%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()
+ {
+ 	ULONG	Channel;
+     UCHAR   statusByte = 0;
+     UCHAR   statusByte2 = 0;
+     ULONG   IOPort1,IOPort2;
+ 	ULONG 	scsiStatus = 0;
+ 	int		i;
+ 
+ 	for(i=0;i<gBoardCount;i++) 
+ 	{
+ 		Channel = inw(BoardInfo[i].ControlRegister + INTSRC) & 0x03;
+ //		printk("I:[%d,%x]",i,Channel);
+ 
+ 		if (Channel == 0) 
+ 			continue;
+ 
+ 		statusByte = statusByte2 = 0;
+ 		
+ 		if (Channel != 3 && 
+ 			( (BoardInfo[i].InterruptFlag[0] & OrderStatus) &
+ 			  (BoardInfo[i].InterruptFlag[1] & OrderStatus)
+ 			)
+ 		   )	
+ 			continue;
+ 		if (Channel & 1) 
+ 		{
+ 			IOPort1 = BoardInfo[i].PrimaryIO;
+ 			CheckJobFinished(i,1);
+ 	   		GetBaseStatus(IOPort1, statusByte);
+ 			BoardInfo[i].InterruptFlag[0] &= (~OrderStatus);
+ 		}
+ 		if (Channel & 2) 
+ 		{
+ 			IOPort2 = BoardInfo[i].SecondaryIO;
+ 			CheckJobFinished(i,2);
+ 			GetBaseStatus(IOPort2, statusByte2);
+ 			BoardInfo[i].InterruptFlag[1] &= (~OrderStatus);
+ 		}
+ 	}
+ }
+ 
+  void            do_ultima_intr(int irq, void *dev_id, struct pt_regs *regs)
+ {
+ 	ULONG	Channel;
+     UCHAR   statusByte = 0;
+     UCHAR   statusByte2 = 0;
+     ULONG   IOPort1,IOPort2;
+ 	ULONG 	scsiStatus = 0;
+ 	IrqID	*pIntID;
+ 	int		i,j,flag;
+     int     ClearFlag = 0;
+ 	int		InterruptCount;
+ 	unsigned long flags;
+ 									
+ 	spin_lock_irqsave(&io_request_lock, flags);
+ 	pIntID = (IrqID *) dev_id;
+ 
+ //	printk("< intr >\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;i<gBoardCount;i++) {
+ 			USHORT		Intena;
+ 
+ 			Channel = inw(BoardInfo[i].ControlRegister + INTSRC);
+ 			Intena = inw(BoardInfo[i].ControlRegister + INTENA);
+ 			IOPort1 = BoardInfo[i].PrimaryIO;
+ 			IOPort2 = BoardInfo[i].SecondaryIO;
+ 			if (Channel & 1) {
+ 				CheckJobFinished(i,1);
+ 		   		GetBaseStatus(IOPort1, statusByte);
+ 			}
+ 			if (Channel & 2) {
+ 				CheckJobFinished(i,2);
+ 		   		GetBaseStatus(IOPort2, statusByte2);
+ 			}
+ 			if (statusByte & 0x1) 
+ 				scsiStatus = CheckScsiError(Channel,IOPort1,statusByte);
+ 	   		GetBaseStatus(IOPort1, statusByte);//KHG
+ 
+ 			if (statusByte2 & 0x1)
+ 				scsiStatus = CheckScsiError(Channel,IOPort2,statusByte);
+ 	   		GetBaseStatus(IOPort2, statusByte2);//KHG
+ 		}
+ 		spin_unlock_irqrestore(&io_request_lock, flags);
+ 		return ;
+ 
+ 	}
+ 
+ 	if (!in_command) {
+  		ClearAllIrq();
+ 		spin_unlock_irqrestore(&io_request_lock, flags);
+ 		return ;
+ 	}
+ 
+ 	for(i=0;i<gBoardCount;i++) {
+ 		Channel = inw(BoardInfo[i].ControlRegister + INTSRC) & 0x03;
+ 		if (Channel == 0) 
+ 			continue;
+ 
+ 		flag = 0;
+ 		statusByte = statusByte2 = 0;
+ 		
+ 		if (Channel != 3 && 
+ 			( (BoardInfo[i].InterruptFlag[0] & OrderStatus) &
+ 			  (BoardInfo[i].InterruptFlag[1] & OrderStatus)
+ 			)
+ 		   )	
+ 			continue;
+ 
+ 		if (Channel & 1) {
+ 			IOPort1 = BoardInfo[i].PrimaryIO;
+ 			CheckJobFinished(i,1);
+ 	   		GetBaseStatus(IOPort1, statusByte);
+ 			BoardInfo[i].InterruptFlag[0] &= (~OrderStatus);
+ 		}
+ 		if (Channel & 2) {
+ 			IOPort2 = BoardInfo[i].SecondaryIO;
+ 			CheckJobFinished(i,2);
+ 	   		GetBaseStatus(IOPort2, statusByte2);
+ 			BoardInfo[i].InterruptFlag[1] &= (~OrderStatus);
+ 		}
+ 
+ 		if (statusByte & 0x1) 
+ 			scsiStatus = CheckScsiError(Channel,IOPort1,statusByte);
+ 
+ 		if (statusByte2 & 0x1) 
+ 			scsiStatus = CheckScsiError(Channel,IOPort2,statusByte);
+ 	}
+ 
+ 	if (OrderStatus != ORDER_FOUR) {
+ 		for(i=0;i<gBoardCount;i++) {
+ 			if (BoardInfo[i].InterruptFlag[0] & OrderStatus || BoardInfo[i].InterruptFlag[1] & OrderStatus) {
+ 				spin_unlock_irqrestore(&io_request_lock, flags);
+ 				return ;
+ 			}
+ 		}	
+ 		flag = 0;
+ 		
+ 		for(i=0;i<gBoardCount;i++) {
+ 			if ((BoardInfo[i].InterruptFlag[0] & ORDER_TWO || BoardInfo[i].InterruptFlag[1] & ORDER_TWO) && (OrderStatus == ORDER_ONE)) {
+ 				flag = 1;
+ 			}
+ 			if ((BoardInfo[i].InterruptFlag[0] & ORDER_THREE || BoardInfo[i].InterruptFlag[1] & ORDER_THREE) && (OrderStatus == ORDER_TWO)) {
+ 				flag = 1;
+ 			}
+ 			if ((BoardInfo[i].InterruptFlag[0] & ORDER_FOUR || BoardInfo[i].InterruptFlag[1] & ORDER_FOUR) && (OrderStatus == ORDER_THREE)) {
+ 				flag = 1;
+ 			}
+ 		}	
+ 		
+ 		if (flag) {
+ 			OrderStatus <<= 4;
+ 			if (RWStatus == READ_STATUS) {
+ 				SetIOInformation(CurrentDisk,DMA_READ,OrderStatus);
+ 				SetIDECommand(IDE_COMMAND_READ_DMA,OrderStatus);
+    				SetDMACommand(DMA_READ,OrderStatus);
+ 			}
+ 			else {
+ 				SetIOInformation(CurrentDisk,DMA_WRITE,OrderStatus);
+ 				SetIDECommand(IDE_COMMAND_WRITE_DMA,OrderStatus);
+    				SetDMACommand(DMA_WRITE,OrderStatus);
+ 			}
+ 			spin_unlock_irqrestore(&io_request_lock, flags);
+ 			return ;
+ 		}
+ 		else {
+ 
+ 			my_done(scsiStatus << 16);
+ 			spin_unlock_irqrestore(&io_request_lock, flags);
+ 			return ;
+ 		}
+ 	}
+ 	else {
+ 		for(i=0;i<gBoardCount;i++) {
+ 	
+ 			if (BoardInfo[i].InterruptFlag[0] & ORDER_FOUR || BoardInfo[i].InterruptFlag[1] & ORDER_FOUR) {
+ 				spin_unlock_irqrestore(&io_request_lock, flags);
+ 				return ;
+ 			}
+ 		}	
+ 	}
+ 	my_done(scsiStatus << 16);
+ 	spin_unlock_irqrestore(&io_request_lock, flags);
+ 	
+ 	return;
+ }
+ 
+ void     internal_done(Scsi_Cmnd * SCpnt)
+ {
+     internal_done_errcode = SCpnt->result;
+     ++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;i<gBoardCount;i++) {
+ 							BoardInfo[i].InterruptFlag[0] = 0;
+ 							BoardInfo[i].InterruptFlag[1] = 0;
+ 						}
+ 						CurrentDisk = current_SC->target;
+ 						
+ 						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;i<SCpnt->use_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;i<gBoardCount;i++)
+ 		{
+ 			for(j=0; j<4; j++)
+ 			{
+ 				if((HddConnected[i][j/2][0] == 0) 
+ 						&& (HddConnected[i][j/2][1] ==0))
+ 				{
+ 					if(j/2)
+ 						IOPort1 = BoardInfo[i].SecondaryIO;
+ 					else
+ 						IOPort1 = BoardInfo[i].PrimaryIO;
+ 					gResetFlag = 1;
+ 					HddConnected[i][j/2][j%2] = 1;
+ 					DisableInterrupt(i);
+ 	 				ultima_1channelreset(i,j/2);
+ 					if(IdentifyDisk(i,j/2,j%2,&DiskIdentifyData[i][j/2][j%2]) == 1)
+ 					{
+ 						DiskID[DiskCount].DiskStatus.BoardID = i;
+ 						DiskID[DiskCount].DiskStatus.Channel = j/2;
+ 						DiskID[DiskCount].DiskStatus.Drive = j%2;
+ 						DiskID[DiskCount].DiskStatus.Size = GetBlockCount(i,j/2,j%2);
+ 						DiskID[DiskCount].RaidStatus = NORMALIDE;
+ 						DiskCount++;
+ 						EnableInterrupt(i);
+ 						mdelay(200);
+ 						gResetFlag = 0;
+ 						return 1;
+ 					}
+ 					EnableInterrupt(i);
+ 					mdelay(200);
+ 					gResetFlag = 0;
+ 				}
+ 			}
+ 		}
+ 		return 0;
+ 	}
+ 	else if(target < DiskCount)
+ 	{
+ 		i = DiskID[target].DiskStatus.BoardID;
+ 		j = DiskID[target].DiskStatus.Channel;
+ 		k = DiskID[target].DiskStatus.Drive;
+ 		if(j == 0)
+ 			IOPort1 = BoardInfo[i].PrimaryIO;
+ 		else
+ 			IOPort1 = BoardInfo[i].SecondaryIO;
+ 		if(HddConnected[i][j][(k+1)%2] == 0) 
+ 		{
+ 			gResetFlag = 1;
+ 			DisableInterrupt(i);
+ 			ultima_1channelreset(i,j);
+ 			if(IdentifyDisk(i,j,k, &DiskIdentifyData[i][j][k]))
+ 			{
+ 				EnableInterrupt(i);
+ 				mdelay(200);
+ 				gResetFlag = 0;
+ 				DiskID[target].DiskStatus.Size = GetBlockCount(i,j,k);
+ 				return 1;
+ 			}
+ 			else
+ 			{
+ 				EnableInterrupt(i);
+ 				mdelay(200);
+ 				gResetFlag = 0;
+ 				return 0;
+ 			}
+ 		}
+ 		else return 1;
+ 	}
+ 	else 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;
+ }
+ 
+ /* End of code derived from Tommy Thorn's work. */
+ 
+ void            print_info(Scsi_Cmnd * SCpnt)
+ {
+     ULONG    imr;
+     ULONG    irr;
+     ULONG    isr;
+ 
+ //	printk("[ print_info ]\n");
+ 
+     if (!SCpnt || !SCpnt->host)
+ 	{
+ 	    printk("scsi: <aralion> 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("<ultima_handle>\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()
+ {
+ 	int		i,j,k;
+ 
+ 	RWStatus = RESET_STATUS;
+ //	printk("ultima cardreset\n");
+ 	gResetFlag = 1;
+ 	for(i=0;i<gBoardCount;i++) {
+ 		DisableInterrupt(i);
+ 		ultima_1cardreset(i);
+ 		for(j=0;j<4;j++)
+ 		{
+ 			IdentifyDisk(i,j/2,j%2,&DiskIdentifyData[i][j/2][j%2]); 
+ 		}
+ 		EnableInterrupt(i);
+ 	}
+ 	gResetFlag = 0;
+ 
+     return SCSI_RESET_WAKEUP;
+ }
+ 
+ #include "/usr/src/linux-2.4/drivers/scsi/sd.h"
+ 
+ int             ultima_biosparam(Scsi_Disk * disk, kdev_t dev,
+ 				 int *info_array)
+ {
+ 	int				size;
+ 	int				target;
+ 
+     if (MAJOR(dev) != SCSI_DISK0_MAJOR)
+ 	{
+ 	    printk("scsi: aralion ultima_biosparam: too many disks");
+ 	    return 0;
+ 	}
+ 
+     target = MINOR(dev) >> 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 /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/ultima.h /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/ultima.h
*** /usr/src/linux-2.4.20-20.9.ashuaria1/drivers/scsi/ultimaraid100/ultima.h	1970-01-01 09:00:00.000000000 +0900
--- /root/temp/linux-2.4.20_ultimaraid133devel/drivers/scsi/ultimaraid100/ultima.h	2002-08-21 15:26:50.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();
+ 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: NULL,						\
+ 			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);
+ 	
