Notice: the grml team is migrating from Mercurial to Git.
Please visit git.grml.org instead!
| author | Michael Prokop <mika@grml.org> |
| Sun Feb 25 13:04:04 2007 +0100 (21 months ago) | |
| changeset 22 | 036807a852e7 |
| manifest | 036807a852e7 |
| parent 21 | 7a552dcb6a53 |
| child 23 | e6892c881c68 |
--- a/config/config-2.6.20 Wed Feb 07 23:57:30 2007 +0100+++ b/config/config-2.6.20 Sun Feb 25 13:04:04 2007 +0100@@ -1,7 +1,7 @@## Automatically generated make config: don't edit-# Linux kernel version: 2.6.20-# Wed Feb 7 23:56:20 2007+# Linux kernel version: 2.6.20-grml+# Sun Feb 25 12:45:29 2007#CONFIG_X86_32=yCONFIG_GENERIC_TIME=y@@ -1285,6 +1285,7 @@ CONFIG_SCSI_3W_9XXX=mCONFIG_SCSI_3W_9XXX=mCONFIG_SCSI_7000FASST=mCONFIG_SCSI_ACARD=m+CONFIG_SCSI_ITERAID=mCONFIG_SCSI_AHA152X=mCONFIG_SCSI_AHA1542=mCONFIG_SCSI_AHA1740=m@@ -3638,6 +3639,8 @@ CONFIG_UFS_FS=mCONFIG_UFS_FS=m# CONFIG_UFS_FS_WRITE is not set# CONFIG_UFS_DEBUG is not set+CONFIG_UNION_FS=m+# CONFIG_UNION_FS_XATTR is not set## Network File Systems
--- /dev/null Thu Jan 01 00:00:00 1970 +0000+++ b/2.6.20/1000_2.6.20.1.patch Sun Feb 25 13:04:04 2007 +0100@@ -0,0 +1,53 @@+diff --git a/Makefile b/Makefile+index 7e2750f..d26f3f5 100644+--- a/Makefile++++ b/Makefile+@@ -1,7 +1,7 @@+ VERSION = 2+ PATCHLEVEL = 6+ SUBLEVEL = 20+-EXTRAVERSION =++EXTRAVERSION = .1+ NAME = Homicidal Dwarf Hamster++ # *DOCUMENTATION*+diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c+index edde5dc..b617428 100644+--- a/fs/nfsd/nfs2acl.c++++ b/fs/nfsd/nfs2acl.c+@@ -287,13 +287,20 @@ static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, __be32 *p,+ return 1;+ }++-static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,+- struct nfsd_fhandle *resp)++static int nfsaclsvc_release_attrstat(struct svc_rqst *rqstp, __be32 *p,++ struct nfsd_attrstat *resp)+ {+ fh_put(&resp->fh);+ return 1;+ }+++static int nfsaclsvc_release_access(struct svc_rqst *rqstp, __be32 *p,++ struct nfsd3_accessres *resp)++{++ fh_put(&resp->fh);++ return 1;++}+++ #define nfsaclsvc_decode_voidargs NULL+ #define nfsaclsvc_encode_voidres NULL+ #define nfsaclsvc_release_void NULL+@@ -322,9 +329,9 @@ struct nfsd3_voidargs { int dummy; };+ static struct svc_procedure nfsd_acl_procedures2[] = {+ PROC(null, void, void, void, RC_NOCACHE, ST),+ PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),+- PROC(setacl, setacl, attrstat, fhandle, RC_NOCACHE, ST+AT),+- PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),+- PROC(access, access, access, fhandle, RC_NOCACHE, ST+AT+1),++ PROC(setacl, setacl, attrstat, attrstat, RC_NOCACHE, ST+AT),++ PROC(getattr, fhandle, attrstat, attrstat, RC_NOCACHE, ST+AT),++ PROC(access, access, access, access, RC_NOCACHE, ST+AT+1),+ };++ struct svc_version nfsd_acl_version2 = {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000+++ b/2.6.20/4150_iteraid.patch Sun Feb 25 13:04:04 2007 +0100@@ -0,0 +1,6548 @@+diff -urN -X dontdiff-mika linux-2.6.17.clean/drivers/scsi/iteraid.c linux-2.6.17/drivers/scsi/iteraid.c+--- linux-2.6.17.clean/drivers/scsi/iteraid.c 1970-01-01 01:00:00.000000000 +0100++++ linux-2.6.17/drivers/scsi/iteraid.c 2006-06-20 15:58:04.344112250 +0200+@@ -0,0 +1,5152 @@++/*++ * linux/drivers/scsi/iteraid.c++ *++ * (C) Copyright 2002-2004 ITE Tech, inc.++ *++ * Nov 11, 2002 Mark Lu file created.++ *++ * Aug 2 , 2004 Donald Huang published the ITE driver.++ *++ * ITE IT8212 RAID controller device driver for Linux.++ *++ * This program is free software; you can redistribute it and/or modify it++ * under the terms of the GNU General Public License as published by the++ * Free Software Foundation; either version 2, or (at your option) any++ * later version.++ *++ * This program is distributed in the hope that it will be useful, but++ * WITHOUT ANY WARRANTY; without even the implied warranty of++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU++ * General Public License for more details.++ *++ * Revision 0.0 2002/12/05 15:12:12 root++ * Empty function bodies; detect() works.++ *++ * Revision 0.1 2002/12/17 19:21:37 root++ * First "dma thing doesn't work" version.++ *++ * Revision 0.3 2002/12/23 17:12:09 root++ * Rewrite the dma routines. Reference the ide-dma.c.++ *++ * Revision 0.4 2002/12/26 10:19:29 root++ * The dma read/write works, using some ways to prove it. But there is a++ * problem about the "unknown partition table". The fdisk is ok, but++ * after writing the created partitions, it still shows the "unknown++ * partition table" and i can't access the created partitions.++ *++ * Revision 0.5 2003/01/07 21:49:30 root++ * The problem of "unknown partition table" has been solved.++ * We must "ENABLE CLUSTERING". There is still a another problem about++ * the SCATTER/GATHER.++ *++ * Revision 0.6 2003/01/10 17:45:32 root++ * The SCATTER/GATHER problem has been solved. Now verify the read/write++ * function and make sure each RAID configurations are workable. If testing++ * is OK, then it will be a version 1.0.....++ *++ * Revision 1.0 2003/01/16 17:45:32 root++ * First release version.++ *++ * FixME 1:++ * In RedHat 7.3, if using SG_ALL, the SCSI will timeout. It looks like++ * an command is requested but the interrupt is not been asserted. So++ * try to add a watchdog timer to monitor the interrupts. But this kind++ * of situration will not happen in Mandrake 9.0 and also when using++ * SG_NONE in RedHat 7.3.++ *++ * FixME 2:++ * Module load problem in RedHat 7.3.++ *++ * Fixed: Compile in the graphic mode (GNOME or KDE) will fix the++ * module load problem.++ *++ * Revision 1.1 2003/02/10 10:32:21 root++ * Compile in the graphic mode (GNOME or KDE) will fix the++ * module load problem.++ *++ * Revision 1.2 2003/02/18 14:10:35 root++ * Fix the interrupt service routine for share irq problem.++ *++ * ATAPI support ---> schedule is three weeks. (2003/02/28)++ *++ * Revision 1.3 2003/02/27++ * First release ATAPI version. But there will be an error if no disc in the++ * CD-ROM. Because the commands like TEST_UNIT_READY and READ_CAPACITY will++ * get the error response. This situration in WINDOWS will be then send the++ * REQUEST SENSE command to the device but in Linux, it will never get++ * REQUEST SENSE command. So can we send by ourself???++ *++ * 2003/03/05 root++ *++ * Note 1:++ * According to "The Linux SCSI Generic (sg) HOWTO", the device will respond++ * with a single byte value call the 'scsi_status'. GOOD is the scsi status++ * indicating everything has gone well. The most common other status is++ * CHECK CONDITION. In this latter case, the SCSI mid layer issues a REQUEST++ * SENSE SCSI command. The response of the REQUEST SENSE is 18 bytes or more++ * in length and is called the "sense buffer". It will indicate why the original++ * command may not have been executed. It is important to realize that a CHECK++ * CONDITION may very in severity from informative (e.g. command needed to be++ * retried before succeeding) to fatal (e.g. 'medium error' which often++ * indicates it is time to replace the disk).++ *++ * Note 2:++ * When using the ATAPI BIOS, we also do not need to set up the timimg in linux++ * driver. But it is necessary to write the timing routine in win system,++ * cause it has a s1, s2, s3 mode and devices wake up from these modes need to++ * be initialized again and do not pass through the BIOS.++ *++ * Note 3:++ * The 48-bit support and AP for RAID in linux will the next job.++ *++ * Revision 1.31 2003/03/14 09:40:35 root++ * Fix an error when no disc is on the CD-ROM and the audio cd is ready to play.++ *++ * 2003/04/08 root++ * The ioctl code sklection is finished. But there is a problem about++ * "Bad address" when copy_from_user() is called.++ *++ * Fixed: Use kmalloc() and kfree() to allocate the buffer instead of automatic++ * variables (use stack). The stack size is limited in kernel space.++ *++ * Revision 1.32 2003/04/14 18:20:23 root++ * Complete the IOCTLs code.++ *++ * The IOCTLs are listed below++ * ===========================++ *++ * (1) ITE_IOC_GET_IDENTIFY_DATA++ *++ * Return virtual drive 512 bytes identification data.++ *++ * (2) ITE_IOC_GET_PHY_DISK_STATUS++ *++ * Developer can decide to return 4 physical disk information in++ * 512 bytes (data structure should be defined) or 512 bytes++ * identification data of the physical disk specified by AP.++ *++ * (3) ITE_IOC_CREATE_DISK_ARRAY++ *++ * Create a new array and erase (or keep) boot sector.++ *++ * (4) ITE_IOC_REBUILD_START++ *++ * AP nees to specify target/source drive, starting LBA and length.++ *++ * (5) ITE_IOC_GET_REBUILD_STATUS++ *++ * Return rebuild percentage or last LBA No.++ *++ * (6) ITE_IOC_RESET_ADAPTER++ *++ * Reset the controller.++ *++ * Revision 1.33 2003/04/15 11:10:08 root++ * The 48-bit support.++ *++ * Revision 1.34 2003/04/20 13:20:38 root++ * Change some values in iteraid.h, so it will not hang in Red Hat Linux++ * and improve the performance.++ *++ * can_queue: 1 --------------------> can_queue: 124++ * sg_tablesize: SG_NONE -----------> sg_tablesize: 16++ * cmd_per_lun: 128 ----------------> cmd_per_lun: 1++ * use_clustering: ENABLE_CLUSTER --> use_clustering: DISABLE_CLUSTER++ *++ * 2003/04/25 root++ * The code will hang on Gigabyte's motherboard when the sourth bridge is++ * sis 962L and 963.++ *++ * Revision 1.35 2003/04/28 10:06:20 root++ * Fixed: Do not enable interrupt again when send each command in++ * IdeSendCommand() routine.++ *++ * 2003/05/20 root++ * Linux SCSI error handling code should be changed to new one.++ *++ * The shortcomings of the existing code.++ *++ * 1. The old error handling code is an imperfect state machine. It++ * would occasionally get stuck in loops whereby the bus would be reset++ * over and over again, where the problem would never be resolved and++ * control of the machine would never return to the user.++ *++ * Reference the http://www.andante.org/scsi.html++ *++ * The kernel after 2.5 or 2.6 will not use the old error handling codes.++ *++ * In iteraid.h++ *++ * #define ITERAID \++ * { \++ * proc_name: "it8212", \++ * proc_info: iteraid_proc_info, \++ * . \++ * . \++ * eh_about_handler: iteraid_about_eh, \ --> New added++ * eh_device_reset_handler: NULL \ --> New added++ * eh_bus_reset_handler: NULL \ --> New added++ * eh_host_reset_handler: iteraid_reset_eh \ --> New added++ * use_new_eh_code: 0 --> 1 \++ * }++ *++ * 2003/06/23 root 17:30:41++ * TODO: Error code still use the old method.++ *++ * Revision 1.36 2003/06/23 19:52:31 root++ * Fixed: Use the new error handling code.++ *++ * Revision 1.40 2003/07/25 10:00:00 root++ * Released version 1.40 by Mark Lu.++ *++ * Revision 1.41 2003/08/06 13:55:17 root++ * Added support for clean shutdown notification/feature table.++ *++ * Revision 1.42 2003/08/21 11:38:57 root++ * Problem: When linux was installed onto IT8212 controller with two disks,++ * configured as RAID 1 (P0S0), the hot swap will hang the system.++ * Solve: Use the AtapiResetController() instead of only IT8212ResetAdapter().++ *++ * Revision 1.43 2003/12/24 23:19:07 root++ * Fixed: Fixed a compile error at line 5815. Just move up the variable++ * rebuild_info of type PRAID_REBUILD_INFO with other variables.++ *++ * Revision 1.44 2004/03/16 13:12:35 root++ * Fixed: (1) The crash problem when using "rmmod" to remove the iteraid module.++ * (2) Support two IT8212 cards or chips.++ * (3) A bug when accessing the slave disk more than 137G.++ * Thanks for Martine Purschke kindly help to find this bug and++ * fix it.++ * (4) can_queue: 12 --------------------> can_queue: 1++ * (5) Change the Transparent(Bypass) mode initial PCI registers setting.++ * (6) Change IDE I/O, control and dma base address from USHORT to ULONG,++ * so that the non x86 platform, like MIPS, will load the correct++ * address.++ * (7) Add GPL license in iteraid.h.++ *++ * Revision 1.45 2004/05/07 11:07:16 root++ * Fixed : (1) 64-bit support.++ * (2) In IT8212SetBestTransferMode() there are a number of arrays,++ * all of which are defined read/write and assigned on the stack.++ * Now put them in a R/O segment, by replacing e.g. "UCHAR++ * udmaTiming" with "static const UCHAR udmaTiming".++ */++++#include <linux/module.h>++MODULE_AUTHOR("ITE Tech,Inc.");++MODULE_DESCRIPTION("ITE IT8212 RAID Controller Linux Driver");++++#include <linux/kernel.h>++#include <linux/pci.h>++#include <linux/time.h>++#include <linux/proc_fs.h>++#include <linux/sched.h>++#include <linux/ioport.h>++#include <linux/blkdev.h>++#include <linux/hdreg.h>++#include <linux/string.h>++#include <linux/smp.h>++#include <linux/delay.h>++#include <linux/reboot.h>++#include <linux/spinlock.h>++#include <linux/interrupt.h>++++#include <asm/errno.h>++#include <asm/io.h>++#include <asm/irq.h>++#include <asm/uaccess.h>++++#include "scsi.h"++#include <scsi/scsi_host.h>++++#include "iteraid.h"++MODULE_LICENSE("GPL");++++#define MARK_DEBUG_DUMP_MEM 0 /* 1=Enable dump memory content */++#define MARK_DEBUG_BYPASS_MODE 0 /* 1=Enable use bypass mode */++#define MARK_DUMP_CREATE_INFO 0 /* 1=Dump raid create info */++#define MARK_SET_BEST_TRANSFER 0 /* 0=BIOS set best trans mode */++++#define PRD_BYTES 8 /* PRD table size */++#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES))++static struct Scsi_Host *ite_vhost = NULL; /* SCSI virtual host */++static Scsi_Cmnd *it8212_req_last = NULL; /* SRB request list */++static unsigned int NumAdapters = 0; /* Adapters number */++static PITE_ADAPTER ite_adapters[2]; /* How many adapters support */++++/*++ * Notifier block to get a notify on system shutdown/halt/reboot.++ */++static int ite_halt(struct notifier_block *nb, ulong event, void *buf);++static struct notifier_block ite_notifier = {++ .notifier_call = ite_halt,++ .next = NULL,++ .priority = 0++};++static struct semaphore mimd_entry_mtx;++static spinlock_t queue_request_lock = SPIN_LOCK_UNLOCKED;++static spinlock_t io_request_lock = SPIN_LOCK_UNLOCKED;++++static void TaskQueue(void);++static void TaskDone(PChannel, PSCSI_REQUEST_BLOCK);++static u8 IssueIdentify(PChannel, u8, u8);++static u8 IT8212ResetAdapter(PITE_ADAPTER);++static u8 AtapiInterrupt(PChannel);++++static int itedev_open(struct inode *, struct file *);++static int itedev_ioctl_entry(struct inode *, struct file *, unsigned int,++ unsigned long);++static int itedev_ioctl(struct inode *, struct file *, unsigned int,++ unsigned long);++static int itedev_close(struct inode *, struct file *);++++#define DRV_VER_8212 "1.45"++static int driver_ver = 145;++static int ite_major = 0;++++static struct file_operations itedev_fops = {++ .owner = THIS_MODULE,++ .ioctl = itedev_ioctl_entry,++ .open = itedev_open,++ .release = itedev_close++};++++#if (MARK_DEBUG_DUMP_MEM)++/*++ * Dump buffer.++ */++static void HexDump(unsigned char *buf, int length)++{++ unsigned int i = 0;++ unsigned int j = 0;++++ printk("\n");++ for (i = 0; i < length; i += 16) {++ printk("%04X ", i);++ for (j = i; (j < i + 8) && (j < length); j++)++ printk(" %02X", buf[j]);++ if (j == i + 8)++ printk("-");++ for (j = i + 8; (j < i + 16) && (j < length); j++)++ printk("%02X ", buf[j]);++ printk("\n");++ }++} /* end HexDump */++#endif++++/*++ * This routine maps ATAPI and IDE errors to specific SRB statuses.++ */++static u8 MapError(PChannel pChan, PSCSI_REQUEST_BLOCK Srb)++{++ u8 errorByte;++ u8 srbStatus;++ u8 scsiStatus;++++ /*++ * Read the error register.++ */++ errorByte = inb(pChan->io_ports[IDE_ERROR_OFFSET]);++ printk("MapError: error register is %x\n", errorByte);++++ /*++ * If this is ATAPI error.++ */++ if (pChan->DeviceFlags[Srb->TargetId & 1] & DFLAGS_ATAPI_DEVICE) {++ switch (errorByte >> 4) {++ case SCSI_SENSE_NO_SENSE:++ printk("ATAPI: no sense information\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ case SCSI_SENSE_RECOVERED_ERROR:++ printk("ATAPI: recovered error\n");++ scsiStatus = 0;++ srbStatus = SRB_STATUS_SUCCESS;++ break;++ case SCSI_SENSE_NOT_READY:++ printk("ATAPI: device not ready\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ case SCSI_SENSE_MEDIUM_ERROR:++ printk("ATAPI: media error\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ case SCSI_SENSE_HARDWARE_ERROR:++ printk("ATAPI: hardware error\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ case SCSI_SENSE_ILLEGAL_REQUEST:++ printk("ATAPI: illegal request\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ case SCSI_SENSE_UNIT_ATTENTION:++ printk("ATAPI: unit attention\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ case SCSI_SENSE_DATA_PROTECT:++ printk("ATAPI: data protect\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ case SCSI_SENSE_BLANK_CHECK:++ printk("ATAPI: blank check\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ case SCSI_SENSE_ABORTED_COMMAND:++ printk("ATAPI: command Aborted\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ break;++ default:++ printk("ATAPI: invalid sense information\n");++ scsiStatus = 0;++ srbStatus = SRB_STATUS_ERROR;++ break;++ }++ } else {++ /*++ * If this is IDE error.++ */++ scsiStatus = 0;++ srbStatus = SRB_STATUS_ERROR;++++ /*++ * Save errorByte, to be used by SCSIOP_REQUEST_SENSE.++ */++ pChan->ReturningMediaStatus = errorByte;++ if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {++ printk("IDE: media change\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {++ printk("IDE: command abort\n");++ srbStatus = SRB_STATUS_ABORTED;++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ if (Srb->SenseInfoBuffer) {++ PSENSE_DATA senseBuffer =++ (PSENSE_DATA) Srb->SenseInfoBuffer;++ senseBuffer->ErrorCode = 0x70;++ senseBuffer->Valid = 1;++ senseBuffer->AdditionalSenseLength = 0xB;++ senseBuffer->SenseKey =++ SCSI_SENSE_ABORTED_COMMAND;++ senseBuffer->AdditionalSenseCode = 0;++ senseBuffer->AdditionalSenseCodeQualifier = 0;++ srbStatus |= SRB_STATUS_AUTOSENSE_VALID;++ }++++ /*++ * pChan->ErrorCount++;++ */++ } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {++ printk("IDE: end of media\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ if (!++ (pChan->++ DeviceFlags[Srb->++ TargetId & 1] &++ DFLAGS_MEDIA_STATUS_ENABLED)) {++++ /*++ * pChan->ErrorCount++;++ */++ }++ } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {++ printk("IDE: illegal length\n");++ srbStatus = SRB_STATUS_INVALID_REQUEST;++ } else if (errorByte & IDE_ERROR_BAD_BLOCK) {++ printk("IDE: bad block\n");++ srbStatus = SRB_STATUS_ERROR;++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ if (Srb->SenseInfoBuffer) {++ PSENSE_DATA senseBuffer =++ (PSENSE_DATA) Srb->SenseInfoBuffer;++ senseBuffer->ErrorCode = 0x70;++ senseBuffer->Valid = 1;++ senseBuffer->AdditionalSenseLength = 0xB;++ senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;++ senseBuffer->AdditionalSenseCode = 0;++ senseBuffer->AdditionalSenseCodeQualifier = 0;++ srbStatus |= SRB_STATUS_AUTOSENSE_VALID;++ }++ } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {++ printk("IDE: id not found\n");++ srbStatus = SRB_STATUS_ERROR;++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ if (Srb->SenseInfoBuffer) {++ PSENSE_DATA senseBuffer =++ (PSENSE_DATA) Srb->SenseInfoBuffer;++ senseBuffer->ErrorCode = 0x70;++ senseBuffer->Valid = 1;++ senseBuffer->AdditionalSenseLength = 0xB;++ senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;++ senseBuffer->AdditionalSenseCode = 0;++ senseBuffer->AdditionalSenseCodeQualifier = 0;++ srbStatus |= SRB_STATUS_AUTOSENSE_VALID;++ }++++ /*++ * pChan->ErrorCount++;++ */++ } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {++ printk("IDE: media change\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ if (Srb->SenseInfoBuffer) {++ PSENSE_DATA senseBuffer =++ (PSENSE_DATA) Srb->SenseInfoBuffer;++ senseBuffer->ErrorCode = 0x70;++ senseBuffer->Valid = 1;++ senseBuffer->AdditionalSenseLength = 0xD;++ senseBuffer->SenseKey =++ SCSI_SENSE_UNIT_ATTENTION;++ senseBuffer->AdditionalSenseCode =++ SCSI_ADSENSE_MEDIUM_CHANGED;++ senseBuffer->AdditionalSenseCodeQualifier = 0;++ srbStatus |= SRB_STATUS_AUTOSENSE_VALID;++ }++ } else if (errorByte & IDE_ERROR_DATA_ERROR) {++ printk("IDE: data error\n");++ scsiStatus = SCSISTAT_CHECK_CONDITION;++ srbStatus = SRB_STATUS_ERROR;++ if (!++ (pChan->++ DeviceFlags[Srb->++ TargetId & 1] &++ DFLAGS_MEDIA_STATUS_ENABLED)) {++++ /*++ * pChan->ErrorCount++;++ */++ }++++ /*++ * Build sense buffer.++ */++ if (Srb->SenseInfoBuffer) {++ PSENSE_DATA senseBuffer =++ (PSENSE_DATA) Srb->SenseInfoBuffer;++ senseBuffer->ErrorCode = 0x70;++ senseBuffer->Valid = 1;++ senseBuffer->AdditionalSenseLength = 0xB;++ senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;++ senseBuffer->AdditionalSenseCode = 0;++ senseBuffer->AdditionalSenseCodeQualifier = 0;++ srbStatus |= SRB_STATUS_AUTOSENSE_VALID;++ }++ }++ }++++ /*++ * Set SCSI status to indicate a check condition.++ */++ Srb->ScsiStatus = scsiStatus;++ return srbStatus;++} /* end MapError */++++/*++ * Reset IDE controller or ATAPI device.++ */++static void AtapiResetController(PITE_ADAPTER pAdap, PChannel pChan)++{++ u8 resetResult;++ u8 status;++ u8 i;++ unsigned long dma_base;++ SCSI_REQUEST_BLOCK srb;++++ printk("AtapiResetController enter\n");++ dma_base = pChan->dma_base;++ resetResult = FALSE;++++ /*++ * Check and see if we are processing an internal srb.++ */++ if (pChan->OriginalSrb) {++ pChan->CurrentSrb = pChan->OriginalSrb;++ pChan->OriginalSrb = NULL;++ }++++ /*++ * To avoid unexpected interrupts occurs during reset procedure.++ *++ * 1. Stop bus master operation.++ */++ outb(0, dma_base);++ for (i = 0; i < 2; i++) {++ outb((u8) ((i << 4) | 0xA0),++ pChan->io_ports[ATAPI_SELECT_OFFSET]);++++ /*++ * 2. Clear interrupts if there is any.++ */++ GetBaseStatus(pChan, status);++++ /*++ * 3. Disable interrupts.++ */++ outb(IDE_DC_DISABLE_INTERRUPTS,++ pChan->io_ports[ATAPI_CONTROL_OFFSET]);++++ /*++ * 4. Clear interrupts again.++ */++ GetBaseStatus(pChan, status);++ }++++ /*++ * Check if request is in progress.++ */++ if (pChan->CurrentSrb) {++++ /*++ * Complete outstanding request with SRB_STATUS_BUS_RESET.++ */++ srb.SrbStatus = SRB_STATUS_BUS_RESET;++++ /*++ * Clear request tracking fields.++ */++ pChan->CurrentSrb = NULL;++ pChan->WordsLeft = 0;++ pChan->DataBuffer = NULL;++++ /*++ * Indicate ready for next request.++ */++ TaskDone(pChan, &srb);++ }++++ /*++ * Clear expecting interrupt flag.++ */++ pChan->ExpectingInterrupt = FALSE;++ pChan->RDP = FALSE;++ resetResult = IT8212ResetAdapter(pAdap);++++ /*++ * Set transfer modes after resetting the adapter.++ */++++ /*++ * Reenable interrupts.++ */++ for (i = 0; i < 4; i++) {++ outb((u8) (((i & 1) << 4) | 0xA0),++ pChan->io_ports[ATAPI_SELECT_OFFSET]);++ outb(IDE_DC_REENABLE_CONTROLLER,++ pChan->io_ports[ATAPI_CONTROL_OFFSET]);++ }++ printk("AtapiResetController exit\n");++} /* end AtapiResetController */++++/*++ * IDE start read/write transfer.++ */++static void IdeStartTransfer(PChannel pChan, PSCSI_REQUEST_BLOCK Srb,++ u32 startingSector, u32 SectorNumber)++{++ u8 DiskId;++ u8 drvSelect;++ u8 bmClearStat;++ unsigned long dma_base;++++ dprintk("IdeStartTransfer enter\n");++ DiskId = (u8) Srb->TargetId;++ dma_base = pChan->dma_base;++++ /*++ * 48-bit support.++ */++ if ((startingSector + SectorNumber) > 0x0FFFFFFF) {++++ /*++ * Select drive and set LBA mode.++ */++ outb((u8) (((DiskId & 0x1) << 4) | 0xA0 | 0x40),++ pChan->io_ports[IDE_SELECT_OFFSET]);++++ /*++ * Sector count register.++ */++ outb((u8) (SectorNumber >> 8),++ pChan->io_ports[IDE_NSECTOR_OFFSET]);++ outb((u8) SectorNumber, pChan->io_ports[IDE_NSECTOR_OFFSET]);++++ /*++ * LBA low register.++ */++ outb((u8) (startingSector >> 24),++ pChan->io_ports[IDE_LOCYL_OFFSET]);++ outb((u8) startingSector, pChan->io_ports[IDE_LOCYL_OFFSET]);++++ /*++ * LBA mid register.++ */++ outb((u8) 0, pChan->io_ports[IDE_MIDCYL_OFFSET]);++ outb((u8) (startingSector >> 8),++ pChan->io_ports[IDE_MIDCYL_OFFSET]);++++ /*++ * LBA high register.++ */++ outb((u8) 0, pChan->io_ports[IDE_HCYL_OFFSET]);++ outb((u8) (startingSector >> 16),++ pChan->io_ports[IDE_HCYL_OFFSET]);++++ /*++ * Start the IDE read/write DMA command.++ */++ if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {++ outb(IDE_COMMAND_READ_DMA_EXT,++ pChan->io_ports[IDE_COMMAND_OFFSET]);++ } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {++ outb(IDE_COMMAND_WRITE_DMA_EXT,++ pChan->io_ports[IDE_COMMAND_OFFSET]);++ }++ } else {++ /*++ * 28-bit addressing.++ */++++ /*++ * Select drive and set LBA mode.++ */++ drvSelect = (u8) (startingSector >> 24);++ drvSelect = drvSelect | (((u8) DiskId & 0x1) << 4)|0x40|0xA0;++ outb(drvSelect, pChan->io_ports[IDE_SELECT_OFFSET]);++ outb((u8) SectorNumber, pChan->io_ports[IDE_NSECTOR_OFFSET]);++ outb((u8) startingSector, pChan->io_ports[IDE_LOCYL_OFFSET]);++ outb((u8) (startingSector >> 8),++ pChan->io_ports[IDE_MIDCYL_OFFSET]);++ outb((u8) (startingSector >> 16),++ pChan->io_ports[IDE_HCYL_OFFSET]);++++ /*++ * Start the IDE read/write DMA command.++ */++ if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {++ outb(IDE_COMMAND_READ_DMA,++ pChan->io_ports[IDE_COMMAND_OFFSET]);++ } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {++ outb(IDE_COMMAND_WRITE_DMA,++ pChan->io_ports[IDE_COMMAND_OFFSET]);++ }++ }++++ /*++ * Indicate expecting an interrupt.++ */++ pChan->ExpectingInterrupt = TRUE;++++ /*++ * Setup PRD table physical address.++ */++ outl(pChan->dmatable_dma, dma_base + 4);++++ /*++ * Read Bus Master status.++ */++ bmClearStat = inb(dma_base + 2);++ if (Srb->TargetId & 1) {++ bmClearStat =++ bmClearStat | BM_DRV1_DMA_CAPABLE | BM_STAT_FLG_INT |++ BM_STAT_FLG_ERR;++ } else {++ bmClearStat =++ bmClearStat | BM_DRV0_DMA_CAPABLE | BM_STAT_FLG_INT |++ BM_STAT_FLG_ERR;++ }++ outb(0, dma_base);++++ /*++ * Clear INTR and ERROR flags.++ */++ outb(bmClearStat, dma_base + 2);++++ /*++ * Start DMA read/write.++ */++ if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)++ outb(BM_CMD_FLG_START | BM_CMD_FLG_WRTTOMEM, dma_base);++ else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)++ outb(BM_CMD_FLG_START | BM_CMD_FLG_WRTTODSK, dma_base);++ dprintk("IdeStartTransfer exit\n");++} /* end IdeStartTransfer */++++/*++ * Setup the PRD table.++ */++static int IdeBuildSglist(PChannel pChan, PSCSI_REQUEST_BLOCK Srb)++{++ int nents = 0;++ u32 bytesRemaining = Srb->DataTransferLength;++ unsigned char *virt_addr = Srb->DataBuffer;++ struct scatterlist *sg = pChan->sg_table;++++ if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)++ pChan->sg_dma_direction = PCI_DMA_FROMDEVICE;++ else++ pChan->sg_dma_direction = PCI_DMA_TODEVICE;++++ /*++ * The upper layer will never give the memory more than 64K bytes.++ */++ memset(&sg[nents], 0, sizeof(*sg));++ sg[nents].dma_address = (dma_addr_t) virt_addr;++ sg[nents].length = bytesRemaining;++ nents++;++ return pci_map_sg(pChan->pPciDev, sg, nents, pChan->sg_dma_direction);++} /* end IdeBuildSglist */++++/*++ * Prepares a dma request.++ */++static int IdeBuildDmaTable(PChannel pChan, PSCSI_REQUEST_BLOCK Srb)++{++ unsigned long *table = pChan->dmatable_cpu;++ unsigned int count = 0;++ int i;++ struct scatterlist *sg;++++ i = IdeBuildSglist(pChan, Srb);++ sg = pChan->sg_table;++ while (i && sg_dma_len(sg)) {++ u32 cur_len;++ u32 cur_addr;++ cur_addr = sg_dma_address(sg);++ cur_len = sg_dma_len(sg);++++ /*++ * Fill in the dma table, without crossing any 64kB boundaries.++ */++ while (cur_len) {++ if (count++ >= PRD_ENTRIES) {++ printk(KERN_WARNING "@@DMA table too small\n");++ } else {++ u32 xcount, bcount =++ 0x10000 - (cur_addr & 0xFFFF);++ if (bcount > cur_len)++ bcount = cur_len;++ *table++ = cpu_to_le32(cur_addr);++ xcount = bcount & 0xFFFF;++ if (xcount == 0x0000) {++ /*++ * Most chipsets correctly interpret a++ * length of 0x0000 as 64KB, but at++ * least one (e.g. CS5530) misinterprets++ * it as zero (!). So here we break the++ * 64KB entry into two 32KB entries++ * instead.++ */++ if (count++ >= PRD_ENTRIES)++ printk(KERN_WARNING++ "##DMA table too small\n");++ *table++ = cpu_to_le32(0x8000);++ *table++ =++ cpu_to_le32(cur_addr + 0x8000);++ xcount = 0x8000;++ }++ *table++ = cpu_to_le32(xcount);++ cur_addr += bcount;++ cur_len -= bcount;++ }++ }++ sg++;++ i--;++ }++ if (count) {++ *--table |= cpu_to_le32(0x80000000);++ return count;++ } else {++ printk(KERN_WARNING "Empty DMA table?\n");++ }++ return count;++} /* end IdeBuildDmaTable */++++/*++ * Prepares a dma scatter/gather request.++ */++static void IdeBuildDmaSgTable(PChannel pChan, PSCSI_REQUEST_BLOCK Srb)++{++ int use_sg = 0;++ int i;++ PPRD_TABLE_ENTRY pSG = (PPRD_TABLE_ENTRY) pChan->dmatable_cpu;++ struct scatterlist *sg = (struct scatterlist *)Srb->DataBuffer;++++ if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)++ pChan->sg_dma_direction = PCI_DMA_FROMDEVICE;++ else++ pChan->sg_dma_direction = PCI_DMA_TODEVICE;++++ use_sg = pci_map_sg(pChan->pPciDev, Srb->DataBuffer, Srb->UseSg,++ pChan->sg_dma_direction);++ for (i = 0; i < use_sg; i++) {++ pSG[i].PhysicalBaseAddress = sg_dma_address(&sg[i]);++ pSG[i].ByteCount = sg_dma_len(&sg[i]);++ pSG[i].EndOfTable = (i == use_sg - 1) ? SG_FLAG_EOT : 0;++ }++} /* end IdeBuildDmaSgTable */++++/*++ * Setup DMA table for channel.++ */++static void++IdeSetupDma(PChannel pChan, unsigned long dma_base, unsigned short num_ports)++{++ printk("Channel[%d] BM-DMA at 0x%lX-0x%lX\n", pChan->channel,++ dma_base, dma_base + num_ports - 1);++++ /*++ * Allocate IDE DMA buffer.++ */++ pChan->dmatable_cpu =++ pci_alloc_consistent(pChan->pPciDev, PRD_ENTRIES * PRD_BYTES,++ &pChan->dmatable_dma);++ if (pChan->dmatable_cpu == NULL) {++ printk("IdeSetupDma: allocate prd table failed.\n");++ return;++ }++ memset(pChan->dmatable_cpu, 0, PRD_ENTRIES * PRD_BYTES);++++ pChan->sg_table =++ kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, GFP_KERNEL);++ if (pChan->sg_table == NULL) {++ printk("IdeSetupDma: allocate sg_table failed.\n");++ pci_free_consistent(pChan->pPciDev, PRD_ENTRIES * PRD_BYTES,++ pChan->dmatable_cpu, pChan->dmatable_dma);++ return;++ }++ return;++} /* end IdeSetupDma */++++/*++ * This will be only used in RAID mode.++ */++static void IT8212ReconfigChannel(PChannel pChan, u8 ArrayId, u8 Operation)++{++ u8 enableVirtualChannel;++ struct pci_dev *pPciDev = pChan->pPciDev;++++ pci_read_config_byte(pPciDev, 0x43, &enableVirtualChannel);++ if (Operation == DisableChannel) {++ enableVirtualChannel &= ~(1 << ArrayId);++ printk("IT8212ReconfigChannel: disable channel %X\n", ArrayId);++ } else {++ enableVirtualChannel |= ~(1 << ArrayId);++ printk("IT8212ReconfigChannel: enable channel %X\n", ArrayId);++ }++ printk("IT8212ReconfigChannel: channel enabled after set 0x%X\n",++ enableVirtualChannel);++++ /*++ * Set enabled virtual channels.++ */++ pci_write_config_byte(pPciDev, 0x43, enableVirtualChannel);++} /* end IT8212ReconfigChannel */++++/*++ * This is a vendor specific command. According to all of the device++ * configurations, the BIOS then can consider the existing RAID configuration++ * reasonable. If the existing RAID configuration is not reasonable, or if++ * there is NO existing RAID configuration, the BIOS can ask the user to setup++ * the RAID configuration. Finally, the BIOS or AP should send the SET CHIP++ * STATUS to every virtual device. Only after receiving SET CHIP STATUS++ * command, the corresponding virtual device will be active.++ */++static u8 IT8212GetChipStatus(uioctl_t * ioc)++{++ u8 PriMasterIsNull = FALSE;++ u8 statusByte;++ u8 srbStatus;++ PChannel pChan;++ PITE_ADAPTER pAdap;++ PHYSICAL_DISK_STATUS *pPhyDiskInfo;++++ dprintk("IT8212GetChipStatus enter\n");++++ /*++ * Only support one controller now! In the future, we can pass the++ * argument (user ioctl structure) to know which controller need to be++ * identified.++ */++ pAdap = ite_adapters[0];++ pChan = &pAdap->IDEChannel[0];++++ pPhyDiskInfo = kmalloc(sizeof(PHYSICAL_DISK_STATUS) * 4, GFP_KERNEL);++ if (pPhyDiskInfo == NULL) {++ printk("IT8212GetChipStatus: error kmalloc for "++ "PHYSCIAL_DISK_STATUS.\n");++ return -ENOMEM;++ }++ memset(pPhyDiskInfo, 0, sizeof(PHYSICAL_DISK_STATUS) * 4);++++ /*++ * Always send GET CHIP STATUS command to primary channel master device.++ * Select device.++ */++ outb((u8) 0xA0, pChan->io_ports[IDE_SELECT_OFFSET]);++++ /*++ * If primary master channel is not enabled, enable it.++ */++ statusByte = inb(pChan->io_ports[IDE_ALTERNATE_OFFSET]);++ if (statusByte == 0) {++ PriMasterIsNull = TRUE;++ IT8212ReconfigChannel(pChan, 0, EnableChannel);++ }++++ /*++ * Wait for device ready (Not BUSY and not DRQ)++ */++ WaitForDeviceReady(pChan, statusByte);++ if ((statusByte & IDE_STATUS_BUSY) || (statusByte & IDE_STATUS_DRQ)++ || (statusByte == 0)) {++ printk("IT8212GetChipStatus: disk[0] not ready. status=0x%X\n",++ statusByte);++ srbStatus = SRB_STATUS_BUSY;++ goto exit;++ }++++ /*++ * Disable interrupt to avoid the unexpected interrupt.++ */++ outb(IDE_DC_DISABLE_INTERRUPTS, pChan->io_ports[IDE_CONTROL_OFFSET]);++++ /*++ * Issue the command.++ */++ outb(IDE_COMMAND_GET_CHIP_STATUS, pChan->io_ports[IDE_COMMAND_OFFSET]);++++ /*++ * Wait for BUSY = 0, DRQ = 1.++ */++ CheckBusyDrq(pChan, statusByte) if (statusByte != 0x58) {++ printk("IT8212GetChipStatus: disk[0] return unexpected "++ "status after");++ printk("issue command. status=0x%X\n", statusByte);++ goto exit_error;++ }++++ /*++ * Read the physical disk info.++ */++ ReadBuffer(pChan, (unsigned short *)pPhyDiskInfo, 256);++++#if (0)++ HexDump((unsigned char *)pPhyDiskInfo, 512);++#endif++++ copy_to_user((unsigned short *)ioc->data,++ (unsigned char *)pPhyDiskInfo, 512);++++ /*++ * Check error.++ */++ WaitForCommandComplete(pChan, statusByte);++ if (statusByte != IDE_STATUS_IDLE) {++ printk("IT8212GetChipStatus: disk[0] return unexpected "++ "status after read data. status=0x%X\n", statusByte);++ goto exit_error;++ }++ srbStatus = SRB_STATUS_SUCCESS;++ goto exit;++exit_error:++ /*++ * If fail, hard reset to avoid the DRQ status pending.++ */++ srbStatus = SRB_STATUS_ERROR;++ IdeHardReset(pChan, statusByte);++exit:++ /*++ * Reenable interrupt after command complete.++ */++ outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]);++++ /*++ * If primary master is null, disable primary master channel before we++ * leave.++ */++ if (PriMasterIsNull)++ IT8212ReconfigChannel(pChan, 0, DisableChannel);++ dprintk("IT8212GetChipStatus exit\n");++ return srbStatus;++} /* end IT8212GetChipStatus */++++/*++ * Erase the partition table.++ */++static unsigned char IT8212ErasePartition(uioctl_t * pioc)++{++ unsigned char drvSelect;++ unsigned char statusByte = 0;++ unsigned char srbStatus;++ unsigned char *buffer;++ PRAID_CREATE_INFO createInfo = (PRAID_CREATE_INFO) pioc->data;++ PITE_ADAPTER pAdap;++ PChannel pChan;++++ printk("IT8212ErasePartition enter\n");++ printk("createInfo->DiskArrayId = %d\n", createInfo->DiskArrayId);++ if (createInfo->ErasePartition == 0++ || (createInfo->RaidType == RAID_LEVEL_NODISK))++ return SRB_STATUS_SUCCESS;++ pAdap = ite_adapters[0];++ if (createInfo->DiskArrayId < 2)++ pChan = &pAdap->IDEChannel[0];++ else++ pChan = &pAdap->IDEChannel[1];++++ if ((buffer = kmalloc(512, GFP_KERNEL)) == NULL) {++ printk("IT8212ErasePartition: error kmalloc.\n");++ return -ENOMEM;++ }++ memset(buffer, 0, 512);++++ /*++ * Select device.++ */++ drvSelect = (((u8) createInfo->DiskArrayId & 0x1) << 4) | 0xA0 | 0x40;++ outb(drvSelect, pChan->io_ports[IDE_SELECT_OFFSET]);++++ /*++ * Wait for device ready (not BUSY and not DRQ).++ */++ WaitForDeviceReady(pChan, statusByte);++ if ((statusByte & IDE_STATUS_BUSY) || (statusByte & IDE_STATUS_DRQ)++ || (statusByte == 0)) {++ printk++ ("IT8212ErasePartition: disk[%d] not ready. status=0x%X\n",++ createInfo->DiskArrayId, statusByte);++ return SRB_STATUS_BUSY;++ }++++ /*++ * Disable interrupt to avoid the unexpected interrupt.++ */++ outb(IDE_DC_DISABLE_INTERRUPTS, pChan->io_ports[IDE_CONTROL_OFFSET]);++++ /*++ * Write LBA 0 (1 sector).++ */++ outb(1, pChan->io_ports[IDE_NSECTOR_OFFSET]);++ outb(0, pChan->io_ports[IDE_LOCYL_OFFSET]);++ outb(0, pChan->io_ports[IDE_MIDCYL_OFFSET]);++ outb(0, pChan->io_ports[IDE_HCYL_OFFSET]);++ outb(drvSelect, pChan->io_ports[IDE_SELECT_OFFSET]);++ outb(IDE_COMMAND_WRITE_SECTOR, pChan->io_ports[IDE_COMMAND_OFFSET]);++++ /*++ * Wait for BUSY = 0, DRQ = 1.++ */++ CheckBusyDrq(pChan, statusByte);++ if (statusByte != 0x58) {++ printk("IT8212ErasePartition: disk[%d] error status. "++ "status=0x%X\n", createInfo->DiskArrayId, statusByte);++ goto exit_error;++ }++++ /*++ * Start erase partition table.++ */++ WriteBuffer(pChan, (unsigned short *)buffer, 256);++++ /*++ * Check error.++ */++ WaitForCommandComplete(pChan, statusByte);++ if (statusByte != IDE_STATUS_IDLE) {++ printk("IT8212ErasePartition: disk[%d] error status. "++ "status=0x%X\n", createInfo->DiskArrayId, statusByte);++ goto exit_error;++ }++ srbStatus = SRB_STATUS_SUCCESS;++ goto exit;++exit_error:++ /*++ * If failed, hard reset to avoid the DRQ status pending.++ */++ IdeHardReset(pChan, statusByte);++ srbStatus = SRB_STATUS_ERROR;++exit:++ /*++ * Reenable interrupt after command complete.++ */++ outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]);++ printk("IT8212ErasePartition exit\n");++ return srbStatus;++} /* end IT8212ErasePartition */++++static u32 IT8212TruncateReduentSectors(u32 OriginalSectorCount,++ u16 StripeSizeInKBytes)++{++ u16 stripeSizeInSector;++++ /*++ * 0 means using default value (32 sectors).++ */++ if (StripeSizeInKBytes == 0)++ stripeSizeInSector = 64 * 2;++ else++ stripeSizeInSector = StripeSizeInKBytes * 2;++ return ((OriginalSectorCount / stripeSizeInSector) *++ stripeSizeInSector);++} /* end IT8212TruncateReduentSectors */++++/*++ * Calculate the addressable sector for this RAID.++ */++static u32 IT8212DiskArrayAddressableSector(unsigned char *DiskArrayCreateInfo)++{++ u8 DiskNo;++ u8 NumOfDisks;++ u32 MinDiskCapacity;++ u32 ArrayCapacity;++ PRAID_CREATE_INFO createInfo = (PRAID_CREATE_INFO) DiskArrayCreateInfo;++++ MinDiskCapacity = ArrayCapacity = NumOfDisks = 0;++ printk("createInfo->AddressableSectors[0] = 0x%X\n",++ createInfo->AddressableSectors[0]);++ printk("createInfo->AddressableSectors[1] = 0x%X\n",++ createInfo->AddressableSectors[1]);++ printk("createInfo->AddressableSectors[2] = 0x%X\n",++ createInfo->AddressableSectors[2]);++ printk("createInfo->AddressableSectors[3] = 0x%X\n",++ createInfo->AddressableSectors[3]);++ for (DiskNo = 0; DiskNo < 4; DiskNo++) {++ /*++ * If disk exist.++ */++ if ((createInfo->ContainingDisks >> DiskNo) & 0x1) {++ NumOfDisks += 1;++ if (!MinDiskCapacity++ || (createInfo->AddressableSectors[DiskNo] <++ MinDiskCapacity)) {++ MinDiskCapacity =++ createInfo->AddressableSectors[DiskNo];++ }++ }++ }++ switch (createInfo->RaidType) {++ /*++ * Containing 2 or 3 or 4 disks.++ */++ case RAID_LEVEL_0:++ MinDiskCapacity =++ IT8212TruncateReduentSectors(MinDiskCapacity - 2,++ createInfo->StripeSize);++ ArrayCapacity = MinDiskCapacity * NumOfDisks;++ break;++++ /*++ * Containing 2 disks.++ */++ case RAID_LEVEL_1:++ ArrayCapacity = MinDiskCapacity - 2;++ break;++++ /*++ * Containing 4 disks.++ */++ case RAID_LEVEL_10:++ MinDiskCapacity =++ IT8212TruncateReduentSectors(MinDiskCapacity - 2,++ createInfo->StripeSize);++ ArrayCapacity = MinDiskCapacity * 2;++ break;++++ /*++ * Containing 2, 3, or 4 disks.++ */++ case RAID_LEVEL_JBOD:++ for (DiskNo = 0; DiskNo < 4; DiskNo++) {++ if ((createInfo->ContainingDisks >> DiskNo) & 0x1) {++ ArrayCapacity =++ ArrayCapacity +++ (createInfo->AddressableSectors[DiskNo] -++ 2);++ }++ }++ break;++++ /*++ * Containing only 1 disk.++ */++ case RAID_LEVEL_NORMAL:++ ArrayCapacity = MinDiskCapacity;++ break;++ }++ return ArrayCapacity;++} /* end IT8212DiskArrayAddressableSector */++++/*++ * Create a new array.++ */++static u8 IT8212CreateDiskArray(uioctl_t * pioc)++{++ u8 i;++ u8 subCommand = 0xFF;++ u8 statusByte;++ u8 dmaSupported;++ u8 udmaSupported;++ u8 srbStatus;++ u8 PriMasterIsNull = FALSE;++ u32 UserAddressableSectors;++ void *buffer;++ PChannel pChan;++ PITE_ADAPTER pAdap;++ PRAID_CREATE_INFO createInfo = (PRAID_CREATE_INFO) pioc->data;++ PIDENTIFY_DATA2 identifyData;++ PIT8212_SET_CHIP_STATUS_INFO setChipStatus;++ static const u16 IT8212TimingTable[7] = {++ 0x3133, /* UDMA timimg register 01 */++ 0x2121, /* UDMA timimg register 23 */++ 0x9111, /* UDMA timimg register 45 */++ 0x0091, /* UDMA timimg register 6 */++ 0x3266, /* DMA timimg register 01 */++ 0x0021, /* DMA timimg register 2 */++ 0x0021 /* PIO timimg register */++ };++ static const u16 IT8212ClockTable[7] = {++ 0x0505, /* UDMA clock register 01 */++ 0x0005, /* UDMA clock register 23 */++ 0x0500, /* UDMA clock register 45 */++ 0x0000, /* UDMA clock register 6 */++ 0x0005, /* DMA clock register 01 */++ 0x0005, /* DMA clock register 2 */++ 0x0005 /* PIO clock register */++ };++++ printk("IT8212CreateDiskArray enter\n");++++#if (MARK_DUMP_CREATE_INFO)++ printk("createInfo->DiskArrayId = %d\n",++ createInfo->DiskArrayId);++ printk("createInfo->ModelNumber = %s\n",++ createInfo->ModelNumber);++ printk("createInfo->RaidType = %d\n",++ createInfo->RaidType);++ printk("createInfo->ContainingDisks = %d\n",++ createInfo->ContainingDisks);++ printk("createInfo->AutoRebuildEnable = %d\n",++ createInfo->AutoRebuildEnable);++ printk("createInfo->StripeSize = %d\n",++ createInfo->StripeSize);++ printk("createInfo->BootableDisk = %d\n",++ createInfo->BootableDisk);++ printk("createInfo->NewlyCreated = %d\n",++ createInfo->NewlyCreated);++ printk("createInfo->ErasePartition = %d\n",++ createInfo->ErasePartition);++ printk("createInfo->DMASupported[0] = 0x%x\n",++ createInfo->DMASupported[0]);++ printk("createInfo->DMASupported[1] = 0x%x\n",++ createInfo->DMASupported[1]);++ printk("createInfo->DMASupported[2] = 0x%x\n",++ createInfo->DMASupported[2]);++ printk("createInfo->DMASupported[3] = 0x%x\n",++ createInfo->DMASupported[3]);++ printk("createInfo->UDMASupported[0] = 0x%x\n",++ createInfo->UDMASupported[0]);++ printk("createInfo->UDMASupported[1] = 0x%x\n",++ createInfo->UDMASupported[1]);++ printk("createInfo->UDMASupported[2] = 0x%x\n",++ createInfo->UDMASupported[2]);++ printk("createInfo->UDMASupported[3] = 0x%x\n",++ createInfo->UDMASupported[3]);++ printk("createInfo->AddressableSectors[0] = 0x%lX\n",++ createInfo->AddressableSectors[0]);++ printk("createInfo->AddressableSectors[1] = 0x%lX\n",++ createInfo->AddressableSectors[1]);++ printk("createInfo->AddressableSectors[2] = 0x%lX\n",++ createInfo->AddressableSectors[2]);++ printk("createInfo->AddressableSectors[3] = 0x%lX\n",++ createInfo->AddressableSectors[3]);++++#endif++ switch (createInfo->RaidType) {++ case RAID_LEVEL_0:++ case RAID_LEVEL_1:++ case RAID_LEVEL_10:++ case RAID_LEVEL_JBOD:++ case RAID_LEVEL_NORMAL:++ subCommand = 0x50;++ break;++ case RAID_LEVEL_NODISK:++ subCommand = 0x48;++ break;++ }++++ /*++ * The command should be sent to virtual primary master.++ */++ pAdap = ite_adapters[0];++ pChan = &pAdap->IDEChannel[0];++++ if ((buffer = kmalloc(512, GFP_KERNEL)) == NULL) {++ printk("IT8212CreateDiskArray: error kmalloc.\n");++ return -ENOMEM;++ }++ identifyData = (PIDENTIFY_DATA2) buffer;++++ /*++ * Remember the vendor specific parameters starts from word 129 not 128.++ */++ setChipStatus = (PIT8212_SET_CHIP_STATUS_INFO) (buffer + 258);++++ /*++ * Configure to RAID or NORMAL.++ */++ if (subCommand == 0x50) {++ memset((unsigned char *)identifyData, 0, sizeof(IDENTIFY_DATA));++++ /*++ * Fill up identify data.++ */++ memmove(identifyData->ModelNumber, createInfo->ModelNumber, 40);++ memmove(identifyData->SerialNumber, &createInfo->SerialNumber,++ sizeof(RAID_SERIAL_NUMBER));++++ /*++ * Set disk array virtual capacity.++ */++ UserAddressableSectors =++ IT8212DiskArrayAddressableSector(pioc->data);++ printk("IT8212CreateDiskArray: array capacity = %X\n",++ UserAddressableSectors);++ identifyData->Capacity_48bit_LOW = UserAddressableSectors;++ identifyData->Capacity_48bit_HIGH = 0;++ if (UserAddressableSectors > 0x0FFFFFFF)++ identifyData->UserAddressableSectors = 0x0FFFFFFF;++ else++ identifyData->UserAddressableSectors =++ UserAddressableSectors;++++ /*++ * Get DMA supported mode and UDMA supported mode.++ */++ dmaSupported = udmaSupported = 0xFF;++ for (i = 0; i < 4; i++) {++ if ((createInfo->ContainingDisks >> i) & 1) {++ dmaSupported &=++ (u8) createInfo->DMASupported[i];++ udmaSupported &=++ (u8) createInfo->UDMASupported[i];++ }++ }++ identifyData->MultiWordDMASupport = dmaSupported;++ identifyData->UltraDMASupport = udmaSupported;++++ /*++ * Fill up SET CHIP STATUS data (word 129 - 153)++ */++ setChipStatus->RaidType = createInfo->RaidType;++ setChipStatus->ContainingDisks = createInfo->ContainingDisks;++ setChipStatus->UltraDmaTiming01 = IT8212TimingTable[0];++ setChipStatus->UltraDmaTiming23 = IT8212TimingTable[1];++ setChipStatus->UltraDmaTiming45 = IT8212TimingTable[2];++ setChipStatus->UltraDmaTiming6 = IT8212TimingTable[3];++ setChipStatus->MultiWordDmaTiming01 = IT8212TimingTable[4];++ setChipStatus->UltraDmaTiming2 = IT8212TimingTable[5];++ setChipStatus->PioTiming4 = IT8212TimingTable[6];++ setChipStatus->AutoRebuildEnable =++ createInfo->AutoRebuildEnable;++ setChipStatus->IdeClkUDma01 = IT8212ClockTable[0];++ setChipStatus->IdeClkUDma23 = IT8212ClockTable[1];++ setChipStatus->IdeClkUDma45 = IT8212ClockTable[2];++ setChipStatus->IdeClkUDma6 = IT8212ClockTable[3];++ setChipStatus->IdeClkMDma01 = IT8212ClockTable[4];++ setChipStatus->IdeClkMDma2 = IT8212ClockTable[5];++ setChipStatus->IdeClkPio4 = IT8212ClockTable[6];++ setChipStatus->StripeSize = createInfo->StripeSize;++ setChipStatus->BootableDisk = createInfo->BootableDisk;++ setChipStatus->CheckHotSwapInterval = 0;++ setChipStatus->TargetSourceDisk = createInfo->TargetSourceDisk;++ setChipStatus->RebuildBlockSize = 0;++ setChipStatus->ResetInterval1 = 0;++ setChipStatus->ResetInterval2 = 0;++ setChipStatus->RebuildRetryTimes = 0;++ setChipStatus->NewlyCreated = createInfo->NewlyCreated;++ }++#if (MARK_DEBUG_DUMP_MEM)++ HexDump(buffer, 512);++#endif++++ /*++ * There are some contrains of disk placement. AP will take care of it.++ */++++ /*++ * Select device.++ */++ outb((u8) 0xA0, pChan->io_ports[IDE_SELECT_OFFSET]);++++ /*++ * If primary master channel is not enabled, enable it.++ */++ statusByte = inb(pChan->io_ports[IDE_CONTROL_OFFSET]);++ if (statusByte == 0) {++ PriMasterIsNull = TRUE;++ IT8212ReconfigChannel(pChan, 0, EnableChannel);++ }++++ /*++ * Wait for device ready (not BUSY and not DRQ)++ */++ WaitForDeviceReady(pChan, statusByte);++ if ((statusByte & IDE_STATUS_BUSY) || (statusByte & IDE_STATUS_DRQ)++ || (statusByte == 0)) {++ printk++ ("IT8212CreateDiskArray: disk[0] not ready. status=0x%X\n",++ statusByte);++ srbStatus = SRB_STATUS_BUSY;++ goto exit;++ }++++ /*++ * Disable interrupt to avoid the unexpected interrupt.++ */++ outb(IDE_DC_DISABLE_INTERRUPTS, pChan->io_ports[IDE_CONTROL_OFFSET]);++ outb(subCommand, pChan->io_ports[IDE_FEATURE_OFFSET]);++ outb(createInfo->DiskArrayId, pChan->io_ports[IDE_SELECT_OFFSET]);++ outb(IDE_COMMAND_SET_CHIP_STATUS, pChan->io_ports[IDE_COMMAND_OFFSET]);++++ /*++ * No disk (no data command protocol)++ */++ if (subCommand == 0x48) {++ WaitForCommandComplete(pChan, statusByte);++ if (statusByte != IDE_STATUS_IDLE) {++ printk("IT8212CreateDiskArray: disk[0] return "++ "unexpected status after issue command.\n");++ goto exit_error;++ }++ IT8212ReconfigChannel(pChan, createInfo->DiskArrayId,++ DisableChannel);++ srbStatus = SRB_STATUS_SUCCESS;++ goto exit;++ }++++ /*++ * Create RAID (PIO data out command protocol).++ */++ if (subCommand == 0x50) {++++ /*++ * Wait for BUSY=0, DRQ=1.++ */++ CheckBusyDrq(pChan, statusByte);++ if (statusByte != 0x58) {++ printk("IT8212CreateDiskArray: disk[0] return "++ "unexpected status after issue command.\n");++ goto exit_error;++ }++ WriteBuffer(pChan, buffer, 256);++++ /*++ * Check error.++ */++ WaitForCommandComplete(pChan, statusByte);++ if (statusByte != IDE_STATUS_IDLE) {++ printk("IT8212CreateDiskArray: disk[0] return "++ "unexpected status after issue command.\n");++ goto exit_error;++ }++ IT8212ReconfigChannel(pChan, createInfo->DiskArrayId,++ EnableChannel);++ srbStatus = SRB_STATUS_SUCCESS;++ goto exit;++ }++exit_error:++ /*++ * If fail, hard reset to avoid the DRQ pending.++ */++ IdeHardReset(pChan, statusByte);++ srbStatus = SRB_STATUS_ERROR;++exit:++ /*++ * If primary master is null, and we are not configuring array 0.++ * Disable primary master channel again.++ */++ if (PriMasterIsNull && createInfo->DiskArrayId)++ IT8212ReconfigChannel(pChan, 0, DisableChannel);++++ /*++ * Reenable interrupt after command complete.++ */++ outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]);++ printk("IT8212CreateDiskArray exit\n");++ return srbStatus;++} /* end IT8212CreateDiskArray */++++#if 0++/*++ * Return "virtual" drive 512 bytes identification data.++ */++static u8 IT8212IssueIdentify(uioctl_t *pioc)++{++ u8 channum;++ u8 devnum;++ u8 statusByte;++ u8 srbStatus;++ PITE_ADAPTER pAdap;++ PChannel pChan;++++ /*++ * Only support one adapter now! In the future, we can pass the argument++ * to know which adapter need to be identified.++ */++ pAdap = ite_adapters[0];++ memset(pioc->data, 0, 512 * 4);++++ /*++ * Two channels per controller.++ */++ for (channum = 0; channum < pAdap->num_channels; channum++) {++ pChan = &pAdap->IDEChannel[channum];++++ /*++ * Two devices per channel.++ */++ for (devnum = 0; devnum < 2; devnum++) {++++ /*++ * Select device.++ */++ outb((u8) ((devnum << 4) | 0xA0),++ pChan->io_ports[IDE_SELECT_OFFSET]);++++ /*++ * Check if disk online?++ */++ statusByte = inb(pChan->io_ports[IDE_ALTERNATE_OFFSET]);++ if ((statusByte & 0x40) != 0x40) {++ printk("IT8212IssueIdentify: disk[%d] is "++ "offline\n", devnum + channum * 2);++ continue;++ }++++ /*++ * Wait for device ready (Not busy and not DRQ)++ */++ WaitForDeviceReady(pChan, statusByte);++ if ((statusByte & IDE_STATUS_BUSY)++ || (statusByte & IDE_STATUS_DRQ)++ || (statusByte == 0)) {++ printk("IT8212IssueIdentify: disk[%d] not "++ "ready. status=0x%X\n",++ devnum + channum * 2, statusByte);++ srbStatus = SRB_STATUS_BUSY;++ goto exit;++ }++++ /*