Bugzilla – Attachment 61959 Details for
Bug 136944
ITE card fails after install (IT8212 Chip Set)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
IDP Log In
|
Forgot Password
[patch]
ITE Raid driver that USED to work in case it helps
Driver.txt (text/plain), 194.60 KB, created by
andy norrie
on 2006-01-04 16:51:27 UTC
(
hide
)
Description:
ITE Raid driver that USED to work in case it helps
Filename:
MIME Type:
Creator:
andy norrie
Created:
2006-01-04 16:51:27 UTC
Size:
194.60 KB
patch
obsolete
>This MAY not be any help but according to a google search this level did work with slightly earlier Linux >2.6.x kernels. > >I will try to apply the patch given but as I cant boot the system properly (I dont have disk space for a >full install with KDE C== and Kernel sources without getting the ITE card working) so I am a bit stuck > > >Regards Andy Norrie GM1MQE@AOL.COM > > > > > > > > > >ITERAID.C > > > >/* > * linux/drivers/scsi/iteraid.c > * > * (C) Copyright 2002-2004 ITE Tech, inc. > * > * Nov 11, 2002 Mark Lu file created. > * > * 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 relase 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 "hosts.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)) > >struct Scsi_Host * ite_vhost = 0; /* SCSI virtual host */ >Scsi_Cmnd * it8212_req_last = 0; /* SRB request list */ > >unsigned int NumAdapters = 0; /* Adapters number */ >PITE_ADAPTER ite_adapters[2]; /* How many adapters support */ > >/************************************************************************ > * Notifier blockto get a notify on system shutdown/halt/reboot. > ************************************************************************/ >static int ite_halt(struct notifier_block *nb, ulong event, void *buf); >struct notifier_block ite_notifier = >{ > ite_halt, NULL, 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 int driver_ver = 145; /* Current driver version */ >static int ite_major = 0; /* itedev chardev major number */ > >/************************************************************************ > * The File Operations structure for the ioctl interface of the driver. > ************************************************************************/ >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. > ************************************************************************/ >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; > } > } > /* > * If this is IDE error. > */ > else > { > 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 */ > >/************************************************************************ > * Just get the higest bit value. > ************************************************************************/ >static u8 >RaidGetHighestBit(u8 Number) >{ > > char bit; > > for (bit = 7; bit >= 0; bit--) > { > if (Number & (1 << bit)) return bit; > } > > return 0xFF; > >} /* end RaidGetHighestBit */ > >/************************************************************************ > * 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. > ************************************************************************/ >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]); > } > } > /* > * 28-bit addressing. > */ > else > { > /* > * 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); > > /* > * Allocate SCATTER/GATHER table buffer. > */ > 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. > ************************************************************************/ >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 */ > >/************************************************************************ > * Get the chip status. 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 configur- > * ation 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. > ************************************************************************/ >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]; > > /* > * Allocate space for PHYSICAL_DISK_STATUS. > */ > if ((pPhyDiskInfo = kmalloc(sizeof(PHYSICAL_DISK_STATUS) * 4, GFP_KERNEL)) == NULL) > { > printk("IT8212GetChipStatus: error kmalloc for PHYSCIAL_DISK_STATUS.\n"); > return -ENOMEM; > } > > memset(pPhyDiskInfo, 0, sizeof(PHYSICAL_DISK_STATUS)); > > /* > * 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 physical disk info to user area. > */ > 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"); > printk("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. > ************************************************************************/ >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]; > } > > /* > * Allocate 512 bytes for buffer. > */ > 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 */ > >/************************************************************************ > * > ************************************************************************/ >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. > ************************************************************************/ >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. > ************************************************************************/ >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]; > > /* > * Allocate 512-bytes buffer. > */ > if ((buffer = kmalloc(512, GFP_KERNEL)) == NULL) > { > printk("IT8212CreateDiskArray: error kmalloc.\n"); > return -ENOMEM; > } > > identifyData = (PIDENTIFY_DATA2) buffer; > > /* > * 2003/05/08 > * 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) > { > /* > * Zero identify data structure. > */ > 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 */ > >/************************************************************************ > * Return "virtual" drive 512 bytes identification data. > ************************************************************************/ >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; > } > > /* > * Disable interrupt to avoid the unexpected interrupt. > */ > outb(IDE_DC_DISABLE_INTERRUPTS, pChan->io_ports[IDE_CONTROL_OFFSET]); > > /* > * Issue command. > */ > outb(IDE_COMMAND_IDENTIFY, pChan->io_ports[IDE_COMMAND_OFFSET]); > > /* > * Wait for BUSY = 0 and DRQ = 1. > */ > CheckBusyDrq(pChan, statusByte); > if (statusByte != 0x58) > { > printk("IT8212IssueIndetify: disk[%d] returns unexpedted status after issue command. status=0x%X\n", > devnum + channum * 2, statusByte); > goto error; > } > > /* > * Read the identify data. > */ > ReadBuffer(pChan, (unsigned short *)&pChan->FullIdentifyData, 256); > > /* > * Then copy to user area. > * unsigned long copy_to_user(void *to, const void *from, unsigned long count). > */ > copy_to_user((unsigned short *) (pioc->data + ((devnum + channum * 2) * 512)), > (unsigned short *)&pChan->FullIdentifyData, 256); > > /* > * Check error after reading data. > */ > WaitForCommandComplete(pChan, statusByte); > if (statusByte != IDE_STATUS_IDLE) > { > printk("IT8212IssueIdentify: disk[%d] returns unexpected status after read data. status=0x%X\n", > devnum + channum * 2, statusByte); > goto error; > } > > } /* end for each device */ > > } /* end for each channel */ > > srbStatus = SRB_STATUS_SUCCESS; > goto exit; > >error: > > /* > * If failed, hard reset to avoid the IRQ pending. > */ > IdeHardReset(pChan, statusByte); > srbStatus = SRB_STATUS_ERROR; > >exit: > > /* > * Reenable interrupt after command complete. > */ > for (channum = 0; channum < pAdap->num_channels; channum++) > { > pChan = &pAdap->IDEChannel[channum]; > outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]); > } > > return srbStatus; > >} /* end IT8212IssueIdentify */ > >/************************************************************************ > * Reset the controller. > ************************************************************************/ >static u8 >IT8212ResetAdapter(PITE_ADAPTER pAdap) >{ > > u8 resetChannel[2]; > u8 channel; > u8 device; > u8 status[4]; > int i; > PChannel pChan; > > /* > * First, perform ATAPI soft reset if ATAPI devices are attached. > */ > for (channel = 0; channel < 2; channel++) > { > pChan = &pAdap->IDEChannel[channel]; > resetChannel[channel] = FALSE; > for (device = 0; device < 2; device++) > { > if (pChan->DeviceFlags[device] & DFLAGS_DEVICE_PRESENT) > { > if (pChan->DeviceFlags[device] & DFLAGS_ATAPI_DEVICE) > { > printk("IT8212ResetAdapter: perform ATAPI soft reset (%d, %d)\n", > channel, device); > AtapiSoftReset(pChan, device); > } > else > { > resetChannel[channel] = TRUE; > } > } > } > } > > /* > * If ATA device is present on this channel, perform channel reset. > */ > for (channel = 0; channel < 2; channel++) > { > pChan = &pAdap->IDEChannel[channel]; > if (resetChannel[channel]) > { > printk("IT8212ResetAdapter: reset channel %d\n", channel); > outb(IDE_DC_RESET_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]); > mdelay(50); > outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]); > } > } > > /* > * Check device status after reset. > */ > for (i = 0; i < 1000 * 1000; i++) > { > for (channel = 0; channel < 2; channel++) > { > pChan = &pAdap->IDEChannel[channel]; > for (device = 0; device < 2; device++) > { > if (pChan->DeviceFlags[device] & DFLAGS_DEVICE_PRESENT) > { > outb((u8)((device << 4) | 0xA0), pChan->io_ports[IDE_SELECT_OFFSET]); > status[(channel * 2) + device] = inb(pChan->io_ports[IDE_COMMAND_OFFSET]); > } > else > { > status[(channel * 2) + device] = 0; > } > } > } > > /* > * ATA device should present status 0x50 after reset. > * ATAPI device should present status 0 after reset. > */ > if ((status[0] != IDE_STATUS_IDLE && status[0] != 0x0) || > (status[1] != IDE_STATUS_IDLE && status[1] != 0x0) || > (status[2] != IDE_STATUS_IDLE && status[2] != 0x0) || > (status[3] != IDE_STATUS_IDLE && status[3] != 0x0)) > { > udelay(30); > } > else > { > break; > } > } > > if (i == 1000 * 1000) > { > printk("IT8212ResetAdapter Fail!\n"); > printk("Device status after reset = [0x%x, 0x%x, 0x%x, 0x%x]\n", > status[0], status[1], status[2], status[3]); > return FALSE; > } > else > { > printk("IT8212ResetAdapter Success!\n"); > return TRUE; > } > >} /* end IT8212ResetAdapter */ > >/************************************************************************ > * Rebuild disk array. > ************************************************************************/ >u8 >IT8212Rebuild(uioctl_t *pioc) >{ > > u8 rebuildDirection; > u8 statusByte = 0; > PRAID_REBUILD_INFO apRebuildInfo = (PRAID_REBUILD_INFO) pioc->data; > PITE_ADAPTER pAdap; > PChannel pChan; > dprintk("IT8212Rebuild enter\n"); > > rebuildDirection = (apRebuildInfo->Resume << 4) | (apRebuildInfo->DestDisk << 2) | > apRebuildInfo->SrcDisk; > > apRebuildInfo->Status = 0xFF; > > pAdap = ite_adapters[0]; > > printk("IT8212Rebuild: diskArrayId=%d\n", apRebuildInfo->DiskArrayId); > > if (apRebuildInfo->DiskArrayId < 2) > { > pChan = &pAdap->IDEChannel[0]; > } > else > { > pChan = &pAdap->IDEChannel[1]; > } > > /* > * Selcet device. > */ > outb((u8)((apRebuildInfo->DiskArrayId & 0x1) << 4 | 0xA0), > 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)) > { > apRebuildInfo->Status = REBUILD_ERR_DISK_BUSY; > printk("IT8212Rebuild: disk[%d] not ready. status=0x%X\n", > apRebuildInfo->DiskArrayId, statusByte); > return SRB_STATUS_BUSY; > } > > /* > * Disable interrupt to avoid the unexpected interrupt. > */ > outb(IDE_DC_DISABLE_INTERRUPTS, pChan->io_ports[IDE_CONTROL_OFFSET]); > > /* > * Give a direction. > */ > outb(rebuildDirection, pChan->io_ports[IDE_FEATURE_OFFSET]); > > /* > * Issue a REBUILD commmand. > */ > outb(IDE_COMMAND_REBUILD, pChan->io_ports[IDE_COMMAND_OFFSET]); > > /* > * Check for errors. > */ > WaitForCommandComplete(pChan, statusByte); > > /* > * Reenable interrupt after command complete. > */ > outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]); > > if (statusByte != IDE_STATUS_IDLE) > { > if (statusByte & IDE_STATUS_ERROR) > { > apRebuildInfo->Status = inb(pChan->io_ports[IDE_NSECTOR_OFFSET]); > printk("IT8212Rebuild: rebuild error. reason=0x%X\n", apRebuildInfo->Status); > } > return apRebuildInfo->Status; > } > > dprintk("IT8212Rebuild exit\n"); > > return SRB_STATUS_PENDING; > >} /* end IT8212Rebuild */ > >/************************************************************************ > * Switch to DMA mode if necessary. > * > * offset 0x50 = PCI Mode Control Register > * > * Bit 0 = PCI Mode Select (1=firmware mode, 0=transparent mode) > * Bit 1 = Primary Channel IDE Clock Frequency Select (1=50, 0=66) > * Bit 2 = Secondary Channel IDE Clock Freq Select (1=50, 0=66) > * Bit 3 = Primary Channel Dev 0 Transfer Mode (1=MultiWord DMA, 0=Ultra DMA) > * Bit 4 = Primary Channel Dev 1 Transfer Mode (1=MultiWord DMA, 0=Ultra DMA) > * Bit 5 = Secondary Channel Dev 0 Transfer Mode (1=MultiWord DMA, 0=Ultra DMA) > * Bit 6 = Secondary Channel Dev 1 Transfer Mode (1=MultiWord DMA, 0=Ultra DMA) > * Bit 7 = PCI Mode Reset > ************************************************************************/ >void >IT8212SwitchDmaMode(PChannel pChan, u8 DeviceId) >{ > > u8 pciControl; > u8 channel; > u8 device; > u8 configByte = 0; > u8 RevisionID; > struct pci_dev * pPciDev = pChan->pPciDev; > > /* > * These tables are for performance issue. Better formance than lots > * of "Shifts". > */ > static const u8 dmaModeV10[4] = {0x18, 0x18, 0x60, 0x60}; > static const u8 udmaModeV10[4] = {0xE7, 0xE7, 0x9F, 0x9F}; > static const u8 ideClock[4] = {0xFD, 0xFD, 0xFB, 0xFB}; > > /* > * channel --> 0-1; device --> 0-1; DeviceId --> 0-3; > */ > channel = DeviceId >> 1; > device = DeviceId & 1; > > /* > * Do nothing if the mode switch is unnecessary. > */ > if (!pChan->DoSwitch || pChan->ActiveDevice == DeviceId) > { > dprintk("IT8212SwitchDmaMode: do not need to switch mode!\n"); > return; > } > > printk("IT8212SwitchDmaMode: switch DMA mode for dev (%x)\n", DeviceId); > > pci_read_config_byte(pPciDev, 0x50, &pciControl); > pci_read_config_byte(pPciDev, 0x08, &RevisionID); > > /* > * Running on MULTIWORD_DMA mode. > */ > if (pChan->DmaType[device] == USE_MULTIWORD_DMA) > { > /* > * Switch to DMA mode. > */ > if (RevisionID == 0x10) > { > configByte = pciControl | dmaModeV10[DeviceId]; > } > pci_write_config_byte(pPciDev, 0x50, configByte); > } > /* > * Running on ULTRA DMA mode. > */ > else > { > /* > * Select UDMA mode. > */ > configByte = pciControl; > if (RevisionID == 0x10) > { > configByte &= udmaModeV10[DeviceId]; > } > > /* > * Select IDE clock. > */ > configByte = (configByte & ideClock[DeviceId]) | > (pChan->IdeClock[device] << (channel + 1)); > > pci_write_config_byte(pPciDev, 0x50, configByte); > > /* > * Set UDMA timing. > * > * offset 0x56 = PCI Mode Primary Device 0 Ultra DMA Timing Registers > * offset 0x57 = PCI Mode Primary Device 1 Ultra DMA Timing Registers > * offset 0x5A = PCI Mode Secondary Device 0 Ultra DMA Timing Registers > * offset 0x5B = PCI Mode Secondary Device 1 Ultra DMA Timing Registers > */ > if (RevisionID == 0x10) > { > configByte = pChan->UdmaTiming[device]; > pci_write_config_byte(pPciDev, (u8) (0x56 + (channel * 4)), configByte); > pci_write_config_byte(pPciDev, (u8) (0x56 + (channel * 4) + 1), configByte); > } > > /* > * Set PIO/DMA timing (Becasuse maybe the IDE clock is changed.) > */ > configByte = pChan->PioDmaTiming[pChan->IdeClock[device]]; > pci_write_config_byte(pPciDev, (u8) (0x54 + (channel * 4)), configByte); > } > > /* > * Record the Active device on this channel > */ > pChan->ActiveDevice = device; > >} /* end IT8212SwitchDmaMode */ > >/************************************************************************ > * IT8212 read/write routine. > ************************************************************************/ >u32 >IT8212ReadWrite(PChannel pChan, PSCSI_REQUEST_BLOCK Srb) >{ > > u8 statusByte = 0; > u32 startingSector; > u32 sectorNumber; > u32 capacity; > PITE_ADAPTER pAdap; > > if (Srb->TargetId >= 4) > { > pAdap = ite_adapters[1]; > if (Srb->TargetId < 6) pChan = &pAdap->IDEChannel[0]; > else pChan = &pAdap->IDEChannel[1]; > } > else > { > pAdap = ite_adapters[0]; > if (Srb->TargetId < 2) pChan = &pAdap->IDEChannel[0]; > else pChan = &pAdap->IDEChannel[1]; > } > > /* > * Return error if overrun. > */ > startingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 | > ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 | > ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 | > ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24; > > sectorNumber = (unsigned short) ((Srb->DataTransferLength + 0x1FF) / 0x200); > > capacity = pChan->IdentifyData[Srb->TargetId & 0x1].UserAddressableSectors; > if (capacity == 0x0FFFFFFF) > { > capacity = pChan->IdentifyData[Srb->TargetId & 0x1].Capacity_48bit_LOW; > } > > if ((startingSector + sectorNumber - 1) > capacity) > { > printk("IT8212ReadWrite: disk[%d] over disk size.\n", Srb->TargetId); > printk("capacity: %d. starting sector: %d. sector number: %d\n", > capacity, startingSector, sectorNumber); > return SRB_STATUS_ERROR; > } > > /* > * Select device. > */ > outb((u8)((Srb->TargetId & 0x1) << 4 | 0xA0), 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("IT8212ReadWrite: disk[%d] not ready. status=0x%x\n", > Srb->TargetId, statusByte); > return SRB_STATUS_BUSY; > } > > /* > * First, switch to DMA or UDMA mode if running on bypass mode. > */ > if (pAdap->bypass_mode) > { > IT8212SwitchDmaMode(pChan, Srb->TargetId); > } > > /* > * Check the SCATTER/GATHER count. The upper will give the different > * memory address depend on whether use_sg is used or not. > */ > if (Srb->UseSg == 0) > { > IdeBuildDmaTable(pChan, Srb); > } > else > { > IdeBuildDmaSgTable(pChan, Srb); > } > > /* > * Start transfer the data. > */ > IdeStartTransfer(pChan, Srb, startingSector, sectorNumber); > > /* > * Wait for interrupt. > */ > return SRB_STATUS_PENDING; > >} /* end IT8212ReadWrite */ > >/************************************************************************ > * Setup the transfer mode. > ************************************************************************/ >void >IT8212SetTransferMode >( > PChannel pChan, > u32 DiskId, > u8 TransferMode, > u8 ModeNumber >) >{ > > u8 statusByte = 0; > > /* > * Select device. > */ > outb((u8) ((DiskId & 0x1) << 4 | 0xA0), 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)) > { > printk("IT8212SetTransferMode: disk[%d] not ready. status=0x%x\n", > DiskId, statusByte); > return; > } > > /* > * Feature number ==> 03 > * > * Mode contained in Sector Count Register. > * > * Bits(7:3) Bits(2:0) Mode > * > * 00000 000 PIO default mode > * 00000 001 PIO default mode, disable IORDY > * 00001 mode PIO flow control transfer mode > * 00010 mode Single Word DMA mode > * 00100 mode Multi-word DMA mode > * 01000 mode Ultra DMA mode > */ > TransferMode |= ModeNumber; > > outb(0x03, pChan->io_ports[IDE_FEATURE_OFFSET]); > outb(TransferMode, pChan->io_ports[IDE_NSECTOR_OFFSET]); > outb(0, pChan->io_ports[IDE_HCYL_OFFSET]); > outb(0, pChan->io_ports[IDE_MIDCYL_OFFSET]); > outb(IDE_COMMAND_SET_FEATURE, pChan->io_ports[IDE_COMMAND_OFFSET]); > > /* > * Check error. > */ > WaitForBaseCommandComplete(pChan, statusByte); > > if ((statusByte != IDE_STATUS_IDLE) && (statusByte != 0)) > { > printk("IT8212SetTransferMode: disk[%d]", DiskId); > printk("return unexpected status after issue command. 0x%x\n", > statusByte); > } > >} /* end IT8212SetTransferMode */ > >/************************************************************************ > * Set the best transfer mode for device. > ************************************************************************/ >void >IT8212SetBestTransferMode(PITE_ADAPTER pAdap, PChannel pChan, u8 channel) >{ > > u8 i; > u8 k; > u8 transferMode; > u8 modeNumber; > u8 pciControl; > u8 device; > u8 configByte; > u8 cableStatus[2] = {CABLE_40_PIN, CABLE_40_PIN}; > u8 RevisionID; > struct pci_dev * pPciDev = pChan->pPciDev; > PIDENTIFY_DATA2 ideIdentifyData; > > /* > * UDMA timing table for 66MHz clock. > * UDMA timing table for 50MHz clock. > * Best of IDE clock in this mode. > */ > static const u8 udmaTiming[3][7] = > { > {0x44, 0x42, 0x31, 0x21, 0x11, 0x22, 0x11}, > {0x33, 0x31, 0x21, 0x21, 0x11, 0x11, 0x11}, > {IDE_CLOCK_66, IDE_CLOCK_50, IDE_CLOCK_66, IDE_CLOCK_66, IDE_CLOCK_66, IDE_CLOCK_50, IDE_CLOCK_66} > }; > > /* > * DMA timing table for 66 MHz clock. > * DMA timing table for 50 MHz clock. > */ > static const u8 dmaTiming[2][3] = > { > {0x88, 0x32, 0x31}, > {0x66, 0x22, 0x21} > }; > > /* > * PIO timing table for 66 MHz clock. > * PIO timing table for 50 MHz clock. > */ > static const u8 pioTiming[2][5] = > { > {0xAA, 0xA3, 0xA1, 0x33, 0x31}, > {0x88, 0x82, 0x81, 0x32, 0x21} > }; > > u8 pio_dma_timing[2][2][4] = > { > {{0, 0, 0, 0}, {0, 0, 0, 0}}, > {{0, 0, 0, 0}, {0, 0, 0, 0}} > }; > > /* > * These tables are for performance issue. Better formance than lots > * of "Shifts". > */ > static const u8 udmaModeV10[4] = {0xE7, 0xE7, 0x9F, 0x9F}; > static const u8 dmaMode[4] = {0x08, 0x10, 0x20, 0x40}; > static const u8 udmaMode[4] = {0xF7, 0xEF, 0xDF, 0xBF}; > static const u8 ideClock[4] = {0xFD, 0xFD, 0xFB, 0xFB}; > > /* > * 2003/07/24 > * If running on Firmware mode, get cable status from it. > */ > > for (i = 0; i < 2; i++) > { > /* > * The dafault of cable status is in PCI configuration 0x40. > */ > cableStatus[i] = pChan->Cable80[i]; > > /* > * channel -->0 to 1. > * device -->0 or 1. > */ > pChan->UseDma[i] = TRUE; > device = i & 1; > > if (!(pChan->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT) || > (pChan->DeviceFlags[i] & DFLAGS_CONFIG_CHANGED)) > { > pio_dma_timing[0][channel][device] = pio_dma_timing[0][channel][device + 2] = 0; > pio_dma_timing[1][channel][device] = pio_dma_timing[1][channel][device + 2] = 0; > continue; > } > > /* > * Set PIO Mode. > */ > ideIdentifyData = &pChan->IdentifyData[i]; > if ((!(ideIdentifyData->ValidFieldIndicator & 0x02)) || (ideIdentifyData->AdvancedPIOModes == 0)) > { > transferMode = PIO_FLOW_CONTROL; > modeNumber = 2; > } > else > { > transferMode = PIO_FLOW_CONTROL; > modeNumber = RaidGetHighestBit((u8) ideIdentifyData->AdvancedPIOModes) + 3; > } > > IT8212SetTransferMode(pChan, i, transferMode, modeNumber); > > /* > * Record the PIO timing for later use.(0 to 4) > */ > pio_dma_timing[0][channel][device] = pioTiming[0][modeNumber]; > pio_dma_timing[1][channel][device] = pioTiming[1][modeNumber]; > > /* > * Get the best transfer mode (maybe Ultra DMA or Multi-Word DMA). > */ > ideIdentifyData = &pChan->IdentifyData[i]; > if ((!(ideIdentifyData->ValidFieldIndicator & 0x04)) || (ideIdentifyData->UltraDMASupport == 0)) > { > /* > * UltraDMA is not valid. > */ > transferMode = MULTIWORD_DMA; > modeNumber = RaidGetHighestBit(ideIdentifyData->MultiWordDMASupport); > printk("The best transfer mode of Device[%d] is DMA-%d\n", i, modeNumber); > } > else > { > transferMode = ULTRA_DMA; > modeNumber = RaidGetHighestBit(ideIdentifyData->UltraDMASupport); > printk("The best transfer mode of Device[%d] is Ultra-%d\n", i, modeNumber); > > /* > * If this is 40-pin cable. Limit to Ultra DMA mode 2. > */ ># if (0) > if ((cableStatus[i] == CABLE_40_PIN) && (modeNumber > 2)) > { > printk("Reduce trans mode of Device[%d] to Ultra-2 for cable issue.\n", i); > modeNumber = 0x02; > } ># endif > } > > IT8212SetTransferMode(pChan, i, transferMode, modeNumber); > > /* > * If running on ByPass mode, driver must take the responsibility to > * set the PIO/DMA/UDMA timing. > */ > if (pAdap->bypass_mode) > { > pci_read_config_byte(pPciDev, 0x50, &pciControl); > pci_read_config_byte(pPciDev, 0x08, &RevisionID); > > if (transferMode == ULTRA_DMA) > { > /* > * Set this channel to UDMA mode (not only the device). > */ > if (RevisionID == 0x10) > { > configByte = pciControl & udmaModeV10[i + channel * 2]; > } > else > { > configByte = pciControl & udmaMode[i + channel * 2]; > } > > /* > * Select IDE clock (50MHz or 66MHz). > */ > configByte &= ideClock[i + channel * 2]; > configByte |= (udmaTiming[2][modeNumber] << (channel + 1)); > > pci_write_config_byte(pPciDev, 0x50, configByte); > > /* > * Set UDMA timing. > */ > configByte = udmaTiming[udmaTiming[2][modeNumber]][modeNumber]; > if (modeNumber == 5 || modeNumber == 6) > { > /* > * Enable UDMA mode 5/6 > */ > configByte |= UDMA_MODE_5_6; > } > > /* > * Bug Bug. Fill these two fields into the same value. > */ > if (RevisionID == 0x10) > { > pci_write_config_byte(pPciDev, (u8) (0x56 + (channel * 4)), configByte); > pci_write_config_byte(pPciDev, (u8) (0x56 + (channel * 4) + 1), configByte); > } > else > { > pci_write_config_byte(pPciDev, (u8) (0x56 + (channel * 4) + device), configByte); > } > > /* > * Record the best UDMA mode for this device. > */ > pChan->DmaType[i] = ULTRA_DMA; > pChan->IdeClock[i] = udmaTiming[2][modeNumber]; > pChan->UdmaTiming[i] = configByte; > } > else if (transferMode == MULTIWORD_DMA) > { > /* > * If an ATAPI device with DMA mode, force it to run in PIO mode. > */ > if (RevisionID == 0x10 && pChan->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE) > { > pChan->UseDma[i] = FALSE; > } > else > { > /* > * Set this device to DMA mode. > */ > configByte = pciControl | dmaMode[i + channel * 2]; > pci_write_config_byte(pPciDev, 0x50, configByte); > > /* > * Record DMA timing (for later use). > */ > pio_dma_timing[0][channel][device + 2] = dmaTiming[0][modeNumber]; > pio_dma_timing[1][channel][device + 2] = dmaTiming[1][modeNumber]; > } > pChan->DmaType[i] = USE_MULTIWORD_DMA; > } > pChan->ActiveDevice = device; > } > } > > /* > * Because each channel owns one PIO/DMA timimg register only, so we > * must set the timing to the slowest one to fit all. Really stupid H/W! :( > */ > if (pAdap->bypass_mode) > { > /* > * Loop for the two IDE clocks (50 MHz and 66 MHz). > */ > for (i = 0; i < 2; i++) > { > configByte = 0; > for (k = 0; k < 4; k++) > { > /* > * High part. > */ > if ((pio_dma_timing[i][channel][k] & 0xF0) > (configByte & 0xF0)) > { > configByte = (configByte & 0xF) | (pio_dma_timing[i][channel][k] & 0xF0); > } > > /* > * Low part. > */ > if ((pio_dma_timing[i][channel][k] & 0xF) > (configByte & 0xF)) > { > configByte = (configByte & 0xF0) | (pio_dma_timing[i][channel][k] & 0xF); > } > } > > /* > * Record the PIO/DMA timing for this channel. > */ > pChan->PioDmaTiming[i] = configByte; > } > > /* > * Set PIO/DMA timing register for each channel. > */ > configByte = pChan->PioDmaTiming[(pciControl >> (channel + 1)) & 1]; > if (configByte != 0) > { > pci_write_config_byte(pPciDev, (u8) (0x54 + (channel * 4)), configByte); > } > > /* > * Check shall we do switch between the two devices > */ > for (i = 0; i < 2; i++) > { > pChan->DoSwitch = TRUE; > > /* > * Master is not present > */ > if (!(pChan->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT) || > (pChan->DeviceFlags[i] & DFLAGS_CONFIG_CHANGED)) > { > printk("Channel %x: master is not present. No switch mode.\n", channel); > pChan->DoSwitch = FALSE; > continue; > } > > /* > * Slave is not present > */ > if (!(pChan->DeviceFlags[i + 1] & DFLAGS_DEVICE_PRESENT) || > (pChan->DeviceFlags[i + 1] & DFLAGS_CONFIG_CHANGED)) > { > printk("Channel %x: slave is not present. No switch mode.\n", channel); > pChan->DoSwitch = FALSE; > continue; > } > > /* > * If both devices are running on DMA mode, no switch. > */ > if (pChan->DmaType[i] == USE_MULTIWORD_DMA && pChan->DmaType[i + 1] == USE_MULTIWORD_DMA) > { > printk("Channel %x: run on DMA mode only. No switch mode.\n", channel); > pChan->DoSwitch = FALSE; > continue; > } > > /* > * No switch if the two devices are running on the same mode. > */ > if ((pChan->DmaType[i] == pChan->DmaType[i + 1] ) && > (pChan->UdmaTiming[i] == pChan->UdmaTiming[i + 1]) && > (pChan->IdeClock[i] == pChan->IdeClock[i + 1] )) > { > printk("Channel %x: two dev run on the same mode. No switch mode.\n", channel); > pChan->DoSwitch = FALSE; > continue; > } > > printk("Channel %x: switch mode if needed.\n", channel); > } > } > >} /* end IT8212SetBestTransferMode */ > >/************************************************************************ > * Initialize bypass(transparent) mode if BIOS is not ready. > ************************************************************************/ >u8 >IT8212InitBypassMode(struct pci_dev *pPciDev) >{ > > /* > * Reset local CPU, and set BIOS not ready. > */ > pci_write_config_byte(pPciDev, 0x5E, 0x01); > > /* > * Set to bypass mode, and reset PCI bus. > */ > pci_write_config_byte(pPciDev, 0x50, 0x00); > > pci_write_config_word(pPciDev, 0x4, 0x0047); > pci_write_config_word(pPciDev, 0x40, 0xA0F3); > > pci_write_config_dword(pPciDev,0x4C, 0x02040204); > pci_write_config_byte(pPciDev, 0x42, 0x36); > pci_write_config_byte(pPciDev, 0x0D, 0x00); > > return TRUE; > >} /* end IT8212InitBypassMode */ > >/************************************************************************ > * This is the interrupt service routine for ATAPI IDE miniport driver. > * TURE if expecting an interrupt. > ************************************************************************/ >u8 >IT8212Interrupt(PChannel pChan, u8 bypass_mode) >{ > > u8 statusByte; > u8 bmstatus; > u32 i; > unsigned long bmbase; > PSCSI_REQUEST_BLOCK Srb; > > bmstatus = 0; > bmbase = pChan->dma_base; > Srb = pChan->CurrentSrb; > > if (Srb == 0 || pChan->ExpectingInterrupt == 0) > { > dprintk("IT8212Interrupt: suspicious interrupt!\n"); > > /* > * Clear interrupt by reading status register. > */ > outb((u8) 0xA0, pChan->io_ports[IDE_SELECT_OFFSET]); > GetBaseStatus(pChan, statusByte); > outb((u8) 0xB0, pChan->io_ports[IDE_SELECT_OFFSET]); > GetBaseStatus(pChan, statusByte); > outb(bmbase + 2, (u8) (inb(bmbase + 2) | BM_STAT_FLG_INT)); > return FALSE; > } > > /* > * To handle share IRQ condition. If the interrupt is not ours, just > * return FALSE. > */ > bmstatus = inb(bmbase + 2); > if ((bmstatus & BM_STAT_FLG_INT) == 0) > { > dprintk("IT8212Interrupt: suspicious interrupt (int bit is not on)\n"); > return FALSE; > } > > /* > * Bug Fixed: All PIO access are blocked during bus master operation, so > * stop bus master operation before we try to access IDE registers. > */ > if (bypass_mode) > { > outb(bmbase, 0); > } > > /* > * Clear interrupt by reading status register. > */ > GetBaseStatus(pChan, statusByte); > outb(bmbase + 2, (u8) (bmstatus | BM_STAT_FLG_INT)); > > /* > * Handle ATAPI interrupt. > */ > if (pChan->DeviceFlags[Srb->TargetId & 1] & DFLAGS_ATAPI_DEVICE) > { > return AtapiInterrupt(pChan); > } > > pChan->ExpectingInterrupt = FALSE; > > if ((statusByte & IDE_STATUS_BUSY) || (statusByte & IDE_STATUS_DRQ)) > { > /* > * Ensure BUSY and DRQ is non-asserted. > */ > for (i = 0; i < 100; i++) > { > GetBaseStatus(pChan, statusByte); > if (!(statusByte & IDE_STATUS_BUSY) && !(statusByte & IDE_STATUS_DRQ)) > { > break; > } > mdelay(5); > } > > if (i == 100) > { > printk("IT8212Interrupt: disk[%x] return busy or drq status. status = 0x%x\n", > Srb->TargetId, statusByte); > return FALSE; > } > } > > if (statusByte & IDE_STATUS_ERROR) > { > /* > * Stop bus master operation. > */ > outb(bmbase, 0); > > printk("IT8212Interrupt: error!\n"); > > /* > * Map error to specific SRB status and handle request sense. > */ > Srb->SrbStatus = MapError(pChan, Srb); > } > else > { > Srb->SrbStatus = SRB_STATUS_SUCCESS; > } > > pChan->CurrentSrb = NULL; > > TaskDone(pChan, Srb); > > return TRUE; > >} /* end IT8212Interrupt */ > >/************************************************************************ > * This is the interrupt service routine for ATAPI IDE miniport driver. > * TRUE if expecting an interrupt. Remember the ATAPI io registers are > * different from IDE io registers and this is for each channel not for > * entire controller. > ************************************************************************/ >static u8 >AtapiInterrupt(PChannel pChan) >{ > > u32 wordCount; > u32 wordsThisInterrupt; > u32 status; > u32 i; > u8 statusByte; > u8 interruptReason; > u8 target_id; > PSCSI_REQUEST_BLOCK srb; > PITE_ADAPTER pAdap; > > wordCount = 0; > wordsThisInterrupt = 256; > srb = pChan->CurrentSrb; > target_id = srb->TargetId; > > if (target_id >= 4) > { > pAdap = ite_adapters[1]; > if (target_id < 6) pChan = &pAdap->IDEChannel[0]; > else pChan = &pAdap->IDEChannel[1]; > } > else > { > pAdap = ite_adapters[0]; > if (target_id < 2) pChan = &pAdap->IDEChannel[0]; > else pChan = &pAdap->IDEChannel[1]; > } > > /* > * Clear interrupt by reading status. > */ > GetBaseStatus(pChan, statusByte); > > dprintk("AtapiInterrupt: entered with status (%x)\n", statusByte); > > if (statusByte & IDE_STATUS_BUSY) > { > /* > * Ensure BUSY is non-asserted. > */ > for (i = 0; i < 10; i++) > { > GetBaseStatus(pChan, statusByte); > if (!(statusByte & IDE_STATUS_BUSY)) > { > break; > } > mdelay(5); > } > > if (i == 10) > { > printk("AtapiInterrupt: BUSY on entry. Status %x\n", statusByte); > return FALSE; > } > } > > /* > * Check for error conditions. > */ > if (statusByte & IDE_STATUS_ERROR) > { > if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) > { > /* > * Fail this request. > */ > status = SRB_STATUS_ERROR; > goto CompleteRequest; > } > } > > /* > * Check reason for this interrupt. > */ > interruptReason = (inb(pChan->io_ports[ATAPI_INTREASON_OFFSET]) & 0x3); > wordsThisInterrupt = 256; > > if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) > { > /* > * Write the packet. > */ > printk("AtapiInterrupt: writing Atapi packet.\n"); > > /* > * Send CDB to device. > */ > WriteBuffer(pChan, (unsigned short *)srb->Cdb, 6); > > return TRUE; > } > else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) > { > /* > * Write the data. > */ > > /* > * Pick up bytes to transfer and convert to words. > */ > wordCount = inb(pChan->io_ports[ATAPI_LCYL_OFFSET]); > wordCount |= inb(pChan->io_ports[ATAPI_HCYL_OFFSET]) << 8; > > /* > * Covert bytes to words. > */ > wordCount >>= 1; > > if (wordCount != pChan->WordsLeft) > { > printk( "AtapiInterrupt: %d words requested; %d words xferred\n", > pChan->WordsLeft, wordCount); > } > > /* > * Verify this makes sense. > */ > if (wordCount > pChan->WordsLeft) > { > wordCount = pChan->WordsLeft; > } > > /* > * Ensure that this is a write command. > */ > if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) > { > dprintk("AtapiInterrupt: write interrupt\n"); > WaitOnBusy(pChan, statusByte); > WriteBuffer(pChan, pChan->DataBuffer, wordCount); > ># if (0) > /* > * Translate ATAPI data back to SCSI data if needed (don't > * convert if the original command is SCSIOP_MODE_SELECT10) > */ > if (srb->Cdb[0] == ATAPI_MODE_SELECT && pchan->ConvertCdb) > { > Atapi2Scsi(pChan, srb, (char *)pChan->DataBuffer, wordCount << 1); > } ># endif > } > else > { > printk("AtapiInterrupt: int reason %x, but srb is for a write %p.\n", > interruptReason, srb); > > /* > * Fail this request. > */ > status = SRB_STATUS_ERROR; > goto CompleteRequest; > } > > /* > * Advance data buffer pointer and bytes left. > */ > pChan->DataBuffer += wordCount; > pChan->WordsLeft -= wordCount; > > return TRUE; > } > else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) > { > /* > * Pick up bytes to transfer and convert to words. > */ > wordCount = inb(pChan->io_ports[ATAPI_LCYL_OFFSET]); > wordCount |= inb(pChan->io_ports[ATAPI_HCYL_OFFSET]) << 8; > > /* > * Covert bytes to words. > */ > wordCount >>= 1; > if (wordCount != pChan->WordsLeft) > { > printk("AtapiInterrupt: %d words requested; %d words xferred\n", > pChan->WordsLeft, wordCount); > } > > /* > * Verify this makes sense. > */ > if (wordCount > pChan->WordsLeft) > { > wordCount = pChan->WordsLeft; > } > > /* > * Ensure that this is a read command. > */ > if (srb->SrbFlags & SRB_FLAGS_DATA_IN) > { > dprintk("AtapiInterrupt: read interrupt\n"); > WaitOnBusy(pChan, statusByte); > ReadBuffer(pChan, pChan->DataBuffer, wordCount); > > /* > * From Windows DDK > * You should typically set the ANSI-approved Version field, > * in the INQUIRY response, to at least 2. > */ > if (srb->Cdb[0] == SCSIOP_INQUIRY) > { > /* > * Maybe it's not necessary in Linux driver. > */ > *((unsigned char *)pChan->DataBuffer + 2) = 2; > } > } > else > { > printk("AtapiInterrupt: int reason %x, but srb is for a read %p.\n", > interruptReason, srb); > > /* > * Fail this request. > */ > status = SRB_STATUS_ERROR; > goto CompleteRequest; > } > > /* > * Advance data buffer pointer and bytes left. > */ > pChan->DataBuffer += wordCount; > pChan->WordsLeft -= wordCount; > > /* > * Check for read command complete. > */ > if (pChan->WordsLeft == 0) > { > /* > * Work around to make many atapi devices return correct sector size > * of 2048. Also certain devices will have sector count == 0x00, check > * for that also. > */ > if ((srb->Cdb[0] == 0x25) && > ((pChan->IdentifyData[srb->TargetId & 1].GeneralConfiguration >> 8) & 0x1F) == 0x05) > { > pChan->DataBuffer -= wordCount; > if (pChan->DataBuffer[0] == 0x00) > { > *((u32 *) &(pChan->DataBuffer[0])) = 0xFFFFFF7F; > } > > *((u32 *) &(pChan->DataBuffer[2])) = 0x00080000; > pChan->DataBuffer += wordCount; > } > } > return TRUE; > } > else if (interruptReason == 0x3 && !(statusByte & IDE_STATUS_DRQ)) > { > dprintk("AtapiInterrupt: command complete!\n"); > /* > * Command complete. > */ > if (pChan->WordsLeft) > { > status = SRB_STATUS_DATA_OVERRUN; > } > else > { > status = SRB_STATUS_SUCCESS; > } > >CompleteRequest: > > if (status == SRB_STATUS_ERROR) > { > /* > * Map error to specific SRB status and handle request sense. > */ > printk("AtapiInterrupt error\n"); > > status = MapError(pChan, srb); > > /* > * Try to recover it.... 2003/02/27 > */ > > > pChan->RDP = FALSE; > } > else > { > /* > * Wait for busy to drop. > */ > for (i = 0; i < 30; i++) > { > GetStatus(pChan, statusByte); > if (!(statusByte & IDE_STATUS_BUSY)) > { > break; > } > udelay(500); > } > > if (i == 30) > { > /* > * Reset the controller. > */ > printk("AtapiInterrupt: resetting due to BSY still up - %x.\n", > statusByte); > AtapiResetController(pAdap, pChan); > return TRUE; > } > > /* > * Check to see if DRQ is still up. > */ > if (statusByte & IDE_STATUS_DRQ) > { > for (i = 0; i < 500; i++) > { > GetStatus(pChan, statusByte); > if (!(statusByte & IDE_STATUS_DRQ)) > { > break; > } > udelay(100); > } > > if (i == 500) > { > /* > * Reset the controller. > */ > printk("AtapiInterrupt: resetting due to DRQ still up - %x\n", > statusByte); > AtapiResetController(pAdap, pChan); > return TRUE; > } > } > } > > /* > * Clear interrupt expecting flag. > */ > pChan->ExpectingInterrupt = FALSE; > > /* > * Sanity check that there is a current request. > */ > if (srb != NULL) > { > /* > * Set status in SRB. > */ > srb->SrbStatus = (u8)status; > > /* > * Check for underflow. > */ > if (pChan->WordsLeft) > { > /* > * Subtract out residual words and update if filemark hit, > * setmark hit , end of data, end of media... > */ > if (!(pChan->DeviceFlags[srb->TargetId & 1] & DFLAGS_TAPE_DEVICE)) > { > if (status == SRB_STATUS_DATA_OVERRUN) > { > srb->DataTransferLength -= pChan->WordsLeft * 2; > } > else > { > srb->DataTransferLength = 0; > } > } > else > { > srb->DataTransferLength -= pChan->WordsLeft * 2; > } > } > > GetBaseStatus(pChan, statusByte); > if (pChan->RDP && !(statusByte & IDE_STATUS_DSC)) > { > printk("-@@-\n"); > } > else > { > /* > * Clear current SRB. Indicate ready for next request. > */ > pChan->CurrentSrb = NULL; > TaskDone(pChan, srb); > } > } > else > { > printk("AtapiInterrupt: no SRB!\n"); > } > > return TRUE; > } > else > { > /* > * Unexpected int. > */ > printk("AtapiInterrupt: unexpected interrupt. intReason %x. status %x.\n", > interruptReason, statusByte); > return FALSE; > } > > return TRUE; > >} /* end AtapiInterrupt */ > >/************************************************************************ > * IRQ handler. > ************************************************************************/ >static irqreturn_t >Irq_Handler(int irq, void *dev_id, struct pt_regs *regs) >{ > > int handled = 0; > u8 i; > u8 j; > unsigned long flags; > PITE_ADAPTER pAdap; > > spin_lock_irqsave(&io_request_lock, flags); > > /* > * Scan for interrupt to process. > */ > for (i = 0; i < NumAdapters; i++) > { > pAdap = ite_adapters[i]; > if (pAdap->irq != irq) continue; > > handled = 1; > for (j = 0; j < pAdap->num_channels; j++) > { > IT8212Interrupt(&pAdap->IDEChannel[j], pAdap->bypass_mode); > } > } > > spin_unlock_irqrestore(&io_request_lock, flags); > > return IRQ_RETVAL(handled); > >} /* end Irq_Handler */ > >/************************************************************************ > * This routine handles IDE Verify. > ************************************************************************/ >u8 >IdeVerify(PChannel pChan, PSCSI_REQUEST_BLOCK Srb) >{ > > u8 drvSelect; > u8 statusByte = 0; > u32 startingSector; > u32 sectors; > u32 endSector; > u32 sectorCount; > > /* > * Select device > */ > outb((u8)((Srb->TargetId & 0x1) << 4 | 0xA0), 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("IdeVerify: disk[%d] not ready. status=0x%x\n", > Srb->TargetId, statusByte); > return SRB_STATUS_BUSY; > } > > /* > * Get the starting sector number from CDB. > */ > startingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 | > ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 | > ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 | > ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24; > > sectorCount = (u16)(((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8 | > ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb ); > > endSector = startingSector + sectorCount; > > /* > * Drive has these number sectors. > * > * 48-bit addressing. > */ > if (endSector > 0x0FFFFFFF) > { > sectors = pChan->IdentifyData[Srb->TargetId & 0x01].Capacity_48bit_LOW; > > printk("IdeVerify (48-bit): starting sector %d, Ending sector %d\n", > startingSector, endSector); > > if (endSector > sectors) > { > /* > * Too big, round down. > */ > printk("IdeVerify: truncating request to %x blocks\n", > sectors - startingSector - 1); > > outb((u8)((sectors - startingSector - 1) >> 8), > pChan->io_ports[IDE_NSECTOR_OFFSET]); > outb((u8)(sectors - startingSector - 1), > pChan->io_ports[IDE_NSECTOR_OFFSET]); > } > else > { > /* > * Set up sector count register. Round up to next block. > */ > if (sectorCount > 0xFFFF) > { > sectorCount = (u16)0xFFFF; > } > > outb((u8)(sectorCount >> 8), pChan->io_ports[IDE_NSECTOR_OFFSET]); > outb((u8) sectorCount, pChan->io_ports[IDE_NSECTOR_OFFSET]); > } > > /* > * Indicate expecting an interrupt. > */ > pChan->ExpectingInterrupt = TRUE; > > /* > * Set up LBA address > */ > outb((u8) (startingSector >> 24), pChan->io_ports[IDE_LOCYL_OFFSET]); > outb((u8) startingSector, pChan->io_ports[IDE_LOCYL_OFFSET]); > outb((u8) 0, pChan->io_ports[IDE_MIDCYL_OFFSET]); > outb((u8) (startingSector >> 8), pChan->io_ports[IDE_MIDCYL_OFFSET]); > outb((u8) 0, pChan->io_ports[IDE_HCYL_OFFSET]); > outb((u8) (startingSector >> 16), pChan->io_ports[IDE_HCYL_OFFSET]); > > /* > * Send verify command. > */ > outb(IDE_COMMAND_READ_VERIFY_EXT, pChan->io_ports[IDE_COMMAND_OFFSET]); > } > /* > * 28-bit addressing > */ > else > { > sectors = pChan->IdentifyData[Srb->TargetId & 0x01].UserAddressableSectors; > > printk("IdeVerify: starting sector %d, ending sector %d\n", > startingSector, endSector); > > if (endSector > sectors) > { > /* > * Too big, round down. > */ > printk("IdeVerify: truncating request to %d blocks\n", > sectors - startingSector - 1); > outb((u8)(sectors - startingSector - 1), > pChan->io_ports[IDE_NSECTOR_OFFSET]); > } > else > { > /* > * Set up sector count register. Round up to next block. > */ > if (sectorCount > 0xFF) > { > sectorCount = (u16)0xFF; > } > outb((u8)sectorCount, pChan->io_ports[IDE_NSECTOR_OFFSET]); > } > > /* > * Indicate expecting an interrupt. > */ > pChan->ExpectingInterrupt = TRUE; > > /* > * Set up LBA address > */ > 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]); > > /* > * Select driver, set LBA mode, set LBA (27:27) > */ > drvSelect = (u8) (startingSector >> 24); > drvSelect = drvSelect | (((u8) Srb->TargetId & 0x1) << 4) | 0xA0 | 0x40; > outb(drvSelect, pChan->io_ports[IDE_SELECT_OFFSET]); > > /* > * Send verify command. > */ > outb(IDE_COMMAND_READ_VERIFY, pChan->io_ports[IDE_COMMAND_OFFSET]); > } > > /* > * Wait for interrupt. > */ > return SRB_STATUS_PENDING; > >} /* end IdeVerify */ > >/************************************************************************ > * This function is used to copy memory with overlapped destination and > * source. I guess ScsiPortMoveMemory cannot handle this well. Can it? > ************************************************************************/ >void >IT8212MoveMemory(unsigned char * DestAddr, unsigned char * SrcAddr, u32 ByteCount) >{ > > long i; > > dprintk("IT8212MoveMemory: DestAddr=0x%p, SrcAddr=0x%p, ByteCount=0x%x\n", > DestAddr, SrcAddr, ByteCount); > > if (DestAddr > SrcAddr) > { > /* > * If Destination Area is in the back of the Source Area, copy from > * the end of the requested area. > */ > for (i = (ByteCount - 1); i >= 0; i--) > { > *(DestAddr + i) = *(SrcAddr + i); > } > } > else if (DestAddr < SrcAddr) > { > /* > * If Destination Area is in the front of the Source Area, copy from > * the begin of the requested area. > */ > for (i = 0; i < ByteCount; i++) > { > *(DestAddr + i) = *(SrcAddr + i); > } > } > >} /* end IT8212MoveMemory */ > >/************************************************************************ > * Convert SCSI packet command to Atapi packet command. > ************************************************************************/ >void >Scsi2Atapi(PChannel pChan, PSCSI_REQUEST_BLOCK Srb) >{ > > /* > * Change the cdb length. > */ > Srb->CdbLength = 12; > > /* > * Because the block descripter and the header translation, we must > * adjust the requested length. > */ > Srb->DataTransferLength -= 4; > > /* > * Record the original CDB for later restore. > */ > memcpy(pChan->TempCdb, Srb->Cdb, MAXIMUM_CDB_SIZE); > > /* > * Indicate that we have performed Scsi2Atapi function. And we must > * restore the CDB back once the command complete. > */ > pChan->ConvertCdb = TRUE; > > switch (Srb->Cdb[0]) > { > /* > * Convert the command from SCSIOP_MODE_SENSE (0x1A) to > * SCSIOP_MODE_SENSE10 (0x5A). > */ > case SCSIOP_MODE_SENSE: > { > PSCSI_MODE_SENSE10 modeSense10 = (PSCSI_MODE_SENSE10) Srb->Cdb; > PSCSI_MODE_SENSE6 modeSense6 = (PSCSI_MODE_SENSE6) pChan->TempCdb; > > /* > * 1. Zero out the whole CDB. > */ > memset((unsigned char *)modeSense10, 0, MAXIMUM_CDB_SIZE); > > /* > * 2. Fill in command code (SCSI_MODE_SENSE10). > */ > modeSense10->OperationCode = ATAPI_MODE_SENSE; > modeSense10->Dbd = modeSense6->Dbd; > modeSense10->PageCode = modeSense6->PageCode; > modeSense10->Pc = modeSense6->Pc; > modeSense10->SubpageCode = modeSense6->SubpageCode; > modeSense10->AllocationLengthLsb = modeSense6->AllocationLength; > modeSense10->Control = modeSense6->Control; > > /* > * 3. Becasuse we will fake a block descripter (-8), and > * translate the header (+4), so the requested length > * should be modified. That is, -8+4=-4 bytes. > */ > modeSense10->AllocationLengthLsb -= 4; > > break; > } > > /* > * Convert the command from SCSIOP_MODE_SELECT (0x15) to > * SCSIOP_MODE_SELECT10 (0x5A). > */ > case SCSIOP_MODE_SELECT: > { > u8 tempHeader[sizeof(PSCSI_MODE_PARAMETER_HEADER6)]; > u16 byteCount; > PSCSI_MODE_PARAMETER_HEADER10 header10 = > (PSCSI_MODE_PARAMETER_HEADER10)Srb->DataBuffer; > PSCSI_MODE_PARAMETER_HEADER6 header6 = > (PSCSI_MODE_PARAMETER_HEADER6)tempHeader; > PSCSI_MODE_SELECT10 modeSelect10 = (PSCSI_MODE_SELECT10)Srb->Cdb; > PSCSI_MODE_SELECT6 modeSelect6 = (PSCSI_MODE_SELECT6)pChan->TempCdb; > > /* > * First, convert the command block. > */ > > /* > * 1. Zero out the whole CDB. > */ > memset((unsigned char *)modeSelect10, 0, MAXIMUM_CDB_SIZE); > > /* > * 2. Fill in command code (SCSI_MODE_SENSE10). > */ > modeSelect10->OperationCode = ATAPI_MODE_SELECT; > modeSelect10->SPBit = modeSelect6->SPBit; > modeSelect10->PFBit = modeSelect6->PFBit; > modeSelect10->ParameterListLengthLsb = modeSelect6->ParameterListLength; > modeSelect10->Control = modeSelect6->Control; > > /* > * 3. Becasuse we will remove the block descripter (-8), and > * translate the header (+4), so the requested length should > * be modified. That is, -8+4=-4 bytes. > */ > modeSelect10->ParameterListLengthLsb -= 4; > > /* > * Second, convert the parameter page format from SCSI to ATAPI. > */ > > /* > * Remove the mode parameter data (except the header and the > * block descripter). > */ > byteCount = modeSelect6->ParameterListLength - > sizeof(SCSI_MODE_PARAMETER_HEADER6) - > sizeof(SCSI_MODE_PARAMTER_BLOCK_DESCRIPTER); > if (byteCount > 0) > { > IT8212MoveMemory( > (unsigned char *) header10 + sizeof(SCSI_MODE_PARAMETER_HEADER10), > (unsigned char *) header10 + sizeof(SCSI_MODE_PARAMETER_HEADER6) + > sizeof(SCSI_MODE_PARAMTER_BLOCK_DESCRIPTER), > byteCount); > } > > /* > * Keep the original header6 (4 bytes) in tempHeader for later use > */ > memcpy(tempHeader, header10, sizeof(SCSI_MODE_PARAMETER_HEADER6)); > > /* > * Change the "mode parameter header(6)" to "mode parameter header(10)" > * Notice: Remove the block descripter in SCSI-2 command out. It > * won't be used in MMC. > */ > memset((unsigned char *)header10, 0, sizeof(SCSI_MODE_PARAMETER_HEADER10)); > header10->ModeDataLengthLsb = header6->ModeDataLength; > header10->MediumType = header6->MediumType; > header10->DeviceSpecificParameter = header6->DeviceSpecificParameter; > header10->BlockDescriptorLengthLsb = header6->BlockDescriptorLength; > > /* > * ATAPI doesn't support block descripter, so remove it from the > * mode paramter. > */ > header10->BlockDescriptorLengthLsb = 0; > > break; > } > } > >} /* end Scsi2Atapi */ > >/************************************************************************ > * Send ATAPI packet command to device. > ************************************************************************/ >u32 >AtapiSendCommand(PChannel pChan, PSCSI_REQUEST_BLOCK Srb) >{ > > u8 statusByte; > u8 byteCountLow; > u8 byteCountHigh; > u8 useDMA; > u8 RevisionID = 0; > u8 bmClearStat; > u32 flags; > int i; > unsigned long bmAddress = pChan->dma_base; > PITE_ADAPTER pAdap = ite_adapters[0]; > > dprintk("AtapiSendCommand: command 0x%X to device %d\n", > Srb->Cdb[0], Srb->TargetId); > > /* > * Default use PIO mode. > */ > useDMA = 0; > pChan->ConvertCdb = FALSE; > > /* > * Make sure command is to ATAPI device. > */ > flags = pChan->DeviceFlags[Srb->TargetId & 1]; > if (flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) > { > if ((Srb->Lun) > (pChan->DiscsPresent[Srb->TargetId & 1] - 1)) > { > /* > * Indicate no device found at this address. > */ > return SRB_STATUS_SELECTION_TIMEOUT; > } > } > else if (Srb->Lun > 0) > { > return SRB_STATUS_SELECTION_TIMEOUT; > } > > if (!(flags & DFLAGS_ATAPI_DEVICE)) > { > return SRB_STATUS_SELECTION_TIMEOUT; > } > > /* > * Select device 0 or 1. > */ > outb((u8)(((Srb->TargetId & 0x1) << 4) | 0xA0), > pChan->io_ports[ATAPI_SELECT_OFFSET]); > > /* > * Try to enable interrupt again. (2003/02/25) > */ >#if (0) > outb(0x00, pChan->io_ports[ATAPI_CONTROL_OFFSET]); >#endif > > /* > * Verify that controller is ready for next command. > */ > GetStatus(pChan, statusByte); > > dprintk("AtapiSendCommand: entered with status %x\n", statusByte); > > if (statusByte & IDE_STATUS_BUSY) > { > printk("AtapiSendCommand: device busy (%x)\n", statusByte); > return SRB_STATUS_BUSY; > } > > if (statusByte & IDE_STATUS_ERROR) > { > if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) > { > printk("AtapiSendCommand: error on entry: (%x)\n", statusByte); > > /* > * Read the error reg. to clear it and fail this request. > */ > return MapError(pChan, Srb); > } > } > > /* > * If a tape drive doesn't have DSC set and the last command is > * restrictive, don't send the next command. See discussion of > * Restrictive Delayed Process commands in QIC-157. > */ > if ((!(statusByte & IDE_STATUS_DSC)) && (flags & DFLAGS_TAPE_DEVICE) && pChan->RDP) > { > mdelay(1); > printk("AtapiSendCommand: DSC not set. %x\n", statusByte); > return SRB_STATUS_BUSY; > } > > if (statusByte & IDE_STATUS_DRQ) > { > printk("AtapiSendCommand: enter with status (%x). Attempt to recover.\n", > statusByte); > > /* > * Try to drain the data that one preliminary device thinks that it has > * to transfer. Hopefully this random assertion of DRQ will not be present > * in production devices. > */ > for (i = 0; i < 0x10000; i++) > { > GetStatus(pChan, statusByte); > > if (statusByte & IDE_STATUS_DRQ) > { > /* > * Note: The data register is always referenced as a 16-bit word. > */ > inw(pChan->io_ports[ATAPI_DATA_OFFSET]); > } > else > { > break; > } > } > > if (i == 0x10000) > { > printk("AtapiSendCommand: DRQ still asserted.Status (%x)\n", statusByte); > printk("AtapiSendCommand: issued soft reset to Atapi device. \n"); > > AtapiSoftReset(pChan, Srb->TargetId); > > /* > * Re-initialize Atapi device. > */ > IssueIdentify(pChan, (Srb->TargetId & 1), IDE_COMMAND_ATAPI_IDENTIFY); > > /* > * Inform the port driver that the bus has been reset. > */ > > /* > * Clean up device extension fields that AtapiStartIo won't. > */ > pChan->ExpectingInterrupt = FALSE; > pChan->RDP = FALSE; > > return SRB_STATUS_BUS_RESET; > } > } > > if (flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) > { > /* > * As the cdrom driver sets the LUN field in the cdb, it must be removed. > */ > Srb->Cdb[1] &= ~0xE0; > > if ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) > { > /* > * Torisan changer. TUR's are overloaded to be platter switches. > */ > Srb->Cdb[7] = Srb->Lun; > } > } > > /* > * Convert SCSI to ATAPI commands if needed > */ > switch (Srb->Cdb[0]) > { > case SCSIOP_MODE_SENSE: > case SCSIOP_MODE_SELECT: > if (flags & DFLAGS_ATAPI_DEVICE) > { > Scsi2Atapi(pChan, Srb); > } > break; > } > > if (pChan->UseDma[Srb->TargetId & 1]) > { > switch (Srb->Cdb[0]) > { > case SCSIOP_READ: /* (0x28) */ > case 0xA8: /* READ(12) */ > case SCSIOP_READ_CD: > > if (Srb->DataTransferLength == 0) > { > break; > } > > /* > * First, switch to DMA or UDMA mode if running on Bypass mode. > */ > if (pAdap->bypass_mode) > { > IT8212SwitchDmaMode(pChan, Srb->TargetId); > } > > /* > * Check the SCATTER/GATHER count. The upper will give the > * different memory address depend on whether use_sg is used > * or not. > */ > if (Srb->UseSg == 0) > { > IdeBuildDmaTable(pChan, Srb); > } > else > { > IdeBuildDmaSgTable(pChan, Srb); > } > > bmClearStat = inb(bmAddress + 2); > if (Srb->TargetId & 0x01) > { > 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; > } > > useDMA = 1; > > outb(0, bmAddress); > > /* > * Setup PRD table physical address. > */ > outl(pChan->dmatable_dma, bmAddress + 4); > > /* > * Clear the status. > */ > outb(bmClearStat, bmAddress + 2); > > break; > } /* end switch (Srb->Cdb[0]) */ > } > > /* > * Set data buffer pointer and words left. > */ > pChan->DataBuffer = (unsigned short *)Srb->DataBuffer; > > if (useDMA) > { > pChan->WordsLeft = 0; > } > else > { > pChan->WordsLeft = Srb->DataTransferLength / 2; > } > > outb((u8)(((Srb->TargetId & 0x1) << 4) | 0xA0), > pChan->io_ports[ATAPI_SELECT_OFFSET]); > > WaitOnBusy(pChan, statusByte); > > /* > * Write transfer byte count to registers. > */ > byteCountLow = (u8)(Srb->DataTransferLength & 0xFF); > byteCountHigh = (u8)(Srb->DataTransferLength >> 8); > > if (Srb->DataTransferLength >= 0x10000) > { > byteCountLow = byteCountHigh = 0xFF; > } > > outb(byteCountLow, pChan->io_ports[ATAPI_LCYL_OFFSET]); > outb(byteCountHigh, pChan->io_ports[ATAPI_HCYL_OFFSET]); > outb(0, pChan->io_ports[ATAPI_INTREASON_OFFSET]); > outb(0, pChan->io_ports[ATAPI_UNUSED1_OFFSET]); > outb(useDMA, pChan->io_ports[ATAPI_FEATURE_OFFSET]); > > WaitOnBusy(pChan, statusByte); > > if (flags & DFLAGS_INT_DRQ) > { > /* > * This device interrupts when ready to receive the packet. > * > * Write ATAPI packet command. > */ > outb(IDE_COMMAND_ATAPI_PACKET, pChan->io_ports[IDE_COMMAND_OFFSET]); > > printk("AtapiSendCommand: wait for int. to send packet. status (%x)\n", > statusByte); > > pChan->ExpectingInterrupt = TRUE; > > return SRB_STATUS_PENDING; > } > else > { > /* > * Write ATAPI packet command. > */ > outb(IDE_COMMAND_ATAPI_PACKET, pChan->io_ports[IDE_COMMAND_OFFSET]); > > /* > * Wait for DRQ. > */ > WaitOnBusy(pChan, statusByte); > WaitForDrq(pChan, statusByte); > > if (!(statusByte & IDE_STATUS_DRQ)) > { > printk("AtapiSendCommand: DRQ never asserted (%x)\n", statusByte); > return SRB_STATUS_ERROR; > } > } > > /* > * Need to read status register. > */ > GetBaseStatus(pChan, statusByte); > > /* > * Send CDB to device. > * After detecting DRQ, the host writes the 12 bytes(6 words) of Command > * to the Data Register. > */ > WaitOnBusy(pChan, statusByte); > WriteBuffer(pChan, (unsigned short *)Srb->Cdb, 6); > > /* > * If running on DMA mode, start BUS MASTER operation. > */ > if (useDMA) > { > /* > * If SCSIOP_READ command is sent to an Audio CD, error will be > * returned. But the error will be blocked by our controller if bus > * master operation started. So wait for a short period to check if > * error occurs. If error occurs, don't start bus master operation. > */ > if (RevisionID == 0x10) > { > for (i = 0; i < 500; i++) > { > udelay(1); > statusByte = inb(bmAddress + 2); > if (statusByte & BM_STAT_FLG_INT) > { > /* > * If error occurs, give up this round. > */ > printk("AtapiSendCommand: command failed. Don't start bus master."); > printk("status=%x, i=%d\n", statusByte, i); > > pChan->ExpectingInterrupt = TRUE; > return SRB_STATUS_PENDING; > } > } > } > > if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) > { > outb(BM_CMD_FLG_START | BM_CMD_FLG_WRTTOMEM, bmAddress); > } > else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) > { > outb(BM_CMD_FLG_START | BM_CMD_FLG_WRTTODSK, bmAddress); > } > } /* end if (useDMA) */ > > /* > * Indicate expecting an interrupt and wait for it. > */ > pChan->ExpectingInterrupt = TRUE; > > return SRB_STATUS_PENDING; > >} /* end AtapiSendCommand */ > >/************************************************************************ > * Program ATA registers for IDE disk transfer. > ************************************************************************/ >static u32 >IdeSendCommand(PChannel pChan, PSCSI_REQUEST_BLOCK Srb) >{ > > u8 statusByte; > u32 status; > u32 i; > Scsi_Cmnd * pREQ; > unsigned char * request_buffer; > PINQUIRYDATA inquiryData; > > pREQ = Srb->pREQ; > status = SRB_STATUS_SUCCESS; > statusByte = 0; > > switch (Srb->Cdb[0]) > { > case SCSIOP_INQUIRY: > dprintk("SCSIOP_INQUIRY\n"); > > /* > * Filter out all TIDs but 0 and 1 since this is an IDE interface > * which support up to two devices. > */ > if ((pREQ->device->lun != 0) || > (!pChan->DeviceFlags[pREQ->device->id & 1] & DFLAGS_DEVICE_PRESENT)) > { > /* > * Indicate no device found at this address. > */ > status = SRB_STATUS_INVALID_TARGET_ID; > break; > } > else > { > request_buffer = Srb->DataBuffer; > inquiryData = Srb->DataBuffer; > > /* > * Zero INQUIRY data structure. > */ > memset(request_buffer, 0, Srb->DataTransferLength); > > /* > * Standard IDE interface only supports disks. > */ > inquiryData->DeviceType = DIRECT_ACCESS_DEVICE; > > /* > * Device type modifer. > */ > request_buffer[1] = 0; > > /* > * No ANSI/ISO compliance. > */ > request_buffer[2] = 0; > > /* > * Additional length. > */ > request_buffer[4] = 31; > memcpy(&request_buffer[8], "ITE ", 8); > memcpy(&request_buffer[16], "IT8212F ", 16); > memcpy(&request_buffer[32], "1.3", 3); > > /* > * Set the removable bit, if applicable. > */ > if (pChan->DeviceFlags[pREQ->device->id & 1] & DFLAGS_REMOVABLE_DRIVE) > { > inquiryData->RemovableMedia = 1; > } > > status = SRB_STATUS_SUCCESS; > } > > break; > > case SCSIOP_MODE_SENSE: > status = SRB_STATUS_INVALID_REQUEST; > break; > > case SCSIOP_TEST_UNIT_READY: > status = SRB_STATUS_SUCCESS; > break; > > case SCSIOP_READ_CAPACITY: > /* > * Claim 512 byte blocks (big-endian). > */ > ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000; > > /* > * Calculate last sector. > */ > if (pChan->IdentifyData[pREQ->device->id & 0x01].UserAddressableSectors == 0x0FFFFFFF) > { > i = pChan->IdentifyData[pREQ->device->id & 0x01].Capacity_48bit_LOW - 1; > } > else > { > i = pChan->IdentifyData[pREQ->device->id & 0x01].UserAddressableSectors - 1; > } > > ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress = > (((unsigned char *)&i)[0] << 24) | (((unsigned char *)&i)[1] << 16) | > (((unsigned char *)&i)[2] << 8) | ((unsigned char *)&i)[3]; > > status = SRB_STATUS_SUCCESS; > break; > > case SCSIOP_VERIFY: > status = IdeVerify(pChan, Srb); > break; > > case SCSIOP_READ: > case SCSIOP_WRITE: > status = IT8212ReadWrite(pChan, Srb); > break; > > case SCSIOP_START_STOP_UNIT: > /* > * Determine what type of operation we should perform > */ > status = SRB_STATUS_SUCCESS; > break; > > case SCSIOP_REQUEST_SENSE: > /* > * This function makes sense buffers to report the results > * of the original GET_MEDIA_STATUS command > */ > status = SRB_STATUS_INVALID_REQUEST; > break; > > default: > printk("IdeSendCommand: unsupported command %x\n", Srb->Cdb[0]); > status = SRB_STATUS_INVALID_REQUEST; > } /* end switch */ > > return status; > >} /* end IdeSendCommand */ > >/************************************************************************ > * This routine is called from the SCSI port driver synchronized with > * the kernel to start an IO request. If the current SRB is busy, return > * FALSE, else return TURE. > ************************************************************************/ >static void >AtapiStartIo(PChannel pChan, PSCSI_REQUEST_BLOCK Srb) >{ > > u32 status = 0; > > /* > * Determine which function. > */ > switch (Srb->Function) > { > case SRB_FUNCTION_EXECUTE_SCSI: > /* > * Sanity check. Only one request can be outstanding on a > * controller. > */ > if (pChan->CurrentSrb) > { > printk("AtapiStartIo: already have a request!\n"); > status = SRB_STATUS_BUSY; > Srb->SrbStatus = SRB_STATUS_BUSY; > goto busy; > } > > /* > * Indicate that a request is active on the controller. > */ > pChan->CurrentSrb = Srb; > Srb->SrbStatus = SRB_STATUS_PENDING; > > /* > * Send command to device. > */ > if (pChan->DeviceFlags[Srb->TargetId & 1] & DFLAGS_ATAPI_DEVICE) > { > /* > * If this is ATAPI device. > */ > status = AtapiSendCommand(pChan, Srb); > } > else if (pChan->DeviceFlags[Srb->TargetId & 1] & DFLAGS_DEVICE_PRESENT) > { > /* > * If this is IDE device. > */ > status = IdeSendCommand(pChan, Srb); > } > else > { > /* > * Nothing else. > */ > status = SRB_STATUS_SELECTION_TIMEOUT; > } > > break; > > case SRB_FUNCTION_IO_CONTROL: > /* > * IO control function. > */ > printk("AtapiStartIo: IO control\n"); > break; > > default: > /* > * Indicate unsupported command. > */ > status = SRB_STATUS_INVALID_REQUEST; > break; > > } /* end switch */ > > busy: > if (status != SRB_STATUS_PENDING) > { > /* > * Set status in SRB. > */ > Srb->SrbStatus = (u8)status; > dprintk("AtapiStartIo: status=%x\n", status); > TaskDone(pChan, Srb); > } > >} /* end AtapiStartIo */ > >/************************************************************************ > * Convert Scsi_Cmnd structure to SCSI_REQUEST_BLOCK. > ************************************************************************/ >static void >MapRequest(Scsi_Cmnd * pREQ, PSCSI_REQUEST_BLOCK Srb) >{ > > Srb->Length = sizeof(SCSI_REQUEST_BLOCK); > Srb->CdbLength = pREQ->cmd_len; > Srb->TargetId = pREQ->device->id; > Srb->Lun = pREQ->device->lun; > Srb->UseSg = pREQ->use_sg; > > /* > * Copy the actual command from Scsi_Cmnd to CDB. > */ > memcpy(Srb->Cdb, pREQ->cmnd, Srb->CdbLength); > > /* > * Always the SCSI_FUNCTION_EXECUTE_SCSI now. > */ > Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; > > Srb->SrbStatus = 0; > Srb->ScsiStatus = 0; > Srb->SenseInfoBufferLength = 16; > > /* > * The CDB's first byte is operation code. > */ > if ((Srb->Cdb[0] == SCSIOP_WRITE6) || (Srb->Cdb[0] == SCSIOP_WRITE) || > (Srb->Cdb[0] == SCSIOP_MODE_SELECT10)) > { > Srb->SrbFlags = SRB_FLAGS_DATA_OUT; > } > else > { > Srb->SrbFlags = SRB_FLAGS_DATA_IN; > } > > Srb->TimeOutValue = 0; > Srb->SenseInfoBuffer = pREQ->sense_buffer; > > if (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) > { > Srb->DataTransferLength = 0x40; > Srb->DataBuffer = pREQ->sense_buffer; > } > else > { > Srb->DataTransferLength = pREQ->request_bufflen; > Srb->DataBuffer = pREQ->request_buffer; > } > > if (pREQ->use_sg) > { > Srb->WorkingFlags |= SRB_WFLAGS_USE_SG; > } > > Srb->pREQ = pREQ; > >} /* end MapRequest */ > >/************************************************************************ > * A task execution has been done. For OS request, we need to Notify OS > * and invoke next take which wait at queue. > ************************************************************************/ >static void >TaskDone(PChannel pChan, PSCSI_REQUEST_BLOCK Srb) >{ > > Scsi_Cmnd * pREQ = Srb->pREQ; > > pChan->CurrentSrb = NULL; > pChan->RetryCount = 0; > > switch (SRB_STATUS(Srb->SrbStatus)) > { > case SRB_STATUS_SUCCESS: > pREQ->result = (DID_OK << 16); > break; > > case SRB_STATUS_SELECTION_TIMEOUT: > pREQ->result = (DID_NO_CONNECT << 16); > break; > > case SRB_STATUS_BUSY: > pREQ->result = (DID_BUS_BUSY << 16); > break; > > case SRB_STATUS_BUS_RESET: > pREQ->result = (DID_RESET << 16); > break; > > case SRB_STATUS_INVALID_TARGET_ID: > case SRB_STATUS_INVALID_PATH_ID: > case SRB_STATUS_INVALID_LUN: > case SRB_STATUS_NO_HBA: > pREQ->result = (DID_BAD_TARGET << 16); > break; > > case SRB_STATUS_NO_DEVICE: > pREQ->result = (DID_BAD_TARGET << 16); > break; > > case SRB_STATUS_ERROR: > pREQ->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | > (CHECK_CONDITION << 1); > break; > } > > dprintk("TaskDone(pChan=%p, pREQ=%p, result=%x)\n", > pChan, pREQ, pREQ->result); > > /* > * Notify OS that this OS request has been done. > */ > pREQ->scsi_done(pREQ); > > /* > * Check the queue again. > */ > TaskQueue(); > >} /* end TaskDone */ > >/************************************************************************ > * Start a command, doing convert first. > ************************************************************************/ >static void >TaskStart(PChannel pChan, Scsi_Cmnd *pREQ) >{ > > PSCSI_REQUEST_BLOCK Srb; > > dprintk("TaskStart(pChan=%p, pREQ=%p)\n", pChan, pREQ); > > Srb = &pChan->_Srb; > > /* > * Clear the SRB structure. > */ > memset(Srb, 0, sizeof(SCSI_REQUEST_BLOCK)); > > /* > * Convert Scsi_Cmnd structure to SCSI_REQUEST_BLOCK. > */ > MapRequest(pREQ, Srb); > > /* > * Start IDE I/O command. > */ > AtapiStartIo(pChan, Srb); > >} /* end TaskStart */ > >/************************************************************************ > * Check if queue is empty. If there are request in queue, transfer the > * request to HIM's request and execute the request. > ************************************************************************/ >static void >TaskQueue(void) >{ > > unsigned long flags; > Scsi_Cmnd * SCpnt; > PChannel pChan; > PITE_ADAPTER pAdap; > > check_next: > > if (it8212_req_last != NULL) > { > spin_lock_irqsave(&queue_request_lock, flags); > SCpnt = (Scsi_Cmnd *)it8212_req_last->SCp.ptr; > > if (it8212_req_last == SCpnt) > { > it8212_req_last = NULL; > } > else > { > it8212_req_last->SCp.ptr = (char *)SCpnt->SCp.ptr; > } > spin_unlock_irqrestore(&queue_request_lock, flags); > > /* > * Check the command. > */ > if (SCpnt->device->host) > { > if ((SCpnt->device->channel != 0) || > (SCpnt->device->id >= (4 * NumAdapters))) > { > /* > * Returns that we have a bad target. > */ > SCpnt->result = (DID_BAD_TARGET << 16); > SCpnt->scsi_done(SCpnt); > goto check_next; > } > } > > if (SCpnt->device->id >= 4) > { > pAdap = ite_adapters[1]; > if (SCpnt->device->id < 6) pChan = &pAdap->IDEChannel[0]; > else pChan = &pAdap->IDEChannel[1]; > } > else > { > pAdap = ite_adapters[0]; > if (SCpnt->device->id < 2) pChan = &pAdap->IDEChannel[0]; > else pChan = &pAdap->IDEChannel[1]; > } > > TaskStart(pChan, SCpnt); > return; > } > >} /* end TaskQueue */ > >/**************************************************************** > * Name: iteraid_queuecommand > * Description: Process a queued command from the SCSI manager. > * Parameters: SCpnt - Pointer to SCSI command structure. > * done - Pointer to done function to call. > * Returns: Status code. > ****************************************************************/ >int >iteraid_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) >{ > > unsigned long flags; > dprintk("##Queuecommand enter##\n"); > > /* > * Hooks the done routine. > */ > SCpnt->scsi_done = (void *)done; > > spin_lock_irqsave(&queue_request_lock, flags); > if (it8212_req_last == NULL) > { > SCpnt->SCp.ptr = (char *)SCpnt; > } > else > { > SCpnt->SCp.ptr = it8212_req_last->SCp.ptr; > it8212_req_last->SCp.ptr = (char *)SCpnt; > } > it8212_req_last = SCpnt; > spin_unlock_irqrestore(&queue_request_lock, flags); > > TaskQueue(); > > dprintk("@@Queuecommand exit@@\n"); > return 0; > >} /* end iteraid_queuecommand */ > >/**************************************************************** > * Name: internal_done :LOCAL > * Description: Done handler for non-queued commands > * Parameters: SCpnt - Pointer to SCSI command structure. > * Returns: Nothing. > ****************************************************************/ >static void >internal_done(Scsi_Cmnd * SCpnt) >{ > > SCpnt->SCp.Status++; > >} /* end internal_done */ > >/**************************************************************** > * Name: iteraid_command > * Description: Process a command from the SCSI manager. > * Parameters: SCpnt - Pointer to SCSI command structure. > * Returns: Status code. > ****************************************************************/ >int >iteraid_command(Scsi_Cmnd *SCpnt) >{ > > unsigned long timeout; > > SCpnt->SCp.Status = 0; > iteraid_queuecommand(SCpnt, internal_done); > > /* > * Should be longer than hard-reset time. > */ > timeout = jiffies + 60 * HZ; > while (!SCpnt->SCp.Status && time_before(jiffies, timeout)) > { > barrier(); > } > > if (!SCpnt->SCp.Status) SCpnt->result = (DID_ERROR << 16); > > return SCpnt->result; > >} /* end iteraid_command */ > >/************************************************************************ > * Enables/disables media status notification. > ************************************************************************/ >static void >IdeMediaStatus(u8 EnableMSN, PChannel pChan, u8 Device) >{ > > u8 statusByte; > u8 errorByte; > > statusByte = 0; > > if (EnableMSN == TRUE) > { > /* > * If supported enable Media Status Notification support. > */ > if ((pChan->DeviceFlags[Device] & DFLAGS_REMOVABLE_DRIVE)) > { > outb((u8) (0x95), pChan->io_ports[IDE_FEATURE_OFFSET]); > outb(IDE_COMMAND_ENABLE_MEDIA_STATUS, pChan->io_ports[IDE_COMMAND_OFFSET]); > > WaitOnBaseBusy(pChan, statusByte); > > if (statusByte & IDE_STATUS_ERROR) > { > /* > * Read the error register. > */ > errorByte = inb(pChan->io_ports[IDE_ERROR_OFFSET]); > > printk("IdeMediaStatus: error enabling media status. status %u, error byte %u\n", > statusByte, errorByte); > } > else > { > pChan->DeviceFlags[Device] |= DFLAGS_MEDIA_STATUS_ENABLED; > printk("IdeMediaStatus: media status notification supported!\n"); > pChan->ReturningMediaStatus = 0; > } > } > } > else /* end if EnableMSN == TRUE */ > { > /* > * Disable if previously enabled. > */ > if ((pChan->DeviceFlags[Device] & DFLAGS_MEDIA_STATUS_ENABLED)) > { > outb((u8)(0x31), pChan->io_ports[IDE_FEATURE_OFFSET]); > outb(IDE_COMMAND_ENABLE_MEDIA_STATUS, > pChan->io_ports[IDE_COMMAND_OFFSET]); > > WaitOnBaseBusy(pChan, statusByte); > pChan->DeviceFlags[Device] &= ~DFLAGS_MEDIA_STATUS_ENABLED; > } > } > >} /* end IdeMediaStatus */ > >/************************************************************************ > * Issue IDENTIFY command to a device. > * Either the standard (EC) or the ATAPI packet (A1) IDENTIFY. > ************************************************************************/ >static u8 >IssueIdentify(PChannel pChan, u8 DeviceNumber, u8 Command) >{ > > u8 statusByte = 0; > u32 i; > u32 j; > > /* > * Check that the status register makes sense. > */ > GetBaseStatus(pChan, statusByte); > > if (Command == IDE_COMMAND_IDENTIFY) > { > /* > * Mask status byte ERROR bits. > */ > statusByte &= ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX); > > dprintk("IssueIdentify: checking for IDE. status (%x)\n", statusByte); > > /* > * Check if register value is reasonable. > */ > if (statusByte != IDE_STATUS_IDLE) > { > /* > * Reset the channel. > */ > printk("IssueIdentify: resetting channel.\n"); > IdeHardReset(pChan, statusByte); > > outb((u8)((DeviceNumber << 4) | 0xA0), pChan->io_ports[IDE_SELECT_OFFSET]); > GetBaseStatus(pChan, statusByte); > statusByte &= ~IDE_STATUS_INDEX; > > if (statusByte != IDE_STATUS_IDLE) > { > /* > * Give up on this. > */ > printk("IssueIdentify(IDE): disk[%d] not ready. status=0x%x\n", > DeviceNumber, statusByte); > return FALSE; > } > } > } > else > { > dprintk("IssueIdentify: checking for ATAPI. status (%x)\n", statusByte); > if ((statusByte & IDE_STATUS_BUSY) || (statusByte & IDE_STATUS_DRQ)) > { > /* > * Reset the device. > */ > dprintk("IssueIdentify: resetting device.\n"); > AtapiSoftReset(pChan, DeviceNumber); > > outb((u8)((DeviceNumber << 4) | 0xA0), > pChan->io_ports[IDE_SELECT_OFFSET]); > GetBaseStatus(pChan, statusByte); > if (statusByte != 0) > { > /* > * Give up on this. > */ > printk("IssueIdentify(ATAPI): disk[%d] not ready. status=0x%x\n", > DeviceNumber, statusByte); > return FALSE; > } > } > } > > for (j = 0; j < 2; j++) > { > /* > * Wait for device ready (Not Busy and Not DRQ). > */ > outb((u8)((DeviceNumber << 4) | 0xA0), > pChan->io_ports[IDE_SELECT_OFFSET]); > WaitForDeviceReady(pChan, statusByte); > if ((statusByte & IDE_STATUS_BUSY) || (statusByte & IDE_STATUS_DRQ)) > { > printk("IssueIdentify: disk[%d] not ready. status=0x%x\n", > DeviceNumber, statusByte); > continue; > } > > /* > * Send IDENTIFY command. > */ > outb(Command, pChan->io_ports[IDE_COMMAND_OFFSET]); > > /* > * Wait for DRQ. > */ > WaitForBaseDrq(pChan, statusByte); > if (!(statusByte & IDE_STATUS_DRQ)) > { > printk("IssueIdentify: disk[%d] DRQ never asserted. status=%x\n", > DeviceNumber, statusByte); > > /* > * Give one more chance. > */ > if (Command == IDE_COMMAND_IDENTIFY) > { > IdeHardReset(pChan, statusByte); > } > else > { > AtapiSoftReset(pChan, DeviceNumber); > } > } > else > { > break; > } > } > > /* > * Check for error on really stupid master devices that assert random > * patterns of bits in the status register at the slave address. > */ > outb((u8)((DeviceNumber << 4) | 0xA0), pChan->io_ports[IDE_SELECT_OFFSET]); > GetBaseStatus(pChan, statusByte); > if (statusByte & IDE_STATUS_ERROR) > { > printk("IssueIdentify: disk[%d] returns error status\n", DeviceNumber); > return FALSE; > } > > dprintk("IssueIdentify: status before read words %x\n", statusByte); > > /* > * Suck out 256 words. After waiting for one model that asserts busy > * after receiving the Packet Identify command. > */ > WaitOnBusy(pChan, statusByte); > > if (!(statusByte & IDE_STATUS_DRQ)) { return FALSE; } > > ReadBuffer(pChan, (unsigned short *)&pChan->FullIdentifyData, 256); > > /* > * Check out a few capabilities / limitations of the device. > * 01/29/2003 > */ > if (pChan->FullIdentifyData.SpecialFunctionsEnabled & 1) > { > /* > * Determine if this drive supports the MSN functions. > */ > printk("Marking drive %x as removable. SFE = %x\n", > DeviceNumber, pChan->FullIdentifyData.SpecialFunctionsEnabled); > pChan->DeviceFlags[DeviceNumber] |= DFLAGS_REMOVABLE_DRIVE; > } > > memcpy(&pChan->IdentifyData[DeviceNumber], &pChan->FullIdentifyData, > sizeof(IDENTIFY_DATA2)); > > if (pChan->IdentifyData[DeviceNumber].GeneralConfiguration & 0x20 && > Command != IDE_COMMAND_IDENTIFY) > { > /* > * This device interrupts with the assertion of DRQ after receiving > * Atapi Packet Command. > */ > pChan->DeviceFlags[DeviceNumber] |= DFLAGS_INT_DRQ; > > dprintk(KERN_NOTICE "Device interrupts on assertion of DRQ.\n"); > } > else > { > dprintk(KERN_NOTICE "Device does't interrupt on assertion of DRQ.\n"); > } > > if (((pChan->IdentifyData[DeviceNumber].GeneralConfiguration & 0xF00) > == 0x100) && Command != IDE_COMMAND_IDENTIFY) > { > /* > * This is a tape. > */ > pChan->DeviceFlags[DeviceNumber] |= DFLAGS_TAPE_DEVICE; > printk(KERN_NOTICE "IssueIdentify: device is a tape drive.\n"); > } > else > { > dprintk(KERN_NOTICE "IssueIdentify: device is not a tape drive.\n"); > } > > /* > * Work around for some IDE and one model Atapi that will present more > * then 256 bytes for the Identify data. > */ > WaitOnBaseBusy(pChan, statusByte); > > for (i = 0; i < 0x10000; i++) > { > GetStatus(pChan, statusByte); > > if (statusByte & IDE_STATUS_DRQ) > { > /* > * Suck out any remaining bytes and throw away. > */ > inw(pChan->io_ports[IDE_DATA_OFFSET]); > } > else > { > break; > } > } > > return TRUE; > >} /* end IssueIdentify() */ > >/************************************************************************ > * Check this is the IDE or ATAPI disk then identify it. > ************************************************************************/ >static u8 >iteraid_find_device(PChannel pChan, u8 channel) >{ > > u8 deviceNumber; > u8 signatureLow; > u8 signatureHigh; > u8 deviceResponded = FALSE; > u8 statusByte = 0; > > /* > * Clear expecting interrupt flag and current SRB field. > */ > pChan->ExpectingInterrupt = FALSE; > pChan->CurrentSrb = NULL; > > /* > * Search for devices in each channel. > */ > for (deviceNumber = 0; deviceNumber < 2; deviceNumber++) > { > /* > * Select the device. > */ > outb((u8)((deviceNumber << 4) | 0xA0), pChan->io_ports[IDE_SELECT_OFFSET]); > > /* > * Disable interrupts during initialization. > */ > outb(IDE_DC_DISABLE_INTERRUPTS, pChan->io_ports[IDE_CONTROL_OFFSET]); > > /* > * Check here for some SCSI adapters that incorporate IDE emulation. > */ > statusByte = inb(pChan->io_ports[IDE_CONTROL_OFFSET]); > > /* > * Do soft reset on selected device. (AtapiSoftReset) > */ > AtapiSoftReset(pChan, deviceNumber); > WaitOnBusy(pChan, statusByte); > > signatureLow = inb(pChan->io_ports[IDE_MIDCYL_OFFSET]); > signatureHigh = inb(pChan->io_ports[IDE_HCYL_OFFSET]); > > if (signatureLow == 0x14 && signatureHigh == 0xEB) > { > /* > * ATAPI signature found. Issue ATAPI packet identify command. > */ > if (IssueIdentify(pChan, deviceNumber, IDE_COMMAND_ATAPI_IDENTIFY)) > { > /* > * Indicate ATAPI device. > */ > printk("iteraid_find_device: channel %x device %x is ATAPI.\n", > channel, deviceNumber); > > pChan->DeviceFlags[deviceNumber] |= DFLAGS_ATAPI_DEVICE; > pChan->DeviceFlags[deviceNumber] |= DFLAGS_DEVICE_PRESENT; > pChan->DeviceFlags[deviceNumber] &= ~DFLAGS_CONFIG_CHANGED; > > deviceResponded = TRUE; > > GetStatus(pChan, statusByte); > if (statusByte & IDE_STATUS_ERROR) > { > AtapiSoftReset(pChan, deviceNumber); > } > } > else > { > /* > * Indicate no working device. > */ > printk("iteraid_find_device: channel %x device %x doesn't respond.\n", > channel, deviceNumber); > pChan->DeviceFlags[deviceNumber] &= ~DFLAGS_DEVICE_PRESENT; > } > } > else > { > /* > * Select the device. > */ > outb((u8)((deviceNumber << 4) | 0xA0), pChan->io_ports[IDE_SELECT_OFFSET]); > > /* > * Check here for some SCSI adapters that incorporate IDE emulation. > */ > GetStatus(pChan, statusByte); > > /* > * No Disk. > */ > if (statusByte == 0xFF || statusByte == 0x7F || statusByte == 0x0) > { > dprintk("FindDevices: cannot find IDE device. status = %x\n", statusByte); > continue; > } > > /* > * Issue IDE Identify. If an ATAPI device is actually present, > * the signature will be asserted, and the drive will be > * recognized as such. > */ > if (IssueIdentify(pChan, deviceNumber, IDE_COMMAND_IDENTIFY)) > { > /* > * IDE drive found. > */ > printk(KERN_WARNING "FindDevices: device %u is IDE\n", > (channel * 2) + deviceNumber); > pChan->DeviceFlags[deviceNumber] |= DFLAGS_DEVICE_PRESENT; > pChan->DeviceFlags[deviceNumber] &= ~DFLAGS_ATAPI_DEVICE; > pChan->DeviceFlags[deviceNumber] &= ~DFLAGS_CONFIG_CHANGED; > deviceResponded = TRUE; > } > else > { > printk(KERN_WARNING "FindDevices: device %u is not present\n", > (channel * 2) + deviceNumber); > pChan->DeviceFlags[deviceNumber] &= ~DFLAGS_DEVICE_PRESENT; > } > } > } > > return deviceResponded; > >} /* end iteraid_find_device */ > >/************************************************************************ > * IDE disk hardware initialize. > ************************************************************************/ >u8 >AtapiHwInitialize(PITE_ADAPTER pAdap, PChannel pChan, u8 channel) >{ > > u8 i; > u8 statusByte = 0; > > /* > * For two devices in this channel. > */ > for (i = 0; i < 2; i++) > { > /* > * only check in Fireware mode. > */ > if (pAdap->bypass_mode == FALSE) > { > outb((u8) (0xA0 | ((u8) i << 4)), pChan->io_ports[IDE_SELECT_OFFSET]); > > /* > * Check if card at this address. > */ > outb(0xAA, pChan->io_ports[IDE_MIDCYL_OFFSET]); > > /* > * Check if indentifier can be read back. > */ > if ((statusByte = inb(pChan->io_ports[IDE_MIDCYL_OFFSET])) != 0xAA) > { > printk("AtapiHwInitialize: identifier read back from (%x, %x) = %x\n", > channel, i, statusByte); > > /* > * ***** Dont free it....For later use ***** > * ScsiPortFreeDeviceBase(HwDeviceExtension, ioSpace1); > */ > continue; > } > > printk("AtapiHwInitialize: found ATA device (%x, %x)n", channel, i); > } > > } > > return TRUE; > >} /* end AtapiHwInitialize */ > >/************************************************************************ > * Initialize a adapter, return 0 means success. > ************************************************************************/ >static int >iteraid_init(PITE_ADAPTER pAdap, struct pci_dev *pPciDev) >{ > > u8 z; > u8 i; > u8 j; > u8 set_irq; > unsigned long control_addr; /* Control reg base address */ > unsigned long base_addr; /* IDE I/O port base address */ > unsigned long bm_base_addr; /* Bus Master base address */ > PChannel pChan; /* Use for each channel */ > > dprintk("iteraid_init enter\n"); > > /* > * Common settings. > */ > pAdap->pci_bus = pPciDev->bus->number; > pAdap->devfn = pPciDev->devfn; > pAdap->irq = pPciDev->irq; > pAdap->irqOwned = 0; > > printk(KERN_NOTICE "Found Controller: %s\n", pAdap->name); > > /* > * Allocate buffer for IDE channles (One IT8212 supports two channels) > */ > pAdap->IDEChannel = > (PChannel)kmalloc(sizeof(Channel) * pAdap->num_channels, GFP_ATOMIC); > > if (pAdap->IDEChannel == 0) > { > printk("iteraid_init: pChan allocate failed.\n"); > return -1; > } > > memset(pAdap->IDEChannel, 0, sizeof(Channel) * pAdap->num_channels); > > set_irq = 1; > for (i = 0; i < NumAdapters; i++) > { > if (ite_adapters[i]->irqOwned == pAdap->irq) set_irq = 0; > } > > /* > * Request the irq (share irq) and hook the interrupt service routine. > */ > if (set_irq) > { > if (request_irq(pAdap->irq, Irq_Handler, SA_SHIRQ, PROC_DIR_NAME, pAdap) < 0) > { > printk("iteraid_init: unable to allocate IRQ for %s\n", pAdap->name); > return -1; > } > pAdap->irqOwned = pAdap->irq; > } > > /* > * Get the IDE port and DMA registers. > */ > for (i = 0; i < pAdap->num_channels; i++) > { > pChan = &pAdap->IDEChannel[i]; > /* > * Reference the book "LINUX DEVICE DRIVER 2nd", Page 484 > * unsigned long pci_resource_start(struct pci_dev *dev, int bar); > */ > base_addr = pci_resource_start(pPciDev, i * 2); > control_addr = pci_resource_start(pPciDev, i * 2 + 1); > bm_base_addr = pci_resource_start(pPciDev, 4); > pChan->dma_base = bm_base_addr + i * 8; > for (j = 0; j <= IDE_STATUS_OFFSET; j++) > { > pChan->io_ports[j] = base_addr; > base_addr += 1; > } > pChan->io_ports[IDE_CONTROL_OFFSET] = control_addr + 2; > } > > /* > * Initialize channels. > */ > for (z = 0; z < pAdap->num_channels; z++) > { > pChan = &pAdap->IDEChannel[z]; > pChan->pPciDev = pPciDev; > pChan->channel = z; > > /* > * This section should be masked off if BIOS is ready. > */ ># if (MARK_DEBUG_BYPASS_MODE) > /* > * BIOS is not ready, so I change to ByPass Mode by myself. > */ > pAdap->bypass_mode = TRUE; > > /* > * Change to bypass mode. > */ > IT8212InitBypassMode(pPciDev); ># endif > > /* > * Hardware initialize. > */ ># if (0) > AtapiHwInitialize(pAdap, pChan, z); ># endif > > /* > * Find and identify the IDE or ATAPI device. > */ > iteraid_find_device(pChan, z); > > /* > * Set the best transfer mode. > */ ># if (MARK_SET_BEST_TRANSFER) > IT8212SetBestTransferMode(pAdap, pChan, z); ># endif > > /* > * Set Scatter/Gather List buffer for the channel. > */ > IdeSetupDma(pChan, pChan->dma_base, 8); > } > > dprintk("iteraid_init exit\n"); > return 0; > >} /* end iteraid_init */ > >/************************************************************************ > * This function will find and initialize any cards. > ************************************************************************/ >int >iteraid_detect(Scsi_Host_Template *tpnt) >{ > > u8 i; > u8 j; > u8 mode; > u8 pci_id; > PChannel pChan; > PITE_ADAPTER pAdap; > struct pci_dev * pPciDev; > dprintk("iteraid_detect enter\n"); > > /* > * Search ITE IT8212 chip. > */ > pPciDev = NULL; > pci_id = 0; > while ((pPciDev = pci_find_device(ITE_VENDOR_ID, ITE_DEVICE_ID, pPciDev))) > { > if (PCI_FUNC(pPciDev->devfn)) continue; > > /* > * Allocate memory for Adapter. > */ > pAdap = (PITE_ADAPTER)kmalloc(sizeof(ITE_ADAPTER), GFP_ATOMIC); > if (pAdap == NULL) > { > printk("iteraid_detect: pAdap allocate failed.\n"); > continue; > } > > memset(pAdap, 0, sizeof(ITE_ADAPTER)); > pAdap->name = CONTROLLER_NAME_IT8212; > pAdap->num_channels = 2; > pAdap->pci_dev = pPciDev; > > /* > * Check if we are in bypass(transparent) or firmware mode. > */ > pci_read_config_byte(pPciDev, 0x50, &mode); > if (mode & 1) > { > dprintk("Firmware mode in PCI#%d\n", pci_id); > pAdap->bypass_mode = FALSE; > } > else > { > dprintk("Transparent mode in PCI#%d\n", pci_id); > pAdap->bypass_mode = TRUE; > } > > if (iteraid_init(pAdap, pPciDev) == 0) > { > ite_adapters[NumAdapters++] = pAdap; > } > pci_id++; > } > > /* > * Reenable interrupt after initialization. 2003/04/28 > */ > for (i = 0; i < NumAdapters; i++) > { > pAdap = ite_adapters[i]; > for (j = 0; j < pAdap->num_channels; j++) > { > pChan = &pAdap->IDEChannel[j]; > outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]); > } > } > > if (NumAdapters) > { > /* > * Register a virtual host. > */ > ite_vhost = scsi_register(tpnt, 0); > > ite_vhost->io_port = 0; > ite_vhost->n_io_port = 0; > ite_vhost->max_channel = 0; > ite_vhost->max_id = MAX_DEVICES; > ite_vhost->max_lun = 1; > ># if (0) ># if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) > scsi_set_device(ite_vhost, &pPciDev->dev); ># elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) > scsi_set_pci_device(ite_vhost, pPciDev); ># endif ># endif > > /* > * Register the driver as a character device, for applications to > * acess it for ioctls. Ideally, this should go in the init_module() > * routine, but since it is hidden in the file "scsi_module.c" ( > * included in the end), we define it here. First argument (major) > * to register_chrdev implies a dynamic major number allocation. > */ > ite_major = register_chrdev(0, "itedev", &itedev_fops); > > /* > * Register the Shutdown Notification hook in the kernel. > */ > register_reboot_notifier(&ite_notifier); > > /* > * Initialize ioctl semphore. > */ > init_MUTEX(&mimd_entry_mtx); > } > > dprintk("iteraid_detect exit\n"); > return 1; > >} /* end iteraid_detect() */ > >/************************************************************************ > * Name: iteraid_release > * Description: Release resources allocated for a single each adapter. > * Parameters: pshost - Pointer to SCSI command structure. > * Returns: zero. > ************************************************************************/ >int >iteraid_release(struct Scsi_Host *pshost) >{ > > u8 i; > PITE_ADAPTER pAdap; > > /* > * Unregister the character device. > */ > if (ite_major > 0) > { > unregister_chrdev(ite_major, "itedev"); > ite_major = -1; > } > > /* > * Free irq and memory. > */ > for (i = 0; i < NumAdapters; i++) > { > pAdap = ite_adapters[i]; > > if (pAdap->irqOwned) free_irq(pAdap->irq, pAdap); > if (pAdap->IDEChannel != NULL) { kfree(pAdap->IDEChannel); } > if (pAdap != NULL) { kfree(pAdap); } > } > > /* > * Unregister the reboot notifier. > */ > unregister_reboot_notifier(&ite_notifier); > > /* > * Tell kernel scsi-layer we are gone. > */ > scsi_unregister(pshost); > > return 0; > >} /* end iteraid_Release */ > >/************************************************************************ > * This is the new scsi eh reset function. > ************************************************************************/ >int >iteraid_reset_eh(Scsi_Cmnd *SCpnt) >{ > > u8 i; > u8 j; > PChannel pChan; > PITE_ADAPTER pAdap; > > if (SCpnt == NULL) > { > printk("iteraid_reset_eh: invalid Scsi_Cmnd\n"); > return FAILED; > } > > for (i = 0; i < NumAdapters; i++) > { > pAdap = ite_adapters[i]; > for (j = 0; j < pAdap->num_channels; j++) > { > pChan = &pAdap->IDEChannel[j]; > AtapiResetController(pAdap, pChan); > } > } > > return SUCCESS; > >} /* end iteraid_reset_eh */ > >/************************************************************************ > * The new error handling code. > ************************************************************************/ >int >iteraid_abort_eh(Scsi_Cmnd *SCpnt) >{ > > if (SCpnt == NULL) > { > printk("iteraid_reset_eh: invalid Scsi_Cmnd\n"); > return FAILED; > } > > return SUCCESS; > >} /* end iteraid_abort_eh */ > >/************************************************************************ > * Name: iteraid_biosparam > * Description: Process the biosparam request from the SCSI manager to > * return C/H/S data. > * Parameters: disk - Pointer to SCSI disk structure. > * dev - Major/minor number from kernel. > * geom - Pointer to integer array to place geometry data. > * Returns: zero. > ************************************************************************/ >int >iteraid_biosparam >( > struct scsi_device * sdev, > struct block_device * bdev, > sector_t capacity, > int geom[] >) >{ > > int heads; > int sectors; > int cylinders; > > /* > * Default heads (64) & sectors (32) > * Handle extended translation size for logical drives > 1Gb > */ > if (capacity >= 0x200000) > { > heads = 255; > sectors = 63; > } > else > { > heads = 64; > sectors = 32; > } > > cylinders = (unsigned long)capacity / (heads * sectors); > > /* > * Return result > */ > geom[0] = heads; > geom[1] = sectors; > geom[2] = cylinders; > > return 0; > >} /* end iteraid_biosparam */ > >/************************************************************************ > * Shutdown routine. > ************************************************************************/ >static int >ite_halt(struct notifier_block *nb, ulong event, void *buf) >{ > > if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) > { > return NOTIFY_DONE; > } > > unregister_reboot_notifier(&ite_notifier); > > return NOTIFY_OK; > >} /* end ite_halt */ > >/************************************************************************ > * PROC information. > ************************************************************************/ >int >iteraid_proc_info >( > struct Scsi_Host * shost, > char * buffer, > char ** start, > off_t offset, > int length, > int inout >) >{ > > return 0; > >} /* end iteraid_proc_info */ > >/************************************************************************ > * IOCTL open entry. > ************************************************************************/ >static int >itedev_open(struct inode *inode, struct file *filep) >{ > > MOD_INC_USE_COUNT; > > return 0; > >} /* end itedev_open */ > >/************************************************************************ > * IOCTL code entry. > ************************************************************************/ >static int >itedev_ioctl_entry >( > struct inode * inode, > struct file * filep, > unsigned int cmd, > unsigned long arg >) >{ > > int ret = -1; > > /* > * We do not allow parallel ioctls to the driver as of now. > */ > down(&mimd_entry_mtx); > ret = itedev_ioctl(inode, filep, cmd, arg); > up(&mimd_entry_mtx); > > return ret; > >} /* end itedev_ioctl_entry */ > >/************************************************************************ > * Real IOCTL function handles ioctl for the character device. > ************************************************************************/ >static int >itedev_ioctl >( > struct inode * inode, > struct file * filep, > unsigned int cmd, > unsigned long arg >) >{ > > u8 diskArrayId; > u8 statusByte = 0; > u8 srbStatus; > u8 progress = 0; > u8 status = 0; > uioctl_t * pioc; > PITE_ADAPTER pAdap; > PChannel pChan; > PRAID_REBUILD_INFO rebuild_info; > dprintk("itedev_ioctl enter\n"); > > /* > * Extract the type and number bitfield. > */ > if (_IOC_TYPE(cmd) != ITE_IOCMAGIC) return -EINVAL; > > /* > * Allocate space for ioctl data structure. > */ > if ((pioc = kmalloc(sizeof(uioctl_t), GFP_KERNEL)) == NULL) > { > printk("itedev_ioctl: error kmalloc on ioctl\n"); > return -ENOMEM; > } > > /* > * Get the user ioctl structure. > */ > if (copy_from_user(pioc, (uioctl_t *)arg, sizeof(uioctl_t))) > { > kfree(pioc); > return -EFAULT; > } > > /* > * Check which command to do. > */ > switch (cmd) > { > case ITE_IOC_GET_PHY_DISK_STATUS: > dprintk("ITE_IOC_GET_PHY_DISK_STATUS\n"); > > /* > * Get the physical disk status. > */ > status = IT8212GetChipStatus(pioc); > return 0; > > case ITE_IOC_CREATE_DISK_ARRAY: > dprintk("ITE_IOC_CREATE_DISK_ARRAY\n"); > > /* > * Create disk array. > */ > status = IT8212CreateDiskArray(pioc); > > if (status != SRB_STATUS_SUCCESS) return status; > > status = IT8212ErasePartition(pioc); > return 0; > > case ITE_IOC_REBUILD_START: > dprintk("ITE_IOC_REBUILD_START\n"); > > /* > * Rebuild array. > */ > status = IT8212Rebuild(pioc); > put_user(status, (u8 *)pioc->data); > return 0; > > case ITE_IOC_GET_REBUILD_STATUS: > dprintk("ITE_IOC_GET_REBUILD_STATUS\n"); > > pAdap = ite_adapters[0]; > > /* > * Get the rebuild disk ID. > */ > rebuild_info = (PRAID_REBUILD_INFO) pioc->data; > diskArrayId = rebuild_info->DiskArrayId; > > /* > * Select channel. > */ > if (diskArrayId < 2) > { > pChan = &pAdap->IDEChannel[0]; > } > else > { > pChan = &pAdap->IDEChannel[1]; > } > > /* > * Select device. > */ > outb(((u8) (diskArrayId << 4) | 0xA0), > 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("IT8212GetRebuildStatus: Disk[%d] busy. Status=0x%X\n", > diskArrayId, 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 command. > */ > outb(IDE_COMMAND_REBUILD_STATUS, pChan->io_ports[IDE_COMMAND_OFFSET]); > > /* > * Check error. > */ > WaitForCommandComplete(pChan, statusByte); > > /* > * Reenable interrupt after command complete. > */ > outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]); > > if (statusByte != IDE_STATUS_IDLE) > { > srbStatus = SRB_STATUS_ERROR; > printk("GetRebuildStatus: ERROR\n"); > goto exit; > } > > progress = inb(pChan->io_ports[IDE_NSECTOR_OFFSET]); > srbStatus = SRB_STATUS_SUCCESS; > > if (progress != 0xFF) progress = 0x64 - progress; > > /* > * Put the rebuild status to user space. > */ > put_user(progress, (u8 *)pioc->data); > >exit: > return 0; > > case ITE_IOC_RESET_ADAPTER: > dprintk("ITE_IOC_RESET_ADAPTER\n"); > > /* > * Reset the adapter. > */ ># if (0) > status = IT8212ResetAdapter(); ># endif > > /* > * Return TURE or FALSE to user space. > */ > put_user(status, (u8 *)arg); > return 0; > > case ITE_IOC_GET_DRIVER_VERSION: > dprintk("ITE_IOC_GET_DRIVER_VERSION\n"); > > /* > * Get the current driver version. > */ > put_user(driver_ver, (int *)arg); > return 0; > > default: > return -EINVAL; > > } /* end switch */ > >} /* end itedev_ioctl */ > >/************************************************************************ > * IOCTL close routine. > ************************************************************************/ >static int >itedev_close(struct inode *inode, struct file *filep) >{ > > MOD_DEC_USE_COUNT; > > return 0; > >} /* end itedev_close */ > >/************************************************************************ > * Scsi_Host_Template Initializer > ************************************************************************/ >static Scsi_Host_Template driver_template = >{ > .proc_name = "IT8212", > .proc_info = iteraid_proc_info, > .name = "ITE RAIDExpress133", > .detect = iteraid_detect, > .release = iteraid_release, > .queuecommand = iteraid_queuecommand, > .eh_abort_handler = iteraid_abort_eh, > .eh_host_reset_handler = iteraid_reset_eh, > .bios_param = iteraid_biosparam, > .can_queue = 1, > .this_id = -1, > .sg_tablesize = 32, > .max_sectors = 256, > .cmd_per_lun = 1, > .use_clustering = DISABLE_CLUSTERING, > .emulated = 1 >}; >#include "scsi_module.c" > > > > > > >ITERAID.H > > > >/* > * linux/drivers/scsi/iteraid.h > * > * (C) Copyright 2002-2004 ITE Tech, inc. > * > * Nov 11, 2002 Mark Lu file created. > * > * 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. > * > * ITE IT8212 RAID Controller device driver header for Linux. > */ > >#ifndef _ITERAID_H_ >#define _ITERAID_H_ > >#include <linux/version.h> >#include <linux/types.h> > >#define ITE_VENDOR_ID 0x1283 /* Vendor ID (ITE) */ >#define ITE_DEVICE_ID 0x8212 /* Device IF (IT8212) */ >#define MAX_ADAPTERS 2 /* Max Board supported */ >#define MAX_DEVICES (MAX_ADAPTERS * 4) /* Max Dev supported */ > >#define TRUE 1 >#define FALSE 0 > >/* > * Undef macros which may conflict > */ >#undef START_STOP > >/************************************************************************ > * Debugging macro > ************************************************************************/ >#ifdef ITE_DEBUG >#define dprintk(msg...) printk(msg) >#else >#define dprintk(msg...) do { } while(0) >#endif > >/************************************************************************ > * Raid level definitions > ************************************************************************/ >#define RAID_LEVEL_0 0 >#define RAID_LEVEL_1 1 >#define RAID_LEVEL_10 2 >#define RAID_LEVEL_JBOD 3 >#define RAID_LEVEL_NORMAL 4 >#define RAID_LEVEL_NODISK 5 > >/************************************************************************ > * Physical disk status definitions > ************************************************************************/ >#define DISK_KEY_OFF 0 >#define DISK_OFF_LINE 1 >#define DISK_ON_LINE 2 >#define DISK_REBUILDING 3 >#define DISK_PLUGGING 4 >#define DISK_PLUGGING_OK 5 > >#define MaximumLBAOf28Bit 0x10000000 > >#define DisableChannel 1 >#define EnableChannel 2 > >#define CABLE_40_PIN 0 >#define CABLE_80_PIN 1 > >#define RaidActive 0 >#define RaidInactive 1 > >#define IDE_CLOCK_66 0 >#define IDE_CLOCK_50 1 > >#define USE_ULTRA_DMA 0 >#define USE_MULTIWORD_DMA 1 > >/************************************************************************ > * Vendor specific information > ************************************************************************/ >typedef struct _PHYSICAL_DISK_STATUS >{ > u8 ModelNumber[40]; /* Byte 00-39 */ > u32 UserAddressableSectors_LOW; /* Byte 40-43 */ > u32 UserAddressableSectors_HIGH; /* Byte 44-47 */ > u8 MultiWordDMASupport; /* Byte 48 */ > u8 MultiWordDMAActive; /* Byte 49 */ > u8 UltraDMASupport; /* Byte 50 */ > u8 UltraDMAActive; /* Byte 51 */ > u8 RaidType; /* Byte 52 */ > u8 RaidNumber; /* Byte 53 */ > u8 SerialNumber[20]; /* Byte 54-73 */ > u8 DiskStatus; /* Byte 74 */ > u8 DiskOriginalLocation; /* Byte 75 */ > u8 Cable80Pin; /* Byte 76 */ > u8 BootableDisk; /* Byte 77 */ > u8 StorageSize[8]; /* Byte 78-85 */ > u8 Reserved[35]; /* Byte 86-120 */ > u8 UpdateYear; /* Byte 121 */ > u8 UpdateMonth; /* Byte 122 */ > u8 UpdateDay; /* Byte 123 */ > u8 FirmwareVer; /* Byte 124 */ > u8 RebuildStatus; /* Byte 125 */ > u8 StripeSize; /* Byte 126 */ > u8 AutoRebuildEnable; /* Byte 127 */ >} PHYSICAL_DISK_STATUS, *PPHYSICAL_DISK_STATUS; > >/************************************************************************ > * vendor specific information > ************************************************************************/ >typedef struct _IT8212_SET_CHIP_STATUS_INFO >{ > u16 RaidType; /* Word 129 */ > u16 ContainingDisks; /* Word 130 */ > u16 UltraDmaTiming01; /* Word 131 */ > u16 UltraDmaTiming23; /* Word 132 */ > u16 UltraDmaTiming45; /* Word 133 */ > u16 UltraDmaTiming6; /* Word 134 */ > u16 MultiWordDmaTiming01; /* Word 135 */ > u16 UltraDmaTiming2; /* Word 136 */ > u16 PioTiming4; /* Word 137 */ > u16 AutoRebuildEnable; /* Word 138 */ > u16 IdeClkUDma01; /* Word 139 */ > u16 IdeClkUDma23; /* Word 140 */ > u16 IdeClkUDma45; /* Word 141 */ > u16 IdeClkUDma6; /* Word 142 */ > u16 IdeClkMDma01; /* Word 143 */ > u16 IdeClkMDma2; /* Word 144 */ > u16 IdeClkPio4; /* Word 145 */ > u16 StripeSize; /* Word 146 */ > u16 BootableDisk; /* Word 147 */ > u16 CheckHotSwapInterval; /* Word 148 */ > u16 TargetSourceDisk; /* Word 149 */ > u16 RebuildBlockSize; /* Word 150 */ > u16 ResetInterval1; /* Word 151 */ > u16 ResetInterval2; /* Word 152 */ > u16 RebuildRetryTimes; /* Word 153 */ > u16 NewlyCreated; /* Word 154 */ >} IT8212_SET_CHIP_STATUS_INFO, *PIT8212_SET_CHIP_STATUS_INFO; > >/************************************************************************ > * Serial number written to HDD (20 bytes) > ************************************************************************/ >typedef struct _RAID_SERIAL_NUMBER >{ > u16 Year; > u8 Month; > u8 Date; > u8 Day; > u8 Hour; > u8 Minute; > u8 Second; > u8 MiniSec; > u8 RaidType; > u8 ContainingDisks; > u8 DontCare[9]; >} RAID_SERIAL_NUMBER, *PRAID_SERIAL_NUMBER; > >/************************************************************************ > * Disk array create information > * > * Following items index definition > * 0: Primary Master > * 1: Secondary Master > * 2: Primary Slave > * 3: Secondary Slave > ************************************************************************/ >typedef struct _RAID_CREATE_INFO >{ > u8 DiskArrayId; > RAID_SERIAL_NUMBER SerialNumber; > u8 ModelNumber[40]; > u16 RaidType; > u16 ContainingDisks; > u16 AutoRebuildEnable; > u16 StripeSize; > u16 BootableDisk; > u16 TargetSourceDisk; > u8 ErasePartition; > u8 DMASupported[4]; > u8 UDMASupported[4]; > u8 AddressableSectors[4]; > u8 NewlyCreated; > u8 Reserved; >} RAID_CREATE_INFO, *PRAID_CREATE_INFO; > >/************************************************************************ > * Rebuild data structure > ************************************************************************/ >typedef struct _RAID_REBUILD_INFO >{ > u8 DiskArrayId; /* Virtual device number (0-3) */ > u8 SrcDisk; /* Source disk (0-3) */ > u8 DestDisk; /* Destination disk (0-3) */ > u8 Resume; /* 1: Resume the last time rebuild */ > /* 0: Rebuild from LBA 0 */ > u8 Status; /* Indicate the status of the current */ > /* rebuild command filled by drivers */ > u8 Reserved[3]; /* For aligement */ >} RAID_REBUILD_INFO, *PRAID_REBUILD_INFO; > >/************************************************************************ > * ATA transfer modes > ************************************************************************/ >#define PIO_DEFAULT 0x00 >#define PIO_DEFAULT_IORDY_DISABLE 0x01 >#define PIO_FLOW_CONTROL 0x08 >#define SINGLEWORD_DMA 0x10 >#define MULTIWORD_DMA 0x20 >#define ULTRA_DMA 0x40 > >#define ITE_DRV_SIGNATURE "ITE RAID CONTROLLER" >#define ITE_DRV_BYPASS "ITE BYPASS MODE" > >/************************************************************************ > * Extra IDE commands supported by Accusys > ************************************************************************/ >#define IDE_COMMAND_GET_CHIP_STATUS 0xFA >#define IDE_COMMAND_SET_CHIP_STATUS 0xFB >#define IDE_COMMAND_REBUILD 0xFC >#define IDE_COMMAND_REBUILD_STATUS 0xFD > >#define REBUILD_ERR_WRONG_ARRAY_TYPE 0x01 >#define REBUILD_ERR_DISK_TOO_SMALL 0x02 >#define REBUILD_ERR_SRC_DISK_LOCATION_INCORRECT 0x03 >#define REBUILD_ERR_SRC_DISK_OFFLINE 0x04 >#define REBUILD_ERR_DEST_DISK_OFFLINE 0x05 >#define REBUILD_ERR_DISK_BUSY 0x10 > >/************************************************************************ > * ATA transfer modes > ************************************************************************/ >#define PIO_DEFAULT 0x00 >#define PIO_DEFAULT_IORDY_DISABLE 0x01 >#define PIO_FLOW_CONTROL 0x08 >#define SINGLEWORD_DMA 0x10 >#define MULTIWORD_DMA 0x20 >#define ULTRA_DMA 0x40 > >/************************************************************************ > * IDE registers offset > ************************************************************************/ >#define IDE_NR_PORTS 10 > >#define IDE_DATA_OFFSET 0 >#define IDE_ERROR_OFFSET 1 >#define IDE_NSECTOR_OFFSET 2 >#define IDE_LOCYL_OFFSET 3 >#define IDE_MIDCYL_OFFSET 4 >#define IDE_HCYL_OFFSET 5 >#define IDE_SELECT_OFFSET 6 >#define IDE_STATUS_OFFSET 7 >#define IDE_CONTROL_OFFSET 8 >#define IDE_IRQ_OFFSET 9 > >#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET >#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET >#define IDE_ALTERNATE_OFFSET IDE_CONTROL_OFFSET > >/************************************************************************ > * ATAPI registers offset > ************************************************************************/ >#define ATAPI_DATA_OFFSET 0 >#define ATAPI_ERROR_OFFSET 1 >#define ATAPI_INTREASON_OFFSET 2 >#define ATAPI_UNUSED1_OFFSET 3 >#define ATAPI_LCYL_OFFSET 4 >#define ATAPI_HCYL_OFFSET 5 >#define ATAPI_SELECT_OFFSET 6 >#define ATAPI_STATUS_OFFSET 7 >#define ATAPI_CONTROL_OFFSET 8 > >#define ATAPI_COMMAND_OFFSET ATAPI_STATUS_OFFSET >#define ATAPI_FEATURE_OFFSET ATAPI_ERROR_OFFSET > >/************************************************************************ > * Following structures are according to SPC-3 (by Chanel) > ************************************************************************/ >typedef struct _SCSI_MODE_SENSE6 >{ > u8 OperationCode; > u8 Reserved1 : 3; > u8 Dbd : 1; > u8 Reserved2 : 4; > u8 PageCode : 6; > u8 Pc : 2; > u8 SubpageCode; > u8 AllocationLength; > u8 Control; >} SCSI_MODE_SENSE6, *PSCSI_MODE_SENSE6; > >typedef struct _SCSI_MODE_SENSE10 >{ > u8 OperationCode; > u8 Reserved1 : 3; > u8 Dbd : 1; > u8 LLBAA : 1; > u8 Reserved2 : 3; > u8 PageCode : 6; > u8 Pc : 2; > u8 SubpageCode; > u8 Reserved3[3]; > u8 AllocationLengthMsb; > u8 AllocationLengthLsb; > u8 Control; >} SCSI_MODE_SENSE10, *PSCSI_MODE_SENSE10; > >typedef struct _SCSI_MODE_SELECT6 >{ > u8 OperationCode; > u8 SPBit : 1; > u8 Reserved1 : 3; > u8 PFBit : 1; > u8 Reserved2 : 3; > u8 Reserved3[2]; > u8 ParameterListLength; > u8 Control; >} SCSI_MODE_SELECT6, *PSCSI_MODE_SELECT6; > >typedef struct _SCSI_MODE_SELECT10 >{ > u8 OperationCode; > u8 SPBit : 1; > u8 Reserved1 : 3; > u8 PFBit : 1; > u8 Reserved2 : 3; > u8 Reserved3[5]; > u8 ParameterListLengthMsb; > u8 ParameterListLengthLsb; > u8 Control; >} SCSI_MODE_SELECT10, *PSCSI_MODE_SELECT10; > >typedef struct _SCSI_MODE_PARAMETER_HEADER6 >{ > u8 ModeDataLength; > u8 MediumType; > u8 DeviceSpecificParameter; > u8 BlockDescriptorLength; >} SCSI_MODE_PARAMETER_HEADER6, *PSCSI_MODE_PARAMETER_HEADER6; > >typedef struct _SCSI_MODE_PARAMETER_HEADER10 >{ > u8 ModeDataLengthMsb; > u8 ModeDataLengthLsb; > u8 MediumType; > u8 DeviceSpecificParameter; > u8 Reserved[2]; > u8 BlockDescriptorLengthMsb; > u8 BlockDescriptorLengthLsb; >} SCSI_MODE_PARAMETER_HEADER10, *PSCSI_MODE_PARAMETER_HEADER10; > >typedef struct _SCSI_MODE_PARAMTER_BLOCK_DESCRIPTER >{ > u8 DesityCode; > u8 NumberOfBlocks2; > u8 NumberOfBlocks1; > u8 NumberOfBlocks0; > u8 Reserved; > u8 BlockLength2; > u8 BlockLength1; > u8 BlockLength0; >} SCSI_MODE_PARAMTER_BLOCK_DESCRIPTER, *PSCSI_MODE_PARAMTER_BLOCK_DESCRIPTER; > >/************************************************************************ > * IDE command definitions > ************************************************************************/ >#define IDE_COMMAND_ATAPI_RESET 0x08 >#define IDE_COMMAND_RECALIBRATE 0x10 >#define IDE_COMMAND_READ_SECTOR 0x20 >#define IDE_COMMAND_READ_SECTOR_EXT 0x24 >#define IDE_COMMAND_READ_DMA_EXT 0x25 >#define IDE_COMMAND_READ_MULTIPLE_EXT 0x29 >#define IDE_COMMAND_WRITE_SECTOR 0x30 >#define IDE_COMMAND_WRITE_SECTOR_EXT 0x34 >#define IDE_COMMAND_WRITE_DMA_EXT 0x35 >#define IDE_COMMAND_WRITE_MULTIPLE_EXT 0x39 >#define IDE_COMMAND_READ_VERIFY 0x40 >#define IDE_COMMAND_READ_VERIFY_EXT 0x42 >#define IDE_COMMAND_SEEK 0x70 >#define IDE_COMMAND_SET_DRIVE_PARAMETERS 0x91 >#define IDE_COMMAND_ATAPI_PACKET 0xA0 >#define IDE_COMMAND_ATAPI_IDENTIFY 0xA1 >#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 >#define IDE_COMMAND_SET_FEATURE 0xEF >#define IDE_COMMAND_IDENTIFY 0xEC >#define IDE_COMMAND_MEDIA_EJECT 0xED > >/************************************************************************ > * IDE status definitions > ************************************************************************/ >#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 > >/************************************************************************ > * IDE drive control definitions. > ************************************************************************/ >#define IDE_DC_DISABLE_INTERRUPTS 0x02 >#define IDE_DC_RESET_CONTROLLER 0x04 >#define IDE_DC_REENABLE_CONTROLLER 0x00 > >/************************************************************************ > * IDE error definitions. > ************************************************************************/ >#define IDE_ERROR_BAD_BLOCK 0x80 >#define IDE_ERROR_DATA_ERROR 0x40 >#define IDE_ERROR_MEDIA_CHANGE 0x20 >#define IDE_ERROR_ID_NOT_FOUND 0x10 >#define IDE_ERROR_MEDIA_CHANGE_REQ 0x08 >#define IDE_ERROR_COMMAND_ABORTED 0x04 >#define IDE_ERROR_END_OF_MEDIA 0x02 >#define IDE_ERROR_ILLEGAL_LENGTH 0x01 > >/************************************************************************ > * IDENTIFY data. > ************************************************************************/ >typedef struct _IDENTIFY_DATA >{ > u16 GeneralConfiguration; /* 00 00 */ > u16 NumberOfCylinders; /* 02 1 */ > u16 Reserved1; /* 04 2 */ > u16 NumberOfHeads; /* 06 3 */ > u16 UnformattedBytesPerTrack; /* 08 4 */ > u16 UnformattedBytesPerSector; /* 0A 5 */ > u16 SectorsPerTrack; /* 0C 6 */ > u16 VendorUnique1[3]; /* 0E 7-9 */ > u16 SerialNumber[10]; /* 14 10-19 */ > u16 BufferType; /* 28 20 */ > u16 BufferSectorSize; /* 2A 21 */ > u16 NumberOfEccBytes; /* 2C 22 */ > u16 FirmwareRevision[4]; /* 2E 23-26 */ > u16 ModelNumber[20]; /* 36 27-46 */ > u8 MaximumBlockTransfer; /* 5E 47 */ > u8 VendorUnique2; /* 5F */ > u16 DoubleWordIo; /* 60 48 */ > u16 Capabilities; /* 62 49 */ > u16 Reserved2; /* 64 50 */ > u8 VendorUnique3; /* 66 51 */ > u8 PioCycleTimingMode; /* 67 */ > u8 VendorUnique4; /* 68 52 */ > u8 DmaCycleTimingMode; /* 69 */ > u16 TranslationFieldsValid : 1; /* 6A 53 */ > u16 Reserved3 : 15; /* */ > u16 NumberOfCurrentCylinders; /* 6C 54 */ > u16 NumberOfCurrentHeads; /* 6E 55 */ > u16 CurrentSectorsPerTrack; /* 70 56 */ > u32 CurrentSectorCapacity; /* 72 57-58 */ > u16 CurrentMultiSectorSetting; /* 59 */ > u32 UserAddressableSectors; /* 60-61 */ > u16 SingleWordDMASupport : 8; /* 62 */ > u16 SingleWordDMAActive : 8; /* */ > u16 MultiWordDMASupport : 8; /* 63 */ > u16 MultiWordDMAActive : 8; /* */ > u16 AdvancedPIOModes : 8; /* 64 */ > u16 Reserved4 : 8; /* */ > u16 MinimumMWXferCycleTime; /* 65 */ > u16 RecommendedMWXferCycleTime; /* 66 */ > u16 MinimumPIOCycleTime; /* 67 */ > u16 MinimumPIOCycleTimeIORDY; /* 68 */ > u16 Reserved5[2]; /* 69-70 */ > u16 ReleaseTimeOverlapped; /* 71 */ > u16 ReleaseTimeServiceCommand; /* 72 */ > u16 MajorRevision; /* 73 */ > u16 MinorRevision; /* 74 */ > u16 Reserved6[50]; /* 75-126 */ > u16 SpecialFunctionsEnabled; /* 127 */ > u16 Reserved7[128]; /* 128-255 */ >} IDENTIFY_DATA, *PIDENTIFY_DATA; > >/************************************************************************ > * Identify data without the Reserved4. > ************************************************************************/ >typedef struct _IDENTIFY_DATA2 >{ > u16 GeneralConfiguration; /* 00 */ > u16 NumberOfCylinders; /* 01 */ > u16 Reserved1; /* 02 */ > u16 NumberOfHeads; /* 03 */ > u16 Reserved2[2]; /* 04-05 */ > u16 SectorsPerTrack; /* 06 */ > u16 Reserved3[3]; /* 07-09 */ > u16 SerialNumber[10]; /* 10-19 */ > u16 Reserved4[3]; /* 20-22 */ > u16 FirmwareRevision[4]; /* 23-26 */ > u16 ModelNumber[20]; /* 27-46 */ > u16 MaximumBlockTransfer; /* 47 */ > u16 Reserved5; /* 48 */ > u16 Capabilities[2]; /* 49-50 */ > u16 Reserved6[2]; /* 51-52 */ > u16 ValidFieldIndicator; /* 53 */ > u16 NumberOfCurrentCylinders; /* 54 */ > u16 NumberOfCurrentHeads; /* 55 */ > u16 CurrentSectorsPerTrack; /* 56 */ > u16 CurrentSectorCapacityLow; /* 57 */ > u16 CurrentSectorCapacityHigh; /* 58 */ > u16 CurrentMultiSectorSetting; /* 59 */ > u32 UserAddressableSectors; /* 60-61 */ > u16 Reserved7; /* 62 */ > u8 MultiWordDMASupport; /* 63 */ > u8 MultiWordDMAActive; /* */ > u16 AdvancedPIOModes; /* 64 */ > u16 MinimumMWXferCycleTime; /* 65 */ > u16 RecommendedMWXferCycleTime; /* 66 */ > u16 MinimumPIOCycleTime; /* 67 */ > u16 MinimumPIOCycleTimeIORDY; /* 68 */ > u16 Reserved8[6]; /* 69-74 */ > u16 QueueDepth; /* 75 */ > u16 Reserved9[4]; /* 76-79 */ > u16 MajorVersionNumber; /* 80 */ > u16 MinorVersionNumber; /* 81 */ > u32 CmdSetSupported; /* 82-83 */ > u16 CmdSetFeatureSupportedExt; /* 84 */ > u16 CmdSetFeatureEnabledLow; /* 85 */ > u16 CmdSetFeatureEnabledHigh; /* 86 */ > u16 CmdSetFeatureDefault; /* 87 */ > u8 UltraDMASupport; /* 88 */ > u8 UltraDMAActive; /* */ > u16 SecurityEraseTime; /* 89 */ > u16 EnhancedSecurityEraseTime; /* 90 */ > u16 PowerManagementValue; /* 91 */ > u16 MasterPasswordRevision; /* 92 */ > u16 HwResetResult; /* 93 */ > u16 Reserved11[6]; /* 94-99 */ > u32 Capacity_48bit_LOW; /* 100-101 */ > u32 Capacity_48bit_HIGH; /* 102-103 */ > u16 Reserved12[24]; /* 104-127 */ > u16 SecurityStatus; /* 128 */ > u16 Reserved13[31]; /* 129-159 vendor spec */ > u16 Reserved14[96]; /* 160-255 */ >} IDENTIFY_DATA2, *PIDENTIFY_DATA2; > >#define IDENTIFY_DATA_SIZE sizeof(IDENTIFY_DATA) > >/************************************************************************ > * IDENTIFY capability bit definitions. > ************************************************************************/ >#define IDENTIFY_CAPABILITIES_DMA_SUPPORTED 0x0100 >#define IDENTIFY_CAPABILITIES_LBA_SUPPORTED 0x0200 > >/************************************************************************ > * IDENTIFY DMA timing cycle modes. > ************************************************************************/ >#define IDENTIFY_DMA_CYCLES_MODE_0 0x00 >#define IDENTIFY_DMA_CYCLES_MODE_1 0x01 >#define IDENTIFY_DMA_CYCLES_MODE_2 0x02 > >typedef struct _SENSE_DATA >{ > u8 ErrorCode:7; > u8 Valid:1; > u8 SegmentNumber; > u8 SenseKey:4; > u8 Reserved:1; > u8 IncorrectLength:1; > u8 EndOfMedia:1; > u8 FileMark:1; > u8 Information[4]; > u8 AdditionalSenseLength; > u8 CommandSpecificInformation[4]; > u8 AdditionalSenseCode; > u8 AdditionalSenseCodeQualifier; > u8 FieldReplaceableUnitCode; > u8 SenseKeySpecific[3]; >} SENSE_DATA, *PSENSE_DATA; > >/************************************************************************ > * Sense codes > ************************************************************************/ >#define SCSI_SENSE_NO_SENSE 0x00 >#define SCSI_SENSE_RECOVERED_ERROR 0x01 >#define SCSI_SENSE_NOT_READY 0x02 >#define SCSI_SENSE_MEDIUM_ERROR 0x03 >#define SCSI_SENSE_HARDWARE_ERROR 0x04 >#define SCSI_SENSE_ILLEGAL_REQUEST 0x05 >#define SCSI_SENSE_UNIT_ATTENTION 0x06 >#define SCSI_SENSE_DATA_PROTECT 0x07 >#define SCSI_SENSE_BLANK_CHECK 0x08 >#define SCSI_SENSE_UNIQUE 0x09 >#define SCSI_SENSE_COPY_ABORTED 0x0A >#define SCSI_SENSE_ABORTED_COMMAND 0x0B >#define SCSI_SENSE_EQUAL 0x0C >#define SCSI_SENSE_VOL_OVERFLOW 0x0D >#define SCSI_SENSE_MISCOMPARE 0x0E >#define SCSI_SENSE_RESERVED 0x0F > >/************************************************************************ > * Additional Sense codes > ************************************************************************/ >#define SCSI_ADSENSE_NO_SENSE 0x00 >#define SCSI_ADSENSE_MAN_INTERV 0x03 >#define SCSI_ADSENSE_LUN_NOT_READY 0x04 >#define SCSI_ADSENSE_ILLEGAL_COMMAND 0x20 >#define SCSI_ADSENSE_ILLEGAL_BLOCK 0x21 >#define SCSI_ADSENSE_INVALID_LUN 0x25 >#define SCSI_ADSENSE_SELECT_TIMEOUT 0x45 >#define SCSI_ADSENSE_MUSIC_AREA 0xA0 >#define SCSI_ADSENSE_DATA_AREA 0xA1 >#define SCSI_ADSENSE_VOLUME_OVERFLOW 0xA7 > >#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE 0x3A >#define SCSI_ADWRITE_PROTECT 0x27 >#define SCSI_ADSENSE_MEDIUM_CHANGED 0x28 >#define SCSI_ADSENSE_BUS_RESET 0x29 >#define SCSI_ADSENSE_TRACK_ERROR 0x14 >#define SCSI_ADSENSE_SEEK_ERROR 0x15 >#define SCSI_ADSENSE_REC_DATA_NOECC 0x17 >#define SCSI_ADSENSE_REC_DATA_ECC 0x18 >#define SCSI_ADSENSE_ILLEGAL_MODE 0x64 >#define SCSI_ADSENSE_BAD_CDB 0x24 >#define SCSI_ADSENSE_BAD_PARM_LIST 0x26 >#define SCSI_ADSENSE_CANNOT_READ_MEDIUM 0x30 > >#define SCSISTAT_CHECK_CONDITION 0x02 > >/************************************************************************ > * Inquiry buffer structure. This is the data returned from the target > * after it receives an inquiry. > * > * This structure may be extended by the number of bytes specified > * in the field AdditionalLength. The defined size constant only > * includes fields through ProductRevisionLevel. > * > * The NT SCSI drivers are only interested in the first 36 bytes of data. > ************************************************************************/ > >#define INQUIRYDATABUFFERSIZE 36 > >typedef struct _INQUIRYDATA >{ > u8 DeviceType : 5; > u8 DeviceTypeQualifier : 3; > u8 DeviceTypeModifier : 7; > u8 RemovableMedia : 1; > u8 Versions; > u8 ResponseDataFormat; > u8 AdditionalLength; > u8 Reserved[2]; > u8 SoftReset : 1; > u8 CommandQueue : 1; > u8 Reserved2 : 1; > u8 LinkedCommands : 1; > u8 Synchronous : 1; > u8 Wide16Bit : 1; > u8 Wide32Bit : 1; > u8 RelativeAddressing : 1; > u8 VendorId[8]; > u8 ProductId[16]; > u8 ProductRevisionLevel[4]; > u8 VendorSpecific[20]; > u8 Reserved3[40]; >} INQUIRYDATA, *PINQUIRYDATA; > >#define DIRECT_ACCESS_DEVICE 0x00 /* Disks */ > >/************************************************************************ > * Read Capacity Data - returned in Big Endian format > ************************************************************************/ >typedef struct _READ_CAPACITY_DATA >{ > u32 LogicalBlockAddress; > u32 BytesPerBlock; >} READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA; > >#define MAXIMUM_CDB_SIZE 12 > >/************************************************************************ > * CDB (Command Descriptor Block) > ************************************************************************/ >typedef union _CDB >{ > /* > * Standard 6-byte CDB > */ > struct _CDB6READWRITE > { > u8 OperationCode; /* Opcode */ > u8 LogicalBlockMsb1 : 5; /* Logical block MSB 5-bit */ > u8 LogicalUnitNumber : 3; /* LUN */ > u8 LogicalBlockMsb0; /* Logical block MSB 8-bit */ > u8 LogicalBlockLsb; /* Logical block LSB 8-bit */ > u8 TransferBlocks; /* Data length */ > u8 Control; /* Control byte */ > } CDB6READWRITE, *PCDB6READWRITE; > > /* > * Standard 10-byte CDB > */ > struct _CDB10 > { > u8 OperationCode; > u8 Reserved1 : 5; > u8 LogicalUnitNumber : 3; > u8 LogicalBlockByte0; > u8 LogicalBlockByte1; > u8 LogicalBlockByte2; > u8 LogicalBlockByte3; > u8 Reserved2; > u8 TransferBlocksMsb; > u8 TransferBlocksLsb; > u8 Control; > } CDB10, *PCDB10; > > struct _START_STOP > { > u8 OperationCode; > u8 Immediate: 1; > u8 Reserved1 : 4; > u8 LogicalUnitNumber : 3; > u8 Reserved2[2]; > u8 Start : 1; > u8 LoadEject : 1; > u8 Reserved3 : 6; > u8 Control; > } START_STOP, *PSTART_STOP; > >} CDB, *PCDB; > >/************************************************************************ > * SCSI CDB operation codes > ************************************************************************/ >#define SCSIOP_TEST_UNIT_READY 0x00 >#define SCSIOP_REZERO_UNIT 0x01 >#define SCSIOP_REWIND 0x01 >#define SCSIOP_REQUEST_BLOCK_ADDR 0x02 >#define SCSIOP_REQUEST_SENSE 0x03 >#define SCSIOP_FORMAT_UNIT 0x04 >#define SCSIOP_READ_BLOCK_LIMITS 0x05 >#define SCSIOP_REASSIGN_BLOCKS 0x07 >#define SCSIOP_READ6 0x08 >#define SCSIOP_RECEIVE 0x08 >#define SCSIOP_WRITE6 0x0A >#define SCSIOP_PRINT 0x0A >#define SCSIOP_SEND 0x0A >#define SCSIOP_SEEK6 0x0B >#define SCSIOP_TRACK_SELECT 0x0B >#define SCSIOP_SLEW_PRINT 0x0B >#define SCSIOP_SEEK_BLOCK 0x0C >#define SCSIOP_PARTITION 0x0D >#define SCSIOP_READ_REVERSE 0x0F >#define SCSIOP_WRITE_FILEMARKS 0x10 >#define SCSIOP_FLUSH_BUFFER 0x10 >#define SCSIOP_SPACE 0x11 >#define SCSIOP_INQUIRY 0x12 >#define SCSIOP_VERIFY6 0x13 >#define SCSIOP_RECOVER_BUF_DATA 0x14 >#define SCSIOP_MODE_SELECT 0x15 >#define SCSIOP_RESERVE_UNIT 0x16 >#define SCSIOP_RELEASE_UNIT 0x17 >#define SCSIOP_COPY 0x18 >#define SCSIOP_ERASE 0x19 >#define SCSIOP_MODE_SENSE 0x1A >#define SCSIOP_START_STOP_UNIT 0x1B >#define SCSIOP_STOP_PRINT 0x1B >#define SCSIOP_LOAD_UNLOAD 0x1B >#define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C >#define SCSIOP_SEND_DIAGNOSTIC 0x1D >#define SCSIOP_MEDIUM_REMOVAL 0x1E >#define SCSIOP_READ_CAPACITY 0x25 >#define SCSIOP_READ 0x28 >#define SCSIOP_WRITE 0x2A >#define SCSIOP_SEEK 0x2B >#define SCSIOP_LOCATE 0x2B >#define SCSIOP_WRITE_VERIFY 0x2E >#define SCSIOP_VERIFY 0x2F >#define SCSIOP_SEARCH_DATA_HIGH 0x30 >#define SCSIOP_SEARCH_DATA_EQUAL 0x31 >#define SCSIOP_SEARCH_DATA_LOW 0x32 >#define SCSIOP_SET_LIMITS 0x33 >#define SCSIOP_READ_POSITION 0x34 >#define SCSIOP_SYNCHRONIZE_CACHE 0x35 >#define SCSIOP_COMPARE 0x39 >#define SCSIOP_COPY_COMPARE 0x3A >#define SCSIOP_WRITE_DATA_BUFF 0x3B >#define SCSIOP_READ_DATA_BUFF 0x3C >#define SCSIOP_CHANGE_DEFINITION 0x40 >#define SCSIOP_READ_SUB_CHANNEL 0x42 >#define SCSIOP_READ_TOC 0x43 >#define SCSIOP_READ_HEADER 0x44 >#define SCSIOP_PLAY_AUDIO 0x45 >#define SCSIOP_PLAY_AUDIO_MSF 0x47 >#define SCSIOP_PLAY_TRACK_INDEX 0x48 >#define SCSIOP_PLAY_TRACK_RELATIVE 0x49 >#define SCSIOP_PAUSE_RESUME 0x4B >#define SCSIOP_LOG_SELECT 0x4C >#define SCSIOP_LOG_SENSE 0x4D >#define SCSIOP_MODE_SELECT10 0x55 >#define SCSIOP_MODE_SENSE10 0x5A >#define SCSIOP_LOAD_UNLOAD_SLOT 0xA6 >#define SCSIOP_MECHANISM_STATUS 0xBD >#define SCSIOP_READ_CD 0xBE > >#define DRIVER_NAME "Device Driver for IT8212 RAID Controller" >#define COMPANY_NAME "Integrated Technology Express, Inc." >#define CONTROLLER_NAME_IT8212 "IT8212 UDMA/ATA133 RAID Controller" >#define PROC_DIR_NAME "it8212" >#define ITE_MAX_CMDS 124 > >#define PCI_IOSEN 0x01 /* Enable IO space */ >#define PCI_BMEN 0x04 /* Enable IDE bus master */ > >/************************************************************************ > * PRD (Physical Region Descriptor) = Scatter-gather table > * > * | byte3 | byte2 | byte1 | byte0 | > * +--------------------------------------------+ > * | Memory Region Physical Base Address[31:1] | > * +----+----------------+----------------------+ > * |EOT | reserved | Byte count[15:1] | > * +----+----------------+----------------------+ > ************************************************************************/ >typedef struct _PRD_TABLE_ENTRY >{ > u32 PhysicalBaseAddress; /* Byte0 - Byte3 */ > u16 ByteCount; /* Byte4 - Byte5 */ > u16 EndOfTable; /* Byte6 - Byte7 */ >} PRD_TABLE_ENTRY, *PPRD_TABLE_ENTRY; > >#define SG_FLAG_EOT 0x8000 /* End of PRD */ >#define MAX_SG_DESCRIPTORS 17 /* 17 -- maximum 64K */ > >#define NUM_OF_PRD_TABLE_ENTRY 0x10 > >/************************************************************************ > * Bus master register bits definition > ************************************************************************/ >#define BM_CMD_FLG_START 0x01 >#define BM_CMD_FLG_WRTTOMEM 0x08 >#define BM_CMD_FLG_WRTTODSK 0x00 > >#define BM_STAT_FLG_ACTIVE 0x01 >#define BM_STAT_FLG_ERR 0x02 >#define BM_STAT_FLG_INT 0x04 >#define BM_DRV0_DMA_CAPABLE 0x20 >#define BM_DRV1_DMA_CAPABLE 0x40 > >#define BM_PRD_FLG_EOT 0x8000 > >/************************************************************************ > * SRB Functions > ************************************************************************/ >#define SRB_FUNCTION_EXECUTE_SCSI 0x00 >#define SRB_FUNCTION_IO_CONTROL 0x02 >#define SRB_FUNCTION_SHUTDOWN 0x07 >#define SRB_FUNCTION_FLUSH 0x08 > >/************************************************************************ > * SRB Status > ************************************************************************/ >#define SRB_STATUS_PENDING 0x00 >#define SRB_STATUS_SUCCESS 0x01 >#define SRB_STATUS_ABORTED 0x02 >#define SRB_STATUS_ABORT_FAILED 0x03 >#define SRB_STATUS_ERROR 0x04 >#define SRB_STATUS_BUSY 0x05 >#define SRB_STATUS_INVALID_REQUEST 0x06 >#define SRB_STATUS_INVALID_PATH_ID 0x07 >#define SRB_STATUS_NO_DEVICE 0x08 >#define SRB_STATUS_TIMEOUT 0x09 >#define SRB_STATUS_SELECTION_TIMEOUT 0x0A >#define SRB_STATUS_COMMAND_TIMEOUT 0x0B >#define SRB_STATUS_MESSAGE_REJECTED 0x0D >#define SRB_STATUS_BUS_RESET 0x0E >#define SRB_STATUS_PARITY_ERROR 0x0F >#define SRB_STATUS_REQUEST_SENSE_FAILED 0x10 >#define SRB_STATUS_NO_HBA 0x11 >#define SRB_STATUS_DATA_OVERRUN 0x12 >#define SRB_STATUS_UNEXPECTED_BUS_FREE 0x13 >#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH 0x15 >#define SRB_STATUS_REQUEST_FLUSHED 0x16 >#define SRB_STATUS_INVALID_LUN 0x20 >#define SRB_STATUS_INVALID_TARGET_ID 0x21 >#define SRB_STATUS_BAD_FUNCTION 0x22 >#define SRB_STATUS_ERROR_RECOVERY 0x23 >#define SRB_STATUS_NEED_REQUEUE 0x24 > >/************************************************************************ > * SRB Status Masks > ************************************************************************/ >#define SRB_STATUS_QUEUE_FROZEN 0x40 >#define SRB_STATUS_AUTOSENSE_VALID 0x80 > >#define SRB_STATUS(Status) \ > (Status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) > >/************************************************************************ > * SRB Flag Bits > ************************************************************************/ >#define SRB_FLAGS_DATA_IN 0x00000040 >#define SRB_FLAGS_DATA_OUT 0x00000080 > >/************************************************************************ > * SRB Working flags define area > ************************************************************************/ >#define SRB_WFLAGS_USE_INTERNAL_BUFFER 0x00000001 >#define SRB_WFLAGS_IGNORE_ARRAY 0x00000002 >#define SRB_WFLAGS_HAS_CALL_BACK 0x00000004 >#define SRB_WFLAGS_MUST_DONE 0x00000008 >#define SRB_WFLAGS_ON_MIRROR_DISK 0x00000010 >#define SRB_WFLAGS_ON_SOURCE_DISK 0x00000020 >#define SRB_WFLAGS_ARRAY_IO_STARTED 0x10000000 >#define SRB_WFLAGS_WATCHTIMER_CALLED 0x20000000 >#define SRB_WFLAGS_USE_SG 0x40000000 > >/************************************************************************ > * SCSI I/O Request Block > ************************************************************************/ >typedef struct _SCSI_REQUEST_BLOCK >{ > u16 Length; > u8 Function; > u8 SrbStatus; > u8 ScsiStatus; > u8 TargetId; > u8 Lun; > u8 CdbLength; > u8 SenseInfoBufferLength; > u8 UseSg; > u8 reseved[2]; > u32 WorkingFlags; > u32 SrbFlags; > u32 DataTransferLength; > u32 TimeOutValue; > void * DataBuffer; > void * SenseInfoBuffer; > u8 Cdb[16]; > Scsi_Cmnd * pREQ; >} SCSI_REQUEST_BLOCK, *PSCSI_REQUEST_BLOCK; > >#define SCSI_REQUEST_BLOCK_SIZE sizeof(SCSI_REQUEST_BLOCK) > >/************************************************************************ > * Second device flags > ***********************************************************************/ >#define DFLAGS_REDUCE_MODE 0x00010000 >#define DFLAGS_DEVICE_DISABLED 0x00020000 >#define DFLAGS_BOOTABLE_DEVICE 0x00080000 >#define DFLAGS_BOOT_MARK 0x00100000 >#define DFLAGS_NEW_ADDED 0x40000000 >#define DFLAGS_REMAINED_MEMBER 0x80000000 > >/************************************************************************ > * Device Extension Device Flags > ************************************************************************/ >/* > * Indicates that some device is present. > */ >#define DFLAGS_DEVICE_PRESENT 0x0001 > >/* > * Indicates whether ATAPI commands can be used. > */ >#define DFLAGS_ATAPI_DEVICE 0x0002 > >/* > * Indicates whether this is a tape device. > */ >#define DFLAGS_TAPE_DEVICE 0x0004 > >/* > * Indicates whether device interrupts as DRQ is set after > * receiving Atapi Packet Command. > */ >#define DFLAGS_INT_DRQ 0x0008 > >/* > * Indicates that the drive has the 'removable' bit set in > * identify data (offset 128) > */ >#define DFLAGS_REMOVABLE_DRIVE 0x0010 > >/* > * Media status notification enabled. > */ >#define DFLAGS_MEDIA_STATUS_ENABLED 0x0020 > >/* > * Indicates atapi 2.5 changer present. > */ >#define DFLAGS_ATAPI_CHANGER 0x0040 > >/* > * Indicates multi-platter device, not conforming to the 2.5 spec. > */ >#define DFLAGS_SANYO_ATAPI_CHANGER 0x0080 > >/* > * Indicates that the init path for changers has already been done. > */ >#define DFLAGS_CHANGER_INITED 0x0100 >#define DFLAGS_CONFIG_CHANGED 0x0200 > >#define UDMA_MODE_5_6 0x80 > >/************************************************************************ > * Used to disable 'advanced' features. > ************************************************************************/ >#define MAX_ERRORS 4 > >/************************************************************************ > * ATAPI command definitions > ************************************************************************/ >#define ATAPI_MODE_SENSE 0x5A >#define ATAPI_MODE_SELECT 0x55 >#define ATAPI_FORMAT_UNIT 0x24 > >/************************************************************************ > * User IOCTL structure > * Notes: > * (1) Data transfers are limited to PAGE_SIZE (4k on i386, 8k for alpha) > ************************************************************************/ >typedef struct _uioctl_t >{ > u16 inlen; /* Length of data written to device */ > u16 outlen; /* Length of data read from device */ > void * data; /* Data read from devic starts here */ > u8 status; /* Status return from driver */ > u8 reserved[3]; /* For 4-byte alignment */ >} uioctl_t; > >/************************************************************************ > * IOCTL commands for RAID > ************************************************************************/ >#define ITE_IOCMAGIC 't' > >#define ITE_IOC_GET_PHY_DISK_STATUS _IO(ITE_IOCMAGIC, 1) >#define ITE_IOC_CREATE_DISK_ARRAY _IO(ITE_IOCMAGIC, 2) >#define ITE_IOC_REBUILD_START _IO(ITE_IOCMAGIC, 3) >#define ITE_IOC_GET_REBUILD_STATUS _IO(ITE_IOCMAGIC, 4) >#define ITE_IOC_RESET_ADAPTER _IO(ITE_IOCMAGIC, 5) >#define ITE_IOC_GET_DRIVER_VERSION _IO(ITE_IOCMAGIC, 6) > >/************************************************************************ > * _Channel > ************************************************************************/ >typedef struct _Channel >{ > /* > * IDE (ATAPI) io port address. > */ > unsigned long io_ports[IDE_NR_PORTS]; > > /* > * DMA base address. > */ > unsigned long dma_base; > > /* > * Flags word for each possible device. > */ > u16 DeviceFlags[2]; > > /* > * Indicates number of platters on changer-ish devices. > */ > u32 DiscsPresent[2]; > > /* > * Indicates expecting an interrupt. > */ > u8 ExpectingInterrupt; > > /* > * Indicate last tape command was DSC Restrictive. > */ > u8 RDP; > > /* > * Interrupt level. > */ > u8 InterruptLevel; > > /* > * Placeholder for status register after a GET_MEDIA_STATUS command. > */ > u8 ReturningMediaStatus; > > /* > * Remember the channel number (0, 1) > */ > u8 channel; > > /* > * Indicates cable status. > */ > u8 Cable80[2]; > > /* > * Reserved for alignment. > */ > u8 reserved1[0]; > > /* > * Data buffer pointer. > */ > unsigned short * DataBuffer; > > /* > * Data words left. > */ > u32 WordsLeft; > > /* > * Retry count. > */ > u32 RetryCount; > > /* > * Keep DMA type (MULTIWORD_DMA or ULTRA_DMA) for each device. > */ > u8 DmaType[2]; > > /* > * Keep UDMA timing for each device. > */ > u8 UdmaTiming[2]; > > /* > * Keep PIO/DMA timing for each channel. PioDmaTiming[clock][channel] > */ > u8 PioDmaTiming[2]; > > /* > * Keep IDE clock (50 MHz or 66 MHz) for each device. > */ > u8 IdeClock[2]; > > /* > * Keep the active device for each channel. > */ > u8 ActiveDevice; > > /* > * Indicate whether we should perform DMA mode switch on this channel? > */ > u8 DoSwitch; > > /* > * ??? > */ > u8 ConvertCdb; > > /* > * Use or do not use DMA. > */ > u8 UseDma[2]; > > /* > * Reserved for alignment. > */ > u8 reserved2[3]; > > /* > * Identify data for device. > */ > IDENTIFY_DATA FullIdentifyData; > IDENTIFY_DATA2 IdentifyData[2]; > > /* > * DMA PRD table physical address. > */ > dma_addr_t dmatable_dma; > > /* > * DMA PRD table virtual address. > */ > unsigned long * dmatable_cpu; > > /* > * Point to SCATTER/GATHER data buffer. > */ > struct scatterlist * sg_table; > > /* > * DMA read or write. > */ > int sg_dma_direction; > > /* > * Current request on controller. > */ > PSCSI_REQUEST_BLOCK CurrentSrb; > > /* > * Original request on controller. > */ > PSCSI_REQUEST_BLOCK OriginalSrb; > > /* > * Internal SRB. > */ > SCSI_REQUEST_BLOCK _Srb; > > /* > * Remember the PCI device. > */ > struct pci_dev * pPciDev; > > /* > * Placeholder for CDB. > */ > u8 TempCdb[MAXIMUM_CDB_SIZE]; >} Channel, *PChannel; > >/************************************************************************ > * _Adapter > ************************************************************************/ >typedef struct _Adapter >{ > char * name; /* Adapter's name */ > u8 num_channels; /* How many channels support */ > u8 irq; /* irq number */ > u8 irqOwned; /* If any irq is use */ > u8 pci_bus; /* PCI bus number */ > u8 devfn; /* Device and function number */ > u8 offline; /* On line or off line */ > u8 bypass_mode; /* bypass or firware mode */ > u8 reserved2[1]; /* Reserved for alignment */ > Channel * IDEChannel; /* IT8212 supports two channels */ > struct pci_dev * pci_dev; /* For PCI device */ >} >ITE_ADAPTER, *PITE_ADAPTER; > >/************************************************************************ > * Beautification macros > ************************************************************************/ >#define ScheduleRetryProcess(pChan) do { \ > pChan->retry_timer->expires = jiffies + 10; \ > add_timer(pChan->retry_timer); \ > } while (0) > >#define CancelRetryProcess(pChan) del_timer(pChan->retry_timer) > >#define GetStatus(pChan, Status) \ > Status = inb(pChan->io_ports[IDE_CONTROL_OFFSET]); > >#define GetBaseStatus(pChan, Status) \ > Status = inb(pChan->io_ports[IDE_COMMAND_OFFSET]); > >#define GetError(pChan, Error) \ > Error = inb(pChan->io_ports[IDE_ERROR_OFFSET]); > >#define ReadBuffer(pChan, Buffer, Count) \ > insw(pChan->io_ports[IDE_DATA_OFFSET], Buffer, Count); > >#define WriteCommand(BaseIoAddress, Command) \ > outb(pChan->io_ports[IDE_COMMAND_OFFSET], Command); > >#define WriteBuffer(pChan, Buffer, Count) \ > outsw(pChan->io_ports[IDE_DATA_OFFSET], Buffer, Count); > >#define WaitOnBusy(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 20000; i++) \ > { \ > GetStatus(pChan, Status); \ > if (Status & IDE_STATUS_BUSY) \ > { \ > udelay(150); \ > continue; \ > } \ > else \ > { \ > break; \ > } \ > } \ >} > >#define WaitOnBaseBusy(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 20000; i++) \ > { \ > GetBaseStatus(pChan, Status); \ > if (Status & IDE_STATUS_BUSY) \ > { \ > udelay(150); \ > continue; \ > } \ > else \ > { \ > break; \ > } \ > } \ >} > >#define WaitForDrq(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 1000; i++) \ > { \ > GetStatus(pChan, Status); \ > if (Status & IDE_STATUS_BUSY) \ > { \ > udelay(100); \ > } \ > else if (Status & IDE_STATUS_DRQ) \ > { \ > break; \ > } \ > else \ > { \ > udelay(200); \ > } \ > } \ >} > >#define WaitForBaseDrq(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 50000; i++) \ > { \ > GetBaseStatus(pChan, Status); \ > if (Status & IDE_STATUS_BUSY) \ > { \ > udelay(100); \ > } \ > else if (Status & IDE_STATUS_DRQ) \ > { \ > break; \ > } \ > else \ > { \ > udelay(200); \ > } \ > } \ >} > >#define CheckBusyDrq(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 50000; i++) \ > { \ > GetBaseStatus(pChan, Status); \ > if ((Status & IDE_STATUS_BUSY) || \ > !(Status & IDE_STATUS_DRQ)) \ > { \ > udelay(200); \ > } \ > else \ > { \ > break; \ > } \ > } \ >} > >#define WaitShortForDrq(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 2; i++) \ > { \ > GetStatus(pChan, Status); \ > if (Status & IDE_STATUS_BUSY) \ > { \ > udelay(100); \ > } \ > else if (Status & IDE_STATUS_DRQ) \ > { \ > break; \ > } \ > else \ > { \ > udelay(100); \ > } \ > } \ >} > >#define WaitForDeviceReady(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 50000; i++) \ > { \ > GetStatus(pChan, Status); \ > if (Status == 0) \ > { \ > break; \ > } \ > if ((Status & IDE_STATUS_BUSY) || (Status & IDE_STATUS_DRQ)) \ > { \ > udelay(200); \ > continue; \ > } \ > else \ > { \ > break; \ > } \ > } \ >} > >#define WaitForCommandComplete(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 50000; i++) \ > { \ > GetStatus(pChan, Status); \ > if ((Status == 0) || (Status & IDE_STATUS_ERROR) \ > || (Status == IDE_STATUS_IDLE)) \ > { \ > break; \ > } \ > udelay(200); \ > continue; \ > } \ >} > >#define WaitForBaseCommandComplete(pChan, Status) \ >{ \ > int i; \ > for (i = 0; i < 50000; i++) \ > { \ > GetBaseStatus(pChan, Status); \ > if ((Status == 0) || (Status & IDE_STATUS_ERROR) \ > || (Status == IDE_STATUS_IDLE)) \ > { \ > break; \ > } \ > udelay(200); \ > continue; \ > } \ >} > >#define AtapiSoftReset(pChan, DevNum) \ >{ \ > unsigned char statusByte; \ > outb((unsigned char)(((DevNum & 0x1) << 4) | 0xA0), pChan->io_ports[IDE_SELECT_OFFSET]); \ > udelay(500); \ > outb(IDE_COMMAND_ATAPI_RESET, pChan->io_ports[IDE_COMMAND_OFFSET]); \ > mdelay(1000); \ > outb((unsigned char)(((DevNum & 0x1) << 4) | 0xA0), pChan->io_ports[IDE_SELECT_OFFSET]); \ > WaitOnBusy(pChan, statusByte); \ > udelay(500); \ >} > >#define IdeHardReset(pChan, result) \ >{ \ > unsigned char statusByte; \ > int i; \ > outb(IDE_DC_RESET_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]); \ > mdelay(50); \ > outb(IDE_DC_REENABLE_CONTROLLER, pChan->io_ports[IDE_CONTROL_OFFSET]); \ > for (i = 0; i < 1000 * 1000; i++) \ > { \ > statusByte = inb(pChan->io_ports[IDE_CONTROL_OFFSET]); \ > if (statusByte != IDE_STATUS_IDLE && statusByte != 0x0) \ > { \ > udelay(30); \ > } \ > else \ > { \ > break; \ > } \ > } \ > if (i == 1000 * 1000) \ > { \ > printk("IdeHardReset Fail!\n"); \ > result = FALSE; \ > } \ > else \ > { \ > dprintk("IdeHardReset Success!\n"); \ > result = TRUE; \ > } \ >} > >/************************************************************************ > * Function prototypes > ************************************************************************/ >const char * iteraid_info (struct Scsi_Host *); >int iteraid_detect (Scsi_Host_Template *); >int iteraid_release (struct Scsi_Host *); >int iteraid_command (Scsi_Cmnd *); >int iteraid_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); >int iteraid_biosparam (struct scsi_device *, struct block_device *, sector_t , int *); >int iteraid_proc_info (struct Scsi_Host *, char *buffer, char **start, off_t offset, > int length, int inout); > >static void TaskStart(PChannel, Scsi_Cmnd *); >static void TaskQueue(void); >static void TaskDone(PChannel, PSCSI_REQUEST_BLOCK); >static u32 IdeSendCommand(PChannel, PSCSI_REQUEST_BLOCK); >static void IdeMediaStatus(u8, PChannel, u8); >static void IdeSetupDma(PChannel, unsigned long, unsigned short); >static void MapRequest(Scsi_Cmnd *, PSCSI_REQUEST_BLOCK); >static u8 IssueIdentify(PChannel, u8, u8); >static u8 IT8212ResetAdapter(PITE_ADAPTER); >static void AtapiStartIo(PChannel, PSCSI_REQUEST_BLOCK); >static u8 AtapiInterrupt(PChannel); >static void AtapiResetController(PITE_ADAPTER pAdap, PChannel pChan); > >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 *); > >#endif /* #ifndef _ITERAID_H_ */ > > > > >MAKEFILE > > > > >KERNEL_SRC = /usr/src/linux-2.6.1 > >EXTRA_FLAGS += -I. > >EXTRA_FLAGS += -Wno-cast-qual -Wno-strict-prototypes > >obj-m += iteraid.o > >iteraid-obj := iteraid.o > >modules: > $(MAKE) -C $(KERNEL_SRC) SUBDIRS=$(PWD) modules > >clean: > rm -rf iteraid.o iteraid.ko iteraid.mod.o iteraid.mod.c *~ > > >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
|
Diff
Attachments on
bug 136944
:
60437
|
60577
|
61131
|
61950
| 61959 |
63609
|
65070