-/* Search IOC page 3 to determine if this is hidden physical disk
- */
-static int
-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
-{
- int i;
-
- if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
- return 0;
-
- for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
- if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
- return 1;
- }
-
- return 0;
-}
-
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mptscsih_domainValidation - Top level handler for domain validation.
- * @hd: Pointer to MPT_SCSI_HOST structure.
- *
- * Uses the ISR, but with special processing.
- * Called from schedule, should not be in interrupt mode.
- * While thread alive, do dv for all devices needing dv
- *
- * Return: None.
- */
-static void
-mptscsih_domainValidation(void *arg)
-{
- MPT_SCSI_HOST *hd;
- MPT_ADAPTER *ioc;
- unsigned long flags;
- int id, maxid, dvStatus, did;
- int ii, isPhysDisk;
-
- spin_lock_irqsave(&dvtaskQ_lock, flags);
- dvtaskQ_active = 1;
- if (dvtaskQ_release) {
- dvtaskQ_active = 0;
- spin_unlock_irqrestore(&dvtaskQ_lock, flags);
- return;
- }
- spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
- /* For this ioc, loop through all devices and do dv to each device.
- * When complete with this ioc, search through the ioc list, and
- * for each scsi ioc found, do dv for all devices. Exit when no
- * device needs dv.
- */
- did = 1;
- while (did) {
- did = 0;
- list_for_each_entry(ioc, &ioc_list, list) {
- spin_lock_irqsave(&dvtaskQ_lock, flags);
- if (dvtaskQ_release) {
- dvtaskQ_active = 0;
- spin_unlock_irqrestore(&dvtaskQ_lock, flags);
- return;
- }
- spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
- msleep(250);
-
- /* DV only to SPI adapters */
- if (ioc->bus_type != SPI)
- continue;
-
- /* Make sure everything looks ok */
- if (ioc->sh == NULL)
- continue;
-
- hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
- if (hd == NULL)
- continue;
-
- if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
- mpt_read_ioc_pg_3(ioc);
- if (ioc->raid_data.pIocPg3) {
- Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
- int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
- while (numPDisk) {
- if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
- ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
-
- pPDisk++;
- numPDisk--;
- }
- }
- ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
- }
-
- maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
-
- for (id = 0; id < maxid; id++) {
- spin_lock_irqsave(&dvtaskQ_lock, flags);
- if (dvtaskQ_release) {
- dvtaskQ_active = 0;
- spin_unlock_irqrestore(&dvtaskQ_lock, flags);
- return;
- }
- spin_unlock_irqrestore(&dvtaskQ_lock, flags);
- dvStatus = hd->ioc->spi_data.dvStatus[id];
-
- if (dvStatus & MPT_SCSICFG_NEED_DV) {
- did++;
- hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
- hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
-
- msleep(250);
-
- /* If hidden phys disk, block IO's to all
- * raid volumes
- * else, process normally
- */
- isPhysDisk = mptscsih_is_phys_disk(ioc, id);
- if (isPhysDisk) {
- for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
- if (hd->ioc->raid_data.isRaid & (1 << ii)) {
- hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
- }
- }
- }
-
- if(mpt_alt_ioc_wait(hd->ioc)!=0) {
- ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
- hd->ioc->name));
- continue;
- }
-
- if (mptscsih_doDv(hd, 0, id) == 1) {
- /* Untagged device was busy, try again
- */
- hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
- hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
- } else {
- /* DV is complete. Clear flags.
- */
- hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
- }
-
- spin_lock(&hd->ioc->initializing_hba_lock);
- hd->ioc->initializing_hba_lock_flag=0;
- spin_unlock(&hd->ioc->initializing_hba_lock);
-
- if (isPhysDisk) {
- for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
- if (hd->ioc->raid_data.isRaid & (1 << ii)) {
- hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
- }
- }
- }
-
- if (hd->ioc->spi_data.noQas)
- mptscsih_qas_check(hd, id);
- }
- }
- }
- }
-
- spin_lock_irqsave(&dvtaskQ_lock, flags);
- dvtaskQ_active = 0;
- spin_unlock_irqrestore(&dvtaskQ_lock, flags);
-
- return;
-}
-
-/* Write SDP1 if no QAS has been enabled
- */
-static void
-mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
-{
- VirtTarget *vtarget;
- int ii;
-
- if (hd->Targets == NULL)
- return;
-
- for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
- if (ii == id)
- continue;
-
- if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
- continue;
-
- vtarget = hd->Targets[ii];
-
- if ((vtarget != NULL) && (!vtarget->raidVolume)) {
- if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
- vtarget->negoFlags |= hd->ioc->spi_data.noQas;
- dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
- mptscsih_writeSDP1(hd, 0, ii, 0);
- }
- } else {
- if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
- dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
- mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
- }
- }
- }
- return;
-}
-
-
-
-#define MPT_GET_NVRAM_VALS 0x01
-#define MPT_UPDATE_MAX 0x02
-#define MPT_SET_MAX 0x04
-#define MPT_SET_MIN 0x08
-#define MPT_FALLBACK 0x10
-#define MPT_SAVE 0x20
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mptscsih_doDv - Perform domain validation to a target.
- * @hd: Pointer to MPT_SCSI_HOST structure.
- * @portnum: IOC port number.
- * @target: Physical ID of this target
- *
- * Uses the ISR, but with special processing.
- * MUST be single-threaded.
- * Test will exit if target is at async & narrow.
- *
- * Return: None.
- */
-static int
-mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
-{
- MPT_ADAPTER *ioc = hd->ioc;
- VirtTarget *vtarget;
- SCSIDevicePage1_t *pcfg1Data;
- SCSIDevicePage0_t *pcfg0Data;
- u8 *pbuf1;
- u8 *pbuf2;
- u8 *pDvBuf;
- dma_addr_t dvbuf_dma = -1;
- dma_addr_t buf1_dma = -1;
- dma_addr_t buf2_dma = -1;
- dma_addr_t cfg1_dma_addr = -1;
- dma_addr_t cfg0_dma_addr = -1;
- ConfigPageHeader_t header1;
- ConfigPageHeader_t header0;
- DVPARAMETERS dv;
- INTERNAL_CMD iocmd;
- CONFIGPARMS cfg;
- int dv_alloc = 0;
- int rc, sz = 0;
- int bufsize = 0;
- int dataBufSize = 0;
- int echoBufSize = 0;
- int notDone;
- int patt;
- int repeat;
- int retcode = 0;
- int nfactor = MPT_ULTRA320;
- char firstPass = 1;
- char doFallback = 0;
- char readPage0;
- char bus, lun;
- char inq0 = 0;
-
- if (ioc->spi_data.sdp1length == 0)
- return 0;
-
- if (ioc->spi_data.sdp0length == 0)
- return 0;
-
- /* If multiple buses are used, require that the initiator
- * id be the same on all buses.
- */
- if (id == ioc->pfacts[0].PortSCSIID)
- return 0;
-
- lun = 0;
- bus = (u8) bus_number;
- ddvtprintk((MYIOC_s_NOTE_FMT
- "DV started: bus=%d, id=%d dv @ %p\n",
- ioc->name, bus, id, &dv));
-
- /* Prep DV structure
- */
- memset (&dv, 0, sizeof(DVPARAMETERS));
- dv.id = id;
-
- /* Populate tmax with the current maximum
- * transfer parameters for this target.
- * Exit if narrow and async.
- */
- dv.cmd = MPT_GET_NVRAM_VALS;
- mptscsih_dv_parms(hd, &dv, NULL);
-
- /* Prep SCSI IO structure
- */
- iocmd.id = id;
- iocmd.bus = bus;
- iocmd.lun = lun;
- iocmd.flags = 0;
- iocmd.physDiskNum = -1;
- iocmd.rsvd = iocmd.rsvd2 = 0;
-
- vtarget = hd->Targets[id];
-
- /* Use tagged commands if possible.
- */
- if (vtarget) {
- if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
- iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
- else {
- if (hd->ioc->facts.FWVersion.Word < 0x01000600)
- return 0;
-
- if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
- (hd->ioc->facts.FWVersion.Word < 0x01010B00))
- return 0;
- }
- }
-
- /* Prep cfg structure
- */
- cfg.pageAddr = (bus<<8) | id;
- cfg.cfghdr.hdr = NULL;
-
- /* Prep SDP0 header
- */
- header0.PageVersion = ioc->spi_data.sdp0version;
- header0.PageLength = ioc->spi_data.sdp0length;
- header0.PageNumber = 0;
- header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-
- /* Prep SDP1 header
- */
- header1.PageVersion = ioc->spi_data.sdp1version;
- header1.PageLength = ioc->spi_data.sdp1length;
- header1.PageNumber = 1;
- header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-
- if (header0.PageLength & 1)
- dv_alloc = (header0.PageLength * 4) + 4;
-
- dv_alloc += (2048 + (header1.PageLength * 4));
-
- pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
- if (pDvBuf == NULL)
- return 0;
-
- sz = 0;
- pbuf1 = (u8 *)pDvBuf;
- buf1_dma = dvbuf_dma;
- sz +=1024;
-
- pbuf2 = (u8 *) (pDvBuf + sz);
- buf2_dma = dvbuf_dma + sz;
- sz +=1024;
-
- pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
- cfg0_dma_addr = dvbuf_dma + sz;
- sz += header0.PageLength * 4;
-
- /* 8-byte alignment
- */
- if (header0.PageLength & 1)
- sz += 4;
-
- pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
- cfg1_dma_addr = dvbuf_dma + sz;
-
- /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
- */
- {
- SpiCfgData *pspi_data = &hd->ioc->spi_data;
- if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
- /* Set the factor from nvram */
- nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
- if (nfactor < pspi_data->minSyncFactor )
- nfactor = pspi_data->minSyncFactor;
-
- if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
- (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
-
- ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
- ioc->name, bus, id, lun));
-
- dv.cmd = MPT_SET_MAX;
- mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
- cfg.cfghdr.hdr = &header1;
-
- /* Save the final negotiated settings to
- * SCSI device page 1.
- */
- cfg.physAddr = cfg1_dma_addr;
- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- cfg.dir = 1;
- mpt_config(hd->ioc, &cfg);
- goto target_done;
- }
- }
- }
-
- /* Finish iocmd inititialization - hidden or visible disk? */
- if (ioc->raid_data.pIocPg3) {
- /* Search IOC page 3 for matching id
- */
- Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
- int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
- while (numPDisk) {
- if (pPDisk->PhysDiskID == id) {
- /* match */
- iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
- iocmd.physDiskNum = pPDisk->PhysDiskNum;
-
- /* Quiesce the IM
- */
- if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
- ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
- goto target_done;
- }
- break;
- }
- pPDisk++;
- numPDisk--;
- }
- }
-
- /* RAID Volume ID's may double for a physical device. If RAID but
- * not a physical ID as well, skip DV.
- */
- if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
- goto target_done;
-
-
- /* Basic Test.
- * Async & Narrow - Inquiry
- * Async & Narrow - Inquiry
- * Maximum transfer rate - Inquiry
- * Compare buffers:
- * If compare, test complete.
- * If miscompare and first pass, repeat
- * If miscompare and not first pass, fall back and repeat
- */
- hd->pLocal = NULL;
- readPage0 = 0;
- sz = SCSI_MAX_INQUIRY_BYTES;
- rc = MPT_SCANDV_GOOD;
- while (1) {
- ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
- retcode = 0;
- dv.cmd = MPT_SET_MIN;
- mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
- cfg.cfghdr.hdr = &header1;
- cfg.physAddr = cfg1_dma_addr;
- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- cfg.dir = 1;
- if (mpt_config(hd->ioc, &cfg) != 0)
- goto target_done;
-
- /* Wide - narrow - wide workaround case
- */
- if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
- /* Send an untagged command to reset disk Qs corrupted
- * when a parity error occurs on a Request Sense.
- */
- if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
- ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
- (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
-
- iocmd.cmd = REQUEST_SENSE;
- iocmd.data_dma = buf1_dma;
- iocmd.data = pbuf1;
- iocmd.size = 0x12;
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
- else {
- if (hd->pLocal == NULL)
- goto target_done;
- rc = hd->pLocal->completion;
- if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
- dv.max.width = 0;
- doFallback = 0;
- } else
- goto target_done;
- }
- } else
- goto target_done;
- }
-
- iocmd.cmd = INQUIRY;
- iocmd.data_dma = buf1_dma;
- iocmd.data = pbuf1;
- iocmd.size = sz;
- memset(pbuf1, 0x00, sz);
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
- else {
- if (hd->pLocal == NULL)
- goto target_done;
- rc = hd->pLocal->completion;
- if (rc == MPT_SCANDV_GOOD) {
- if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
- if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
- retcode = 1;
- else
- retcode = 0;
-
- goto target_done;
- }
- } else if (rc == MPT_SCANDV_SENSE) {
- ;
- } else {
- /* If first command doesn't complete
- * with a good status or with a check condition,
- * exit.
- */
- goto target_done;
- }
- }
-
- /* Reset the size for disks
- */
- inq0 = (*pbuf1) & 0x1F;
- if ((inq0 == 0) && vtarget && !vtarget->raidVolume) {
- sz = 0x40;
- iocmd.size = sz;
- }
-
- /* Another GEM workaround. Check peripheral device type,
- * if PROCESSOR, quit DV.
- */
- if (inq0 == TYPE_PROCESSOR) {
- mptscsih_initTarget(hd,
- vtarget,
- lun,
- pbuf1,
- sz);
- goto target_done;
- }
-
- if (inq0 > 0x08)
- goto target_done;
-
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
-
- if (sz == 0x40) {
- if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A)
- && (vtarget->minSyncFactor > 0x09)) {
- if ((pbuf1[56] & 0x04) == 0)
- ;
- else if ((pbuf1[56] & 0x01) == 1) {
- vtarget->minSyncFactor =
- nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
- } else {
- vtarget->minSyncFactor =
- nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
- }
-
- dv.max.factor = vtarget->minSyncFactor;
-
- if ((pbuf1[56] & 0x02) == 0) {
- vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
- hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
- ddvprintk((MYIOC_s_NOTE_FMT
- "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
- ioc->name, id, pbuf1[56]));
- }
- }
- }
-
- if (doFallback)
- dv.cmd = MPT_FALLBACK;
- else
- dv.cmd = MPT_SET_MAX;
-
- mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
- if (mpt_config(hd->ioc, &cfg) != 0)
- goto target_done;
-
- if ((!dv.now.width) && (!dv.now.offset))
- goto target_done;
-
- iocmd.cmd = INQUIRY;
- iocmd.data_dma = buf2_dma;
- iocmd.data = pbuf2;
- iocmd.size = sz;
- memset(pbuf2, 0x00, sz);
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
- else if (hd->pLocal == NULL)
- goto target_done;
- else {
- /* Save the return code.
- * If this is the first pass,
- * read SCSI Device Page 0
- * and update the target max parameters.
- */
- rc = hd->pLocal->completion;
- doFallback = 0;
- if (rc == MPT_SCANDV_GOOD) {
- if (!readPage0) {
- u32 sdp0_info;
- u32 sdp0_nego;
-
- cfg.cfghdr.hdr = &header0;
- cfg.physAddr = cfg0_dma_addr;
- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
- cfg.dir = 0;
-
- if (mpt_config(hd->ioc, &cfg) != 0)
- goto target_done;
-
- sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
- sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
-
- /* Quantum and Fujitsu workarounds.
- * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
- * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
- * Resetart with a request for U160.
- */
- if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
- doFallback = 1;
- } else {
- dv.cmd = MPT_UPDATE_MAX;
- mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
- /* Update the SCSI device page 1 area
- */
- pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
- readPage0 = 1;
- }
- }
-
- /* Quantum workaround. Restart this test will the fallback
- * flag set.
- */
- if (doFallback == 0) {
- if (memcmp(pbuf1, pbuf2, sz) != 0) {
- if (!firstPass)
- doFallback = 1;
- } else {
- ddvprintk((MYIOC_s_NOTE_FMT
- "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
- hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
- mptscsih_initTarget(hd,
- vtarget,
- lun,
- pbuf1,
- sz);
- break; /* test complete */
- }
- }
-
-
- } else if (rc == MPT_SCANDV_ISSUE_SENSE)
- doFallback = 1; /* set fallback flag */
- else if ((rc == MPT_SCANDV_DID_RESET) ||
- (rc == MPT_SCANDV_SENSE) ||
- (rc == MPT_SCANDV_FALLBACK))
- doFallback = 1; /* set fallback flag */
- else
- goto target_done;
-
- firstPass = 0;
- }
- }
- ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
-
- if (ioc->spi_data.mpt_dv == 0)
- goto target_done;
-
- inq0 = (*pbuf1) & 0x1F;
-
- /* Continue only for disks
- */
- if (inq0 != 0)
- goto target_done;
-
- if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
- goto target_done;
-
- /* Start the Enhanced Test.
- * 0) issue TUR to clear out check conditions
- * 1) read capacity of echo (regular) buffer
- * 2) reserve device
- * 3) do write-read-compare data pattern test
- * 4) release
- * 5) update nego parms to target struct
- */
- cfg.cfghdr.hdr = &header1;
- cfg.physAddr = cfg1_dma_addr;
- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- cfg.dir = 1;
-
- iocmd.cmd = TEST_UNIT_READY;
- iocmd.data_dma = -1;
- iocmd.data = NULL;
- iocmd.size = 0;
- notDone = 1;
- while (notDone) {
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
-
- if (hd->pLocal == NULL)
- goto target_done;
-
- rc = hd->pLocal->completion;
- if (rc == MPT_SCANDV_GOOD)
- notDone = 0;
- else if (rc == MPT_SCANDV_SENSE) {
- u8 skey = hd->pLocal->sense[2] & 0x0F;
- u8 asc = hd->pLocal->sense[12];
- u8 ascq = hd->pLocal->sense[13];
- ddvprintk((MYIOC_s_INFO_FMT
- "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
- ioc->name, skey, asc, ascq));
-
- if (skey == UNIT_ATTENTION)
- notDone++; /* repeat */
- else if ((skey == NOT_READY) &&
- (asc == 0x04)&&(ascq == 0x01)) {
- /* wait then repeat */
- mdelay (2000);
- notDone++;
- } else if ((skey == NOT_READY) && (asc == 0x3A)) {
- /* no medium, try read test anyway */
- notDone = 0;
- } else {
- /* All other errors are fatal.
- */
- ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
- ioc->name));
- goto target_done;
- }
- } else
- goto target_done;
- }
-
- iocmd.cmd = READ_BUFFER;
- iocmd.data_dma = buf1_dma;
- iocmd.data = pbuf1;
- iocmd.size = 4;
- iocmd.flags |= MPT_ICFLAG_BUF_CAP;
-
- dataBufSize = 0;
- echoBufSize = 0;
- for (patt = 0; patt < 2; patt++) {
- if (patt == 0)
- iocmd.flags |= MPT_ICFLAG_ECHO;
- else
- iocmd.flags &= ~MPT_ICFLAG_ECHO;
-
- notDone = 1;
- while (notDone) {
- bufsize = 0;
-
- /* If not ready after 8 trials,
- * give up on this device.
- */
- if (notDone > 8)
- goto target_done;
-
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
- else if (hd->pLocal == NULL)
- goto target_done;
- else {
- rc = hd->pLocal->completion;
- ddvprintk(("ReadBuffer Comp Code %d", rc));
- ddvprintk((" buff: %0x %0x %0x %0x\n",
- pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
-
- if (rc == MPT_SCANDV_GOOD) {
- notDone = 0;
- if (iocmd.flags & MPT_ICFLAG_ECHO) {
- bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
- if (pbuf1[0] & 0x01)
- iocmd.flags |= MPT_ICFLAG_EBOS;
- } else {
- bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
- }
- } else if (rc == MPT_SCANDV_SENSE) {
- u8 skey = hd->pLocal->sense[2] & 0x0F;
- u8 asc = hd->pLocal->sense[12];
- u8 ascq = hd->pLocal->sense[13];
- ddvprintk((MYIOC_s_INFO_FMT
- "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
- ioc->name, skey, asc, ascq));
- if (skey == ILLEGAL_REQUEST) {
- notDone = 0;
- } else if (skey == UNIT_ATTENTION) {
- notDone++; /* repeat */
- } else if ((skey == NOT_READY) &&
- (asc == 0x04)&&(ascq == 0x01)) {
- /* wait then repeat */
- mdelay (2000);
- notDone++;
- } else {
- /* All other errors are fatal.
- */
- ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
- ioc->name));
- goto target_done;
- }
- } else {
- /* All other errors are fatal
- */
- goto target_done;
- }
- }
- }
-
- if (iocmd.flags & MPT_ICFLAG_ECHO)
- echoBufSize = bufsize;
- else
- dataBufSize = bufsize;
- }
- sz = 0;
- iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
-
- /* Use echo buffers if possible,
- * Exit if both buffers are 0.
- */
- if (echoBufSize > 0) {
- iocmd.flags |= MPT_ICFLAG_ECHO;
- if (dataBufSize > 0)
- bufsize = min(echoBufSize, dataBufSize);
- else
- bufsize = echoBufSize;
- } else if (dataBufSize == 0)
- goto target_done;
-
- ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
- (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
-
- /* Data buffers for write-read-compare test max 1K.
- */
- sz = min(bufsize, 1024);
-
- /* --- loop ----
- * On first pass, always issue a reserve.
- * On additional loops, only if a reset has occurred.
- * iocmd.flags indicates if echo or regular buffer
- */
- for (patt = 0; patt < 4; patt++) {
- ddvprintk(("Pattern %d\n", patt));
- if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
- iocmd.cmd = TEST_UNIT_READY;
- iocmd.data_dma = -1;
- iocmd.data = NULL;
- iocmd.size = 0;
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
-
- iocmd.cmd = RELEASE;
- iocmd.data_dma = -1;
- iocmd.data = NULL;
- iocmd.size = 0;
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
- else if (hd->pLocal == NULL)
- goto target_done;
- else {
- rc = hd->pLocal->completion;
- ddvprintk(("Release rc %d\n", rc));
- if (rc == MPT_SCANDV_GOOD)
- iocmd.flags &= ~MPT_ICFLAG_RESERVED;
- else
- goto target_done;
- }
- iocmd.flags &= ~MPT_ICFLAG_RESERVED;
- }
- iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
-
- if (iocmd.flags & MPT_ICFLAG_EBOS)
- goto skip_Reserve;
-
- repeat = 5;
- while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
- iocmd.cmd = RESERVE;
- iocmd.data_dma = -1;
- iocmd.data = NULL;
- iocmd.size = 0;
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
- else if (hd->pLocal == NULL)
- goto target_done;
- else {
- rc = hd->pLocal->completion;
- if (rc == MPT_SCANDV_GOOD) {
- iocmd.flags |= MPT_ICFLAG_RESERVED;
- } else if (rc == MPT_SCANDV_SENSE) {
- /* Wait if coming ready
- */
- u8 skey = hd->pLocal->sense[2] & 0x0F;
- u8 asc = hd->pLocal->sense[12];
- u8 ascq = hd->pLocal->sense[13];
- ddvprintk((MYIOC_s_INFO_FMT
- "DV: Reserve Failed: ", ioc->name));
- ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
- skey, asc, ascq));
-
- if ((skey == NOT_READY) && (asc == 0x04)&&
- (ascq == 0x01)) {
- /* wait then repeat */
- mdelay (2000);
- notDone++;
- } else {
- ddvprintk((MYIOC_s_INFO_FMT
- "DV: Reserved Failed.", ioc->name));
- goto target_done;
- }
- } else {
- ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
- ioc->name));
- goto target_done;
- }
- }
- }
-
-skip_Reserve:
- mptscsih_fillbuf(pbuf1, sz, patt, 1);
- iocmd.cmd = WRITE_BUFFER;
- iocmd.data_dma = buf1_dma;
- iocmd.data = pbuf1;
- iocmd.size = sz;
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
- else if (hd->pLocal == NULL)
- goto target_done;
- else {
- rc = hd->pLocal->completion;
- if (rc == MPT_SCANDV_GOOD)
- ; /* Issue read buffer */
- else if (rc == MPT_SCANDV_DID_RESET) {
- /* If using echo buffers, reset to data buffers.
- * Else do Fallback and restart
- * this test (re-issue reserve
- * because of bus reset).
- */
- if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
- iocmd.flags &= ~MPT_ICFLAG_ECHO;
- } else {
- dv.cmd = MPT_FALLBACK;
- mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
- if (mpt_config(hd->ioc, &cfg) != 0)
- goto target_done;
-
- if ((!dv.now.width) && (!dv.now.offset))
- goto target_done;
- }
-
- iocmd.flags |= MPT_ICFLAG_DID_RESET;
- patt = -1;
- continue;
- } else if (rc == MPT_SCANDV_SENSE) {
- /* Restart data test if UA, else quit.
- */
- u8 skey = hd->pLocal->sense[2] & 0x0F;
- ddvprintk((MYIOC_s_INFO_FMT
- "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
- hd->pLocal->sense[12], hd->pLocal->sense[13]));
- if (skey == UNIT_ATTENTION) {
- patt = -1;
- continue;
- } else if (skey == ILLEGAL_REQUEST) {
- if (iocmd.flags & MPT_ICFLAG_ECHO) {
- if (dataBufSize >= bufsize) {
- iocmd.flags &= ~MPT_ICFLAG_ECHO;
- patt = -1;
- continue;
- }
- }
- goto target_done;
- }
- else
- goto target_done;
- } else {
- /* fatal error */
- goto target_done;
- }
- }
-
- iocmd.cmd = READ_BUFFER;
- iocmd.data_dma = buf2_dma;
- iocmd.data = pbuf2;
- iocmd.size = sz;
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- goto target_done;
- else if (hd->pLocal == NULL)
- goto target_done;
- else {
- rc = hd->pLocal->completion;
- if (rc == MPT_SCANDV_GOOD) {
- /* If buffers compare,
- * go to next pattern,
- * else, do a fallback and restart
- * data transfer test.
- */
- if (memcmp (pbuf1, pbuf2, sz) == 0) {
- ; /* goto next pattern */
- } else {
- /* Miscompare with Echo buffer, go to data buffer,
- * if that buffer exists.
- * Miscompare with Data buffer, check first 4 bytes,
- * some devices return capacity. Exit in this case.
- */
- if (iocmd.flags & MPT_ICFLAG_ECHO) {
- if (dataBufSize >= bufsize)
- iocmd.flags &= ~MPT_ICFLAG_ECHO;
- else
- goto target_done;
- } else {
- if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
- /* Argh. Device returning wrong data.
- * Quit DV for this device.
- */
- goto target_done;
- }
-
- /* Had an actual miscompare. Slow down.*/
- dv.cmd = MPT_FALLBACK;
- mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
- if (mpt_config(hd->ioc, &cfg) != 0)
- goto target_done;
-
- if ((!dv.now.width) && (!dv.now.offset))
- goto target_done;
- }
-
- patt = -1;
- continue;
- }
- } else if (rc == MPT_SCANDV_DID_RESET) {
- /* Do Fallback and restart
- * this test (re-issue reserve
- * because of bus reset).
- */
- dv.cmd = MPT_FALLBACK;
- mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
- if (mpt_config(hd->ioc, &cfg) != 0)
- goto target_done;
-
- if ((!dv.now.width) && (!dv.now.offset))
- goto target_done;
-
- iocmd.flags |= MPT_ICFLAG_DID_RESET;
- patt = -1;
- continue;
- } else if (rc == MPT_SCANDV_SENSE) {
- /* Restart data test if UA, else quit.
- */
- u8 skey = hd->pLocal->sense[2] & 0x0F;
- ddvprintk((MYIOC_s_INFO_FMT
- "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
- hd->pLocal->sense[12], hd->pLocal->sense[13]));
- if (skey == UNIT_ATTENTION) {
- patt = -1;
- continue;
- }
- else
- goto target_done;
- } else {
- /* fatal error */
- goto target_done;
- }
- }
-
- } /* --- end of patt loop ---- */
-
-target_done:
- if (iocmd.flags & MPT_ICFLAG_RESERVED) {
- iocmd.cmd = RELEASE;
- iocmd.data_dma = -1;
- iocmd.data = NULL;
- iocmd.size = 0;
- if (mptscsih_do_cmd(hd, &iocmd) < 0)
- printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
- ioc->name, id);
- else if (hd->pLocal) {
- if (hd->pLocal->completion == MPT_SCANDV_GOOD)
- iocmd.flags &= ~MPT_ICFLAG_RESERVED;
- } else {
- printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
- ioc->name, id);
- }
- }
-
-
- /* Set if cfg1_dma_addr contents is valid
- */
- if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
- /* If disk, not U320, disable QAS
- */
- if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
- hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
- ddvprintk((MYIOC_s_NOTE_FMT
- "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
- }
-
- dv.cmd = MPT_SAVE;
- mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
-
- /* Double writes to SDP1 can cause problems,
- * skip save of the final negotiated settings to
- * SCSI device page 1.
- *
- cfg.cfghdr.hdr = &header1;
- cfg.physAddr = cfg1_dma_addr;
- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- cfg.dir = 1;
- mpt_config(hd->ioc, &cfg);
- */
- }
-
- /* If this is a RAID Passthrough, enable internal IOs
- */
- if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
- if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
- ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
- }
-
- /* Done with the DV scan of the current target
- */
- if (pDvBuf)
- pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
-
- ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
- ioc->name, id));
-
- return retcode;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptscsih_dv_parms - perform a variety of operations on the
- * parameters used for negotiation.
- * @hd: Pointer to a SCSI host.
- * @dv: Pointer to a structure that contains the maximum and current
- * negotiated parameters.
- */
-static void
-mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
-{
- VirtTarget *vtarget;
- SCSIDevicePage0_t *pPage0;
- SCSIDevicePage1_t *pPage1;
- int val = 0, data, configuration;
- u8 width = 0;
- u8 offset = 0;
- u8 factor = 0;
- u8 negoFlags = 0;
- u8 cmd = dv->cmd;
- u8 id = dv->id;
-
- switch (cmd) {
- case MPT_GET_NVRAM_VALS:
- ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
- hd->ioc->name));
- /* Get the NVRAM values and save in tmax
- * If not an LVD bus, the adapter minSyncFactor has been
- * already throttled back.
- */
- negoFlags = hd->ioc->spi_data.noQas;
- if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) {
- width = vtarget->maxWidth;
- offset = vtarget->maxOffset;
- factor = vtarget->minSyncFactor;
- negoFlags |= vtarget->negoFlags;
- } else {
- if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
- data = hd->ioc->spi_data.nvram[id];
- width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
- if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
- factor = MPT_ASYNC;
- else {
- factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
- if ((factor == 0) || (factor == MPT_ASYNC)){
- factor = MPT_ASYNC;
- offset = 0;
- }
- }
- } else {
- width = MPT_NARROW;
- offset = 0;
- factor = MPT_ASYNC;
- }
-
- /* Set the negotiation flags */
- if (!width)
- negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
-
- if (!offset)
- negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
- }
-
- /* limit by adapter capabilities */
- width = min(width, hd->ioc->spi_data.maxBusWidth);
- offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
- factor = max(factor, hd->ioc->spi_data.minSyncFactor);
-
- /* Check Consistency */
- if (offset && (factor < MPT_ULTRA2) && !width)
- factor = MPT_ULTRA2;
-
- dv->max.width = width;
- dv->max.offset = offset;
- dv->max.factor = factor;
- dv->max.flags = negoFlags;
- ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
- id, width, factor, offset, negoFlags));
- break;
-
- case MPT_UPDATE_MAX:
- ddvprintk((MYIOC_s_NOTE_FMT
- "Updating with SDP0 Data: ", hd->ioc->name));
- /* Update tmax values with those from Device Page 0.*/
- pPage0 = (SCSIDevicePage0_t *) pPage;
- if (pPage0) {
- val = le32_to_cpu(pPage0->NegotiatedParameters);
- dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
- dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
- dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
- }
-
- dv->now.width = dv->max.width;
- dv->now.offset = dv->max.offset;
- dv->now.factor = dv->max.factor;
- ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
- id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
- break;
-
- case MPT_SET_MAX:
- ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
- hd->ioc->name));
- /* Set current to the max values. Update the config page.*/
- dv->now.width = dv->max.width;
- dv->now.offset = dv->max.offset;
- dv->now.factor = dv->max.factor;
- dv->now.flags = dv->max.flags;
-
- pPage1 = (SCSIDevicePage1_t *)pPage;
- if (pPage1) {
- mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
- dv->now.offset, &val, &configuration, dv->now.flags);
- dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
- id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
- pPage1->RequestedParameters = cpu_to_le32(val);
- pPage1->Reserved = 0;
- pPage1->Configuration = cpu_to_le32(configuration);
- }
-
- ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
- id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
- break;
-
- case MPT_SET_MIN:
- ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
- hd->ioc->name));
- /* Set page to asynchronous and narrow
- * Do not update now, breaks fallback routine. */
- width = MPT_NARROW;
- offset = 0;
- factor = MPT_ASYNC;
- negoFlags = dv->max.flags;
-
- pPage1 = (SCSIDevicePage1_t *)pPage;
- if (pPage1) {
- mptscsih_setDevicePage1Flags (width, factor,
- offset, &val, &configuration, negoFlags);
- dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
- id, width, factor, offset, negoFlags, val, configuration));
- pPage1->RequestedParameters = cpu_to_le32(val);
- pPage1->Reserved = 0;
- pPage1->Configuration = cpu_to_le32(configuration);
- }
- ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
- id, width, factor, offset, val, configuration, negoFlags));
- break;
-
- case MPT_FALLBACK:
- ddvprintk((MYIOC_s_NOTE_FMT
- "Fallback: Start: offset %d, factor %x, width %d \n",
- hd->ioc->name, dv->now.offset,
- dv->now.factor, dv->now.width));
- width = dv->now.width;
- offset = dv->now.offset;
- factor = dv->now.factor;
- if ((offset) && (dv->max.width)) {
- if (factor < MPT_ULTRA160)
- factor = MPT_ULTRA160;
- else if (factor < MPT_ULTRA2) {
- factor = MPT_ULTRA2;
- width = MPT_WIDE;
- } else if ((factor == MPT_ULTRA2) && width) {
- factor = MPT_ULTRA2;
- width = MPT_NARROW;
- } else if (factor < MPT_ULTRA) {
- factor = MPT_ULTRA;
- width = MPT_WIDE;
- } else if ((factor == MPT_ULTRA) && width) {
- width = MPT_NARROW;
- } else if (factor < MPT_FAST) {
- factor = MPT_FAST;
- width = MPT_WIDE;
- } else if ((factor == MPT_FAST) && width) {
- factor = MPT_FAST;
- width = MPT_NARROW;
- } else if (factor < MPT_SCSI) {
- factor = MPT_SCSI;
- width = MPT_WIDE;
- } else if ((factor == MPT_SCSI) && width) {
- factor = MPT_SCSI;
- width = MPT_NARROW;
- } else {
- factor = MPT_ASYNC;
- offset = 0;
- }
-
- } else if (offset) {
- width = MPT_NARROW;
- if (factor < MPT_ULTRA)
- factor = MPT_ULTRA;
- else if (factor < MPT_FAST)
- factor = MPT_FAST;
- else if (factor < MPT_SCSI)
- factor = MPT_SCSI;
- else {
- factor = MPT_ASYNC;
- offset = 0;
- }
-
- } else {
- width = MPT_NARROW;
- factor = MPT_ASYNC;
- }
- dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
- dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
-
- dv->now.width = width;
- dv->now.offset = offset;
- dv->now.factor = factor;
- dv->now.flags = dv->max.flags;
-
- pPage1 = (SCSIDevicePage1_t *)pPage;
- if (pPage1) {
- mptscsih_setDevicePage1Flags (width, factor, offset, &val,
- &configuration, dv->now.flags);
- dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
- id, width, offset, factor, dv->now.flags, val, configuration));
-
- pPage1->RequestedParameters = cpu_to_le32(val);
- pPage1->Reserved = 0;
- pPage1->Configuration = cpu_to_le32(configuration);
- }
-
- ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
- id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
- break;
-
- case MPT_SAVE:
- ddvprintk((MYIOC_s_NOTE_FMT
- "Saving to Target structure: ", hd->ioc->name));
- ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
- id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
-
- /* Save these values to target structures
- * or overwrite nvram (phys disks only).
- */
-
- if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) {
- vtarget->maxWidth = dv->now.width;
- vtarget->maxOffset = dv->now.offset;
- vtarget->minSyncFactor = dv->now.factor;
- vtarget->negoFlags = dv->now.flags;
- } else {
- /* Preserv all flags, use
- * read-modify-write algorithm
- */
- if (hd->ioc->spi_data.nvram) {
- data = hd->ioc->spi_data.nvram[id];
-
- if (dv->now.width)
- data &= ~MPT_NVRAM_WIDE_DISABLE;
- else
- data |= MPT_NVRAM_WIDE_DISABLE;
-
- if (!dv->now.offset)
- factor = MPT_ASYNC;
-
- data &= ~MPT_NVRAM_SYNC_MASK;
- data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
-
- hd->ioc->spi_data.nvram[id] = data;
- }
- }
- break;
- }
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptscsih_fillbuf - fill a buffer with a special data pattern
- * cleanup. For bus scan only.
- *
- * @buffer: Pointer to data buffer to be filled.
- * @size: Number of bytes to fill
- * @index: Pattern index
- * @width: bus width, 0 (8 bits) or 1 (16 bits)
- */
-static void
-mptscsih_fillbuf(char *buffer, int size, int index, int width)
-{
- char *ptr = buffer;
- int ii;
- char byte;
- short val;
-
- switch (index) {
- case 0:
-
- if (width) {
- /* Pattern: 0000 FFFF 0000 FFFF
- */
- for (ii=0; ii < size; ii++, ptr++) {
- if (ii & 0x02)
- *ptr = 0xFF;
- else
- *ptr = 0x00;
- }
- } else {
- /* Pattern: 00 FF 00 FF
- */
- for (ii=0; ii < size; ii++, ptr++) {
- if (ii & 0x01)
- *ptr = 0xFF;
- else
- *ptr = 0x00;
- }
- }
- break;
-
- case 1:
- if (width) {
- /* Pattern: 5555 AAAA 5555 AAAA 5555
- */
- for (ii=0; ii < size; ii++, ptr++) {
- if (ii & 0x02)
- *ptr = 0xAA;
- else
- *ptr = 0x55;
- }
- } else {
- /* Pattern: 55 AA 55 AA 55
- */
- for (ii=0; ii < size; ii++, ptr++) {
- if (ii & 0x01)
- *ptr = 0xAA;
- else
- *ptr = 0x55;
- }
- }
- break;
-
- case 2:
- /* Pattern: 00 01 02 03 04 05
- * ... FE FF 00 01..
- */
- for (ii=0; ii < size; ii++, ptr++)
- *ptr = (char) ii;
- break;
-
- case 3:
- if (width) {
- /* Wide Pattern: FFFE 0001 FFFD 0002
- * ... 4000 DFFF 8000 EFFF
- */
- byte = 0;
- for (ii=0; ii < size/2; ii++) {
- /* Create the base pattern
- */
- val = (1 << byte);
- /* every 64 (0x40) bytes flip the pattern
- * since we fill 2 bytes / iteration,
- * test for ii = 0x20
- */
- if (ii & 0x20)
- val = ~(val);
-
- if (ii & 0x01) {
- *ptr = (char)( (val & 0xFF00) >> 8);
- ptr++;
- *ptr = (char)(val & 0xFF);
- byte++;
- byte &= 0x0F;
- } else {
- val = ~val;
- *ptr = (char)( (val & 0xFF00) >> 8);
- ptr++;
- *ptr = (char)(val & 0xFF);
- }
-
- ptr++;
- }
- } else {
- /* Narrow Pattern: FE 01 FD 02 FB 04
- * .. 7F 80 01 FE 02 FD ... 80 7F
- */
- byte = 0;
- for (ii=0; ii < size; ii++, ptr++) {
- /* Base pattern - first 32 bytes
- */
- if (ii & 0x01) {
- *ptr = (1 << byte);
- byte++;
- byte &= 0x07;
- } else {
- *ptr = (char) (~(1 << byte));
- }
-
- /* Flip the pattern every 32 bytes
- */
- if (ii & 0x20)
- *ptr = ~(*ptr);
- }
- }
- break;
- }
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
- * Else set the NEED_DV flag after Read Capacity Issued (disks)
- * or Mode Sense (cdroms).
- *
- * Tapes, initTarget will set this flag on completion of Inquiry command.
- * Called only if DV_NOT_DONE flag is set
- */
-static void
-mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
-{
- MPT_ADAPTER *ioc = hd->ioc;
- u8 cmd;
- SpiCfgData *pSpi;
-
- ddvtprintk((MYIOC_s_NOTE_FMT
- " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
- hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0]));
-
- if ((sc->device->lun != 0) || (hd->negoNvram != 0))
- return;
-
- cmd = sc->cmnd[0];
-
- if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
- pSpi = &ioc->spi_data;
- if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) {
- /* Set NEED_DV for all hidden disks
- */
- Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
- int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
- while (numPDisk) {
- pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
- ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
- pPDisk++;
- numPDisk--;
- }
- }
- pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV;
- ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id));
- }
-}
-
-/* mptscsih_raid_set_dv_flags()
- *
- * New or replaced disk. Set DV flag and schedule DV.
- */
-static void
-mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
-{
- MPT_ADAPTER *ioc = hd->ioc;
- SpiCfgData *pSpi = &ioc->spi_data;
- Ioc3PhysDisk_t *pPDisk;
- int numPDisk;
-
- if (hd->negoNvram != 0)
- return;
-
- ddvtprintk(("DV requested for phys disk id %d\n", id));
- if (ioc->raid_data.pIocPg3) {
- pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
- numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
- while (numPDisk) {
- if (id == pPDisk->PhysDiskNum) {
- pSpi->dvStatus[pPDisk->PhysDiskID] =
- (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
- pSpi->forceDv = MPT_SCSICFG_NEED_DV;
- ddvtprintk(("NEED_DV set for phys disk id %d\n",
- pPDisk->PhysDiskID));
- break;
- }
- pPDisk++;
- numPDisk--;
- }
-
- if (numPDisk == 0) {
- /* The physical disk that needs DV was not found
- * in the stored IOC Page 3. The driver must reload
- * this page. DV routine will set the NEED_DV flag for
- * all phys disks that have DV_NOT_DONE set.
- */
- pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
- ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
- }
- }
-}
-#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
-