ips.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:261k
- /* Remove the item from the active queue */
- ips_removeq_scb(&ha->scb_activelist, scb);
- if (!scb->scsi_cmd)
- /* internal commands are handled in do_ipsintr */
- return ;
- DEBUG_VAR(2, "(%s%d) ips_chkstatus: cmd 0x%X id %d (%d %d %d)",
- ips_name,
- ha->host_num,
- scb->cdb[0],
- scb->cmd.basic_io.command_id,
- scb->bus,
- scb->target_id,
- scb->lun);
- #ifndef NO_IPS_CMDLINE
- if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd)))
- /* passthru - just returns the raw result */
- return ;
- #endif
- errcode = DID_OK;
- if (((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_SUCCESS) ||
- ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR)) {
- if (scb->bus == 0) {
- if ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR) {
- DEBUG_VAR(1, "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x",
- ips_name, ha->host_num,
- scb->cmd.basic_io.op_code, basic_status, ext_status);
- }
- switch (scb->scsi_cmd->cmnd[0]) {
- case ALLOW_MEDIUM_REMOVAL:
- case REZERO_UNIT:
- case ERASE:
- case WRITE_FILEMARKS:
- case SPACE:
- errcode = DID_ERROR;
- break;
- case START_STOP:
- break;
- case TEST_UNIT_READY:
- if (!ips_online(ha, scb)) {
- errcode = DID_TIME_OUT;
- }
- break;
- case INQUIRY:
- if (ips_online(ha, scb)) {
- ips_inquiry(ha, scb);
- } else {
- errcode = DID_TIME_OUT;
- }
- break;
- case REQUEST_SENSE:
- ips_reqsen(ha, scb);
- break;
- case READ_6:
- case WRITE_6:
- case READ_10:
- case WRITE_10:
- case RESERVE:
- case RELEASE:
- break;
- case MODE_SENSE:
- if (!ips_online(ha, scb) || !ips_msense(ha, scb)) {
- errcode = DID_ERROR;
- }
- break;
- case READ_CAPACITY:
- if (ips_online(ha, scb))
- ips_rdcap(ha, scb);
- else {
- errcode = DID_TIME_OUT;
- }
- break;
- case SEND_DIAGNOSTIC:
- case REASSIGN_BLOCKS:
- break;
- case FORMAT_UNIT:
- errcode = DID_ERROR;
- break;
- case SEEK_10:
- case VERIFY:
- case READ_DEFECT_DATA:
- case READ_BUFFER:
- case WRITE_BUFFER:
- break;
- default:
- errcode = DID_ERROR;
- } /* end switch */
- scb->scsi_cmd->result = errcode << 16;
- } else { /* bus == 0 */
- /* restrict access to physical drives */
- if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
- ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) {
- scb->scsi_cmd->result = DID_TIME_OUT << 16;
- }
- } /* else */
- } else { /* recovered error / success */
- if (scb->bus == 0) {
- DEBUG_VAR(1, "(%s%d) Unrecovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x",
- ips_name, ha->host_num,
- scb->cmd.basic_io.op_code, basic_status, ext_status);
- }
- ips_map_status(ha, scb, sp);
- } /* else */
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_online */
- /* */
- /* Routine Description: */
- /* */
- /* Determine if a logical drive is online */
- /* */
- /****************************************************************************/
- static int
- ips_online(ips_ha_t *ha, ips_scb_t *scb) {
- METHOD_TRACE("ips_online", 1);
- if (scb->target_id >= IPS_MAX_LD)
- return (0);
- if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) {
- memset(&ha->adapt->logical_drive_info, 0, sizeof(ha->adapt->logical_drive_info));
- return (0);
- }
- if (ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_OFFLINE &&
- ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_FREE &&
- ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_CRS &&
- ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_SYS)
- return (1);
- else
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_inquiry */
- /* */
- /* Routine Description: */
- /* */
- /* Simulate an inquiry command to a logical drive */
- /* */
- /****************************************************************************/
- static int
- ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) {
- IPS_SCSI_INQ_DATA inquiry;
- METHOD_TRACE("ips_inquiry", 1);
- memset(&inquiry, 0, sizeof(IPS_SCSI_INQ_DATA));
- inquiry.DeviceType = IPS_SCSI_INQ_TYPE_DASD;
- inquiry.DeviceTypeQualifier = IPS_SCSI_INQ_LU_CONNECTED;
- inquiry.Version = IPS_SCSI_INQ_REV2;
- inquiry.ResponseDataFormat = IPS_SCSI_INQ_RD_REV2;
- inquiry.AdditionalLength = 31;
- inquiry.Flags[0] = IPS_SCSI_INQ_Address16;
- inquiry.Flags[1] = IPS_SCSI_INQ_WBus16 | IPS_SCSI_INQ_Sync;
- strncpy(inquiry.VendorId, "IBM ", 8);
- strncpy(inquiry.ProductId, "SERVERAID ", 16);
- strncpy(inquiry.ProductRevisionLevel, "1.00", 4);
- memcpy(scb->scsi_cmd->request_buffer, &inquiry, scb->scsi_cmd->request_bufflen);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_rdcap */
- /* */
- /* Routine Description: */
- /* */
- /* Simulate a read capacity command to a logical drive */
- /* */
- /****************************************************************************/
- static int
- ips_rdcap(ips_ha_t *ha, ips_scb_t *scb) {
- IPS_SCSI_CAPACITY *cap;
- METHOD_TRACE("ips_rdcap", 1);
- if (scb->scsi_cmd->bufflen < 8)
- return (0);
- cap = (IPS_SCSI_CAPACITY *) scb->scsi_cmd->request_buffer;
- cap->lba = cpu_to_be32(le32_to_cpu(ha->adapt->logical_drive_info.drive_info[scb->target_id].sector_count) - 1);
- cap->len = cpu_to_be32((u_int32_t) IPS_BLKSIZE);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_msense */
- /* */
- /* Routine Description: */
- /* */
- /* Simulate a mode sense command to a logical drive */
- /* */
- /****************************************************************************/
- static int
- ips_msense(ips_ha_t *ha, ips_scb_t *scb) {
- u_int16_t heads;
- u_int16_t sectors;
- u_int32_t cylinders;
- IPS_SCSI_MODE_PAGE_DATA mdata;
- METHOD_TRACE("ips_msense", 1);
- if (le32_to_cpu(ha->enq->ulDriveSize[scb->target_id]) > 0x400000 &&
- (ha->enq->ucMiscFlag & 0x8) == 0) {
- heads = IPS_NORM_HEADS;
- sectors = IPS_NORM_SECTORS;
- } else {
- heads = IPS_COMP_HEADS;
- sectors = IPS_COMP_SECTORS;
- }
- cylinders = (le32_to_cpu(ha->enq->ulDriveSize[scb->target_id]) - 1) / (heads * sectors);
- memset(&mdata, 0, sizeof(IPS_SCSI_MODE_PAGE_DATA));
- mdata.hdr.BlockDescLength = 8;
- switch (scb->scsi_cmd->cmnd[2] & 0x3f) {
- case 0x03: /* page 3 */
- mdata.pdata.pg3.PageCode = 3;
- mdata.pdata.pg3.PageLength = sizeof(IPS_SCSI_MODE_PAGE3);
- mdata.hdr.DataLength = 3 + mdata.hdr.BlockDescLength + mdata.pdata.pg3.PageLength;
- mdata.pdata.pg3.TracksPerZone = 0;
- mdata.pdata.pg3.AltSectorsPerZone = 0;
- mdata.pdata.pg3.AltTracksPerZone = 0;
- mdata.pdata.pg3.AltTracksPerVolume = 0;
- mdata.pdata.pg3.SectorsPerTrack = cpu_to_be16(sectors);
- mdata.pdata.pg3.BytesPerSector = cpu_to_be16(IPS_BLKSIZE);
- mdata.pdata.pg3.Interleave = cpu_to_be16(1);
- mdata.pdata.pg3.TrackSkew = 0;
- mdata.pdata.pg3.CylinderSkew = 0;
- mdata.pdata.pg3.flags = IPS_SCSI_MP3_SoftSector;
- break;
- case 0x4:
- mdata.pdata.pg4.PageCode = 4;
- mdata.pdata.pg4.PageLength = sizeof(IPS_SCSI_MODE_PAGE4);
- mdata.hdr.DataLength = 3 + mdata.hdr.BlockDescLength + mdata.pdata.pg4.PageLength;
- mdata.pdata.pg4.CylindersHigh = cpu_to_be16((cylinders >> 8) & 0xFFFF);
- mdata.pdata.pg4.CylindersLow = (cylinders & 0xFF);
- mdata.pdata.pg4.Heads = heads;
- mdata.pdata.pg4.WritePrecompHigh = 0;
- mdata.pdata.pg4.WritePrecompLow = 0;
- mdata.pdata.pg4.ReducedWriteCurrentHigh = 0;
- mdata.pdata.pg4.ReducedWriteCurrentLow = 0;
- mdata.pdata.pg4.StepRate = cpu_to_be16(1);
- mdata.pdata.pg4.LandingZoneHigh = 0;
- mdata.pdata.pg4.LandingZoneLow = 0;
- mdata.pdata.pg4.flags = 0;
- mdata.pdata.pg4.RotationalOffset = 0;
- mdata.pdata.pg4.MediumRotationRate = 0;
- break;
- default:
- return (0);
- } /* end switch */
- memcpy(scb->scsi_cmd->request_buffer, &mdata, scb->scsi_cmd->request_bufflen);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_reqsen */
- /* */
- /* Routine Description: */
- /* */
- /* Simulate a request sense command to a logical drive */
- /* */
- /****************************************************************************/
- static int
- ips_reqsen(ips_ha_t *ha, ips_scb_t *scb) {
- IPS_SCSI_REQSEN reqsen;
- METHOD_TRACE("ips_reqsen", 1);
- memset(&reqsen, 0, sizeof(IPS_SCSI_REQSEN));
- reqsen.ResponseCode = IPS_SCSI_REQSEN_VALID | IPS_SCSI_REQSEN_CURRENT_ERR;
- reqsen.AdditionalLength = 10;
- reqsen.AdditionalSenseCode = IPS_SCSI_REQSEN_NO_SENSE;
- reqsen.AdditionalSenseCodeQual = IPS_SCSI_REQSEN_NO_SENSE;
- memcpy(scb->scsi_cmd->request_buffer, &reqsen, scb->scsi_cmd->request_bufflen);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_free */
- /* */
- /* Routine Description: */
- /* */
- /* Free any allocated space for this controller */
- /* */
- /****************************************************************************/
- static void
- ips_free(ips_ha_t *ha) {
- int i;
- METHOD_TRACE("ips_free", 1);
- if (ha) {
- if (ha->enq) {
- kfree(ha->enq);
- ha->enq = NULL;
- }
- if (ha->conf) {
- kfree(ha->conf);
- ha->conf = NULL;
- }
- if (ha->adapt) {
- kfree(ha->adapt);
- ha->adapt = NULL;
- }
- if (ha->nvram) {
- kfree(ha->nvram);
- ha->nvram = NULL;
- }
- if (ha->subsys) {
- kfree(ha->subsys);
- ha->subsys = NULL;
- }
- if (ha->dummy) {
- kfree(ha->dummy);
- ha->dummy = NULL;
- }
- if (ha->ioctl_data) {
- free_pages((unsigned long) ha->ioctl_data, ha->ioctl_order);
- ha->ioctl_data = NULL;
- ha->ioctl_datasize = 0;
- ha->ioctl_order = 0;
- }
- if (ha->scbs) {
- for (i = 0; i < ha->max_cmds; i++) {
- if (ha->scbs[i].sg_list)
- kfree(ha->scbs[i].sg_list);
- }
- kfree(ha->scbs);
- ha->scbs = NULL;
- } /* end if */
- /* free memory mapped (if applicable) */
- if (ha->mem_ptr) {
- iounmap(ha->ioremap_ptr);
- ha->ioremap_ptr = NULL;
- ha->mem_ptr = NULL;
- }
- #if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,17)
- if (ha->mem_addr)
- release_mem_region(ha->mem_addr, ha->mem_len);
- #endif
- ha->mem_addr = 0;
- }
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_allocatescbs */
- /* */
- /* Routine Description: */
- /* */
- /* Allocate the command blocks */
- /* */
- /****************************************************************************/
- static int
- ips_allocatescbs(ips_ha_t *ha) {
- ips_scb_t *scb_p;
- int i;
- METHOD_TRACE("ips_allocatescbs", 1);
- /* Allocate memory for the CCBs */
- ha->scbs = (ips_scb_t *) kmalloc(ha->max_cmds * sizeof(ips_scb_t), GFP_KERNEL);
- if (ha->scbs == NULL)
- return 0;
- memset(ha->scbs, 0, ha->max_cmds * sizeof(ips_scb_t));
- for (i = 0; i < ha->max_cmds; i++) {
- scb_p = &ha->scbs[i];
- /* allocate S/G list */
- scb_p->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_ATOMIC);
- if (! scb_p->sg_list)
- return (0);
- /* add to the free list */
- if (i < ha->max_cmds - 1) {
- scb_p->q_next = ha->scb_freelist;
- ha->scb_freelist = scb_p;
- }
- }
- /* success */
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_init_scb */
- /* */
- /* Routine Description: */
- /* */
- /* Initialize a CCB to default values */
- /* */
- /****************************************************************************/
- static void
- ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) {
- IPS_SG_LIST *sg_list;
- METHOD_TRACE("ips_init_scb", 1);
- if (scb == NULL)
- return ;
- sg_list = scb->sg_list;
- /* zero fill */
- memset(scb, 0, sizeof(ips_scb_t));
- memset(ha->dummy, 0, sizeof(IPS_IO_CMD));
- /* Initialize dummy command bucket */
- ha->dummy->op_code = 0xFF;
- ha->dummy->ccsar = cpu_to_le32(VIRT_TO_BUS(ha->dummy));
- ha->dummy->command_id = IPS_MAX_CMDS;
- /* set bus address of scb */
- scb->scb_busaddr = VIRT_TO_BUS(scb);
- scb->sg_list = sg_list;
- /* Neptune Fix */
- scb->cmd.basic_io.cccr = cpu_to_le32((u_int32_t) IPS_BIT_ILE);
- scb->cmd.basic_io.ccsar = cpu_to_le32(VIRT_TO_BUS(ha->dummy));
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_get_scb */
- /* */
- /* Routine Description: */
- /* */
- /* Initialize a CCB to default values */
- /* */
- /* ASSUMED to be callled from within a lock */
- /* */
- /****************************************************************************/
- static ips_scb_t *
- ips_getscb(ips_ha_t *ha) {
- ips_scb_t *scb;
- unsigned long cpu_flags;
- METHOD_TRACE("ips_getscb", 1);
- IPS_SCB_LOCK(cpu_flags);
- if ((scb = ha->scb_freelist) == NULL) {
- IPS_SCB_UNLOCK(cpu_flags);
- return (NULL);
- }
- ha->scb_freelist = scb->q_next;
- scb->q_next = NULL;
- IPS_SCB_UNLOCK(cpu_flags);
- ips_init_scb(ha, scb);
- return (scb);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_free_scb */
- /* */
- /* Routine Description: */
- /* */
- /* Return an unused CCB back to the free list */
- /* */
- /* ASSUMED to be called from within a lock */
- /* */
- /****************************************************************************/
- static void
- ips_freescb(ips_ha_t *ha, ips_scb_t *scb) {
- unsigned long cpu_flags;
- METHOD_TRACE("ips_freescb", 1);
- /* check to make sure this is not our "special" scb */
- if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) {
- IPS_SCB_LOCK(cpu_flags);
- scb->q_next = ha->scb_freelist;
- ha->scb_freelist = scb;
- IPS_SCB_UNLOCK(cpu_flags);
- }
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_isinit_copperhead */
- /* */
- /* Routine Description: */
- /* */
- /* Reset the controller */
- /* */
- /****************************************************************************/
- static int
- ips_isinit_copperhead(ips_ha_t *ha) {
- u_int8_t scpr;
- u_int8_t isr;
- METHOD_TRACE("ips_isinit_copperhead", 1);
- isr = inb(ha->io_addr + IPS_REG_HISR);
- scpr = inb(ha->io_addr + IPS_REG_SCPR);
- if (((isr & IPS_BIT_EI) == 0) && ((scpr & IPS_BIT_EBM) == 0))
- return (0);
- else
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_isinit_copperhead_memio */
- /* */
- /* Routine Description: */
- /* */
- /* Reset the controller */
- /* */
- /****************************************************************************/
- static int
- ips_isinit_copperhead_memio(ips_ha_t *ha) {
- u_int8_t isr=0;
- u_int8_t scpr;
- METHOD_TRACE("ips_is_init_copperhead_memio", 1);
- isr = readb(ha->mem_ptr + IPS_REG_HISR);
- scpr = readb(ha->mem_ptr + IPS_REG_SCPR);
- if (((isr & IPS_BIT_EI) == 0) && ((scpr & IPS_BIT_EBM) == 0))
- return (0);
- else
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_isinit_morpheus */
- /* */
- /* Routine Description: */
- /* */
- /* Reset the controller */
- /* */
- /****************************************************************************/
- static int
- ips_isinit_morpheus(ips_ha_t *ha) {
- u_int32_t post;
- u_int32_t bits;
- METHOD_TRACE("ips_is_init_morpheus", 1);
- post = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I960_MSG0));
- bits = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I2O_HIR));
- if (post == 0)
- return (0);
- else if (bits & 0x3)
- return (0);
- else
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_enable_int_copperhead */
- /* */
- /* Routine Description: */
- /* Turn on interrupts */
- /* */
- /****************************************************************************/
- static void
- ips_enable_int_copperhead(ips_ha_t *ha) {
- METHOD_TRACE("ips_enable_int_copperhead", 1);
- outb(ha->io_addr + IPS_REG_HISR, IPS_BIT_EI);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_enable_int_copperhead_memio */
- /* */
- /* Routine Description: */
- /* Turn on interrupts */
- /* */
- /****************************************************************************/
- static void
- ips_enable_int_copperhead_memio(ips_ha_t *ha) {
- METHOD_TRACE("ips_enable_int_copperhead_memio", 1);
- writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_enable_int_morpheus */
- /* */
- /* Routine Description: */
- /* Turn on interrupts */
- /* */
- /****************************************************************************/
- static void
- ips_enable_int_morpheus(ips_ha_t *ha) {
- u_int32_t Oimr;
- METHOD_TRACE("ips_enable_int_morpheus", 1);
- Oimr = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I960_OIMR));
- Oimr &= ~0x08;
- writel(cpu_to_le32(Oimr), ha->mem_ptr + IPS_REG_I960_OIMR);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_init_copperhead */
- /* */
- /* Routine Description: */
- /* */
- /* Initialize a copperhead controller */
- /* */
- /****************************************************************************/
- static int
- ips_init_copperhead(ips_ha_t *ha) {
- u_int8_t Isr;
- u_int8_t Cbsp;
- u_int8_t PostByte[IPS_MAX_POST_BYTES];
- u_int8_t ConfigByte[IPS_MAX_CONFIG_BYTES];
- int i, j;
- METHOD_TRACE("ips_init_copperhead", 1);
- for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
- for (j = 0; j < 45; j++) {
- Isr = inb(ha->io_addr + IPS_REG_HISR);
- if (Isr & IPS_BIT_GHI)
- break;
- MDELAY(IPS_ONE_SEC);
- }
- if (j >= 45)
- /* error occurred */
- return (0);
- PostByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
- outb(Isr, ha->io_addr + IPS_REG_HISR);
- }
- if (PostByte[0] < IPS_GOOD_POST_STATUS) {
- printk(KERN_WARNING "(%s%d) reset controller fails (post status %x %x).n",
- ips_name, ha->host_num, PostByte[0], PostByte[1]);
- return (0);
- }
- for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
- for (j = 0; j < 240; j++) {
- Isr = inb(ha->io_addr + IPS_REG_HISR);
- if (Isr & IPS_BIT_GHI)
- break;
- MDELAY(IPS_ONE_SEC); /* 1 sec */
- }
- if (j >= 240)
- /* error occurred */
- return (0);
- ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
- outb(Isr, ha->io_addr + IPS_REG_HISR);
- }
- for (i = 0; i < 240; i++) {
- Cbsp = inb(ha->io_addr + IPS_REG_CBSP);
- if ((Cbsp & IPS_BIT_OP) == 0)
- break;
- MDELAY(IPS_ONE_SEC);
- }
- if (i >= 240)
- /* reset failed */
- return (0);
- /* setup CCCR */
- outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
- /* Enable busmastering */
- outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- /* fix for anaconda64 */
- outl(0, ha->io_addr + IPS_REG_NDAE);
- /* Enable interrupts */
- outb(IPS_BIT_EI, ha->io_addr + IPS_REG_HISR);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_init_copperhead_memio */
- /* */
- /* Routine Description: */
- /* */
- /* Initialize a copperhead controller with memory mapped I/O */
- /* */
- /****************************************************************************/
- static int
- ips_init_copperhead_memio(ips_ha_t *ha) {
- u_int8_t Isr=0;
- u_int8_t Cbsp;
- u_int8_t PostByte[IPS_MAX_POST_BYTES];
- u_int8_t ConfigByte[IPS_MAX_CONFIG_BYTES];
- int i, j;
- METHOD_TRACE("ips_init_copperhead_memio", 1);
- for (i = 0; i < IPS_MAX_POST_BYTES; i++) {
- for (j = 0; j < 45; j++) {
- Isr = readb(ha->mem_ptr + IPS_REG_HISR);
- if (Isr & IPS_BIT_GHI)
- break;
- MDELAY(IPS_ONE_SEC);
- }
- if (j >= 45)
- /* error occurred */
- return (0);
- PostByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
- writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
- }
- if (PostByte[0] < IPS_GOOD_POST_STATUS) {
- printk(KERN_WARNING "(%s%d) reset controller fails (post status %x %x).n",
- ips_name, ha->host_num, PostByte[0], PostByte[1]);
- return (0);
- }
- for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) {
- for (j = 0; j < 240; j++) {
- Isr = readb(ha->mem_ptr + IPS_REG_HISR);
- if (Isr & IPS_BIT_GHI)
- break;
- MDELAY(IPS_ONE_SEC); /* 100 msec */
- }
- if (j >= 240)
- /* error occurred */
- return (0);
- ConfigByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
- writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
- }
- for (i = 0; i < 240; i++) {
- Cbsp = readb(ha->mem_ptr + IPS_REG_CBSP);
- if ((Cbsp & IPS_BIT_OP) == 0)
- break;
- MDELAY(IPS_ONE_SEC);
- }
- if (i >= 240)
- /* error occurred */
- return (0);
- /* setup CCCR */
- writel(cpu_to_le32(0x1010), ha->mem_ptr + IPS_REG_CCCR);
- /* Enable busmastering */
- writeb(IPS_BIT_EBM, ha->mem_ptr + IPS_REG_SCPR);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- /* fix for anaconda64 */
- writel(0, ha->mem_ptr + IPS_REG_NDAE);
- /* Enable interrupts */
- writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
- /* if we get here then everything went OK */
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_init_morpheus */
- /* */
- /* Routine Description: */
- /* */
- /* Initialize a morpheus controller */
- /* */
- /****************************************************************************/
- static int
- ips_init_morpheus(ips_ha_t *ha) {
- u_int32_t Post;
- u_int32_t Config;
- u_int32_t Isr;
- u_int32_t Oimr;
- int i;
- METHOD_TRACE("ips_init_morpheus", 1);
- /* Wait up to 45 secs for Post */
- for (i = 0; i < 45; i++) {
- Isr = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I2O_HIR));
- if (Isr & IPS_BIT_I960_MSG0I)
- break;
- MDELAY(IPS_ONE_SEC);
- }
- if (i >= 45) {
- /* error occurred */
- printk(KERN_WARNING "(%s%d) timeout waiting for post.n",
- ips_name, ha->host_num);
- return (0);
- }
- Post = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I960_MSG0));
- /* Clear the interrupt bit */
- Isr = (u_int32_t) IPS_BIT_I960_MSG0I;
- writel(cpu_to_le32(Isr), ha->mem_ptr + IPS_REG_I2O_HIR);
- if (Post < (IPS_GOOD_POST_STATUS << 8)) {
- printk(KERN_WARNING "(%s%d) reset controller fails (post status %x).n",
- ips_name, ha->host_num, Post);
- return (0);
- }
- /* Wait up to 240 secs for config bytes */
- for (i = 0; i < 240; i++) {
- Isr = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I2O_HIR));
- if (Isr & IPS_BIT_I960_MSG1I)
- break;
- MDELAY(IPS_ONE_SEC); /* 100 msec */
- }
- if (i >= 240) {
- /* error occurred */
- printk(KERN_WARNING "(%s%d) timeout waiting for config.n",
- ips_name, ha->host_num);
- return (0);
- }
- Config = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I960_MSG1));
- /* Clear interrupt bit */
- Isr = (u_int32_t) IPS_BIT_I960_MSG1I;
- writel(cpu_to_le32(Isr), ha->mem_ptr + IPS_REG_I2O_HIR);
- /* Turn on the interrupts */
- Oimr = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I960_OIMR));
- Oimr &= ~0x8;
- writel(cpu_to_le32(Oimr), ha->mem_ptr + IPS_REG_I960_OIMR);
- /* if we get here then everything went OK */
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_reset_copperhead */
- /* */
- /* Routine Description: */
- /* */
- /* Reset the controller */
- /* */
- /****************************************************************************/
- static int
- ips_reset_copperhead(ips_ha_t *ha) {
- int reset_counter;
- unsigned long cpu_flags;
- METHOD_TRACE("ips_reset_copperhead", 1);
- DEBUG_VAR(1, "(%s%d) ips_reset_copperhead: io addr: %x, irq: %d",
- ips_name, ha->host_num, ha->io_addr, ha->irq);
- IPS_HA_LOCK(cpu_flags);
- reset_counter = 0;
- while (reset_counter < 2) {
- reset_counter++;
- outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR);
- MDELAY(IPS_ONE_SEC);
- outb(0, ha->io_addr + IPS_REG_SCPR);
- MDELAY(IPS_ONE_SEC);
- if ((*ha->func.init)(ha))
- break;
- else if (reset_counter >= 2) {
- IPS_HA_UNLOCK(cpu_flags);
- return (0);
- }
- }
- IPS_HA_UNLOCK(cpu_flags);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_reset_copperhead_memio */
- /* */
- /* Routine Description: */
- /* */
- /* Reset the controller */
- /* */
- /****************************************************************************/
- static int
- ips_reset_copperhead_memio(ips_ha_t *ha) {
- int reset_counter;
- unsigned long cpu_flags;
- METHOD_TRACE("ips_reset_copperhead_memio", 1);
- DEBUG_VAR(1, "(%s%d) ips_reset_copperhead_memio: mem addr: %x, irq: %d",
- ips_name, ha->host_num, ha->mem_addr, ha->irq);
- IPS_HA_LOCK(cpu_flags);
- reset_counter = 0;
- while (reset_counter < 2) {
- reset_counter++;
- writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR);
- MDELAY(IPS_ONE_SEC);
- writeb(0, ha->mem_ptr + IPS_REG_SCPR);
- MDELAY(IPS_ONE_SEC);
- if ((*ha->func.init)(ha))
- break;
- else if (reset_counter >= 2) {
- IPS_HA_UNLOCK(cpu_flags);
- return (0);
- }
- }
- IPS_HA_UNLOCK(cpu_flags);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_reset_morpheus */
- /* */
- /* Routine Description: */
- /* */
- /* Reset the controller */
- /* */
- /****************************************************************************/
- static int
- ips_reset_morpheus(ips_ha_t *ha) {
- int reset_counter;
- u_int8_t junk;
- unsigned long cpu_flags;
- METHOD_TRACE("ips_reset_morpheus", 1);
- DEBUG_VAR(1, "(%s%d) ips_reset_morpheus: mem addr: %x, irq: %d",
- ips_name, ha->host_num, ha->mem_addr, ha->irq);
- IPS_HA_LOCK(cpu_flags);
- reset_counter = 0;
- while (reset_counter < 2) {
- reset_counter++;
- writel(cpu_to_le32(0x80000000), ha->mem_ptr + IPS_REG_I960_IDR);
- /* Delay for 5 sec */
- MDELAY(5 * IPS_ONE_SEC);
- /* Do a PCI config read to wait for adapter */
- pci_read_config_byte(ha->pcidev, 4, &junk);
- if ((*ha->func.init)(ha))
- break;
- else if (reset_counter >= 2) {
- IPS_HA_UNLOCK(cpu_flags);
- return (0);
- }
- }
- IPS_HA_UNLOCK(cpu_flags);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_statinit */
- /* */
- /* Routine Description: */
- /* */
- /* Initialize the status queues on the controller */
- /* */
- /****************************************************************************/
- static void
- ips_statinit(ips_ha_t *ha) {
- u_int32_t phys_status_start;
- METHOD_TRACE("ips_statinit", 1);
- ha->adapt->p_status_start = ha->adapt->status;
- ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
- ha->adapt->p_status_tail = ha->adapt->status;
- phys_status_start = VIRT_TO_BUS(ha->adapt->status);
- outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQSR);
- outl(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE), ha->io_addr + IPS_REG_SQER);
- outl(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE), ha->io_addr + IPS_REG_SQHR);
- outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQTR);
- ha->adapt->hw_status_start = phys_status_start;
- ha->adapt->hw_status_tail = phys_status_start;
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_statinit_memio */
- /* */
- /* Routine Description: */
- /* */
- /* Initialize the status queues on the controller */
- /* */
- /****************************************************************************/
- static void
- ips_statinit_memio(ips_ha_t *ha) {
- u_int32_t phys_status_start;
- METHOD_TRACE("ips_statinit_memio", 1);
- ha->adapt->p_status_start = ha->adapt->status;
- ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS;
- ha->adapt->p_status_tail = ha->adapt->status;
- phys_status_start = VIRT_TO_BUS(ha->adapt->status);
- writel(cpu_to_le32(phys_status_start), ha->mem_ptr + IPS_REG_SQSR);
- writel(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE), ha->mem_ptr + IPS_REG_SQER);
- writel(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE), ha->mem_ptr + IPS_REG_SQHR);
- writel(cpu_to_le32(phys_status_start), ha->mem_ptr + IPS_REG_SQTR);
- ha->adapt->hw_status_start = phys_status_start;
- ha->adapt->hw_status_tail = phys_status_start;
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_statupd_copperhead */
- /* */
- /* Routine Description: */
- /* */
- /* Remove an element from the status queue */
- /* */
- /****************************************************************************/
- static u_int32_t
- ips_statupd_copperhead(ips_ha_t *ha) {
- METHOD_TRACE("ips_statupd_copperhead", 1);
- if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
- ha->adapt->p_status_tail++;
- ha->adapt->hw_status_tail += sizeof(IPS_STATUS);
- } else {
- ha->adapt->p_status_tail = ha->adapt->p_status_start;
- ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
- }
- outl(cpu_to_le32(ha->adapt->hw_status_tail), ha->io_addr + IPS_REG_SQTR);
- return (ha->adapt->p_status_tail->value);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_statupd_copperhead_memio */
- /* */
- /* Routine Description: */
- /* */
- /* Remove an element from the status queue */
- /* */
- /****************************************************************************/
- static u_int32_t
- ips_statupd_copperhead_memio(ips_ha_t *ha) {
- METHOD_TRACE("ips_statupd_copperhead_memio", 1);
- if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
- ha->adapt->p_status_tail++;
- ha->adapt->hw_status_tail += sizeof(IPS_STATUS);
- } else {
- ha->adapt->p_status_tail = ha->adapt->p_status_start;
- ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
- }
- writel(cpu_to_le32(ha->adapt->hw_status_tail), ha->mem_ptr + IPS_REG_SQTR);
- return (ha->adapt->p_status_tail->value);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_statupd_morpheus */
- /* */
- /* Routine Description: */
- /* */
- /* Remove an element from the status queue */
- /* */
- /****************************************************************************/
- static u_int32_t
- ips_statupd_morpheus(ips_ha_t *ha) {
- u_int32_t val;
- METHOD_TRACE("ips_statupd_morpheus", 1);
- val = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I2O_OUTMSGQ));
- return (val);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_issue_copperhead */
- /* */
- /* Routine Description: */
- /* */
- /* Send a command down to the controller */
- /* */
- /****************************************************************************/
- static int
- ips_issue_copperhead(ips_ha_t *ha, ips_scb_t *scb) {
- u_int32_t TimeOut;
- u_int32_t val;
- unsigned long cpu_flags;
- METHOD_TRACE("ips_issue_copperhead", 1);
- if (scb->scsi_cmd) {
- DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
- ips_name,
- ha->host_num,
- scb->cdb[0],
- scb->cmd.basic_io.command_id,
- scb->bus,
- scb->target_id,
- scb->lun);
- } else {
- DEBUG_VAR(2, KERN_NOTICE "(%s%d) ips_issue: logical cmd id %d",
- ips_name,
- ha->host_num,
- scb->cmd.basic_io.command_id);
- }
- IPS_HA_LOCK(cpu_flags);
- TimeOut = 0;
- while ((val = le32_to_cpu(inl(ha->io_addr + IPS_REG_CCCR))) & IPS_BIT_SEM) {
- udelay(1000);
- if (++TimeOut >= IPS_SEM_TIMEOUT) {
- if (!(val & IPS_BIT_START_STOP))
- break;
- printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].n",
- ips_name, ha->host_num, val);
- printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.n",
- ips_name, ha->host_num);
- IPS_HA_UNLOCK(cpu_flags);
- return (IPS_FAILURE);
- } /* end if */
- } /* end while */
- outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
- outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
- IPS_HA_UNLOCK(cpu_flags);
- return (IPS_SUCCESS);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_issue_copperhead_memio */
- /* */
- /* Routine Description: */
- /* */
- /* Send a command down to the controller */
- /* */
- /****************************************************************************/
- static int
- ips_issue_copperhead_memio(ips_ha_t *ha, ips_scb_t *scb) {
- u_int32_t TimeOut;
- u_int32_t val;
- unsigned long cpu_flags;
- METHOD_TRACE("ips_issue_copperhead_memio", 1);
- if (scb->scsi_cmd) {
- DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
- ips_name,
- ha->host_num,
- scb->cdb[0],
- scb->cmd.basic_io.command_id,
- scb->bus,
- scb->target_id,
- scb->lun);
- } else {
- DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
- ips_name,
- ha->host_num,
- scb->cmd.basic_io.command_id);
- }
- IPS_HA_LOCK(cpu_flags);
- TimeOut = 0;
- while ((val = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_CCCR))) & IPS_BIT_SEM) {
- udelay(1000);
- if (++TimeOut >= IPS_SEM_TIMEOUT) {
- if (!(val & IPS_BIT_START_STOP))
- break;
- printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].n",
- ips_name, ha->host_num, val);
- printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.n",
- ips_name, ha->host_num);
- IPS_HA_UNLOCK(cpu_flags);
- return (IPS_FAILURE);
- } /* end if */
- } /* end while */
- writel(cpu_to_le32(scb->scb_busaddr), ha->mem_ptr + IPS_REG_CCSAR);
- writel(cpu_to_le32(IPS_BIT_START_CMD), ha->mem_ptr + IPS_REG_CCCR);
- IPS_HA_UNLOCK(cpu_flags);
- return (IPS_SUCCESS);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_issue_i2o */
- /* */
- /* Routine Description: */
- /* */
- /* Send a command down to the controller */
- /* */
- /****************************************************************************/
- static int
- ips_issue_i2o(ips_ha_t *ha, ips_scb_t *scb) {
- unsigned long cpu_flags;
- METHOD_TRACE("ips_issue_i2o", 1);
- if (scb->scsi_cmd) {
- DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
- ips_name,
- ha->host_num,
- scb->cdb[0],
- scb->cmd.basic_io.command_id,
- scb->bus,
- scb->target_id,
- scb->lun);
- } else {
- DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
- ips_name,
- ha->host_num,
- scb->cmd.basic_io.command_id);
- }
- IPS_HA_LOCK(cpu_flags);
- outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
- IPS_HA_UNLOCK(cpu_flags);
- return (IPS_SUCCESS);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_issue_i2o_memio */
- /* */
- /* Routine Description: */
- /* */
- /* Send a command down to the controller */
- /* */
- /****************************************************************************/
- static int
- ips_issue_i2o_memio(ips_ha_t *ha, ips_scb_t *scb) {
- unsigned long cpu_flags;
- METHOD_TRACE("ips_issue_i2o_memio", 1);
- if (scb->scsi_cmd) {
- DEBUG_VAR(2, "(%s%d) ips_issue: cmd 0x%X id %d (%d %d %d)",
- ips_name,
- ha->host_num,
- scb->cdb[0],
- scb->cmd.basic_io.command_id,
- scb->bus,
- scb->target_id,
- scb->lun);
- } else {
- DEBUG_VAR(2, "(%s%d) ips_issue: logical cmd id %d",
- ips_name,
- ha->host_num,
- scb->cmd.basic_io.command_id);
- }
- IPS_HA_LOCK(cpu_flags);
- writel(cpu_to_le32(scb->scb_busaddr), ha->mem_ptr + IPS_REG_I2O_INMSGQ);
- IPS_HA_UNLOCK(cpu_flags);
- return (IPS_SUCCESS);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_isintr_copperhead */
- /* */
- /* Routine Description: */
- /* */
- /* Test to see if an interrupt is for us */
- /* */
- /****************************************************************************/
- static int
- ips_isintr_copperhead(ips_ha_t *ha) {
- u_int8_t Isr;
- METHOD_TRACE("ips_isintr_copperhead", 2);
- Isr = inb(ha->io_addr + IPS_REG_HISR);
- if (Isr == 0xFF)
- /* ?!?! Nothing really there */
- return (0);
- if (Isr & IPS_BIT_SCE)
- return (1);
- else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
- /* status queue overflow or GHI */
- /* just clear the interrupt */
- outb(Isr, ha->io_addr + IPS_REG_HISR);
- }
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_isintr_copperhead_memio */
- /* */
- /* Routine Description: */
- /* */
- /* Test to see if an interrupt is for us */
- /* */
- /****************************************************************************/
- static int
- ips_isintr_copperhead_memio(ips_ha_t *ha) {
- u_int8_t Isr;
- METHOD_TRACE("ips_isintr_memio", 2);
- Isr = readb(ha->mem_ptr + IPS_REG_HISR);
- if (Isr == 0xFF)
- /* ?!?! Nothing really there */
- return (0);
- if (Isr & IPS_BIT_SCE)
- return (1);
- else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) {
- /* status queue overflow or GHI */
- /* just clear the interrupt */
- writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
- }
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_isintr_morpheus */
- /* */
- /* Routine Description: */
- /* */
- /* Test to see if an interrupt is for us */
- /* */
- /****************************************************************************/
- static int
- ips_isintr_morpheus(ips_ha_t *ha) {
- u_int32_t Isr;
- METHOD_TRACE("ips_isintr_morpheus", 2);
- Isr = le32_to_cpu(readl(ha->mem_ptr + IPS_REG_I2O_HIR));
- if (Isr & IPS_BIT_I2O_OPQI)
- return (1);
- else
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_wait */
- /* */
- /* Routine Description: */
- /* */
- /* Wait for a command to complete */
- /* */
- /****************************************************************************/
- static int
- ips_wait(ips_ha_t *ha, int time, int intr) {
- int ret;
- u_int8_t done;
- METHOD_TRACE("ips_wait", 1);
- ret = IPS_FAILURE;
- done = FALSE;
- time *= IPS_ONE_SEC; /* convert seconds to milliseconds */
- while ((time > 0) && (!done)) {
- if (intr == IPS_INTR_ON) {
- if (ha->waitflag == FALSE) {
- ret = IPS_SUCCESS;
- done = TRUE;
- break;
- }
- } else if (intr == IPS_INTR_IORL) {
- if (ha->waitflag == FALSE) {
- /*
- * controller generated an interrupt to
- * acknowledge completion of the command
- * and ips_intr() has serviced the interrupt.
- */
- ret = IPS_SUCCESS;
- done = TRUE;
- break;
- }
- /*
- * NOTE: we already have the io_request_lock so
- * even if we get an interrupt it won't get serviced
- * until after we finish.
- */
- while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
- udelay(1000);
- (*ha->func.intr)(ha);
- clear_bit(IPS_IN_INTR, &ha->flags);
- } else if (intr == IPS_INTR_HAL) {
- if (ha->waitflag == FALSE) {
- /*
- * controller generated an interrupt to
- * acknowledge completion of the command
- * and ips_intr() has serviced the interrupt.
- */
- ret = IPS_SUCCESS;
- done = TRUE;
- break;
- }
- /*
- * NOTE: since we were not called with the iorequest lock
- * we must obtain it before we can call the interrupt handler.
- * We were called under the HA lock so we can assume that interrupts
- * are masked.
- */
- spin_lock(&io_request_lock);
- while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
- udelay(1000);
- (*ha->func.intr)(ha);
- clear_bit(IPS_IN_INTR, &ha->flags);
- spin_unlock(&io_request_lock);
- }
- udelay(1000); /* 1 milisecond */
- time--;
- }
- return (ret);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_write_driver_status */
- /* */
- /* Routine Description: */
- /* */
- /* Write OS/Driver version to Page 5 of the nvram on the controller */
- /* */
- /****************************************************************************/
- static int
- ips_write_driver_status(ips_ha_t *ha, int intr) {
- METHOD_TRACE("ips_write_driver_status", 1);
- if (!ips_readwrite_page5(ha, FALSE, intr)) {
- printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.n",
- ips_name, ha->host_num);
- return (0);
- }
- /* check to make sure the page has a valid */
- /* signature */
- if (le32_to_cpu(ha->nvram->signature) != IPS_NVRAM_P5_SIG) {
- DEBUG_VAR(1, "(%s%d) NVRAM page 5 has an invalid signature: %X.",
- ips_name, ha->host_num, ha->nvram->signature);
- return (1);
- }
- DEBUG_VAR(2, "(%s%d) Ad Type: %d, Ad Slot: %d, BIOS: %c%c%c%c %c%c%c%c.",
- ips_name, ha->host_num, le16_to_cpu(ha->nvram->adapter_type),
- ha->nvram->adapter_slot,
- ha->nvram->bios_high[0], ha->nvram->bios_high[1],
- ha->nvram->bios_high[2], ha->nvram->bios_high[3],
- ha->nvram->bios_low[0], ha->nvram->bios_low[1],
- ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
- ips_get_bios_version(ha, intr);
- /* change values (as needed) */
- ha->nvram->operating_system = IPS_OS_LINUX;
- ha->nvram->adapter_type = ha->ad_type;
- strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
- strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
- strncpy((char *) ha->nvram->bios_high, ha->bios_version, 4);
- strncpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4);
- /* now update the page */
- if (!ips_readwrite_page5(ha, TRUE, intr)) {
- printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.n",
- ips_name, ha->host_num);
- return (0);
- }
- /* IF NVRAM Page 5 is OK, Use it for Slot Number Info Because Linux Doesn't Do Slots */
- ha->slot_num = ha->nvram->adapter_slot;
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_read_adapter_status */
- /* */
- /* Routine Description: */
- /* */
- /* Do an Inquiry command to the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_read_adapter_status(ips_ha_t *ha, int intr) {
- ips_scb_t *scb;
- int ret;
- METHOD_TRACE("ips_read_adapter_status", 1);
- scb = &ha->scbs[ha->max_cmds-1];
- ips_init_scb(ha, scb);
- scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = IPS_CMD_ENQUIRY;
- scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY;
- scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.basic_io.sg_count = 0;
- scb->cmd.basic_io.sg_addr = cpu_to_le32(VIRT_TO_BUS(ha->enq));
- scb->cmd.basic_io.lba = 0;
- scb->cmd.basic_io.sector_count = 0;
- scb->cmd.basic_io.log_drv = 0;
- scb->cmd.basic_io.reserved = 0;
- /* send command */
- if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
- (ret == IPS_SUCCESS_IMM) ||
- ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
- return (0);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_read_subsystem_parameters */
- /* */
- /* Routine Description: */
- /* */
- /* Read subsystem parameters from the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_read_subsystem_parameters(ips_ha_t *ha, int intr) {
- ips_scb_t *scb;
- int ret;
- METHOD_TRACE("ips_read_subsystem_parameters", 1);
- scb = &ha->scbs[ha->max_cmds-1];
- ips_init_scb(ha, scb);
- scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = IPS_CMD_GET_SUBSYS;
- scb->cmd.basic_io.op_code = IPS_CMD_GET_SUBSYS;
- scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.basic_io.sg_count = 0;
- scb->cmd.basic_io.sg_addr = cpu_to_le32(VIRT_TO_BUS(ha->subsys));
- scb->cmd.basic_io.lba = 0;
- scb->cmd.basic_io.sector_count = 0;
- scb->cmd.basic_io.log_drv = 0;
- scb->cmd.basic_io.reserved = 0;
- /* send command */
- if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
- (ret == IPS_SUCCESS_IMM) ||
- ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
- return (0);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_read_config */
- /* */
- /* Routine Description: */
- /* */
- /* Read the configuration on the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_read_config(ips_ha_t *ha, int intr) {
- ips_scb_t *scb;
- int i;
- int ret;
- METHOD_TRACE("ips_read_config", 1);
- /* set defaults for initiator IDs */
- for (i = 0; i < 4; i++)
- ha->conf->init_id[i] = 7;
- scb = &ha->scbs[ha->max_cmds-1];
- ips_init_scb(ha, scb);
- scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = IPS_CMD_READ_CONF;
- scb->cmd.basic_io.op_code = IPS_CMD_READ_CONF;
- scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.basic_io.sg_addr = cpu_to_le32(VIRT_TO_BUS(ha->conf));
- /* send command */
- if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
- (ret == IPS_SUCCESS_IMM) ||
- ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
- memset(ha->conf, 0, sizeof(IPS_CONF));
- /* reset initiator IDs */
- for (i = 0; i < 4; i++)
- ha->conf->init_id[i] = 7;
- return (0);
- }
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_readwrite_page5 */
- /* */
- /* Routine Description: */
- /* */
- /* Read nvram page 5 from the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_readwrite_page5(ips_ha_t *ha, int write, int intr) {
- ips_scb_t *scb;
- int ret;
- METHOD_TRACE("ips_readwrite_page5", 1);
- scb = &ha->scbs[ha->max_cmds-1];
- ips_init_scb(ha, scb);
- scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = IPS_CMD_RW_NVRAM_PAGE;
- scb->cmd.nvram.op_code = IPS_CMD_RW_NVRAM_PAGE;
- scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.nvram.page = 5;
- scb->cmd.nvram.write = write;
- scb->cmd.nvram.buffer_addr = cpu_to_le32(VIRT_TO_BUS(ha->nvram));
- scb->cmd.nvram.reserved = 0;
- scb->cmd.nvram.reserved2 = 0;
- /* issue the command */
- if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
- (ret == IPS_SUCCESS_IMM) ||
- ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
- memset(ha->nvram, 0, sizeof(IPS_NVRAM_P5));
- return (0);
- }
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_clear_adapter */
- /* */
- /* Routine Description: */
- /* */
- /* Clear the stripe lock tables */
- /* */
- /****************************************************************************/
- static int
- ips_clear_adapter(ips_ha_t *ha, int intr) {
- ips_scb_t *scb;
- int ret;
- METHOD_TRACE("ips_clear_adapter", 1);
- scb = &ha->scbs[ha->max_cmds-1];
- ips_init_scb(ha, scb);
- scb->timeout = ips_reset_timeout;
- scb->cdb[0] = IPS_CMD_CONFIG_SYNC;
- scb->cmd.config_sync.op_code = IPS_CMD_CONFIG_SYNC;
- scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.config_sync.channel = 0;
- scb->cmd.config_sync.source_target = IPS_POCL;
- scb->cmd.config_sync.reserved = 0;
- scb->cmd.config_sync.reserved2 = 0;
- scb->cmd.config_sync.reserved3 = 0;
- /* issue command */
- if (((ret = ips_send_wait(ha, scb, ips_reset_timeout, intr)) == IPS_FAILURE) ||
- (ret == IPS_SUCCESS_IMM) ||
- ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
- return (0);
- /* send unlock stripe command */
- ips_init_scb(ha, scb);
- scb->cdb[0] = IPS_CMD_ERROR_TABLE;
- scb->timeout = ips_reset_timeout;
- scb->cmd.unlock_stripe.op_code = IPS_CMD_ERROR_TABLE;
- scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.unlock_stripe.log_drv = 0;
- scb->cmd.unlock_stripe.control = IPS_CSL;
- scb->cmd.unlock_stripe.reserved = 0;
- scb->cmd.unlock_stripe.reserved2 = 0;
- scb->cmd.unlock_stripe.reserved3 = 0;
- /* issue command */
- if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
- (ret == IPS_SUCCESS_IMM) ||
- ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
- return (0);
- return (1);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_ffdc_reset */
- /* */
- /* Routine Description: */
- /* */
- /* FFDC: write reset info */
- /* */
- /****************************************************************************/
- static void
- ips_ffdc_reset(ips_ha_t *ha, int intr) {
- ips_scb_t *scb;
- METHOD_TRACE("ips_ffdc_reset", 1);
- scb = &ha->scbs[ha->max_cmds-1];
- ips_init_scb(ha, scb);
- scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = IPS_CMD_FFDC;
- scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
- scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.ffdc.reset_count = ha->reset_count;
- scb->cmd.ffdc.reset_type = 0x80;
- /* convert time to what the card wants */
- ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
- /* issue command */
- ips_send_wait(ha, scb, ips_cmd_timeout, intr);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_ffdc_time */
- /* */
- /* Routine Description: */
- /* */
- /* FFDC: write time info */
- /* */
- /****************************************************************************/
- static void
- ips_ffdc_time(ips_ha_t *ha, int intr) {
- ips_scb_t *scb;
- METHOD_TRACE("ips_ffdc_time", 1);
- DEBUG_VAR(1, "(%s%d) Sending time update.",
- ips_name, ha->host_num);
- scb = &ha->scbs[ha->max_cmds-1];
- ips_init_scb(ha, scb);
- scb->timeout = ips_cmd_timeout;
- scb->cdb[0] = IPS_CMD_FFDC;
- scb->cmd.ffdc.op_code = IPS_CMD_FFDC;
- scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb);
- scb->cmd.ffdc.reset_count = 0;
- scb->cmd.ffdc.reset_type = 0x80;
- /* convert time to what the card wants */
- ips_fix_ffdc_time(ha, scb, ha->last_ffdc);
- /* issue command */
- ips_send_wait(ha, scb, ips_cmd_timeout, intr);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_fix_ffdc_time */
- /* */
- /* Routine Description: */
- /* Adjust time_t to what the card wants */
- /* */
- /****************************************************************************/
- static void
- ips_fix_ffdc_time(ips_ha_t *ha, ips_scb_t *scb, time_t current_time) {
- long days;
- long rem;
- int i;
- int year;
- int yleap;
- int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR };
- int month_lengths[12][2] = { {31, 31},
- {28, 29},
- {31, 31},
- {30, 30},
- {31, 31},
- {30, 30},
- {31, 31},
- {31, 31},
- {30, 30},
- {31, 31},
- {30, 30},
- {31, 31} };
- METHOD_TRACE("ips_fix_ffdc_time", 1);
- days = current_time / IPS_SECS_DAY;
- rem = current_time % IPS_SECS_DAY;
- scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR);
- rem = rem % IPS_SECS_HOUR;
- scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN);
- scb->cmd.ffdc.second = (rem % IPS_SECS_MIN);
- year = IPS_EPOCH_YEAR;
- while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) {
- int newy;
- newy = year + (days / IPS_DAYS_NORMAL_YEAR);
- if (days < 0)
- --newy;
- days -= (newy - year) * IPS_DAYS_NORMAL_YEAR +
- IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) -
- IPS_NUM_LEAP_YEARS_THROUGH(year - 1);
- year = newy;
- }
- scb->cmd.ffdc.yearH = year / 100;
- scb->cmd.ffdc.yearL = year % 100;
- for (i = 0; days >= month_lengths[i][yleap]; ++i)
- days -= month_lengths[i][yleap];
- scb->cmd.ffdc.month = i + 1;
- scb->cmd.ffdc.day = days + 1;
- }
- /****************************************************************************
- * BIOS Flash Routines *
- ****************************************************************************/
- /****************************************************************************/
- /* */
- /* Routine Name: ips_erase_bios */
- /* */
- /* Routine Description: */
- /* Erase the BIOS on the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_erase_bios(ips_ha_t *ha) {
- int timeout;
- u_int8_t status=0;
- METHOD_TRACE("ips_erase_bios", 1);
- status = 0;
- /* Clear the status register */
- outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- outb(0x50, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* Erase Setup */
- outb(0x20, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* Erase Confirm */
- outb(0xD0, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* Erase Status */
- outb(0x70, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- timeout = 80000; /* 80 seconds */
- while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
- outl(0, ha->io_addr + IPS_REG_FLAP);
- udelay(5); /* 5 us */
- }
- status = inb(ha->io_addr + IPS_REG_FLDP);
- if (status & 0x80)
- break;
- MDELAY(1);
- timeout--;
- }
- /* check for timeout */
- if (timeout <= 0) {
- /* timeout */
- /* try to suspend the erase */
- outb(0xB0, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* wait for 10 seconds */
- timeout = 10000;
- while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
- outl(0, ha->io_addr + IPS_REG_FLAP);
- udelay(5); /* 5 us */
- }
- status = inb(ha->io_addr + IPS_REG_FLDP);
- if (status & 0xC0)
- break;
- MDELAY(1);
- timeout--;
- }
- return (1);
- }
- /* check for valid VPP */
- if (status & 0x08)
- /* VPP failure */
- return (1);
- /* check for succesful flash */
- if (status & 0x30)
- /* sequence error */
- return (1);
- /* Otherwise, we were successful */
- /* clear status */
- outb(0x50, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* enable reads */
- outb(0xFF, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_erase_bios_memio */
- /* */
- /* Routine Description: */
- /* Erase the BIOS on the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_erase_bios_memio(ips_ha_t *ha) {
- int timeout;
- u_int8_t status;
- METHOD_TRACE("ips_erase_bios_memio", 1);
- status = 0;
- /* Clear the status register */
- writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* Erase Setup */
- writeb(0x20, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* Erase Confirm */
- writeb(0xD0, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* Erase Status */
- writeb(0x70, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- timeout = 80000; /* 80 seconds */
- while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
- writel(0, ha->mem_ptr + IPS_REG_FLAP);
- udelay(5); /* 5 us */
- }
- status = readb(ha->mem_ptr + IPS_REG_FLDP);
- if (status & 0x80)
- break;
- MDELAY(1);
- timeout--;
- }
- /* check for timeout */
- if (timeout <= 0) {
- /* timeout */
- /* try to suspend the erase */
- writeb(0xB0, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* wait for 10 seconds */
- timeout = 10000;
- while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
- writel(0, ha->mem_ptr + IPS_REG_FLAP);
- udelay(5); /* 5 us */
- }
- status = readb(ha->mem_ptr + IPS_REG_FLDP);
- if (status & 0xC0)
- break;
- MDELAY(1);
- timeout--;
- }
- return (1);
- }
- /* check for valid VPP */
- if (status & 0x08)
- /* VPP failure */
- return (1);
- /* check for succesful flash */
- if (status & 0x30)
- /* sequence error */
- return (1);
- /* Otherwise, we were successful */
- /* clear status */
- writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* enable reads */
- writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_program_bios */
- /* */
- /* Routine Description: */
- /* Program the BIOS on the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_program_bios(ips_ha_t *ha, char *buffer, u_int32_t buffersize, u_int32_t offset) {
- int i;
- int timeout;
- u_int8_t status=0;
- METHOD_TRACE("ips_program_bios", 1);
- status = 0;
- for (i = 0; i < buffersize; i++) {
- /* write a byte */
- outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- outb(0x40, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- outb(buffer[i], ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* wait up to one second */
- timeout = 1000;
- while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
- outl(0, ha->io_addr + IPS_REG_FLAP);
- udelay(5); /* 5 us */
- }
- status = inb(ha->io_addr + IPS_REG_FLDP);
- if (status & 0x80)
- break;
- MDELAY(1);
- timeout--;
- }
- if (timeout == 0) {
- /* timeout error */
- outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- outb(0xFF, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- return (1);
- }
- /* check the status */
- if (status & 0x18) {
- /* programming error */
- outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- outb(0xFF, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- return (1);
- }
- } /* end for */
- /* Enable reading */
- outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- outb(0xFF, ha->io_addr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_program_bios_memio */
- /* */
- /* Routine Description: */
- /* Program the BIOS on the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_program_bios_memio(ips_ha_t *ha, char *buffer, u_int32_t buffersize, u_int32_t offset) {
- int i;
- int timeout;
- u_int8_t status=0;
- METHOD_TRACE("ips_program_bios_memio", 1);
- status = 0;
- for (i = 0; i < buffersize; i++) {
- /* write a byte */
- writel(cpu_to_le32(i + offset), ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- writeb(0x40, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- writeb(buffer[i], ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- /* wait up to one second */
- timeout = 1000;
- while (timeout > 0) {
- if (ha->revision_id == IPS_REVID_TROMBONE64) {
- writel(0, ha->mem_ptr + IPS_REG_FLAP);
- udelay(5); /* 5 us */
- }
- status = readb(ha->mem_ptr + IPS_REG_FLDP);
- if (status & 0x80)
- break;
- MDELAY(1);
- timeout--;
- }
- if (timeout == 0) {
- /* timeout error */
- writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- return (1);
- }
- /* check the status */
- if (status & 0x18) {
- /* programming error */
- writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- return (1);
- }
- } /* end for */
- /* Enable reading */
- writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_verify_bios */
- /* */
- /* Routine Description: */
- /* Verify the BIOS on the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_verify_bios(ips_ha_t *ha, char *buffer, u_int32_t buffersize, u_int32_t offset) {
- u_int8_t checksum;
- int i;
- METHOD_TRACE("ips_verify_bios", 1);
- /* test 1st byte */
- outl(0, ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
- return (1);
- outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
- return (1);
- checksum = 0xff;
- for (i = 2; i < buffersize; i++) {
- outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- checksum = (u_int8_t) checksum + inb(ha->io_addr + IPS_REG_FLDP);
- }
- if (checksum != 0)
- /* failure */
- return (1);
- else
- /* success */
- return (0);
- }
- /****************************************************************************/
- /* */
- /* Routine Name: ips_verify_bios_memio */
- /* */
- /* Routine Description: */
- /* Verify the BIOS on the adapter */
- /* */
- /****************************************************************************/
- static int
- ips_verify_bios_memio(ips_ha_t *ha, char *buffer, u_int32_t buffersize, u_int32_t offset) {
- u_int8_t checksum;
- int i;
- METHOD_TRACE("ips_verify_bios_memio", 1);
- /* test 1st byte */
- writel(0, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
- return (1);
- writel(1, ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
- return (1);
- checksum = 0xff;
- for (i = 2; i < buffersize; i++) {
- writel(cpu_to_le32(i + offset), ha->mem_ptr + IPS_REG_FLAP);
- if (ha->revision_id == IPS_REVID_TROMBONE64)
- udelay(5); /* 5 us */
- checksum = (u_int8_t) checksum + readb(ha->mem_ptr + IPS_REG_FLDP);
- }
- if (checksum != 0)
- /* failure */
- return (1);
- else
- /* success */
- return (0);
- }
- #if defined (MODULE) || (LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0))
- static Scsi_Host_Template driver_template = IPS;
- #include "scsi_module.c"
- #endif
- /*
- * Overrides for Emacs so that we almost follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 2
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -2
- * c-argdecl-indent: 2
- * c-label-offset: -2
- * c-continued-statement-offset: 2
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */