diff options
Diffstat (limited to 'drivers')
80 files changed, 4585 insertions, 18074 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 90961a8ea895..4aca7ddfdddf 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -555,7 +555,6 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag) { struct scsi_cmnd *cmd; ctlr_info_t *ctlr; - u64bit addr64; ErrorInfo_struct *ei; ei = cp->err_info; @@ -569,20 +568,7 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag) cmd = (struct scsi_cmnd *) cp->scsi_cmd; ctlr = hba[cp->ctlr]; - /* undo the DMA mappings */ - - if (cmd->use_sg) { - pci_unmap_sg(ctlr->pdev, - cmd->request_buffer, cmd->use_sg, - cmd->sc_data_direction); - } - else if (cmd->request_bufflen) { - addr64.val32.lower = cp->SG[0].Addr.lower; - addr64.val32.upper = cp->SG[0].Addr.upper; - pci_unmap_single(ctlr->pdev, (dma_addr_t) addr64.val, - cmd->request_bufflen, - cmd->sc_data_direction); - } + scsi_dma_unmap(cmd); cmd->result = (DID_OK << 16); /* host byte */ cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ @@ -597,7 +583,7 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag) ei->SenseLen > SCSI_SENSE_BUFFERSIZE ? SCSI_SENSE_BUFFERSIZE : ei->SenseLen); - cmd->resid = ei->ResidualCnt; + scsi_set_resid(cmd, ei->ResidualCnt); if(ei->CommandStatus != 0) { /* an error has occurred */ @@ -1204,46 +1190,29 @@ cciss_scatter_gather(struct pci_dev *pdev, CommandList_struct *cp, struct scsi_cmnd *cmd) { - unsigned int use_sg, nsegs=0, len; - struct scatterlist *scatter = (struct scatterlist *) cmd->request_buffer; + unsigned int len; + struct scatterlist *sg; __u64 addr64; - - /* is it just one virtual address? */ - if (!cmd->use_sg) { - if (cmd->request_bufflen) { /* anything to xfer? */ - - addr64 = (__u64) pci_map_single(pdev, - cmd->request_buffer, - cmd->request_bufflen, - cmd->sc_data_direction); - - cp->SG[0].Addr.lower = - (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); - cp->SG[0].Addr.upper = - (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); - cp->SG[0].Len = cmd->request_bufflen; - nsegs=1; - } - } /* else, must be a list of virtual addresses.... */ - else if (cmd->use_sg <= MAXSGENTRIES) { /* not too many addrs? */ - - use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, - cmd->sc_data_direction); - - for (nsegs=0; nsegs < use_sg; nsegs++) { - addr64 = (__u64) sg_dma_address(&scatter[nsegs]); - len = sg_dma_len(&scatter[nsegs]); - cp->SG[nsegs].Addr.lower = - (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); - cp->SG[nsegs].Addr.upper = - (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); - cp->SG[nsegs].Len = len; - cp->SG[nsegs].Ext = 0; // we are not chaining + int use_sg, i; + + BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES); + + use_sg = scsi_dma_map(cmd); + if (use_sg) { /* not too many addrs? */ + scsi_for_each_sg(cmd, sg, use_sg, i) { + addr64 = (__u64) sg_dma_address(sg); + len = sg_dma_len(sg); + cp->SG[i].Addr.lower = + (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); + cp->SG[i].Addr.upper = + (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF); + cp->SG[i].Len = len; + cp->SG[i].Ext = 0; // we are not chaining } - } else BUG(); + } - cp->Header.SGList = (__u8) nsegs; /* no. SGs contig in this cmd */ - cp->Header.SGTotal = (__u16) nsegs; /* total sgs in this cmd list */ + cp->Header.SGList = (__u8) use_sg; /* no. SGs contig in this cmd */ + cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */ return; } diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 875eadd5e8f5..ce86ff226a28 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1489,69 +1489,6 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, } } -static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb, - struct sbp2_fwhost_info *hi, - struct sbp2_command_info *cmd, - struct scatterlist *sgpnt, - u32 orb_direction, - unsigned int scsi_request_bufflen, - void *scsi_request_buffer, - enum dma_data_direction dma_dir) -{ - cmd->dma_dir = dma_dir; - cmd->dma_size = scsi_request_bufflen; - cmd->dma_type = CMD_DMA_SINGLE; - cmd->cmd_dma = dma_map_single(hi->host->device.parent, - scsi_request_buffer, - cmd->dma_size, cmd->dma_dir); - orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); - orb->misc |= ORB_SET_DIRECTION(orb_direction); - - /* handle case where we get a command w/o s/g enabled - * (but check for transfers larger than 64K) */ - if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) { - - orb->data_descriptor_lo = cmd->cmd_dma; - orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen); - - } else { - /* The buffer is too large. Turn this into page tables. */ - - struct sbp2_unrestricted_page_table *sg_element = - &cmd->scatter_gather_element[0]; - u32 sg_count, sg_len; - dma_addr_t sg_addr; - - orb->data_descriptor_lo = cmd->sge_dma; - orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); - - /* fill out our SBP-2 page tables; split up the large buffer */ - sg_count = 0; - sg_len = scsi_request_bufflen; - sg_addr = cmd->cmd_dma; - while (sg_len) { - sg_element[sg_count].segment_base_lo = sg_addr; - if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { - sg_element[sg_count].length_segment_base_hi = - PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); - sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; - sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; - } else { - sg_element[sg_count].length_segment_base_hi = - PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); - sg_len = 0; - } - sg_count++; - } - - orb->misc |= ORB_SET_DATA_SIZE(sg_count); - - sbp2util_cpu_to_be32_buffer(sg_element, - (sizeof(struct sbp2_unrestricted_page_table)) * - sg_count); - } -} - static void sbp2_create_command_orb(struct sbp2_lu *lu, struct sbp2_command_info *cmd, unchar *scsi_cmd, @@ -1595,13 +1532,9 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu, orb->data_descriptor_hi = 0x0; orb->data_descriptor_lo = 0x0; orb->misc |= ORB_SET_DIRECTION(1); - } else if (scsi_use_sg) + } else sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt, orb_direction, dma_dir); - else - sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction, - scsi_request_bufflen, - scsi_request_buffer, dma_dir); sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb)); @@ -1690,15 +1623,15 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { unchar *scsi_cmd = (unchar *)SCpnt->cmnd; - unsigned int request_bufflen = SCpnt->request_bufflen; + unsigned int request_bufflen = scsi_bufflen(SCpnt); struct sbp2_command_info *cmd; cmd = sbp2util_allocate_command_orb(lu, SCpnt, done); if (!cmd) return -EIO; - sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg, - request_bufflen, SCpnt->request_buffer, + sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt), + request_bufflen, scsi_sglist(SCpnt), SCpnt->sc_data_direction); sbp2_link_orb_command(lu, cmd); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 3bd94f11e7d6..bc740a6dd93c 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -260,30 +260,13 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, /* Map the data portion, if any. * sges_left = 0 if no data transfer. */ - if ( (sges_left = SCpnt->use_sg) ) { - sges_left = pci_map_sg(ioc->pcidev, - (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, - SCpnt->sc_data_direction); - if (sges_left == 0) - return FAILED; - } else if (SCpnt->request_bufflen) { - SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev, - SCpnt->request_buffer, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n", - ioc->name, SCpnt, SCpnt->request_bufflen)); - mptscsih_add_sge((char *) &pReq->SGL, - 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen, - SCpnt->SCp.dma_handle); - - return SUCCESS; - } + sges_left = scsi_dma_map(SCpnt); + if (sges_left < 0) + return FAILED; /* Handle the SG case. */ - sg = (struct scatterlist *) SCpnt->request_buffer; + sg = scsi_sglist(SCpnt); sg_done = 0; sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION); chainSge = NULL; @@ -662,7 +645,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) scsi_state = pScsiReply->SCSIState; scsi_status = pScsiReply->SCSIStatus; xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); - sc->resid = sc->request_bufflen - xfer_cnt; + scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt); log_info = le32_to_cpu(pScsiReply->IOCLogInfo); /* @@ -767,7 +750,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) break; case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - sc->resid = sc->request_bufflen - xfer_cnt; + scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt); if((xfer_cnt==0)||(sc->underflow > xfer_cnt)) sc->result=DID_SOFT_ERROR << 16; else /* Sufficient data transfer occurred */ @@ -816,7 +799,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) break; case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ - sc->resid=0; + scsi_set_resid(sc, 0); case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ sc->result = (DID_OK << 16) | scsi_status; @@ -899,23 +882,18 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) scsi_state, scsi_status, log_info)); dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d " - "bufflen=%d xfer_cnt=%d\n", __FUNCTION__, - sc->device->host->host_no, sc->device->channel, sc->device->id, - sc->device->lun, sc->resid, sc->request_bufflen, - xfer_cnt)); + "bufflen=%d xfer_cnt=%d\n", __FUNCTION__, + sc->device->host->host_no, + sc->device->channel, sc->device->id, + sc->device->lun, scsi_get_resid(sc), + scsi_bufflen(sc), xfer_cnt)); } #endif } /* end of address reply case */ /* Unmap the DMA buffers, if any. */ - if (sc->use_sg) { - pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer, - sc->use_sg, sc->sc_data_direction); - } else if (sc->request_bufflen) { - pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle, - sc->request_bufflen, sc->sc_data_direction); - } + scsi_dma_unmap(sc); sc->scsi_done(sc); /* Issue the command callback */ @@ -970,17 +948,8 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) /* Set status, free OS resources (SG DMA buffers) * Do OS callback */ - if (SCpnt->use_sg) { - pci_unmap_sg(ioc->pcidev, - (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, - SCpnt->sc_data_direction); - } else if (SCpnt->request_bufflen) { - pci_unmap_single(ioc->pcidev, - SCpnt->SCp.dma_handle, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - } + scsi_dma_unmap(SCpnt); + SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; @@ -1039,17 +1008,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); if ((unsigned char *)mf != sc->host_scribble) continue; - if (sc->use_sg) { - pci_unmap_sg(hd->ioc->pcidev, - (struct scatterlist *) sc->request_buffer, - sc->use_sg, - sc->sc_data_direction); - } else if (sc->request_bufflen) { - pci_unmap_single(hd->ioc->pcidev, - sc->SCp.dma_handle, - sc->request_bufflen, - sc->sc_data_direction); - } + scsi_dma_unmap(sc); + sc->host_scribble = NULL; sc->result = DID_NO_CONNECT << 16; sc->scsi_done(sc); @@ -1380,10 +1340,10 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) * will be no data transfer! GRRRRR... */ if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { - datalen = SCpnt->request_bufflen; + datalen = scsi_bufflen(SCpnt); scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */ } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { - datalen = SCpnt->request_bufflen; + datalen = scsi_bufflen(SCpnt); scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */ } else { datalen = 0; diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index eb766c3af1c8..113aaed490d4 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1306,22 +1306,26 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) wake_up(&tw_dev->ioctl_wqueue); } } else { + struct scsi_cmnd *cmd; + + cmd = tw_dev->srb[request_id]; + twa_scsiop_execute_scsi_complete(tw_dev, request_id); /* If no error command was a success */ if (error == 0) { - tw_dev->srb[request_id]->result = (DID_OK << 16); + cmd->result = (DID_OK << 16); } /* If error, command failed */ if (error == 1) { /* Ask for a host reset */ - tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); + cmd->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } /* Report residual bytes for single sgl */ - if ((tw_dev->srb[request_id]->use_sg <= 1) && (full_command_packet->command.newcommand.status == 0)) { - if (full_command_packet->command.newcommand.sg_list[0].length < tw_dev->srb[request_id]->request_bufflen) - tw_dev->srb[request_id]->resid = tw_dev->srb[request_id]->request_bufflen - full_command_packet->command.newcommand.sg_list[0].length; + if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) { + if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id])) + scsi_set_resid(cmd, scsi_bufflen(cmd) - full_command_packet->command.newcommand.sg_list[0].length); } /* Now complete the io */ @@ -1384,52 +1388,20 @@ static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) { int use_sg; struct scsi_cmnd *cmd = tw_dev->srb[request_id]; - struct pci_dev *pdev = tw_dev->tw_pci_dev; - int retval = 0; - - if (cmd->use_sg == 0) - goto out; - - use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); - if (use_sg == 0) { + use_sg = scsi_dma_map(cmd); + if (!use_sg) + return 0; + else if (use_sg < 0) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); - goto out; + return 0; } cmd->SCp.phase = TW_PHASE_SGLIST; cmd->SCp.have_data_in = use_sg; - retval = use_sg; -out: - return retval; -} /* End twa_map_scsi_sg_data() */ -/* This function will perform a pci-dma map for a single buffer */ -static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int request_id) -{ - dma_addr_t mapping; - struct scsi_cmnd *cmd = tw_dev->srb[request_id]; - struct pci_dev *pdev = tw_dev->tw_pci_dev; - dma_addr_t retval = 0; - - if (cmd->request_bufflen == 0) { - retval = 0; - goto out; - } - - mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, DMA_BIDIRECTIONAL); - - if (mapping == 0) { - TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Failed to map page"); - goto out; - } - - cmd->SCp.phase = TW_PHASE_SINGLE; - cmd->SCp.have_data_in = mapping; - retval = mapping; -out: - return retval; -} /* End twa_map_scsi_single_data() */ + return use_sg; +} /* End twa_map_scsi_sg_data() */ /* This function will poll for a response interrupt of a request */ static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) @@ -1815,15 +1787,13 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, u32 num_sectors = 0x0; int i, sg_count; struct scsi_cmnd *srb = NULL; - struct scatterlist *sglist = NULL; - dma_addr_t buffaddr = 0x0; + struct scatterlist *sglist = NULL, *sg; int retval = 1; if (tw_dev->srb[request_id]) { - if (tw_dev->srb[request_id]->request_buffer) { - sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; - } srb = tw_dev->srb[request_id]; + if (scsi_sglist(srb)) + sglist = scsi_sglist(srb); } /* Initialize command packet */ @@ -1856,32 +1826,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, if (!sglistarg) { /* Map sglist from scsi layer to cmd packet */ - if (tw_dev->srb[request_id]->use_sg == 0) { - if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) { - command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); - command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); - if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) - memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen); - } else { - buffaddr = twa_map_scsi_single_data(tw_dev, request_id); - if (buffaddr == 0) - goto out; - - command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr); - command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen); - } - command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1)); - - if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { - TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi"); - goto out; - } - } - if (tw_dev->srb[request_id]->use_sg > 0) { - if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) { - if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) { - struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; + if (scsi_sg_count(srb)) { + if ((scsi_sg_count(srb) == 1) && + (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) { + if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) { + struct scatterlist *sg = scsi_sglist(srb); char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length); kunmap_atomic(buf - sg->offset, KM_IRQ0); @@ -1893,16 +1843,16 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, if (sg_count == 0) goto out; - for (i = 0; i < sg_count; i++) { - command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i])); - command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i])); + scsi_for_each_sg(srb, sg, sg_count, i) { + command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg)); + command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(sg)); if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi"); goto out; } } } - command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg)); + command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id]))); } } else { /* Internal cdb post */ @@ -1932,7 +1882,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, /* Update SG statistics */ if (srb) { - tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg; + tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]); if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) tw_dev->max_sgl_entries = tw_dev->sgl_entries; } @@ -1951,16 +1901,19 @@ out: /* This function completes an execute scsi operation */ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id) { - if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH && - (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE || - tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) { - if (tw_dev->srb[request_id]->use_sg == 0) { - memcpy(tw_dev->srb[request_id]->request_buffer, + struct scsi_cmnd *cmd = tw_dev->srb[request_id]; + int use_sg = scsi_sg_count(cmd); + + if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH && + (cmd->sc_data_direction == DMA_FROM_DEVICE || + cmd->sc_data_direction == DMA_BIDIRECTIONAL)) { + if (!use_sg) + memcpy(scsi_sglist(cmd), tw_dev->generic_buffer_virt[request_id], - tw_dev->srb[request_id]->request_bufflen); - } - if (tw_dev->srb[request_id]->use_sg == 1) { - struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; + scsi_bufflen(cmd)); + + if (use_sg == 1) { + struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]); char *buf; unsigned long flags = 0; local_irq_save(flags); @@ -2017,16 +1970,8 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code) static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) { struct scsi_cmnd *cmd = tw_dev->srb[request_id]; - struct pci_dev *pdev = tw_dev->tw_pci_dev; - switch(cmd->SCp.phase) { - case TW_PHASE_SINGLE: - pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL); - break; - case TW_PHASE_SGLIST: - pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); - break; - } + scsi_dma_unmap(cmd); } /* End twa_unmap_scsi_data() */ /* scsi_host_template initializer */ diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 656bdb1352d8..c7995fc216e8 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -1273,57 +1273,24 @@ static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) int use_sg; dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n"); - - if (cmd->use_sg == 0) - return 0; - use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); - - if (use_sg == 0) { + use_sg = scsi_dma_map(cmd); + if (use_sg < 0) { printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); return 0; } cmd->SCp.phase = TW_PHASE_SGLIST; cmd->SCp.have_data_in = use_sg; - + return use_sg; } /* End tw_map_scsi_sg_data() */ -static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) -{ - dma_addr_t mapping; - - dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n"); - - if (cmd->request_bufflen == 0) - return 0; - - mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL); - - if (mapping == 0) { - printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n"); - return 0; - } - - cmd->SCp.phase = TW_PHASE_SINGLE; - cmd->SCp.have_data_in = mapping; - - return mapping; -} /* End tw_map_scsi_single_data() */ - static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) { dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n"); - switch(cmd->SCp.phase) { - case TW_PHASE_SINGLE: - pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL); - break; - case TW_PHASE_SGLIST: - pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); - break; - } + scsi_dma_unmap(cmd); } /* End tw_unmap_scsi_data() */ /* This function will reset a device extension */ @@ -1499,27 +1466,16 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id, void *buf; unsigned int transfer_len; unsigned long flags = 0; + struct scatterlist *sg = scsi_sglist(cmd); - if (cmd->use_sg) { - struct scatterlist *sg = - (struct scatterlist *)cmd->request_buffer; - local_irq_save(flags); - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; - transfer_len = min(sg->length, len); - } else { - buf = cmd->request_buffer; - transfer_len = min(cmd->request_bufflen, len); - } + local_irq_save(flags); + buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + transfer_len = min(sg->length, len); memcpy(buf, data, transfer_len); - - if (cmd->use_sg) { - struct scatterlist *sg; - sg = (struct scatterlist *)cmd->request_buffer; - kunmap_atomic(buf - sg->offset, KM_IRQ0); - local_irq_restore(flags); - } + kunmap_atomic(buf - sg->offset, KM_IRQ0); + local_irq_restore(flags); } /* This function is called by the isr to complete an inquiry command */ @@ -1764,19 +1720,20 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) { TW_Command *command_packet; unsigned long command_que_value; - u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0; + u32 lba = 0x0, num_sectors = 0x0; int i, use_sg; struct scsi_cmnd *srb; - struct scatterlist *sglist; + struct scatterlist *sglist, *sg; dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n"); - if (tw_dev->srb[request_id]->request_buffer == NULL) { + srb = tw_dev->srb[request_id]; + + sglist = scsi_sglist(srb); + if (!sglist) { printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n"); return 1; } - sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; - srb = tw_dev->srb[request_id]; /* Initialize command packet */ command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; @@ -1819,33 +1776,18 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) command_packet->byte8.io.lba = lba; command_packet->byte6.block_count = num_sectors; - /* Do this if there are no sg list entries */ - if (tw_dev->srb[request_id]->use_sg == 0) { - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n"); - buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); - if (buffaddr == 0) - return 1; + use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); + if (!use_sg) + return 1; - command_packet->byte8.io.sgl[0].address = buffaddr; - command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen; + scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) { + command_packet->byte8.io.sgl[i].address = sg_dma_address(sg); + command_packet->byte8.io.sgl[i].length = sg_dma_len(sg); command_packet->size+=2; } - /* Do this if we have multiple sg list entries */ - if (tw_dev->srb[request_id]->use_sg > 0) { - use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); - if (use_sg == 0) - return 1; - - for (i=0;i<use_sg; i++) { - command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]); - command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]); - command_packet->size+=2; - } - } - /* Update SG statistics */ - tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg; + tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]); if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) tw_dev->max_sgl_entries = tw_dev->sgl_entries; diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index cb02656eb54c..405d9d6f9653 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -585,16 +585,8 @@ NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, struct scsi_cmnd *SCp, struct NCR_700_command_slot *slot) { if(SCp->sc_data_direction != DMA_NONE && - SCp->sc_data_direction != DMA_BIDIRECTIONAL) { - if(SCp->use_sg) { - dma_unmap_sg(hostdata->dev, SCp->request_buffer, - SCp->use_sg, SCp->sc_data_direction); - } else { - dma_unmap_single(hostdata->dev, slot->dma_handle, - SCp->request_bufflen, - SCp->sc_data_direction); - } - } + SCp->sc_data_direction != DMA_BIDIRECTIONAL) + scsi_dma_unmap(SCp); } STATIC inline void @@ -1263,14 +1255,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, host->host_no, pun, lun, NCR_700_condition[i], NCR_700_phase[j], dsp - hostdata->pScript); if(SCp != NULL) { - scsi_print_command(SCp); + struct scatterlist *sg; - if(SCp->use_sg) { - for(i = 0; i < SCp->use_sg + 1; i++) { - printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); - } + scsi_print_command(SCp); + scsi_for_each_sg(SCp, sg, scsi_sg_count(SCp) + 1, i) { + printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, sg->length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); } - } + } NCR_700_internal_bus_reset(host); } else if((dsps & 0xfffff000) == A_DEBUG_INTERRUPT) { printk(KERN_NOTICE "scsi%d (%d:%d) DEBUG INTERRUPT %d AT %08x[%04x], continuing\n", @@ -1844,8 +1835,8 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) } /* sanity check: some of the commands generated by the mid-layer * have an eccentric idea of their sc_data_direction */ - if(!SCp->use_sg && !SCp->request_bufflen - && SCp->sc_data_direction != DMA_NONE) { + if(!scsi_sg_count(SCp) && !scsi_bufflen(SCp) && + SCp->sc_data_direction != DMA_NONE) { #ifdef NCR_700_DEBUG printk("53c700: Command"); scsi_print_command(SCp); @@ -1887,31 +1878,15 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) int i; int sg_count; dma_addr_t vPtr = 0; + struct scatterlist *sg; __u32 count = 0; - if(SCp->use_sg) { - sg_count = dma_map_sg(hostdata->dev, - SCp->request_buffer, SCp->use_sg, - direction); - } else { - vPtr = dma_map_single(hostdata->dev, - SCp->request_buffer, - SCp->request_bufflen, - direction); - count = SCp->request_bufflen; - slot->dma_handle = vPtr; - sg_count = 1; - } - + sg_count = scsi_dma_map(SCp); + BUG_ON(sg_count < 0); - for(i = 0; i < sg_count; i++) { - - if(SCp->use_sg) { - struct scatterlist *sg = SCp->request_buffer; - - vPtr = sg_dma_address(&sg[i]); - count = sg_dma_len(&sg[i]); - } + scsi_for_each_sg(SCp, sg, sg_count, i) { + vPtr = sg_dma_address(sg); + count = sg_dma_len(sg); slot->SG[i].ins = bS_to_host(move_ins | count); DEBUG((" scatter block %d: move %d[%08x] from 0x%lx\n", diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c deleted file mode 100644 index 93b41f45638a..000000000000 --- a/drivers/scsi/53c7xx.c +++ /dev/null @@ -1,6102 +0,0 @@ -/* - * 53c710 driver. Modified from Drew Eckhardts driver - * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk] - * Check out PERM_OPTIONS and EXPECTED_CLOCK, which may be defined in the - * relevant machine specific file (eg. mvme16x.[ch], amiga7xx.[ch]). - * There are also currently some defines at the top of 53c7xx.scr. - * The chip type is #defined in script_asm.pl, as well as the Makefile. - * Host scsi ID expected to be 7 - see NCR53c7x0_init(). - * - * I have removed the PCI code and some of the 53c8xx specific code - - * simply to make this file smaller and easier to manage. - * - * MVME16x issues: - * Problems trying to read any chip registers in NCR53c7x0_init(), as they - * may never have been set by 16xBug (eg. If kernel has come in over tftp). - */ - -/* - * Adapted for Linux/m68k Amiga platforms for the A4000T/A4091 and - * WarpEngine SCSI controllers. - * By Alan Hourihane <alanh@fairlite.demon.co.uk> - * Thanks to Richard Hirst for making it possible with the MVME additions - */ - -/* - * 53c710 rev 0 doesn't support add with carry. Rev 1 and 2 does. To - * overcome this problem you can define FORCE_DSA_ALIGNMENT, which ensures - * that the DSA address is always xxxxxx00. If disconnection is not allowed, - * then the script only ever tries to add small (< 256) positive offsets to - * DSA, so lack of carry isn't a problem. FORCE_DSA_ALIGNMENT can, of course, - * be defined for all chip revisions at a small cost in memory usage. - */ - -#define FORCE_DSA_ALIGNMENT - -/* - * Selection timer does not always work on the 53c710, depending on the - * timing at the last disconnect, if this is a problem for you, try - * using validids as detailed below. - * - * Options for the NCR7xx driver - * - * noasync:0 - disables sync and asynchronous negotiation - * nosync:0 - disables synchronous negotiation (does async) - * nodisconnect:0 - disables disconnection - * validids:0x?? - Bitmask field that disallows certain ID's. - * - e.g. 0x03 allows ID 0,1 - * - 0x1F allows ID 0,1,2,3,4 - * opthi:n - replace top word of options with 'n' - * optlo:n - replace bottom word of options with 'n' - * - ALWAYS SPECIFY opthi THEN optlo <<<<<<<<<< - */ - -/* - * PERM_OPTIONS are driver options which will be enabled for all NCR boards - * in the system at driver initialization time. - * - * Don't THINK about touching these in PERM_OPTIONS : - * OPTION_MEMORY_MAPPED - * 680x0 doesn't have an IO map! - * - * OPTION_DEBUG_TEST1 - * Test 1 does bus mastering and interrupt tests, which will help weed - * out brain damaged main boards. - * - * Other PERM_OPTIONS settings are listed below. Note the actual options - * required are set in the relevant file (mvme16x.c, amiga7xx.c, etc): - * - * OPTION_NO_ASYNC - * Don't negotiate for asynchronous transfers on the first command - * when OPTION_ALWAYS_SYNCHRONOUS is set. Useful for dain bramaged - * devices which do something bad rather than sending a MESSAGE - * REJECT back to us like they should if they can't cope. - * - * OPTION_SYNCHRONOUS - * Enable support for synchronous transfers. Target negotiated - * synchronous transfers will be responded to. To initiate - * a synchronous transfer request, call - * - * request_synchronous (hostno, target) - * - * from within KGDB. - * - * OPTION_ALWAYS_SYNCHRONOUS - * Negotiate for synchronous transfers with every target after - * driver initialization or a SCSI bus reset. This is a bit dangerous, - * since there are some dain bramaged SCSI devices which will accept - * SDTR messages but keep talking asynchronously. - * - * OPTION_DISCONNECT - * Enable support for disconnect/reconnect. To change the - * default setting on a given host adapter, call - * - * request_disconnect (hostno, allow) - * - * where allow is non-zero to allow, 0 to disallow. - * - * If you really want to run 10MHz FAST SCSI-II transfers, you should - * know that the NCR driver currently ignores parity information. Most - * systems do 5MHz SCSI fine. I've seen a lot that have problems faster - * than 8MHz. To play it safe, we only request 5MHz transfers. - * - * If you'd rather get 10MHz transfers, edit sdtr_message and change - * the fourth byte from 50 to 25. - */ - -/* - * Sponsored by - * iX Multiuser Multitasking Magazine - * Hannover, Germany - * hm@ix.de - * - * Copyright 1993, 1994, 1995 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@PoohSticks.ORG - * +1 (303) 786-7975 - * - * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. - * - * For more information, please consult - * - * NCR53C810 - * SCSI I/O Processor - * Programmer's Guide - * - * NCR 53C810 - * PCI-SCSI I/O Processor - * Data Manual - * - * NCR 53C810/53C820 - * PCI-SCSI I/O Processor Design In Guide - * - * For literature on Symbios Logic Inc. formerly NCR, SCSI, - * and Communication products please call (800) 334-5454 or - * (719) 536-3300. - * - * PCI BIOS Specification Revision - * PCI Local Bus Specification - * PCI System Design Guide - * - * PCI Special Interest Group - * M/S HF3-15A - * 5200 N.E. Elam Young Parkway - * Hillsboro, Oregon 97124-6497 - * +1 (503) 696-2000 - * +1 (800) 433-5177 - */ - -/* - * Design issues : - * The cumulative latency needed to propagate a read/write request - * through the file system, buffer cache, driver stacks, SCSI host, and - * SCSI device is ultimately the limiting factor in throughput once we - * have a sufficiently fast host adapter. - * - * So, to maximize performance we want to keep the ratio of latency to data - * transfer time to a minimum by - * 1. Minimizing the total number of commands sent (typical command latency - * including drive and bus mastering host overhead is as high as 4.5ms) - * to transfer a given amount of data. - * - * This is accomplished by placing no arbitrary limit on the number - * of scatter/gather buffers supported, since we can transfer 1K - * per scatter/gather buffer without Eric's cluster patches, - * 4K with. - * - * 2. Minimizing the number of fatal interrupts serviced, since - * fatal interrupts halt the SCSI I/O processor. Basically, - * this means offloading the practical maximum amount of processing - * to the SCSI chip. - * - * On the NCR53c810/820/720, this is accomplished by using - * interrupt-on-the-fly signals when commands complete, - * and only handling fatal errors and SDTR / WDTR messages - * in the host code. - * - * On the NCR53c710, interrupts are generated as on the NCR53c8x0, - * only the lack of a interrupt-on-the-fly facility complicates - * things. Also, SCSI ID registers and commands are - * bit fielded rather than binary encoded. - * - * On the NCR53c700 and NCR53c700-66, operations that are done via - * indirect, table mode on the more advanced chips must be - * replaced by calls through a jump table which - * acts as a surrogate for the DSA. Unfortunately, this - * will mean that we must service an interrupt for each - * disconnect/reconnect. - * - * 3. Eliminating latency by pipelining operations at the different levels. - * - * This driver allows a configurable number of commands to be enqueued - * for each target/lun combination (experimentally, I have discovered - * that two seems to work best) and will ultimately allow for - * SCSI-II tagged queuing. - * - * - * Architecture : - * This driver is built around a Linux queue of commands waiting to - * be executed, and a shared Linux/NCR array of commands to start. Commands - * are transferred to the array by the run_process_issue_queue() function - * which is called whenever a command completes. - * - * As commands are completed, the interrupt routine is triggered, - * looks for commands in the linked list of completed commands with - * valid status, removes these commands from a list of running commands, - * calls the done routine, and flags their target/luns as not busy. - * - * Due to limitations in the intelligence of the NCR chips, certain - * concessions are made. In many cases, it is easier to dynamically - * generate/fix-up code rather than calculate on the NCR at run time. - * So, code is generated or fixed up for - * - * - Handling data transfers, using a variable number of MOVE instructions - * interspersed with CALL MSG_IN, WHEN MSGIN instructions. - * - * The DATAIN and DATAOUT routines are separate, so that an incorrect - * direction can be trapped, and space isn't wasted. - * - * It may turn out that we're better off using some sort - * of table indirect instruction in a loop with a variable - * sized table on the NCR53c710 and newer chips. - * - * - Checking for reselection (NCR53c710 and better) - * - * - Handling the details of SCSI context switches (NCR53c710 and better), - * such as reprogramming appropriate synchronous parameters, - * removing the dsa structure from the NCR's queue of outstanding - * commands, etc. - * - */ - -#include <linux/module.h> - - -#include <linux/types.h> -#include <asm/setup.h> -#include <asm/dma.h> -#include <asm/io.h> -#include <asm/system.h> -#include <linux/delay.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/time.h> -#include <linux/blkdev.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h> -#include <asm/pgtable.h> - -#ifdef CONFIG_AMIGA -#include <asm/amigahw.h> -#include <asm/amigaints.h> -#include <asm/irq.h> - -#define BIG_ENDIAN -#define NO_IO_SPACE -#endif - -#ifdef CONFIG_MVME16x -#include <asm/mvme16xhw.h> - -#define BIG_ENDIAN -#define NO_IO_SPACE -#define VALID_IDS -#endif - -#ifdef CONFIG_BVME6000 -#include <asm/bvme6000hw.h> - -#define BIG_ENDIAN -#define NO_IO_SPACE -#define VALID_IDS -#endif - -#include "scsi.h" -#include <scsi/scsi_dbg.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_transport_spi.h> -#include "53c7xx.h" -#include <linux/stat.h> -#include <linux/stddef.h> - -#ifdef NO_IO_SPACE -/* - * The following make the definitions in 53c7xx.h (write8, etc) smaller, - * we don't have separate i/o space anyway. - */ -#undef inb -#undef outb -#undef inw -#undef outw -#undef inl -#undef outl -#define inb(x) 1 -#define inw(x) 1 -#define inl(x) 1 -#define outb(x,y) 1 -#define outw(x,y) 1 -#define outl(x,y) 1 -#endif - -static int check_address (unsigned long addr, int size); -static void dump_events (struct Scsi_Host *host, int count); -static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, - int free, int issue); -static void hard_reset (struct Scsi_Host *host); -static void ncr_scsi_reset (struct Scsi_Host *host); -static void print_lots (struct Scsi_Host *host); -static void set_synchronous (struct Scsi_Host *host, int target, int sxfer, - int scntl3, int now_connected); -static int datapath_residual (struct Scsi_Host *host); -static const char * sbcl_to_phase (int sbcl); -static void print_progress (Scsi_Cmnd *cmd); -static void print_queues (struct Scsi_Host *host); -static void process_issue_queue (unsigned long flags); -static int shutdown (struct Scsi_Host *host); -static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result); -static int disable (struct Scsi_Host *host); -static int NCR53c7xx_run_tests (struct Scsi_Host *host); -static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id); -static void NCR53c7x0_intfly (struct Scsi_Host *host); -static int ncr_halt (struct Scsi_Host *host); -static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd - *cmd); -static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd); -static void print_dsa (struct Scsi_Host *host, u32 *dsa, - const char *prefix); -static int print_insn (struct Scsi_Host *host, const u32 *insn, - const char *prefix, int kernel); - -static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd); -static void NCR53c7x0_init_fixup (struct Scsi_Host *host); -static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct - NCR53c7x0_cmd *cmd); -static void NCR53c7x0_soft_reset (struct Scsi_Host *host); - -/* Size of event list (per host adapter) */ -static int track_events = 0; -static struct Scsi_Host *first_host = NULL; /* Head of list of NCR boards */ -static struct scsi_host_template *the_template = NULL; - -/* NCR53c710 script handling code */ - -#include "53c7xx_d.h" -#ifdef A_int_debug_sync -#define DEBUG_SYNC_INTR A_int_debug_sync -#endif -int NCR53c7xx_script_len = sizeof (SCRIPT); -int NCR53c7xx_dsa_len = A_dsa_end + Ent_dsa_zero - Ent_dsa_code_template; -#ifdef FORCE_DSA_ALIGNMENT -int CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff; -#endif - -static char *setup_strings[] = - {"","","","","","","",""}; - -#define MAX_SETUP_STRINGS ARRAY_SIZE(setup_strings) -#define SETUP_BUFFER_SIZE 200 -static char setup_buffer[SETUP_BUFFER_SIZE]; -static char setup_used[MAX_SETUP_STRINGS]; - -void ncr53c7xx_setup (char *str, int *ints) -{ - int i; - char *p1, *p2; - - p1 = setup_buffer; - *p1 = '\0'; - if (str) - strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer)); - setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0'; - p1 = setup_buffer; - i = 0; - while (*p1 && (i < MAX_SETUP_STRINGS)) { - p2 = strchr(p1, ','); - if (p2) { - *p2 = '\0'; - if (p1 != p2) - setup_strings[i] = p1; - p1 = p2 + 1; - i++; - } - else { - setup_strings[i] = p1; - break; - } - } - for (i=0; i<MAX_SETUP_STRINGS; i++) - setup_used[i] = 0; -} - - -/* check_setup_strings() returns index if key found, 0 if not - */ - -static int check_setup_strings(char *key, int *flags, int *val, char *buf) -{ -int x; -char *cp; - - for (x=0; x<MAX_SETUP_STRINGS; x++) { - if (setup_used[x]) - continue; - if (!strncmp(setup_strings[x], key, strlen(key))) - break; - if (!strncmp(setup_strings[x], "next", strlen("next"))) - return 0; - } - if (x == MAX_SETUP_STRINGS) - return 0; - setup_used[x] = 1; - cp = setup_strings[x] + strlen(key); - *val = -1; - if (*cp != ':') - return ++x; - cp++; - if ((*cp >= '0') && (*cp <= '9')) { - *val = simple_strtoul(cp,NULL,0); - } - return ++x; -} - - - -/* - * KNOWN BUGS : - * - There is some sort of conflict when the PPP driver is compiled with - * support for 16 channels? - * - * - On systems which predate the 1.3.x initialization order change, - * the NCR driver will cause Cannot get free page messages to appear. - * These are harmless, but I don't know of an easy way to avoid them. - * - * - With OPTION_DISCONNECT, on two systems under unknown circumstances, - * we get a PHASE MISMATCH with DSA set to zero (suggests that we - * are occurring somewhere in the reselection code) where - * DSP=some value DCMD|DBC=same value. - * - * Closer inspection suggests that we may be trying to execute - * some portion of the DSA? - * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) - * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) - * scsi0 : no current command : unexpected phase MSGIN. - * DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0 - * DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80 - * scsi0 : DSP-> - * 001c46cc : 0x001c46cc 0x00000000 - * 001c46d4 : 0x001c5ea0 0x000011f8 - * - * Changed the print code in the phase_mismatch handler so - * that we call print_lots to try to diagnose this. - * - */ - -/* - * Possible future direction of architecture for max performance : - * - * We're using a single start array for the NCR chip. This is - * sub-optimal, because we cannot add a command which would conflict with - * an executing command to this start queue, and therefore must insert the - * next command for a given I/T/L combination after the first has completed; - * incurring our interrupt latency between SCSI commands. - * - * To allow further pipelining of the NCR and host CPU operation, we want - * to set things up so that immediately on termination of a command destined - * for a given LUN, we get that LUN busy again. - * - * To do this, we need to add a 32 bit pointer to which is jumped to - * on completion of a command. If no new command is available, this - * would point to the usual DSA issue queue select routine. - * - * If one were, it would point to a per-NCR53c7x0_cmd select routine - * which starts execution immediately, inserting the command at the head - * of the start queue if the NCR chip is selected or reselected. - * - * We would change so that we keep a list of outstanding commands - * for each unit, rather than a single running_list. We'd insert - * a new command into the right running list; if the NCR didn't - * have something running for that yet, we'd put it in the - * start queue as well. Some magic needs to happen to handle the - * race condition between the first command terminating before the - * new one is written. - * - * Potential for profiling : - * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution. - */ - - -/* - * TODO : - * 1. To support WIDE transfers, not much needs to happen. We - * should do CHMOVE instructions instead of MOVEs when - * we have scatter/gather segments of uneven length. When - * we do this, we need to handle the case where we disconnect - * between segments. - * - * 2. Currently, when Icky things happen we do a FATAL(). Instead, - * we want to do an integrity check on the parts of the NCR hostdata - * structure which were initialized at boot time; FATAL() if that - * fails, and otherwise try to recover. Keep track of how many - * times this has happened within a single SCSI command; if it - * gets excessive, then FATAL(). - * - * 3. Parity checking is currently disabled, and a few things should - * happen here now that we support synchronous SCSI transfers : - * 1. On soft-reset, we shoould set the EPC (Enable Parity Checking) - * and AAP (Assert SATN/ on parity error) bits in SCNTL0. - * - * 2. We should enable the parity interrupt in the SIEN0 register. - * - * 3. intr_phase_mismatch() needs to believe that message out is - * always an "acceptable" phase to have a mismatch in. If - * the old phase was MSG_IN, we should send a MESSAGE PARITY - * error. If the old phase was something else, we should send - * a INITIATOR_DETECTED_ERROR message. Note that this could - * cause a RESTORE POINTERS message; so we should handle that - * correctly first. Instead, we should probably do an - * initiator_abort. - * - * 4. MPEE bit of CTEST4 should be set so we get interrupted if - * we detect an error. - * - * - * 5. The initial code has been tested on the NCR53c810. I don't - * have access to NCR53c700, 700-66 (Forex boards), NCR53c710 - * (NCR Pentium systems), NCR53c720, NCR53c820, or NCR53c825 boards to - * finish development on those platforms. - * - * NCR53c820/825/720 - need to add wide transfer support, including WDTR - * negotiation, programming of wide transfer capabilities - * on reselection and table indirect selection. - * - * NCR53c710 - need to add fatal interrupt or GEN code for - * command completion signaling. Need to modify all - * SDID, SCID, etc. registers, and table indirect select code - * since these use bit fielded (ie 1<<target) instead of - * binary encoded target ids. Need to accommodate - * different register mappings, probably scan through - * the SCRIPT code and change the non SFBR register operand - * of all MOVE instructions. - * - * It is rather worse than this actually, the 710 corrupts - * both TEMP and DSA when you do a MOVE MEMORY. This - * screws you up all over the place. MOVE MEMORY 4 with a - * destination of DSA seems to work OK, which helps some. - * Richard Hirst richard@sleepie.demon.co.uk - * - * NCR53c700/700-66 - need to add code to refix addresses on - * every nexus change, eliminate all table indirect code, - * very messy. - * - * 6. The NCR53c7x0 series is very popular on other platforms that - * could be running Linux - ie, some high performance AMIGA SCSI - * boards use it. - * - * So, I should include #ifdef'd code so that it is - * compatible with these systems. - * - * Specifically, the little Endian assumptions I made in my - * bit fields need to change, and if the NCR doesn't see memory - * the right way, we need to provide options to reverse words - * when the scripts are relocated. - * - * 7. Use vremap() to access memory mapped boards. - */ - -/* - * Allow for simultaneous existence of multiple SCSI scripts so we - * can have a single driver binary for all of the family. - * - * - one for NCR53c700 and NCR53c700-66 chips (not yet supported) - * - one for rest (only the NCR53c810, 815, 820, and 825 are currently - * supported) - * - * So that we only need two SCSI scripts, we need to modify things so - * that we fixup register accesses in READ/WRITE instructions, and - * we'll also have to accommodate the bit vs. binary encoding of IDs - * with the 7xx chips. - */ - -#define ROUNDUP(adr,type) \ - ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1))) - - -/* - * Function: issue_to_cmd - * - * Purpose: convert jump instruction in issue array to NCR53c7x0_cmd - * structure pointer. - * - * Inputs; issue - pointer to start of NOP or JUMP instruction - * in issue array. - * - * Returns: pointer to command on success; 0 if opcode is NOP. - */ - -static inline struct NCR53c7x0_cmd * -issue_to_cmd (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, - u32 *issue) -{ - return (issue[0] != hostdata->NOP_insn) ? - /* - * If the IF TRUE bit is set, it's a JUMP instruction. The - * operand is a bus pointer to the dsa_begin routine for this DSA. The - * dsa field of the NCR53c7x0_cmd structure starts with the - * DSA code template. By converting to a virtual address, - * subtracting the code template size, and offset of the - * dsa field, we end up with a pointer to the start of the - * structure (alternatively, we could use the - * dsa_cmnd field, an anachronism from when we weren't - * sure what the relationship between the NCR structures - * and host structures were going to be. - */ - (struct NCR53c7x0_cmd *) ((char *) bus_to_virt (issue[1]) - - (hostdata->E_dsa_code_begin - hostdata->E_dsa_code_template) - - offsetof(struct NCR53c7x0_cmd, dsa)) - /* If the IF TRUE bit is not set, it's a NOP */ - : NULL; -} - - -/* - * FIXME: we should junk these, in favor of synchronous_want and - * wide_want in the NCR53c7x0_hostdata structure. - */ - -/* Template for "preferred" synchronous transfer parameters. */ - -static const unsigned char sdtr_message[] = { -#ifdef CONFIG_SCSI_NCR53C7xx_FAST - EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 25 /* *4ns */, 8 /* off */ -#else - EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 50 /* *4ns */, 8 /* off */ -#endif -}; - -/* Template to request asynchronous transfers */ - -static const unsigned char async_message[] = { - EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */ -}; - -/* Template for "preferred" WIDE transfer parameters */ - -static const unsigned char wdtr_message[] = { - EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */ -}; - -#if 0 -/* - * Function : struct Scsi_Host *find_host (int host) - * - * Purpose : KGDB support function which translates a host number - * to a host structure. - * - * Inputs : host - number of SCSI host - * - * Returns : NULL on failure, pointer to host structure on success. - */ - -static struct Scsi_Host * -find_host (int host) { - struct Scsi_Host *h; - for (h = first_host; h && h->host_no != host; h = h->next); - if (!h) { - printk (KERN_ALERT "scsi%d not found\n", host); - return NULL; - } else if (h->hostt != the_template) { - printk (KERN_ALERT "scsi%d is not a NCR board\n", host); - return NULL; - } - return h; -} - -#if 0 -/* - * Function : request_synchronous (int host, int target) - * - * Purpose : KGDB interface which will allow us to negotiate for - * synchronous transfers. This ill be replaced with a more - * integrated function; perhaps a new entry in the scsi_host - * structure, accessible via an ioctl() or perhaps /proc/scsi. - * - * Inputs : host - number of SCSI host; target - number of target. - * - * Returns : 0 when negotiation has been setup for next SCSI command, - * -1 on failure. - */ - -static int -request_synchronous (int host, int target) { - struct Scsi_Host *h; - struct NCR53c7x0_hostdata *hostdata; - unsigned long flags; - if (target < 0) { - printk (KERN_ALERT "target %d is bogus\n", target); - return -1; - } - if (!(h = find_host (host))) - return -1; - else if (h->this_id == target) { - printk (KERN_ALERT "target %d is host ID\n", target); - return -1; - } - else if (target >= h->max_id) { - printk (KERN_ALERT "target %d exceeds maximum of %d\n", target, - h->max_id); - return -1; - } - hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0]; - - local_irq_save(flags); - if (hostdata->initiate_sdtr & (1 << target)) { - local_irq_restore(flags); - printk (KERN_ALERT "target %d already doing SDTR\n", target); - return -1; - } - hostdata->initiate_sdtr |= (1 << target); - local_irq_restore(flags); - return 0; -} -#endif - -/* - * Function : request_disconnect (int host, int on_or_off) - * - * Purpose : KGDB support function, tells us to allow or disallow - * disconnections. - * - * Inputs : host - number of SCSI host; on_or_off - non-zero to allow, - * zero to disallow. - * - * Returns : 0 on success, * -1 on failure. - */ - -static int -request_disconnect (int host, int on_or_off) { - struct Scsi_Host *h; - struct NCR53c7x0_hostdata *hostdata; - if (!(h = find_host (host))) - return -1; - hostdata = (struct NCR53c7x0_hostdata *) h->hostdata[0]; - if (on_or_off) - hostdata->options |= OPTION_DISCONNECT; - else - hostdata->options &= ~OPTION_DISCONNECT; - return 0; -} -#endif - -/* - * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host) - * - * Purpose : Initialize internal structures, as required on startup, or - * after a SCSI bus reset. - * - * Inputs : host - pointer to this host adapter's structure - */ - -static void -NCR53c7x0_driver_init (struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - int i, j; - u32 *ncrcurrent; - - for (i = 0; i < 16; ++i) { - hostdata->request_sense[i] = 0; - for (j = 0; j < 8; ++j) - hostdata->busy[i][j] = 0; - set_synchronous (host, i, /* sxfer */ 0, hostdata->saved_scntl3, 0); - } - hostdata->issue_queue = NULL; - hostdata->running_list = hostdata->finished_queue = - hostdata->ncrcurrent = NULL; - for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; - i < host->can_queue; ++i, ncrcurrent += 2) { - ncrcurrent[0] = hostdata->NOP_insn; - ncrcurrent[1] = 0xdeadbeef; - } - ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE; - ncrcurrent[1] = (u32) virt_to_bus (hostdata->script) + - hostdata->E_wait_reselect; - hostdata->reconnect_dsa_head = 0; - hostdata->addr_reconnect_dsa_head = (u32) - virt_to_bus((void *) &(hostdata->reconnect_dsa_head)); - hostdata->expecting_iid = 0; - hostdata->expecting_sto = 0; - if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS) - hostdata->initiate_sdtr = 0xffff; - else - hostdata->initiate_sdtr = 0; - hostdata->talked_to = 0; - hostdata->idle = 1; -} - -/* - * Function : static int clock_to_ccf_710 (int clock) - * - * Purpose : Return the clock conversion factor for a given SCSI clock. - * - * Inputs : clock - SCSI clock expressed in Hz. - * - * Returns : ccf on success, -1 on failure. - */ - -static int -clock_to_ccf_710 (int clock) { - if (clock <= 16666666) - return -1; - if (clock <= 25000000) - return 2; /* Divide by 1.0 */ - else if (clock <= 37500000) - return 1; /* Divide by 1.5 */ - else if (clock <= 50000000) - return 0; /* Divide by 2.0 */ - else if (clock <= 66000000) - return 3; /* Divide by 3.0 */ - else - return -1; -} - -/* - * Function : static int NCR53c7x0_init (struct Scsi_Host *host) - * - * Purpose : initialize the internal structures for a given SCSI host - * - * Inputs : host - pointer to this host adapter's structure - * - * Preconditions : when this function is called, the chip_type - * field of the hostdata structure MUST have been set. - * - * Returns : 0 on success, -1 on failure. - */ - -int -NCR53c7x0_init (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - int i, ccf; - unsigned char revision; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - /* - * There are some things which we need to know about in order to provide - * a semblance of support. Print 'em if they aren't what we expect, - * otherwise don't add to the noise. - * - * -1 means we don't know what to expect. - */ - int val, flags; - char buf[32]; - int expected_id = -1; - int expected_clock = -1; - int uninitialized = 0; -#ifdef NO_IO_SPACE - int expected_mapping = OPTION_MEMORY_MAPPED; -#else - int expected_mapping = OPTION_IO_MAPPED; -#endif - for (i=0;i<7;i++) - hostdata->valid_ids[i] = 1; /* Default all ID's to scan */ - - /* Parse commandline flags */ - if (check_setup_strings("noasync",&flags,&val,buf)) - { - hostdata->options |= OPTION_NO_ASYNC; - hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS); - } - - if (check_setup_strings("nosync",&flags,&val,buf)) - { - hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS); - } - - if (check_setup_strings("nodisconnect",&flags,&val,buf)) - hostdata->options &= ~OPTION_DISCONNECT; - - if (check_setup_strings("validids",&flags,&val,buf)) - { - for (i=0;i<7;i++) - hostdata->valid_ids[i] = val & (1<<i); - } - - if ((i = check_setup_strings("next",&flags,&val,buf))) - { - while (i) - setup_used[--i] = 1; - } - - if (check_setup_strings("opthi",&flags,&val,buf)) - hostdata->options = (long long)val << 32; - if (check_setup_strings("optlo",&flags,&val,buf)) - hostdata->options |= val; - - NCR53c7x0_local_setup(host); - switch (hostdata->chip) { - case 710: - case 770: - hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr; - hostdata->init_save_regs = NULL; - hostdata->dsa_fixup = NCR53c7xx_dsa_fixup; - hostdata->init_fixup = NCR53c7x0_init_fixup; - hostdata->soft_reset = NCR53c7x0_soft_reset; - hostdata->run_tests = NCR53c7xx_run_tests; - expected_clock = hostdata->scsi_clock; - expected_id = 7; - break; - default: - printk ("scsi%d : chip type of %d is not supported yet, detaching.\n", - host->host_no, hostdata->chip); - scsi_unregister (host); - return -1; - } - - /* Assign constants accessed by NCR */ - hostdata->NCR53c7xx_zero = 0; - hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT; - hostdata->NCR53c7xx_msg_abort = ABORT; - hostdata->NCR53c7xx_msg_nop = NOP; - hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24; - if (expected_mapping == -1 || - (hostdata->options & (OPTION_MEMORY_MAPPED)) != - (expected_mapping & OPTION_MEMORY_MAPPED)) - printk ("scsi%d : using %s mapped access\n", host->host_no, - (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" : - "io"); - - hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ? - DMODE_REG_00 : DMODE_REG_10; - hostdata->istat = ((hostdata->chip / 100) == 8) ? - ISTAT_REG_800 : ISTAT_REG_700; - -/* We have to assume that this may be the first access to the chip, so - * we must set EA in DCNTL. */ - - NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM); - - -/* Only the ISTAT register is readable when the NCR is running, so make - sure it's halted. */ - ncr_halt(host); - -/* - * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc, - * as does the 710 with one bit per SCSI ID. Conversely, the NCR - * uses a normal, 3 bit binary representation of these values. - * - * Get the rest of the NCR documentation, and FIND OUT where the change - * was. - */ - -#if 0 - /* May not be able to do this - chip my not have been set up yet */ - tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG); - for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id); -#else - host->this_id = 7; -#endif - -/* - * Note : we should never encounter a board setup for ID0. So, - * if we see ID0, assume that it was uninitialized and set it - * to the industry standard 7. - */ - if (!host->this_id) { - printk("scsi%d : initiator ID was %d, changing to 7\n", - host->host_no, host->this_id); - host->this_id = 7; - hostdata->this_id_mask = 1 << 7; - uninitialized = 1; - }; - - if (expected_id == -1 || host->this_id != expected_id) - printk("scsi%d : using initiator ID %d\n", host->host_no, - host->this_id); - - /* - * Save important registers to allow a soft reset. - */ - - /* - * CTEST7 controls cache snooping, burst mode, and support for - * external differential drivers. This isn't currently used - the - * default value may not be optimal anyway. - * Even worse, it may never have been set up since reset. - */ - hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE; - revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4; - switch (revision) { - case 1: revision = 0; break; - case 2: revision = 1; break; - case 4: revision = 2; break; - case 8: revision = 3; break; - default: revision = 255; break; - } - printk("scsi%d: Revision 0x%x\n",host->host_no,revision); - - if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS))) - { - printk ("scsi%d: Disabling sync working and disconnect/reselect\n", - host->host_no); - hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS); - } - - /* - * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor, - * on 800 series chips, it allows for a totem-pole IRQ driver. - * NOTE saved_dcntl currently overwritten in init function. - * The value read here may be garbage anyway, MVME16x board at least - * does not initialise chip if kernel arrived via tftp. - */ - - hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG); - - /* - * DMODE controls DMA burst length, and on 700 series chips, - * 286 mode and bus width - * NOTE: On MVME16x, chip may have been reset, so this could be a - * power-on/reset default value. - */ - hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode); - - /* - * Now that burst length and enabled/disabled status is known, - * clue the user in on it. - */ - - ccf = clock_to_ccf_710 (expected_clock); - - for (i = 0; i < 16; ++i) - hostdata->cmd_allocated[i] = 0; - - if (hostdata->init_save_regs) - hostdata->init_save_regs (host); - if (hostdata->init_fixup) - hostdata->init_fixup (host); - - if (!the_template) { - the_template = host->hostt; - first_host = host; - } - - /* - * Linux SCSI drivers have always been plagued with initialization - * problems - some didn't work with the BIOS disabled since they expected - * initialization from it, some didn't work when the networking code - * was enabled and registers got scrambled, etc. - * - * To avoid problems like this, in the future, we will do a soft - * reset on the SCSI chip, taking it back to a sane state. - */ - - hostdata->soft_reset (host); - -#if 1 - hostdata->debug_count_limit = -1; -#else - hostdata->debug_count_limit = 1; -#endif - hostdata->intrs = -1; - hostdata->resets = -1; - memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message, - sizeof (hostdata->synchronous_want)); - - NCR53c7x0_driver_init (host); - - if (request_irq(host->irq, NCR53c7x0_intr, IRQF_SHARED, "53c7xx", host)) - { - printk("scsi%d : IRQ%d not free, detaching\n", - host->host_no, host->irq); - goto err_unregister; - } - - if ((hostdata->run_tests && hostdata->run_tests(host) == -1) || - (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) { - /* XXX Should disable interrupts, etc. here */ - goto err_free_irq; - } else { - if (host->io_port) { - host->n_io_port = 128; - if (!request_region (host->io_port, host->n_io_port, "ncr53c7xx")) - goto err_free_irq; - } - } - - if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) { - printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no); - hard_reset (host); - } - return 0; - - err_free_irq: - free_irq(host->irq, NCR53c7x0_intr); - err_unregister: - scsi_unregister(host); - return -1; -} - -/* - * Function : int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip, - * unsigned long base, int io_port, int irq, int dma, long long options, - * int clock); - * - * Purpose : initializes a NCR53c7,8x0 based on base addresses, - * IRQ, and DMA channel. - * - * Inputs : tpnt - Template for this SCSI adapter, board - board level - * product, chip - 710 - * - * Returns : 0 on success, -1 on failure. - * - */ - -int -ncr53c7xx_init (struct scsi_host_template *tpnt, int board, int chip, - unsigned long base, int io_port, int irq, int dma, - long long options, int clock) -{ - struct Scsi_Host *instance; - struct NCR53c7x0_hostdata *hostdata; - char chip_str[80]; - int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0, - schedule_size = 0, ok = 0; - void *tmp; - unsigned long page; - - switch (chip) { - case 710: - case 770: - schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */; - script_len = NCR53c7xx_script_len; - dsa_len = NCR53c7xx_dsa_len; - options |= OPTION_INTFLY; - sprintf (chip_str, "NCR53c%d", chip); - break; - default: - printk("scsi-ncr53c7xx : unsupported SCSI chip %d\n", chip); - return -1; - } - - printk("scsi-ncr53c7xx : %s at memory 0x%lx, io 0x%x, irq %d", - chip_str, base, io_port, irq); - if (dma == DMA_NONE) - printk("\n"); - else - printk(", dma %d\n", dma); - - if (options & OPTION_DEBUG_PROBE_ONLY) { - printk ("scsi-ncr53c7xx : probe only enabled, aborting initialization\n"); - return -1; - } - - max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len + - /* Size of dynamic part of command structure : */ - 2 * /* Worst case : we don't know if we need DATA IN or DATA out */ - ( 2 * /* Current instructions per scatter/gather segment */ - tpnt->sg_tablesize + - 3 /* Current startup / termination required per phase */ - ) * - 8 /* Each instruction is eight bytes */; - - /* Allocate fixed part of hostdata, dynamic part to hold appropriate - SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure. - - We need a NCR53c7x0_cmd structure for scan_scsis() when we are - not loaded as a module, and when we're loaded as a module, we - can't use a non-dynamically allocated structure because modules - are vmalloc()'d, which can allow structures to cross page - boundaries and breaks our physical/virtual address assumptions - for DMA. - - So, we stick it past the end of our hostdata structure. - - ASSUMPTION : - Regardless of how many simultaneous SCSI commands we allow, - the probe code only executes a _single_ instruction at a time, - so we only need one here, and don't need to allocate NCR53c7x0_cmd - structures for each target until we are no longer in scan_scsis - and kmalloc() has become functional (memory_init() happens - after all device driver initialization). - */ - - size = sizeof(struct NCR53c7x0_hostdata) + script_len + - /* Note that alignment will be guaranteed, since we put the command - allocated at probe time after the fixed-up SCSI script, which - consists of 32 bit words, aligned on a 32 bit boundary. But - on a 64bit machine we need 8 byte alignment for hostdata->free, so - we add in another 4 bytes to take care of potential misalignment - */ - (sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size; - - page = __get_free_pages(GFP_ATOMIC,1); - if(page==0) - { - printk(KERN_ERR "53c7xx: out of memory.\n"); - return -ENOMEM; - } -#ifdef FORCE_DSA_ALIGNMENT - /* - * 53c710 rev.0 doesn't have an add-with-carry instruction. - * Ensure we allocate enough memory to force DSA alignment. - */ - size += 256; -#endif - /* Size should be < 8K, so we can fit it in two pages. */ - if (size > 8192) { - printk(KERN_ERR "53c7xx: hostdata > 8K\n"); - return -1; - } - - instance = scsi_register (tpnt, 4); - if (!instance) - { - free_page(page); - return -1; - } - instance->hostdata[0] = page; - memset((void *)instance->hostdata[0], 0, 8192); - cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192); - cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192); - kernel_set_cachemode((void *)instance->hostdata[0], 8192, IOMAP_NOCACHE_SER); - - /* FIXME : if we ever support an ISA NCR53c7xx based board, we - need to check if the chip is running in a 16 bit mode, and if so - unregister it if it is past the 16M (0x1000000) mark */ - - hostdata = (struct NCR53c7x0_hostdata *)instance->hostdata[0]; - hostdata->size = size; - hostdata->script_count = script_len / sizeof(u32); - hostdata->board = board; - hostdata->chip = chip; - - /* - * Being memory mapped is more desirable, since - * - * - Memory accesses may be faster. - * - * - The destination and source address spaces are the same for - * all instructions, meaning we don't have to twiddle dmode or - * any other registers. - * - * So, we try for memory mapped, and if we don't get it, - * we go for port mapped, and that failing we tell the user - * it can't work. - */ - - if (base) { - instance->base = base; - /* Check for forced I/O mapping */ - if (!(options & OPTION_IO_MAPPED)) { - options |= OPTION_MEMORY_MAPPED; - ok = 1; - } - } else { - options &= ~OPTION_MEMORY_MAPPED; - } - - if (io_port) { - instance->io_port = io_port; - options |= OPTION_IO_MAPPED; - ok = 1; - } else { - options &= ~OPTION_IO_MAPPED; - } - - if (!ok) { - printk ("scsi%d : not initializing, no I/O or memory mapping known \n", - instance->host_no); - scsi_unregister (instance); - return -1; - } - instance->irq = irq; - instance->dma_channel = dma; - - hostdata->options = options; - hostdata->dsa_len = dsa_len; - hostdata->max_cmd_size = max_cmd_size; - hostdata->num_cmds = 1; - hostdata->scsi_clock = clock; - /* Initialize single command */ - tmp = (hostdata->script + hostdata->script_count); -#ifdef FORCE_DSA_ALIGNMENT - { - void *t = ROUNDUP(tmp, void *); - if (((u32)t & 0xff) > CmdPageStart) - t = (void *)((u32)t + 255); - t = (void *)(((u32)t & ~0xff) + CmdPageStart); - hostdata->free = t; -#if 0 - printk ("scsi: Registered size increased by 256 to %d\n", size); - printk ("scsi: CmdPageStart = 0x%02x\n", CmdPageStart); - printk ("scsi: tmp = 0x%08x, hostdata->free set to 0x%08x\n", - (u32)tmp, (u32)t); -#endif - } -#else - hostdata->free = ROUNDUP(tmp, void *); -#endif - hostdata->free->real = tmp; - hostdata->free->size = max_cmd_size; - hostdata->free->free = NULL; - hostdata->free->next = NULL; - hostdata->extra_allocate = 0; - - /* Allocate command start code space */ - hostdata->schedule = (chip == 700 || chip == 70066) ? - NULL : (u32 *) ((char *)hostdata->free + max_cmd_size); - -/* - * For diagnostic purposes, we don't really care how fast things blaze. - * For profiling, we want to access the 800ns resolution system clock, - * using a 'C' call on the host processor. - * - * Therefore, there's no need for the NCR chip to directly manipulate - * this data, and we should put it wherever is most convenient for - * Linux. - */ - if (track_events) - hostdata->events = (struct NCR53c7x0_event *) (track_events ? - vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL); - else - hostdata->events = NULL; - - if (hostdata->events) { - memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) * - track_events); - hostdata->event_size = track_events; - hostdata->event_index = 0; - } else - hostdata->event_size = 0; - - return NCR53c7x0_init(instance); -} - - -/* - * Function : static void NCR53c7x0_init_fixup (struct Scsi_Host *host) - * - * Purpose : copy and fixup the SCSI SCRIPTS(tm) code for this device. - * - * Inputs : host - pointer to this host adapter's structure - * - */ - -static void -NCR53c7x0_init_fixup (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - unsigned char tmp; - int i, ncr_to_memory, memory_to_ncr; - u32 base; - NCR53c7x0_local_setup(host); - - - /* XXX - NOTE : this code MUST be made endian aware */ - /* Copy code into buffer that was allocated at detection time. */ - memcpy ((void *) hostdata->script, (void *) SCRIPT, - sizeof(SCRIPT)); - /* Fixup labels */ - for (i = 0; i < PATCHES; ++i) - hostdata->script[LABELPATCHES[i]] += - virt_to_bus(hostdata->script); - /* Fixup addresses of constants that used to be EXTERNAL */ - - patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_abort, - virt_to_bus(&(hostdata->NCR53c7xx_msg_abort))); - patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_reject, - virt_to_bus(&(hostdata->NCR53c7xx_msg_reject))); - patch_abs_32 (hostdata->script, 0, NCR53c7xx_zero, - virt_to_bus(&(hostdata->NCR53c7xx_zero))); - patch_abs_32 (hostdata->script, 0, NCR53c7xx_sink, - virt_to_bus(&(hostdata->NCR53c7xx_sink))); - patch_abs_32 (hostdata->script, 0, NOP_insn, - virt_to_bus(&(hostdata->NOP_insn))); - patch_abs_32 (hostdata->script, 0, schedule, - virt_to_bus((void *) hostdata->schedule)); - - /* Fixup references to external variables: */ - for (i = 0; i < EXTERNAL_PATCHES_LEN; ++i) - hostdata->script[EXTERNAL_PATCHES[i].offset] += - virt_to_bus(EXTERNAL_PATCHES[i].address); - - /* - * Fixup absolutes set at boot-time. - * - * All non-code absolute variables suffixed with "dsa_" and "int_" - * are constants, and need no fixup provided the assembler has done - * it for us (I don't know what the "real" NCR assembler does in - * this case, my assembler does the right magic). - */ - - patch_abs_rwri_data (hostdata->script, 0, dsa_save_data_pointer, - Ent_dsa_code_save_data_pointer - Ent_dsa_zero); - patch_abs_rwri_data (hostdata->script, 0, dsa_restore_pointers, - Ent_dsa_code_restore_pointers - Ent_dsa_zero); - patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, - Ent_dsa_code_check_reselect - Ent_dsa_zero); - - /* - * Just for the hell of it, preserve the settings of - * Burst Length and Enable Read Line bits from the DMODE - * register. Make sure SCRIPTS start automagically. - */ - -#if defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) - /* We know better what we want than 16xBug does! */ - tmp = DMODE_10_BL_8 | DMODE_10_FC2; -#else - tmp = NCR53c7x0_read8(DMODE_REG_10); - tmp &= (DMODE_BL_MASK | DMODE_10_FC2 | DMODE_10_FC1 | DMODE_710_PD | - DMODE_710_UO); -#endif - - if (!(hostdata->options & OPTION_MEMORY_MAPPED)) { - base = (u32) host->io_port; - memory_to_ncr = tmp|DMODE_800_DIOM; - ncr_to_memory = tmp|DMODE_800_SIOM; - } else { - base = virt_to_bus((void *)host->base); - memory_to_ncr = ncr_to_memory = tmp; - } - - /* SCRATCHB_REG_10 == SCRATCHA_REG_800, as it happens */ - patch_abs_32 (hostdata->script, 0, addr_scratch, base + SCRATCHA_REG_800); - patch_abs_32 (hostdata->script, 0, addr_temp, base + TEMP_REG); - patch_abs_32 (hostdata->script, 0, addr_dsa, base + DSA_REG); - - /* - * I needed some variables in the script to be accessible to - * both the NCR chip and the host processor. For these variables, - * I made the arbitrary decision to store them directly in the - * hostdata structure rather than in the RELATIVE area of the - * SCRIPTS. - */ - - - patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp); - patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr); - patch_abs_rwri_data (hostdata->script, 0, dmode_ncr_to_memory, ncr_to_memory); - - patch_abs_32 (hostdata->script, 0, msg_buf, - virt_to_bus((void *)&(hostdata->msg_buf))); - patch_abs_32 (hostdata->script, 0, reconnect_dsa_head, - virt_to_bus((void *)&(hostdata->reconnect_dsa_head))); - patch_abs_32 (hostdata->script, 0, addr_reconnect_dsa_head, - virt_to_bus((void *)&(hostdata->addr_reconnect_dsa_head))); - patch_abs_32 (hostdata->script, 0, reselected_identify, - virt_to_bus((void *)&(hostdata->reselected_identify))); -/* reselected_tag is currently unused */ -#if 0 - patch_abs_32 (hostdata->script, 0, reselected_tag, - virt_to_bus((void *)&(hostdata->reselected_tag))); -#endif - - patch_abs_32 (hostdata->script, 0, test_dest, - virt_to_bus((void*)&hostdata->test_dest)); - patch_abs_32 (hostdata->script, 0, test_src, - virt_to_bus(&hostdata->test_source)); - patch_abs_32 (hostdata->script, 0, saved_dsa, - virt_to_bus((void *)&hostdata->saved2_dsa)); - patch_abs_32 (hostdata->script, 0, emulfly, - virt_to_bus((void *)&hostdata->emulated_intfly)); - - patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, - (unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero)); - -/* These are for event logging; the ncr_event enum contains the - actual interrupt numbers. */ -#ifdef A_int_EVENT_SELECT - patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT, (u32) EVENT_SELECT); -#endif -#ifdef A_int_EVENT_DISCONNECT - patch_abs_32 (hostdata->script, 0, int_EVENT_DISCONNECT, (u32) EVENT_DISCONNECT); -#endif -#ifdef A_int_EVENT_RESELECT - patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT, (u32) EVENT_RESELECT); -#endif -#ifdef A_int_EVENT_COMPLETE - patch_abs_32 (hostdata->script, 0, int_EVENT_COMPLETE, (u32) EVENT_COMPLETE); -#endif -#ifdef A_int_EVENT_IDLE - patch_abs_32 (hostdata->script, 0, int_EVENT_IDLE, (u32) EVENT_IDLE); -#endif -#ifdef A_int_EVENT_SELECT_FAILED - patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT_FAILED, - (u32) EVENT_SELECT_FAILED); -#endif -#ifdef A_int_EVENT_BEFORE_SELECT - patch_abs_32 (hostdata->script, 0, int_EVENT_BEFORE_SELECT, - (u32) EVENT_BEFORE_SELECT); -#endif -#ifdef A_int_EVENT_RESELECT_FAILED - patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT_FAILED, - (u32) EVENT_RESELECT_FAILED); -#endif - - /* - * Make sure the NCR and Linux code agree on the location of - * certain fields. - */ - - hostdata->E_accept_message = Ent_accept_message; - hostdata->E_command_complete = Ent_command_complete; - hostdata->E_cmdout_cmdout = Ent_cmdout_cmdout; - hostdata->E_data_transfer = Ent_data_transfer; - hostdata->E_debug_break = Ent_debug_break; - hostdata->E_dsa_code_template = Ent_dsa_code_template; - hostdata->E_dsa_code_template_end = Ent_dsa_code_template_end; - hostdata->E_end_data_transfer = Ent_end_data_transfer; - hostdata->E_initiator_abort = Ent_initiator_abort; - hostdata->E_msg_in = Ent_msg_in; - hostdata->E_other_transfer = Ent_other_transfer; - hostdata->E_other_in = Ent_other_in; - hostdata->E_other_out = Ent_other_out; - hostdata->E_reject_message = Ent_reject_message; - hostdata->E_respond_message = Ent_respond_message; - hostdata->E_select = Ent_select; - hostdata->E_select_msgout = Ent_select_msgout; - hostdata->E_target_abort = Ent_target_abort; -#ifdef Ent_test_0 - hostdata->E_test_0 = Ent_test_0; -#endif - hostdata->E_test_1 = Ent_test_1; - hostdata->E_test_2 = Ent_test_2; -#ifdef Ent_test_3 - hostdata->E_test_3 = Ent_test_3; -#endif - hostdata->E_wait_reselect = Ent_wait_reselect; - hostdata->E_dsa_code_begin = Ent_dsa_code_begin; - - hostdata->dsa_cmdout = A_dsa_cmdout; - hostdata->dsa_cmnd = A_dsa_cmnd; - hostdata->dsa_datain = A_dsa_datain; - hostdata->dsa_dataout = A_dsa_dataout; - hostdata->dsa_end = A_dsa_end; - hostdata->dsa_msgin = A_dsa_msgin; - hostdata->dsa_msgout = A_dsa_msgout; - hostdata->dsa_msgout_other = A_dsa_msgout_other; - hostdata->dsa_next = A_dsa_next; - hostdata->dsa_select = A_dsa_select; - hostdata->dsa_start = Ent_dsa_code_template - Ent_dsa_zero; - hostdata->dsa_status = A_dsa_status; - hostdata->dsa_jump_dest = Ent_dsa_code_fix_jump - Ent_dsa_zero + - 8 /* destination operand */; - - /* sanity check */ - if (A_dsa_fields_start != Ent_dsa_code_template_end - - Ent_dsa_zero) - printk("scsi%d : NCR dsa_fields start is %d not %d\n", - host->host_no, A_dsa_fields_start, Ent_dsa_code_template_end - - Ent_dsa_zero); - - printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no, - virt_to_bus(hostdata->script), hostdata->script); -} - -/* - * Function : static int NCR53c7xx_run_tests (struct Scsi_Host *host) - * - * Purpose : run various verification tests on the NCR chip, - * including interrupt generation, and proper bus mastering - * operation. - * - * Inputs : host - a properly initialized Scsi_Host structure - * - * Preconditions : the NCR chip must be in a halted state. - * - * Returns : 0 if all tests were successful, -1 on error. - * - */ - -static int -NCR53c7xx_run_tests (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - unsigned long timeout; - u32 start; - int failed, i; - unsigned long flags; - NCR53c7x0_local_setup(host); - - /* The NCR chip _must_ be idle to run the test scripts */ - - local_irq_save(flags); - if (!hostdata->idle) { - printk ("scsi%d : chip not idle, aborting tests\n", host->host_no); - local_irq_restore(flags); - return -1; - } - - /* - * Check for functional interrupts, this could work as an - * autoprobe routine. - */ - - if ((hostdata->options & OPTION_DEBUG_TEST1) && - hostdata->state != STATE_DISABLED) { - hostdata->idle = 0; - hostdata->test_running = 1; - hostdata->test_completed = -1; - hostdata->test_dest = 0; - hostdata->test_source = 0xdeadbeef; - start = virt_to_bus (hostdata->script) + hostdata->E_test_1; - hostdata->state = STATE_RUNNING; - printk ("scsi%d : test 1", host->host_no); - NCR53c7x0_write32 (DSP_REG, start); - if (hostdata->options & OPTION_DEBUG_TRACE) - NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM | - DCNTL_STD); - printk (" started\n"); - local_irq_restore(flags); - - /* - * This is currently a .5 second timeout, since (in theory) no slow - * board will take that long. In practice, we've seen one - * pentium which occassionally fails with this, but works with - * 10 times as much? - */ - - timeout = jiffies + 5 * HZ / 10; - while ((hostdata->test_completed == -1) && time_before(jiffies, timeout)) - barrier(); - - failed = 1; - if (hostdata->test_completed == -1) - printk ("scsi%d : driver test 1 timed out%s\n",host->host_no , - (hostdata->test_dest == 0xdeadbeef) ? - " due to lost interrupt.\n" - " Please verify that the correct IRQ is being used for your board,\n" - : ""); - else if (hostdata->test_completed != 1) - printk ("scsi%d : test 1 bad interrupt value (%d)\n", - host->host_no, hostdata->test_completed); - else - failed = (hostdata->test_dest != 0xdeadbeef); - - if (hostdata->test_dest != 0xdeadbeef) { - printk ("scsi%d : driver test 1 read 0x%x instead of 0xdeadbeef indicating a\n" - " probable cache invalidation problem. Please configure caching\n" - " as write-through or disabled\n", - host->host_no, hostdata->test_dest); - } - - if (failed) { - printk ("scsi%d : DSP = 0x%p (script at 0x%p, start at 0x%x)\n", - host->host_no, bus_to_virt(NCR53c7x0_read32(DSP_REG)), - hostdata->script, start); - printk ("scsi%d : DSPS = 0x%x\n", host->host_no, - NCR53c7x0_read32(DSPS_REG)); - local_irq_restore(flags); - return -1; - } - hostdata->test_running = 0; - } - - if ((hostdata->options & OPTION_DEBUG_TEST2) && - hostdata->state != STATE_DISABLED) { - u32 dsa[48]; - unsigned char identify = IDENTIFY(0, 0); - unsigned char cmd[6]; - unsigned char data[36]; - unsigned char status = 0xff; - unsigned char msg = 0xff; - - cmd[0] = INQUIRY; - cmd[1] = cmd[2] = cmd[3] = cmd[5] = 0; - cmd[4] = sizeof(data); - - dsa[2] = 1; - dsa[3] = virt_to_bus(&identify); - dsa[4] = 6; - dsa[5] = virt_to_bus(&cmd); - dsa[6] = sizeof(data); - dsa[7] = virt_to_bus(&data); - dsa[8] = 1; - dsa[9] = virt_to_bus(&status); - dsa[10] = 1; - dsa[11] = virt_to_bus(&msg); - - for (i = 0; i < 6; ++i) { -#ifdef VALID_IDS - if (!hostdata->valid_ids[i]) - continue; -#endif - local_irq_disable(); - if (!hostdata->idle) { - printk ("scsi%d : chip not idle, aborting tests\n", host->host_no); - local_irq_restore(flags); - return -1; - } - - /* 710: bit mapped scsi ID, async */ - dsa[0] = (1 << i) << 16; - hostdata->idle = 0; - hostdata->test_running = 2; - hostdata->test_completed = -1; - start = virt_to_bus(hostdata->script) + hostdata->E_test_2; - hostdata->state = STATE_RUNNING; - NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa)); - NCR53c7x0_write32 (DSP_REG, start); - if (hostdata->options & OPTION_DEBUG_TRACE) - NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | - DCNTL_SSM | DCNTL_STD); - local_irq_restore(flags); - - timeout = jiffies + 5 * HZ; /* arbitrary */ - while ((hostdata->test_completed == -1) && time_before(jiffies, timeout)) - barrier(); - - NCR53c7x0_write32 (DSA_REG, 0); - - if (hostdata->test_completed == 2) { - data[35] = 0; - printk ("scsi%d : test 2 INQUIRY to target %d, lun 0 : %s\n", - host->host_no, i, data + 8); - printk ("scsi%d : status ", host->host_no); - scsi_print_status (status); - printk ("\nscsi%d : message ", host->host_no); - spi_print_msg(&msg); - printk ("\n"); - } else if (hostdata->test_completed == 3) { - printk("scsi%d : test 2 no connection with target %d\n", - host->host_no, i); - if (!hostdata->idle) { - printk("scsi%d : not idle\n", host->host_no); - local_irq_restore(flags); - return -1; - } - } else if (hostdata->test_completed == -1) { - printk ("scsi%d : test 2 timed out\n", host->host_no); - local_irq_restore(flags); - return -1; - } - hostdata->test_running = 0; - } - } - - local_irq_restore(flags); - return 0; -} - -/* - * Function : static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) - * - * Purpose : copy the NCR53c8xx dsa structure into cmd's dsa buffer, - * performing all necessary relocation. - * - * Inputs : cmd, a NCR53c7x0_cmd structure with a dsa area large - * enough to hold the NCR53c8xx dsa. - */ - -static void -NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) { - Scsi_Cmnd *c = cmd->cmd; - struct Scsi_Host *host = c->device->host; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - int i; - - memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4), - hostdata->E_dsa_code_template_end - hostdata->E_dsa_code_template); - - /* - * Note : within the NCR 'C' code, dsa points to the _start_ - * of the DSA structure, and _not_ the offset of dsa_zero within - * that structure used to facilitate shorter signed offsets - * for the 8 bit ALU. - * - * The implications of this are that - * - * - 32 bit A_dsa_* absolute values require an additional - * dsa_zero added to their value to be correct, since they are - * relative to dsa_zero which is in essentially a separate - * space from the code symbols. - * - * - All other symbols require no special treatment. - */ - - patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_lun, c->device->lun); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr)); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero - - Ent_dsa_code_template + A_dsa_next); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->device->id].script)); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->device->id].sscf_710)); - patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_target, 1 << c->device->id); - /* XXX - new pointer stuff */ - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer)); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_saved_residual, virt_to_bus(&cmd->saved_residual)); - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_residual, virt_to_bus(&cmd->residual)); - - /* XXX - new start stuff */ - - patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr)); -} - -/* - * Function : run_process_issue_queue (void) - * - * Purpose : insure that the coroutine is running and will process our - * request. process_issue_queue_running is checked/set here (in an - * inline function) rather than in process_issue_queue itself to reduce - * the chances of stack overflow. - * - */ - -static volatile int process_issue_queue_running = 0; - -static __inline__ void -run_process_issue_queue(void) { - unsigned long flags; - local_irq_save(flags); - if (!process_issue_queue_running) { - process_issue_queue_running = 1; - process_issue_queue(flags); - /* - * process_issue_queue_running is cleared in process_issue_queue - * once it can't do more work, and process_issue_queue exits with - * interrupts disabled. - */ - } - local_irq_restore(flags); -} - -/* - * Function : static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int - * result) - * - * Purpose : mark SCSI command as finished, OR'ing the host portion - * of the result word into the result field of the corresponding - * Scsi_Cmnd structure, and removing it from the internal queues. - * - * Inputs : cmd - command, result - entire result field - * - * Preconditions : the NCR chip should be in a halted state when - * abnormal_finished is run, since it modifies structures which - * the NCR expects to have exclusive access to. - */ - -static void -abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) { - Scsi_Cmnd *c = cmd->cmd; - struct Scsi_Host *host = c->device->host; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - unsigned long flags; - int left, found; - volatile struct NCR53c7x0_cmd * linux_search; - volatile struct NCR53c7x0_cmd * volatile *linux_prev; - volatile u32 *ncr_prev, *ncrcurrent, ncr_search; - -#if 0 - printk ("scsi%d: abnormal finished\n", host->host_no); -#endif - - local_irq_save(flags); - found = 0; - /* - * Traverse the NCR issue array until we find a match or run out - * of instructions. Instructions in the NCR issue array are - * either JUMP or NOP instructions, which are 2 words in length. - */ - - - for (found = 0, left = host->can_queue, ncrcurrent = hostdata->schedule; - left > 0; --left, ncrcurrent += 2) - { - if (issue_to_cmd (host, hostdata, (u32 *) ncrcurrent) == cmd) - { - ncrcurrent[0] = hostdata->NOP_insn; - ncrcurrent[1] = 0xdeadbeef; - ++found; - break; - } - } - - /* - * Traverse the NCR reconnect list of DSA structures until we find - * a pointer to this dsa or have found too many command structures. - * We let prev point at the next field of the previous element or - * head of the list, so we don't do anything different for removing - * the head element. - */ - - for (left = host->can_queue, - ncr_search = hostdata->reconnect_dsa_head, - ncr_prev = &hostdata->reconnect_dsa_head; - left >= 0 && ncr_search && - ((char*)bus_to_virt(ncr_search) + hostdata->dsa_start) - != (char *) cmd->dsa; - ncr_prev = (u32*) ((char*)bus_to_virt(ncr_search) + - hostdata->dsa_next), ncr_search = *ncr_prev, --left); - - if (left < 0) - printk("scsi%d: loop detected in ncr reconncect list\n", - host->host_no); - else if (ncr_search) { - if (found) - printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n", - host->host_no, c->pid); - else { - volatile u32 * next = (u32 *) - ((char *)bus_to_virt(ncr_search) + hostdata->dsa_next); - *ncr_prev = *next; -/* If we're at the tail end of the issue queue, update that pointer too. */ - found = 1; - } - } - - /* - * Traverse the host running list until we find this command or discover - * we have too many elements, pointing linux_prev at the next field of the - * linux_previous element or head of the list, search at this element. - */ - - for (left = host->can_queue, linux_search = hostdata->running_list, - linux_prev = &hostdata->running_list; - left >= 0 && linux_search && linux_search != cmd; - linux_prev = &(linux_search->next), - linux_search = linux_search->next, --left); - - if (left < 0) - printk ("scsi%d: loop detected in host running list for scsi pid %ld\n", - host->host_no, c->pid); - else if (linux_search) { - *linux_prev = linux_search->next; - --hostdata->busy[c->device->id][c->device->lun]; - } - - /* Return the NCR command structure to the free list */ - cmd->next = hostdata->free; - hostdata->free = cmd; - c->host_scribble = NULL; - - /* And return */ - c->result = result; - c->scsi_done(c); - - local_irq_restore(flags); - run_process_issue_queue(); -} - -/* - * Function : static void intr_break (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : Handler for breakpoint interrupts from a SCSI script - * - * Inputs : host - pointer to this host adapter's structure, - * cmd - pointer to the command (if any) dsa was pointing - * to. - * - */ - -static void -intr_break (struct Scsi_Host *host, struct - NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_break *bp; -#if 0 - Scsi_Cmnd *c = cmd ? cmd->cmd : NULL; -#endif - u32 *dsp; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - unsigned long flags; - NCR53c7x0_local_setup(host); - - /* - * Find the break point corresponding to this address, and - * dump the appropriate debugging information to standard - * output. - */ - local_irq_save(flags); - dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG)); - for (bp = hostdata->breakpoints; bp && bp->address != dsp; - bp = bp->next); - if (!bp) - panic("scsi%d : break point interrupt from %p with no breakpoint!", - host->host_no, dsp); - - /* - * Configure the NCR chip for manual start mode, so that we can - * point the DSP register at the instruction that follows the - * INT int_debug_break instruction. - */ - - NCR53c7x0_write8 (hostdata->dmode, - NCR53c7x0_read8(hostdata->dmode)|DMODE_MAN); - - /* - * And update the DSP register, using the size of the old - * instruction in bytes. - */ - - local_irq_restore(flags); -} -/* - * Function : static void print_synchronous (const char *prefix, - * const unsigned char *msg) - * - * Purpose : print a pretty, user and machine parsable representation - * of a SDTR message, including the "real" parameters, data - * clock so we can tell transfer rate at a glance. - * - * Inputs ; prefix - text to prepend, msg - SDTR message (5 bytes) - */ - -static void -print_synchronous (const char *prefix, const unsigned char *msg) { - if (msg[4]) { - int Hz = 1000000000 / (msg[3] * 4); - int integer = Hz / 1000000; - int fraction = (Hz - (integer * 1000000)) / 10000; - printk ("%speriod %dns offset %d %d.%02dMHz %s SCSI%s\n", - prefix, (int) msg[3] * 4, (int) msg[4], integer, fraction, - (((msg[3] * 4) < 200) ? "FAST" : "synchronous"), - (((msg[3] * 4) < 200) ? "-II" : "")); - } else - printk ("%sasynchronous SCSI\n", prefix); -} - -/* - * Function : static void set_synchronous (struct Scsi_Host *host, - * int target, int sxfer, int scntl3, int now_connected) - * - * Purpose : reprogram transfers between the selected SCSI initiator and - * target with the given register values; in the indirect - * select operand, reselection script, and chip registers. - * - * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id, - * sxfer and scntl3 - NCR registers. now_connected - if non-zero, - * we should reprogram the registers now too. - * - * NOTE: For 53c710, scntl3 is actually used for SCF bits from - * SBCL, as we don't have a SCNTL3. - */ - -static void -set_synchronous (struct Scsi_Host *host, int target, int sxfer, int scntl3, - int now_connected) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - u32 *script; - NCR53c7x0_local_setup(host); - - /* These are eight bit registers */ - sxfer &= 0xff; - scntl3 &= 0xff; - - hostdata->sync[target].sxfer_sanity = sxfer; - hostdata->sync[target].scntl3_sanity = scntl3; - -/* - * HARD CODED : synchronous script is EIGHT words long. This - * must agree with 53c7.8xx.h - */ - - if ((hostdata->chip != 700) && (hostdata->chip != 70066)) { - hostdata->sync[target].select_indirect = (1 << target) << 16 | - (sxfer << 8); - hostdata->sync[target].sscf_710 = scntl3; - - script = (u32 *) hostdata->sync[target].script; - - /* XXX - add NCR53c7x0 code to reprogram SCF bits if we want to */ - script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY | - DCMD_RWRI_OP_MOVE) << 24) | - (SBCL_REG << 16) | (scntl3 << 8); - script[1] = 0; - script += 2; - - script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY | - DCMD_RWRI_OP_MOVE) << 24) | - (SXFER_REG << 16) | (sxfer << 8); - script[1] = 0; - script += 2; - -#ifdef DEBUG_SYNC_INTR - if (hostdata->options & OPTION_DEBUG_DISCONNECT) { - script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_INT) << 24) | DBC_TCI_TRUE; - script[1] = DEBUG_SYNC_INTR; - script += 2; - } -#endif - - script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_RETURN) << 24) | DBC_TCI_TRUE; - script[1] = 0; - script += 2; - } - - if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) - printk ("scsi%d : target %d sync parameters are sxfer=0x%x, scntl3=0x%x\n", - host->host_no, target, sxfer, scntl3); - - if (now_connected) { - NCR53c7x0_write8(SBCL_REG, scntl3); - NCR53c7x0_write8(SXFER_REG, sxfer); - } -} - - -/* - * Function : static int asynchronous (struct Scsi_Host *host, int target) - * - * Purpose : reprogram between the selected SCSI Host adapter and target - * (assumed to be currently connected) for asynchronous transfers. - * - * Inputs : host - SCSI host structure, target - numeric target ID. - * - * Preconditions : the NCR chip should be in one of the halted states - */ - -static void -asynchronous (struct Scsi_Host *host, int target) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - NCR53c7x0_local_setup(host); - set_synchronous (host, target, /* no offset */ 0, hostdata->saved_scntl3, - 1); - printk ("scsi%d : setting target %d to asynchronous SCSI\n", - host->host_no, target); -} - -/* - * XXX - do we want to go out of our way (ie, add extra code to selection - * in the NCR53c710/NCR53c720 script) to reprogram the synchronous - * conversion bits, or can we be content in just setting the - * sxfer bits? I chose to do so [richard@sleepie.demon.co.uk] - */ - -/* Table for NCR53c8xx synchronous values */ - -/* This table is also correct for 710, allowing that scf=4 is equivalent - * of SSCF=0 (ie use DCNTL, divide by 3) for a 50.01-66.00MHz clock. - * For any other clock values, we cannot use entries with SCF values of - * 4. I guess that for a 66MHz clock, the slowest it will set is 2MHz, - * and for a 50MHz clock, the slowest will be 2.27Mhz. Should check - * that a device doesn't try and negotiate sync below these limits! - */ - -static const struct { - int div; /* Total clock divisor * 10 */ - unsigned char scf; /* */ - unsigned char tp; /* 4 + tp = xferp divisor */ -} syncs[] = { -/* div scf tp div scf tp div scf tp */ - { 40, 1, 0}, { 50, 1, 1}, { 60, 1, 2}, - { 70, 1, 3}, { 75, 2, 1}, { 80, 1, 4}, - { 90, 1, 5}, { 100, 1, 6}, { 105, 2, 3}, - { 110, 1, 7}, { 120, 2, 4}, { 135, 2, 5}, - { 140, 3, 3}, { 150, 2, 6}, { 160, 3, 4}, - { 165, 2, 7}, { 180, 3, 5}, { 200, 3, 6}, - { 210, 4, 3}, { 220, 3, 7}, { 240, 4, 4}, - { 270, 4, 5}, { 300, 4, 6}, { 330, 4, 7} -}; - -/* - * Function : static void synchronous (struct Scsi_Host *host, int target, - * char *msg) - * - * Purpose : reprogram transfers between the selected SCSI initiator and - * target for synchronous SCSI transfers such that the synchronous - * offset is less than that requested and period at least as long - * as that requested. Also modify *msg such that it contains - * an appropriate response. - * - * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id, - * msg - synchronous transfer request. - */ - - -static void -synchronous (struct Scsi_Host *host, int target, char *msg) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - int desire, divisor, i, limit; - unsigned char scntl3, sxfer; -/* The diagnostic message fits on one line, even with max. width integers */ - char buf[80]; - -/* Desired transfer clock in Hz */ - desire = 1000000000L / (msg[3] * 4); -/* Scale the available SCSI clock by 10 so we get tenths */ - divisor = (hostdata->scsi_clock * 10) / desire; - -/* NCR chips can handle at most an offset of 8 */ - if (msg[4] > 8) - msg[4] = 8; - - if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : optimal synchronous divisor of %d.%01d\n", - host->host_no, divisor / 10, divisor % 10); - - limit = ARRAY_SIZE(syncs) - 1; - for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i); - - if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : selected synchronous divisor of %d.%01d\n", - host->host_no, syncs[i].div / 10, syncs[i].div % 10); - - msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4); - - if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : selected synchronous period of %dns\n", host->host_no, - msg[3] * 4); - - scntl3 = syncs[i].scf; - sxfer = (msg[4] << SXFER_MO_SHIFT) | (syncs[i].tp << 4); - if (hostdata->options & OPTION_DEBUG_SDTR) - printk ("scsi%d : sxfer=0x%x scntl3=0x%x\n", - host->host_no, (int) sxfer, (int) scntl3); - set_synchronous (host, target, sxfer, scntl3, 1); - sprintf (buf, "scsi%d : setting target %d to ", host->host_no, target); - print_synchronous (buf, msg); -} - -/* - * Function : static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : Handler for INT generated instructions for the - * NCR53c810/820 SCSI SCRIPT - * - * Inputs : host - pointer to this host adapter's structure, - * cmd - pointer to the command (if any) dsa was pointing - * to. - * - */ - -static int -NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct - NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - int print; - Scsi_Cmnd *c = cmd ? cmd->cmd : NULL; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - u32 dsps,*dsp; /* Argument of the INT instruction */ - - NCR53c7x0_local_setup(host); - dsps = NCR53c7x0_read32(DSPS_REG); - dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG)); - - /* RGH 150597: Frig. Commands which fail with Check Condition are - * Flagged as successful - hack dsps to indicate check condition */ -#if 0 - /* RGH 200597: Need to disable for BVME6000, as it gets Check Conditions - * and then dies. Seems to handle Check Condition at startup, but - * not mid kernel build. */ - if (dsps == A_int_norm_emulateintfly && cmd && cmd->result == 2) - dsps = A_int_err_check_condition; -#endif - - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : DSPS = 0x%x\n", host->host_no, dsps); - - switch (dsps) { - case A_int_msg_1: - print = 1; - switch (hostdata->msg_buf[0]) { - /* - * Unless we've initiated synchronous negotiation, I don't - * think that this should happen. - */ - case MESSAGE_REJECT: - hostdata->dsp = hostdata->script + hostdata->E_accept_message / - sizeof(u32); - hostdata->dsp_changed = 1; - if (cmd && (cmd->flags & CMD_FLAG_SDTR)) { - printk ("scsi%d : target %d rejected SDTR\n", host->host_no, - c->device->id); - cmd->flags &= ~CMD_FLAG_SDTR; - asynchronous (host, c->device->id); - print = 0; - } - break; - case INITIATE_RECOVERY: - printk ("scsi%d : extended contingent allegiance not supported yet, rejecting\n", - host->host_no); - /* Fall through to default */ - hostdata->dsp = hostdata->script + hostdata->E_reject_message / - sizeof(u32); - hostdata->dsp_changed = 1; - break; - default: - printk ("scsi%d : unsupported message, rejecting\n", - host->host_no); - hostdata->dsp = hostdata->script + hostdata->E_reject_message / - sizeof(u32); - hostdata->dsp_changed = 1; - } - if (print) { - printk ("scsi%d : received message", host->host_no); - if (c) - printk (" from target %d lun %d ", c->device->id, c->device->lun); - spi_print_msg((unsigned char *) hostdata->msg_buf); - printk("\n"); - } - - return SPECIFIC_INT_NOTHING; - - - case A_int_msg_sdtr: -/* - * At this point, hostdata->msg_buf contains - * 0 EXTENDED MESSAGE - * 1 length - * 2 SDTR - * 3 period * 4ns - * 4 offset - */ - - if (cmd) { - char buf[80]; - sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->device->id, - (cmd->flags & CMD_FLAG_SDTR) ? "accepting" : "requesting"); - print_synchronous (buf, (unsigned char *) hostdata->msg_buf); - - /* - * Initiator initiated, won't happen unless synchronous - * transfers are enabled. If we get a SDTR message in - * response to our SDTR, we should program our parameters - * such that - * offset <= requested offset - * period >= requested period - */ - if (cmd->flags & CMD_FLAG_SDTR) { - cmd->flags &= ~CMD_FLAG_SDTR; - if (hostdata->msg_buf[4]) - synchronous (host, c->device->id, (unsigned char *) - hostdata->msg_buf); - else - asynchronous (host, c->device->id); - hostdata->dsp = hostdata->script + hostdata->E_accept_message / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; - } else { - if (hostdata->options & OPTION_SYNCHRONOUS) { - cmd->flags |= CMD_FLAG_DID_SDTR; - synchronous (host, c->device->id, (unsigned char *) - hostdata->msg_buf); - } else { - hostdata->msg_buf[4] = 0; /* 0 offset = async */ - asynchronous (host, c->device->id); - } - patch_dsa_32 (cmd->dsa, dsa_msgout_other, 0, 5); - patch_dsa_32 (cmd->dsa, dsa_msgout_other, 1, (u32) - virt_to_bus ((void *)&hostdata->msg_buf)); - hostdata->dsp = hostdata->script + - hostdata->E_respond_message / sizeof(u32); - hostdata->dsp_changed = 1; - } - return SPECIFIC_INT_NOTHING; - } - /* Fall through to abort if we couldn't find a cmd, and - therefore a dsa structure to twiddle */ - case A_int_msg_wdtr: - hostdata->dsp = hostdata->script + hostdata->E_reject_message / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; - case A_int_err_unexpected_phase: - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : unexpected phase\n", host->host_no); - return SPECIFIC_INT_ABORT; - case A_int_err_selected: - if ((hostdata->chip / 100) == 8) - printk ("scsi%d : selected by target %d\n", host->host_no, - (int) NCR53c7x0_read8(SDID_REG_800) &7); - else - printk ("scsi%d : selected by target LCRC=0x%02x\n", host->host_no, - (int) NCR53c7x0_read8(LCRC_REG_10)); - hostdata->dsp = hostdata->script + hostdata->E_target_abort / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; - case A_int_err_unexpected_reselect: - if ((hostdata->chip / 100) == 8) - printk ("scsi%d : unexpected reselect by target %d lun %d\n", - host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & 7, - hostdata->reselected_identify & 7); - else - printk ("scsi%d : unexpected reselect LCRC=0x%02x\n", host->host_no, - (int) NCR53c7x0_read8(LCRC_REG_10)); - hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; -/* - * Since contingent allegiance conditions are cleared by the next - * command issued to a target, we must issue a REQUEST SENSE - * command after receiving a CHECK CONDITION status, before - * another command is issued. - * - * Since this NCR53c7x0_cmd will be freed after use, we don't - * care if we step on the various fields, so modify a few things. - */ - case A_int_err_check_condition: -#if 0 - if (hostdata->options & OPTION_DEBUG_INTR) -#endif - printk ("scsi%d : CHECK CONDITION\n", host->host_no); - if (!c) { - printk("scsi%d : CHECK CONDITION with no SCSI command\n", - host->host_no); - return SPECIFIC_INT_PANIC; - } - - /* - * FIXME : this uses the normal one-byte selection message. - * We may want to renegotiate for synchronous & WIDE transfers - * since these could be the crux of our problem. - * - hostdata->NOP_insn* FIXME : once SCSI-II tagged queuing is implemented, we'll - * have to set this up so that the rest of the DSA - * agrees with this being an untagged queue'd command. - */ - - patch_dsa_32 (cmd->dsa, dsa_msgout, 0, 1); - - /* - * Modify the table indirect for COMMAND OUT phase, since - * Request Sense is a six byte command. - */ - - patch_dsa_32 (cmd->dsa, dsa_cmdout, 0, 6); - - /* - * The CDB is now mirrored in our local non-cached - * structure, but keep the old structure up to date as well, - * just in case anyone looks at it. - */ - - /* - * XXX Need to worry about data buffer alignment/cache state - * XXX here, but currently never get A_int_err_check_condition, - * XXX so ignore problem for now. - */ - cmd->cmnd[0] = c->cmnd[0] = REQUEST_SENSE; - cmd->cmnd[0] = c->cmnd[1] &= 0xe0; /* Zero all but LUN */ - cmd->cmnd[0] = c->cmnd[2] = 0; - cmd->cmnd[0] = c->cmnd[3] = 0; - cmd->cmnd[0] = c->cmnd[4] = sizeof(c->sense_buffer); - cmd->cmnd[0] = c->cmnd[5] = 0; - - /* - * Disable dataout phase, and program datain to transfer to the - * sense buffer, and add a jump to other_transfer after the - * command so overflow/underrun conditions are detected. - */ - - patch_dsa_32 (cmd->dsa, dsa_dataout, 0, - virt_to_bus(hostdata->script) + hostdata->E_other_transfer); - patch_dsa_32 (cmd->dsa, dsa_datain, 0, - virt_to_bus(cmd->data_transfer_start)); - cmd->data_transfer_start[0] = (((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | - DCMD_BMI_IO)) << 24) | sizeof(c->sense_buffer); - cmd->data_transfer_start[1] = (u32) virt_to_bus(c->sense_buffer); - - cmd->data_transfer_start[2] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) - << 24) | DBC_TCI_TRUE; - cmd->data_transfer_start[3] = (u32) virt_to_bus(hostdata->script) + - hostdata->E_other_transfer; - - /* - * Currently, this command is flagged as completed, ie - * it has valid status and message data. Reflag it as - * incomplete. Q - need to do something so that original - * status, etc are used. - */ - - cmd->result = cmd->cmd->result = 0xffff; - - /* - * Restart command as a REQUEST SENSE. - */ - hostdata->dsp = (u32 *) hostdata->script + hostdata->E_select / - sizeof(u32); - hostdata->dsp_changed = 1; - return SPECIFIC_INT_NOTHING; - case A_int_debug_break: - return SPECIFIC_INT_BREAK; - case A_int_norm_aborted: - hostdata->dsp = (u32 *) hostdata->schedule; - hostdata->dsp_changed = 1; - if (cmd) - abnormal_finished (cmd, DID_ERROR << 16); - return SPECIFIC_INT_NOTHING; - case A_int_norm_emulateintfly: - NCR53c7x0_intfly(host); - return SPECIFIC_INT_NOTHING; - case A_int_test_1: - case A_int_test_2: - hostdata->idle = 1; - hostdata->test_completed = (dsps - A_int_test_1) / 0x00010000 + 1; - if (hostdata->options & OPTION_DEBUG_INTR) - printk("scsi%d : test%d complete\n", host->host_no, - hostdata->test_completed); - return SPECIFIC_INT_NOTHING; -#ifdef A_int_debug_reselected_ok - case A_int_debug_reselected_ok: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - /* - * Note - this dsa is not based on location relative to - * the command structure, but to location relative to the - * DSA register - */ - u32 *dsa; - dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG)); - - printk("scsi%d : reselected_ok (DSA = 0x%x (virt 0x%p)\n", - host->host_no, NCR53c7x0_read32(DSA_REG), dsa); - printk("scsi%d : resume address is 0x%x (virt 0x%p)\n", - host->host_no, cmd->saved_data_pointer, - bus_to_virt(cmd->saved_data_pointer)); - print_insn (host, hostdata->script + Ent_reselected_ok / - sizeof(u32), "", 1); - if ((hostdata->chip / 100) == 8) - printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n", - host->host_no, NCR53c7x0_read8(SXFER_REG), - NCR53c7x0_read8(SCNTL3_REG_800)); - else - printk ("scsi%d : sxfer=0x%x, cannot read SBCL\n", - host->host_no, NCR53c7x0_read8(SXFER_REG)); - if (c) { - print_insn (host, (u32 *) - hostdata->sync[c->device->id].script, "", 1); - print_insn (host, (u32 *) - hostdata->sync[c->device->id].script + 2, "", 1); - } - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_reselect_check - case A_int_debug_reselect_check: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - u32 *dsa; -#if 0 - u32 *code; -#endif - /* - * Note - this dsa is not based on location relative to - * the command structure, but to location relative to the - * DSA register - */ - dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG)); - printk("scsi%d : reselected_check_next (DSA = 0x%lx (virt 0x%p))\n", - host->host_no, virt_to_bus(dsa), dsa); - if (dsa) { - printk("scsi%d : resume address is 0x%x (virt 0x%p)\n", - host->host_no, cmd->saved_data_pointer, - bus_to_virt (cmd->saved_data_pointer)); -#if 0 - printk("scsi%d : template code :\n", host->host_no); - for (code = dsa + (Ent_dsa_code_check_reselect - Ent_dsa_zero) - / sizeof(u32); code < (dsa + Ent_dsa_zero / sizeof(u32)); - code += print_insn (host, code, "", 1)); -#endif - } - print_insn (host, hostdata->script + Ent_reselected_ok / - sizeof(u32), "", 1); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_dsa_schedule - case A_int_debug_dsa_schedule: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - u32 *dsa; - /* - * Note - this dsa is not based on location relative to - * the command structure, but to location relative to the - * DSA register - */ - dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG)); - printk("scsi%d : dsa_schedule (old DSA = 0x%lx (virt 0x%p))\n", - host->host_no, virt_to_bus(dsa), dsa); - if (dsa) - printk("scsi%d : resume address is 0x%x (virt 0x%p)\n" - " (temp was 0x%x (virt 0x%p))\n", - host->host_no, cmd->saved_data_pointer, - bus_to_virt (cmd->saved_data_pointer), - NCR53c7x0_read32 (TEMP_REG), - bus_to_virt (NCR53c7x0_read32(TEMP_REG))); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_scheduled - case A_int_debug_scheduled: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - printk("scsi%d : new I/O 0x%x (virt 0x%p) scheduled\n", - host->host_no, NCR53c7x0_read32(DSA_REG), - bus_to_virt(NCR53c7x0_read32(DSA_REG))); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_idle - case A_int_debug_idle: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - printk("scsi%d : idle\n", host->host_no); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_cmd - case A_int_debug_cmd: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - printk("scsi%d : command sent\n"); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_dsa_loaded - case A_int_debug_dsa_loaded: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - printk("scsi%d : DSA loaded with 0x%x (virt 0x%p)\n", host->host_no, - NCR53c7x0_read32(DSA_REG), - bus_to_virt(NCR53c7x0_read32(DSA_REG))); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_reselected - case A_int_debug_reselected: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - if ((hostdata->chip / 100) == 8) - printk("scsi%d : reselected by target %d lun %d\n", - host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & ~0x80, - (int) hostdata->reselected_identify & 7); - else - printk("scsi%d : reselected by LCRC=0x%02x lun %d\n", - host->host_no, (int) NCR53c7x0_read8(LCRC_REG_10), - (int) hostdata->reselected_identify & 7); - print_queues(host); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_disconnect_msg - case A_int_debug_disconnect_msg: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { - if (c) - printk("scsi%d : target %d lun %d disconnecting\n", - host->host_no, c->device->id, c->device->lun); - else - printk("scsi%d : unknown target disconnecting\n", - host->host_no); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_disconnected - case A_int_debug_disconnected: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - printk ("scsi%d : disconnected, new queues are\n", - host->host_no); - print_queues(host); -#if 0 - /* Not valid on ncr53c710! */ - printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n", - host->host_no, NCR53c7x0_read8(SXFER_REG), - NCR53c7x0_read8(SCNTL3_REG_800)); -#endif - if (c) { - print_insn (host, (u32 *) - hostdata->sync[c->device->id].script, "", 1); - print_insn (host, (u32 *) - hostdata->sync[c->device->id].script + 2, "", 1); - } - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_panic - case A_int_debug_panic: - printk("scsi%d : int_debug_panic received\n", host->host_no); - print_lots (host); - return SPECIFIC_INT_PANIC; -#endif -#ifdef A_int_debug_saved - case A_int_debug_saved: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - printk ("scsi%d : saved data pointer 0x%x (virt 0x%p)\n", - host->host_no, cmd->saved_data_pointer, - bus_to_virt (cmd->saved_data_pointer)); - print_progress (c); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_restored - case A_int_debug_restored: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT)) { - if (cmd) { - int size; - printk ("scsi%d : restored data pointer 0x%x (virt 0x%p)\n", - host->host_no, cmd->saved_data_pointer, bus_to_virt ( - cmd->saved_data_pointer)); - size = print_insn (host, (u32 *) - bus_to_virt(cmd->saved_data_pointer), "", 1); - size = print_insn (host, (u32 *) - bus_to_virt(cmd->saved_data_pointer) + size, "", 1); - print_progress (c); - } -#if 0 - printk ("scsi%d : datapath residual %d\n", - host->host_no, datapath_residual (host)) ; -#endif - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_sync - case A_int_debug_sync: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) { - unsigned char sxfer = NCR53c7x0_read8 (SXFER_REG), scntl3; - if ((hostdata->chip / 100) == 8) { - scntl3 = NCR53c7x0_read8 (SCNTL3_REG_800); - if (c) { - if (sxfer != hostdata->sync[c->device->id].sxfer_sanity || - scntl3 != hostdata->sync[c->device->id].scntl3_sanity) { - printk ("scsi%d : sync sanity check failed sxfer=0x%x, scntl3=0x%x", - host->host_no, sxfer, scntl3); - NCR53c7x0_write8 (SXFER_REG, sxfer); - NCR53c7x0_write8 (SCNTL3_REG_800, scntl3); - } - } else - printk ("scsi%d : unknown command sxfer=0x%x, scntl3=0x%x\n", - host->host_no, (int) sxfer, (int) scntl3); - } else { - if (c) { - if (sxfer != hostdata->sync[c->device->id].sxfer_sanity) { - printk ("scsi%d : sync sanity check failed sxfer=0x%x", - host->host_no, sxfer); - NCR53c7x0_write8 (SXFER_REG, sxfer); - NCR53c7x0_write8 (SBCL_REG, - hostdata->sync[c->device->id].sscf_710); - } - } else - printk ("scsi%d : unknown command sxfer=0x%x\n", - host->host_no, (int) sxfer); - } - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_datain - case A_int_debug_datain: - if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| - OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) { - int size; - if ((hostdata->chip / 100) == 8) - printk ("scsi%d : In do_datain (%s) sxfer=0x%x, scntl3=0x%x\n" - " datapath residual=%d\n", - host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)), - (int) NCR53c7x0_read8(SXFER_REG), - (int) NCR53c7x0_read8(SCNTL3_REG_800), - datapath_residual (host)) ; - else - printk ("scsi%d : In do_datain (%s) sxfer=0x%x\n" - " datapath residual=%d\n", - host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)), - (int) NCR53c7x0_read8(SXFER_REG), - datapath_residual (host)) ; - print_insn (host, dsp, "", 1); - size = print_insn (host, (u32 *) bus_to_virt(dsp[1]), "", 1); - print_insn (host, (u32 *) bus_to_virt(dsp[1]) + size, "", 1); - } - return SPECIFIC_INT_RESTART; -#endif -#ifdef A_int_debug_check_dsa - case A_int_debug_check_dsa: - if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) { - int sdid; - int tmp; - char *where; - if (hostdata->chip / 100 == 8) - sdid = NCR53c7x0_read8 (SDID_REG_800) & 15; - else { - tmp = NCR53c7x0_read8 (SDID_REG_700); - if (!tmp) - panic ("SDID_REG_700 = 0"); - tmp >>= 1; - sdid = 0; - while (tmp) { - tmp >>= 1; - sdid++; - } - } - where = dsp - NCR53c7x0_insn_size(NCR53c7x0_read8 - (DCMD_REG)) == hostdata->script + - Ent_select_check_dsa / sizeof(u32) ? - "selection" : "reselection"; - if (c && sdid != c->device->id) { - printk ("scsi%d : SDID target %d != DSA target %d at %s\n", - host->host_no, sdid, c->device->id, where); - print_lots(host); - dump_events (host, 20); - return SPECIFIC_INT_PANIC; - } - } - return SPECIFIC_INT_RESTART; -#endif - default: - if ((dsps & 0xff000000) == 0x03000000) { - printk ("scsi%d : misc debug interrupt 0x%x\n", - host->host_no, dsps); - return SPECIFIC_INT_RESTART; - } else if ((dsps & 0xff000000) == 0x05000000) { - if (hostdata->events) { - struct NCR53c7x0_event *event; - ++hostdata->event_index; - if (hostdata->event_index >= hostdata->event_size) - hostdata->event_index = 0; - event = (struct NCR53c7x0_event *) hostdata->events + - hostdata->event_index; - event->event = (enum ncr_event) dsps; - event->dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); - if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) { - if (hostdata->chip / 100 == 8) - event->target = NCR53c7x0_read8(SSID_REG_800); - else { - unsigned char tmp, sdid; - tmp = NCR53c7x0_read8 (SDID_REG_700); - if (!tmp) - panic ("SDID_REG_700 = 0"); - tmp >>= 1; - sdid = 0; - while (tmp) { - tmp >>= 1; - sdid++; - } - event->target = sdid; - } - } - else - event->target = 255; - - if (event->event == EVENT_RESELECT) - event->lun = hostdata->reselected_identify & 0xf; - else if (c) - event->lun = c->device->lun; - else - event->lun = 255; - do_gettimeofday(&(event->time)); - if (c) { - event->pid = c->pid; - memcpy ((void *) event->cmnd, (void *) c->cmnd, - sizeof (event->cmnd)); - } else { - event->pid = -1; - } - } - return SPECIFIC_INT_RESTART; - } - - printk ("scsi%d : unknown user interrupt 0x%x\n", - host->host_no, (unsigned) dsps); - return SPECIFIC_INT_PANIC; - } -} - -/* - * XXX - the stock NCR assembler won't output the scriptu.h file, - * which undefine's all #define'd CPP symbols from the script.h - * file, which will create problems if you use multiple scripts - * with the same symbol names. - * - * If you insist on using NCR's assembler, you could generate - * scriptu.h from script.h using something like - * - * grep #define script.h | \ - * sed 's/#define[ ][ ]*\([_a-zA-Z][_a-zA-Z0-9]*\).*$/#undefine \1/' \ - * > scriptu.h - */ - -#include "53c7xx_u.h" - -/* XXX - add alternate script handling code here */ - - -/* - * Function : static void NCR537xx_soft_reset (struct Scsi_Host *host) - * - * Purpose : perform a soft reset of the NCR53c7xx chip - * - * Inputs : host - pointer to this host adapter's structure - * - * Preconditions : NCR53c7x0_init must have been called for this - * host. - * - */ - -static void -NCR53c7x0_soft_reset (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - unsigned long flags; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - NCR53c7x0_local_setup(host); - - local_irq_save(flags); - - /* Disable scsi chip and s/w level 7 ints */ - -#ifdef CONFIG_MVME16x - if (MACH_IS_MVME16x) - { - volatile unsigned long v; - - v = *(volatile unsigned long *)0xfff4006c; - v &= ~0x8000; - *(volatile unsigned long *)0xfff4006c = v; - v = *(volatile unsigned long *)0xfff4202c; - v &= ~0x10; - *(volatile unsigned long *)0xfff4202c = v; - } -#endif - /* Anything specific for your hardware? */ - - /* - * Do a soft reset of the chip so that everything is - * reinitialized to the power-on state. - * - * Basically follow the procedure outlined in the NCR53c700 - * data manual under Chapter Six, How to Use, Steps Necessary to - * Start SCRIPTS, with the exception of actually starting the - * script and setting up the synchronous transfer gunk. - */ - - /* Should we reset the scsi bus here??????????????????? */ - - NCR53c7x0_write8(ISTAT_REG_700, ISTAT_10_SRST); - NCR53c7x0_write8(ISTAT_REG_700, 0); - - /* - * saved_dcntl is set up in NCR53c7x0_init() before it is overwritten - * here. We should have some better way of working out the CF bit - * setting.. - */ - - hostdata->saved_dcntl = DCNTL_10_EA|DCNTL_10_COM; - if (hostdata->scsi_clock > 50000000) - hostdata->saved_dcntl |= DCNTL_700_CF_3; - else - if (hostdata->scsi_clock > 37500000) - hostdata->saved_dcntl |= DCNTL_700_CF_2; -#if 0 - else - /* Any clocks less than 37.5MHz? */ -#endif - - if (hostdata->options & OPTION_DEBUG_TRACE) - NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM); - else - NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl); - /* Following disables snooping - snooping is not required, as non- - * cached pages are used for shared data, and appropriate use is - * made of cache_push/cache_clear. Indeed, for 68060 - * enabling snooping causes disk corruption of ext2fs free block - * bitmaps and the like. If you have a 68060 with snooping hardwared - * on, then you need to enable CONFIG_060_WRITETHROUGH. - */ - NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD); - /* Actually burst of eight, according to my 53c710 databook */ - NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2); - NCR53c7x0_write8(SCID_REG, 1 << host->this_id); - NCR53c7x0_write8(SBCL_REG, 0); - NCR53c7x0_write8(SCNTL1_REG, SCNTL1_ESR_700); - NCR53c7x0_write8(SCNTL0_REG, ((hostdata->options & OPTION_PARITY) ? - SCNTL0_EPC : 0) | SCNTL0_EPG_700 | SCNTL0_ARB1 | SCNTL0_ARB2); - - /* - * Enable all interrupts, except parity which we only want when - * the user requests it. - */ - - NCR53c7x0_write8(DIEN_REG, DIEN_700_BF | - DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC); - - NCR53c7x0_write8(SIEN_REG_700, ((hostdata->options & OPTION_PARITY) ? - SIEN_PAR : 0) | SIEN_700_STO | SIEN_RST | SIEN_UDC | - SIEN_SGE | SIEN_MA); - -#ifdef CONFIG_MVME16x - if (MACH_IS_MVME16x) - { - volatile unsigned long v; - - /* Enable scsi chip and s/w level 7 ints */ - v = *(volatile unsigned long *)0xfff40080; - v = (v & ~(0xf << 28)) | (4 << 28); - *(volatile unsigned long *)0xfff40080 = v; - v = *(volatile unsigned long *)0xfff4006c; - v |= 0x8000; - *(volatile unsigned long *)0xfff4006c = v; - v = *(volatile unsigned long *)0xfff4202c; - v = (v & ~0xff) | 0x10 | 4; - *(volatile unsigned long *)0xfff4202c = v; - } -#endif - /* Anything needed for your hardware? */ - local_irq_restore(flags); -} - - -/* - * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd) - * - * Purpose : Return the first free NCR53c7x0_cmd structure (which are - * reused in a LIFO manner to minimize cache thrashing). - * - * Side effects : If we haven't yet scheduled allocation of NCR53c7x0_cmd - * structures for this device, do so. Attempt to complete all scheduled - * allocations using get_zeroed_page(), putting NCR53c7x0_cmd structures on - * the free list. Teach programmers not to drink and hack. - * - * Inputs : cmd - SCSI command - * - * Returns : NCR53c7x0_cmd structure allocated on behalf of cmd; - * NULL on failure. - */ - -static void -my_free_page (void *addr, int dummy) -{ - /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which - * XXX may be invalid (CONFIG_060_WRITETHROUGH) - */ - kernel_set_cachemode((void *)addr, 4096, IOMAP_FULL_CACHING); - free_page ((u32)addr); -} - -static struct NCR53c7x0_cmd * -allocate_cmd (Scsi_Cmnd *cmd) { - struct Scsi_Host *host = cmd->device->host; - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata[0]; - u32 real; /* Real address */ - int size; /* Size of *tmp */ - struct NCR53c7x0_cmd *tmp; - unsigned long flags; - - if (hostdata->options & OPTION_DEBUG_ALLOCATION) - printk ("scsi%d : num_cmds = %d, can_queue = %d\n" - " target = %d, lun = %d, %s\n", - host->host_no, hostdata->num_cmds, host->can_queue, - cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] & - (1 << cmd->device->lun)) ? "already allocated" : "not allocated"); - -/* - * If we have not yet reserved commands for this I_T_L nexus, and - * the device exists (as indicated by permanent Scsi_Cmnd structures - * being allocated under 1.3.x, or being outside of scan_scsis in - * 1.2.x), do so now. - */ - if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) && - cmd->device && cmd->device->has_cmdblocks) { - if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue) - hostdata->extra_allocate += host->cmd_per_lun; - hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun); - } - - for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, - ++hostdata->num_cmds) { - /* historically, kmalloc has returned unaligned addresses; pad so we - have enough room to ROUNDUP */ - size = hostdata->max_cmd_size + sizeof (void *); -#ifdef FORCE_DSA_ALIGNMENT - /* - * 53c710 rev.0 doesn't have an add-with-carry instruction. - * Ensure we allocate enough memory to force alignment. - */ - size += 256; -#endif -/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */ - - if (size > 4096) { - printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n"); - return NULL; - } - real = get_zeroed_page(GFP_ATOMIC); - if (real == 0) - return NULL; - cache_push(virt_to_phys((void *)real), 4096); - cache_clear(virt_to_phys((void *)real), 4096); - kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER); - tmp = ROUNDUP(real, void *); -#ifdef FORCE_DSA_ALIGNMENT - { - if (((u32)tmp & 0xff) > CmdPageStart) - tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255); - tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart); -#if 0 - printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n", - size, real, (u32)tmp); -#endif - } -#endif - tmp->real = (void *)real; - tmp->size = size; - tmp->free = ((void (*)(void *, int)) my_free_page); - local_irq_save(flags); - tmp->next = hostdata->free; - hostdata->free = tmp; - local_irq_restore(flags); - } - local_irq_save(flags); - tmp = (struct NCR53c7x0_cmd *) hostdata->free; - if (tmp) { - hostdata->free = tmp->next; - } - local_irq_restore(flags); - if (!tmp) - printk ("scsi%d : can't allocate command for target %d lun %d\n", - host->host_no, cmd->device->id, cmd->device->lun); - return tmp; -} - -/* - * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) - * - * - * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the - * Scsi_Cmnd structure passed in cmd, including dsa and Linux field - * initialization, and dsa code relocation. - * - * Inputs : cmd - SCSI command - * - * Returns : NCR53c7x0_cmd structure corresponding to cmd, - * NULL on failure. - */ -static struct NCR53c7x0_cmd * -create_cmd (Scsi_Cmnd *cmd) { - NCR53c7x0_local_declare(); - struct Scsi_Host *host = cmd->device->host; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - struct NCR53c7x0_cmd *tmp; /* NCR53c7x0_cmd structure for this command */ - int datain, /* Number of instructions per phase */ - dataout; - int data_transfer_instructions, /* Count of dynamic instructions */ - i; /* Counter */ - u32 *cmd_datain, /* Address of datain/dataout code */ - *cmd_dataout; /* Incremented as we assemble */ -#ifdef notyet - unsigned char *msgptr; /* Current byte in select message */ - int msglen; /* Length of whole select message */ -#endif - unsigned long flags; - u32 exp_select_indirect; /* Used in sanity check */ - NCR53c7x0_local_setup(cmd->device->host); - - if (!(tmp = allocate_cmd (cmd))) - return NULL; - - /* - * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd. - * We do this because NCR53c7x0_cmd may have a special cache mode - * selected to cope with lack of bus snooping, etc. - */ - - memcpy(tmp->cmnd, cmd->cmnd, 12); - tmp->result = cmd->result; - - /* - * Decide whether we need to generate commands for DATA IN, - * DATA OUT, neither, or both based on the SCSI command - */ - - switch (cmd->cmnd[0]) { - /* These commands do DATA IN */ - case INQUIRY: - case MODE_SENSE: - case READ_6: - case READ_10: - case READ_CAPACITY: - case REQUEST_SENSE: - case READ_BLOCK_LIMITS: - case READ_TOC: - datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; - dataout = 0; - break; - /* These commands do DATA OUT */ - case MODE_SELECT: - case WRITE_6: - case WRITE_10: -#if 0 - printk("scsi%d : command is ", host->host_no); - __scsi_print_command(cmd->cmnd); -#endif -#if 0 - printk ("scsi%d : %d scatter/gather segments\n", host->host_no, - cmd->use_sg); -#endif - datain = 0; - dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; -#if 0 - hostdata->options |= OPTION_DEBUG_INTR; -#endif - break; - /* - * These commands do no data transfer, we should force an - * interrupt if a data phase is attempted on them. - */ - case TEST_UNIT_READY: - case ALLOW_MEDIUM_REMOVAL: - case START_STOP: - datain = dataout = 0; - break; - /* - * We don't know about these commands, so generate code to handle - * both DATA IN and DATA OUT phases. More efficient to identify them - * and add them to the above cases. - */ - default: - printk("scsi%d : datain+dataout for command ", host->host_no); - __scsi_print_command(cmd->cmnd); - datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; - } - - /* - * New code : so that active pointers work correctly regardless - * of where the saved data pointer is at, we want to immediately - * enter the dynamic code after selection, and on a non-data - * phase perform a CALL to the non-data phase handler, with - * returns back to this address. - * - * If a phase mismatch is encountered in the middle of a - * Block MOVE instruction, we want to _leave_ that instruction - * unchanged as the current case is, modify a temporary buffer, - * and point the active pointer (TEMP) at that. - * - * Furthermore, we want to implement a saved data pointer, - * set by the SAVE_DATA_POINTERs message. - * - * So, the data transfer segments will change to - * CALL data_transfer, WHEN NOT data phase - * MOVE x, x, WHEN data phase - * ( repeat ) - * JUMP other_transfer - */ - - data_transfer_instructions = datain + dataout; - - /* - * When we perform a request sense, we overwrite various things, - * including the data transfer code. Make sure we have enough - * space to do that. - */ - - if (data_transfer_instructions < 2) - data_transfer_instructions = 2; - - - /* - * The saved data pointer is set up so that a RESTORE POINTERS message - * will start the data transfer over at the beginning. - */ - - tmp->saved_data_pointer = virt_to_bus (hostdata->script) + - hostdata->E_data_transfer; - - /* - * Initialize Linux specific fields. - */ - - tmp->cmd = cmd; - tmp->next = NULL; - tmp->flags = 0; - tmp->dsa_next_addr = virt_to_bus(tmp->dsa) + hostdata->dsa_next - - hostdata->dsa_start; - tmp->dsa_addr = virt_to_bus(tmp->dsa) - hostdata->dsa_start; - - /* - * Calculate addresses of dynamic code to fill in DSA - */ - - tmp->data_transfer_start = tmp->dsa + (hostdata->dsa_end - - hostdata->dsa_start) / sizeof(u32); - tmp->data_transfer_end = tmp->data_transfer_start + - 2 * data_transfer_instructions; - - cmd_datain = datain ? tmp->data_transfer_start : NULL; - cmd_dataout = dataout ? (datain ? cmd_datain + 2 * datain : tmp-> - data_transfer_start) : NULL; - - /* - * Fill in the NCR53c7x0_cmd structure as follows - * dsa, with fixed up DSA code - * datain code - * dataout code - */ - - /* Copy template code into dsa and perform all necessary fixups */ - if (hostdata->dsa_fixup) - hostdata->dsa_fixup(tmp); - - patch_dsa_32(tmp->dsa, dsa_next, 0, 0); - /* - * XXX is this giving 53c710 access to the Scsi_Cmnd in some way? - * Do we need to change it for caching reasons? - */ - patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd)); - - if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) { - - exp_select_indirect = ((1 << cmd->device->id) << 16) | - (hostdata->sync[cmd->device->id].sxfer_sanity << 8); - - if (hostdata->sync[cmd->device->id].select_indirect != - exp_select_indirect) { - printk ("scsi%d : sanity check failed select_indirect=0x%x\n", - host->host_no, hostdata->sync[cmd->device->id].select_indirect); - FATAL(host); - - } - } - - patch_dsa_32(tmp->dsa, dsa_select, 0, - hostdata->sync[cmd->device->id].select_indirect); - - /* - * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on - * different commands; although it should be trivial to do them - * both at the same time. - */ - if (hostdata->initiate_wdtr & (1 << cmd->device->id)) { - memcpy ((void *) (tmp->select + 1), (void *) wdtr_message, - sizeof(wdtr_message)); - patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message)); - local_irq_save(flags); - hostdata->initiate_wdtr &= ~(1 << cmd->device->id); - local_irq_restore(flags); - } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) { - memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, - sizeof(sdtr_message)); - patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message)); - tmp->flags |= CMD_FLAG_SDTR; - local_irq_save(flags); - hostdata->initiate_sdtr &= ~(1 << cmd->device->id); - local_irq_restore(flags); - - } -#if 1 - else if (!(hostdata->talked_to & (1 << cmd->device->id)) && - !(hostdata->options & OPTION_NO_ASYNC)) { - - memcpy ((void *) (tmp->select + 1), (void *) async_message, - sizeof(async_message)); - patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(async_message)); - tmp->flags |= CMD_FLAG_SDTR; - } -#endif - else - patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1); - - hostdata->talked_to |= (1 << cmd->device->id); - tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ? - IDENTIFY (1, cmd->device->lun) : IDENTIFY (0, cmd->device->lun); - patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select)); - patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len); - patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd)); - patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? - virt_to_bus (cmd_dataout) - : virt_to_bus (hostdata->script) + hostdata->E_other_transfer); - patch_dsa_32(tmp->dsa, dsa_datain, 0, cmd_datain ? - virt_to_bus (cmd_datain) - : virt_to_bus (hostdata->script) + hostdata->E_other_transfer); - /* - * XXX - need to make endian aware, should use separate variables - * for both status and message bytes. - */ - patch_dsa_32(tmp->dsa, dsa_msgin, 0, 1); -/* - * FIXME : these only works for little endian. We probably want to - * provide message and status fields in the NCR53c7x0_cmd - * structure, and assign them to cmd->result when we're done. - */ -#ifdef BIG_ENDIAN - patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 2); - patch_dsa_32(tmp->dsa, dsa_status, 0, 1); - patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result) + 3); -#else - patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 1); - patch_dsa_32(tmp->dsa, dsa_status, 0, 1); - patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result)); -#endif - patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1); - patch_dsa_32(tmp->dsa, dsa_msgout_other, 1, - virt_to_bus(&(hostdata->NCR53c7xx_msg_nop))); - - /* - * Generate code for zero or more of the DATA IN, DATA OUT phases - * in the format - * - * CALL data_transfer, WHEN NOT phase - * MOVE first buffer length, first buffer address, WHEN phase - * ... - * MOVE last buffer length, last buffer address, WHEN phase - * JUMP other_transfer - */ - -/* - * See if we're getting to data transfer by generating an unconditional - * interrupt. - */ -#if 0 - if (datain) { - cmd_datain[0] = 0x98080000; - cmd_datain[1] = 0x03ffd00d; - cmd_datain += 2; - } -#endif - -/* - * XXX - I'm undecided whether all of this nonsense is faster - * in the long run, or whether I should just go and implement a loop - * on the NCR chip using table indirect mode? - * - * In any case, this is how it _must_ be done for 53c700/700-66 chips, - * so this stays even when we come up with something better. - * - * When we're limited to 1 simultaneous command, no overlapping processing, - * we're seeing 630K/sec, with 7% CPU usage on a slow Syquest 45M - * drive. - * - * Not bad, not good. We'll see. - */ - - tmp->bounce.len = 0; /* Assume aligned buffer */ - - for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, - cmd_dataout += 4, ++i) { - u32 vbuf = cmd->use_sg - ? (u32)page_address(((struct scatterlist *)cmd->request_buffer)[i].page)+ - ((struct scatterlist *)cmd->request_buffer)[i].offset - : (u32)(cmd->request_buffer); - u32 bbuf = virt_to_bus((void *)vbuf); - u32 count = cmd->use_sg ? - ((struct scatterlist *)cmd->request_buffer)[i].length : - cmd->request_bufflen; - - /* - * If we have buffers which are not aligned with 16 byte cache - * lines, then we just hope nothing accesses the other parts of - * those cache lines while the transfer is in progress. That would - * fill the cache, and subsequent reads of the dma data would pick - * up the wrong thing. - * XXX We need a bounce buffer to handle that correctly. - */ - - if (((bbuf & 15) || (count & 15)) && (datain || dataout)) - { - /* Bounce buffer needed */ - if (cmd->use_sg) - printk ("53c7xx: Non-aligned buffer with use_sg\n"); - else if (datain && dataout) - printk ("53c7xx: Non-aligned buffer with datain && dataout\n"); - else if (count > 256) - printk ("53c7xx: Non-aligned transfer > 256 bytes\n"); - else - { - if (datain) - { - tmp->bounce.len = count; - tmp->bounce.addr = vbuf; - bbuf = virt_to_bus(tmp->bounce.buf); - tmp->bounce.buf[0] = 0xff; - tmp->bounce.buf[1] = 0xfe; - tmp->bounce.buf[2] = 0xfd; - tmp->bounce.buf[3] = 0xfc; - } - if (dataout) - { - memcpy ((void *)tmp->bounce.buf, (void *)vbuf, count); - bbuf = virt_to_bus(tmp->bounce.buf); - } - } - } - - if (datain) { - cache_clear(virt_to_phys((void *)vbuf), count); - /* CALL other_in, WHEN NOT DATA_IN */ - cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | - DCMD_TCI_IO) << 24) | - DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; - cmd_datain[1] = virt_to_bus (hostdata->script) + - hostdata->E_other_in; - /* MOVE count, buf, WHEN DATA_IN */ - cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO) - << 24) | count; - cmd_datain[3] = bbuf; -#if 0 - print_insn (host, cmd_datain, "dynamic ", 1); - print_insn (host, cmd_datain + 2, "dynamic ", 1); -#endif - } - if (dataout) { - cache_push(virt_to_phys((void *)vbuf), count); - /* CALL other_out, WHEN NOT DATA_OUT */ - cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) | - DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; - cmd_dataout[1] = virt_to_bus(hostdata->script) + - hostdata->E_other_out; - /* MOVE count, buf, WHEN DATA+OUT */ - cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24) - | count; - cmd_dataout[3] = bbuf; -#if 0 - print_insn (host, cmd_dataout, "dynamic ", 1); - print_insn (host, cmd_dataout + 2, "dynamic ", 1); -#endif - } - } - - /* - * Install JUMP instructions after the data transfer routines to return - * control to the do_other_transfer routines. - */ - - - if (datain) { - cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) | - DBC_TCI_TRUE; - cmd_datain[1] = virt_to_bus(hostdata->script) + - hostdata->E_other_transfer; -#if 0 - print_insn (host, cmd_datain, "dynamic jump ", 1); -#endif - cmd_datain += 2; - } -#if 0 - if (datain) { - cmd_datain[0] = 0x98080000; - cmd_datain[1] = 0x03ffdeed; - cmd_datain += 2; - } -#endif - if (dataout) { - cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) | - DBC_TCI_TRUE; - cmd_dataout[1] = virt_to_bus(hostdata->script) + - hostdata->E_other_transfer; -#if 0 - print_insn (host, cmd_dataout, "dynamic jump ", 1); -#endif - cmd_dataout += 2; - } - - return tmp; -} - -/* - * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd, - * void (*done)(Scsi_Cmnd *)) - * - * Purpose : enqueues a SCSI command - * - * Inputs : cmd - SCSI command, done - function called on completion, with - * a pointer to the command descriptor. - * - * Returns : 0 - * - * Side effects : - * cmd is added to the per instance driver issue_queue, with major - * twiddling done to the host specific fields of cmd. If the - * process_issue_queue coroutine isn't running, it is restarted. - * - * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to - * hold our own data, and pervert the ptr field of the SCp field - * to create a linked list. - */ - -int -NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { - struct Scsi_Host *host = cmd->device->host; - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata[0]; - unsigned long flags; - Scsi_Cmnd *tmp; - - cmd->scsi_done = done; - cmd->host_scribble = NULL; - cmd->SCp.ptr = NULL; - cmd->SCp.buffer = NULL; - -#ifdef VALID_IDS - /* Ignore commands on invalid IDs */ - if (!hostdata->valid_ids[cmd->device->id]) { - printk("scsi%d : ignoring target %d lun %d\n", host->host_no, - cmd->device->id, cmd->device->lun); - cmd->result = (DID_BAD_TARGET << 16); - done(cmd); - return 0; - } -#endif - - local_irq_save(flags); - if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) - || ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) && - !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun))) -#ifdef LINUX_1_2 - || cmd->device->id > 7 -#else - || cmd->device->id >= host->max_id -#endif - || cmd->device->id == host->this_id - || hostdata->state == STATE_DISABLED) { - printk("scsi%d : disabled or bad target %d lun %d\n", host->host_no, - cmd->device->id, cmd->device->lun); - cmd->result = (DID_BAD_TARGET << 16); - done(cmd); - local_irq_restore(flags); - return 0; - } - - if ((hostdata->options & OPTION_DEBUG_NCOMMANDS_LIMIT) && - (hostdata->debug_count_limit == 0)) { - printk("scsi%d : maximum commands exceeded\n", host->host_no); - cmd->result = (DID_BAD_TARGET << 16); - done(cmd); - local_irq_restore(flags); - return 0; - } - - if (hostdata->options & OPTION_DEBUG_READ_ONLY) { - switch (cmd->cmnd[0]) { - case WRITE_6: - case WRITE_10: - printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", - host->host_no); - cmd->result = (DID_BAD_TARGET << 16); - done(cmd); - local_irq_restore(flags); - return 0; - } - } - - if ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) && - hostdata->debug_count_limit != -1) - --hostdata->debug_count_limit; - - cmd->result = 0xffff; /* The NCR will overwrite message - and status with valid data */ - cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd); - - /* - * REQUEST SENSE commands are inserted at the head of the queue - * so that we do not clear the contingent allegiance condition - * they may be looking at. - */ - - if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { - cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue; - hostdata->issue_queue = cmd; - } else { - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr; - tmp = (Scsi_Cmnd *) tmp->SCp.ptr); - tmp->SCp.ptr = (unsigned char *) cmd; - } - local_irq_restore(flags); - run_process_issue_queue(); - return 0; -} - -/* - * Function : void to_schedule_list (struct Scsi_Host *host, - * struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd) - * - * Purpose : takes a SCSI command which was just removed from the - * issue queue, and deals with it by inserting it in the first - * free slot in the schedule list or by terminating it immediately. - * - * Inputs : - * host - SCSI host adapter; hostdata - hostdata structure for - * this adapter; cmd - a pointer to the command; should have - * the host_scribble field initialized to point to a valid - * - * Side effects : - * cmd is added to the per instance schedule list, with minor - * twiddling done to the host specific fields of cmd. - * - */ - -static __inline__ void -to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, - struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - Scsi_Cmnd *tmp = cmd->cmd; - unsigned long flags; - /* dsa start is negative, so subtraction is used */ - volatile u32 *ncrcurrent; - - int i; - NCR53c7x0_local_setup(host); -#if 0 - printk("scsi%d : new dsa is 0x%lx (virt 0x%p)\n", host->host_no, - virt_to_bus(hostdata->dsa), hostdata->dsa); -#endif - - local_irq_save(flags); - - /* - * Work around race condition : if an interrupt fired and we - * got disabled forget about this command. - */ - - if (hostdata->state == STATE_DISABLED) { - printk("scsi%d : driver disabled\n", host->host_no); - tmp->result = (DID_BAD_TARGET << 16); - cmd->next = (struct NCR53c7x0_cmd *) hostdata->free; - hostdata->free = cmd; - tmp->scsi_done(tmp); - local_irq_restore(flags); - return; - } - - for (i = host->can_queue, ncrcurrent = hostdata->schedule; - i > 0 && ncrcurrent[0] != hostdata->NOP_insn; - --i, ncrcurrent += 2 /* JUMP instructions are two words */); - - if (i > 0) { - ++hostdata->busy[tmp->device->id][tmp->device->lun]; - cmd->next = hostdata->running_list; - hostdata->running_list = cmd; - - /* Restore this instruction to a NOP once the command starts */ - cmd->dsa [(hostdata->dsa_jump_dest - hostdata->dsa_start) / - sizeof(u32)] = (u32) virt_to_bus ((void *)ncrcurrent); - /* Replace the current jump operand. */ - ncrcurrent[1] = - virt_to_bus ((void *) cmd->dsa) + hostdata->E_dsa_code_begin - - hostdata->E_dsa_code_template; - /* Replace the NOP instruction with a JUMP */ - ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | - DBC_TCI_TRUE; - } else { - printk ("scsi%d: no free slot\n", host->host_no); - disable(host); - tmp->result = (DID_ERROR << 16); - cmd->next = (struct NCR53c7x0_cmd *) hostdata->free; - hostdata->free = cmd; - tmp->scsi_done(tmp); - local_irq_restore(flags); - return; - } - - /* - * If the NCR chip is in an idle state, start it running the scheduler - * immediately. Otherwise, signal the chip to jump to schedule as - * soon as it is idle. - */ - - if (hostdata->idle) { - hostdata->idle = 0; - hostdata->state = STATE_RUNNING; - NCR53c7x0_write32 (DSP_REG, virt_to_bus ((void *)hostdata->schedule)); - if (hostdata->options & OPTION_DEBUG_TRACE) - NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | - DCNTL_SSM | DCNTL_STD); - } else { - NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP); - } - - local_irq_restore(flags); -} - -/* - * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata - * *hostdata, Scsi_Cmnd *cmd) - * - * Purpose : decide if we can pass the given SCSI command on to the - * device in question or not. - * - * Returns : non-zero when we're busy, 0 when we aren't. - */ - -static __inline__ int -busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, - Scsi_Cmnd *cmd) { - /* FIXME : in the future, this needs to accommodate SCSI-II tagged - queuing, and we may be able to play with fairness here a bit. - */ - return hostdata->busy[cmd->device->id][cmd->device->lun]; -} - -/* - * Function : process_issue_queue (void) - * - * Purpose : transfer commands from the issue queue to NCR start queue - * of each NCR53c7/8xx in the system, avoiding kernel stack - * overflows when the scsi_done() function is invoked recursively. - * - * NOTE : process_issue_queue exits with interrupts *disabled*, so the - * caller must reenable them if it desires. - * - * NOTE : process_issue_queue should be called from both - * NCR53c7x0_queue_command() and from the interrupt handler - * after command completion in case NCR53c7x0_queue_command() - * isn't invoked again but we've freed up resources that are - * needed. - */ - -static void -process_issue_queue (unsigned long flags) { - Scsi_Cmnd *tmp, *prev; - struct Scsi_Host *host; - struct NCR53c7x0_hostdata *hostdata; - int done; - - /* - * We run (with interrupts disabled) until we're sure that none of - * the host adapters have anything that can be done, at which point - * we set process_issue_queue_running to 0 and exit. - * - * Interrupts are enabled before doing various other internal - * instructions, after we've decided that we need to run through - * the loop again. - * - */ - - do { - local_irq_disable(); /* Freeze request queues */ - done = 1; - for (host = first_host; host && host->hostt == the_template; - host = host->next) { - hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; - local_irq_disable(); - if (hostdata->issue_queue) { - if (hostdata->state == STATE_DISABLED) { - tmp = (Scsi_Cmnd *) hostdata->issue_queue; - hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr; - tmp->result = (DID_BAD_TARGET << 16); - if (tmp->host_scribble) { - ((struct NCR53c7x0_cmd *)tmp->host_scribble)->next = - hostdata->free; - hostdata->free = - (struct NCR53c7x0_cmd *)tmp->host_scribble; - tmp->host_scribble = NULL; - } - tmp->scsi_done (tmp); - done = 0; - } else - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, - prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) - tmp->SCp.ptr) - if (!tmp->host_scribble || - !busyp (host, hostdata, tmp)) { - if (prev) - prev->SCp.ptr = tmp->SCp.ptr; - else - hostdata->issue_queue = (Scsi_Cmnd *) - tmp->SCp.ptr; - tmp->SCp.ptr = NULL; - if (tmp->host_scribble) { - if (hostdata->options & OPTION_DEBUG_QUEUES) - printk ("scsi%d : moving command for target %d lun %d to start list\n", - host->host_no, tmp->device->id, tmp->device->lun); - - - to_schedule_list (host, hostdata, - (struct NCR53c7x0_cmd *) - tmp->host_scribble); - } else { - if (((tmp->result & 0xff) == 0xff) || - ((tmp->result & 0xff00) == 0xff00)) { - printk ("scsi%d : danger Will Robinson!\n", - host->host_no); - tmp->result = DID_ERROR << 16; - disable (host); - } - tmp->scsi_done(tmp); - } - done = 0; - } /* if target/lun is not busy */ - } /* if hostdata->issue_queue */ - if (!done) - local_irq_restore(flags); - } /* for host */ - } while (!done); - process_issue_queue_running = 0; -} - -/* - * Function : static void intr_scsi (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : handle all SCSI interrupts, indicated by the setting - * of the SIP bit in the ISTAT register. - * - * Inputs : host, cmd - host and NCR command causing the interrupt, cmd - * may be NULL. - */ - -static void -intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata[0]; - unsigned char sstat0_sist0, sist1, /* Registers */ - fatal; /* Did a fatal interrupt - occur ? */ - - NCR53c7x0_local_setup(host); - - fatal = 0; - - sstat0_sist0 = NCR53c7x0_read8(SSTAT0_REG); - sist1 = 0; - - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : SIST0 0x%0x, SIST1 0x%0x\n", host->host_no, - sstat0_sist0, sist1); - - /* 250ms selection timeout */ - if (sstat0_sist0 & SSTAT0_700_STO) { - fatal = 1; - if (hostdata->options & OPTION_DEBUG_INTR) { - printk ("scsi%d : Selection Timeout\n", host->host_no); - if (cmd) { - printk("scsi%d : target %d, lun %d, command ", - host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); - __scsi_print_command (cmd->cmd->cmnd); - printk("scsi%d : dsp = 0x%x (virt 0x%p)\n", host->host_no, - NCR53c7x0_read32(DSP_REG), - bus_to_virt(NCR53c7x0_read32(DSP_REG))); - } else { - printk("scsi%d : no command\n", host->host_no); - } - } -/* - * XXX - question : how do we want to handle the Illegal Instruction - * interrupt, which may occur before or after the Selection Timeout - * interrupt? - */ - - if (1) { - hostdata->idle = 1; - hostdata->expecting_sto = 0; - - if (hostdata->test_running) { - hostdata->test_running = 0; - hostdata->test_completed = 3; - } else if (cmd) { - abnormal_finished(cmd, DID_BAD_TARGET << 16); - } -#if 0 - hostdata->intrs = 0; -#endif - } - } - -/* - * FIXME : in theory, we can also get a UDC when a STO occurs. - */ - if (sstat0_sist0 & SSTAT0_UDC) { - fatal = 1; - if (cmd) { - printk("scsi%d : target %d lun %d unexpected disconnect\n", - host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); - print_lots (host); - abnormal_finished(cmd, DID_ERROR << 16); - } else - printk("scsi%d : unexpected disconnect (no command)\n", - host->host_no); - - hostdata->dsp = (u32 *) hostdata->schedule; - hostdata->dsp_changed = 1; - } - - /* SCSI PARITY error */ - if (sstat0_sist0 & SSTAT0_PAR) { - fatal = 1; - if (cmd && cmd->cmd) { - printk("scsi%d : target %d lun %d parity error.\n", - host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); - abnormal_finished (cmd, DID_PARITY << 16); - } else - printk("scsi%d : parity error\n", host->host_no); - /* Should send message out, parity error */ - - /* XXX - Reduce synchronous transfer rate! */ - hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / - sizeof(u32); - hostdata->dsp_changed = 1; - /* SCSI GROSS error */ - } - - if (sstat0_sist0 & SSTAT0_SGE) { - fatal = 1; - printk("scsi%d : gross error, saved2_dsa = 0x%x\n", host->host_no, - (unsigned int)hostdata->saved2_dsa); - print_lots (host); - - /* - * A SCSI gross error may occur when we have - * - * - A synchronous offset which causes the SCSI FIFO to be overwritten. - * - * - A REQ which causes the maximum synchronous offset programmed in - * the SXFER register to be exceeded. - * - * - A phase change with an outstanding synchronous offset. - * - * - Residual data in the synchronous data FIFO, with a transfer - * other than a synchronous receive is started.$# - */ - - - /* XXX Should deduce synchronous transfer rate! */ - hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / - sizeof(u32); - hostdata->dsp_changed = 1; - /* Phase mismatch */ - } - - if (sstat0_sist0 & SSTAT0_MA) { - fatal = 1; - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : SSTAT0_MA\n", host->host_no); - intr_phase_mismatch (host, cmd); - } - -#if 0 - if (sstat0_sist0 & SIST0_800_RSL) - printk ("scsi%d : Oh no Mr. Bill!\n", host->host_no); -#endif - -/* - * If a fatal SCSI interrupt occurs, we must insure that the DMA and - * SCSI FIFOs were flushed. - */ - - if (fatal) { - if (!hostdata->dstat_valid) { - hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); - hostdata->dstat_valid = 1; - } - - if (!(hostdata->dstat & DSTAT_DFE)) { - printk ("scsi%d : DMA FIFO not empty\n", host->host_no); - /* - * Really need to check this code for 710 RGH. - * Havn't seen any problems, but maybe we should FLUSH before - * clearing sometimes. - */ - NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF); - while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF) - ; - hostdata->dstat |= DSTAT_DFE; - } - } -} - -#ifdef CYCLIC_TRACE - -/* - * The following implements a cyclic log of instructions executed, if you turn - * TRACE on. It will also print the log for you. Very useful when debugging - * 53c710 support, possibly not really needed any more. - */ - -u32 insn_log[4096]; -u32 insn_log_index = 0; - -void log1 (u32 i) -{ - insn_log[insn_log_index++] = i; - if (insn_log_index == 4096) - insn_log_index = 0; -} - -void log_insn (u32 *ip) -{ - log1 ((u32)ip); - log1 (*ip); - log1 (*(ip+1)); - if (((*ip >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) - log1 (*(ip+2)); -} - -void dump_log(void) -{ - int cnt = 0; - int i = insn_log_index; - int size; - struct Scsi_Host *host = first_host; - - while (cnt < 4096) { - printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4); - if (++i == 4096) - i = 0; - cnt++; - if (((insn_log[i] >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) - size = 3; - else - size = 2; - while (size--) { - printk ("%08x ", insn_log[i]); - if (++i == 4096) - i = 0; - cnt++; - } - printk ("\n"); - } -} -#endif - - -/* - * Function : static void NCR53c7x0_intfly (struct Scsi_Host *host) - * - * Purpose : Scan command queue for specified host, looking for completed - * commands. - * - * Inputs : Scsi_Host pointer. - * - * This is called from the interrupt handler, when a simulated INTFLY - * interrupt occurs. - */ - -static void -NCR53c7x0_intfly (struct Scsi_Host *host) -{ - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata; /* host->hostdata[0] */ - struct NCR53c7x0_cmd *cmd, /* command which halted */ - **cmd_prev_ptr; - unsigned long flags; - char search_found = 0; /* Got at least one ? */ - - hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; - NCR53c7x0_local_setup(host); - - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : INTFLY\n", host->host_no); - - /* - * Traverse our list of running commands, and look - * for those with valid (non-0xff ff) status and message - * bytes encoded in the result which signify command - * completion. - */ - - local_irq_save(flags); -restart: - for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list), - cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ; - cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), - cmd = (struct NCR53c7x0_cmd *) cmd->next) - { - Scsi_Cmnd *tmp; - - if (!cmd) { - printk("scsi%d : very weird.\n", host->host_no); - break; - } - - if (!(tmp = cmd->cmd)) { - printk("scsi%d : weird. NCR53c7x0_cmd has no Scsi_Cmnd\n", - host->host_no); - continue; - } - /* Copy the result over now; may not be complete, - * but subsequent tests may as well be done on - * cached memory. - */ - tmp->result = cmd->result; - - if (((tmp->result & 0xff) == 0xff) || - ((tmp->result & 0xff00) == 0xff00)) - continue; - - search_found = 1; - - if (cmd->bounce.len) - memcpy ((void *)cmd->bounce.addr, - (void *)cmd->bounce.buf, cmd->bounce.len); - - /* Important - remove from list _before_ done is called */ - if (cmd_prev_ptr) - *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next; - - --hostdata->busy[tmp->device->id][tmp->device->lun]; - cmd->next = hostdata->free; - hostdata->free = cmd; - - tmp->host_scribble = NULL; - - if (hostdata->options & OPTION_DEBUG_INTR) { - printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", - host->host_no, tmp->pid, tmp->device->id, tmp->device->lun, tmp->result); - __scsi_print_command (tmp->cmnd); - } - - tmp->scsi_done(tmp); - goto restart; - } - local_irq_restore(flags); - - if (!search_found) { - printk ("scsi%d : WARNING : INTFLY with no completed commands.\n", - host->host_no); - } else { - run_process_issue_queue(); - } - return; -} - -/* - * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id) - * - * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing - * the same IRQ line. - * - * Inputs : Since we're using the IRQF_DISABLED interrupt handler - * semantics, irq indicates the interrupt which invoked - * this handler. - * - * On the 710 we simualte an INTFLY with a script interrupt, and the - * script interrupt handler will call back to this function. - */ - -static irqreturn_t -NCR53c7x0_intr (int irq, void *dev_id) -{ - NCR53c7x0_local_declare(); - struct Scsi_Host *host; /* Host we are looking at */ - unsigned char istat; /* Values of interrupt regs */ - struct NCR53c7x0_hostdata *hostdata; /* host->hostdata[0] */ - struct NCR53c7x0_cmd *cmd; /* command which halted */ - u32 *dsa; /* DSA */ - int handled = 0; - -#ifdef NCR_DEBUG - char buf[80]; /* Debugging sprintf buffer */ - size_t buflen; /* Length of same */ -#endif - - host = (struct Scsi_Host *)dev_id; - hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; - NCR53c7x0_local_setup(host); - - /* - * Only read istat once per loop, since reading it again will unstack - * interrupts - */ - - while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) { - handled = 1; - hostdata->dsp_changed = 0; - hostdata->dstat_valid = 0; - hostdata->state = STATE_HALTED; - - if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) - printk ("scsi%d : SCSI FIFO not empty\n", host->host_no); - - /* - * NCR53c700 and NCR53c700-66 change the current SCSI - * process, hostdata->ncrcurrent, in the Linux driver so - * cmd = hostdata->ncrcurrent. - * - * With other chips, we must look through the commands - * executing and find the command structure which - * corresponds to the DSA register. - */ - - if (hostdata->options & OPTION_700) { - cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent; - } else { - dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); - for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; - cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa; - cmd = (struct NCR53c7x0_cmd *)(cmd->next)) - ; - } - if (hostdata->options & OPTION_DEBUG_INTR) { - if (cmd) { - printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", - host->host_no, cmd->cmd->pid, (int) cmd->cmd->device->id, - (int) cmd->cmd->device->lun); - __scsi_print_command (cmd->cmd->cmnd); - } else { - printk("scsi%d : no active command\n", host->host_no); - } - } - - if (istat & ISTAT_SIP) { - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : ISTAT_SIP\n", host->host_no); - intr_scsi (host, cmd); - } - - if (istat & ISTAT_DIP) { - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : ISTAT_DIP\n", host->host_no); - intr_dma (host, cmd); - } - - if (!hostdata->dstat_valid) { - hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); - hostdata->dstat_valid = 1; - } - - if (!(hostdata->dstat & DSTAT_DFE)) { - printk ("scsi%d : DMA FIFO not empty\n", host->host_no); - /* Really need to check this out for 710 RGH */ - NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF); - while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF) - ; - hostdata->dstat |= DSTAT_DFE; - } - - if (!hostdata->idle && hostdata->state == STATE_HALTED) { - if (!hostdata->dsp_changed) - hostdata->dsp = (u32 *)bus_to_virt(NCR53c7x0_read32(DSP_REG)); -#if 0 - printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n", - host->host_no, virt_to_bus(hostdata->dsp), hostdata->dsp); -#endif - - hostdata->state = STATE_RUNNING; - NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp)); - if (hostdata->options & OPTION_DEBUG_TRACE) { -#ifdef CYCLIC_TRACE - log_insn (hostdata->dsp); -#else - print_insn (host, hostdata->dsp, "t ", 1); -#endif - NCR53c7x0_write8 (DCNTL_REG, - hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD); - } - } - } - return IRQ_HANDLED; -} - - -/* - * Function : static int abort_connected (struct Scsi_Host *host) - * - * Purpose : Assuming that the NCR SCSI processor is currently - * halted, break the currently established nexus. Clean - * up of the NCR53c7x0_cmd and Scsi_Cmnd structures should - * be done on receipt of the abort interrupt. - * - * Inputs : host - SCSI host - * - */ - -static int -abort_connected (struct Scsi_Host *host) { -#ifdef NEW_ABORT - NCR53c7x0_local_declare(); -#endif - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; -/* FIXME : this probably should change for production kernels; at the - least, counter should move to a per-host structure. */ - static int counter = 5; -#ifdef NEW_ABORT - int sstat, phase, offset; - u32 *script; - NCR53c7x0_local_setup(host); -#endif - - if (--counter <= 0) { - disable(host); - return 0; - } - - printk ("scsi%d : DANGER : abort_connected() called \n", - host->host_no); - -#ifdef NEW_ABORT - -/* - * New strategy : Rather than using a generic abort routine, - * we'll specifically try to source or sink the appropriate - * amount of data for the phase we're currently in (taking into - * account the current synchronous offset) - */ - - sstat = NCR53c8x0_read8 (SSTAT2_REG); - offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT; - phase = sstat & SSTAT2_PHASE_MASK; - -/* - * SET ATN - * MOVE source_or_sink, WHEN CURRENT PHASE - * < repeat for each outstanding byte > - * JUMP send_abort_message - */ - - script = hostdata->abort_script = kmalloc ( - 8 /* instruction size */ * ( - 1 /* set ATN */ + - (!offset ? 1 : offset) /* One transfer per outstanding byte */ + - 1 /* send abort message */), - GFP_ATOMIC); - - -#else /* def NEW_ABORT */ - hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / - sizeof(u32); -#endif /* def NEW_ABORT */ - hostdata->dsp_changed = 1; - -/* XXX - need to flag the command as aborted after the abort_connected - code runs - */ - return 0; -} - -/* - * Function : static int datapath_residual (Scsi_Host *host) - * - * Purpose : return residual data count of what's in the chip. - * - * Inputs : host - SCSI host - */ - -static int -datapath_residual (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - int count, synchronous, sstat; - unsigned int ddir; - - NCR53c7x0_local_setup(host); - /* COMPAT : the 700 and 700-66 need to use DFIFO_00_BO_MASK */ - count = ((NCR53c7x0_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) - - (NCR53c7x0_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK; - synchronous = NCR53c7x0_read8 (SXFER_REG) & SXFER_MO_MASK; - /* COMPAT : DDIR is elsewhere on non-'8xx chips. */ - ddir = NCR53c7x0_read8 (CTEST0_REG_700) & CTEST0_700_DDIR; - - if (ddir) { - /* Receive */ - if (synchronous) - count += (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT; - else - if (NCR53c7x0_read8 (SSTAT1_REG) & SSTAT1_ILF) - ++count; - } else { - /* Send */ - sstat = NCR53c7x0_read8 (SSTAT1_REG); - if (sstat & SSTAT1_OLF) - ++count; - if (synchronous && (sstat & SSTAT1_ORF)) - ++count; - } - return count; -} - -/* - * Function : static const char * sbcl_to_phase (int sbcl)_ - * - * Purpose : Convert SBCL register to user-parsable phase representation - * - * Inputs : sbcl - value of sbcl register - */ - - -static const char * -sbcl_to_phase (int sbcl) { - switch (sbcl & SBCL_PHASE_MASK) { - case SBCL_PHASE_DATAIN: - return "DATAIN"; - case SBCL_PHASE_DATAOUT: - return "DATAOUT"; - case SBCL_PHASE_MSGIN: - return "MSGIN"; - case SBCL_PHASE_MSGOUT: - return "MSGOUT"; - case SBCL_PHASE_CMDOUT: - return "CMDOUT"; - case SBCL_PHASE_STATIN: - return "STATUSIN"; - default: - return "unknown"; - } -} - -/* - * Function : static const char * sstat2_to_phase (int sstat)_ - * - * Purpose : Convert SSTAT2 register to user-parsable phase representation - * - * Inputs : sstat - value of sstat register - */ - - -static const char * -sstat2_to_phase (int sstat) { - switch (sstat & SSTAT2_PHASE_MASK) { - case SSTAT2_PHASE_DATAIN: - return "DATAIN"; - case SSTAT2_PHASE_DATAOUT: - return "DATAOUT"; - case SSTAT2_PHASE_MSGIN: - return "MSGIN"; - case SSTAT2_PHASE_MSGOUT: - return "MSGOUT"; - case SSTAT2_PHASE_CMDOUT: - return "CMDOUT"; - case SSTAT2_PHASE_STATIN: - return "STATUSIN"; - default: - return "unknown"; - } -} - -/* - * Function : static void intr_phase_mismatch (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : Handle phase mismatch interrupts - * - * Inputs : host, cmd - host and NCR command causing the interrupt, cmd - * may be NULL. - * - * Side effects : The abort_connected() routine is called or the NCR chip - * is restarted, jumping to the command_complete entry point, or - * patching the address and transfer count of the current instruction - * and calling the msg_in entry point as appropriate. - */ - -static void -intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - u32 dbc_dcmd, *dsp, *dsp_next; - unsigned char dcmd, sbcl; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - int residual; - enum {ACTION_ABORT, ACTION_ABORT_PRINT, ACTION_CONTINUE} action = - ACTION_ABORT_PRINT; - const char *where = NULL; - - NCR53c7x0_local_setup(host); - - /* - * Corrective action is based on where in the SCSI SCRIPT(tm) the error - * occurred, as well as which SCSI phase we are currently in. - */ - dsp_next = bus_to_virt(NCR53c7x0_read32(DSP_REG)); - - /* - * Fetch the current instruction, and remove the operands for easier - * interpretation. - */ - dbc_dcmd = NCR53c7x0_read32(DBC_REG); - dcmd = (dbc_dcmd & 0xff000000) >> 24; - /* - * Like other processors, the NCR adjusts the instruction pointer before - * instruction decode. Set the DSP address back to what it should - * be for this instruction based on its size (2 or 3 32 bit words). - */ - dsp = dsp_next - NCR53c7x0_insn_size(dcmd); - - - /* - * Read new SCSI phase from the SBCL lines. Since all of our code uses - * a WHEN conditional instead of an IF conditional, we don't need to - * wait for a new REQ. - */ - sbcl = NCR53c7x0_read8(SBCL_REG) & SBCL_PHASE_MASK; - - if (!cmd) { - action = ACTION_ABORT_PRINT; - where = "no current command"; - /* - * The way my SCSI SCRIPTS(tm) are architected, recoverable phase - * mismatches should only occur where we're doing a multi-byte - * BMI instruction. Specifically, this means - * - * - select messages (a SCSI-I target may ignore additional messages - * after the IDENTIFY; any target may reject a SDTR or WDTR) - * - * - command out (targets may send a message to signal an error - * condition, or go into STATUSIN after they've decided - * they don't like the command. - * - * - reply_message (targets may reject a multi-byte message in the - * middle) - * - * - data transfer routines (command completion with buffer space - * left, disconnect message, or error message) - */ - } else if (((dsp >= cmd->data_transfer_start && - dsp < cmd->data_transfer_end)) || dsp == (cmd->residual + 2)) { - if ((dcmd & (DCMD_TYPE_MASK|DCMD_BMI_OP_MASK|DCMD_BMI_INDIRECT| - DCMD_BMI_MSG|DCMD_BMI_CD)) == (DCMD_TYPE_BMI| - DCMD_BMI_OP_MOVE_I)) { - residual = datapath_residual (host); - if (hostdata->options & OPTION_DEBUG_DISCONNECT) - printk ("scsi%d : handling residual transfer (+ %d bytes from DMA FIFO)\n", - host->host_no, residual); - - /* - * The first instruction is a CALL to the alternate handler for - * this data transfer phase, so we can do calls to - * munge_msg_restart as we would if control were passed - * from normal dynamic code. - */ - if (dsp != cmd->residual + 2) { - cmd->residual[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | - ((dcmd & DCMD_BMI_IO) ? DCMD_TCI_IO : 0)) << 24) | - DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; - cmd->residual[1] = virt_to_bus(hostdata->script) - + ((dcmd & DCMD_BMI_IO) - ? hostdata->E_other_in : hostdata->E_other_out); - } - - /* - * The second instruction is the a data transfer block - * move instruction, reflecting the pointer and count at the - * time of the phase mismatch. - */ - cmd->residual[2] = dbc_dcmd + residual; - cmd->residual[3] = NCR53c7x0_read32(DNAD_REG) - residual; - - /* - * The third and final instruction is a jump to the instruction - * which follows the instruction which had to be 'split' - */ - if (dsp != cmd->residual + 2) { - cmd->residual[4] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) - << 24) | DBC_TCI_TRUE; - cmd->residual[5] = virt_to_bus(dsp_next); - } - - /* - * For the sake of simplicity, transfer control to the - * conditional CALL at the start of the residual buffer. - */ - hostdata->dsp = cmd->residual; - hostdata->dsp_changed = 1; - action = ACTION_CONTINUE; - } else { - where = "non-BMI dynamic DSA code"; - action = ACTION_ABORT_PRINT; - } - } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4 + 2)) { - /* RGH 290697: Added +2 above, to compensate for the script - * instruction which disables the selection timer. */ - /* Release ATN */ - NCR53c7x0_write8 (SOCL_REG, 0); - switch (sbcl) { - /* - * Some devices (SQ555 come to mind) grab the IDENTIFY message - * sent on selection, and decide to go into COMMAND OUT phase - * rather than accepting the rest of the messages or rejecting - * them. Handle these devices gracefully. - */ - case SBCL_PHASE_CMDOUT: - hostdata->dsp = dsp + 2 /* two _words_ */; - hostdata->dsp_changed = 1; - printk ("scsi%d : target %d ignored SDTR and went into COMMAND OUT\n", - host->host_no, cmd->cmd->device->id); - cmd->flags &= ~CMD_FLAG_SDTR; - action = ACTION_CONTINUE; - break; - case SBCL_PHASE_MSGIN: - hostdata->dsp = hostdata->script + hostdata->E_msg_in / - sizeof(u32); - hostdata->dsp_changed = 1; - action = ACTION_CONTINUE; - break; - default: - where="select message out"; - action = ACTION_ABORT_PRINT; - } - /* - * Some SCSI devices will interpret a command as they read the bytes - * off the SCSI bus, and may decide that the command is Bogus before - * they've read the entire command off the bus. - */ - } else if (dsp == hostdata->script + hostdata->E_cmdout_cmdout / sizeof - (u32)) { - hostdata->dsp = hostdata->script + hostdata->E_data_transfer / - sizeof (u32); - hostdata->dsp_changed = 1; - action = ACTION_CONTINUE; - /* FIXME : we need to handle message reject, etc. within msg_respond. */ -#ifdef notyet - } else if (dsp == hostdata->script + hostdata->E_reply_message) { - switch (sbcl) { - /* Any other phase mismatches abort the currently executing command. */ -#endif - } else { - where = "unknown location"; - action = ACTION_ABORT_PRINT; - } - - /* Flush DMA FIFO */ - if (!hostdata->dstat_valid) { - hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); - hostdata->dstat_valid = 1; - } - if (!(hostdata->dstat & DSTAT_DFE)) { - /* Really need to check this out for 710 RGH */ - NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF); - while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF); - hostdata->dstat |= DSTAT_DFE; - } - - switch (action) { - case ACTION_ABORT_PRINT: - printk("scsi%d : %s : unexpected phase %s.\n", - host->host_no, where ? where : "unknown location", - sbcl_to_phase(sbcl)); - print_lots (host); - /* Fall through to ACTION_ABORT */ - case ACTION_ABORT: - abort_connected (host); - break; - case ACTION_CONTINUE: - break; - } - -#if 0 - if (hostdata->dsp_changed) { - printk("scsi%d: new dsp 0x%p\n", host->host_no, hostdata->dsp); - print_insn (host, hostdata->dsp, "", 1); - } -#endif -} - -/* - * Function : static void intr_bf (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : handle BUS FAULT interrupts - * - * Inputs : host, cmd - host and NCR command causing the interrupt, cmd - * may be NULL. - */ - -static void -intr_bf (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - u32 *dsp, - *next_dsp, /* Current dsp */ - *dsa, - dbc_dcmd; /* DCMD (high eight bits) + DBC */ - char *reason = NULL; - /* Default behavior is for a silent error, with a retry until we've - exhausted retries. */ - enum {MAYBE, ALWAYS, NEVER} retry = MAYBE; - int report = 0; - NCR53c7x0_local_setup(host); - - dbc_dcmd = NCR53c7x0_read32 (DBC_REG); - next_dsp = bus_to_virt (NCR53c7x0_read32(DSP_REG)); - dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff); -/* FIXME - check chip type */ - dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG)); - - /* - * Bus faults can be caused by either a Bad Address or - * Target Abort. We should check the Received Target Abort - * bit of the PCI status register and Master Abort Bit. - * - * - Master Abort bit indicates that no device claimed - * the address with DEVSEL within five clocks - * - * - Target Abort bit indicates that a target claimed it, - * but changed its mind once it saw the byte enables. - * - */ - - /* 53c710, not PCI system */ - report = 1; - reason = "Unknown"; - -#ifndef notyet - report = 1; -#endif - if (report && reason) - { - printk(KERN_ALERT "scsi%d : BUS FAULT reason = %s\n", - host->host_no, reason ? reason : "unknown"); - print_lots (host); - } - -#ifndef notyet - retry = NEVER; -#endif - - /* - * TODO : we should attempt to recover from any spurious bus - * faults. After X retries, we should figure that things are - * sufficiently wedged, and call NCR53c7xx_reset. - * - * This code should only get executed once we've decided that we - * cannot retry. - */ - - if (retry == NEVER) { - printk(KERN_ALERT " mail richard@sleepie.demon.co.uk\n"); - FATAL (host); - } -} - -/* - * Function : static void intr_dma (struct Scsi_Host *host, - * struct NCR53c7x0_cmd *cmd) - * - * Purpose : handle all DMA interrupts, indicated by the setting - * of the DIP bit in the ISTAT register. - * - * Inputs : host, cmd - host and NCR command causing the interrupt, cmd - * may be NULL. - */ - -static void -intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - unsigned char dstat; /* DSTAT */ - u32 *dsp, - *next_dsp, /* Current dsp */ - *dsa, - dbc_dcmd; /* DCMD (high eight bits) + DBC */ - int tmp; - unsigned long flags; - NCR53c7x0_local_setup(host); - - if (!hostdata->dstat_valid) { - hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); - hostdata->dstat_valid = 1; - } - - dstat = hostdata->dstat; - - if (hostdata->options & OPTION_DEBUG_INTR) - printk("scsi%d : DSTAT=0x%x\n", host->host_no, (int) dstat); - - dbc_dcmd = NCR53c7x0_read32 (DBC_REG); - next_dsp = bus_to_virt(NCR53c7x0_read32(DSP_REG)); - dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff); -/* XXX - check chip type */ - dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); - - /* - * DSTAT_ABRT is the aborted interrupt. This is set whenever the - * SCSI chip is aborted. - * - * With NCR53c700 and NCR53c700-66 style chips, we should only - * get this when the chip is currently running the accept - * reselect/select code and we have set the abort bit in the - * ISTAT register. - * - */ - - if (dstat & DSTAT_ABRT) { -#if 0 - /* XXX - add code here to deal with normal abort */ - if ((hostdata->options & OPTION_700) && (hostdata->state == - STATE_ABORTING)) { - } else -#endif - { - printk(KERN_ALERT "scsi%d : unexpected abort interrupt at\n" - " ", host->host_no); - print_insn (host, dsp, KERN_ALERT "s ", 1); - FATAL (host); - } - } - - /* - * DSTAT_SSI is the single step interrupt. Should be generated - * whenever we have single stepped or are tracing. - */ - - if (dstat & DSTAT_SSI) { - if (hostdata->options & OPTION_DEBUG_TRACE) { - /* Don't print instr. until we write DSP at end of intr function */ - } else if (hostdata->options & OPTION_DEBUG_SINGLE) { - print_insn (host, dsp, "s ", 0); - local_irq_save(flags); -/* XXX - should we do this, or can we get away with writing dsp? */ - - NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) & - ~DCNTL_SSM) | DCNTL_STD); - local_irq_restore(flags); - } else { - printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n" - " ", host->host_no); - print_insn (host, dsp, KERN_ALERT "", 1); - printk(KERN_ALERT " mail drew@PoohSticks.ORG\n"); - FATAL (host); - } - } - - /* - * DSTAT_IID / DSTAT_OPC (same bit, same meaning, only the name - * is different) is generated whenever an illegal instruction is - * encountered. - * - * XXX - we may want to emulate INTFLY here, so we can use - * the same SCSI SCRIPT (tm) for NCR53c710 through NCR53c810 - * chips. - */ - - if (dstat & DSTAT_OPC) { - /* - * Ascertain if this IID interrupts occurred before or after a STO - * interrupt. Since the interrupt handling code now leaves - * DSP unmodified until _after_ all stacked interrupts have been - * processed, reading the DSP returns the original DSP register. - * This means that if dsp lies between the select code, and - * message out following the selection code (where the IID interrupt - * would have to have occurred by due to the implicit wait for REQ), - * we have an IID interrupt resulting from a STO condition and - * can ignore it. - */ - - if (((dsp >= (hostdata->script + hostdata->E_select / sizeof(u32))) && - (dsp <= (hostdata->script + hostdata->E_select_msgout / - sizeof(u32) + 8))) || (hostdata->test_running == 2)) { - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : ignoring DSTAT_IID for SSTAT_STO\n", - host->host_no); - if (hostdata->expecting_iid) { - hostdata->expecting_iid = 0; - hostdata->idle = 1; - if (hostdata->test_running == 2) { - hostdata->test_running = 0; - hostdata->test_completed = 3; - } else if (cmd) - abnormal_finished (cmd, DID_BAD_TARGET << 16); - } else { - hostdata->expecting_sto = 1; - } - /* - * We can't guarantee we'll be able to execute the WAIT DISCONNECT - * instruction within the 3.4us of bus free and arbitration delay - * that a target can RESELECT in and assert REQ after we've dropped - * ACK. If this happens, we'll get an illegal instruction interrupt. - * Doing away with the WAIT DISCONNECT instructions broke everything, - * so instead I'll settle for moving one WAIT DISCONNECT a few - * instructions closer to the CLEAR ACK before it to minimize the - * chances of this happening, and handle it if it occurs anyway. - * - * Simply continue with what we were doing, and control should - * be transferred to the schedule routine which will ultimately - * pass control onto the reselection or selection (not yet) - * code. - */ - } else if (dbc_dcmd == 0x48000000 && (NCR53c7x0_read8 (SBCL_REG) & - SBCL_REQ)) { - if (!(hostdata->options & OPTION_NO_PRINT_RACE)) - { - printk("scsi%d: REQ before WAIT DISCONNECT IID\n", - host->host_no); - hostdata->options |= OPTION_NO_PRINT_RACE; - } - } else { - printk(KERN_ALERT "scsi%d : invalid instruction\n", host->host_no); - print_lots (host); - printk(KERN_ALERT " mail Richard@sleepie.demon.co.uk with ALL\n" - " boot messages and diagnostic output\n"); - FATAL (host); - } - } - - /* - * DSTAT_BF are bus fault errors. DSTAT_800_BF is valid for 710 also. - */ - - if (dstat & DSTAT_800_BF) { - intr_bf (host, cmd); - } - - - /* - * DSTAT_SIR interrupts are generated by the execution of - * the INT instruction. Since the exact values available - * are determined entirely by the SCSI script running, - * and are local to a particular script, a unique handler - * is called for each script. - */ - - if (dstat & DSTAT_SIR) { - if (hostdata->options & OPTION_DEBUG_INTR) - printk ("scsi%d : DSTAT_SIR\n", host->host_no); - switch ((tmp = hostdata->dstat_sir_intr (host, cmd))) { - case SPECIFIC_INT_NOTHING: - case SPECIFIC_INT_RESTART: - break; - case SPECIFIC_INT_ABORT: - abort_connected(host); - break; - case SPECIFIC_INT_PANIC: - printk(KERN_ALERT "scsi%d : failure at ", host->host_no); - print_insn (host, dsp, KERN_ALERT "", 1); - printk(KERN_ALERT " dstat_sir_intr() returned SPECIFIC_INT_PANIC\n"); - FATAL (host); - break; - case SPECIFIC_INT_BREAK: - intr_break (host, cmd); - break; - default: - printk(KERN_ALERT "scsi%d : failure at ", host->host_no); - print_insn (host, dsp, KERN_ALERT "", 1); - printk(KERN_ALERT" dstat_sir_intr() returned unknown value %d\n", - tmp); - FATAL (host); - } - } -} - -/* - * Function : static int print_insn (struct Scsi_Host *host, - * u32 *insn, int kernel) - * - * Purpose : print numeric representation of the instruction pointed - * to by insn to the debugging or kernel message buffer - * as appropriate. - * - * If desired, a user level program can interpret this - * information. - * - * Inputs : host, insn - host, pointer to instruction, prefix - - * string to prepend, kernel - use printk instead of debugging buffer. - * - * Returns : size, in u32s, of instruction printed. - */ - -/* - * FIXME: should change kernel parameter so that it takes an ENUM - * specifying severity - either KERN_ALERT or KERN_PANIC so - * all panic messages are output with the same severity. - */ - -static int -print_insn (struct Scsi_Host *host, const u32 *insn, - const char *prefix, int kernel) { - char buf[160], /* Temporary buffer and pointer. ICKY - arbitrary length. */ - - - *tmp; - unsigned char dcmd; /* dcmd register for *insn */ - int size; - - /* - * Check to see if the instruction pointer is not bogus before - * indirecting through it; avoiding red-zone at start of - * memory. - * - * FIXME: icky magic needs to happen here on non-intel boxes which - * don't have kernel memory mapped in like this. Might be reasonable - * to use vverify()? - */ - - if (virt_to_phys((void *)insn) < PAGE_SIZE || - virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) || - ((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) && - virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) { - size = 0; - sprintf (buf, "%s%p: address out of range\n", - prefix, insn); - } else { -/* - * FIXME : (void *) cast in virt_to_bus should be unnecessary, because - * it should take const void * as argument. - */ -#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000) - sprintf(buf, "%s0x%lx (virt 0x%p) : 0x%08x 0x%08x (virt 0x%p)", - (prefix ? prefix : ""), virt_to_bus((void *) insn), insn, - insn[0], insn[1], bus_to_virt (insn[1])); -#else - /* Remove virtual addresses to reduce output, as they are the same */ - sprintf(buf, "%s0x%x (+%x) : 0x%08x 0x%08x", - (prefix ? prefix : ""), (u32)insn, ((u32)insn - - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4, - insn[0], insn[1]); -#endif - tmp = buf + strlen(buf); - if ((dcmd & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) { -#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000) - sprintf (tmp, " 0x%08x (virt 0x%p)\n", insn[2], - bus_to_virt(insn[2])); -#else - /* Remove virtual addr to reduce output, as it is the same */ - sprintf (tmp, " 0x%08x\n", insn[2]); -#endif - size = 3; - } else { - sprintf (tmp, "\n"); - size = 2; - } - } - - if (kernel) - printk ("%s", buf); -#ifdef NCR_DEBUG - else { - size_t len = strlen(buf); - debugger_kernel_write(host, buf, len); - } -#endif - return size; -} - -/* - * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd) - * - * Purpose : Abort an errant SCSI command, doing all necessary - * cleanup of the issue_queue, running_list, shared Linux/NCR - * dsa issue and reconnect queues. - * - * Inputs : cmd - command to abort, code - entire result field - * - * Returns : 0 on success, -1 on failure. - */ - -int -NCR53c7xx_abort (Scsi_Cmnd *cmd) { - NCR53c7x0_local_declare(); - struct Scsi_Host *host = cmd->device->host; - struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) - host->hostdata[0] : NULL; - unsigned long flags; - struct NCR53c7x0_cmd *curr, **prev; - Scsi_Cmnd *me, **last; -#if 0 - static long cache_pid = -1; -#endif - - - if (!host) { - printk ("Bogus SCSI command pid %ld; no host structure\n", - cmd->pid); - return SCSI_ABORT_ERROR; - } else if (!hostdata) { - printk ("Bogus SCSI host %d; no hostdata\n", host->host_no); - return SCSI_ABORT_ERROR; - } - NCR53c7x0_local_setup(host); - -/* - * CHECK : I don't think that reading ISTAT will unstack any interrupts, - * since we need to write the INTF bit to clear it, and SCSI/DMA - * interrupts don't clear until we read SSTAT/SIST and DSTAT registers. - * - * See that this is the case. Appears to be correct on the 710, at least. - * - * I suspect that several of our failures may be coming from a new fatal - * interrupt (possibly due to a phase mismatch) happening after we've left - * the interrupt handler, but before the PIC has had the interrupt condition - * cleared. - */ - - if (NCR53c7x0_read8(hostdata->istat) & (ISTAT_DIP|ISTAT_SIP)) { - printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no, - cmd->pid); - NCR53c7x0_intr (host->irq, NULL, NULL); - return SCSI_ABORT_BUSY; - } - - local_irq_save(flags); -#if 0 - if (cache_pid == cmd->pid) - panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid); - else - cache_pid = cmd->pid; -#endif - - -/* - * The command could be hiding in the issue_queue. This would be very - * nice, as commands can't be moved from the high level driver's issue queue - * into the shared queue until an interrupt routine is serviced, and this - * moving is atomic. - * - * If this is the case, we don't have to worry about anything - we simply - * pull the command out of the old queue, and call it aborted. - */ - - for (me = (Scsi_Cmnd *) hostdata->issue_queue, - last = (Scsi_Cmnd **) &(hostdata->issue_queue); - me && me != cmd; last = (Scsi_Cmnd **)&(me->SCp.ptr), - me = (Scsi_Cmnd *)me->SCp.ptr); - - if (me) { - *last = (Scsi_Cmnd *) me->SCp.ptr; - if (me->host_scribble) { - ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free; - hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble; - me->host_scribble = NULL; - } - cmd->result = DID_ABORT << 16; - cmd->scsi_done(cmd); - printk ("scsi%d : found command %ld in Linux issue queue\n", - host->host_no, me->pid); - local_irq_restore(flags); - run_process_issue_queue(); - return SCSI_ABORT_SUCCESS; - } - -/* - * That failing, the command could be in our list of already executing - * commands. If this is the case, drastic measures are called for. - */ - - for (curr = (struct NCR53c7x0_cmd *) hostdata->running_list, - prev = (struct NCR53c7x0_cmd **) &(hostdata->running_list); - curr && curr->cmd != cmd; prev = (struct NCR53c7x0_cmd **) - &(curr->next), curr = (struct NCR53c7x0_cmd *) curr->next); - - if (curr) { - if ((curr->result & 0xff) != 0xff && (curr->result & 0xff00) != 0xff00) { - cmd->result = curr->result; - if (prev) - *prev = (struct NCR53c7x0_cmd *) curr->next; - curr->next = (struct NCR53c7x0_cmd *) hostdata->free; - cmd->host_scribble = NULL; - hostdata->free = curr; - cmd->scsi_done(cmd); - printk ("scsi%d : found finished command %ld in running list\n", - host->host_no, cmd->pid); - local_irq_restore(flags); - return SCSI_ABORT_NOT_RUNNING; - } else { - printk ("scsi%d : DANGER : command running, can not abort.\n", - cmd->device->host->host_no); - local_irq_restore(flags); - return SCSI_ABORT_BUSY; - } - } - -/* - * And if we couldn't find it in any of our queues, it must have been - * a dropped interrupt. - */ - - curr = (struct NCR53c7x0_cmd *) cmd->host_scribble; - if (curr) { - curr->next = hostdata->free; - hostdata->free = curr; - cmd->host_scribble = NULL; - } - - if (curr == NULL || ((curr->result & 0xff00) == 0xff00) || - ((curr->result & 0xff) == 0xff)) { - printk ("scsi%d : did this command ever run?\n", host->host_no); - cmd->result = DID_ABORT << 16; - } else { - printk ("scsi%d : probably lost INTFLY, normal completion\n", - host->host_no); - cmd->result = curr->result; -/* - * FIXME : We need to add an additional flag which indicates if a - * command was ever counted as BUSY, so if we end up here we can - * decrement the busy count if and only if it is necessary. - */ - --hostdata->busy[cmd->device->id][cmd->device->lun]; - } - local_irq_restore(flags); - cmd->scsi_done(cmd); - -/* - * We need to run process_issue_queue since termination of this command - * may allow another queued command to execute first? - */ - return SCSI_ABORT_NOT_RUNNING; -} - -/* - * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd) - * - * Purpose : perform a hard reset of the SCSI bus and NCR - * chip. - * - * Inputs : cmd - command which caused the SCSI RESET - * - * Returns : 0 on success. - */ - -int -NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) { - NCR53c7x0_local_declare(); - unsigned long flags; - int found = 0; - struct NCR53c7x0_cmd * c; - Scsi_Cmnd *tmp; - /* - * When we call scsi_done(), it's going to wake up anything sleeping on the - * resources which were in use by the aborted commands, and we'll start to - * get new commands. - * - * We can't let this happen until after we've re-initialized the driver - * structures, and can't reinitialize those structures until after we've - * dealt with their contents. - * - * So, we need to find all of the commands which were running, stick - * them on a linked list of completed commands (we'll use the host_scribble - * pointer), do our reinitialization, and then call the done function for - * each command. - */ - Scsi_Cmnd *nuke_list = NULL; - struct Scsi_Host *host = cmd->device->host; - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata[0]; - - NCR53c7x0_local_setup(host); - local_irq_save(flags); - ncr_halt (host); - print_lots (host); - dump_events (host, 30); - ncr_scsi_reset (host); - for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */, - 0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer) - if (tmp == cmd) { - found = 1; - break; - } - - /* - * If we didn't find the command which caused this reset in our running - * list, then we've lost it. See that it terminates normally anyway. - */ - if (!found) { - c = (struct NCR53c7x0_cmd *) cmd->host_scribble; - if (c) { - cmd->host_scribble = NULL; - c->next = hostdata->free; - hostdata->free = c; - } else - printk ("scsi%d: lost command %ld\n", host->host_no, cmd->pid); - cmd->SCp.buffer = (struct scatterlist *) nuke_list; - nuke_list = cmd; - } - - NCR53c7x0_driver_init (host); - hostdata->soft_reset (host); - if (hostdata->resets == 0) - disable(host); - else if (hostdata->resets != -1) - --hostdata->resets; - local_irq_restore(flags); - for (; nuke_list; nuke_list = tmp) { - tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer; - nuke_list->result = DID_RESET << 16; - nuke_list->scsi_done (nuke_list); - } - local_irq_restore(flags); - return SCSI_RESET_SUCCESS; -} - -/* - * The NCR SDMS bios follows Annex A of the SCSI-CAM draft, and - * therefore shares the scsicam_bios_param function. - */ - -/* - * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) - * - * Purpose : convert instructions stored at NCR pointer into data - * pointer offset. - * - * Inputs : cmd - SCSI command; insn - pointer to instruction. Either current - * DSP, or saved data pointer. - * - * Returns : offset on success, -1 on failure. - */ - - -static int -insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) { - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0]; - struct NCR53c7x0_cmd *ncmd = - (struct NCR53c7x0_cmd *) cmd->host_scribble; - int offset = 0, buffers; - struct scatterlist *segment; - char *ptr; - int found = 0; - -/* - * With the current code implementation, if the insn is inside dynamically - * generated code, the data pointer will be the instruction preceding - * the next transfer segment. - */ - - if (!check_address ((unsigned long) ncmd, sizeof (struct NCR53c7x0_cmd)) && - ((insn >= ncmd->data_transfer_start && - insn < ncmd->data_transfer_end) || - (insn >= ncmd->residual && - insn < (ncmd->residual + - sizeof(ncmd->residual))))) { - ptr = bus_to_virt(insn[3]); - - if ((buffers = cmd->use_sg)) { - for (offset = 0, - segment = (struct scatterlist *) cmd->request_buffer; - buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) && - (ptr < ((char *)page_address(segment->page)+segment->offset+segment->length))))); - --buffers, offset += segment->length, ++segment) -#if 0 - printk("scsi%d: comparing 0x%p to 0x%p\n", - cmd->device->host->host_no, saved, page_address(segment->page+segment->offset)); -#else - ; -#endif - offset += ptr - ((char *)page_address(segment->page)+segment->offset); - } else { - found = 1; - offset = ptr - (char *) (cmd->request_buffer); - } - } else if ((insn >= hostdata->script + - hostdata->E_data_transfer / sizeof(u32)) && - (insn <= hostdata->script + - hostdata->E_end_data_transfer / sizeof(u32))) { - found = 1; - offset = 0; - } - return found ? offset : -1; -} - - - -/* - * Function : void print_progress (Scsi_Cmnd *cmd) - * - * Purpose : print the current location of the saved data pointer - * - * Inputs : cmd - command we are interested in - * - */ - -static void -print_progress (Scsi_Cmnd *cmd) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_cmd *ncmd = - (struct NCR53c7x0_cmd *) cmd->host_scribble; - int offset, i; - char *where; - u32 *ptr; - NCR53c7x0_local_setup (cmd->device->host); - - if (check_address ((unsigned long) ncmd,sizeof (struct NCR53c7x0_cmd)) == 0) - { - printk("\nNCR53c7x0_cmd fields:\n"); - printk(" bounce.len=0x%x, addr=0x%0x, buf[]=0x%02x %02x %02x %02x\n", - ncmd->bounce.len, ncmd->bounce.addr, ncmd->bounce.buf[0], - ncmd->bounce.buf[1], ncmd->bounce.buf[2], ncmd->bounce.buf[3]); - printk(" result=%04x, cdb[0]=0x%02x\n", ncmd->result, ncmd->cmnd[0]); - } - - for (i = 0; i < 2; ++i) { - if (check_address ((unsigned long) ncmd, - sizeof (struct NCR53c7x0_cmd)) == -1) - continue; - if (!i) { - where = "saved"; - ptr = bus_to_virt(ncmd->saved_data_pointer); - } else { - where = "active"; - ptr = bus_to_virt (NCR53c7x0_read32 (DSP_REG) - - NCR53c7x0_insn_size (NCR53c7x0_read8 (DCMD_REG)) * - sizeof(u32)); - } - offset = insn_to_offset (cmd, ptr); - - if (offset != -1) - printk ("scsi%d : %s data pointer at offset %d\n", - cmd->device->host->host_no, where, offset); - else { - int size; - printk ("scsi%d : can't determine %s data pointer offset\n", - cmd->device->host->host_no, where); - if (ncmd) { - size = print_insn (cmd->device->host, - bus_to_virt(ncmd->saved_data_pointer), "", 1); - print_insn (cmd->device->host, - bus_to_virt(ncmd->saved_data_pointer) + size * sizeof(u32), - "", 1); - } - } - } -} - - -static void -print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - int i, len; - char *ptr; - Scsi_Cmnd *cmd; - - if (check_address ((unsigned long) dsa, hostdata->dsa_end - - hostdata->dsa_start) == -1) { - printk("scsi%d : bad dsa virt 0x%p\n", host->host_no, dsa); - return; - } - printk("%sscsi%d : dsa at phys 0x%lx (virt 0x%p)\n" - " + %d : dsa_msgout length = %u, data = 0x%x (virt 0x%p)\n" , - prefix ? prefix : "", - host->host_no, virt_to_bus (dsa), dsa, hostdata->dsa_msgout, - dsa[hostdata->dsa_msgout / sizeof(u32)], - dsa[hostdata->dsa_msgout / sizeof(u32) + 1], - bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1])); - - /* - * Only print messages if they're sane in length so we don't - * blow the kernel printk buffer on something which won't buy us - * anything. - */ - - if (dsa[hostdata->dsa_msgout / sizeof(u32)] < - sizeof (hostdata->free->select)) - for (i = dsa[hostdata->dsa_msgout / sizeof(u32)], - ptr = bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]); - i > 0 && !check_address ((unsigned long) ptr, 1); - ptr += len, i -= len) { - printk(" "); - len = spi_print_msg(ptr); - printk("\n"); - if (!len) - break; - } - - printk(" + %d : select_indirect = 0x%x\n", - hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]); - cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]); - printk(" + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd, - (u32) virt_to_bus(cmd)); - /* XXX Maybe we should access cmd->host_scribble->result here. RGH */ - if (cmd) { - printk(" result = 0x%x, target = %d, lun = %d, cmd = ", - cmd->result, cmd->device->id, cmd->device->lun); - __scsi_print_command(cmd->cmnd); - } else - printk("\n"); - printk(" + %d : dsa_next = 0x%x\n", hostdata->dsa_next, - dsa[hostdata->dsa_next / sizeof(u32)]); - if (cmd) { - printk("scsi%d target %d : sxfer_sanity = 0x%x, scntl3_sanity = 0x%x\n" - " script : ", - host->host_no, cmd->device->id, - hostdata->sync[cmd->device->id].sxfer_sanity, - hostdata->sync[cmd->device->id].scntl3_sanity); - for (i = 0; i < (sizeof(hostdata->sync[cmd->device->id].script) / 4); ++i) - printk ("0x%x ", hostdata->sync[cmd->device->id].script[i]); - printk ("\n"); - print_progress (cmd); - } -} -/* - * Function : void print_queues (Scsi_Host *host) - * - * Purpose : print the contents of the NCR issue and reconnect queues - * - * Inputs : host - SCSI host we are interested in - * - */ - -static void -print_queues (struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - u32 *dsa, *next_dsa; - volatile u32 *ncrcurrent; - int left; - Scsi_Cmnd *cmd, *next_cmd; - unsigned long flags; - - printk ("scsi%d : issue queue\n", host->host_no); - - for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue; - left >= 0 && cmd; - cmd = next_cmd) { - next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr; - local_irq_save(flags); - if (cmd->host_scribble) { - if (check_address ((unsigned long) (cmd->host_scribble), - sizeof (cmd->host_scribble)) == -1) - printk ("scsi%d: scsi pid %ld bad pointer to NCR53c7x0_cmd\n", - host->host_no, cmd->pid); - /* print_dsa does sanity check on address, no need to check */ - else - print_dsa (host, ((struct NCR53c7x0_cmd *) cmd->host_scribble) - -> dsa, ""); - } else - printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n", - host->host_no, cmd->pid, cmd->device->id, cmd->device->lun); - local_irq_restore(flags); - } - - if (left <= 0) { - printk ("scsi%d : loop detected in issue queue\n", - host->host_no); - } - - /* - * Traverse the NCR reconnect and start DSA structures, printing out - * each element until we hit the end or detect a loop. Currently, - * the reconnect structure is a linked list; and the start structure - * is an array. Eventually, the reconnect structure will become a - * list as well, since this simplifies the code. - */ - - printk ("scsi%d : schedule dsa array :\n", host->host_no); - for (left = host->can_queue, ncrcurrent = hostdata->schedule; - left > 0; ncrcurrent += 2, --left) - if (ncrcurrent[0] != hostdata->NOP_insn) -/* FIXME : convert pointer to dsa_begin to pointer to dsa. */ - print_dsa (host, bus_to_virt (ncrcurrent[1] - - (hostdata->E_dsa_code_begin - - hostdata->E_dsa_code_template)), ""); - printk ("scsi%d : end schedule dsa array\n", host->host_no); - - printk ("scsi%d : reconnect_dsa_head :\n", host->host_no); - - for (left = host->can_queue, - dsa = bus_to_virt (hostdata->reconnect_dsa_head); - left >= 0 && dsa; - dsa = next_dsa) { - local_irq_save(flags); - if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) { - printk ("scsi%d: bad DSA pointer 0x%p", host->host_no, - dsa); - next_dsa = NULL; - } - else - { - next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]); - print_dsa (host, dsa, ""); - } - local_irq_restore(flags); - } - printk ("scsi%d : end reconnect_dsa_head\n", host->host_no); - if (left < 0) - printk("scsi%d: possible loop in ncr reconnect list\n", - host->host_no); -} - -static void -print_lots (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata[0]; - u32 *dsp_next, *dsp, *dsa, dbc_dcmd; - unsigned char dcmd, sbcl; - int i, size; - NCR53c7x0_local_setup(host); - - if ((dsp_next = bus_to_virt(NCR53c7x0_read32 (DSP_REG)))) { - dbc_dcmd = NCR53c7x0_read32(DBC_REG); - dcmd = (dbc_dcmd & 0xff000000) >> 24; - dsp = dsp_next - NCR53c7x0_insn_size(dcmd); - dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); - sbcl = NCR53c7x0_read8 (SBCL_REG); - - /* - * For the 53c710, the following will report value 0 for SCNTL3 - * and STEST0 - we don't have these registers. - */ - printk ("scsi%d : DCMD|DBC=0x%x, DNAD=0x%x (virt 0x%p)\n" - " DSA=0x%lx (virt 0x%p)\n" - " DSPS=0x%x, TEMP=0x%x (virt 0x%p), DMODE=0x%x\n" - " SXFER=0x%x, SCNTL3=0x%x\n" - " %s%s%sphase=%s, %d bytes in SCSI FIFO\n" - " SCRATCH=0x%x, saved2_dsa=0x%0lx\n", - host->host_no, dbc_dcmd, NCR53c7x0_read32(DNAD_REG), - bus_to_virt(NCR53c7x0_read32(DNAD_REG)), - virt_to_bus(dsa), dsa, - NCR53c7x0_read32(DSPS_REG), NCR53c7x0_read32(TEMP_REG), - bus_to_virt (NCR53c7x0_read32(TEMP_REG)), - (int) NCR53c7x0_read8(hostdata->dmode), - (int) NCR53c7x0_read8(SXFER_REG), - ((hostdata->chip / 100) == 8) ? - (int) NCR53c7x0_read8(SCNTL3_REG_800) : 0, - (sbcl & SBCL_BSY) ? "BSY " : "", - (sbcl & SBCL_SEL) ? "SEL " : "", - (sbcl & SBCL_REQ) ? "REQ " : "", - sstat2_to_phase(NCR53c7x0_read8 (((hostdata->chip / 100) == 8) ? - SSTAT1_REG : SSTAT2_REG)), - (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? - SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT, - ((hostdata->chip / 100) == 8) ? NCR53c7x0_read8 (STEST0_REG_800) : - NCR53c7x0_read32(SCRATCHA_REG_800), - hostdata->saved2_dsa); - printk ("scsi%d : DSP 0x%lx (virt 0x%p) ->\n", host->host_no, - virt_to_bus(dsp), dsp); - for (i = 6; i > 0; --i, dsp += size) - size = print_insn (host, dsp, "", 1); - if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) { - if ((hostdata->chip / 100) == 8) - printk ("scsi%d : connected (SDID=0x%x, SSID=0x%x)\n", - host->host_no, NCR53c7x0_read8 (SDID_REG_800), - NCR53c7x0_read8 (SSID_REG_800)); - else - printk ("scsi%d : connected (SDID=0x%x)\n", - host->host_no, NCR53c7x0_read8 (SDID_REG_700)); - print_dsa (host, dsa, ""); - } - -#if 1 - print_queues (host); -#endif - } -} - -/* - * Function : static int shutdown (struct Scsi_Host *host) - * - * Purpose : does a clean (we hope) shutdown of the NCR SCSI - * chip. Use prior to dumping core, unloading the NCR driver, - * - * Returns : 0 on success - */ -static int -shutdown (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - unsigned long flags; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - NCR53c7x0_local_setup(host); - local_irq_save(flags); -/* Get in a state where we can reset the SCSI bus */ - ncr_halt (host); - ncr_scsi_reset (host); - hostdata->soft_reset(host); - - disable (host); - local_irq_restore(flags); - return 0; -} - -/* - * Function : void ncr_scsi_reset (struct Scsi_Host *host) - * - * Purpose : reset the SCSI bus. - */ - -static void -ncr_scsi_reset (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - unsigned long flags; - NCR53c7x0_local_setup(host); - local_irq_save(flags); - NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST); - udelay(25); /* Minimum amount of time to assert RST */ - NCR53c7x0_write8(SCNTL1_REG, 0); - local_irq_restore(flags); -} - -/* - * Function : void hard_reset (struct Scsi_Host *host) - * - */ - -static void -hard_reset (struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - unsigned long flags; - local_irq_save(flags); - ncr_scsi_reset(host); - NCR53c7x0_driver_init (host); - if (hostdata->soft_reset) - hostdata->soft_reset (host); - local_irq_restore(flags); -} - - -/* - * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host, - * int free, int issue) - * - * Purpose : return a linked list (using the SCp.buffer field as next, - * so we don't perturb hostdata. We don't use a field of the - * NCR53c7x0_cmd structure since we may not have allocated one - * for the command causing the reset.) of Scsi_Cmnd structures that - * had propagated below the Linux issue queue level. If free is set, - * free the NCR53c7x0_cmd structures which are associated with - * the Scsi_Cmnd structures, and clean up any internal - * NCR lists that the commands were on. If issue is set, - * also return commands in the issue queue. - * - * Returns : linked list of commands - * - * NOTE : the caller should insure that the NCR chip is halted - * if the free flag is set. - */ - -static Scsi_Cmnd * -return_outstanding_commands (struct Scsi_Host *host, int free, int issue) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - struct NCR53c7x0_cmd *c; - int i; - u32 *ncrcurrent; - Scsi_Cmnd *list = NULL, *tmp; - for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c; - c = (struct NCR53c7x0_cmd *) c->next) { - if (c->cmd->SCp.buffer) { - printk ("scsi%d : loop detected in running list!\n", host->host_no); - break; - } else { - printk ("Duh? Bad things happening in the NCR driver\n"); - break; - } - - c->cmd->SCp.buffer = (struct scatterlist *) list; - list = c->cmd; - if (free) { - c->next = hostdata->free; - hostdata->free = c; - } - } - - if (free) { - for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; - i < host->can_queue; ++i, ncrcurrent += 2) { - ncrcurrent[0] = hostdata->NOP_insn; - ncrcurrent[1] = 0xdeadbeef; - } - hostdata->ncrcurrent = NULL; - } - - if (issue) { - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) { - if (tmp->SCp.buffer) { - printk ("scsi%d : loop detected in issue queue!\n", - host->host_no); - break; - } - tmp->SCp.buffer = (struct scatterlist *) list; - list = tmp; - } - if (free) - hostdata->issue_queue = NULL; - - } - return list; -} - -/* - * Function : static int disable (struct Scsi_Host *host) - * - * Purpose : disables the given NCR host, causing all commands - * to return a driver error. Call this so we can unload the - * module during development and try again. Eventually, - * we should be able to find clean workarounds for these - * problems. - * - * Inputs : host - hostadapter to twiddle - * - * Returns : 0 on success. - */ - -static int -disable (struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - unsigned long flags; - Scsi_Cmnd *nuke_list, *tmp; - local_irq_save(flags); - if (hostdata->state != STATE_HALTED) - ncr_halt (host); - nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */); - hard_reset (host); - hostdata->state = STATE_DISABLED; - local_irq_restore(flags); - printk ("scsi%d : nuking commands\n", host->host_no); - for (; nuke_list; nuke_list = tmp) { - tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer; - nuke_list->result = DID_ERROR << 16; - nuke_list->scsi_done(nuke_list); - } - printk ("scsi%d : done. \n", host->host_no); - printk (KERN_ALERT "scsi%d : disabled. Unload and reload\n", - host->host_no); - return 0; -} - -/* - * Function : static int ncr_halt (struct Scsi_Host *host) - * - * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip - * - * Inputs : host - SCSI chip to halt - * - * Returns : 0 on success - */ - -static int -ncr_halt (struct Scsi_Host *host) { - NCR53c7x0_local_declare(); - unsigned long flags; - unsigned char istat, tmp; - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - int stage; - NCR53c7x0_local_setup(host); - - local_irq_save(flags); - /* Stage 0 : eat all interrupts - Stage 1 : set ABORT - Stage 2 : eat all but abort interrupts - Stage 3 : eat all interrupts - */ - for (stage = 0;;) { - if (stage == 1) { - NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT); - ++stage; - } - istat = NCR53c7x0_read8 (hostdata->istat); - if (istat & ISTAT_SIP) { - tmp = NCR53c7x0_read8(SSTAT0_REG); - } else if (istat & ISTAT_DIP) { - tmp = NCR53c7x0_read8(DSTAT_REG); - if (stage == 2) { - if (tmp & DSTAT_ABRT) { - NCR53c7x0_write8(hostdata->istat, 0); - ++stage; - } else { - printk(KERN_ALERT "scsi%d : could not halt NCR chip\n", - host->host_no); - disable (host); - } - } - } - if (!(istat & (ISTAT_SIP|ISTAT_DIP))) { - if (stage == 0) - ++stage; - else if (stage == 3) - break; - } - } - hostdata->state = STATE_HALTED; - local_irq_restore(flags); -#if 0 - print_lots (host); -#endif - return 0; -} - -/* - * Function: event_name (int event) - * - * Purpose: map event enum into user-readable strings. - */ - -static const char * -event_name (int event) { - switch (event) { - case EVENT_NONE: return "none"; - case EVENT_ISSUE_QUEUE: return "to issue queue"; - case EVENT_START_QUEUE: return "to start queue"; - case EVENT_SELECT: return "selected"; - case EVENT_DISCONNECT: return "disconnected"; - case EVENT_RESELECT: return "reselected"; - case EVENT_COMPLETE: return "completed"; - case EVENT_IDLE: return "idle"; - case EVENT_SELECT_FAILED: return "select failed"; - case EVENT_BEFORE_SELECT: return "before select"; - case EVENT_RESELECT_FAILED: return "reselect failed"; - default: return "unknown"; - } -} - -/* - * Function : void dump_events (struct Scsi_Host *host, count) - * - * Purpose : print last count events which have occurred. - */ -static void -dump_events (struct Scsi_Host *host, int count) { - struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) - host->hostdata[0]; - struct NCR53c7x0_event event; - int i; - unsigned long flags; - if (hostdata->events) { - if (count > hostdata->event_size) - count = hostdata->event_size; - for (i = hostdata->event_index; count > 0; - i = (i ? i - 1 : hostdata->event_size -1), --count) { -/* - * By copying the event we're currently examining with interrupts - * disabled, we can do multiple printk(), etc. operations and - * still be guaranteed that they're happening on the same - * event structure. - */ - local_irq_save(flags); -#if 0 - event = hostdata->events[i]; -#else - memcpy ((void *) &event, (void *) &(hostdata->events[i]), - sizeof(event)); -#endif - - local_irq_restore(flags); - printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n", - host->host_no, event_name (event.event), count, - (long) event.time.tv_sec, (long) event.time.tv_usec, - event.target, event.lun); - if (event.dsa) - printk (" event for dsa 0x%lx (virt 0x%p)\n", - virt_to_bus(event.dsa), event.dsa); - if (event.pid != -1) { - printk (" event for pid %ld ", event.pid); - __scsi_print_command (event.cmnd); - } - } - } -} - -/* - * Function: check_address - * - * Purpose: Check to see if a possibly corrupt pointer will fault the - * kernel. - * - * Inputs: addr - address; size - size of area - * - * Returns: 0 if area is OK, -1 on error. - * - * NOTES: should be implemented in terms of vverify on kernels - * that have it. - */ - -static int -check_address (unsigned long addr, int size) { - return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ? -1 : 0); -} - -#ifdef MODULE -int -NCR53c7x0_release(struct Scsi_Host *host) { - struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) host->hostdata[0]; - struct NCR53c7x0_cmd *cmd, *tmp; - shutdown (host); - if (host->irq != SCSI_IRQ_NONE) - { - int irq_count; - struct Scsi_Host *tmp; - for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next) - if (tmp->hostt == the_template && tmp->irq == host->irq) - ++irq_count; - if (irq_count == 1) - free_irq(host->irq, NULL); - } - if (host->dma_channel != DMA_NONE) - free_dma(host->dma_channel); - if (host->io_port) - release_region(host->io_port, host->n_io_port); - - for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp, - --hostdata->num_cmds) { - tmp = (struct NCR53c7x0_cmd *) cmd->next; - /* - * If we're going to loop, try to stop it to get a more accurate - * count of the leaked commands. - */ - cmd->next = NULL; - if (cmd->free) - cmd->free ((void *) cmd->real, cmd->size); - } - if (hostdata->num_cmds) - printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n", - host->host_no, hostdata->num_cmds); - - vfree(hostdata->events); - - /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which - * XXX may be invalid (CONFIG_060_WRITETHROUGH) - */ - kernel_set_cachemode((void *)hostdata, 8192, IOMAP_FULL_CACHING); - free_pages ((u32)hostdata, 1); - return 1; -} -#endif /* def MODULE */ diff --git a/drivers/scsi/53c7xx.h b/drivers/scsi/53c7xx.h deleted file mode 100644 index 218f3b901537..000000000000 --- a/drivers/scsi/53c7xx.h +++ /dev/null @@ -1,1608 +0,0 @@ -/* - * 53c710 driver. Modified from Drew Eckhardts driver - * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk] - * - * I have left the code for the 53c8xx family in here, because it didn't - * seem worth removing it. The possibility of IO_MAPPED chips rather - * than MEMORY_MAPPED remains, in case someone wants to add support for - * 53c710 chips on Intel PCs (some older machines have them on the - * motherboard). - * - * NOTE THERE MAY BE PROBLEMS WITH CASTS IN read8 AND Co. - */ - -/* - * NCR 53c{7,8}0x0 driver, header file - * - * Sponsored by - * iX Multiuser Multitasking Magazine - * Hannover, Germany - * hm@ix.de - * - * Copyright 1993, 1994, 1995 Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@PoohSticks.ORG - * +1 (303) 786-7975 - * - * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. - * - * PRE-ALPHA - * - * For more information, please consult - * - * NCR 53C700/53C700-66 - * SCSI I/O Processor - * Data Manual - * - * NCR 53C810 - * PCI-SCSI I/O Processor - * Data Manual - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * +1 (719) 578-3400 - * - * Toll free literature number - * +1 (800) 334-5454 - * - */ - -#ifndef NCR53c710_H -#define NCR53c710_H - -#ifndef HOSTS_C - -/* SCSI control 0 rw, default = 0xc0 */ -#define SCNTL0_REG 0x00 -#define SCNTL0_ARB1 0x80 /* 0 0 = simple arbitration */ -#define SCNTL0_ARB2 0x40 /* 1 1 = full arbitration */ -#define SCNTL0_STRT 0x20 /* Start Sequence */ -#define SCNTL0_WATN 0x10 /* Select with ATN */ -#define SCNTL0_EPC 0x08 /* Enable parity checking */ -/* Bit 2 is reserved on 800 series chips */ -#define SCNTL0_EPG_700 0x04 /* Enable parity generation */ -#define SCNTL0_AAP 0x02 /* ATN/ on parity error */ -#define SCNTL0_TRG 0x01 /* Target mode */ - -/* SCSI control 1 rw, default = 0x00 */ - -#define SCNTL1_REG 0x01 -#define SCNTL1_EXC 0x80 /* Extra Clock Cycle of Data setup */ -#define SCNTL1_ADB 0x40 /* contents of SODL on bus */ -#define SCNTL1_ESR_700 0x20 /* Enable SIOP response to selection - and reselection */ -#define SCNTL1_DHP_800 0x20 /* Disable halt on parity error or ATN - target mode only */ -#define SCNTL1_CON 0x10 /* Connected */ -#define SCNTL1_RST 0x08 /* SCSI RST/ */ -#define SCNTL1_AESP 0x04 /* Force bad parity */ -#define SCNTL1_SND_700 0x02 /* Start SCSI send */ -#define SCNTL1_IARB_800 0x02 /* Immediate Arbitration, start - arbitration immediately after - busfree is detected */ -#define SCNTL1_RCV_700 0x01 /* Start SCSI receive */ -#define SCNTL1_SST_800 0x01 /* Start SCSI transfer */ - -/* SCSI control 2 rw, */ - -#define SCNTL2_REG_800 0x02 -#define SCNTL2_800_SDU 0x80 /* SCSI disconnect unexpected */ - -/* SCSI control 3 rw */ - -#define SCNTL3_REG_800 0x03 -#define SCNTL3_800_SCF_SHIFT 4 -#define SCNTL3_800_SCF_MASK 0x70 -#define SCNTL3_800_SCF2 0x40 /* Synchronous divisor */ -#define SCNTL3_800_SCF1 0x20 /* 0x00 = SCLK/3 */ -#define SCNTL3_800_SCF0 0x10 /* 0x10 = SCLK/1 */ - /* 0x20 = SCLK/1.5 - 0x30 = SCLK/2 - 0x40 = SCLK/3 */ - -#define SCNTL3_800_CCF_SHIFT 0 -#define SCNTL3_800_CCF_MASK 0x07 -#define SCNTL3_800_CCF2 0x04 /* 0x00 50.01 to 66 */ -#define SCNTL3_800_CCF1 0x02 /* 0x01 16.67 to 25 */ -#define SCNTL3_800_CCF0 0x01 /* 0x02 25.01 - 37.5 - 0x03 37.51 - 50 - 0x04 50.01 - 66 */ - -/* - * SCSI destination ID rw - the appropriate bit is set for the selected - * target ID. This is written by the SCSI SCRIPTS processor. - * default = 0x00 - */ -#define SDID_REG_700 0x02 -#define SDID_REG_800 0x06 - -#define GP_REG_800 0x07 /* General purpose IO */ -#define GP_800_IO1 0x02 -#define GP_800_IO2 0x01 - -/* SCSI interrupt enable rw, default = 0x00 */ -#define SIEN_REG_700 0x03 -#define SIEN0_REG_800 0x40 -#define SIEN_MA 0x80 /* Phase mismatch (ini) or ATN (tgt) */ -#define SIEN_FC 0x40 /* Function complete */ -#define SIEN_700_STO 0x20 /* Selection or reselection timeout */ -#define SIEN_800_SEL 0x20 /* Selected */ -#define SIEN_700_SEL 0x10 /* Selected or reselected */ -#define SIEN_800_RESEL 0x10 /* Reselected */ -#define SIEN_SGE 0x08 /* SCSI gross error */ -#define SIEN_UDC 0x04 /* Unexpected disconnect */ -#define SIEN_RST 0x02 /* SCSI RST/ received */ -#define SIEN_PAR 0x01 /* Parity error */ - -/* - * SCSI chip ID rw - * NCR53c700 : - * When arbitrating, the highest bit is used, when reselection or selection - * occurs, the chip responds to all IDs for which a bit is set. - * default = 0x00 - * NCR53c810 : - * Uses bit mapping - */ -#define SCID_REG 0x04 -/* Bit 7 is reserved on 800 series chips */ -#define SCID_800_RRE 0x40 /* Enable response to reselection */ -#define SCID_800_SRE 0x20 /* Enable response to selection */ -/* Bits four and three are reserved on 800 series chips */ -#define SCID_800_ENC_MASK 0x07 /* Encoded SCSI ID */ - -/* SCSI transfer rw, default = 0x00 */ -#define SXFER_REG 0x05 -#define SXFER_DHP 0x80 /* Disable halt on parity */ - -#define SXFER_TP2 0x40 /* Transfer period msb */ -#define SXFER_TP1 0x20 -#define SXFER_TP0 0x10 /* lsb */ -#define SXFER_TP_MASK 0x70 -/* FIXME : SXFER_TP_SHIFT == 5 is right for '8xx chips */ -#define SXFER_TP_SHIFT 5 -#define SXFER_TP_4 0x00 /* Divisors */ -#define SXFER_TP_5 0x10<<1 -#define SXFER_TP_6 0x20<<1 -#define SXFER_TP_7 0x30<<1 -#define SXFER_TP_8 0x40<<1 -#define SXFER_TP_9 0x50<<1 -#define SXFER_TP_10 0x60<<1 -#define SXFER_TP_11 0x70<<1 - -#define SXFER_MO3 0x08 /* Max offset msb */ -#define SXFER_MO2 0x04 -#define SXFER_MO1 0x02 -#define SXFER_MO0 0x01 /* lsb */ -#define SXFER_MO_MASK 0x0f -#define SXFER_MO_SHIFT 0 - -/* - * SCSI output data latch rw - * The contents of this register are driven onto the SCSI bus when - * the Assert Data Bus bit of the SCNTL1 register is set and - * the CD, IO, and MSG bits of the SOCL register match the SCSI phase - */ -#define SODL_REG_700 0x06 -#define SODL_REG_800 0x54 - - -/* - * SCSI output control latch rw, default = 0 - * Note that when the chip is being manually programmed as an initiator, - * the MSG, CD, and IO bits must be set correctly for the phase the target - * is driving the bus in. Otherwise no data transfer will occur due to - * phase mismatch. - */ - -#define SOCL_REG 0x07 -#define SOCL_REQ 0x80 /* REQ */ -#define SOCL_ACK 0x40 /* ACK */ -#define SOCL_BSY 0x20 /* BSY */ -#define SOCL_SEL 0x10 /* SEL */ -#define SOCL_ATN 0x08 /* ATN */ -#define SOCL_MSG 0x04 /* MSG */ -#define SOCL_CD 0x02 /* C/D */ -#define SOCL_IO 0x01 /* I/O */ - -/* - * SCSI first byte received latch ro - * This register contains the first byte received during a block MOVE - * SCSI SCRIPTS instruction, including - * - * Initiator mode Target mode - * Message in Command - * Status Message out - * Data in Data out - * - * It also contains the selecting or reselecting device's ID and our - * ID. - * - * Note that this is the register the various IF conditionals can - * operate on. - */ -#define SFBR_REG 0x08 - -/* - * SCSI input data latch ro - * In initiator mode, data is latched into this register on the rising - * edge of REQ/. In target mode, data is latched on the rising edge of - * ACK/ - */ -#define SIDL_REG_700 0x09 -#define SIDL_REG_800 0x50 - -/* - * SCSI bus data lines ro - * This register reflects the instantaneous status of the SCSI data - * lines. Note that SCNTL0 must be set to disable parity checking, - * otherwise reading this register will latch new parity. - */ -#define SBDL_REG_700 0x0a -#define SBDL_REG_800 0x58 - -#define SSID_REG_800 0x0a -#define SSID_800_VAL 0x80 /* Exactly two bits asserted at sel */ -#define SSID_800_ENCID_MASK 0x07 /* Device which performed operation */ - - -/* - * SCSI bus control lines rw, - * instantaneous readout of control lines - */ -#define SBCL_REG 0x0b -#define SBCL_REQ 0x80 /* REQ ro */ -#define SBCL_ACK 0x40 /* ACK ro */ -#define SBCL_BSY 0x20 /* BSY ro */ -#define SBCL_SEL 0x10 /* SEL ro */ -#define SBCL_ATN 0x08 /* ATN ro */ -#define SBCL_MSG 0x04 /* MSG ro */ -#define SBCL_CD 0x02 /* C/D ro */ -#define SBCL_IO 0x01 /* I/O ro */ -#define SBCL_PHASE_CMDOUT SBCL_CD -#define SBCL_PHASE_DATAIN SBCL_IO -#define SBCL_PHASE_DATAOUT 0 -#define SBCL_PHASE_MSGIN (SBCL_CD|SBCL_IO|SBCL_MSG) -#define SBCL_PHASE_MSGOUT (SBCL_CD|SBCL_MSG) -#define SBCL_PHASE_STATIN (SBCL_CD|SBCL_IO) -#define SBCL_PHASE_MASK (SBCL_CD|SBCL_IO|SBCL_MSG) -/* - * Synchronous SCSI Clock Control bits - * 0 - set by DCNTL - * 1 - SCLK / 1.0 - * 2 - SCLK / 1.5 - * 3 - SCLK / 2.0 - */ -#define SBCL_SSCF1 0x02 /* wo, -66 only */ -#define SBCL_SSCF0 0x01 /* wo, -66 only */ -#define SBCL_SSCF_MASK 0x03 - -/* - * XXX note : when reading the DSTAT and STAT registers to clear interrupts, - * insure that 10 clocks elapse between the two - */ -/* DMA status ro */ -#define DSTAT_REG 0x0c -#define DSTAT_DFE 0x80 /* DMA FIFO empty */ -#define DSTAT_800_MDPE 0x40 /* Master Data Parity Error */ -#define DSTAT_800_BF 0x20 /* Bus Fault */ -#define DSTAT_ABRT 0x10 /* Aborted - set on error */ -#define DSTAT_SSI 0x08 /* SCRIPTS single step interrupt */ -#define DSTAT_SIR 0x04 /* SCRIPTS interrupt received - - set when INT instruction is - executed */ -#define DSTAT_WTD 0x02 /* Watchdog timeout detected */ -#define DSTAT_OPC 0x01 /* Illegal instruction */ -#define DSTAT_800_IID 0x01 /* Same thing, different name */ - - -/* NCR53c800 moves this stuff into SIST0 */ -#define SSTAT0_REG 0x0d /* SCSI status 0 ro */ -#define SIST0_REG_800 0x42 -#define SSTAT0_MA 0x80 /* ini : phase mismatch, - * tgt : ATN/ asserted - */ -#define SSTAT0_CMP 0x40 /* function complete */ -#define SSTAT0_700_STO 0x20 /* Selection or reselection timeout */ -#define SIST0_800_SEL 0x20 /* Selected */ -#define SSTAT0_700_SEL 0x10 /* Selected or reselected */ -#define SIST0_800_RSL 0x10 /* Reselected */ -#define SSTAT0_SGE 0x08 /* SCSI gross error */ -#define SSTAT0_UDC 0x04 /* Unexpected disconnect */ -#define SSTAT0_RST 0x02 /* SCSI RST/ received */ -#define SSTAT0_PAR 0x01 /* Parity error */ - -/* And uses SSTAT0 for what was SSTAT1 */ - -#define SSTAT1_REG 0x0e /* SCSI status 1 ro */ -#define SSTAT1_ILF 0x80 /* SIDL full */ -#define SSTAT1_ORF 0x40 /* SODR full */ -#define SSTAT1_OLF 0x20 /* SODL full */ -#define SSTAT1_AIP 0x10 /* Arbitration in progress */ -#define SSTAT1_LOA 0x08 /* Lost arbitration */ -#define SSTAT1_WOA 0x04 /* Won arbitration */ -#define SSTAT1_RST 0x02 /* Instant readout of RST/ */ -#define SSTAT1_SDP 0x01 /* Instant readout of SDP/ */ - -#define SSTAT2_REG 0x0f /* SCSI status 2 ro */ -#define SSTAT2_FF3 0x80 /* number of bytes in synchronous */ -#define SSTAT2_FF2 0x40 /* data FIFO */ -#define SSTAT2_FF1 0x20 -#define SSTAT2_FF0 0x10 -#define SSTAT2_FF_MASK 0xf0 -#define SSTAT2_FF_SHIFT 4 - -/* - * Latched signals, latched on the leading edge of REQ/ for initiators, - * ACK/ for targets. - */ -#define SSTAT2_SDP 0x08 /* SDP */ -#define SSTAT2_MSG 0x04 /* MSG */ -#define SSTAT2_CD 0x02 /* C/D */ -#define SSTAT2_IO 0x01 /* I/O */ -#define SSTAT2_PHASE_CMDOUT SSTAT2_CD -#define SSTAT2_PHASE_DATAIN SSTAT2_IO -#define SSTAT2_PHASE_DATAOUT 0 -#define SSTAT2_PHASE_MSGIN (SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG) -#define SSTAT2_PHASE_MSGOUT (SSTAT2_CD|SSTAT2_MSG) -#define SSTAT2_PHASE_STATIN (SSTAT2_CD|SSTAT2_IO) -#define SSTAT2_PHASE_MASK (SSTAT2_CD|SSTAT2_IO|SSTAT2_MSG) - - -/* NCR53c700-66 only */ -#define SCRATCHA_REG_00 0x10 /* through 0x13 Scratch A rw */ -/* NCR53c710 and higher */ -#define DSA_REG 0x10 /* DATA structure address */ - -#define CTEST0_REG_700 0x14 /* Chip test 0 ro */ -#define CTEST0_REG_800 0x18 /* Chip test 0 rw, general purpose */ -/* 0x80 - 0x04 are reserved */ -#define CTEST0_700_RTRG 0x02 /* Real target mode */ -#define CTEST0_700_DDIR 0x01 /* Data direction, 1 = - * SCSI bus to host, 0 = - * host to SCSI. - */ - -#define CTEST1_REG_700 0x15 /* Chip test 1 ro */ -#define CTEST1_REG_800 0x19 /* Chip test 1 ro */ -#define CTEST1_FMT3 0x80 /* Identify which byte lanes are empty */ -#define CTEST1_FMT2 0x40 /* in the DMA FIFO */ -#define CTEST1_FMT1 0x20 -#define CTEST1_FMT0 0x10 - -#define CTEST1_FFL3 0x08 /* Identify which bytes lanes are full */ -#define CTEST1_FFL2 0x04 /* in the DMA FIFO */ -#define CTEST1_FFL1 0x02 -#define CTEST1_FFL0 0x01 - -#define CTEST2_REG_700 0x16 /* Chip test 2 ro */ -#define CTEST2_REG_800 0x1a /* Chip test 2 ro */ - -#define CTEST2_800_DDIR 0x80 /* 1 = SCSI->host */ -#define CTEST2_800_SIGP 0x40 /* A copy of SIGP in ISTAT. - Reading this register clears */ -#define CTEST2_800_CIO 0x20 /* Configured as IO */. -#define CTEST2_800_CM 0x10 /* Configured as memory */ - -/* 0x80 - 0x40 are reserved on 700 series chips */ -#define CTEST2_700_SOFF 0x20 /* SCSI Offset Compare, - * As an initiator, this bit is - * one when the synchronous offset - * is zero, as a target this bit - * is one when the synchronous - * offset is at the maximum - * defined in SXFER - */ -#define CTEST2_700_SFP 0x10 /* SCSI FIFO parity bit, - * reading CTEST3 unloads a byte - * from the FIFO and sets this - */ -#define CTEST2_700_DFP 0x08 /* DMA FIFO parity bit, - * reading CTEST6 unloads a byte - * from the FIFO and sets this - */ -#define CTEST2_TEOP 0x04 /* SCSI true end of process, - * indicates a totally finished - * transfer - */ -#define CTEST2_DREQ 0x02 /* Data request signal */ -/* 0x01 is reserved on 700 series chips */ -#define CTEST2_800_DACK 0x01 - -/* - * Chip test 3 ro - * Unloads the bottom byte of the eight deep SCSI synchronous FIFO, - * check SSTAT2 FIFO full bits to determine size. Note that a GROSS - * error results if a read is attempted on this register. Also note - * that 16 and 32 bit reads of this register will cause corruption. - */ -#define CTEST3_REG_700 0x17 -/* Chip test 3 rw */ -#define CTEST3_REG_800 0x1b -#define CTEST3_800_V3 0x80 /* Chip revision */ -#define CTEST3_800_V2 0x40 -#define CTEST3_800_V1 0x20 -#define CTEST3_800_V0 0x10 -#define CTEST3_800_FLF 0x08 /* Flush DMA FIFO */ -#define CTEST3_800_CLF 0x04 /* Clear DMA FIFO */ -#define CTEST3_800_FM 0x02 /* Fetch mode pin */ -/* bit 0 is reserved on 800 series chips */ - -#define CTEST4_REG_700 0x18 /* Chip test 4 rw */ -#define CTEST4_REG_800 0x21 /* Chip test 4 rw */ -/* 0x80 is reserved on 700 series chips */ -#define CTEST4_800_BDIS 0x80 /* Burst mode disable */ -#define CTEST4_ZMOD 0x40 /* High impedance mode */ -#define CTEST4_SZM 0x20 /* SCSI bus high impedance */ -#define CTEST4_700_SLBE 0x10 /* SCSI loopback enabled */ -#define CTEST4_800_SRTM 0x10 /* Shadow Register Test Mode */ -#define CTEST4_700_SFWR 0x08 /* SCSI FIFO write enable, - * redirects writes from SODL - * to the SCSI FIFO. - */ -#define CTEST4_800_MPEE 0x08 /* Enable parity checking - during master cycles on PCI - bus */ - -/* - * These bits send the contents of the CTEST6 register to the appropriate - * byte lane of the 32 bit DMA FIFO. Normal operation is zero, otherwise - * the high bit means the low two bits select the byte lane. - */ -#define CTEST4_FBL2 0x04 -#define CTEST4_FBL1 0x02 -#define CTEST4_FBL0 0x01 -#define CTEST4_FBL_MASK 0x07 -#define CTEST4_FBL_0 0x04 /* Select DMA FIFO byte lane 0 */ -#define CTEST4_FBL_1 0x05 /* Select DMA FIFO byte lane 1 */ -#define CTEST4_FBL_2 0x06 /* Select DMA FIFO byte lane 2 */ -#define CTEST4_FBL_3 0x07 /* Select DMA FIFO byte lane 3 */ -#define CTEST4_800_SAVE (CTEST4_800_BDIS) - - -#define CTEST5_REG_700 0x19 /* Chip test 5 rw */ -#define CTEST5_REG_800 0x22 /* Chip test 5 rw */ -/* - * Clock Address Incrementor. When set, it increments the - * DNAD register to the next bus size boundary. It automatically - * resets itself when the operation is complete. - */ -#define CTEST5_ADCK 0x80 -/* - * Clock Byte Counter. When set, it decrements the DBC register to - * the next bus size boundary. - */ -#define CTEST5_BBCK 0x40 -/* - * Reset SCSI Offset. Setting this bit to 1 clears the current offset - * pointer in the SCSI synchronous offset counter (SSTAT). This bit - * is set to 1 if a SCSI Gross Error Condition occurs. The offset should - * be cleared when a synchronous transfer fails. When written, it is - * automatically cleared after the SCSI synchronous offset counter is - * reset. - */ -/* Bit 5 is reserved on 800 series chips */ -#define CTEST5_700_ROFF 0x20 -/* - * Master Control for Set or Reset pulses. When 1, causes the low - * four bits of register to set when set, 0 causes the low bits to - * clear when set. - */ -#define CTEST5_MASR 0x10 -#define CTEST5_DDIR 0x08 /* DMA direction */ -/* - * Bits 2-0 are reserved on 800 series chips - */ -#define CTEST5_700_EOP 0x04 /* End of process */ -#define CTEST5_700_DREQ 0x02 /* Data request */ -#define CTEST5_700_DACK 0x01 /* Data acknowledge */ - -/* - * Chip test 6 rw - writing to this register writes to the byte - * lane in the DMA FIFO as determined by the FBL bits in the CTEST4 - * register. - */ -#define CTEST6_REG_700 0x1a -#define CTEST6_REG_800 0x23 - -#define CTEST7_REG 0x1b /* Chip test 7 rw */ -/* 0x80 - 0x40 are reserved on NCR53c700 and NCR53c700-66 chips */ -#define CTEST7_10_CDIS 0x80 /* Cache burst disable */ -#define CTEST7_10_SC1 0x40 /* Snoop control bits */ -#define CTEST7_10_SC0 0x20 -#define CTEST7_10_SC_MASK 0x60 -/* 0x20 is reserved on the NCR53c700 */ -#define CTEST7_0060_FM 0x20 /* Fetch mode */ -#define CTEST7_STD 0x10 /* Selection timeout disable */ -#define CTEST7_DFP 0x08 /* DMA FIFO parity bit for CTEST6 */ -#define CTEST7_EVP 0x04 /* 1 = host bus even parity, 0 = odd */ -#define CTEST7_10_TT1 0x02 /* Transfer type */ -#define CTEST7_00_DC 0x02 /* Set to drive DC low during instruction - fetch */ -#define CTEST7_DIFF 0x01 /* Differential mode */ - -#define CTEST7_SAVE ( CTEST7_EVP | CTEST7_DIFF ) - - -#define TEMP_REG 0x1c /* through 0x1f Temporary stack rw */ - -#define DFIFO_REG 0x20 /* DMA FIFO rw */ -/* - * 0x80 is reserved on the NCR53c710, the CLF and FLF bits have been - * moved into the CTEST8 register. - */ -#define DFIFO_00_FLF 0x80 /* Flush DMA FIFO to memory */ -#define DFIFO_00_CLF 0x40 /* Clear DMA and SCSI FIFOs */ -#define DFIFO_BO6 0x40 -#define DFIFO_BO5 0x20 -#define DFIFO_BO4 0x10 -#define DFIFO_BO3 0x08 -#define DFIFO_BO2 0x04 -#define DFIFO_BO1 0x02 -#define DFIFO_BO0 0x01 -#define DFIFO_10_BO_MASK 0x7f /* 7 bit counter */ -#define DFIFO_00_BO_MASK 0x3f /* 6 bit counter */ - -/* - * Interrupt status rw - * Note that this is the only register which can be read while SCSI - * SCRIPTS are being executed. - */ -#define ISTAT_REG_700 0x21 -#define ISTAT_REG_800 0x14 -#define ISTAT_ABRT 0x80 /* Software abort, write - *1 to abort, wait for interrupt. */ -/* 0x40 and 0x20 are reserved on NCR53c700 and NCR53c700-66 chips */ -#define ISTAT_10_SRST 0x40 /* software reset */ -#define ISTAT_10_SIGP 0x20 /* signal script */ -/* 0x10 is reserved on NCR53c700 series chips */ -#define ISTAT_800_SEM 0x10 /* semaphore */ -#define ISTAT_CON 0x08 /* 1 when connected */ -#define ISTAT_800_INTF 0x04 /* Interrupt on the fly */ -#define ISTAT_700_PRE 0x04 /* Pointer register empty. - * Set to 1 when DSPS and DSP - * registers are empty in pipeline - * mode, always set otherwise. - */ -#define ISTAT_SIP 0x02 /* SCSI interrupt pending from - * SCSI portion of SIOP see - * SSTAT0 - */ -#define ISTAT_DIP 0x01 /* DMA interrupt pending - * see DSTAT - */ - -/* NCR53c700-66 and NCR53c710 only */ -#define CTEST8_REG 0x22 /* Chip test 8 rw */ -#define CTEST8_0066_EAS 0x80 /* Enable alternate SCSI clock, - * ie read from SCLK/ rather than CLK/ - */ -#define CTEST8_0066_EFM 0x40 /* Enable fetch and master outputs */ -#define CTEST8_0066_GRP 0x20 /* Generate Receive Parity for - * pass through. This insures that - * bad parity won't reach the host - * bus. - */ -#define CTEST8_0066_TE 0x10 /* TolerANT enable. Enable - * active negation, should only - * be used for slow SCSI - * non-differential. - */ -#define CTEST8_0066_HSC 0x08 /* Halt SCSI clock */ -#define CTEST8_0066_SRA 0x04 /* Shorten REQ/ACK filtering, - * must be set for fast SCSI-II - * speeds. - */ -#define CTEST8_0066_DAS 0x02 /* Disable automatic target/initiator - * switching. - */ -#define CTEST8_0066_LDE 0x01 /* Last disconnect enable. - * The status of pending - * disconnect is maintained by - * the core, eliminating - * the possibility of missing a - * selection or reselection - * while waiting to fetch a - * WAIT DISCONNECT opcode. - */ - -#define CTEST8_10_V3 0x80 /* Chip revision */ -#define CTEST8_10_V2 0x40 -#define CTEST8_10_V1 0x20 -#define CTEST8_10_V0 0x10 -#define CTEST8_10_V_MASK 0xf0 -#define CTEST8_10_FLF 0x08 /* Flush FIFOs */ -#define CTEST8_10_CLF 0x04 /* Clear FIFOs */ -#define CTEST8_10_FM 0x02 /* Fetch pin mode */ -#define CTEST8_10_SM 0x01 /* Snoop pin mode */ - - -/* - * The CTEST9 register may be used to differentiate between a - * NCR53c700 and a NCR53c710. - * - * Write 0xff to this register. - * Read it. - * If the contents are 0xff, it is a NCR53c700 - * If the contents are 0x00, it is a NCR53c700-66 first revision - * If the contents are some other value, it is some other NCR53c700-66 - */ -#define CTEST9_REG_00 0x23 /* Chip test 9 ro */ -#define LCRC_REG_10 0x23 - -/* - * 0x24 through 0x27 are the DMA byte counter register. Instructions - * write their high 8 bits into the DCMD register, the low 24 bits into - * the DBC register. - * - * Function is dependent on the command type being executed. - */ - - -#define DBC_REG 0x24 -/* - * For Block Move Instructions, DBC is a 24 bit quantity representing - * the number of bytes to transfer. - * For Transfer Control Instructions, DBC is bit fielded as follows : - */ -/* Bits 20 - 23 should be clear */ -#define DBC_TCI_TRUE (1 << 19) /* Jump when true */ -#define DBC_TCI_COMPARE_DATA (1 << 18) /* Compare data */ -#define DBC_TCI_COMPARE_PHASE (1 << 17) /* Compare phase with DCMD field */ -#define DBC_TCI_WAIT_FOR_VALID (1 << 16) /* Wait for REQ */ -/* Bits 8 - 15 are reserved on some implementations ? */ -#define DBC_TCI_MASK_MASK 0xff00 /* Mask for data compare */ -#define DBC_TCI_MASK_SHIFT 8 -#define DBC_TCI_DATA_MASK 0xff /* Data to be compared */ -#define DBC_TCI_DATA_SHIFT 0 - -#define DBC_RWRI_IMMEDIATE_MASK 0xff00 /* Immediate data */ -#define DBC_RWRI_IMMEDIATE_SHIFT 8 /* Amount to shift */ -#define DBC_RWRI_ADDRESS_MASK 0x3f0000 /* Register address */ -#define DBC_RWRI_ADDRESS_SHIFT 16 - - -/* - * DMA command r/w - */ -#define DCMD_REG 0x27 -#define DCMD_TYPE_MASK 0xc0 /* Masks off type */ -#define DCMD_TYPE_BMI 0x00 /* Indicates a Block Move instruction */ -#define DCMD_BMI_IO 0x01 /* I/O, CD, and MSG bits selecting */ -#define DCMD_BMI_CD 0x02 /* the phase for the block MOVE */ -#define DCMD_BMI_MSG 0x04 /* instruction */ - -#define DCMD_BMI_OP_MASK 0x18 /* mask for opcode */ -#define DCMD_BMI_OP_MOVE_T 0x00 /* MOVE */ -#define DCMD_BMI_OP_MOVE_I 0x08 /* MOVE Initiator */ - -#define DCMD_BMI_INDIRECT 0x20 /* Indirect addressing */ - -#define DCMD_TYPE_TCI 0x80 /* Indicates a Transfer Control - instruction */ -#define DCMD_TCI_IO 0x01 /* I/O, CD, and MSG bits selecting */ -#define DCMD_TCI_CD 0x02 /* the phase for the block MOVE */ -#define DCMD_TCI_MSG 0x04 /* instruction */ -#define DCMD_TCI_OP_MASK 0x38 /* mask for opcode */ -#define DCMD_TCI_OP_JUMP 0x00 /* JUMP */ -#define DCMD_TCI_OP_CALL 0x08 /* CALL */ -#define DCMD_TCI_OP_RETURN 0x10 /* RETURN */ -#define DCMD_TCI_OP_INT 0x18 /* INT */ - -#define DCMD_TYPE_RWRI 0x40 /* Indicates I/O or register Read/Write - instruction */ -#define DCMD_RWRI_OPC_MASK 0x38 /* Opcode mask */ -#define DCMD_RWRI_OPC_WRITE 0x28 /* Write SFBR to register */ -#define DCMD_RWRI_OPC_READ 0x30 /* Read register to SFBR */ -#define DCMD_RWRI_OPC_MODIFY 0x38 /* Modify in place */ - -#define DCMD_RWRI_OP_MASK 0x07 -#define DCMD_RWRI_OP_MOVE 0x00 -#define DCMD_RWRI_OP_SHL 0x01 -#define DCMD_RWRI_OP_OR 0x02 -#define DCMD_RWRI_OP_XOR 0x03 -#define DCMD_RWRI_OP_AND 0x04 -#define DCMD_RWRI_OP_SHR 0x05 -#define DCMD_RWRI_OP_ADD 0x06 -#define DCMD_RWRI_OP_ADDC 0x07 - -#define DCMD_TYPE_MMI 0xc0 /* Indicates a Memory Move instruction - (three words) */ - - -#define DNAD_REG 0x28 /* through 0x2b DMA next address for - data */ -#define DSP_REG 0x2c /* through 0x2f DMA SCRIPTS pointer rw */ -#define DSPS_REG 0x30 /* through 0x33 DMA SCRIPTS pointer - save rw */ -#define DMODE_REG_00 0x34 /* DMA mode rw */ -#define DMODE_00_BL1 0x80 /* Burst length bits */ -#define DMODE_00_BL0 0x40 -#define DMODE_BL_MASK 0xc0 -/* Burst lengths (800) */ -#define DMODE_BL_2 0x00 /* 2 transfer */ -#define DMODE_BL_4 0x40 /* 4 transfers */ -#define DMODE_BL_8 0x80 /* 8 transfers */ -#define DMODE_BL_16 0xc0 /* 16 transfers */ - -#define DMODE_10_BL_1 0x00 /* 1 transfer */ -#define DMODE_10_BL_2 0x40 /* 2 transfers */ -#define DMODE_10_BL_4 0x80 /* 4 transfers */ -#define DMODE_10_BL_8 0xc0 /* 8 transfers */ -#define DMODE_10_FC2 0x20 /* Driven to FC2 pin */ -#define DMODE_10_FC1 0x10 /* Driven to FC1 pin */ -#define DMODE_710_PD 0x08 /* Program/data on FC0 pin */ -#define DMODE_710_UO 0x02 /* User prog. output */ - -#define DMODE_700_BW16 0x20 /* Host buswidth = 16 */ -#define DMODE_700_286 0x10 /* 286 mode */ -#define DMODE_700_IOM 0x08 /* Transfer to IO port */ -#define DMODE_700_FAM 0x04 /* Fixed address mode */ -#define DMODE_700_PIPE 0x02 /* Pipeline mode disables - * automatic fetch / exec - */ -#define DMODE_MAN 0x01 /* Manual start mode, - * requires a 1 to be written - * to the start DMA bit in the DCNTL - * register to run scripts - */ - -#define DMODE_700_SAVE ( DMODE_00_BL_MASK | DMODE_00_BW16 | DMODE_00_286 ) - -/* NCR53c800 series only */ -#define SCRATCHA_REG_800 0x34 /* through 0x37 Scratch A rw */ -/* NCR53c710 only */ -#define SCRATCHB_REG_10 0x34 /* through 0x37 scratch B rw */ - -#define DMODE_REG_10 0x38 /* DMA mode rw, NCR53c710 and newer */ -#define DMODE_800_SIOM 0x20 /* Source IO = 1 */ -#define DMODE_800_DIOM 0x10 /* Destination IO = 1 */ -#define DMODE_800_ERL 0x08 /* Enable Read Line */ - -/* 35-38 are reserved on 700 and 700-66 series chips */ -#define DIEN_REG 0x39 /* DMA interrupt enable rw */ -/* 0x80, 0x40, and 0x20 are reserved on 700-series chips */ -#define DIEN_800_MDPE 0x40 /* Master data parity error */ -#define DIEN_800_BF 0x20 /* BUS fault */ -#define DIEN_700_BF 0x20 /* BUS fault */ -#define DIEN_ABRT 0x10 /* Enable aborted interrupt */ -#define DIEN_SSI 0x08 /* Enable single step interrupt */ -#define DIEN_SIR 0x04 /* Enable SCRIPTS INT command - * interrupt - */ -/* 0x02 is reserved on 800 series chips */ -#define DIEN_700_WTD 0x02 /* Enable watchdog timeout interrupt */ -#define DIEN_700_OPC 0x01 /* Enable illegal instruction - * interrupt - */ -#define DIEN_800_IID 0x01 /* Same meaning, different name */ - -/* - * DMA watchdog timer rw - * set in 16 CLK input periods. - */ -#define DWT_REG 0x3a - -/* DMA control rw */ -#define DCNTL_REG 0x3b -#define DCNTL_700_CF1 0x80 /* Clock divisor bits */ -#define DCNTL_700_CF0 0x40 -#define DCNTL_700_CF_MASK 0xc0 -/* Clock divisors Divisor SCLK range (MHZ) */ -#define DCNTL_700_CF_2 0x00 /* 2.0 37.51-50.00 */ -#define DCNTL_700_CF_1_5 0x40 /* 1.5 25.01-37.50 */ -#define DCNTL_700_CF_1 0x80 /* 1.0 16.67-25.00 */ -#define DCNTL_700_CF_3 0xc0 /* 3.0 50.01-66.67 (53c700-66) */ - -#define DCNTL_700_S16 0x20 /* Load scripts 16 bits at a time */ -#define DCNTL_SSM 0x10 /* Single step mode */ -#define DCNTL_700_LLM 0x08 /* Low level mode, can only be set - * after selection */ -#define DCNTL_800_IRQM 0x08 /* Totem pole IRQ pin */ -#define DCNTL_STD 0x04 /* Start DMA / SCRIPTS */ -/* 0x02 is reserved */ -#define DCNTL_00_RST 0x01 /* Software reset, resets everything - * but 286 mode bit in DMODE. On the - * NCR53c710, this bit moved to CTEST8 - */ -#define DCNTL_10_COM 0x01 /* 700 software compatibility mode */ -#define DCNTL_10_EA 0x20 /* Enable Ack - needed for MVME16x */ - -#define DCNTL_700_SAVE ( DCNTL_CF_MASK | DCNTL_S16) - - -/* NCR53c700-66 only */ -#define SCRATCHB_REG_00 0x3c /* through 0x3f scratch b rw */ -#define SCRATCHB_REG_800 0x5c /* through 0x5f scratch b rw */ -/* NCR53c710 only */ -#define ADDER_REG_10 0x3c /* Adder, NCR53c710 only */ - -#define SIEN1_REG_800 0x41 -#define SIEN1_800_STO 0x04 /* selection/reselection timeout */ -#define SIEN1_800_GEN 0x02 /* general purpose timer */ -#define SIEN1_800_HTH 0x01 /* handshake to handshake */ - -#define SIST1_REG_800 0x43 -#define SIST1_800_STO 0x04 /* selection/reselection timeout */ -#define SIST1_800_GEN 0x02 /* general purpose timer */ -#define SIST1_800_HTH 0x01 /* handshake to handshake */ - -#define SLPAR_REG_800 0x44 /* Parity */ - -#define MACNTL_REG_800 0x46 /* Memory access control */ -#define MACNTL_800_TYP3 0x80 -#define MACNTL_800_TYP2 0x40 -#define MACNTL_800_TYP1 0x20 -#define MACNTL_800_TYP0 0x10 -#define MACNTL_800_DWR 0x08 -#define MACNTL_800_DRD 0x04 -#define MACNTL_800_PSCPT 0x02 -#define MACNTL_800_SCPTS 0x01 - -#define GPCNTL_REG_800 0x47 /* General Purpose Pin Control */ - -/* Timeouts are expressed such that 0=off, 1=100us, doubling after that */ -#define STIME0_REG_800 0x48 /* SCSI Timer Register 0 */ -#define STIME0_800_HTH_MASK 0xf0 /* Handshake to Handshake timeout */ -#define STIME0_800_HTH_SHIFT 4 -#define STIME0_800_SEL_MASK 0x0f /* Selection timeout */ -#define STIME0_800_SEL_SHIFT 0 - -#define STIME1_REG_800 0x49 -#define STIME1_800_GEN_MASK 0x0f /* General purpose timer */ - -#define RESPID_REG_800 0x4a /* Response ID, bit fielded. 8 - bits on narrow chips, 16 on WIDE */ - -#define STEST0_REG_800 0x4c -#define STEST0_800_SLT 0x08 /* Selection response logic test */ -#define STEST0_800_ART 0x04 /* Arbitration priority encoder test */ -#define STEST0_800_SOZ 0x02 /* Synchronous offset zero */ -#define STEST0_800_SOM 0x01 /* Synchronous offset maximum */ - -#define STEST1_REG_800 0x4d -#define STEST1_800_SCLK 0x80 /* Disable SCSI clock */ - -#define STEST2_REG_800 0x4e -#define STEST2_800_SCE 0x80 /* Enable SOCL/SODL */ -#define STEST2_800_ROF 0x40 /* Reset SCSI sync offset */ -#define STEST2_800_SLB 0x10 /* Enable SCSI loopback mode */ -#define STEST2_800_SZM 0x08 /* SCSI high impedance mode */ -#define STEST2_800_EXT 0x02 /* Extend REQ/ACK filter 30 to 60ns */ -#define STEST2_800_LOW 0x01 /* SCSI low level mode */ - -#define STEST3_REG_800 0x4f -#define STEST3_800_TE 0x80 /* Enable active negation */ -#define STEST3_800_STR 0x40 /* SCSI FIFO test read */ -#define STEST3_800_HSC 0x20 /* Halt SCSI clock */ -#define STEST3_800_DSI 0x10 /* Disable single initiator response */ -#define STEST3_800_TTM 0x04 /* Time test mode */ -#define STEST3_800_CSF 0x02 /* Clear SCSI FIFO */ -#define STEST3_800_STW 0x01 /* SCSI FIFO test write */ - -#define OPTION_PARITY 0x1 /* Enable parity checking */ -#define OPTION_TAGGED_QUEUE 0x2 /* Enable SCSI-II tagged queuing */ -#define OPTION_700 0x8 /* Always run NCR53c700 scripts */ -#define OPTION_INTFLY 0x10 /* Use INTFLY interrupts */ -#define OPTION_DEBUG_INTR 0x20 /* Debug interrupts */ -#define OPTION_DEBUG_INIT_ONLY 0x40 /* Run initialization code and - simple test code, return - DID_NO_CONNECT if any SCSI - commands are attempted. */ -#define OPTION_DEBUG_READ_ONLY 0x80 /* Return DID_ERROR if any - SCSI write is attempted */ -#define OPTION_DEBUG_TRACE 0x100 /* Animated trace mode, print - each address and instruction - executed to debug buffer. */ -#define OPTION_DEBUG_SINGLE 0x200 /* stop after executing one - instruction */ -#define OPTION_SYNCHRONOUS 0x400 /* Enable sync SCSI. */ -#define OPTION_MEMORY_MAPPED 0x800 /* NCR registers have valid - memory mapping */ -#define OPTION_IO_MAPPED 0x1000 /* NCR registers have valid - I/O mapping */ -#define OPTION_DEBUG_PROBE_ONLY 0x2000 /* Probe only, don't even init */ -#define OPTION_DEBUG_TESTS_ONLY 0x4000 /* Probe, init, run selected tests */ -#define OPTION_DEBUG_TEST0 0x08000 /* Run test 0 */ -#define OPTION_DEBUG_TEST1 0x10000 /* Run test 1 */ -#define OPTION_DEBUG_TEST2 0x20000 /* Run test 2 */ -#define OPTION_DEBUG_DUMP 0x40000 /* Dump commands */ -#define OPTION_DEBUG_TARGET_LIMIT 0x80000 /* Only talk to target+luns specified */ -#define OPTION_DEBUG_NCOMMANDS_LIMIT 0x100000 /* Limit the number of commands */ -#define OPTION_DEBUG_SCRIPT 0x200000 /* Print when checkpoints are passed */ -#define OPTION_DEBUG_FIXUP 0x400000 /* print fixup values */ -#define OPTION_DEBUG_DSA 0x800000 -#define OPTION_DEBUG_CORRUPTION 0x1000000 /* Detect script corruption */ -#define OPTION_DEBUG_SDTR 0x2000000 /* Debug SDTR problem */ -#define OPTION_DEBUG_MISMATCH 0x4000000 /* Debug phase mismatches */ -#define OPTION_DISCONNECT 0x8000000 /* Allow disconnect */ -#define OPTION_DEBUG_DISCONNECT 0x10000000 -#define OPTION_ALWAYS_SYNCHRONOUS 0x20000000 /* Negotiate sync. transfers - on power up */ -#define OPTION_DEBUG_QUEUES 0x80000000 -#define OPTION_DEBUG_ALLOCATION 0x100000000LL -#define OPTION_DEBUG_SYNCHRONOUS 0x200000000LL /* Sanity check SXFER and - SCNTL3 registers */ -#define OPTION_NO_ASYNC 0x400000000LL /* Don't automagically send - SDTR for async transfers when - we haven't been told to do - a synchronous transfer. */ -#define OPTION_NO_PRINT_RACE 0x800000000LL /* Don't print message when - the reselect/WAIT DISCONNECT - race condition hits */ -#if !defined(PERM_OPTIONS) -#define PERM_OPTIONS 0 -#endif - -/* - * Some data which is accessed by the NCR chip must be 4-byte aligned. - * For some hosts the default is less than that (eg. 68K uses 2-byte). - * Alignment has only been forced where it is important; also if one - * 32 bit structure field is aligned then it is assumed that following - * 32 bit fields are also aligned. Take care when adding fields - * which are other than 32 bit. - */ - -struct NCR53c7x0_synchronous { - u32 select_indirect /* Value used for indirect selection */ - __attribute__ ((aligned (4))); - u32 sscf_710; /* Used to set SSCF bits for 710 */ - u32 script[8]; /* Size ?? Script used when target is - reselected */ - unsigned char synchronous_want[5]; /* Per target desired SDTR */ -/* - * Set_synchronous programs these, select_indirect and current settings after - * int_debug_should show a match. - */ - unsigned char sxfer_sanity, scntl3_sanity; -}; - -#define CMD_FLAG_SDTR 1 /* Initiating synchronous - transfer negotiation */ -#define CMD_FLAG_WDTR 2 /* Initiating wide transfer - negotiation */ -#define CMD_FLAG_DID_SDTR 4 /* did SDTR */ -#define CMD_FLAG_DID_WDTR 8 /* did WDTR */ - -struct NCR53c7x0_table_indirect { - u32 count; - void *address; -}; - -enum ncr_event { - EVENT_NONE = 0, -/* - * Order is IMPORTANT, since these must correspond to the event interrupts - * in 53c7,8xx.scr - */ - - EVENT_ISSUE_QUEUE = 0x5000000, /* 0 Command was added to issue queue */ - EVENT_START_QUEUE, /* 1 Command moved to start queue */ - EVENT_SELECT, /* 2 Command completed selection */ - EVENT_DISCONNECT, /* 3 Command disconnected */ - EVENT_RESELECT, /* 4 Command reselected */ - EVENT_COMPLETE, /* 5 Command completed */ - EVENT_IDLE, /* 6 */ - EVENT_SELECT_FAILED, /* 7 */ - EVENT_BEFORE_SELECT, /* 8 */ - EVENT_RESELECT_FAILED /* 9 */ -}; - -struct NCR53c7x0_event { - enum ncr_event event; /* What type of event */ - unsigned char target; - unsigned char lun; - struct timeval time; - u32 *dsa; /* What's in the DSA register now (virt) */ -/* - * A few things from that SCSI pid so we know what happened after - * the Scsi_Cmnd structure in question may have disappeared. - */ - unsigned long pid; /* The SCSI PID which caused this - event */ - unsigned char cmnd[12]; -}; - -/* - * Things in the NCR53c7x0_cmd structure are split into two parts : - * - * 1. A fixed portion, for things which are not accessed directly by static NCR - * code (ie, are referenced only by the Linux side of the driver, - * or only by dynamically generated code). - * - * 2. The DSA portion, for things which are accessed directly by static NCR - * code. - * - * This is a little ugly, but it - * 1. Avoids conflicts between the NCR code's picture of the structure, and - * Linux code's idea of what it looks like. - * - * 2. Minimizes the pain in the Linux side of the code needed - * to calculate real dsa locations for things, etc. - * - */ - -struct NCR53c7x0_cmd { - void *real; /* Real, unaligned address for - free function */ - void (* free)(void *, int); /* Command to deallocate; NULL - for structures allocated with - scsi_register, etc. */ - Scsi_Cmnd *cmd; /* Associated Scsi_Cmnd - structure, Scsi_Cmnd points - at NCR53c7x0_cmd using - host_scribble structure */ - - int size; /* scsi_malloc'd size of this - structure */ - - int flags; /* CMD_* flags */ - - unsigned char cmnd[12]; /* CDB, copied from Scsi_Cmnd */ - int result; /* Copy to Scsi_Cmnd when done */ - - struct { /* Private non-cached bounce buffer */ - unsigned char buf[256]; - u32 addr; - u32 len; - } bounce; - -/* - * SDTR and WIDE messages are an either/or affair - * in this message, since we will go into message out and send - * _the whole mess_ without dropping out of message out to - * let the target go into message in after sending the first - * message. - */ - - unsigned char select[11]; /* Select message, includes - IDENTIFY - (optional) QUEUE TAG - (optional) SDTR or WDTR - */ - - - volatile struct NCR53c7x0_cmd *next; /* Linux maintained lists (free, - running, eventually finished */ - - - u32 *data_transfer_start; /* Start of data transfer routines */ - u32 *data_transfer_end; /* Address after end of data transfer o - routines */ -/* - * The following three fields were moved from the DSA proper to here - * since only dynamically generated NCR code refers to them, meaning - * we don't need dsa_* absolutes, and it is simpler to let the - * host code refer to them directly. - */ - -/* - * HARD CODED : residual and saved_residual need to agree with the sizes - * used in NCR53c7,8xx.scr. - * - * FIXME: we want to consider the case where we have odd-length - * scatter/gather buffers and a WIDE transfer, in which case - * we'll need to use the CHAIN MOVE instruction. Ick. - */ - u32 residual[6] __attribute__ ((aligned (4))); - /* Residual data transfer which - allows pointer code to work - right. - - [0-1] : Conditional call to - appropriate other transfer - routine. - [2-3] : Residual block transfer - instruction. - [4-5] : Jump to instruction - after splice. - */ - u32 saved_residual[6]; /* Copy of old residual, so we - can get another partial - transfer and still recover - */ - - u32 saved_data_pointer; /* Saved data pointer */ - - u32 dsa_next_addr; /* _Address_ of dsa_next field - in this dsa for RISCy - style constant. */ - - u32 dsa_addr; /* Address of dsa; RISCy style - constant */ - - u32 dsa[0]; /* Variable length (depending - on host type, number of scatter / - gather buffers, etc). */ -}; - -struct NCR53c7x0_break { - u32 *address, old_instruction[2]; - struct NCR53c7x0_break *next; - unsigned char old_size; /* Size of old instruction */ -}; - -/* Indicates that the NCR is not executing code */ -#define STATE_HALTED 0 -/* - * Indicates that the NCR is executing the wait for select / reselect - * script. Only used when running NCR53c700 compatible scripts, only - * state during which an ABORT is _not_ considered an error condition. - */ -#define STATE_WAITING 1 -/* Indicates that the NCR is executing other code. */ -#define STATE_RUNNING 2 -/* - * Indicates that the NCR was being aborted. - */ -#define STATE_ABORTING 3 -/* Indicates that the NCR was successfully aborted. */ -#define STATE_ABORTED 4 -/* Indicates that the NCR has been disabled due to a fatal error */ -#define STATE_DISABLED 5 - -/* - * Where knowledge of SCSI SCRIPT(tm) specified values are needed - * in an interrupt handler, an interrupt handler exists for each - * different SCSI script so we don't have name space problems. - * - * Return values of these handlers are as follows : - */ -#define SPECIFIC_INT_NOTHING 0 /* don't even restart */ -#define SPECIFIC_INT_RESTART 1 /* restart at the next instruction */ -#define SPECIFIC_INT_ABORT 2 /* recoverable error, abort cmd */ -#define SPECIFIC_INT_PANIC 3 /* unrecoverable error, panic */ -#define SPECIFIC_INT_DONE 4 /* normal command completion */ -#define SPECIFIC_INT_BREAK 5 /* break point encountered */ - -struct NCR53c7x0_hostdata { - int size; /* Size of entire Scsi_Host - structure */ - int board; /* set to board type, useful if - we have host specific things, - ie, a general purpose I/O - bit is being used to enable - termination, etc. */ - - int chip; /* set to chip type; 700-66 is - 700-66, rest are last three - digits of part number */ - - char valid_ids[8]; /* Valid SCSI ID's for adapter */ - - u32 *dsp; /* dsp to restart with after - all stacked interrupts are - handled. */ - - unsigned dsp_changed:1; /* Has dsp changed within this - set of stacked interrupts ? */ - - unsigned char dstat; /* Most recent value of dstat */ - unsigned dstat_valid:1; - - unsigned expecting_iid:1; /* Expect IID interrupt */ - unsigned expecting_sto:1; /* Expect STO interrupt */ - - /* - * The code stays cleaner if we use variables with function - * pointers and offsets that are unique for the different - * scripts rather than having a slew of switch(hostdata->chip) - * statements. - * - * It also means that the #defines from the SCSI SCRIPTS(tm) - * don't have to be visible outside of the script-specific - * instructions, preventing name space pollution. - */ - - void (* init_fixup)(struct Scsi_Host *host); - void (* init_save_regs)(struct Scsi_Host *host); - void (* dsa_fixup)(struct NCR53c7x0_cmd *cmd); - void (* soft_reset)(struct Scsi_Host *host); - int (* run_tests)(struct Scsi_Host *host); - - /* - * Called when DSTAT_SIR is set, indicating an interrupt generated - * by the INT instruction, where values are unique for each SCSI - * script. Should return one of the SPEC_* values. - */ - - int (* dstat_sir_intr)(struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd); - - int dsa_len; /* Size of DSA structure */ - - /* - * Location of DSA fields for the SCSI SCRIPT corresponding to this - * chip. - */ - - s32 dsa_start; - s32 dsa_end; - s32 dsa_next; - s32 dsa_prev; - s32 dsa_cmnd; - s32 dsa_select; - s32 dsa_msgout; - s32 dsa_cmdout; - s32 dsa_dataout; - s32 dsa_datain; - s32 dsa_msgin; - s32 dsa_msgout_other; - s32 dsa_write_sync; - s32 dsa_write_resume; - s32 dsa_check_reselect; - s32 dsa_status; - s32 dsa_saved_pointer; - s32 dsa_jump_dest; - - /* - * Important entry points that generic fixup code needs - * to know about, fixed up. - */ - - s32 E_accept_message; - s32 E_command_complete; - s32 E_data_transfer; - s32 E_dsa_code_template; - s32 E_dsa_code_template_end; - s32 E_end_data_transfer; - s32 E_msg_in; - s32 E_initiator_abort; - s32 E_other_transfer; - s32 E_other_in; - s32 E_other_out; - s32 E_target_abort; - s32 E_debug_break; - s32 E_reject_message; - s32 E_respond_message; - s32 E_select; - s32 E_select_msgout; - s32 E_test_0; - s32 E_test_1; - s32 E_test_2; - s32 E_test_3; - s32 E_dsa_zero; - s32 E_cmdout_cmdout; - s32 E_wait_reselect; - s32 E_dsa_code_begin; - - long long options; /* Bitfielded set of options enabled */ - volatile u32 test_completed; /* Test completed */ - int test_running; /* Test currently running */ - s32 test_source - __attribute__ ((aligned (4))); - volatile s32 test_dest; - - volatile int state; /* state of driver, only used for - OPTION_700 */ - - unsigned char dmode; /* - * set to the address of the DMODE - * register for this chip. - */ - unsigned char istat; /* - * set to the address of the ISTAT - * register for this chip. - */ - - int scsi_clock; /* - * SCSI clock in HZ. 0 may be used - * for unknown, although this will - * disable synchronous negotiation. - */ - - volatile int intrs; /* Number of interrupts */ - volatile int resets; /* Number of SCSI resets */ - unsigned char saved_dmode; - unsigned char saved_ctest4; - unsigned char saved_ctest7; - unsigned char saved_dcntl; - unsigned char saved_scntl3; - - unsigned char this_id_mask; - - /* Debugger information */ - struct NCR53c7x0_break *breakpoints, /* Linked list of all break points */ - *breakpoint_current; /* Current breakpoint being stepped - through, NULL if we are running - normally. */ -#ifdef NCR_DEBUG - int debug_size; /* Size of debug buffer */ - volatile int debug_count; /* Current data count */ - volatile char *debug_buf; /* Output ring buffer */ - volatile char *debug_write; /* Current write pointer */ - volatile char *debug_read; /* Current read pointer */ -#endif /* def NCR_DEBUG */ - - /* XXX - primitive debugging junk, remove when working ? */ - int debug_print_limit; /* Number of commands to print - out exhaustive debugging - information for if - OPTION_DEBUG_DUMP is set */ - - unsigned char debug_lun_limit[16]; /* If OPTION_DEBUG_TARGET_LIMIT - set, puke if commands are sent - to other target/lun combinations */ - - int debug_count_limit; /* Number of commands to execute - before puking to limit debugging - output */ - - - volatile unsigned idle:1; /* set to 1 if idle */ - - /* - * Table of synchronous+wide transfer parameters set on a per-target - * basis. - */ - - volatile struct NCR53c7x0_synchronous sync[16] - __attribute__ ((aligned (4))); - - volatile Scsi_Cmnd *issue_queue - __attribute__ ((aligned (4))); - /* waiting to be issued by - Linux driver */ - volatile struct NCR53c7x0_cmd *running_list; - /* commands running, maintained - by Linux driver */ - - volatile struct NCR53c7x0_cmd *ncrcurrent; /* currently connected - nexus, ONLY valid for - NCR53c700/NCR53c700-66 - */ - - volatile struct NCR53c7x0_cmd *spare; /* pointer to spare, - allocated at probe time, - which we can use for - initialization */ - volatile struct NCR53c7x0_cmd *free; - int max_cmd_size; /* Maximum size of NCR53c7x0_cmd - based on number of - scatter/gather segments, etc. - */ - volatile int num_cmds; /* Number of commands - allocated */ - volatile int extra_allocate; - volatile unsigned char cmd_allocated[16]; /* Have we allocated commands - for this target yet? If not, - do so ASAP */ - volatile unsigned char busy[16][8]; /* number of commands - executing on each target - */ - /* - * Eventually, I'll switch to a coroutine for calling - * cmd->done(cmd), etc. so that we can overlap interrupt - * processing with this code for maximum performance. - */ - - volatile struct NCR53c7x0_cmd *finished_queue; - - /* Shared variables between SCRIPT and host driver */ - volatile u32 *schedule - __attribute__ ((aligned (4))); /* Array of JUMPs to dsa_begin - routines of various DSAs. - When not in use, replace - with jump to next slot */ - - - volatile unsigned char msg_buf[16]; /* buffer for messages - other than the command - complete message */ - - /* Per-target default synchronous and WIDE messages */ - volatile unsigned char synchronous_want[16][5]; - volatile unsigned char wide_want[16][4]; - - /* Bit fielded set of targets we want to speak synchronously with */ - volatile u16 initiate_sdtr; - /* Bit fielded set of targets we want to speak wide with */ - volatile u16 initiate_wdtr; - /* Bit fielded list of targets we've talked to. */ - volatile u16 talked_to; - - /* Array of bit-fielded lun lists that we need to request_sense */ - volatile unsigned char request_sense[16]; - - u32 addr_reconnect_dsa_head - __attribute__ ((aligned (4))); /* RISCy style constant, - address of following */ - volatile u32 reconnect_dsa_head; - /* Data identifying nexus we are trying to match during reselection */ - volatile unsigned char reselected_identify; /* IDENTIFY message */ - volatile unsigned char reselected_tag; /* second byte of queue tag - message or 0 */ - - /* These were static variables before we moved them */ - - s32 NCR53c7xx_zero - __attribute__ ((aligned (4))); - s32 NCR53c7xx_sink; - u32 NOP_insn; - char NCR53c7xx_msg_reject; - char NCR53c7xx_msg_abort; - char NCR53c7xx_msg_nop; - - /* - * Following item introduced by RGH to support NCRc710, which is - * VERY brain-dead when it come to memory moves - */ - - /* DSA save area used only by the NCR chip */ - volatile unsigned long saved2_dsa - __attribute__ ((aligned (4))); - - volatile unsigned long emulated_intfly - __attribute__ ((aligned (4))); - - volatile int event_size, event_index; - volatile struct NCR53c7x0_event *events; - - /* If we need to generate code to kill off the currently connected - command, this is where we do it. Should have a BMI instruction - to source or sink the current data, followed by a JUMP - to abort_connected */ - - u32 *abort_script; - - int script_count; /* Size of script in words */ - u32 script[0]; /* Relocated SCSI script */ - -}; - -#define SCSI_IRQ_NONE 255 -#define DMA_NONE 255 -#define IRQ_AUTO 254 -#define DMA_AUTO 254 - -#define BOARD_GENERIC 0 - -#define NCR53c7x0_insn_size(insn) \ - (((insn) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI ? 3 : 2) - - -#define NCR53c7x0_local_declare() \ - volatile unsigned char *NCR53c7x0_address_memory; \ - unsigned int NCR53c7x0_address_io; \ - int NCR53c7x0_memory_mapped - -#define NCR53c7x0_local_setup(host) \ - NCR53c7x0_address_memory = (void *) (host)->base; \ - NCR53c7x0_address_io = (unsigned int) (host)->io_port; \ - NCR53c7x0_memory_mapped = ((struct NCR53c7x0_hostdata *) \ - host->hostdata[0])-> options & OPTION_MEMORY_MAPPED - -#ifdef BIG_ENDIAN -/* These could be more efficient, given that we are always memory mapped, - * but they don't give the same problems as the write macros, so leave - * them. */ -#ifdef __mc68000__ -#define NCR53c7x0_read8(address) \ - ((unsigned int)raw_inb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) ) - -#define NCR53c7x0_read16(address) \ - ((unsigned int)raw_inw((u32)NCR53c7x0_address_memory + ((u32)(address)^2))) -#else -#define NCR53c7x0_read8(address) \ - (NCR53c7x0_memory_mapped ? \ - (unsigned int)readb((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) : \ - inb(NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_read16(address) \ - (NCR53c7x0_memory_mapped ? \ - (unsigned int)readw((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) : \ - inw(NCR53c7x0_address_io + (address))) -#endif /* mc68000 */ -#else -#define NCR53c7x0_read8(address) \ - (NCR53c7x0_memory_mapped ? \ - (unsigned int)readb((u32)NCR53c7x0_address_memory + (u32)(address)) : \ - inb(NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_read16(address) \ - (NCR53c7x0_memory_mapped ? \ - (unsigned int)readw((u32)NCR53c7x0_address_memory + (u32)(address)) : \ - inw(NCR53c7x0_address_io + (address))) -#endif - -#ifdef __mc68000__ -#define NCR53c7x0_read32(address) \ - ((unsigned int) raw_inl((u32)NCR53c7x0_address_memory + (u32)(address))) -#else -#define NCR53c7x0_read32(address) \ - (NCR53c7x0_memory_mapped ? \ - (unsigned int) readl((u32)NCR53c7x0_address_memory + (u32)(address)) : \ - inl(NCR53c7x0_address_io + (address))) -#endif /* mc68000*/ - -#ifdef BIG_ENDIAN -/* If we are big-endian, then we are not Intel, so probably don't have - * an i/o map as well as a memory map. So, let's assume memory mapped. - * Also, I am having terrible problems trying to persuade the compiler - * not to lay down code which does a read after write for these macros. - * If you remove 'volatile' from writeb() and friends it is ok.... - */ - -#define NCR53c7x0_write8(address,value) \ - *(volatile unsigned char *) \ - ((u32)NCR53c7x0_address_memory + ((u32)(address)^3)) = (value) - -#define NCR53c7x0_write16(address,value) \ - *(volatile unsigned short *) \ - ((u32)NCR53c7x0_address_memory + ((u32)(address)^2)) = (value) - -#define NCR53c7x0_write32(address,value) \ - *(volatile unsigned long *) \ - ((u32)NCR53c7x0_address_memory + ((u32)(address))) = (value) - -#else - -#define NCR53c7x0_write8(address,value) \ - (NCR53c7x0_memory_mapped ? \ - ({writeb((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) : \ - outb((value), NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_write16(address,value) \ - (NCR53c7x0_memory_mapped ? \ - ({writew((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) : \ - outw((value), NCR53c7x0_address_io + (address))) - -#define NCR53c7x0_write32(address,value) \ - (NCR53c7x0_memory_mapped ? \ - ({writel((value), (u32)NCR53c7x0_address_memory + (u32)(address)); mb();}) : \ - outl((value), NCR53c7x0_address_io + (address))) - -#endif - -/* Patch arbitrary 32 bit words in the script */ -#define patch_abs_32(script, offset, symbol, value) \ - for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof \ - (u32)); ++i) { \ - (script)[A_##symbol##_used[i] - (offset)] += (value); \ - if (hostdata->options & OPTION_DEBUG_FIXUP) \ - printk("scsi%d : %s reference %d at 0x%x in %s is now 0x%x\n",\ - host->host_no, #symbol, i, A_##symbol##_used[i] - \ - (int)(offset), #script, (script)[A_##symbol##_used[i] - \ - (offset)]); \ - } - -/* Patch read/write instruction immediate field */ -#define patch_abs_rwri_data(script, offset, symbol, value) \ - for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof \ - (u32)); ++i) \ - (script)[A_##symbol##_used[i] - (offset)] = \ - ((script)[A_##symbol##_used[i] - (offset)] & \ - ~DBC_RWRI_IMMEDIATE_MASK) | \ - (((value) << DBC_RWRI_IMMEDIATE_SHIFT) & \ - DBC_RWRI_IMMEDIATE_MASK) - -/* Patch transfer control instruction data field */ -#define patch_abs_tci_data(script, offset, symbol, value) \ - for (i = 0; i < (sizeof (A_##symbol##_used) / sizeof \ - (u32)); ++i) \ - (script)[A_##symbol##_used[i] - (offset)] = \ - ((script)[A_##symbol##_used[i] - (offset)] & \ - ~DBC_TCI_DATA_MASK) | \ - (((value) << DBC_TCI_DATA_SHIFT) & \ - DBC_TCI_DATA_MASK) - -/* Patch field in dsa structure (assignment should be +=?) */ -#define patch_dsa_32(dsa, symbol, word, value) \ - { \ - (dsa)[(hostdata->##symbol - hostdata->dsa_start) / sizeof(u32) \ - + (word)] = (value); \ - if (hostdata->options & OPTION_DEBUG_DSA) \ - printk("scsi : dsa %s symbol %s(%d) word %d now 0x%x\n", \ - #dsa, #symbol, hostdata->##symbol, \ - (word), (u32) (value)); \ - } - -/* Paranoid people could use panic() here. */ -#define FATAL(host) shutdown((host)); - -extern int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip, - unsigned long base, int io_port, int irq, int dma, - long long options, int clock); - -#endif /* NCR53c710_C */ -#endif /* NCR53c710_H */ diff --git a/drivers/scsi/53c7xx.scr b/drivers/scsi/53c7xx.scr deleted file mode 100644 index 9c5694a2da8a..000000000000 --- a/drivers/scsi/53c7xx.scr +++ /dev/null @@ -1,1591 +0,0 @@ -#undef DEBUG -#undef EVENTS -#undef NO_SELECTION_TIMEOUT -#define BIG_ENDIAN - -; 53c710 driver. Modified from Drew Eckhardts driver -; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk] -; -; I have left the script for the 53c8xx family in here, as it is likely -; to be useful to see what I changed when bug hunting. - -; NCR 53c810 driver, main script -; Sponsored by -; iX Multiuser Multitasking Magazine -; hm@ix.de -; -; Copyright 1993, 1994, 1995 Drew Eckhardt -; Visionary Computing -; (Unix and Linux consulting and custom programming) -; drew@PoohSticks.ORG -; +1 (303) 786-7975 -; -; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. -; -; PRE-ALPHA -; -; For more information, please consult -; -; NCR 53C810 -; PCI-SCSI I/O Processor -; Data Manual -; -; NCR 53C710 -; SCSI I/O Processor -; Programmers Guide -; -; NCR Microelectronics -; 1635 Aeroplaza Drive -; Colorado Springs, CO 80916 -; 1+ (719) 578-3400 -; -; Toll free literature number -; +1 (800) 334-5454 -; -; IMPORTANT : This code is self modifying due to the limitations of -; the NCR53c7,8xx series chips. Persons debugging this code with -; the remote debugger should take this into account, and NOT set -; breakpoints in modified instructions. -; -; Design: -; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard -; microcontroller using a simple instruction set. -; -; So, to minimize the effects of interrupt latency, and to maximize -; throughput, this driver offloads the practical maximum amount -; of processing to the SCSI chip while still maintaining a common -; structure. -; -; Where tradeoffs were needed between efficiency on the older -; chips and the newer NCR53c800 series, the NCR53c800 series -; was chosen. -; -; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully -; automate SCSI transfers without host processor intervention, this -; isn't the case with the NCR53c710 and newer chips which allow -; -; - reads and writes to the internal registers from within the SCSI -; scripts, allowing the SCSI SCRIPTS(tm) code to save processor -; state so that multiple threads of execution are possible, and also -; provide an ALU for loop control, etc. -; -; - table indirect addressing for some instructions. This allows -; pointers to be located relative to the DSA ((Data Structure -; Address) register. -; -; These features make it possible to implement a mailbox style interface, -; where the same piece of code is run to handle I/O for multiple threads -; at once minimizing our need to relocate code. Since the NCR53c700/ -; NCR53c800 series have a unique combination of features, making a -; a standard ingoing/outgoing mailbox system, costly, I've modified it. -; -; - Mailboxes are a mixture of code and data. This lets us greatly -; simplify the NCR53c810 code and do things that would otherwise -; not be possible. -; -; The saved data pointer is now implemented as follows : -; -; Control flow has been architected such that if control reaches -; munge_save_data_pointer, on a restore pointers message or -; reconnection, a jump to the address formerly in the TEMP register -; will allow the SCSI command to resume execution. -; - -; -; Note : the DSA structures must be aligned on 32 bit boundaries, -; since the source and destination of MOVE MEMORY instructions -; must share the same alignment and this is the alignment of the -; NCR registers. -; - -; For some systems (MVME166, for example) dmode is always the same, so don't -; waste time writing it - -#if 1 -#define DMODE_MEMORY_TO_NCR -#define DMODE_MEMORY_TO_MEMORY -#define DMODE_NCR_TO_MEMORY -#else -#define DMODE_MEMORY_TO_NCR MOVE dmode_memory_to_ncr TO DMODE -#define DMODE_MEMORY_TO_MEMORY MOVE dmode_memory_to_memory TO DMODE -#define DMODE_NCR_TO_MEMORY MOVE dmode_ncr_to_memory TO DMODE -#endif - -ABSOLUTE dsa_temp_lun = 0 ; Patch to lun for current dsa -ABSOLUTE dsa_temp_next = 0 ; Patch to dsa next for current dsa -ABSOLUTE dsa_temp_addr_next = 0 ; Patch to address of dsa next address - ; for current dsa -ABSOLUTE dsa_temp_sync = 0 ; Patch to address of per-target - ; sync routine -ABSOLUTE dsa_sscf_710 = 0 ; Patch to address of per-target - ; sscf value (53c710) -ABSOLUTE dsa_temp_target = 0 ; Patch to id for current dsa -ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command - ; saved data pointer -ABSOLUTE dsa_temp_addr_residual = 0 ; Patch to address of per-command - ; current residual code -ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command - ; saved residual code -ABSOLUTE dsa_temp_addr_new_value = 0 ; Address of value for JUMP operand -ABSOLUTE dsa_temp_addr_array_value = 0 ; Address to copy to -ABSOLUTE dsa_temp_addr_dsa_value = 0 ; Address of this DSA value - -; -; Once a device has initiated reselection, we need to compare it -; against the singly linked list of commands which have disconnected -; and are pending reselection. These commands are maintained in -; an unordered singly linked list of DSA structures, through the -; DSA pointers at their 'centers' headed by the reconnect_dsa_head -; pointer. -; -; To avoid complications in removing commands from the list, -; I minimize the amount of expensive (at eight operations per -; addition @ 500-600ns each) pointer operations which must -; be done in the NCR driver by precomputing them on the -; host processor during dsa structure generation. -; -; The fixed-up per DSA code knows how to recognize the nexus -; associated with the corresponding SCSI command, and modifies -; the source and destination pointers for the MOVE MEMORY -; instruction which is executed when reselected_ok is called -; to remove the command from the list. Similarly, DSA is -; loaded with the address of the next DSA structure and -; reselected_check_next is called if a failure occurs. -; -; Perhaps more concisely, the net effect of the mess is -; -; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, -; src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) { -; src = &dsa->next; -; if (target_id == dsa->id && target_lun == dsa->lun) { -; *dest = *src; -; break; -; } -; } -; -; if (!dsa) -; error (int_err_unexpected_reselect); -; else -; longjmp (dsa->jump_resume, 0); -; -; - -#if (CHIP != 700) && (CHIP != 70066) -; Define DSA structure used for mailboxes -ENTRY dsa_code_template -dsa_code_template: -ENTRY dsa_code_begin -dsa_code_begin: -; RGH: Don't care about TEMP and DSA here - DMODE_MEMORY_TO_NCR - MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch - DMODE_MEMORY_TO_MEMORY -#if (CHIP == 710) - MOVE MEMORY 4, addr_scratch, saved_dsa - ; We are about to go and select the device, so must set SSCF bits - MOVE MEMORY 4, dsa_sscf_710, addr_scratch -#ifdef BIG_ENDIAN - MOVE SCRATCH3 TO SFBR -#else - MOVE SCRATCH0 TO SFBR -#endif - MOVE SFBR TO SBCL - MOVE MEMORY 4, saved_dsa, addr_dsa -#else - CALL scratch_to_dsa -#endif - CALL select -; Handle the phase mismatch which may have resulted from the -; MOVE FROM dsa_msgout if we returned here. The CLEAR ATN -; may or may not be necessary, and we should update script_asm.pl -; to handle multiple pieces. - CLEAR ATN - CLEAR ACK - -; Replace second operand with address of JUMP instruction dest operand -; in schedule table for this DSA. Becomes dsa_jump_dest in 53c7,8xx.c. -ENTRY dsa_code_fix_jump -dsa_code_fix_jump: - MOVE MEMORY 4, NOP_insn, 0 - JUMP select_done - -; wrong_dsa loads the DSA register with the value of the dsa_next -; field. -; -wrong_dsa: -#if (CHIP == 710) -; NOTE DSA is corrupt when we arrive here! -#endif -; Patch the MOVE MEMORY INSTRUCTION such that -; the destination address is the address of the OLD -; next pointer. -; - MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8 - DMODE_MEMORY_TO_NCR -; -; Move the _contents_ of the next pointer into the DSA register as -; the next I_T_L or I_T_L_Q tupple to check against the established -; nexus. -; - MOVE MEMORY 4, dsa_temp_next, addr_scratch - DMODE_MEMORY_TO_MEMORY -#if (CHIP == 710) - MOVE MEMORY 4, addr_scratch, saved_dsa - MOVE MEMORY 4, saved_dsa, addr_dsa -#else - CALL scratch_to_dsa -#endif - JUMP reselected_check_next - -ABSOLUTE dsa_save_data_pointer = 0 -ENTRY dsa_code_save_data_pointer -dsa_code_save_data_pointer: -#if (CHIP == 710) - ; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt - ; We MUST return with DSA correct - MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual - CLEAR ACK -#ifdef DEBUG - INT int_debug_saved -#endif - MOVE MEMORY 4, saved_dsa, addr_dsa - JUMP jump_temp -#else - DMODE_NCR_TO_MEMORY - MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer - DMODE_MEMORY_TO_MEMORY -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual - CLEAR ACK -#ifdef DEBUG - INT int_debug_saved -#endif - RETURN -#endif -ABSOLUTE dsa_restore_pointers = 0 -ENTRY dsa_code_restore_pointers -dsa_code_restore_pointers: -#if (CHIP == 710) - ; TEMP and DSA are corrupt when we get here, but who cares! - MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4 -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual - CLEAR ACK - ; Restore DSA, note we don't care about TEMP - MOVE MEMORY 4, saved_dsa, addr_dsa -#ifdef DEBUG - INT int_debug_restored -#endif - JUMP jump_temp -#else - DMODE_MEMORY_TO_NCR - MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp - DMODE_MEMORY_TO_MEMORY -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual - CLEAR ACK -#ifdef DEBUG - INT int_debug_restored -#endif - RETURN -#endif - -ABSOLUTE dsa_check_reselect = 0 -; dsa_check_reselect determines whether or not the current target and -; lun match the current DSA -ENTRY dsa_code_check_reselect -dsa_code_check_reselect: -#if (CHIP == 710) - /* Arrives here with DSA correct */ - /* Assumes we are always ID 7 */ - MOVE LCRC TO SFBR ; LCRC has our ID and his ID bits set - JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80 -#else - MOVE SSID TO SFBR ; SSID contains 3 bit target ID -; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips - JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8 -#endif -; -; Hack - move to scratch first, since SFBR is not writeable -; via the CPU and hence a MOVE MEMORY instruction. -; - DMODE_MEMORY_TO_NCR - MOVE MEMORY 1, reselected_identify, addr_scratch - DMODE_MEMORY_TO_MEMORY -#ifdef BIG_ENDIAN - ; BIG ENDIAN ON MVME16x - MOVE SCRATCH3 TO SFBR -#else - MOVE SCRATCH0 TO SFBR -#endif -; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips -; Are you sure about that? richard@sleepie.demon.co.uk - JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8 -; Patch the MOVE MEMORY INSTRUCTION such that -; the source address is the address of this dsa's -; next pointer. - MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4 - CALL reselected_ok -#if (CHIP == 710) -; Restore DSA following memory moves in reselected_ok -; dsa_temp_sync doesn't really care about DSA, but it has an -; optional debug INT so a valid DSA is a good idea. - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif - CALL dsa_temp_sync -; Release ACK on the IDENTIFY message _after_ we've set the synchronous -; transfer parameters! - CLEAR ACK -; Implicitly restore pointers on reselection, so a RETURN -; will transfer control back to the right spot. - CALL REL (dsa_code_restore_pointers) - RETURN -ENTRY dsa_zero -dsa_zero: -ENTRY dsa_code_template_end -dsa_code_template_end: - -; Perform sanity check for dsa_fields_start == dsa_code_template_end - -; dsa_zero, puke. - -ABSOLUTE dsa_fields_start = 0 ; Sanity marker - ; pad 48 bytes (fix this RSN) -ABSOLUTE dsa_next = 48 ; len 4 Next DSA - ; del 4 Previous DSA address -ABSOLUTE dsa_cmnd = 56 ; len 4 Scsi_Cmnd * for this thread. -ABSOLUTE dsa_select = 60 ; len 4 Device ID, Period, Offset for - ; table indirect select -ABSOLUTE dsa_msgout = 64 ; len 8 table indirect move parameter for - ; select message -ABSOLUTE dsa_cmdout = 72 ; len 8 table indirect move parameter for - ; command -ABSOLUTE dsa_dataout = 80 ; len 4 code pointer for dataout -ABSOLUTE dsa_datain = 84 ; len 4 code pointer for datain -ABSOLUTE dsa_msgin = 88 ; len 8 table indirect move for msgin -ABSOLUTE dsa_status = 96 ; len 8 table indirect move for status byte -ABSOLUTE dsa_msgout_other = 104 ; len 8 table indirect for normal message out - ; (Synchronous transfer negotiation, etc). -ABSOLUTE dsa_end = 112 - -ABSOLUTE schedule = 0 ; Array of JUMP dsa_begin or JUMP (next), - ; terminated by a call to JUMP wait_reselect - -; Linked lists of DSA structures -ABSOLUTE reconnect_dsa_head = 0 ; Link list of DSAs which can reconnect -ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing - ; address of reconnect_dsa_head - -; These select the source and destination of a MOVE MEMORY instruction -ABSOLUTE dmode_memory_to_memory = 0x0 -ABSOLUTE dmode_memory_to_ncr = 0x0 -ABSOLUTE dmode_ncr_to_memory = 0x0 - -ABSOLUTE addr_scratch = 0x0 -ABSOLUTE addr_temp = 0x0 -#if (CHIP == 710) -ABSOLUTE saved_dsa = 0x0 -ABSOLUTE emulfly = 0x0 -ABSOLUTE addr_dsa = 0x0 -#endif -#endif /* CHIP != 700 && CHIP != 70066 */ - -; Interrupts - -; MSB indicates type -; 0 handle error condition -; 1 handle message -; 2 handle normal condition -; 3 debugging interrupt -; 4 testing interrupt -; Next byte indicates specific error - -; XXX not yet implemented, I'm not sure if I want to - -; Next byte indicates the routine the error occurred in -; The LSB indicates the specific place the error occurred - -ABSOLUTE int_err_unexpected_phase = 0x00000000 ; Unexpected phase encountered -ABSOLUTE int_err_selected = 0x00010000 ; SELECTED (nee RESELECTED) -ABSOLUTE int_err_unexpected_reselect = 0x00020000 -ABSOLUTE int_err_check_condition = 0x00030000 -ABSOLUTE int_err_no_phase = 0x00040000 -ABSOLUTE int_msg_wdtr = 0x01000000 ; WDTR message received -ABSOLUTE int_msg_sdtr = 0x01010000 ; SDTR received -ABSOLUTE int_msg_1 = 0x01020000 ; single byte special message - ; received - -ABSOLUTE int_norm_select_complete = 0x02000000 ; Select complete, reprogram - ; registers. -ABSOLUTE int_norm_reselect_complete = 0x02010000 ; Nexus established -ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete -ABSOLUTE int_norm_disconnected = 0x02030000 ; Disconnected -ABSOLUTE int_norm_aborted =0x02040000 ; Aborted *dsa -ABSOLUTE int_norm_reset = 0x02050000 ; Generated BUS reset. -ABSOLUTE int_norm_emulateintfly = 0x02060000 ; 53C710 Emulated intfly -ABSOLUTE int_debug_break = 0x03000000 ; Break point -#ifdef DEBUG -ABSOLUTE int_debug_scheduled = 0x03010000 ; new I/O scheduled -ABSOLUTE int_debug_idle = 0x03020000 ; scheduler is idle -ABSOLUTE int_debug_dsa_loaded = 0x03030000 ; dsa reloaded -ABSOLUTE int_debug_reselected = 0x03040000 ; NCR reselected -ABSOLUTE int_debug_head = 0x03050000 ; issue head overwritten -ABSOLUTE int_debug_disconnected = 0x03060000 ; disconnected -ABSOLUTE int_debug_disconnect_msg = 0x03070000 ; got message to disconnect -ABSOLUTE int_debug_dsa_schedule = 0x03080000 ; in dsa_schedule -ABSOLUTE int_debug_reselect_check = 0x03090000 ; Check for reselection of DSA -ABSOLUTE int_debug_reselected_ok = 0x030a0000 ; Reselection accepted -#endif -ABSOLUTE int_debug_panic = 0x030b0000 ; Panic driver -#ifdef DEBUG -ABSOLUTE int_debug_saved = 0x030c0000 ; save/restore pointers -ABSOLUTE int_debug_restored = 0x030d0000 -ABSOLUTE int_debug_sync = 0x030e0000 ; Sanity check synchronous - ; parameters. -ABSOLUTE int_debug_datain = 0x030f0000 ; going into data in phase - ; now. -ABSOLUTE int_debug_check_dsa = 0x03100000 ; Sanity check DSA against - ; SDID. -#endif - -ABSOLUTE int_test_1 = 0x04000000 ; Test 1 complete -ABSOLUTE int_test_2 = 0x04010000 ; Test 2 complete -ABSOLUTE int_test_3 = 0x04020000 ; Test 3 complete - - -; These should start with 0x05000000, with low bits incrementing for -; each one. - -#ifdef EVENTS -ABSOLUTE int_EVENT_SELECT = 0 -ABSOLUTE int_EVENT_DISCONNECT = 0 -ABSOLUTE int_EVENT_RESELECT = 0 -ABSOLUTE int_EVENT_COMPLETE = 0 -ABSOLUTE int_EVENT_IDLE = 0 -ABSOLUTE int_EVENT_SELECT_FAILED = 0 -ABSOLUTE int_EVENT_BEFORE_SELECT = 0 -ABSOLUTE int_EVENT_RESELECT_FAILED = 0 -#endif - -ABSOLUTE NCR53c7xx_msg_abort = 0 ; Pointer to abort message -ABSOLUTE NCR53c7xx_msg_reject = 0 ; Pointer to reject message -ABSOLUTE NCR53c7xx_zero = 0 ; long with zero in it, use for source -ABSOLUTE NCR53c7xx_sink = 0 ; long to dump worthless data in -ABSOLUTE NOP_insn = 0 ; NOP instruction - -; Pointer to message, potentially multi-byte -ABSOLUTE msg_buf = 0 - -; Pointer to holding area for reselection information -ABSOLUTE reselected_identify = 0 -ABSOLUTE reselected_tag = 0 - -; Request sense command pointer, it's a 6 byte command, should -; be constant for all commands since we always want 16 bytes of -; sense and we don't need to change any fields as we did under -; SCSI-I when we actually cared about the LUN field. -;EXTERNAL NCR53c7xx_sense ; Request sense command - -#if (CHIP != 700) && (CHIP != 70066) -; dsa_schedule -; PURPOSE : after a DISCONNECT message has been received, and pointers -; saved, insert the current DSA structure at the head of the -; disconnected queue and fall through to the scheduler. -; -; CALLS : OK -; -; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list -; of disconnected commands -; -; MODIFIES : SCRATCH, reconnect_dsa_head -; -; EXITS : always passes control to schedule - -ENTRY dsa_schedule -dsa_schedule: -#ifdef DEBUG - INT int_debug_dsa_schedule -#endif - -; -; Calculate the address of the next pointer within the DSA -; structure of the command that is currently disconnecting -; -#if (CHIP == 710) - ; Read what should be the current DSA from memory - actual DSA - ; register is probably corrupt - MOVE MEMORY 4, saved_dsa, addr_scratch -#else - CALL dsa_to_scratch -#endif - MOVE SCRATCH0 + dsa_next TO SCRATCH0 - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -; Point the next field of this DSA structure at the current disconnected -; list - DMODE_NCR_TO_MEMORY - MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8 - DMODE_MEMORY_TO_MEMORY -dsa_schedule_insert: - MOVE MEMORY 4, reconnect_dsa_head, 0 - -; And update the head pointer. -#if (CHIP == 710) - ; Read what should be the current DSA from memory - actual DSA - ; register is probably corrupt - MOVE MEMORY 4, saved_dsa, addr_scratch -#else - CALL dsa_to_scratch -#endif - DMODE_NCR_TO_MEMORY - MOVE MEMORY 4, addr_scratch, reconnect_dsa_head - DMODE_MEMORY_TO_MEMORY -/* Temporarily, see what happens. */ -#ifndef ORIGINAL -#if (CHIP != 710) - MOVE SCNTL2 & 0x7f TO SCNTL2 -#endif - CLEAR ACK -#endif -#if (CHIP == 710) - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif - WAIT DISCONNECT -#ifdef EVENTS - INT int_EVENT_DISCONNECT; -#endif -#ifdef DEBUG - INT int_debug_disconnected -#endif - JUMP schedule -#endif - -; -; select -; -; PURPOSE : establish a nexus for the SCSI command referenced by DSA. -; On success, the current DSA structure is removed from the issue -; queue. Usually, this is entered as a fall-through from schedule, -; although the contingent allegiance handling code will write -; the select entry address to the DSP to restart a command as a -; REQUEST SENSE. A message is sent (usually IDENTIFY, although -; additional SDTR or WDTR messages may be sent). COMMAND OUT -; is handled. -; -; INPUTS : DSA - SCSI command, issue_dsa_head -; -; CALLS : NOT OK -; -; MODIFIES : SCRATCH, issue_dsa_head -; -; EXITS : on reselection or selection, go to select_failed -; otherwise, RETURN so control is passed back to -; dsa_begin. -; - -ENTRY select -select: - -#ifdef EVENTS - INT int_EVENT_BEFORE_SELECT -#endif - -#ifdef DEBUG - INT int_debug_scheduled -#endif - CLEAR TARGET - -; XXX -; -; In effect, SELECTION operations are backgrounded, with execution -; continuing until code which waits for REQ or a fatal interrupt is -; encountered. -; -; So, for more performance, we could overlap the code which removes -; the command from the NCRs issue queue with the selection, but -; at this point I don't want to deal with the error recovery. -; - -#if (CHIP != 700) && (CHIP != 70066) -#if (CHIP == 710) - ; Enable selection timer -#ifdef NO_SELECTION_TIMEOUT - MOVE CTEST7 & 0xff TO CTEST7 -#else - MOVE CTEST7 & 0xef TO CTEST7 -#endif -#endif - SELECT ATN FROM dsa_select, select_failed - JUMP select_msgout, WHEN MSG_OUT -ENTRY select_msgout -select_msgout: -#if (CHIP == 710) - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 -#endif - MOVE FROM dsa_msgout, WHEN MSG_OUT -#else -ENTRY select_msgout - SELECT ATN 0, select_failed -select_msgout: - MOVE 0, 0, WHEN MSGOUT -#endif - -#ifdef EVENTS - INT int_EVENT_SELECT -#endif - RETURN - -; -; select_done -; -; PURPOSE: continue on to normal data transfer; called as the exit -; point from dsa_begin. -; -; INPUTS: dsa -; -; CALLS: OK -; -; - -select_done: -#if (CHIP == 710) -; NOTE DSA is corrupt when we arrive here! - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif - -#ifdef DEBUG -ENTRY select_check_dsa -select_check_dsa: - INT int_debug_check_dsa -#endif - -; After a successful selection, we should get either a CMD phase or -; some transfer request negotiation message. - - JUMP cmdout, WHEN CMD - INT int_err_unexpected_phase, WHEN NOT MSG_IN - -select_msg_in: - CALL msg_in, WHEN MSG_IN - JUMP select_msg_in, WHEN MSG_IN - -cmdout: - INT int_err_unexpected_phase, WHEN NOT CMD -#if (CHIP == 700) - INT int_norm_selected -#endif -ENTRY cmdout_cmdout -cmdout_cmdout: -#if (CHIP != 700) && (CHIP != 70066) - MOVE FROM dsa_cmdout, WHEN CMD -#else - MOVE 0, 0, WHEN CMD -#endif /* (CHIP != 700) && (CHIP != 70066) */ - -; -; data_transfer -; other_out -; other_in -; other_transfer -; -; PURPOSE : handle the main data transfer for a SCSI command in -; several parts. In the first part, data_transfer, DATA_IN -; and DATA_OUT phases are allowed, with the user provided -; code (usually dynamically generated based on the scatter/gather -; list associated with a SCSI command) called to handle these -; phases. -; -; After control has passed to one of the user provided -; DATA_IN or DATA_OUT routines, back calls are made to -; other_transfer_in or other_transfer_out to handle non-DATA IN -; and DATA OUT phases respectively, with the state of the active -; data pointer being preserved in TEMP. -; -; On completion, the user code passes control to other_transfer -; which causes DATA_IN and DATA_OUT to result in unexpected_phase -; interrupts so that data overruns may be trapped. -; -; INPUTS : DSA - SCSI command -; -; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in -; other_transfer -; -; MODIFIES : SCRATCH -; -; EXITS : if STATUS IN is detected, signifying command completion, -; the NCR jumps to command_complete. If MSG IN occurs, a -; CALL is made to msg_in. Otherwise, other_transfer runs in -; an infinite loop. -; - -ENTRY data_transfer -data_transfer: - JUMP cmdout_cmdout, WHEN CMD - CALL msg_in, WHEN MSG_IN - INT int_err_unexpected_phase, WHEN MSG_OUT - JUMP do_dataout, WHEN DATA_OUT - JUMP do_datain, WHEN DATA_IN - JUMP command_complete, WHEN STATUS - JUMP data_transfer -ENTRY end_data_transfer -end_data_transfer: - -; -; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain -; should be fixed up whenever the nexus changes so it can point to the -; correct routine for that command. -; - -#if (CHIP != 700) && (CHIP != 70066) -; Nasty jump to dsa->dataout -do_dataout: -#if (CHIP == 710) - MOVE MEMORY 4, saved_dsa, addr_scratch -#else - CALL dsa_to_scratch -#endif - MOVE SCRATCH0 + dsa_dataout TO SCRATCH0 - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - DMODE_NCR_TO_MEMORY - MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4 - DMODE_MEMORY_TO_MEMORY -dataout_to_jump: - MOVE MEMORY 4, 0, dataout_jump + 4 -#if (CHIP == 710) - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif -dataout_jump: - JUMP 0 - -; Nasty jump to dsa->dsain -do_datain: -#if (CHIP == 710) - MOVE MEMORY 4, saved_dsa, addr_scratch -#else - CALL dsa_to_scratch -#endif - MOVE SCRATCH0 + dsa_datain TO SCRATCH0 - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - DMODE_NCR_TO_MEMORY - MOVE MEMORY 4, addr_scratch, datain_to_jump + 4 - DMODE_MEMORY_TO_MEMORY -ENTRY datain_to_jump -datain_to_jump: - MOVE MEMORY 4, 0, datain_jump + 4 -#if (CHIP == 710) - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif -#ifdef DEBUG - INT int_debug_datain -#endif -datain_jump: - JUMP 0 -#endif /* (CHIP != 700) && (CHIP != 70066) */ - - -; Note that other_out and other_in loop until a non-data phase -; is discovered, so we only execute return statements when we -; can go on to the next data phase block move statement. - -ENTRY other_out -other_out: -#if 0 - INT 0x03ffdead -#endif - INT int_err_unexpected_phase, WHEN CMD - JUMP msg_in_restart, WHEN MSG_IN - INT int_err_unexpected_phase, WHEN MSG_OUT - INT int_err_unexpected_phase, WHEN DATA_IN - JUMP command_complete, WHEN STATUS - JUMP other_out, WHEN NOT DATA_OUT -#if (CHIP == 710) -; TEMP should be OK, as we got here from a call in the user dataout code. -#endif - RETURN - -ENTRY other_in -other_in: -#if 0 - INT 0x03ffdead -#endif - INT int_err_unexpected_phase, WHEN CMD - JUMP msg_in_restart, WHEN MSG_IN - INT int_err_unexpected_phase, WHEN MSG_OUT - INT int_err_unexpected_phase, WHEN DATA_OUT - JUMP command_complete, WHEN STATUS - JUMP other_in, WHEN NOT DATA_IN -#if (CHIP == 710) -; TEMP should be OK, as we got here from a call in the user datain code. -#endif - RETURN - - -ENTRY other_transfer -other_transfer: - INT int_err_unexpected_phase, WHEN CMD - CALL msg_in, WHEN MSG_IN - INT int_err_unexpected_phase, WHEN MSG_OUT - INT int_err_unexpected_phase, WHEN DATA_OUT - INT int_err_unexpected_phase, WHEN DATA_IN - JUMP command_complete, WHEN STATUS - JUMP other_transfer - -; -; msg_in_restart -; msg_in -; munge_msg -; -; PURPOSE : process messages from a target. msg_in is called when the -; caller hasn't read the first byte of the message. munge_message -; is called when the caller has read the first byte of the message, -; and left it in SFBR. msg_in_restart is called when the caller -; hasn't read the first byte of the message, and wishes RETURN -; to transfer control back to the address of the conditional -; CALL instruction rather than to the instruction after it. -; -; Various int_* interrupts are generated when the host system -; needs to intervene, as is the case with SDTR, WDTR, and -; INITIATE RECOVERY messages. -; -; When the host system handles one of these interrupts, -; it can respond by reentering at reject_message, -; which rejects the message and returns control to -; the caller of msg_in or munge_msg, accept_message -; which clears ACK and returns control, or reply_message -; which sends the message pointed to by the DSA -; msgout_other table indirect field. -; -; DISCONNECT messages are handled by moving the command -; to the reconnect_dsa_queue. -#if (CHIP == 710) -; NOTE: DSA should be valid when we get here - we cannot save both it -; and TEMP in this routine. -#endif -; -; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg -; only) -; -; CALLS : NO. The TEMP register isn't backed up to allow nested calls. -; -; MODIFIES : SCRATCH, DSA on DISCONNECT -; -; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS, -; and normal return from message handlers running under -; Linux, control is returned to the caller. Receipt -; of DISCONNECT messages pass control to dsa_schedule. -; -ENTRY msg_in_restart -msg_in_restart: -; XXX - hackish -; -; Since it's easier to debug changes to the statically -; compiled code, rather than the dynamically generated -; stuff, such as -; -; MOVE x, y, WHEN data_phase -; CALL other_z, WHEN NOT data_phase -; MOVE x, y, WHEN data_phase -; -; I'd like to have certain routines (notably the message handler) -; restart on the conditional call rather than the next instruction. -; -; So, subtract 8 from the return address - - MOVE TEMP0 + 0xf8 TO TEMP0 - MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY - MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY - MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY - -ENTRY msg_in -msg_in: - MOVE 1, msg_buf, WHEN MSG_IN - -munge_msg: - JUMP munge_extended, IF 0x01 ; EXTENDED MESSAGE - JUMP munge_2, IF 0x20, AND MASK 0xdf ; two byte message -; -; XXX - I've seen a handful of broken SCSI devices which fail to issue -; a SAVE POINTERS message before disconnecting in the middle of -; a transfer, assuming that the DATA POINTER will be implicitly -; restored. -; -; Historically, I've often done an implicit save when the DISCONNECT -; message is processed. We may want to consider having the option of -; doing that here. -; - JUMP munge_save_data_pointer, IF 0x02 ; SAVE DATA POINTER - JUMP munge_restore_pointers, IF 0x03 ; RESTORE POINTERS - JUMP munge_disconnect, IF 0x04 ; DISCONNECT - INT int_msg_1, IF 0x07 ; MESSAGE REJECT - INT int_msg_1, IF 0x0f ; INITIATE RECOVERY -#ifdef EVENTS - INT int_EVENT_SELECT_FAILED -#endif - JUMP reject_message - -munge_2: - JUMP reject_message -; -; The SCSI standard allows targets to recover from transient -; error conditions by backing up the data pointer with a -; RESTORE POINTERS message. -; -; So, we must save and restore the _residual_ code as well as -; the current instruction pointer. Because of this messiness, -; it is simpler to put dynamic code in the dsa for this and to -; just do a simple jump down there. -; - -munge_save_data_pointer: -#if (CHIP == 710) - ; We have something in TEMP here, so first we must save that - MOVE TEMP0 TO SFBR - MOVE SFBR TO SCRATCH0 - MOVE TEMP1 TO SFBR - MOVE SFBR TO SCRATCH1 - MOVE TEMP2 TO SFBR - MOVE SFBR TO SCRATCH2 - MOVE TEMP3 TO SFBR - MOVE SFBR TO SCRATCH3 - MOVE MEMORY 4, addr_scratch, jump_temp + 4 - ; Now restore DSA - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif - MOVE DSA0 + dsa_save_data_pointer TO SFBR - MOVE SFBR TO SCRATCH0 - MOVE DSA1 + 0xff TO SFBR WITH CARRY - MOVE SFBR TO SCRATCH1 - MOVE DSA2 + 0xff TO SFBR WITH CARRY - MOVE SFBR TO SCRATCH2 - MOVE DSA3 + 0xff TO SFBR WITH CARRY - MOVE SFBR TO SCRATCH3 - - DMODE_NCR_TO_MEMORY - MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4 - DMODE_MEMORY_TO_MEMORY -jump_dsa_save: - JUMP 0 - -munge_restore_pointers: -#if (CHIP == 710) - ; The code at dsa_restore_pointers will RETURN, but we don't care - ; about TEMP here, as it will overwrite it anyway. -#endif - MOVE DSA0 + dsa_restore_pointers TO SFBR - MOVE SFBR TO SCRATCH0 - MOVE DSA1 + 0xff TO SFBR WITH CARRY - MOVE SFBR TO SCRATCH1 - MOVE DSA2 + 0xff TO SFBR WITH CARRY - MOVE SFBR TO SCRATCH2 - MOVE DSA3 + 0xff TO SFBR WITH CARRY - MOVE SFBR TO SCRATCH3 - - DMODE_NCR_TO_MEMORY - MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4 - DMODE_MEMORY_TO_MEMORY -jump_dsa_restore: - JUMP 0 - - -munge_disconnect: -#ifdef DEBUG - INT int_debug_disconnect_msg -#endif - -/* - * Before, we overlapped processing with waiting for disconnect, but - * debugging was beginning to appear messy. Temporarily move things - * to just before the WAIT DISCONNECT. - */ - -#ifdef ORIGINAL -#if (CHIP == 710) -; Following clears Unexpected Disconnect bit. What do we do? -#else - MOVE SCNTL2 & 0x7f TO SCNTL2 -#endif - CLEAR ACK -#endif - -#if (CHIP != 700) && (CHIP != 70066) - JUMP dsa_schedule -#else - WAIT DISCONNECT - INT int_norm_disconnected -#endif - -munge_extended: - CLEAR ACK - INT int_err_unexpected_phase, WHEN NOT MSG_IN - MOVE 1, msg_buf + 1, WHEN MSG_IN - JUMP munge_extended_2, IF 0x02 - JUMP munge_extended_3, IF 0x03 - JUMP reject_message - -munge_extended_2: - CLEAR ACK - MOVE 1, msg_buf + 2, WHEN MSG_IN - JUMP reject_message, IF NOT 0x02 ; Must be WDTR - CLEAR ACK - MOVE 1, msg_buf + 3, WHEN MSG_IN - INT int_msg_wdtr - -munge_extended_3: - CLEAR ACK - MOVE 1, msg_buf + 2, WHEN MSG_IN - JUMP reject_message, IF NOT 0x01 ; Must be SDTR - CLEAR ACK - MOVE 2, msg_buf + 3, WHEN MSG_IN - INT int_msg_sdtr - -ENTRY reject_message -reject_message: - SET ATN - CLEAR ACK - MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT - RETURN - -ENTRY accept_message -accept_message: - CLEAR ATN - CLEAR ACK - RETURN - -ENTRY respond_message -respond_message: - SET ATN - CLEAR ACK - MOVE FROM dsa_msgout_other, WHEN MSG_OUT - RETURN - -; -; command_complete -; -; PURPOSE : handle command termination when STATUS IN is detected by reading -; a status byte followed by a command termination message. -; -; Normal termination results in an INTFLY instruction, and -; the host system can pick out which command terminated by -; examining the MESSAGE and STATUS buffers of all currently -; executing commands; -; -; Abnormal (CHECK_CONDITION) termination results in an -; int_err_check_condition interrupt so that a REQUEST SENSE -; command can be issued out-of-order so that no other command -; clears the contingent allegiance condition. -; -; -; INPUTS : DSA - command -; -; CALLS : OK -; -; EXITS : On successful termination, control is passed to schedule. -; On abnormal termination, the user will usually modify the -; DSA fields and corresponding buffers and return control -; to select. -; - -ENTRY command_complete -command_complete: - MOVE FROM dsa_status, WHEN STATUS -#if (CHIP != 700) && (CHIP != 70066) - MOVE SFBR TO SCRATCH0 ; Save status -#endif /* (CHIP != 700) && (CHIP != 70066) */ -ENTRY command_complete_msgin -command_complete_msgin: - MOVE FROM dsa_msgin, WHEN MSG_IN -; Indicate that we should be expecting a disconnect -#if (CHIP != 710) - MOVE SCNTL2 & 0x7f TO SCNTL2 -#else - ; Above code cleared the Unexpected Disconnect bit, what do we do? -#endif - CLEAR ACK -#if (CHIP != 700) && (CHIP != 70066) - WAIT DISCONNECT - -; -; The SCSI specification states that when a UNIT ATTENTION condition -; is pending, as indicated by a CHECK CONDITION status message, -; the target shall revert to asynchronous transfers. Since -; synchronous transfers parameters are maintained on a per INITIATOR/TARGET -; basis, and returning control to our scheduler could work on a command -; running on another lun on that target using the old parameters, we must -; interrupt the host processor to get them changed, or change them ourselves. -; -; Once SCSI-II tagged queueing is implemented, things will be even more -; hairy, since contingent allegiance conditions exist on a per-target/lun -; basis, and issuing a new command with a different tag would clear it. -; In these cases, we must interrupt the host processor to get a request -; added to the HEAD of the queue with the request sense command, or we -; must automatically issue the request sense command. - -#if 0 - MOVE SCRATCH0 TO SFBR - JUMP command_failed, IF 0x02 -#endif -#if (CHIP == 710) -#if defined(MVME16x_INTFLY) -; For MVME16x (ie CHIP=710) we will force an INTFLY by triggering a software -; interrupt (SW7). We can use SCRATCH, as we are about to jump to -; schedule, which corrupts it anyway. Will probably remove this later, -; but want to check performance effects first. - -#define INTFLY_ADDR 0xfff40070 - - MOVE 0 TO SCRATCH0 - MOVE 0x80 TO SCRATCH1 - MOVE 0 TO SCRATCH2 - MOVE 0 TO SCRATCH3 - MOVE MEMORY 4, addr_scratch, INTFLY_ADDR -#else - INT int_norm_emulateintfly -#endif -#else - INTFLY -#endif -#endif /* (CHIP != 700) && (CHIP != 70066) */ -#if (CHIP == 710) - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif -#ifdef EVENTS - INT int_EVENT_COMPLETE -#endif -#if (CHIP != 700) && (CHIP != 70066) - JUMP schedule -command_failed: - INT int_err_check_condition -#else - INT int_norm_command_complete -#endif - -; -; wait_reselect -; -; PURPOSE : This is essentially the idle routine, where control lands -; when there are no new processes to schedule. wait_reselect -; waits for reselection, selection, and new commands. -; -; When a successful reselection occurs, with the aid -; of fixed up code in each DSA, wait_reselect walks the -; reconnect_dsa_queue, asking each dsa if the target ID -; and LUN match its. -; -; If a match is found, a call is made back to reselected_ok, -; which through the miracles of self modifying code, extracts -; the found DSA from the reconnect_dsa_queue and then -; returns control to the DSAs thread of execution. -; -; INPUTS : NONE -; -; CALLS : OK -; -; MODIFIES : DSA, -; -; EXITS : On successful reselection, control is returned to the -; DSA which called reselected_ok. If the WAIT RESELECT -; was interrupted by a new commands arrival signaled by -; SIG_P, control is passed to schedule. If the NCR is -; selected, the host system is interrupted with an -; int_err_selected which is usually responded to by -; setting DSP to the target_abort address. - -ENTRY wait_reselect -wait_reselect: -#ifdef EVENTS - int int_EVENT_IDLE -#endif -#ifdef DEBUG - int int_debug_idle -#endif - WAIT RESELECT wait_reselect_failed - -reselected: -#ifdef EVENTS - int int_EVENT_RESELECT -#endif - CLEAR TARGET - DMODE_MEMORY_TO_MEMORY - ; Read all data needed to reestablish the nexus - - MOVE 1, reselected_identify, WHEN MSG_IN - ; We used to CLEAR ACK here. -#if (CHIP != 700) && (CHIP != 70066) -#ifdef DEBUG - int int_debug_reselected -#endif - - ; Point DSA at the current head of the disconnected queue. - DMODE_MEMORY_TO_NCR - MOVE MEMORY 4, reconnect_dsa_head, addr_scratch - DMODE_MEMORY_TO_MEMORY -#if (CHIP == 710) - MOVE MEMORY 4, addr_scratch, saved_dsa -#else - CALL scratch_to_dsa -#endif - - ; Fix the update-next pointer so that the reconnect_dsa_head - ; pointer is the one that will be updated if this DSA is a hit - ; and we remove it from the queue. - - MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8 -#if (CHIP == 710) - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif - -ENTRY reselected_check_next -reselected_check_next: -#ifdef DEBUG - INT int_debug_reselect_check -#endif - ; Check for a NULL pointer. - MOVE DSA0 TO SFBR - JUMP reselected_not_end, IF NOT 0 - MOVE DSA1 TO SFBR - JUMP reselected_not_end, IF NOT 0 - MOVE DSA2 TO SFBR - JUMP reselected_not_end, IF NOT 0 - MOVE DSA3 TO SFBR - JUMP reselected_not_end, IF NOT 0 - INT int_err_unexpected_reselect - -reselected_not_end: - ; - ; XXX the ALU is only eight bits wide, and the assembler - ; wont do the dirt work for us. As long as dsa_check_reselect - ; is negative, we need to sign extend with 1 bits to the full - ; 32 bit width of the address. - ; - ; A potential work around would be to have a known alignment - ; of the DSA structure such that the base address plus - ; dsa_check_reselect doesn't require carrying from bytes - ; higher than the LSB. - ; - - MOVE DSA0 TO SFBR - MOVE SFBR + dsa_check_reselect TO SCRATCH0 - MOVE DSA1 TO SFBR - MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY - MOVE DSA2 TO SFBR - MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY - MOVE DSA3 TO SFBR - MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY - - DMODE_NCR_TO_MEMORY - MOVE MEMORY 4, addr_scratch, reselected_check + 4 - DMODE_MEMORY_TO_MEMORY -#if (CHIP == 710) - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa -#endif -reselected_check: - JUMP 0 - - -; -; -#if (CHIP == 710) -; We have problems here - the memory move corrupts TEMP and DSA. This -; routine is called from DSA code, and patched from many places. Scratch -; is probably free when it is called. -; We have to: -; copy temp to scratch, one byte at a time -; write scratch to patch a jump in place of the return -; do the move memory -; jump to the patched in return address -; DSA is corrupt when we get here, and can be left corrupt - -ENTRY reselected_ok -reselected_ok: - MOVE TEMP0 TO SFBR - MOVE SFBR TO SCRATCH0 - MOVE TEMP1 TO SFBR - MOVE SFBR TO SCRATCH1 - MOVE TEMP2 TO SFBR - MOVE SFBR TO SCRATCH2 - MOVE TEMP3 TO SFBR - MOVE SFBR TO SCRATCH3 - MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4 -reselected_ok_patch: - MOVE MEMORY 4, 0, 0 -reselected_ok_jump: - JUMP 0 -#else -ENTRY reselected_ok -reselected_ok: -reselected_ok_patch: - MOVE MEMORY 4, 0, 0 ; Patched : first word - ; is address of - ; successful dsa_next - ; Second word is last - ; unsuccessful dsa_next, - ; starting with - ; dsa_reconnect_head - ; We used to CLEAR ACK here. -#ifdef DEBUG - INT int_debug_reselected_ok -#endif -#ifdef DEBUG - INT int_debug_check_dsa -#endif - RETURN ; Return control to where -#endif -#else - INT int_norm_reselected -#endif /* (CHIP != 700) && (CHIP != 70066) */ - -selected: - INT int_err_selected; - -; -; A select or reselect failure can be caused by one of two conditions : -; 1. SIG_P was set. This will be the case if the user has written -; a new value to a previously NULL head of the issue queue. -; -; 2. The NCR53c810 was selected or reselected by another device. -; -; 3. The bus was already busy since we were selected or reselected -; before starting the command. - -wait_reselect_failed: -#ifdef EVENTS - INT int_EVENT_RESELECT_FAILED -#endif -; Check selected bit. -#if (CHIP == 710) - ; Must work out how to tell if we are selected.... -#else - MOVE SIST0 & 0x20 TO SFBR - JUMP selected, IF 0x20 -#endif -; Reading CTEST2 clears the SIG_P bit in the ISTAT register. - MOVE CTEST2 & 0x40 TO SFBR - JUMP schedule, IF 0x40 -; Check connected bit. -; FIXME: this needs to change if we support target mode - MOVE ISTAT & 0x08 TO SFBR - JUMP reselected, IF 0x08 -; FIXME : Something bogus happened, and we shouldn't fail silently. -#if 0 - JUMP schedule -#else - INT int_debug_panic -#endif - - -select_failed: -#if (CHIP == 710) - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 -#endif -#ifdef EVENTS - int int_EVENT_SELECT_FAILED -#endif -; Otherwise, mask the selected and reselected bits off SIST0 -#if (CHIP ==710) - ; Let's assume we don't get selected for now - MOVE SSTAT0 & 0x10 TO SFBR -#else - MOVE SIST0 & 0x30 TO SFBR - JUMP selected, IF 0x20 -#endif - JUMP reselected, IF 0x10 -; If SIGP is set, the user just gave us another command, and -; we should restart or return to the scheduler. -; Reading CTEST2 clears the SIG_P bit in the ISTAT register. - MOVE CTEST2 & 0x40 TO SFBR - JUMP select, IF 0x40 -; Check connected bit. -; FIXME: this needs to change if we support target mode -; FIXME: is this really necessary? - MOVE ISTAT & 0x08 TO SFBR - JUMP reselected, IF 0x08 -; FIXME : Something bogus happened, and we shouldn't fail silently. -#if 0 - JUMP schedule -#else - INT int_debug_panic -#endif - -; -; test_1 -; test_2 -; -; PURPOSE : run some verification tests on the NCR. test_1 -; copies test_src to test_dest and interrupts the host -; processor, testing for cache coherency and interrupt -; problems in the processes. -; -; test_2 runs a command with offsets relative to the -; DSA on entry, and is useful for miscellaneous experimentation. -; - -; Verify that interrupts are working correctly and that we don't -; have a cache invalidation problem. - -ABSOLUTE test_src = 0, test_dest = 0 -ENTRY test_1 -test_1: - MOVE MEMORY 4, test_src, test_dest - INT int_test_1 - -; -; Run arbitrary commands, with test code establishing a DSA -; - -ENTRY test_2 -test_2: - CLEAR TARGET -#if (CHIP == 710) - ; Enable selection timer -#ifdef NO_SELECTION_TIMEOUT - MOVE CTEST7 & 0xff TO CTEST7 -#else - MOVE CTEST7 & 0xef TO CTEST7 -#endif -#endif - SELECT ATN FROM 0, test_2_fail - JUMP test_2_msgout, WHEN MSG_OUT -ENTRY test_2_msgout -test_2_msgout: -#if (CHIP == 710) - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 -#endif - MOVE FROM 8, WHEN MSG_OUT - MOVE FROM 16, WHEN CMD - MOVE FROM 24, WHEN DATA_IN - MOVE FROM 32, WHEN STATUS - MOVE FROM 40, WHEN MSG_IN -#if (CHIP != 710) - MOVE SCNTL2 & 0x7f TO SCNTL2 -#endif - CLEAR ACK - WAIT DISCONNECT -test_2_fail: -#if (CHIP == 710) - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 -#endif - INT int_test_2 - -ENTRY debug_break -debug_break: - INT int_debug_break - -; -; initiator_abort -; target_abort -; -; PURPOSE : Abort the currently established nexus from with initiator -; or target mode. -; -; - -ENTRY target_abort -target_abort: - SET TARGET - DISCONNECT - CLEAR TARGET - JUMP schedule - -ENTRY initiator_abort -initiator_abort: - SET ATN -; -; The SCSI-I specification says that targets may go into MSG out at -; their leisure upon receipt of the ATN single. On all versions of the -; specification, we can't change phases until REQ transitions true->false, -; so we need to sink/source one byte of data to allow the transition. -; -; For the sake of safety, we'll only source one byte of data in all -; cases, but to accommodate the SCSI-I dain bramage, we'll sink an -; arbitrary number of bytes. - JUMP spew_cmd, WHEN CMD - JUMP eat_msgin, WHEN MSG_IN - JUMP eat_datain, WHEN DATA_IN - JUMP eat_status, WHEN STATUS - JUMP spew_dataout, WHEN DATA_OUT - JUMP sated -spew_cmd: - MOVE 1, NCR53c7xx_zero, WHEN CMD - JUMP sated -eat_msgin: - MOVE 1, NCR53c7xx_sink, WHEN MSG_IN - JUMP eat_msgin, WHEN MSG_IN - JUMP sated -eat_status: - MOVE 1, NCR53c7xx_sink, WHEN STATUS - JUMP eat_status, WHEN STATUS - JUMP sated -eat_datain: - MOVE 1, NCR53c7xx_sink, WHEN DATA_IN - JUMP eat_datain, WHEN DATA_IN - JUMP sated -spew_dataout: - MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT -sated: -#if (CHIP != 710) - MOVE SCNTL2 & 0x7f TO SCNTL2 -#endif - MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT - WAIT DISCONNECT - INT int_norm_aborted - -#if (CHIP != 710) -; -; dsa_to_scratch -; scratch_to_dsa -; -; PURPOSE : -; The NCR chips cannot do a move memory instruction with the DSA register -; as the source or destination. So, we provide a couple of subroutines -; that let us switch between the DSA register and scratch register. -; -; Memory moves to/from the DSPS register also don't work, but we -; don't use them. -; -; - - -dsa_to_scratch: - MOVE DSA0 TO SFBR - MOVE SFBR TO SCRATCH0 - MOVE DSA1 TO SFBR - MOVE SFBR TO SCRATCH1 - MOVE DSA2 TO SFBR - MOVE SFBR TO SCRATCH2 - MOVE DSA3 TO SFBR - MOVE SFBR TO SCRATCH3 - RETURN - -scratch_to_dsa: - MOVE SCRATCH0 TO SFBR - MOVE SFBR TO DSA0 - MOVE SCRATCH1 TO SFBR - MOVE SFBR TO DSA1 - MOVE SCRATCH2 TO SFBR - MOVE SFBR TO DSA2 - MOVE SCRATCH3 TO SFBR - MOVE SFBR TO DSA3 - RETURN -#endif - -#if (CHIP == 710) -; Little patched jump, used to overcome problems with TEMP getting -; corrupted on memory moves. - -jump_temp: - JUMP 0 -#endif diff --git a/drivers/scsi/53c7xx_d.h_shipped b/drivers/scsi/53c7xx_d.h_shipped deleted file mode 100644 index 21d31b08ec31..000000000000 --- a/drivers/scsi/53c7xx_d.h_shipped +++ /dev/null @@ -1,2874 +0,0 @@ -/* DO NOT EDIT - Generated automatically by script_asm.pl */ -static u32 SCRIPT[] = { -/* - - - - - -; 53c710 driver. Modified from Drew Eckhardts driver -; for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk] -; -; I have left the script for the 53c8xx family in here, as it is likely -; to be useful to see what I changed when bug hunting. - -; NCR 53c810 driver, main script -; Sponsored by -; iX Multiuser Multitasking Magazine -; hm@ix.de -; -; Copyright 1993, 1994, 1995 Drew Eckhardt -; Visionary Computing -; (Unix and Linux consulting and custom programming) -; drew@PoohSticks.ORG -; +1 (303) 786-7975 -; -; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. -; -; PRE-ALPHA -; -; For more information, please consult -; -; NCR 53C810 -; PCI-SCSI I/O Processor -; Data Manual -; -; NCR 53C710 -; SCSI I/O Processor -; Programmers Guide -; -; NCR Microelectronics -; 1635 Aeroplaza Drive -; Colorado Springs, CO 80916 -; 1+ (719) 578-3400 -; -; Toll free literature number -; +1 (800) 334-5454 -; -; IMPORTANT : This code is self modifying due to the limitations of -; the NCR53c7,8xx series chips. Persons debugging this code with -; the remote debugger should take this into account, and NOT set -; breakpoints in modified instructions. -; -; Design: -; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard -; microcontroller using a simple instruction set. -; -; So, to minimize the effects of interrupt latency, and to maximize -; throughput, this driver offloads the practical maximum amount -; of processing to the SCSI chip while still maintaining a common -; structure. -; -; Where tradeoffs were needed between efficiency on the older -; chips and the newer NCR53c800 series, the NCR53c800 series -; was chosen. -; -; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully -; automate SCSI transfers without host processor intervention, this -; isn't the case with the NCR53c710 and newer chips which allow -; -; - reads and writes to the internal registers from within the SCSI -; scripts, allowing the SCSI SCRIPTS(tm) code to save processor -; state so that multiple threads of execution are possible, and also -; provide an ALU for loop control, etc. -; -; - table indirect addressing for some instructions. This allows -; pointers to be located relative to the DSA ((Data Structure -; Address) register. -; -; These features make it possible to implement a mailbox style interface, -; where the same piece of code is run to handle I/O for multiple threads -; at once minimizing our need to relocate code. Since the NCR53c700/ -; NCR53c800 series have a unique combination of features, making a -; a standard ingoing/outgoing mailbox system, costly, I've modified it. -; -; - Mailboxes are a mixture of code and data. This lets us greatly -; simplify the NCR53c810 code and do things that would otherwise -; not be possible. -; -; The saved data pointer is now implemented as follows : -; -; Control flow has been architected such that if control reaches -; munge_save_data_pointer, on a restore pointers message or -; reconnection, a jump to the address formerly in the TEMP register -; will allow the SCSI command to resume execution. -; - -; -; Note : the DSA structures must be aligned on 32 bit boundaries, -; since the source and destination of MOVE MEMORY instructions -; must share the same alignment and this is the alignment of the -; NCR registers. -; - -; For some systems (MVME166, for example) dmode is always the same, so don't -; waste time writing it - - - - - - - - - - - -ABSOLUTE dsa_temp_lun = 0 ; Patch to lun for current dsa -ABSOLUTE dsa_temp_next = 0 ; Patch to dsa next for current dsa -ABSOLUTE dsa_temp_addr_next = 0 ; Patch to address of dsa next address - ; for current dsa -ABSOLUTE dsa_temp_sync = 0 ; Patch to address of per-target - ; sync routine -ABSOLUTE dsa_sscf_710 = 0 ; Patch to address of per-target - ; sscf value (53c710) -ABSOLUTE dsa_temp_target = 0 ; Patch to id for current dsa -ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command - ; saved data pointer -ABSOLUTE dsa_temp_addr_residual = 0 ; Patch to address of per-command - ; current residual code -ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command - ; saved residual code -ABSOLUTE dsa_temp_addr_new_value = 0 ; Address of value for JUMP operand -ABSOLUTE dsa_temp_addr_array_value = 0 ; Address to copy to -ABSOLUTE dsa_temp_addr_dsa_value = 0 ; Address of this DSA value - -; -; Once a device has initiated reselection, we need to compare it -; against the singly linked list of commands which have disconnected -; and are pending reselection. These commands are maintained in -; an unordered singly linked list of DSA structures, through the -; DSA pointers at their 'centers' headed by the reconnect_dsa_head -; pointer. -; -; To avoid complications in removing commands from the list, -; I minimize the amount of expensive (at eight operations per -; addition @ 500-600ns each) pointer operations which must -; be done in the NCR driver by precomputing them on the -; host processor during dsa structure generation. -; -; The fixed-up per DSA code knows how to recognize the nexus -; associated with the corresponding SCSI command, and modifies -; the source and destination pointers for the MOVE MEMORY -; instruction which is executed when reselected_ok is called -; to remove the command from the list. Similarly, DSA is -; loaded with the address of the next DSA structure and -; reselected_check_next is called if a failure occurs. -; -; Perhaps more concisely, the net effect of the mess is -; -; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, -; src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) { -; src = &dsa->next; -; if (target_id == dsa->id && target_lun == dsa->lun) { -; *dest = *src; -; break; -; } -; } -; -; if (!dsa) -; error (int_err_unexpected_reselect); -; else -; longjmp (dsa->jump_resume, 0); -; -; - - -; Define DSA structure used for mailboxes -ENTRY dsa_code_template -dsa_code_template: -ENTRY dsa_code_begin -dsa_code_begin: -; RGH: Don't care about TEMP and DSA here - - MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch - -at 0x00000000 : */ 0xc0000004,0x00000000,0x00000000, -/* - - - MOVE MEMORY 4, addr_scratch, saved_dsa - -at 0x00000003 : */ 0xc0000004,0x00000000,0x00000000, -/* - ; We are about to go and select the device, so must set SSCF bits - MOVE MEMORY 4, dsa_sscf_710, addr_scratch - -at 0x00000006 : */ 0xc0000004,0x00000000,0x00000000, -/* - - MOVE SCRATCH3 TO SFBR - -at 0x00000009 : */ 0x72370000,0x00000000, -/* - - - - MOVE SFBR TO SBCL - -at 0x0000000b : */ 0x6a0b0000,0x00000000, -/* - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x0000000d : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - CALL select - -at 0x00000010 : */ 0x88080000,0x000001f8, -/* -; Handle the phase mismatch which may have resulted from the -; MOVE FROM dsa_msgout if we returned here. The CLEAR ATN -; may or may not be necessary, and we should update script_asm.pl -; to handle multiple pieces. - CLEAR ATN - -at 0x00000012 : */ 0x60000008,0x00000000, -/* - CLEAR ACK - -at 0x00000014 : */ 0x60000040,0x00000000, -/* - -; Replace second operand with address of JUMP instruction dest operand -; in schedule table for this DSA. Becomes dsa_jump_dest in 53c7,8xx.c. -ENTRY dsa_code_fix_jump -dsa_code_fix_jump: - MOVE MEMORY 4, NOP_insn, 0 - -at 0x00000016 : */ 0xc0000004,0x00000000,0x00000000, -/* - JUMP select_done - -at 0x00000019 : */ 0x80080000,0x00000230, -/* - -; wrong_dsa loads the DSA register with the value of the dsa_next -; field. -; -wrong_dsa: - -; NOTE DSA is corrupt when we arrive here! - -; Patch the MOVE MEMORY INSTRUCTION such that -; the destination address is the address of the OLD -; next pointer. -; - MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 8 - -at 0x0000001b : */ 0xc0000004,0x00000000,0x000007ec, -/* - -; -; Move the _contents_ of the next pointer into the DSA register as -; the next I_T_L or I_T_L_Q tupple to check against the established -; nexus. -; - MOVE MEMORY 4, dsa_temp_next, addr_scratch - -at 0x0000001e : */ 0xc0000004,0x00000000,0x00000000, -/* - - - MOVE MEMORY 4, addr_scratch, saved_dsa - -at 0x00000021 : */ 0xc0000004,0x00000000,0x00000000, -/* - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x00000024 : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - JUMP reselected_check_next - -at 0x00000027 : */ 0x80080000,0x000006f0, -/* - -ABSOLUTE dsa_save_data_pointer = 0 -ENTRY dsa_code_save_data_pointer -dsa_code_save_data_pointer: - - ; When we get here, TEMP has been saved in jump_temp+4, DSA is corrupt - ; We MUST return with DSA correct - MOVE MEMORY 4, jump_temp+4, dsa_temp_addr_saved_pointer - -at 0x00000029 : */ 0xc0000004,0x000009c8,0x00000000, -/* -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual - -at 0x0000002c : */ 0xc0000018,0x00000000,0x00000000, -/* - CLEAR ACK - -at 0x0000002f : */ 0x60000040,0x00000000, -/* - - - - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x00000031 : */ 0xc0000004,0x00000000,0x00000000, -/* - JUMP jump_temp - -at 0x00000034 : */ 0x80080000,0x000009c4, -/* - -ABSOLUTE dsa_restore_pointers = 0 -ENTRY dsa_code_restore_pointers -dsa_code_restore_pointers: - - ; TEMP and DSA are corrupt when we get here, but who cares! - MOVE MEMORY 4, dsa_temp_addr_saved_pointer, jump_temp + 4 - -at 0x00000036 : */ 0xc0000004,0x00000000,0x000009c8, -/* -; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h - MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual - -at 0x00000039 : */ 0xc0000018,0x00000000,0x00000000, -/* - CLEAR ACK - -at 0x0000003c : */ 0x60000040,0x00000000, -/* - ; Restore DSA, note we don't care about TEMP - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x0000003e : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - JUMP jump_temp - -at 0x00000041 : */ 0x80080000,0x000009c4, -/* - - -ABSOLUTE dsa_check_reselect = 0 -; dsa_check_reselect determines whether or not the current target and -; lun match the current DSA -ENTRY dsa_code_check_reselect -dsa_code_check_reselect: - - - - MOVE LCRC TO SFBR ; LCRC has our ID and his ID bits set - -at 0x00000043 : */ 0x72230000,0x00000000, -/* - JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0x80 - -at 0x00000045 : */ 0x80848000,0x00ffff50, -/* - - - - - -; -; Hack - move to scratch first, since SFBR is not writeable -; via the CPU and hence a MOVE MEMORY instruction. -; - - MOVE MEMORY 1, reselected_identify, addr_scratch - -at 0x00000047 : */ 0xc0000001,0x00000000,0x00000000, -/* - - - ; BIG ENDIAN ON MVME16x - MOVE SCRATCH3 TO SFBR - -at 0x0000004a : */ 0x72370000,0x00000000, -/* - - - -; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips -; Are you sure about that? richard@sleepie.demon.co.uk - JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8 - -at 0x0000004c : */ 0x8084f800,0x00ffff34, -/* -; Patch the MOVE MEMORY INSTRUCTION such that -; the source address is the address of this dsa's -; next pointer. - MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok_patch + 4 - -at 0x0000004e : */ 0xc0000004,0x00000000,0x000007e8, -/* - CALL reselected_ok - -at 0x00000051 : */ 0x88080000,0x00000798, -/* - -; Restore DSA following memory moves in reselected_ok -; dsa_temp_sync doesn't really care about DSA, but it has an -; optional debug INT so a valid DSA is a good idea. - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x00000053 : */ 0xc0000004,0x00000000,0x00000000, -/* - - CALL dsa_temp_sync - -at 0x00000056 : */ 0x88080000,0x00000000, -/* -; Release ACK on the IDENTIFY message _after_ we've set the synchronous -; transfer parameters! - CLEAR ACK - -at 0x00000058 : */ 0x60000040,0x00000000, -/* -; Implicitly restore pointers on reselection, so a RETURN -; will transfer control back to the right spot. - CALL REL (dsa_code_restore_pointers) - -at 0x0000005a : */ 0x88880000,0x00ffff68, -/* - RETURN - -at 0x0000005c : */ 0x90080000,0x00000000, -/* -ENTRY dsa_zero -dsa_zero: -ENTRY dsa_code_template_end -dsa_code_template_end: - -; Perform sanity check for dsa_fields_start == dsa_code_template_end - -; dsa_zero, puke. - -ABSOLUTE dsa_fields_start = 0 ; Sanity marker - ; pad 48 bytes (fix this RSN) -ABSOLUTE dsa_next = 48 ; len 4 Next DSA - ; del 4 Previous DSA address -ABSOLUTE dsa_cmnd = 56 ; len 4 Scsi_Cmnd * for this thread. -ABSOLUTE dsa_select = 60 ; len 4 Device ID, Period, Offset for - ; table indirect select -ABSOLUTE dsa_msgout = 64 ; len 8 table indirect move parameter for - ; select message -ABSOLUTE dsa_cmdout = 72 ; len 8 table indirect move parameter for - ; command -ABSOLUTE dsa_dataout = 80 ; len 4 code pointer for dataout -ABSOLUTE dsa_datain = 84 ; len 4 code pointer for datain -ABSOLUTE dsa_msgin = 88 ; len 8 table indirect move for msgin -ABSOLUTE dsa_status = 96 ; len 8 table indirect move for status byte -ABSOLUTE dsa_msgout_other = 104 ; len 8 table indirect for normal message out - ; (Synchronous transfer negotiation, etc). -ABSOLUTE dsa_end = 112 - -ABSOLUTE schedule = 0 ; Array of JUMP dsa_begin or JUMP (next), - ; terminated by a call to JUMP wait_reselect - -; Linked lists of DSA structures -ABSOLUTE reconnect_dsa_head = 0 ; Link list of DSAs which can reconnect -ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing - ; address of reconnect_dsa_head - -; These select the source and destination of a MOVE MEMORY instruction -ABSOLUTE dmode_memory_to_memory = 0x0 -ABSOLUTE dmode_memory_to_ncr = 0x0 -ABSOLUTE dmode_ncr_to_memory = 0x0 - -ABSOLUTE addr_scratch = 0x0 -ABSOLUTE addr_temp = 0x0 - -ABSOLUTE saved_dsa = 0x0 -ABSOLUTE emulfly = 0x0 -ABSOLUTE addr_dsa = 0x0 - - - -; Interrupts - -; MSB indicates type -; 0 handle error condition -; 1 handle message -; 2 handle normal condition -; 3 debugging interrupt -; 4 testing interrupt -; Next byte indicates specific error - -; XXX not yet implemented, I'm not sure if I want to - -; Next byte indicates the routine the error occurred in -; The LSB indicates the specific place the error occurred - -ABSOLUTE int_err_unexpected_phase = 0x00000000 ; Unexpected phase encountered -ABSOLUTE int_err_selected = 0x00010000 ; SELECTED (nee RESELECTED) -ABSOLUTE int_err_unexpected_reselect = 0x00020000 -ABSOLUTE int_err_check_condition = 0x00030000 -ABSOLUTE int_err_no_phase = 0x00040000 -ABSOLUTE int_msg_wdtr = 0x01000000 ; WDTR message received -ABSOLUTE int_msg_sdtr = 0x01010000 ; SDTR received -ABSOLUTE int_msg_1 = 0x01020000 ; single byte special message - ; received - -ABSOLUTE int_norm_select_complete = 0x02000000 ; Select complete, reprogram - ; registers. -ABSOLUTE int_norm_reselect_complete = 0x02010000 ; Nexus established -ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete -ABSOLUTE int_norm_disconnected = 0x02030000 ; Disconnected -ABSOLUTE int_norm_aborted =0x02040000 ; Aborted *dsa -ABSOLUTE int_norm_reset = 0x02050000 ; Generated BUS reset. -ABSOLUTE int_norm_emulateintfly = 0x02060000 ; 53C710 Emulated intfly -ABSOLUTE int_debug_break = 0x03000000 ; Break point - -ABSOLUTE int_debug_panic = 0x030b0000 ; Panic driver - - -ABSOLUTE int_test_1 = 0x04000000 ; Test 1 complete -ABSOLUTE int_test_2 = 0x04010000 ; Test 2 complete -ABSOLUTE int_test_3 = 0x04020000 ; Test 3 complete - - -; These should start with 0x05000000, with low bits incrementing for -; each one. - - - -ABSOLUTE NCR53c7xx_msg_abort = 0 ; Pointer to abort message -ABSOLUTE NCR53c7xx_msg_reject = 0 ; Pointer to reject message -ABSOLUTE NCR53c7xx_zero = 0 ; long with zero in it, use for source -ABSOLUTE NCR53c7xx_sink = 0 ; long to dump worthless data in -ABSOLUTE NOP_insn = 0 ; NOP instruction - -; Pointer to message, potentially multi-byte -ABSOLUTE msg_buf = 0 - -; Pointer to holding area for reselection information -ABSOLUTE reselected_identify = 0 -ABSOLUTE reselected_tag = 0 - -; Request sense command pointer, it's a 6 byte command, should -; be constant for all commands since we always want 16 bytes of -; sense and we don't need to change any fields as we did under -; SCSI-I when we actually cared about the LUN field. -;EXTERNAL NCR53c7xx_sense ; Request sense command - - -; dsa_schedule -; PURPOSE : after a DISCONNECT message has been received, and pointers -; saved, insert the current DSA structure at the head of the -; disconnected queue and fall through to the scheduler. -; -; CALLS : OK -; -; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list -; of disconnected commands -; -; MODIFIES : SCRATCH, reconnect_dsa_head -; -; EXITS : always passes control to schedule - -ENTRY dsa_schedule -dsa_schedule: - - - - -; -; Calculate the address of the next pointer within the DSA -; structure of the command that is currently disconnecting -; - - ; Read what should be the current DSA from memory - actual DSA - ; register is probably corrupt - MOVE MEMORY 4, saved_dsa, addr_scratch - -at 0x0000005e : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - MOVE SCRATCH0 + dsa_next TO SCRATCH0 - -at 0x00000061 : */ 0x7e343000,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x00000063 : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x00000065 : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x00000067 : */ 0x7f370000,0x00000000, -/* - -; Point the next field of this DSA structure at the current disconnected -; list - - MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8 - -at 0x00000069 : */ 0xc0000004,0x00000000,0x000001b8, -/* - -dsa_schedule_insert: - MOVE MEMORY 4, reconnect_dsa_head, 0 - -at 0x0000006c : */ 0xc0000004,0x00000000,0x00000000, -/* - -; And update the head pointer. - - ; Read what should be the current DSA from memory - actual DSA - ; register is probably corrupt - MOVE MEMORY 4, saved_dsa, addr_scratch - -at 0x0000006f : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - - MOVE MEMORY 4, addr_scratch, reconnect_dsa_head - -at 0x00000072 : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - - - - CLEAR ACK - -at 0x00000075 : */ 0x60000040,0x00000000, -/* - - - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x00000077 : */ 0xc0000004,0x00000000,0x00000000, -/* - - WAIT DISCONNECT - -at 0x0000007a : */ 0x48000000,0x00000000, -/* - - - - - - - JUMP schedule - -at 0x0000007c : */ 0x80080000,0x00000000, -/* - - -; -; select -; -; PURPOSE : establish a nexus for the SCSI command referenced by DSA. -; On success, the current DSA structure is removed from the issue -; queue. Usually, this is entered as a fall-through from schedule, -; although the contingent allegiance handling code will write -; the select entry address to the DSP to restart a command as a -; REQUEST SENSE. A message is sent (usually IDENTIFY, although -; additional SDTR or WDTR messages may be sent). COMMAND OUT -; is handled. -; -; INPUTS : DSA - SCSI command, issue_dsa_head -; -; CALLS : NOT OK -; -; MODIFIES : SCRATCH, issue_dsa_head -; -; EXITS : on reselection or selection, go to select_failed -; otherwise, RETURN so control is passed back to -; dsa_begin. -; - -ENTRY select -select: - - - - - - - - - CLEAR TARGET - -at 0x0000007e : */ 0x60000200,0x00000000, -/* - -; XXX -; -; In effect, SELECTION operations are backgrounded, with execution -; continuing until code which waits for REQ or a fatal interrupt is -; encountered. -; -; So, for more performance, we could overlap the code which removes -; the command from the NCRs issue queue with the selection, but -; at this point I don't want to deal with the error recovery. -; - - - - ; Enable selection timer - - - - MOVE CTEST7 & 0xef TO CTEST7 - -at 0x00000080 : */ 0x7c1bef00,0x00000000, -/* - - - SELECT ATN FROM dsa_select, select_failed - -at 0x00000082 : */ 0x4300003c,0x00000828, -/* - JUMP select_msgout, WHEN MSG_OUT - -at 0x00000084 : */ 0x860b0000,0x00000218, -/* -ENTRY select_msgout -select_msgout: - - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 - -at 0x00000086 : */ 0x7a1b1000,0x00000000, -/* - - MOVE FROM dsa_msgout, WHEN MSG_OUT - -at 0x00000088 : */ 0x1e000000,0x00000040, -/* - - - - - - - - - - - RETURN - -at 0x0000008a : */ 0x90080000,0x00000000, -/* - -; -; select_done -; -; PURPOSE: continue on to normal data transfer; called as the exit -; point from dsa_begin. -; -; INPUTS: dsa -; -; CALLS: OK -; -; - -select_done: - -; NOTE DSA is corrupt when we arrive here! - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x0000008c : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - - - - - -; After a successful selection, we should get either a CMD phase or -; some transfer request negotiation message. - - JUMP cmdout, WHEN CMD - -at 0x0000008f : */ 0x820b0000,0x0000025c, -/* - INT int_err_unexpected_phase, WHEN NOT MSG_IN - -at 0x00000091 : */ 0x9f030000,0x00000000, -/* - -select_msg_in: - CALL msg_in, WHEN MSG_IN - -at 0x00000093 : */ 0x8f0b0000,0x0000041c, -/* - JUMP select_msg_in, WHEN MSG_IN - -at 0x00000095 : */ 0x870b0000,0x0000024c, -/* - -cmdout: - INT int_err_unexpected_phase, WHEN NOT CMD - -at 0x00000097 : */ 0x9a030000,0x00000000, -/* - - - -ENTRY cmdout_cmdout -cmdout_cmdout: - - MOVE FROM dsa_cmdout, WHEN CMD - -at 0x00000099 : */ 0x1a000000,0x00000048, -/* - - - - -; -; data_transfer -; other_out -; other_in -; other_transfer -; -; PURPOSE : handle the main data transfer for a SCSI command in -; several parts. In the first part, data_transfer, DATA_IN -; and DATA_OUT phases are allowed, with the user provided -; code (usually dynamically generated based on the scatter/gather -; list associated with a SCSI command) called to handle these -; phases. -; -; After control has passed to one of the user provided -; DATA_IN or DATA_OUT routines, back calls are made to -; other_transfer_in or other_transfer_out to handle non-DATA IN -; and DATA OUT phases respectively, with the state of the active -; data pointer being preserved in TEMP. -; -; On completion, the user code passes control to other_transfer -; which causes DATA_IN and DATA_OUT to result in unexpected_phase -; interrupts so that data overruns may be trapped. -; -; INPUTS : DSA - SCSI command -; -; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in -; other_transfer -; -; MODIFIES : SCRATCH -; -; EXITS : if STATUS IN is detected, signifying command completion, -; the NCR jumps to command_complete. If MSG IN occurs, a -; CALL is made to msg_in. Otherwise, other_transfer runs in -; an infinite loop. -; - -ENTRY data_transfer -data_transfer: - JUMP cmdout_cmdout, WHEN CMD - -at 0x0000009b : */ 0x820b0000,0x00000264, -/* - CALL msg_in, WHEN MSG_IN - -at 0x0000009d : */ 0x8f0b0000,0x0000041c, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x0000009f : */ 0x9e0b0000,0x00000000, -/* - JUMP do_dataout, WHEN DATA_OUT - -at 0x000000a1 : */ 0x800b0000,0x000002a4, -/* - JUMP do_datain, WHEN DATA_IN - -at 0x000000a3 : */ 0x810b0000,0x000002fc, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000a5 : */ 0x830b0000,0x0000065c, -/* - JUMP data_transfer - -at 0x000000a7 : */ 0x80080000,0x0000026c, -/* -ENTRY end_data_transfer -end_data_transfer: - -; -; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain -; should be fixed up whenever the nexus changes so it can point to the -; correct routine for that command. -; - - -; Nasty jump to dsa->dataout -do_dataout: - - MOVE MEMORY 4, saved_dsa, addr_scratch - -at 0x000000a9 : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - MOVE SCRATCH0 + dsa_dataout TO SCRATCH0 - -at 0x000000ac : */ 0x7e345000,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x000000ae : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x000000b0 : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x000000b2 : */ 0x7f370000,0x00000000, -/* - - MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4 - -at 0x000000b4 : */ 0xc0000004,0x00000000,0x000002e0, -/* - -dataout_to_jump: - MOVE MEMORY 4, 0, dataout_jump + 4 - -at 0x000000b7 : */ 0xc0000004,0x00000000,0x000002f8, -/* - - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x000000ba : */ 0xc0000004,0x00000000,0x00000000, -/* - -dataout_jump: - JUMP 0 - -at 0x000000bd : */ 0x80080000,0x00000000, -/* - -; Nasty jump to dsa->dsain -do_datain: - - MOVE MEMORY 4, saved_dsa, addr_scratch - -at 0x000000bf : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - MOVE SCRATCH0 + dsa_datain TO SCRATCH0 - -at 0x000000c2 : */ 0x7e345400,0x00000000, -/* - MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY - -at 0x000000c4 : */ 0x7f350000,0x00000000, -/* - MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY - -at 0x000000c6 : */ 0x7f360000,0x00000000, -/* - MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY - -at 0x000000c8 : */ 0x7f370000,0x00000000, -/* - - MOVE MEMORY 4, addr_scratch, datain_to_jump + 4 - -at 0x000000ca : */ 0xc0000004,0x00000000,0x00000338, -/* - -ENTRY datain_to_jump -datain_to_jump: - MOVE MEMORY 4, 0, datain_jump + 4 - -at 0x000000cd : */ 0xc0000004,0x00000000,0x00000350, -/* - - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x000000d0 : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - -datain_jump: - JUMP 0 - -at 0x000000d3 : */ 0x80080000,0x00000000, -/* - - - -; Note that other_out and other_in loop until a non-data phase -; is discovered, so we only execute return statements when we -; can go on to the next data phase block move statement. - -ENTRY other_out -other_out: - - - - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000d5 : */ 0x9a0b0000,0x00000000, -/* - JUMP msg_in_restart, WHEN MSG_IN - -at 0x000000d7 : */ 0x870b0000,0x000003fc, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000d9 : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_IN - -at 0x000000db : */ 0x990b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000dd : */ 0x830b0000,0x0000065c, -/* - JUMP other_out, WHEN NOT DATA_OUT - -at 0x000000df : */ 0x80030000,0x00000354, -/* - -; TEMP should be OK, as we got here from a call in the user dataout code. - - RETURN - -at 0x000000e1 : */ 0x90080000,0x00000000, -/* - -ENTRY other_in -other_in: - - - - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000e3 : */ 0x9a0b0000,0x00000000, -/* - JUMP msg_in_restart, WHEN MSG_IN - -at 0x000000e5 : */ 0x870b0000,0x000003fc, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000e7 : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_OUT - -at 0x000000e9 : */ 0x980b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000eb : */ 0x830b0000,0x0000065c, -/* - JUMP other_in, WHEN NOT DATA_IN - -at 0x000000ed : */ 0x81030000,0x0000038c, -/* - -; TEMP should be OK, as we got here from a call in the user datain code. - - RETURN - -at 0x000000ef : */ 0x90080000,0x00000000, -/* - - -ENTRY other_transfer -other_transfer: - INT int_err_unexpected_phase, WHEN CMD - -at 0x000000f1 : */ 0x9a0b0000,0x00000000, -/* - CALL msg_in, WHEN MSG_IN - -at 0x000000f3 : */ 0x8f0b0000,0x0000041c, -/* - INT int_err_unexpected_phase, WHEN MSG_OUT - -at 0x000000f5 : */ 0x9e0b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_OUT - -at 0x000000f7 : */ 0x980b0000,0x00000000, -/* - INT int_err_unexpected_phase, WHEN DATA_IN - -at 0x000000f9 : */ 0x990b0000,0x00000000, -/* - JUMP command_complete, WHEN STATUS - -at 0x000000fb : */ 0x830b0000,0x0000065c, -/* - JUMP other_transfer - -at 0x000000fd : */ 0x80080000,0x000003c4, -/* - -; -; msg_in_restart -; msg_in -; munge_msg -; -; PURPOSE : process messages from a target. msg_in is called when the -; caller hasn't read the first byte of the message. munge_message -; is called when the caller has read the first byte of the message, -; and left it in SFBR. msg_in_restart is called when the caller -; hasn't read the first byte of the message, and wishes RETURN -; to transfer control back to the address of the conditional -; CALL instruction rather than to the instruction after it. -; -; Various int_* interrupts are generated when the host system -; needs to intervene, as is the case with SDTR, WDTR, and -; INITIATE RECOVERY messages. -; -; When the host system handles one of these interrupts, -; it can respond by reentering at reject_message, -; which rejects the message and returns control to -; the caller of msg_in or munge_msg, accept_message -; which clears ACK and returns control, or reply_message -; which sends the message pointed to by the DSA -; msgout_other table indirect field. -; -; DISCONNECT messages are handled by moving the command -; to the reconnect_dsa_queue. - -; NOTE: DSA should be valid when we get here - we cannot save both it -; and TEMP in this routine. - -; -; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg -; only) -; -; CALLS : NO. The TEMP register isn't backed up to allow nested calls. -; -; MODIFIES : SCRATCH, DSA on DISCONNECT -; -; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS, -; and normal return from message handlers running under -; Linux, control is returned to the caller. Receipt -; of DISCONNECT messages pass control to dsa_schedule. -; -ENTRY msg_in_restart -msg_in_restart: -; XXX - hackish -; -; Since it's easier to debug changes to the statically -; compiled code, rather than the dynamically generated -; stuff, such as -; -; MOVE x, y, WHEN data_phase -; CALL other_z, WHEN NOT data_phase -; MOVE x, y, WHEN data_phase -; -; I'd like to have certain routines (notably the message handler) -; restart on the conditional call rather than the next instruction. -; -; So, subtract 8 from the return address - - MOVE TEMP0 + 0xf8 TO TEMP0 - -at 0x000000ff : */ 0x7e1cf800,0x00000000, -/* - MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY - -at 0x00000101 : */ 0x7f1dff00,0x00000000, -/* - MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY - -at 0x00000103 : */ 0x7f1eff00,0x00000000, -/* - MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY - -at 0x00000105 : */ 0x7f1fff00,0x00000000, -/* - -ENTRY msg_in -msg_in: - MOVE 1, msg_buf, WHEN MSG_IN - -at 0x00000107 : */ 0x0f000001,0x00000000, -/* - -munge_msg: - JUMP munge_extended, IF 0x01 ; EXTENDED MESSAGE - -at 0x00000109 : */ 0x800c0001,0x00000574, -/* - JUMP munge_2, IF 0x20, AND MASK 0xdf ; two byte message - -at 0x0000010b : */ 0x800cdf20,0x00000464, -/* -; -; XXX - I've seen a handful of broken SCSI devices which fail to issue -; a SAVE POINTERS message before disconnecting in the middle of -; a transfer, assuming that the DATA POINTER will be implicitly -; restored. -; -; Historically, I've often done an implicit save when the DISCONNECT -; message is processed. We may want to consider having the option of -; doing that here. -; - JUMP munge_save_data_pointer, IF 0x02 ; SAVE DATA POINTER - -at 0x0000010d : */ 0x800c0002,0x0000046c, -/* - JUMP munge_restore_pointers, IF 0x03 ; RESTORE POINTERS - -at 0x0000010f : */ 0x800c0003,0x00000518, -/* - JUMP munge_disconnect, IF 0x04 ; DISCONNECT - -at 0x00000111 : */ 0x800c0004,0x0000056c, -/* - INT int_msg_1, IF 0x07 ; MESSAGE REJECT - -at 0x00000113 : */ 0x980c0007,0x01020000, -/* - INT int_msg_1, IF 0x0f ; INITIATE RECOVERY - -at 0x00000115 : */ 0x980c000f,0x01020000, -/* - - - - JUMP reject_message - -at 0x00000117 : */ 0x80080000,0x00000604, -/* - -munge_2: - JUMP reject_message - -at 0x00000119 : */ 0x80080000,0x00000604, -/* -; -; The SCSI standard allows targets to recover from transient -; error conditions by backing up the data pointer with a -; RESTORE POINTERS message. -; -; So, we must save and restore the _residual_ code as well as -; the current instruction pointer. Because of this messiness, -; it is simpler to put dynamic code in the dsa for this and to -; just do a simple jump down there. -; - -munge_save_data_pointer: - - ; We have something in TEMP here, so first we must save that - MOVE TEMP0 TO SFBR - -at 0x0000011b : */ 0x721c0000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x0000011d : */ 0x6a340000,0x00000000, -/* - MOVE TEMP1 TO SFBR - -at 0x0000011f : */ 0x721d0000,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x00000121 : */ 0x6a350000,0x00000000, -/* - MOVE TEMP2 TO SFBR - -at 0x00000123 : */ 0x721e0000,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x00000125 : */ 0x6a360000,0x00000000, -/* - MOVE TEMP3 TO SFBR - -at 0x00000127 : */ 0x721f0000,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x00000129 : */ 0x6a370000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, jump_temp + 4 - -at 0x0000012b : */ 0xc0000004,0x00000000,0x000009c8, -/* - ; Now restore DSA - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x0000012e : */ 0xc0000004,0x00000000,0x00000000, -/* - - MOVE DSA0 + dsa_save_data_pointer TO SFBR - -at 0x00000131 : */ 0x76100000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x00000133 : */ 0x6a340000,0x00000000, -/* - MOVE DSA1 + 0xff TO SFBR WITH CARRY - -at 0x00000135 : */ 0x7711ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x00000137 : */ 0x6a350000,0x00000000, -/* - MOVE DSA2 + 0xff TO SFBR WITH CARRY - -at 0x00000139 : */ 0x7712ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x0000013b : */ 0x6a360000,0x00000000, -/* - MOVE DSA3 + 0xff TO SFBR WITH CARRY - -at 0x0000013d : */ 0x7713ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x0000013f : */ 0x6a370000,0x00000000, -/* - - - MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4 - -at 0x00000141 : */ 0xc0000004,0x00000000,0x00000514, -/* - -jump_dsa_save: - JUMP 0 - -at 0x00000144 : */ 0x80080000,0x00000000, -/* - -munge_restore_pointers: - - ; The code at dsa_restore_pointers will RETURN, but we don't care - ; about TEMP here, as it will overwrite it anyway. - - MOVE DSA0 + dsa_restore_pointers TO SFBR - -at 0x00000146 : */ 0x76100000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x00000148 : */ 0x6a340000,0x00000000, -/* - MOVE DSA1 + 0xff TO SFBR WITH CARRY - -at 0x0000014a : */ 0x7711ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x0000014c : */ 0x6a350000,0x00000000, -/* - MOVE DSA2 + 0xff TO SFBR WITH CARRY - -at 0x0000014e : */ 0x7712ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x00000150 : */ 0x6a360000,0x00000000, -/* - MOVE DSA3 + 0xff TO SFBR WITH CARRY - -at 0x00000152 : */ 0x7713ff00,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x00000154 : */ 0x6a370000,0x00000000, -/* - - - MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4 - -at 0x00000156 : */ 0xc0000004,0x00000000,0x00000568, -/* - -jump_dsa_restore: - JUMP 0 - -at 0x00000159 : */ 0x80080000,0x00000000, -/* - - -munge_disconnect: - - - - - - - - - - - - - - - - - - - - - JUMP dsa_schedule - -at 0x0000015b : */ 0x80080000,0x00000178, -/* - - - - - -munge_extended: - CLEAR ACK - -at 0x0000015d : */ 0x60000040,0x00000000, -/* - INT int_err_unexpected_phase, WHEN NOT MSG_IN - -at 0x0000015f : */ 0x9f030000,0x00000000, -/* - MOVE 1, msg_buf + 1, WHEN MSG_IN - -at 0x00000161 : */ 0x0f000001,0x00000001, -/* - JUMP munge_extended_2, IF 0x02 - -at 0x00000163 : */ 0x800c0002,0x000005a4, -/* - JUMP munge_extended_3, IF 0x03 - -at 0x00000165 : */ 0x800c0003,0x000005d4, -/* - JUMP reject_message - -at 0x00000167 : */ 0x80080000,0x00000604, -/* - -munge_extended_2: - CLEAR ACK - -at 0x00000169 : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 2, WHEN MSG_IN - -at 0x0000016b : */ 0x0f000001,0x00000002, -/* - JUMP reject_message, IF NOT 0x02 ; Must be WDTR - -at 0x0000016d : */ 0x80040002,0x00000604, -/* - CLEAR ACK - -at 0x0000016f : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 3, WHEN MSG_IN - -at 0x00000171 : */ 0x0f000001,0x00000003, -/* - INT int_msg_wdtr - -at 0x00000173 : */ 0x98080000,0x01000000, -/* - -munge_extended_3: - CLEAR ACK - -at 0x00000175 : */ 0x60000040,0x00000000, -/* - MOVE 1, msg_buf + 2, WHEN MSG_IN - -at 0x00000177 : */ 0x0f000001,0x00000002, -/* - JUMP reject_message, IF NOT 0x01 ; Must be SDTR - -at 0x00000179 : */ 0x80040001,0x00000604, -/* - CLEAR ACK - -at 0x0000017b : */ 0x60000040,0x00000000, -/* - MOVE 2, msg_buf + 3, WHEN MSG_IN - -at 0x0000017d : */ 0x0f000002,0x00000003, -/* - INT int_msg_sdtr - -at 0x0000017f : */ 0x98080000,0x01010000, -/* - -ENTRY reject_message -reject_message: - SET ATN - -at 0x00000181 : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x00000183 : */ 0x60000040,0x00000000, -/* - MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT - -at 0x00000185 : */ 0x0e000001,0x00000000, -/* - RETURN - -at 0x00000187 : */ 0x90080000,0x00000000, -/* - -ENTRY accept_message -accept_message: - CLEAR ATN - -at 0x00000189 : */ 0x60000008,0x00000000, -/* - CLEAR ACK - -at 0x0000018b : */ 0x60000040,0x00000000, -/* - RETURN - -at 0x0000018d : */ 0x90080000,0x00000000, -/* - -ENTRY respond_message -respond_message: - SET ATN - -at 0x0000018f : */ 0x58000008,0x00000000, -/* - CLEAR ACK - -at 0x00000191 : */ 0x60000040,0x00000000, -/* - MOVE FROM dsa_msgout_other, WHEN MSG_OUT - -at 0x00000193 : */ 0x1e000000,0x00000068, -/* - RETURN - -at 0x00000195 : */ 0x90080000,0x00000000, -/* - -; -; command_complete -; -; PURPOSE : handle command termination when STATUS IN is detected by reading -; a status byte followed by a command termination message. -; -; Normal termination results in an INTFLY instruction, and -; the host system can pick out which command terminated by -; examining the MESSAGE and STATUS buffers of all currently -; executing commands; -; -; Abnormal (CHECK_CONDITION) termination results in an -; int_err_check_condition interrupt so that a REQUEST SENSE -; command can be issued out-of-order so that no other command -; clears the contingent allegiance condition. -; -; -; INPUTS : DSA - command -; -; CALLS : OK -; -; EXITS : On successful termination, control is passed to schedule. -; On abnormal termination, the user will usually modify the -; DSA fields and corresponding buffers and return control -; to select. -; - -ENTRY command_complete -command_complete: - MOVE FROM dsa_status, WHEN STATUS - -at 0x00000197 : */ 0x1b000000,0x00000060, -/* - - MOVE SFBR TO SCRATCH0 ; Save status - -at 0x00000199 : */ 0x6a340000,0x00000000, -/* - -ENTRY command_complete_msgin -command_complete_msgin: - MOVE FROM dsa_msgin, WHEN MSG_IN - -at 0x0000019b : */ 0x1f000000,0x00000058, -/* -; Indicate that we should be expecting a disconnect - - - - ; Above code cleared the Unexpected Disconnect bit, what do we do? - - CLEAR ACK - -at 0x0000019d : */ 0x60000040,0x00000000, -/* - - WAIT DISCONNECT - -at 0x0000019f : */ 0x48000000,0x00000000, -/* - -; -; The SCSI specification states that when a UNIT ATTENTION condition -; is pending, as indicated by a CHECK CONDITION status message, -; the target shall revert to asynchronous transfers. Since -; synchronous transfers parameters are maintained on a per INITIATOR/TARGET -; basis, and returning control to our scheduler could work on a command -; running on another lun on that target using the old parameters, we must -; interrupt the host processor to get them changed, or change them ourselves. -; -; Once SCSI-II tagged queueing is implemented, things will be even more -; hairy, since contingent allegiance conditions exist on a per-target/lun -; basis, and issuing a new command with a different tag would clear it. -; In these cases, we must interrupt the host processor to get a request -; added to the HEAD of the queue with the request sense command, or we -; must automatically issue the request sense command. - - - - - - - - INT int_norm_emulateintfly - -at 0x000001a1 : */ 0x98080000,0x02060000, -/* - - - - - - - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x000001a3 : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - - - JUMP schedule - -at 0x000001a6 : */ 0x80080000,0x00000000, -/* -command_failed: - INT int_err_check_condition - -at 0x000001a8 : */ 0x98080000,0x00030000, -/* - - - - -; -; wait_reselect -; -; PURPOSE : This is essentially the idle routine, where control lands -; when there are no new processes to schedule. wait_reselect -; waits for reselection, selection, and new commands. -; -; When a successful reselection occurs, with the aid -; of fixed up code in each DSA, wait_reselect walks the -; reconnect_dsa_queue, asking each dsa if the target ID -; and LUN match its. -; -; If a match is found, a call is made back to reselected_ok, -; which through the miracles of self modifying code, extracts -; the found DSA from the reconnect_dsa_queue and then -; returns control to the DSAs thread of execution. -; -; INPUTS : NONE -; -; CALLS : OK -; -; MODIFIES : DSA, -; -; EXITS : On successful reselection, control is returned to the -; DSA which called reselected_ok. If the WAIT RESELECT -; was interrupted by a new commands arrival signaled by -; SIG_P, control is passed to schedule. If the NCR is -; selected, the host system is interrupted with an -; int_err_selected which is usually responded to by -; setting DSP to the target_abort address. - -ENTRY wait_reselect -wait_reselect: - - - - - - - WAIT RESELECT wait_reselect_failed - -at 0x000001aa : */ 0x50000000,0x00000800, -/* - -reselected: - - - - CLEAR TARGET - -at 0x000001ac : */ 0x60000200,0x00000000, -/* - - ; Read all data needed to reestablish the nexus - - MOVE 1, reselected_identify, WHEN MSG_IN - -at 0x000001ae : */ 0x0f000001,0x00000000, -/* - ; We used to CLEAR ACK here. - - - - - - ; Point DSA at the current head of the disconnected queue. - - MOVE MEMORY 4, reconnect_dsa_head, addr_scratch - -at 0x000001b0 : */ 0xc0000004,0x00000000,0x00000000, -/* - - - MOVE MEMORY 4, addr_scratch, saved_dsa - -at 0x000001b3 : */ 0xc0000004,0x00000000,0x00000000, -/* - - - - - ; Fix the update-next pointer so that the reconnect_dsa_head - ; pointer is the one that will be updated if this DSA is a hit - ; and we remove it from the queue. - - MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8 - -at 0x000001b6 : */ 0xc0000004,0x00000000,0x000007ec, -/* - - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x000001b9 : */ 0xc0000004,0x00000000,0x00000000, -/* - - -ENTRY reselected_check_next -reselected_check_next: - - - - ; Check for a NULL pointer. - MOVE DSA0 TO SFBR - -at 0x000001bc : */ 0x72100000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001be : */ 0x80040000,0x00000738, -/* - MOVE DSA1 TO SFBR - -at 0x000001c0 : */ 0x72110000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001c2 : */ 0x80040000,0x00000738, -/* - MOVE DSA2 TO SFBR - -at 0x000001c4 : */ 0x72120000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001c6 : */ 0x80040000,0x00000738, -/* - MOVE DSA3 TO SFBR - -at 0x000001c8 : */ 0x72130000,0x00000000, -/* - JUMP reselected_not_end, IF NOT 0 - -at 0x000001ca : */ 0x80040000,0x00000738, -/* - INT int_err_unexpected_reselect - -at 0x000001cc : */ 0x98080000,0x00020000, -/* - -reselected_not_end: - ; - ; XXX the ALU is only eight bits wide, and the assembler - ; wont do the dirt work for us. As long as dsa_check_reselect - ; is negative, we need to sign extend with 1 bits to the full - ; 32 bit width of the address. - ; - ; A potential work around would be to have a known alignment - ; of the DSA structure such that the base address plus - ; dsa_check_reselect doesn't require carrying from bytes - ; higher than the LSB. - ; - - MOVE DSA0 TO SFBR - -at 0x000001ce : */ 0x72100000,0x00000000, -/* - MOVE SFBR + dsa_check_reselect TO SCRATCH0 - -at 0x000001d0 : */ 0x6e340000,0x00000000, -/* - MOVE DSA1 TO SFBR - -at 0x000001d2 : */ 0x72110000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY - -at 0x000001d4 : */ 0x6f35ff00,0x00000000, -/* - MOVE DSA2 TO SFBR - -at 0x000001d6 : */ 0x72120000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY - -at 0x000001d8 : */ 0x6f36ff00,0x00000000, -/* - MOVE DSA3 TO SFBR - -at 0x000001da : */ 0x72130000,0x00000000, -/* - MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY - -at 0x000001dc : */ 0x6f37ff00,0x00000000, -/* - - - MOVE MEMORY 4, addr_scratch, reselected_check + 4 - -at 0x000001de : */ 0xc0000004,0x00000000,0x00000794, -/* - - - ; Time to correct DSA following memory move - MOVE MEMORY 4, saved_dsa, addr_dsa - -at 0x000001e1 : */ 0xc0000004,0x00000000,0x00000000, -/* - -reselected_check: - JUMP 0 - -at 0x000001e4 : */ 0x80080000,0x00000000, -/* - - -; -; - -; We have problems here - the memory move corrupts TEMP and DSA. This -; routine is called from DSA code, and patched from many places. Scratch -; is probably free when it is called. -; We have to: -; copy temp to scratch, one byte at a time -; write scratch to patch a jump in place of the return -; do the move memory -; jump to the patched in return address -; DSA is corrupt when we get here, and can be left corrupt - -ENTRY reselected_ok -reselected_ok: - MOVE TEMP0 TO SFBR - -at 0x000001e6 : */ 0x721c0000,0x00000000, -/* - MOVE SFBR TO SCRATCH0 - -at 0x000001e8 : */ 0x6a340000,0x00000000, -/* - MOVE TEMP1 TO SFBR - -at 0x000001ea : */ 0x721d0000,0x00000000, -/* - MOVE SFBR TO SCRATCH1 - -at 0x000001ec : */ 0x6a350000,0x00000000, -/* - MOVE TEMP2 TO SFBR - -at 0x000001ee : */ 0x721e0000,0x00000000, -/* - MOVE SFBR TO SCRATCH2 - -at 0x000001f0 : */ 0x6a360000,0x00000000, -/* - MOVE TEMP3 TO SFBR - -at 0x000001f2 : */ 0x721f0000,0x00000000, -/* - MOVE SFBR TO SCRATCH3 - -at 0x000001f4 : */ 0x6a370000,0x00000000, -/* - MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4 - -at 0x000001f6 : */ 0xc0000004,0x00000000,0x000007f4, -/* -reselected_ok_patch: - MOVE MEMORY 4, 0, 0 - -at 0x000001f9 : */ 0xc0000004,0x00000000,0x00000000, -/* -reselected_ok_jump: - JUMP 0 - -at 0x000001fc : */ 0x80080000,0x00000000, -/* - - - - - -selected: - INT int_err_selected; - -at 0x000001fe : */ 0x98080000,0x00010000, -/* - -; -; A select or reselect failure can be caused by one of two conditions : -; 1. SIG_P was set. This will be the case if the user has written -; a new value to a previously NULL head of the issue queue. -; -; 2. The NCR53c810 was selected or reselected by another device. -; -; 3. The bus was already busy since we were selected or reselected -; before starting the command. - -wait_reselect_failed: - - - -; Check selected bit. - - ; Must work out how to tell if we are selected.... - - - - -; Reading CTEST2 clears the SIG_P bit in the ISTAT register. - MOVE CTEST2 & 0x40 TO SFBR - -at 0x00000200 : */ 0x74164000,0x00000000, -/* - JUMP schedule, IF 0x40 - -at 0x00000202 : */ 0x800c0040,0x00000000, -/* -; Check connected bit. -; FIXME: this needs to change if we support target mode - MOVE ISTAT & 0x08 TO SFBR - -at 0x00000204 : */ 0x74210800,0x00000000, -/* - JUMP reselected, IF 0x08 - -at 0x00000206 : */ 0x800c0008,0x000006b0, -/* -; FIXME : Something bogus happened, and we shouldn't fail silently. - - - - INT int_debug_panic - -at 0x00000208 : */ 0x98080000,0x030b0000, -/* - - - -select_failed: - - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 - -at 0x0000020a : */ 0x7a1b1000,0x00000000, -/* - - - - -; Otherwise, mask the selected and reselected bits off SIST0 - - ; Let's assume we don't get selected for now - MOVE SSTAT0 & 0x10 TO SFBR - -at 0x0000020c : */ 0x740d1000,0x00000000, -/* - - - - - JUMP reselected, IF 0x10 - -at 0x0000020e : */ 0x800c0010,0x000006b0, -/* -; If SIGP is set, the user just gave us another command, and -; we should restart or return to the scheduler. -; Reading CTEST2 clears the SIG_P bit in the ISTAT register. - MOVE CTEST2 & 0x40 TO SFBR - -at 0x00000210 : */ 0x74164000,0x00000000, -/* - JUMP select, IF 0x40 - -at 0x00000212 : */ 0x800c0040,0x000001f8, -/* -; Check connected bit. -; FIXME: this needs to change if we support target mode -; FIXME: is this really necessary? - MOVE ISTAT & 0x08 TO SFBR - -at 0x00000214 : */ 0x74210800,0x00000000, -/* - JUMP reselected, IF 0x08 - -at 0x00000216 : */ 0x800c0008,0x000006b0, -/* -; FIXME : Something bogus happened, and we shouldn't fail silently. - - - - INT int_debug_panic - -at 0x00000218 : */ 0x98080000,0x030b0000, -/* - - -; -; test_1 -; test_2 -; -; PURPOSE : run some verification tests on the NCR. test_1 -; copies test_src to test_dest and interrupts the host -; processor, testing for cache coherency and interrupt -; problems in the processes. -; -; test_2 runs a command with offsets relative to the -; DSA on entry, and is useful for miscellaneous experimentation. -; - -; Verify that interrupts are working correctly and that we don't -; have a cache invalidation problem. - -ABSOLUTE test_src = 0, test_dest = 0 -ENTRY test_1 -test_1: - MOVE MEMORY 4, test_src, test_dest - -at 0x0000021a : */ 0xc0000004,0x00000000,0x00000000, -/* - INT int_test_1 - -at 0x0000021d : */ 0x98080000,0x04000000, -/* - -; -; Run arbitrary commands, with test code establishing a DSA -; - -ENTRY test_2 -test_2: - CLEAR TARGET - -at 0x0000021f : */ 0x60000200,0x00000000, -/* - - ; Enable selection timer - - - - MOVE CTEST7 & 0xef TO CTEST7 - -at 0x00000221 : */ 0x7c1bef00,0x00000000, -/* - - - SELECT ATN FROM 0, test_2_fail - -at 0x00000223 : */ 0x43000000,0x000008dc, -/* - JUMP test_2_msgout, WHEN MSG_OUT - -at 0x00000225 : */ 0x860b0000,0x0000089c, -/* -ENTRY test_2_msgout -test_2_msgout: - - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 - -at 0x00000227 : */ 0x7a1b1000,0x00000000, -/* - - MOVE FROM 8, WHEN MSG_OUT - -at 0x00000229 : */ 0x1e000000,0x00000008, -/* - MOVE FROM 16, WHEN CMD - -at 0x0000022b : */ 0x1a000000,0x00000010, -/* - MOVE FROM 24, WHEN DATA_IN - -at 0x0000022d : */ 0x19000000,0x00000018, -/* - MOVE FROM 32, WHEN STATUS - -at 0x0000022f : */ 0x1b000000,0x00000020, -/* - MOVE FROM 40, WHEN MSG_IN - -at 0x00000231 : */ 0x1f000000,0x00000028, -/* - - - - CLEAR ACK - -at 0x00000233 : */ 0x60000040,0x00000000, -/* - WAIT DISCONNECT - -at 0x00000235 : */ 0x48000000,0x00000000, -/* -test_2_fail: - - ; Disable selection timer - MOVE CTEST7 | 0x10 TO CTEST7 - -at 0x00000237 : */ 0x7a1b1000,0x00000000, -/* - - INT int_test_2 - -at 0x00000239 : */ 0x98080000,0x04010000, -/* - -ENTRY debug_break -debug_break: - INT int_debug_break - -at 0x0000023b : */ 0x98080000,0x03000000, -/* - -; -; initiator_abort -; target_abort -; -; PURPOSE : Abort the currently established nexus from with initiator -; or target mode. -; -; - -ENTRY target_abort -target_abort: - SET TARGET - -at 0x0000023d : */ 0x58000200,0x00000000, -/* - DISCONNECT - -at 0x0000023f : */ 0x48000000,0x00000000, -/* - CLEAR TARGET - -at 0x00000241 : */ 0x60000200,0x00000000, -/* - JUMP schedule - -at 0x00000243 : */ 0x80080000,0x00000000, -/* - -ENTRY initiator_abort -initiator_abort: - SET ATN - -at 0x00000245 : */ 0x58000008,0x00000000, -/* -; -; The SCSI-I specification says that targets may go into MSG out at -; their leisure upon receipt of the ATN single. On all versions of the -; specification, we can't change phases until REQ transitions true->false, -; so we need to sink/source one byte of data to allow the transition. -; -; For the sake of safety, we'll only source one byte of data in all -; cases, but to accommodate the SCSI-I dain bramage, we'll sink an -; arbitrary number of bytes. - JUMP spew_cmd, WHEN CMD - -at 0x00000247 : */ 0x820b0000,0x0000094c, -/* - JUMP eat_msgin, WHEN MSG_IN - -at 0x00000249 : */ 0x870b0000,0x0000095c, -/* - JUMP eat_datain, WHEN DATA_IN - -at 0x0000024b : */ 0x810b0000,0x0000098c, -/* - JUMP eat_status, WHEN STATUS - -at 0x0000024d : */ 0x830b0000,0x00000974, -/* - JUMP spew_dataout, WHEN DATA_OUT - -at 0x0000024f : */ 0x800b0000,0x000009a4, -/* - JUMP sated - -at 0x00000251 : */ 0x80080000,0x000009ac, -/* -spew_cmd: - MOVE 1, NCR53c7xx_zero, WHEN CMD - -at 0x00000253 : */ 0x0a000001,0x00000000, -/* - JUMP sated - -at 0x00000255 : */ 0x80080000,0x000009ac, -/* -eat_msgin: - MOVE 1, NCR53c7xx_sink, WHEN MSG_IN - -at 0x00000257 : */ 0x0f000001,0x00000000, -/* - JUMP eat_msgin, WHEN MSG_IN - -at 0x00000259 : */ 0x870b0000,0x0000095c, -/* - JUMP sated - -at 0x0000025b : */ 0x80080000,0x000009ac, -/* -eat_status: - MOVE 1, NCR53c7xx_sink, WHEN STATUS - -at 0x0000025d : */ 0x0b000001,0x00000000, -/* - JUMP eat_status, WHEN STATUS - -at 0x0000025f : */ 0x830b0000,0x00000974, -/* - JUMP sated - -at 0x00000261 : */ 0x80080000,0x000009ac, -/* -eat_datain: - MOVE 1, NCR53c7xx_sink, WHEN DATA_IN - -at 0x00000263 : */ 0x09000001,0x00000000, -/* - JUMP eat_datain, WHEN DATA_IN - -at 0x00000265 : */ 0x810b0000,0x0000098c, -/* - JUMP sated - -at 0x00000267 : */ 0x80080000,0x000009ac, -/* -spew_dataout: - MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT - -at 0x00000269 : */ 0x08000001,0x00000000, -/* -sated: - - - - MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT - -at 0x0000026b : */ 0x0e000001,0x00000000, -/* - WAIT DISCONNECT - -at 0x0000026d : */ 0x48000000,0x00000000, -/* - INT int_norm_aborted - -at 0x0000026f : */ 0x98080000,0x02040000, -/* - - - - -; Little patched jump, used to overcome problems with TEMP getting -; corrupted on memory moves. - -jump_temp: - JUMP 0 - -at 0x00000271 : */ 0x80080000,0x00000000, -}; - -#define A_NCR53c7xx_msg_abort 0x00000000 -static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = { - 0x0000026c, -}; - -#define A_NCR53c7xx_msg_reject 0x00000000 -static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = { - 0x00000186, -}; - -#define A_NCR53c7xx_sink 0x00000000 -static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = { - 0x00000258, - 0x0000025e, - 0x00000264, -}; - -#define A_NCR53c7xx_zero 0x00000000 -static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = { - 0x00000254, - 0x0000026a, -}; - -#define A_NOP_insn 0x00000000 -static u32 A_NOP_insn_used[] __attribute((unused)) = { - 0x00000017, -}; - -#define A_addr_dsa 0x00000000 -static u32 A_addr_dsa_used[] __attribute((unused)) = { - 0x0000000f, - 0x00000026, - 0x00000033, - 0x00000040, - 0x00000055, - 0x00000079, - 0x0000008e, - 0x000000bc, - 0x000000d2, - 0x00000130, - 0x000001a5, - 0x000001bb, - 0x000001e3, -}; - -#define A_addr_reconnect_dsa_head 0x00000000 -static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = { - 0x000001b7, -}; - -#define A_addr_scratch 0x00000000 -static u32 A_addr_scratch_used[] __attribute((unused)) = { - 0x00000002, - 0x00000004, - 0x00000008, - 0x00000020, - 0x00000022, - 0x00000049, - 0x00000060, - 0x0000006a, - 0x00000071, - 0x00000073, - 0x000000ab, - 0x000000b5, - 0x000000c1, - 0x000000cb, - 0x0000012c, - 0x00000142, - 0x00000157, - 0x000001b2, - 0x000001b4, - 0x000001df, - 0x000001f7, -}; - -#define A_addr_temp 0x00000000 -static u32 A_addr_temp_used[] __attribute((unused)) = { -}; - -#define A_dmode_memory_to_memory 0x00000000 -static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = { -}; - -#define A_dmode_memory_to_ncr 0x00000000 -static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = { -}; - -#define A_dmode_ncr_to_memory 0x00000000 -static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = { -}; - -#define A_dsa_check_reselect 0x00000000 -static u32 A_dsa_check_reselect_used[] __attribute((unused)) = { - 0x000001d0, -}; - -#define A_dsa_cmdout 0x00000048 -static u32 A_dsa_cmdout_used[] __attribute((unused)) = { - 0x0000009a, -}; - -#define A_dsa_cmnd 0x00000038 -static u32 A_dsa_cmnd_used[] __attribute((unused)) = { -}; - -#define A_dsa_datain 0x00000054 -static u32 A_dsa_datain_used[] __attribute((unused)) = { - 0x000000c2, -}; - -#define A_dsa_dataout 0x00000050 -static u32 A_dsa_dataout_used[] __attribute((unused)) = { - 0x000000ac, -}; - -#define A_dsa_end 0x00000070 -static u32 A_dsa_end_used[] __attribute((unused)) = { -}; - -#define A_dsa_fields_start 0x00000000 -static u32 A_dsa_fields_start_used[] __attribute((unused)) = { -}; - -#define A_dsa_msgin 0x00000058 -static u32 A_dsa_msgin_used[] __attribute((unused)) = { - 0x0000019c, -}; - -#define A_dsa_msgout 0x00000040 -static u32 A_dsa_msgout_used[] __attribute((unused)) = { - 0x00000089, -}; - -#define A_dsa_msgout_other 0x00000068 -static u32 A_dsa_msgout_other_used[] __attribute((unused)) = { - 0x00000194, -}; - -#define A_dsa_next 0x00000030 -static u32 A_dsa_next_used[] __attribute((unused)) = { - 0x00000061, -}; - -#define A_dsa_restore_pointers 0x00000000 -static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = { - 0x00000146, -}; - -#define A_dsa_save_data_pointer 0x00000000 -static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = { - 0x00000131, -}; - -#define A_dsa_select 0x0000003c -static u32 A_dsa_select_used[] __attribute((unused)) = { - 0x00000082, -}; - -#define A_dsa_sscf_710 0x00000000 -static u32 A_dsa_sscf_710_used[] __attribute((unused)) = { - 0x00000007, -}; - -#define A_dsa_status 0x00000060 -static u32 A_dsa_status_used[] __attribute((unused)) = { - 0x00000198, -}; - -#define A_dsa_temp_addr_array_value 0x00000000 -static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = { -}; - -#define A_dsa_temp_addr_dsa_value 0x00000000 -static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = { - 0x00000001, -}; - -#define A_dsa_temp_addr_new_value 0x00000000 -static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = { -}; - -#define A_dsa_temp_addr_next 0x00000000 -static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = { - 0x0000001c, - 0x0000004f, -}; - -#define A_dsa_temp_addr_residual 0x00000000 -static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = { - 0x0000002d, - 0x0000003b, -}; - -#define A_dsa_temp_addr_saved_pointer 0x00000000 -static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = { - 0x0000002b, - 0x00000037, -}; - -#define A_dsa_temp_addr_saved_residual 0x00000000 -static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = { - 0x0000002e, - 0x0000003a, -}; - -#define A_dsa_temp_lun 0x00000000 -static u32 A_dsa_temp_lun_used[] __attribute((unused)) = { - 0x0000004c, -}; - -#define A_dsa_temp_next 0x00000000 -static u32 A_dsa_temp_next_used[] __attribute((unused)) = { - 0x0000001f, -}; - -#define A_dsa_temp_sync 0x00000000 -static u32 A_dsa_temp_sync_used[] __attribute((unused)) = { - 0x00000057, -}; - -#define A_dsa_temp_target 0x00000000 -static u32 A_dsa_temp_target_used[] __attribute((unused)) = { - 0x00000045, -}; - -#define A_emulfly 0x00000000 -static u32 A_emulfly_used[] __attribute((unused)) = { -}; - -#define A_int_debug_break 0x03000000 -static u32 A_int_debug_break_used[] __attribute((unused)) = { - 0x0000023c, -}; - -#define A_int_debug_panic 0x030b0000 -static u32 A_int_debug_panic_used[] __attribute((unused)) = { - 0x00000209, - 0x00000219, -}; - -#define A_int_err_check_condition 0x00030000 -static u32 A_int_err_check_condition_used[] __attribute((unused)) = { - 0x000001a9, -}; - -#define A_int_err_no_phase 0x00040000 -static u32 A_int_err_no_phase_used[] __attribute((unused)) = { -}; - -#define A_int_err_selected 0x00010000 -static u32 A_int_err_selected_used[] __attribute((unused)) = { - 0x000001ff, -}; - -#define A_int_err_unexpected_phase 0x00000000 -static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = { - 0x00000092, - 0x00000098, - 0x000000a0, - 0x000000d6, - 0x000000da, - 0x000000dc, - 0x000000e4, - 0x000000e8, - 0x000000ea, - 0x000000f2, - 0x000000f6, - 0x000000f8, - 0x000000fa, - 0x00000160, -}; - -#define A_int_err_unexpected_reselect 0x00020000 -static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = { - 0x000001cd, -}; - -#define A_int_msg_1 0x01020000 -static u32 A_int_msg_1_used[] __attribute((unused)) = { - 0x00000114, - 0x00000116, -}; - -#define A_int_msg_sdtr 0x01010000 -static u32 A_int_msg_sdtr_used[] __attribute((unused)) = { - 0x00000180, -}; - -#define A_int_msg_wdtr 0x01000000 -static u32 A_int_msg_wdtr_used[] __attribute((unused)) = { - 0x00000174, -}; - -#define A_int_norm_aborted 0x02040000 -static u32 A_int_norm_aborted_used[] __attribute((unused)) = { - 0x00000270, -}; - -#define A_int_norm_command_complete 0x02020000 -static u32 A_int_norm_command_complete_used[] __attribute((unused)) = { -}; - -#define A_int_norm_disconnected 0x02030000 -static u32 A_int_norm_disconnected_used[] __attribute((unused)) = { -}; - -#define A_int_norm_emulateintfly 0x02060000 -static u32 A_int_norm_emulateintfly_used[] __attribute((unused)) = { - 0x000001a2, -}; - -#define A_int_norm_reselect_complete 0x02010000 -static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = { -}; - -#define A_int_norm_reset 0x02050000 -static u32 A_int_norm_reset_used[] __attribute((unused)) = { -}; - -#define A_int_norm_select_complete 0x02000000 -static u32 A_int_norm_select_complete_used[] __attribute((unused)) = { -}; - -#define A_int_test_1 0x04000000 -static u32 A_int_test_1_used[] __attribute((unused)) = { - 0x0000021e, -}; - -#define A_int_test_2 0x04010000 -static u32 A_int_test_2_used[] __attribute((unused)) = { - 0x0000023a, -}; - -#define A_int_test_3 0x04020000 -static u32 A_int_test_3_used[] __attribute((unused)) = { -}; - -#define A_msg_buf 0x00000000 -static u32 A_msg_buf_used[] __attribute((unused)) = { - 0x00000108, - 0x00000162, - 0x0000016c, - 0x00000172, - 0x00000178, - 0x0000017e, -}; - -#define A_reconnect_dsa_head 0x00000000 -static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = { - 0x0000006d, - 0x00000074, - 0x000001b1, -}; - -#define A_reselected_identify 0x00000000 -static u32 A_reselected_identify_used[] __attribute((unused)) = { - 0x00000048, - 0x000001af, -}; - -#define A_reselected_tag 0x00000000 -static u32 A_reselected_tag_used[] __attribute((unused)) = { -}; - -#define A_saved_dsa 0x00000000 -static u32 A_saved_dsa_used[] __attribute((unused)) = { - 0x00000005, - 0x0000000e, - 0x00000023, - 0x00000025, - 0x00000032, - 0x0000003f, - 0x00000054, - 0x0000005f, - 0x00000070, - 0x00000078, - 0x0000008d, - 0x000000aa, - 0x000000bb, - 0x000000c0, - 0x000000d1, - 0x0000012f, - 0x000001a4, - 0x000001b5, - 0x000001ba, - 0x000001e2, -}; - -#define A_schedule 0x00000000 -static u32 A_schedule_used[] __attribute((unused)) = { - 0x0000007d, - 0x000001a7, - 0x00000203, - 0x00000244, -}; - -#define A_test_dest 0x00000000 -static u32 A_test_dest_used[] __attribute((unused)) = { - 0x0000021c, -}; - -#define A_test_src 0x00000000 -static u32 A_test_src_used[] __attribute((unused)) = { - 0x0000021b, -}; - -#define Ent_accept_message 0x00000624 -#define Ent_cmdout_cmdout 0x00000264 -#define Ent_command_complete 0x0000065c -#define Ent_command_complete_msgin 0x0000066c -#define Ent_data_transfer 0x0000026c -#define Ent_datain_to_jump 0x00000334 -#define Ent_debug_break 0x000008ec -#define Ent_dsa_code_begin 0x00000000 -#define Ent_dsa_code_check_reselect 0x0000010c -#define Ent_dsa_code_fix_jump 0x00000058 -#define Ent_dsa_code_restore_pointers 0x000000d8 -#define Ent_dsa_code_save_data_pointer 0x000000a4 -#define Ent_dsa_code_template 0x00000000 -#define Ent_dsa_code_template_end 0x00000178 -#define Ent_dsa_schedule 0x00000178 -#define Ent_dsa_zero 0x00000178 -#define Ent_end_data_transfer 0x000002a4 -#define Ent_initiator_abort 0x00000914 -#define Ent_msg_in 0x0000041c -#define Ent_msg_in_restart 0x000003fc -#define Ent_other_in 0x0000038c -#define Ent_other_out 0x00000354 -#define Ent_other_transfer 0x000003c4 -#define Ent_reject_message 0x00000604 -#define Ent_reselected_check_next 0x000006f0 -#define Ent_reselected_ok 0x00000798 -#define Ent_respond_message 0x0000063c -#define Ent_select 0x000001f8 -#define Ent_select_msgout 0x00000218 -#define Ent_target_abort 0x000008f4 -#define Ent_test_1 0x00000868 -#define Ent_test_2 0x0000087c -#define Ent_test_2_msgout 0x0000089c -#define Ent_wait_reselect 0x000006a8 -static u32 LABELPATCHES[] __attribute((unused)) = { - 0x00000011, - 0x0000001a, - 0x0000001d, - 0x00000028, - 0x0000002a, - 0x00000035, - 0x00000038, - 0x00000042, - 0x00000050, - 0x00000052, - 0x0000006b, - 0x00000083, - 0x00000085, - 0x00000090, - 0x00000094, - 0x00000096, - 0x0000009c, - 0x0000009e, - 0x000000a2, - 0x000000a4, - 0x000000a6, - 0x000000a8, - 0x000000b6, - 0x000000b9, - 0x000000cc, - 0x000000cf, - 0x000000d8, - 0x000000de, - 0x000000e0, - 0x000000e6, - 0x000000ec, - 0x000000ee, - 0x000000f4, - 0x000000fc, - 0x000000fe, - 0x0000010a, - 0x0000010c, - 0x0000010e, - 0x00000110, - 0x00000112, - 0x00000118, - 0x0000011a, - 0x0000012d, - 0x00000143, - 0x00000158, - 0x0000015c, - 0x00000164, - 0x00000166, - 0x00000168, - 0x0000016e, - 0x0000017a, - 0x000001ab, - 0x000001b8, - 0x000001bf, - 0x000001c3, - 0x000001c7, - 0x000001cb, - 0x000001e0, - 0x000001f8, - 0x00000207, - 0x0000020f, - 0x00000213, - 0x00000217, - 0x00000224, - 0x00000226, - 0x00000248, - 0x0000024a, - 0x0000024c, - 0x0000024e, - 0x00000250, - 0x00000252, - 0x00000256, - 0x0000025a, - 0x0000025c, - 0x00000260, - 0x00000262, - 0x00000266, - 0x00000268, -}; - -static struct { - u32 offset; - void *address; -} EXTERNAL_PATCHES[] __attribute((unused)) = { -}; - -static u32 INSTRUCTIONS __attribute((unused)) = 290; -static u32 PATCHES __attribute((unused)) = 78; -static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0; diff --git a/drivers/scsi/53c7xx_u.h_shipped b/drivers/scsi/53c7xx_u.h_shipped deleted file mode 100644 index 7b337174e228..000000000000 --- a/drivers/scsi/53c7xx_u.h_shipped +++ /dev/null @@ -1,102 +0,0 @@ -#undef A_NCR53c7xx_msg_abort -#undef A_NCR53c7xx_msg_reject -#undef A_NCR53c7xx_sink -#undef A_NCR53c7xx_zero -#undef A_NOP_insn -#undef A_addr_dsa -#undef A_addr_reconnect_dsa_head -#undef A_addr_scratch -#undef A_addr_temp -#undef A_dmode_memory_to_memory -#undef A_dmode_memory_to_ncr -#undef A_dmode_ncr_to_memory -#undef A_dsa_check_reselect -#undef A_dsa_cmdout -#undef A_dsa_cmnd -#undef A_dsa_datain -#undef A_dsa_dataout -#undef A_dsa_end -#undef A_dsa_fields_start -#undef A_dsa_msgin -#undef A_dsa_msgout -#undef A_dsa_msgout_other -#undef A_dsa_next -#undef A_dsa_restore_pointers -#undef A_dsa_save_data_pointer -#undef A_dsa_select -#undef A_dsa_sscf_710 -#undef A_dsa_status -#undef A_dsa_temp_addr_array_value -#undef A_dsa_temp_addr_dsa_value -#undef A_dsa_temp_addr_new_value -#undef A_dsa_temp_addr_next -#undef A_dsa_temp_addr_residual -#undef A_dsa_temp_addr_saved_pointer -#undef A_dsa_temp_addr_saved_residual -#undef A_dsa_temp_lun -#undef A_dsa_temp_next -#undef A_dsa_temp_sync -#undef A_dsa_temp_target -#undef A_emulfly -#undef A_int_debug_break -#undef A_int_debug_panic -#undef A_int_err_check_condition -#undef A_int_err_no_phase -#undef A_int_err_selected -#undef A_int_err_unexpected_phase -#undef A_int_err_unexpected_reselect -#undef A_int_msg_1 -#undef A_int_msg_sdtr -#undef A_int_msg_wdtr -#undef A_int_norm_aborted -#undef A_int_norm_command_complete -#undef A_int_norm_disconnected -#undef A_int_norm_emulateintfly -#undef A_int_norm_reselect_complete -#undef A_int_norm_reset -#undef A_int_norm_select_complete -#undef A_int_test_1 -#undef A_int_test_2 -#undef A_int_test_3 -#undef A_msg_buf -#undef A_reconnect_dsa_head -#undef A_reselected_identify -#undef A_reselected_tag -#undef A_saved_dsa -#undef A_schedule -#undef A_test_dest -#undef A_test_src -#undef Ent_accept_message -#undef Ent_cmdout_cmdout -#undef Ent_command_complete -#undef Ent_command_complete_msgin -#undef Ent_data_transfer -#undef Ent_datain_to_jump -#undef Ent_debug_break -#undef Ent_dsa_code_begin -#undef Ent_dsa_code_check_reselect -#undef Ent_dsa_code_fix_jump -#undef Ent_dsa_code_restore_pointers -#undef Ent_dsa_code_save_data_pointer -#undef Ent_dsa_code_template -#undef Ent_dsa_code_template_end -#undef Ent_dsa_schedule -#undef Ent_dsa_zero -#undef Ent_end_data_transfer -#undef Ent_initiator_abort -#undef Ent_msg_in -#undef Ent_msg_in_restart -#undef Ent_other_in -#undef Ent_other_out -#undef Ent_other_transfer -#undef Ent_reject_message -#undef Ent_reselected_check_next -#undef Ent_reselected_ok -#undef Ent_respond_message -#undef Ent_select -#undef Ent_select_msgout -#undef Ent_target_abort -#undef Ent_test_1 -#undef Ent_test_2 -#undef Ent_test_2_msgout -#undef Ent_wait_reselect diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 96f4cab07614..9b206176f717 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -304,18 +304,10 @@ static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB) { struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter; - struct scsi_cmnd *cmd = CCB->Command; - if (cmd->use_sg != 0) { - pci_unmap_sg(HostAdapter->PCI_Device, - (struct scatterlist *)cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); - } else if (cmd->request_bufflen != 0) { - pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer, - CCB->DataLength, cmd->sc_data_direction); - } + scsi_dma_unmap(CCB->Command); pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer, - CCB->SenseDataLength, PCI_DMA_FROMDEVICE); + CCB->SenseDataLength, PCI_DMA_FROMDEVICE); CCB->Command = NULL; CCB->Status = BusLogic_CCB_Free; @@ -2648,7 +2640,8 @@ static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapt */ if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) { struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID]; - struct SCSI_Inquiry *InquiryResult = (struct SCSI_Inquiry *) Command->request_buffer; + struct SCSI_Inquiry *InquiryResult = + (struct SCSI_Inquiry *) scsi_sglist(Command); TargetFlags->TargetExists = true; TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue; TargetFlags->WideTransfersSupported = InquiryResult->WBus16; @@ -2819,9 +2812,8 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou int CDB_Length = Command->cmd_len; int TargetID = Command->device->id; int LogicalUnit = Command->device->lun; - void *BufferPointer = Command->request_buffer; - int BufferLength = Command->request_bufflen; - int SegmentCount = Command->use_sg; + int BufferLength = scsi_bufflen(Command); + int Count; struct BusLogic_CCB *CCB; /* SCSI REQUEST_SENSE commands will be executed automatically by the Host @@ -2851,36 +2843,35 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou return 0; } } + /* Initialize the fields in the BusLogic Command Control Block (CCB). */ - if (SegmentCount == 0 && BufferLength != 0) { - CCB->Opcode = BusLogic_InitiatorCCB; - CCB->DataLength = BufferLength; - CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device, - BufferPointer, BufferLength, - Command->sc_data_direction); - } else if (SegmentCount != 0) { - struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer; - int Segment, Count; - - Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount, - Command->sc_data_direction); + Count = scsi_dma_map(Command); + BUG_ON(Count < 0); + if (Count) { + struct scatterlist *sg; + int i; + CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment); if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB); else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList); - for (Segment = 0; Segment < Count; Segment++) { - CCB->ScatterGatherList[Segment].SegmentByteCount = sg_dma_len(ScatterList + Segment); - CCB->ScatterGatherList[Segment].SegmentDataPointer = sg_dma_address(ScatterList + Segment); + + scsi_for_each_sg(Command, sg, Count, i) { + CCB->ScatterGatherList[i].SegmentByteCount = + sg_dma_len(sg); + CCB->ScatterGatherList[i].SegmentDataPointer = + sg_dma_address(sg); } - } else { + } else if (!Count) { CCB->Opcode = BusLogic_InitiatorCCB; CCB->DataLength = BufferLength; CCB->DataPointer = 0; } + switch (CDB[0]) { case READ_6: case READ_10: diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 572034ceb143..aac9cd9a172f 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -738,7 +738,7 @@ config SCSI_GENERIC_NCR53C400 config SCSI_IBMMCA tristate "IBMMCA SCSI support" - depends on MCA_LEGACY && SCSI + depends on MCA && SCSI ---help--- This is support for the IBM SCSI adapter found in many of the PS/2 series computers. These machines have an MCA bus, so you need to diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index b1b632791580..cba39679f947 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -37,7 +37,6 @@ obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas/ obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o -obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o @@ -53,8 +52,6 @@ obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o obj-$(CONFIG_MAC_SCSI) += mac_scsi.o obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o sun3_scsi_vme.o -obj-$(CONFIG_MVME16x_SCSI) += mvme16x.o 53c7xx.o -obj-$(CONFIG_BVME6000_SCSI) += bvme6000.o 53c7xx.o obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o obj-$(CONFIG_SCSI_PSI240I) += psi240i.o @@ -168,10 +165,8 @@ NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o # Files generated that shall be removed upon make clean -clean-files := 53c7xx_d.h 53c700_d.h \ - 53c7xx_u.h 53c700_u.h +clean-files := 53c700_d.h 53c700_u.h -$(obj)/53c7xx.o: $(obj)/53c7xx_d.h $(obj)/53c7xx_u.h $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h # If you want to play with the firmware, uncomment @@ -179,11 +174,6 @@ $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h ifdef GENERATE_FIRMWARE -$(obj)/53c7xx_d.h: $(src)/53c7xx.scr $(src)/script_asm.pl - $(CPP) -traditional -DCHIP=710 - < $< | grep -v '^#' | $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h) - -$(obj)/53c7xx_u.h: $(obj)/53c7xx_d.h - $(obj)/53c700_d.h: $(src)/53c700.scr $(src)/script_asm.pl $(PERL) -s $(src)/script_asm.pl -ncr7x0_family $@ $(@:_d.h=_u.h) < $< diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index bb3cb3360541..37de6b37b084 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -347,7 +347,7 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, int reg, int bit, i if((r & bit) == val) return 0; if(!in_interrupt()) - yield(); + cond_resched(); else cpu_relax(); } @@ -357,7 +357,7 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, int reg, int bit, i static struct { unsigned char value; const char *name; -} phases[] = { +} phases[] __maybe_unused = { {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, @@ -575,7 +575,8 @@ static irqreturn_t __init probe_intr(int irq, void *dev_id) * Locks: none, irqs must be enabled on entry */ -static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible) +static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, + int possible) { NCR5380_local_declare(); struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; @@ -629,7 +630,8 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible) * Locks: none */ -static void __init NCR5380_print_options(struct Scsi_Host *instance) +static void __init __maybe_unused +NCR5380_print_options(struct Scsi_Host *instance) { printk(" generic options" #ifdef AUTOPROBE_IRQ @@ -703,8 +705,8 @@ char *lprint_command(unsigned char *cmd, char *pos, char *buffer, int len); static char *lprint_opcode(int opcode, char *pos, char *buffer, int length); -static -int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset, int length, int inout) +static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance, + char *buffer, char **start, off_t offset, int length, int inout) { char *pos = buffer; struct NCR5380_hostdata *hostdata; diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 713a108c02ef..bccf13f71532 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -299,7 +299,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance); static irqreturn_t NCR5380_intr(int irq, void *dev_id); #endif static void NCR5380_main(struct work_struct *work); -static void NCR5380_print_options(struct Scsi_Host *instance); +static void __maybe_unused NCR5380_print_options(struct Scsi_Host *instance); #ifdef NDEBUG static void NCR5380_print_phase(struct Scsi_Host *instance); static void NCR5380_print(struct Scsi_Host *instance); @@ -307,8 +307,8 @@ static void NCR5380_print(struct Scsi_Host *instance); static int NCR5380_abort(Scsi_Cmnd * cmd); static int NCR5380_bus_reset(Scsi_Cmnd * cmd); static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); -static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, -off_t offset, int length, int inout); +static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance, + char *buffer, char **start, off_t offset, int length, int inout); static void NCR5380_reselect(struct Scsi_Host *instance); static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag); diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index 7c0b17f86903..eda8c48f6be7 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -698,7 +698,7 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) int i; VDEB(printk("NCR53c406a_queue called\n")); - DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, SCpnt->request_bufflen)); + DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt))); #if 0 VDEB(for (i = 0; i < SCpnt->cmd_len; i++) @@ -785,8 +785,8 @@ static void NCR53c406a_intr(void *dev_id) unsigned char status, int_reg; #if USE_PIO unsigned char pio_status; - struct scatterlist *sglist; - unsigned int sgcount; + struct scatterlist *sg; + int i; #endif VDEB(printk("NCR53c406a_intr called\n")); @@ -866,22 +866,18 @@ static void NCR53c406a_intr(void *dev_id) current_SC->SCp.phase = data_out; VDEB(printk("NCR53c406a: Data-Out phase\n")); outb(FLUSH_FIFO, CMD_REG); - LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ + LOAD_DMA_COUNT(scsi_bufflen(current_SC)); /* Max transfer size */ #if USE_DMA /* No s/g support for DMA */ - NCR53c406a_dma_write(current_SC->request_buffer, current_SC->request_bufflen); + NCR53c406a_dma_write(scsi_sglist(current_SC), + scsdi_bufflen(current_SC)); + #endif /* USE_DMA */ outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO - if (!current_SC->use_sg) /* Don't use scatter-gather */ - NCR53c406a_pio_write(current_SC->request_buffer, current_SC->request_bufflen); - else { /* use scatter-gather */ - sgcount = current_SC->use_sg; - sglist = current_SC->request_buffer; - while (sgcount--) { - NCR53c406a_pio_write(page_address(sglist->page) + sglist->offset, sglist->length); - sglist++; - } - } + scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) { + NCR53c406a_pio_write(page_address(sg->page) + sg->offset, + sg->length); + } REG0; #endif /* USE_PIO */ } @@ -893,22 +889,17 @@ static void NCR53c406a_intr(void *dev_id) current_SC->SCp.phase = data_in; VDEB(printk("NCR53c406a: Data-In phase\n")); outb(FLUSH_FIFO, CMD_REG); - LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ + LOAD_DMA_COUNT(scsi_bufflen(current_SC)); /* Max transfer size */ #if USE_DMA /* No s/g support for DMA */ - NCR53c406a_dma_read(current_SC->request_buffer, current_SC->request_bufflen); + NCR53c406a_dma_read(scsi_sglist(current_SC), + scsdi_bufflen(current_SC)); #endif /* USE_DMA */ outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO - if (!current_SC->use_sg) /* Don't use scatter-gather */ - NCR53c406a_pio_read(current_SC->request_buffer, current_SC->request_bufflen); - else { /* Use scatter-gather */ - sgcount = current_SC->use_sg; - sglist = current_SC->request_buffer; - while (sgcount--) { - NCR53c406a_pio_read(page_address(sglist->page) + sglist->offset, sglist->length); - sglist++; - } - } + scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) { + NCR53c406a_pio_read(page_address(sg->page) + sg->offset, + sg->length); + } REG0; #endif /* USE_PIO */ } diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 7f4241bfb9c4..7cedc722fad9 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -796,7 +796,7 @@ static void orc_interrupt( *****************************************************************************/ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, struct scsi_cmnd * SCpnt) { /* Create corresponding SCB */ - struct scatterlist *pSrbSG; + struct scatterlist *sg; ORC_SG *pSG; /* Pointer to SG list */ int i, count_sg; ESCB *pEScb; @@ -813,30 +813,22 @@ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, struct scsi_cmnd * S pSCB->SCB_Reserved1 = 0; pSCB->SCB_SGLen = 0; - if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) { - pSG = (ORC_SG *) & pEScb->ESCB_SGList[0]; - if (SCpnt->use_sg) { - pSrbSG = (struct scatterlist *) SCpnt->request_buffer; - count_sg = pci_map_sg(pHCB->pdev, pSrbSG, SCpnt->use_sg, - SCpnt->sc_data_direction); - pSCB->SCB_SGLen = (U32) (count_sg * 8); - for (i = 0; i < count_sg; i++, pSG++, pSrbSG++) { - pSG->SG_Ptr = (U32) sg_dma_address(pSrbSG); - pSG->SG_Len = (U32) sg_dma_len(pSrbSG); - } - } else if (SCpnt->request_bufflen != 0) {/* Non SG */ - pSCB->SCB_SGLen = 0x8; - SCpnt->SCp.dma_handle = pci_map_single(pHCB->pdev, - SCpnt->request_buffer, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - pSG->SG_Ptr = (U32) SCpnt->SCp.dma_handle; - pSG->SG_Len = (U32) SCpnt->request_bufflen; - } else { - pSCB->SCB_SGLen = 0; - pSG->SG_Ptr = 0; - pSG->SG_Len = 0; + pSCB->SCB_XferLen = (U32) scsi_bufflen(SCpnt); + pSG = (ORC_SG *) & pEScb->ESCB_SGList[0]; + + count_sg = scsi_dma_map(SCpnt); + BUG_ON(count_sg < 0); + if (count_sg) { + pSCB->SCB_SGLen = (U32) (count_sg * 8); + scsi_for_each_sg(SCpnt, sg, count_sg, i) { + pSG->SG_Ptr = (U32) sg_dma_address(sg); + pSG->SG_Len = (U32) sg_dma_len(sg); + pSG++; } + } else { + pSCB->SCB_SGLen = 0; + pSG->SG_Ptr = 0; + pSG->SG_Len = 0; } pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr; pSCB->SCB_HaStat = 0; @@ -995,15 +987,7 @@ static void inia100SCBPost(BYTE * pHcb, BYTE * pScb) } pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16); - if (pSRB->use_sg) { - pci_unmap_sg(pHCB->pdev, - (struct scatterlist *)pSRB->request_buffer, - pSRB->use_sg, pSRB->sc_data_direction); - } else if (pSRB->request_bufflen != 0) { - pci_unmap_single(pHCB->pdev, pSRB->SCp.dma_handle, - pSRB->request_bufflen, - pSRB->sc_data_direction); - } + scsi_dma_unmap(pSRB); pSRB->scsi_done(pSRB); /* Notify system DONE */ diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 8dcfe4ec35c2..47014beef96e 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -825,7 +825,7 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); readcmd->count = cpu_to_le32(count<<9); readcmd->cid = cpu_to_le16(scmd_id(cmd)); - readcmd->flags = cpu_to_le16(1); + readcmd->flags = cpu_to_le16(IO_TYPE_READ); readcmd->bpTotal = 0; readcmd->bpComplete = 0; @@ -904,7 +904,7 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 (void *) cmd); } -static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua) { u16 fibsize; struct aac_raw_io *writecmd; @@ -914,7 +914,9 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); writecmd->count = cpu_to_le32(count<<9); writecmd->cid = cpu_to_le16(scmd_id(cmd)); - writecmd->flags = 0; + writecmd->flags = fua ? + cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) : + cpu_to_le16(IO_TYPE_WRITE); writecmd->bpTotal = 0; writecmd->bpComplete = 0; @@ -933,7 +935,7 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u (void *) cmd); } -static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua) { u16 fibsize; struct aac_write64 *writecmd; @@ -964,7 +966,7 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, (void *) cmd); } -static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua) { u16 fibsize; struct aac_write *writecmd; @@ -1498,6 +1500,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) { u64 lba; u32 count; + int fua; int status; struct aac_dev *dev; struct fib * cmd_fibcontext; @@ -1512,6 +1515,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) count = scsicmd->cmnd[4]; if (count == 0) count = 256; + fua = 0; } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd))); @@ -1524,6 +1528,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; + fua = scsicmd->cmnd[1] & 0x8; } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd))); @@ -1531,10 +1536,12 @@ static int aac_write(struct scsi_cmnd * scsicmd) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; + fua = scsicmd->cmnd[1] & 0x8; } else { dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; + fua = scsicmd->cmnd[1] & 0x8; } dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n", smp_processor_id(), (unsigned long long)lba, jiffies)); @@ -1549,7 +1556,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) return 0; } - status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count); + status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua); /* * Check that the command queued to the controller @@ -1886,15 +1893,29 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case MODE_SENSE: { - char mode_buf[4]; + char mode_buf[7]; + int mode_buf_length = 4; dprintk((KERN_DEBUG "MODE SENSE command.\n")); mode_buf[0] = 3; /* Mode data length */ mode_buf[1] = 0; /* Medium type - default */ - mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ + mode_buf[2] = 0; /* Device-specific param, + bit 8: 0/1 = write enabled/protected + bit 4: 0/1 = FUA enabled */ + if (dev->raw_io_interface) + mode_buf[2] = 0x10; mode_buf[3] = 0; /* Block descriptor length */ - - aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); + if (((scsicmd->cmnd[2] & 0x3f) == 8) || + ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) { + mode_buf[0] = 6; + mode_buf[4] = 8; + mode_buf[5] = 1; + mode_buf[6] = 0x04; /* WCE */ + mode_buf_length = 7; + if (mode_buf_length > scsicmd->cmnd[4]) + mode_buf_length = scsicmd->cmnd[4]; + } + aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); @@ -1902,18 +1923,33 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) } case MODE_SENSE_10: { - char mode_buf[8]; + char mode_buf[11]; + int mode_buf_length = 8; dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); mode_buf[0] = 0; /* Mode data length (MSB) */ mode_buf[1] = 6; /* Mode data length (LSB) */ mode_buf[2] = 0; /* Medium type - default */ - mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ + mode_buf[3] = 0; /* Device-specific param, + bit 8: 0/1 = write enabled/protected + bit 4: 0/1 = FUA enabled */ + if (dev->raw_io_interface) + mode_buf[3] = 0x10; mode_buf[4] = 0; /* reserved */ mode_buf[5] = 0; /* reserved */ mode_buf[6] = 0; /* Block descriptor length (MSB) */ mode_buf[7] = 0; /* Block descriptor length (LSB) */ - aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); + if (((scsicmd->cmnd[2] & 0x3f) == 8) || + ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) { + mode_buf[1] = 9; + mode_buf[8] = 8; + mode_buf[9] = 1; + mode_buf[10] = 0x04; /* WCE */ + mode_buf_length = 11; + if (mode_buf_length > scsicmd->cmnd[8]) + mode_buf_length = scsicmd->cmnd[8]; + } + aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index c81edf36913f..fdbedb17d03b 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -464,12 +464,12 @@ struct adapter_ops int (*adapter_restart)(struct aac_dev *dev, int bled); /* Transport operations */ int (*adapter_ioremap)(struct aac_dev * dev, u32 size); - irqreturn_t (*adapter_intr)(int irq, void *dev_id); + irq_handler_t adapter_intr; /* Packet operations */ int (*adapter_deliver)(struct fib * fib); int (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba); int (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); - int (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); + int (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua); int (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd); /* Administrative operations */ int (*adapter_comm)(struct aac_dev * dev, int comm); @@ -1054,8 +1054,8 @@ struct aac_dev #define aac_adapter_read(fib,cmd,lba,count) \ ((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count) -#define aac_adapter_write(fib,cmd,lba,count) \ - ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count) +#define aac_adapter_write(fib,cmd,lba,count,fua) \ + ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count,fua) #define aac_adapter_scsi(fib,cmd) \ ((fib)->dev)->a_ops.adapter_scsi(fib,cmd) @@ -1213,6 +1213,9 @@ struct aac_write64 __le32 block; __le16 pad; __le16 flags; +#define IO_TYPE_WRITE 0x00000000 +#define IO_TYPE_READ 0x00000001 +#define IO_SUREWRITE 0x00000008 struct sgmap64 sg; // Must be last in struct because it is variable }; struct aac_write_reply diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 350ea7feb61d..a270a3f00647 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -403,10 +403,6 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, static int aac_slave_configure(struct scsi_device *sdev) { - if (sdev_channel(sdev) == CONTAINER_CHANNEL) { - sdev->skip_ms_page_8 = 1; - sdev->skip_ms_page_3f = 1; - } if ((sdev->type == TYPE_DISK) && (sdev_channel(sdev) != CONTAINER_CHANNEL)) { if (expose_physicals == 0) diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 9b3303b64113..2b6689709e53 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -798,7 +798,6 @@ #include <scsi/scsi_tcq.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> -#include "advansys.h" #ifdef CONFIG_PCI #include <linux/pci.h> #endif /* CONFIG_PCI */ @@ -2014,7 +2013,7 @@ STATIC int AscSgListToQueue(int); STATIC void AscEnableIsaDma(uchar); #endif /* CONFIG_ISA */ STATIC ASC_DCNT AscGetMaxDmaCount(ushort); - +static const char *advansys_info(struct Scsi_Host *shp); /* * --- Adv Library Constants and Macros @@ -3970,10 +3969,6 @@ STATIC ushort asc_bus[ASC_NUM_BUS] __initdata = { ASC_IS_PCI, }; -/* - * Used with the LILO 'advansys' option to eliminate or - * limit I/O port probing at boot time, cf. advansys_setup(). - */ STATIC int asc_iopflag = ASC_FALSE; STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; @@ -4055,10 +4050,6 @@ STATIC void asc_prt_hex(char *f, uchar *, int); #endif /* ADVANSYS_DEBUG */ -/* - * --- Linux 'struct scsi_host_template' and advansys_setup() Functions - */ - #ifdef CONFIG_PROC_FS /* * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] @@ -4080,7 +4071,7 @@ STATIC void asc_prt_hex(char *f, uchar *, int); * if 'prtbuf' is too small it will not be overwritten. Instead the * user just won't get all the available statistics. */ -int +static int advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int inout) { @@ -4296,7 +4287,7 @@ advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, * it must not call SCSI mid-level functions including scsi_malloc() * and scsi_free(). */ -int __init +static int __init advansys_detect(struct scsi_host_template *tpnt) { static int detect_called = ASC_FALSE; @@ -5428,7 +5419,7 @@ advansys_detect(struct scsi_host_template *tpnt) * * Release resources allocated for a single AdvanSys adapter. */ -int +static int advansys_release(struct Scsi_Host *shp) { asc_board_t *boardp; @@ -5475,7 +5466,7 @@ advansys_release(struct Scsi_Host *shp) * Note: The information line should not exceed ASC_INFO_SIZE bytes, * otherwise the static 'info' array will be overrun. */ -const char * +static const char * advansys_info(struct Scsi_Host *shp) { static char info[ASC_INFO_SIZE]; @@ -5568,7 +5559,7 @@ advansys_info(struct Scsi_Host *shp) * This function always returns 0. Command return status is saved * in the 'scp' result field. */ -int +static int advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) { struct Scsi_Host *shp; @@ -5656,7 +5647,7 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) * sleeping is allowed and no locking other than for host structures is * required. Returns SUCCESS or FAILED. */ -int +static int advansys_reset(struct scsi_cmnd *scp) { struct Scsi_Host *shp; @@ -5841,7 +5832,7 @@ advansys_reset(struct scsi_cmnd *scp) * ip[1]: sectors * ip[2]: cylinders */ -int +static int advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int ip[]) { @@ -5875,82 +5866,6 @@ advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, } /* - * advansys_setup() - * - * This function is called from init/main.c at boot time. - * It it passed LILO parameters that can be set from the - * LILO command line or in /etc/lilo.conf. - * - * It is used by the AdvanSys driver to either disable I/O - * port scanning or to limit scanning to 1 - 4 I/O ports. - * Regardless of the option setting EISA and PCI boards - * will still be searched for and detected. This option - * only affects searching for ISA and VL boards. - * - * If ADVANSYS_DEBUG is defined the driver debug level may - * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. - * - * Examples: - * 1. Eliminate I/O port scanning: - * boot: linux advansys= - * or - * boot: linux advansys=0x0 - * 2. Limit I/O port scanning to one I/O port: - * boot: linux advansys=0x110 - * 3. Limit I/O port scanning to four I/O ports: - * boot: linux advansys=0x110,0x210,0x230,0x330 - * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and - * set the driver debug level to 2. - * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2 - * - * ints[0] - number of arguments - * ints[1] - first argument - * ints[2] - second argument - * ... - */ -void __init -advansys_setup(char *str, int *ints) -{ - int i; - - if (asc_iopflag == ASC_TRUE) { - printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n"); - return; - } - - asc_iopflag = ASC_TRUE; - - if (ints[0] > ASC_NUM_IOPORT_PROBE) { -#ifdef ADVANSYS_DEBUG - if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) && - (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) { - asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf; - } else { -#endif /* ADVANSYS_DEBUG */ - printk("AdvanSys SCSI: only %d I/O ports accepted\n", - ASC_NUM_IOPORT_PROBE); -#ifdef ADVANSYS_DEBUG - } -#endif /* ADVANSYS_DEBUG */ - } - -#ifdef ADVANSYS_DEBUG - ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]); - for (i = 1; i < ints[0]; i++) { - ASC_DBG2(1, " ints[%d] 0x%x", i, ints[i]); - } - ASC_DBG(1, "\n"); -#endif /* ADVANSYS_DEBUG */ - - for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) { - asc_ioport[i-1] = ints[i]; - ASC_DBG2(1, "advansys_setup: asc_ioport[%d] 0x%x\n", - i - 1, asc_ioport[i-1]); - } -} - - -/* * --- Loadable Driver Support */ diff --git a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h deleted file mode 100644 index 8ee7fb16a725..000000000000 --- a/drivers/scsi/advansys.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters - * - * Copyright (c) 1995-2000 Advanced System Products, Inc. - * Copyright (c) 2000-2001 ConnectCom Solutions, Inc. - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that redistributions of source - * code retain the above copyright notice and this comment without - * modification. - * - * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys) - * changed its name to ConnectCom Solutions, Inc. - * - */ - -#ifndef _ADVANSYS_H -#define _ADVANSYS_H - -/* - * struct scsi_host_template function prototypes. - */ -int advansys_detect(struct scsi_host_template *); -int advansys_release(struct Scsi_Host *); -const char *advansys_info(struct Scsi_Host *); -int advansys_queuecommand(struct scsi_cmnd *, void (* done)(struct scsi_cmnd *)); -int advansys_reset(struct scsi_cmnd *); -int advansys_biosparam(struct scsi_device *, struct block_device *, - sector_t, int[]); -static int advansys_slave_configure(struct scsi_device *); - -/* init/main.c setup function */ -void advansys_setup(char *, int *); - -#endif /* _ADVANSYS_H */ diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 4b4d1233ce8a..85f2394ffc3e 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -240,6 +240,7 @@ #include <linux/io.h> #include <linux/blkdev.h> #include <asm/system.h> +#include <linux/completion.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/wait.h> @@ -253,7 +254,6 @@ #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/list.h> -#include <asm/semaphore.h> #include <scsi/scsicam.h> #include "scsi.h" @@ -551,7 +551,7 @@ struct aha152x_hostdata { */ struct aha152x_scdata { Scsi_Cmnd *next; /* next sc in queue */ - struct semaphore *sem; /* semaphore to block on */ + struct completion *done;/* semaphore to block on */ unsigned char cmd_len; unsigned char cmnd[MAX_COMMAND_SIZE]; unsigned short use_sg; @@ -608,7 +608,7 @@ struct aha152x_scdata { #define SCDATA(SCpnt) ((struct aha152x_scdata *) (SCpnt)->host_scribble) #define SCNEXT(SCpnt) SCDATA(SCpnt)->next -#define SCSEM(SCpnt) SCDATA(SCpnt)->sem +#define SCSEM(SCpnt) SCDATA(SCpnt)->done #define SG_ADDRESS(buffer) ((char *) (page_address((buffer)->page)+(buffer)->offset)) @@ -969,7 +969,8 @@ static int setup_expected_interrupts(struct Scsi_Host *shpnt) /* * Queue a command and setup interrupts for a free bus. */ -static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, void (*done)(Scsi_Cmnd *)) +static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete, + int phase, void (*done)(Scsi_Cmnd *)) { struct Scsi_Host *shpnt = SCpnt->device->host; unsigned long flags; @@ -1013,7 +1014,7 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int p } SCNEXT(SCpnt) = NULL; - SCSEM(SCpnt) = sem; + SCSEM(SCpnt) = complete; /* setup scratch area SCp.ptr : buffer pointer @@ -1084,9 +1085,9 @@ static void reset_done(Scsi_Cmnd *SCpnt) DPRINTK(debug_eh, INFO_LEAD "reset_done called\n", CMDINFO(SCpnt)); #endif if(SCSEM(SCpnt)) { - up(SCSEM(SCpnt)); + complete(SCSEM(SCpnt)); } else { - printk(KERN_ERR "aha152x: reset_done w/o semaphore\n"); + printk(KERN_ERR "aha152x: reset_done w/o completion\n"); } } @@ -1139,21 +1140,6 @@ static int aha152x_abort(Scsi_Cmnd *SCpnt) return FAILED; } -static void timer_expired(unsigned long p) -{ - Scsi_Cmnd *SCp = (Scsi_Cmnd *)p; - struct semaphore *sem = SCSEM(SCp); - struct Scsi_Host *shpnt = SCp->device->host; - unsigned long flags; - - /* remove command from issue queue */ - DO_LOCK(flags); - remove_SC(&ISSUE_SC, SCp); - DO_UNLOCK(flags); - - up(sem); -} - /* * Reset a device * @@ -1161,14 +1147,14 @@ static void timer_expired(unsigned long p) static int aha152x_device_reset(Scsi_Cmnd * SCpnt) { struct Scsi_Host *shpnt = SCpnt->device->host; - DECLARE_MUTEX_LOCKED(sem); - struct timer_list timer; + DECLARE_COMPLETION(done); int ret, issued, disconnected; unsigned char old_cmd_len = SCpnt->cmd_len; unsigned short old_use_sg = SCpnt->use_sg; void *old_buffer = SCpnt->request_buffer; unsigned old_bufflen = SCpnt->request_bufflen; unsigned long flags; + unsigned long timeleft; #if defined(AHA152X_DEBUG) if(HOSTDATA(shpnt)->debug & debug_eh) { @@ -1192,15 +1178,15 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) SCpnt->request_buffer = NULL; SCpnt->request_bufflen = 0; - init_timer(&timer); - timer.data = (unsigned long) SCpnt; - timer.expires = jiffies + 100*HZ; /* 10s */ - timer.function = (void (*)(unsigned long)) timer_expired; + aha152x_internal_queue(SCpnt, &done, resetting, reset_done); - aha152x_internal_queue(SCpnt, &sem, resetting, reset_done); - add_timer(&timer); - down(&sem); - del_timer(&timer); + timeleft = wait_for_completion_timeout(&done, 100*HZ); + if (!timeleft) { + /* remove command from issue queue */ + DO_LOCK(flags); + remove_SC(&ISSUE_SC, SCpnt); + DO_UNLOCK(flags); + } SCpnt->cmd_len = old_cmd_len; SCpnt->use_sg = old_use_sg; diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index d7af9c63a04d..e4a4f3a965d9 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -271,20 +271,8 @@ static irqreturn_t aha1740_intr_handle(int irq, void *dev_id) continue; } sgptr = (struct aha1740_sg *) SCtmp->host_scribble; - if (SCtmp->use_sg) { - /* We used scatter-gather. - Do the unmapping dance. */ - dma_unmap_sg (&edev->dev, - (struct scatterlist *) SCtmp->request_buffer, - SCtmp->use_sg, - SCtmp->sc_data_direction); - } else { - dma_unmap_single (&edev->dev, - sgptr->buf_dma_addr, - SCtmp->request_bufflen, - DMA_BIDIRECTIONAL); - } - + scsi_dma_unmap(SCtmp); + /* Free the sg block */ dma_free_coherent (&edev->dev, sizeof (struct aha1740_sg), @@ -349,11 +337,9 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) unchar target = scmd_id(SCpnt); struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host); unsigned long flags; - void *buff = SCpnt->request_buffer; - int bufflen = SCpnt->request_bufflen; dma_addr_t sg_dma; struct aha1740_sg *sgptr; - int ecbno; + int ecbno, nseg; DEB(int i); if(*cmd == REQUEST_SENSE) { @@ -423,24 +409,23 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) } sgptr = (struct aha1740_sg *) SCpnt->host_scribble; sgptr->sg_dma_addr = sg_dma; - - if (SCpnt->use_sg) { - struct scatterlist * sgpnt; + + nseg = scsi_dma_map(SCpnt); + BUG_ON(nseg < 0); + if (nseg) { + struct scatterlist *sg; struct aha1740_chain * cptr; - int i, count; + int i; DEB(unsigned char * ptr); host->ecb[ecbno].sg = 1; /* SCSI Initiator Command * w/scatter-gather*/ - sgpnt = (struct scatterlist *) SCpnt->request_buffer; cptr = sgptr->sg_chain; - count = dma_map_sg (&host->edev->dev, sgpnt, SCpnt->use_sg, - SCpnt->sc_data_direction); - for(i=0; i < count; i++) { - cptr[i].datalen = sg_dma_len (sgpnt + i); - cptr[i].dataptr = sg_dma_address (sgpnt + i); + scsi_for_each_sg(SCpnt, sg, nseg, i) { + cptr[i].datalen = sg_dma_len (sg); + cptr[i].dataptr = sg_dma_address (sg); } - host->ecb[ecbno].datalen = count*sizeof(struct aha1740_chain); + host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain); host->ecb[ecbno].dataptr = sg_dma; #ifdef DEBUG printk("cptr %x: ",cptr); @@ -448,11 +433,8 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) for(i=0;i<24;i++) printk("%02x ", ptr[i]); #endif } else { - host->ecb[ecbno].datalen = bufflen; - sgptr->buf_dma_addr = dma_map_single (&host->edev->dev, - buff, bufflen, - DMA_BIDIRECTIONAL); - host->ecb[ecbno].dataptr = sgptr->buf_dma_addr; + host->ecb[ecbno].datalen = 0; + host->ecb[ecbno].dataptr = 0; } host->ecb[ecbno].lun = SCpnt->device->lun; host->ecb[ecbno].ses = 1; /* Suppress underrun errors */ diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 6054881f21f1..286ab83116f9 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -376,21 +376,10 @@ static __inline void ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) { struct scsi_cmnd *cmd; - int direction; cmd = scb->io_ctx; - direction = cmd->sc_data_direction; ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE); - if (cmd->use_sg != 0) { - struct scatterlist *sg; - - sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(ahd->dev_softc, sg, cmd->use_sg, direction); - } else if (cmd->request_bufflen != 0) { - pci_unmap_single(ahd->dev_softc, - scb->platform_data->buf_busaddr, - cmd->request_bufflen, direction); - } + scsi_dma_unmap(cmd); } /******************************** Macros **************************************/ @@ -1422,6 +1411,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, u_int col_idx; uint16_t mask; unsigned long flags; + int nseg; ahd_lock(ahd, &flags); @@ -1494,18 +1484,17 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, ahd_set_residual(scb, 0); ahd_set_sense_residual(scb, 0); scb->sg_count = 0; - if (cmd->use_sg != 0) { - void *sg; - struct scatterlist *cur_seg; - u_int nseg; - int dir; - - cur_seg = (struct scatterlist *)cmd->request_buffer; - dir = cmd->sc_data_direction; - nseg = pci_map_sg(ahd->dev_softc, cur_seg, - cmd->use_sg, dir); + + nseg = scsi_dma_map(cmd); + BUG_ON(nseg < 0); + if (nseg > 0) { + void *sg = scb->sg_list; + struct scatterlist *cur_seg; + int i; + scb->platform_data->xfer_len = 0; - for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { + + scsi_for_each_sg(cmd, cur_seg, nseg, i) { dma_addr_t addr; bus_size_t len; @@ -1513,22 +1502,8 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, len = sg_dma_len(cur_seg); scb->platform_data->xfer_len += len; sg = ahd_sg_setup(ahd, scb, sg, addr, len, - /*last*/nseg == 1); + i == (nseg - 1)); } - } else if (cmd->request_bufflen != 0) { - void *sg; - dma_addr_t addr; - int dir; - - sg = scb->sg_list; - dir = cmd->sc_data_direction; - addr = pci_map_single(ahd->dev_softc, - cmd->request_buffer, - cmd->request_bufflen, dir); - scb->platform_data->xfer_len = cmd->request_bufflen; - scb->platform_data->buf_busaddr = addr; - sg = ahd_sg_setup(ahd, scb, sg, addr, - cmd->request_bufflen, /*last*/TRUE); } LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index ad9761b237dc..853998be1474 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -781,7 +781,7 @@ int ahd_get_transfer_dir(struct scb *scb) static __inline void ahd_set_residual(struct scb *scb, u_long resid) { - scb->io_ctx->resid = resid; + scsi_set_resid(scb->io_ctx, resid); } static __inline @@ -793,7 +793,7 @@ void ahd_set_sense_residual(struct scb *scb, u_long resid) static __inline u_long ahd_get_residual(struct scb *scb) { - return (scb->io_ctx->resid); + return scsi_get_resid(scb->io_ctx); } static __inline diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 660f26e23a38..1803ab6fc21c 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -402,18 +402,8 @@ ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) cmd = scb->io_ctx; ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE); - if (cmd->use_sg != 0) { - struct scatterlist *sg; - - sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg, - cmd->sc_data_direction); - } else if (cmd->request_bufflen != 0) { - pci_unmap_single(ahc->dev_softc, - scb->platform_data->buf_busaddr, - cmd->request_bufflen, - cmd->sc_data_direction); - } + + scsi_dma_unmap(cmd); } static __inline int @@ -1381,6 +1371,7 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev, struct ahc_tmode_tstate *tstate; uint16_t mask; struct scb_tailq *untagged_q = NULL; + int nseg; /* * Schedule us to run later. The only reason we are not @@ -1472,23 +1463,21 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev, ahc_set_residual(scb, 0); ahc_set_sense_residual(scb, 0); scb->sg_count = 0; - if (cmd->use_sg != 0) { + + nseg = scsi_dma_map(cmd); + BUG_ON(nseg < 0); + if (nseg > 0) { struct ahc_dma_seg *sg; struct scatterlist *cur_seg; - struct scatterlist *end_seg; - int nseg; + int i; - cur_seg = (struct scatterlist *)cmd->request_buffer; - nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg, - cmd->sc_data_direction); - end_seg = cur_seg + nseg; /* Copy the segments into the SG list. */ sg = scb->sg_list; /* * The sg_count may be larger than nseg if * a transfer crosses a 32bit page. - */ - while (cur_seg < end_seg) { + */ + scsi_for_each_sg(cmd, cur_seg, nseg, i) { dma_addr_t addr; bus_size_t len; int consumed; @@ -1499,7 +1488,6 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev, sg, addr, len); sg += consumed; scb->sg_count += consumed; - cur_seg++; } sg--; sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); @@ -1516,33 +1504,6 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev, */ scb->hscb->dataptr = scb->sg_list->addr; scb->hscb->datacnt = scb->sg_list->len; - } else if (cmd->request_bufflen != 0) { - struct ahc_dma_seg *sg; - dma_addr_t addr; - - sg = scb->sg_list; - addr = pci_map_single(ahc->dev_softc, - cmd->request_buffer, - cmd->request_bufflen, - cmd->sc_data_direction); - scb->platform_data->buf_busaddr = addr; - scb->sg_count = ahc_linux_map_seg(ahc, scb, - sg, addr, - cmd->request_bufflen); - sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); - - /* - * Reset the sg list pointer. - */ - scb->hscb->sgptr = - ahc_htole32(scb->sg_list_phys | SG_FULL_RESID); - - /* - * Copy the first SG into the "current" - * data pointer area. - */ - scb->hscb->dataptr = sg->addr; - scb->hscb->datacnt = sg->len; } else { scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL); scb->hscb->dataptr = 0; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 8fee7edc6eb3..b48dab447bde 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -751,7 +751,7 @@ int ahc_get_transfer_dir(struct scb *scb) static __inline void ahc_set_residual(struct scb *scb, u_long resid) { - scb->io_ctx->resid = resid; + scsi_set_resid(scb->io_ctx, resid); } static __inline @@ -763,7 +763,7 @@ void ahc_set_sense_residual(struct scb *scb, u_long resid) static __inline u_long ahc_get_residual(struct scb *scb) { - return (scb->io_ctx->resid); + return scsi_get_resid(scb->io_ctx); } static __inline diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index a988d5abf702..f5e3c6b27c70 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -2690,17 +2690,8 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb) struct aic7xxx_scb *scbp; unsigned char queue_depth; - if (cmd->use_sg > 1) - { - struct scatterlist *sg; + scsi_dma_unmap(cmd); - sg = (struct scatterlist *)cmd->request_buffer; - pci_unmap_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction); - } - else if (cmd->request_bufflen) - pci_unmap_single(p->pdev, aic7xxx_mapping(cmd), - cmd->request_bufflen, - cmd->sc_data_direction); if (scb->flags & SCB_SENSE) { pci_unmap_single(p->pdev, @@ -3869,7 +3860,7 @@ aic7xxx_calculate_residual (struct aic7xxx_host *p, struct aic7xxx_scb *scb) * the mid layer didn't check residual data counts to see if the * command needs retried. */ - cmd->resid = scb->sg_length - actual; + scsi_set_resid(cmd, scb->sg_length - actual); aic7xxx_status(cmd) = hscb->target_status; } } @@ -10137,6 +10128,7 @@ static void aic7xxx_buildscb(struct aic7xxx_host *p, struct scsi_cmnd *cmd, struct scsi_device *sdptr = cmd->device; unsigned char tindex = TARGET_INDEX(cmd); struct request *req = cmd->request; + int use_sg; mask = (0x01 << tindex); hscb = scb->hscb; @@ -10209,8 +10201,10 @@ static void aic7xxx_buildscb(struct aic7xxx_host *p, struct scsi_cmnd *cmd, memcpy(scb->cmnd, cmd->cmnd, cmd->cmd_len); hscb->SCSI_cmd_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, scb->cmnd)); - if (cmd->use_sg) - { + use_sg = scsi_dma_map(cmd); + BUG_ON(use_sg < 0); + + if (use_sg) { struct scatterlist *sg; /* Must be mid-level SCSI code scatterlist */ /* @@ -10219,11 +10213,11 @@ static void aic7xxx_buildscb(struct aic7xxx_host *p, struct scsi_cmnd *cmd, * differences and the kernel SG list uses virtual addresses where * we need physical addresses. */ - int i, use_sg; + int i; - sg = (struct scatterlist *)cmd->request_buffer; scb->sg_length = 0; - use_sg = pci_map_sg(p->pdev, sg, cmd->use_sg, cmd->sc_data_direction); + + /* * Copy the segments into the SG array. NOTE!!! - We used to * have the first entry both in the data_pointer area and the first @@ -10231,10 +10225,9 @@ static void aic7xxx_buildscb(struct aic7xxx_host *p, struct scsi_cmnd *cmd, * entry in both places, but now we download the address of * scb->sg_list[1] instead of 0 to the sg pointer in the hscb. */ - for (i = 0; i < use_sg; i++) - { - unsigned int len = sg_dma_len(sg+i); - scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg+i)); + scsi_for_each_sg(cmd, sg, use_sg, i) { + unsigned int len = sg_dma_len(sg); + scb->sg_list[i].address = cpu_to_le32(sg_dma_address(sg)); scb->sg_list[i].length = cpu_to_le32(len); scb->sg_length += len; } @@ -10244,33 +10237,13 @@ static void aic7xxx_buildscb(struct aic7xxx_host *p, struct scsi_cmnd *cmd, scb->sg_count = i; hscb->SG_segment_count = i; hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[1])); - } - else - { - if (cmd->request_bufflen) - { - unsigned int address = pci_map_single(p->pdev, cmd->request_buffer, - cmd->request_bufflen, - cmd->sc_data_direction); - aic7xxx_mapping(cmd) = address; - scb->sg_list[0].address = cpu_to_le32(address); - scb->sg_list[0].length = cpu_to_le32(cmd->request_bufflen); - scb->sg_count = 1; - scb->sg_length = cmd->request_bufflen; - hscb->SG_segment_count = 1; - hscb->SG_list_pointer = cpu_to_le32(SCB_DMA_ADDR(scb, &scb->sg_list[0])); - hscb->data_count = scb->sg_list[0].length; - hscb->data_pointer = scb->sg_list[0].address; - } - else - { + } else { scb->sg_count = 0; scb->sg_length = 0; hscb->SG_segment_count = 0; hscb->SG_list_pointer = 0; hscb->data_count = 0; hscb->data_pointer = 0; - } } } diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c deleted file mode 100644 index d5d3c4d5a253..000000000000 --- a/drivers/scsi/amiga7xx.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux. - * Amiga MacroSystemUS WarpEngine SCSI controller. - * Amiga Technologies A4000T SCSI controller. - * Amiga Technologies/DKB A4091 SCSI controller. - * - * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk> - * plus modifications of the 53c7xx.c driver to support the Amiga. - */ -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/blkdev.h> -#include <linux/zorro.h> -#include <linux/stat.h> - -#include <asm/setup.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/amigaints.h> -#include <asm/amigahw.h> -#include <asm/dma.h> -#include <asm/irq.h> - -#include "scsi.h" -#include <scsi/scsi_host.h> -#include "53c7xx.h" -#include "amiga7xx.h" - - -static int amiga7xx_register_one(struct scsi_host_template *tpnt, - unsigned long address) -{ - long long options; - int clock; - - if (!request_mem_region(address, 0x1000, "ncr53c710")) - return 0; - - address = (unsigned long)z_ioremap(address, 0x1000); - options = OPTION_MEMORY_MAPPED | OPTION_DEBUG_TEST1 | OPTION_INTFLY | - OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS | - OPTION_DISCONNECT; - clock = 50000000; /* 50 MHz SCSI Clock */ - ncr53c7xx_init(tpnt, 0, 710, address, 0, IRQ_AMIGA_PORTS, DMA_NONE, - options, clock); - return 1; -} - - -#ifdef CONFIG_ZORRO - -static struct { - zorro_id id; - unsigned long offset; - int absolute; /* offset is absolute address */ -} amiga7xx_table[] = { - { .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, .offset = 0xf40000, - .absolute = 1 }, - { .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, .offset = 0x40000 }, - { .id = ZORRO_PROD_CBM_A4091_1, .offset = 0x800000 }, - { .id = ZORRO_PROD_CBM_A4091_2, .offset = 0x800000 }, - { .id = ZORRO_PROD_GVP_GFORCE_040_060, .offset = 0x40000 }, - { 0 } -}; - -static int __init amiga7xx_zorro_detect(struct scsi_host_template *tpnt) -{ - int num = 0, i; - struct zorro_dev *z = NULL; - unsigned long address; - - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - for (i = 0; amiga7xx_table[i].id; i++) - if (z->id == amiga7xx_table[i].id) - break; - if (!amiga7xx_table[i].id) - continue; - if (amiga7xx_table[i].absolute) - address = amiga7xx_table[i].offset; - else - address = z->resource.start + amiga7xx_table[i].offset; - num += amiga7xx_register_one(tpnt, address); - } - return num; -} - -#endif /* CONFIG_ZORRO */ - - -int __init amiga7xx_detect(struct scsi_host_template *tpnt) -{ - static unsigned char called = 0; - int num = 0; - - if (called || !MACH_IS_AMIGA) - return 0; - - tpnt->proc_name = "Amiga7xx"; - - if (AMIGAHW_PRESENT(A4000_SCSI)) - num += amiga7xx_register_one(tpnt, 0xdd0040); - -#ifdef CONFIG_ZORRO - num += amiga7xx_zorro_detect(tpnt); -#endif - - called = 1; - return num; -} - -static int amiga7xx_release(struct Scsi_Host *shost) -{ - if (shost->irq) - free_irq(shost->irq, NULL); - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - scsi_unregister(shost); - return 0; -} - -static struct scsi_host_template driver_template = { - .name = "Amiga NCR53c710 SCSI", - .detect = amiga7xx_detect, - .release = amiga7xx_release, - .queuecommand = NCR53c7xx_queue_command, - .abort = NCR53c7xx_abort, - .reset = NCR53c7xx_reset, - .can_queue = 24, - .this_id = 7, - .sg_tablesize = 63, - .cmd_per_lun = 3, - .use_clustering = DISABLE_CLUSTERING -}; - - -#include "scsi_module.c" diff --git a/drivers/scsi/amiga7xx.h b/drivers/scsi/amiga7xx.h deleted file mode 100644 index 7cd63a996886..000000000000 --- a/drivers/scsi/amiga7xx.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef AMIGA7XX_H - -#include <linux/types.h> - -int amiga7xx_detect(struct scsi_host_template *); -const char *NCR53c7x0_info(void); -int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int NCR53c7xx_abort(Scsi_Cmnd *); -int NCR53c7x0_release (struct Scsi_Host *); -int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int); -void NCR53c7x0_intr(int irq, void *dev_id); - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 3 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 24 -#endif - -#include <scsi/scsicam.h> - -#endif /* AMIGA7XX_H */ diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 8b46158cc045..672df79d7e39 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -369,19 +369,9 @@ static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) { - struct AdapterControlBlock *acb = ccb->acb; struct scsi_cmnd *pcmd = ccb->pcmd; - if (pcmd->use_sg != 0) { - struct scatterlist *sl; - - sl = (struct scatterlist *)pcmd->request_buffer; - pci_unmap_sg(acb->pdev, sl, pcmd->use_sg, pcmd->sc_data_direction); - } - else if (pcmd->request_bufflen != 0) - pci_unmap_single(acb->pdev, - pcmd->SCp.dma_handle, - pcmd->request_bufflen, pcmd->sc_data_direction); + scsi_dma_unmap(pcmd); } static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) @@ -551,6 +541,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, int8_t *psge = (int8_t *)&arcmsr_cdb->u; uint32_t address_lo, address_hi; int arccdbsize = 0x30; + int nseg; ccb->pcmd = pcmd; memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB)); @@ -561,20 +552,20 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len; arcmsr_cdb->Context = (unsigned long)arcmsr_cdb; memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); - if (pcmd->use_sg) { - int length, sgcount, i, cdb_sgcount = 0; - struct scatterlist *sl; - - /* Get Scatter Gather List from scsiport. */ - sl = (struct scatterlist *) pcmd->request_buffer; - sgcount = pci_map_sg(acb->pdev, sl, pcmd->use_sg, - pcmd->sc_data_direction); + + nseg = scsi_dma_map(pcmd); + BUG_ON(nseg < 0); + + if (nseg) { + int length, i, cdb_sgcount = 0; + struct scatterlist *sg; + /* map stor port SG list to our iop SG List. */ - for (i = 0; i < sgcount; i++) { + scsi_for_each_sg(pcmd, sg, nseg, i) { /* Get the physical address of the current data pointer */ - length = cpu_to_le32(sg_dma_len(sl)); - address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sl))); - address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sl))); + length = cpu_to_le32(sg_dma_len(sg)); + address_lo = cpu_to_le32(dma_addr_lo32(sg_dma_address(sg))); + address_hi = cpu_to_le32(dma_addr_hi32(sg_dma_address(sg))); if (address_hi == 0) { struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; @@ -591,32 +582,12 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, psge += sizeof (struct SG64ENTRY); arccdbsize += sizeof (struct SG64ENTRY); } - sl++; cdb_sgcount++; } arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount; - arcmsr_cdb->DataLength = pcmd->request_bufflen; + arcmsr_cdb->DataLength = scsi_bufflen(pcmd); if ( arccdbsize > 256) arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; - } else if (pcmd->request_bufflen) { - dma_addr_t dma_addr; - dma_addr = pci_map_single(acb->pdev, pcmd->request_buffer, - pcmd->request_bufflen, pcmd->sc_data_direction); - pcmd->SCp.dma_handle = dma_addr; - address_lo = cpu_to_le32(dma_addr_lo32(dma_addr)); - address_hi = cpu_to_le32(dma_addr_hi32(dma_addr)); - if (address_hi == 0) { - struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; - pdma_sg->address = address_lo; - pdma_sg->length = pcmd->request_bufflen; - } else { - struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; - pdma_sg->addresshigh = address_hi; - pdma_sg->address = address_lo; - pdma_sg->length = pcmd->request_bufflen|IS_SG64_ADDR; - } - arcmsr_cdb->sgcount = 1; - arcmsr_cdb->DataLength = pcmd->request_bufflen; } if (pcmd->sc_data_direction == DMA_TO_DEVICE ) { arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; @@ -848,24 +819,21 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ struct CMD_MESSAGE_FIELD *pcmdmessagefld; int retvalue = 0, transfer_len = 0; char *buffer; + struct scatterlist *sg; uint32_t controlcode = (uint32_t ) cmd->cmnd[5] << 24 | (uint32_t ) cmd->cmnd[6] << 16 | (uint32_t ) cmd->cmnd[7] << 8 | (uint32_t ) cmd->cmnd[8]; /* 4 bytes: Areca io control code */ - if (cmd->use_sg) { - struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; - buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; - if (cmd->use_sg > 1) { - retvalue = ARCMSR_MESSAGE_FAIL; - goto message_out; - } - transfer_len += sg->length; - } else { - buffer = cmd->request_buffer; - transfer_len = cmd->request_bufflen; + sg = scsi_sglist(cmd); + buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + if (scsi_sg_count(cmd) > 1) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; } + transfer_len += sg->length; + if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { retvalue = ARCMSR_MESSAGE_FAIL; goto message_out; @@ -1057,12 +1025,9 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ retvalue = ARCMSR_MESSAGE_FAIL; } message_out: - if (cmd->use_sg) { - struct scatterlist *sg; + sg = scsi_sglist(cmd); + kunmap_atomic(buffer - sg->offset, KM_IRQ0); - sg = (struct scatterlist *) cmd->request_buffer; - kunmap_atomic(buffer - sg->offset, KM_IRQ0); - } return retvalue; } @@ -1085,6 +1050,7 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, case INQUIRY: { unsigned char inqdata[36]; char *buffer; + struct scatterlist *sg; if (cmd->device->lun) { cmd->result = (DID_TIME_OUT << 16); @@ -1104,21 +1070,14 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ strncpy(&inqdata[32], "R001", 4); /* Product Revision */ - if (cmd->use_sg) { - struct scatterlist *sg; - sg = (struct scatterlist *) cmd->request_buffer; - buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; - } else { - buffer = cmd->request_buffer; - } + sg = scsi_sglist(cmd); + buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + memcpy(buffer, inqdata, sizeof(inqdata)); - if (cmd->use_sg) { - struct scatterlist *sg; + sg = scsi_sglist(cmd); + kunmap_atomic(buffer - sg->offset, KM_IRQ0); - sg = (struct scatterlist *) cmd->request_buffer; - kunmap_atomic(buffer - sg->offset, KM_IRQ0); - } cmd->scsi_done(cmd); } break; diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c deleted file mode 100644 index 599b400a3c43..000000000000 --- a/drivers/scsi/bvme6000.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Detection routine for the NCR53c710 based BVME6000 SCSI Controllers for Linux. - * - * Based on work by Alan Hourihane - */ -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/blkdev.h> -#include <linux/zorro.h> - -#include <asm/setup.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/bvme6000hw.h> -#include <asm/irq.h> - -#include "scsi.h" -#include <scsi/scsi_host.h> -#include "53c7xx.h" -#include "bvme6000.h" - -#include<linux/stat.h> - - -int bvme6000_scsi_detect(struct scsi_host_template *tpnt) -{ - static unsigned char called = 0; - int clock; - long long options; - - if (called) - return 0; - if (!MACH_IS_BVME6000) - return 0; - - tpnt->proc_name = "BVME6000"; - - options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT; - - clock = 40000000; /* 66MHz SCSI Clock */ - - ncr53c7xx_init(tpnt, 0, 710, (unsigned long)BVME_NCR53C710_BASE, - 0, BVME_IRQ_SCSI, DMA_NONE, - options, clock); - called = 1; - return 1; -} - -static int bvme6000_scsi_release(struct Scsi_Host *shost) -{ - if (shost->irq) - free_irq(shost->irq, NULL); - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - scsi_unregister(shost); - return 0; -} - -static struct scsi_host_template driver_template = { - .name = "BVME6000 NCR53c710 SCSI", - .detect = bvme6000_scsi_detect, - .release = bvme6000_scsi_release, - .queuecommand = NCR53c7xx_queue_command, - .abort = NCR53c7xx_abort, - .reset = NCR53c7xx_reset, - .can_queue = 24, - .this_id = 7, - .sg_tablesize = 63, - .cmd_per_lun = 3, - .use_clustering = DISABLE_CLUSTERING -}; - - -#include "scsi_module.c" diff --git a/drivers/scsi/bvme6000.h b/drivers/scsi/bvme6000.h deleted file mode 100644 index ea3e4b2b9220..000000000000 --- a/drivers/scsi/bvme6000.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef BVME6000_SCSI_H -#define BVME6000_SCSI_H - -#include <linux/types.h> - -int bvme6000_scsi_detect(struct scsi_host_template *); -const char *NCR53c7x0_info(void); -int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int NCR53c7xx_abort(Scsi_Cmnd *); -int NCR53c7x0_release (struct Scsi_Host *); -int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int); -void NCR53c7x0_intr(int irq, void *dev_id); - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 3 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 24 -#endif - -#include <scsi/scsicam.h> - -#endif /* BVME6000_SCSI_H */ diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index 2d38025861a5..a83e9f150b97 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1609,8 +1609,9 @@ static int eata2x_detect(struct scsi_host_template *tpnt) static void map_dma(unsigned int i, struct hostdata *ha) { - unsigned int k, count, pci_dir; - struct scatterlist *sgpnt; + unsigned int k, pci_dir; + int count; + struct scatterlist *sg; struct mscp *cpp; struct scsi_cmnd *SCpnt; @@ -1625,38 +1626,19 @@ static void map_dma(unsigned int i, struct hostdata *ha) cpp->sense_len = sizeof SCpnt->sense_buffer; - if (!SCpnt->use_sg) { - - /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */ - if (!SCpnt->request_bufflen) - pci_dir = PCI_DMA_BIDIRECTIONAL; - - if (SCpnt->request_buffer) - cpp->data_address = H2DEV(pci_map_single(ha->pdev, - SCpnt-> - request_buffer, - SCpnt-> - request_bufflen, - pci_dir)); - - cpp->data_len = H2DEV(SCpnt->request_bufflen); - return; - } - - sgpnt = (struct scatterlist *)SCpnt->request_buffer; - count = pci_map_sg(ha->pdev, sgpnt, SCpnt->use_sg, pci_dir); - - for (k = 0; k < count; k++) { - cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k])); - cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k])); + count = scsi_dma_map(SCpnt); + BUG_ON(count < 0); + scsi_for_each_sg(SCpnt, sg, count, k) { + cpp->sglist[k].address = H2DEV(sg_dma_address(sg)); + cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg)); } cpp->sg = 1; cpp->data_address = H2DEV(pci_map_single(ha->pdev, cpp->sglist, - SCpnt->use_sg * + scsi_sg_count(SCpnt) * sizeof(struct sg_list), pci_dir)); - cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list))); + cpp->data_len = H2DEV((scsi_sg_count(SCpnt) * sizeof(struct sg_list))); } static void unmap_dma(unsigned int i, struct hostdata *ha) @@ -1673,9 +1655,7 @@ static void unmap_dma(unsigned int i, struct hostdata *ha) pci_unmap_single(ha->pdev, DEV2H(cpp->sense_addr), DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - if (SCpnt->use_sg) - pci_unmap_sg(ha->pdev, SCpnt->request_buffer, SCpnt->use_sg, - pci_dir); + scsi_dma_unmap(SCpnt); if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; @@ -1700,9 +1680,9 @@ static void sync_dma(unsigned int i, struct hostdata *ha) DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - if (SCpnt->use_sg) - pci_dma_sync_sg_for_cpu(ha->pdev, SCpnt->request_buffer, - SCpnt->use_sg, pci_dir); + if (scsi_sg_count(SCpnt)) + pci_dma_sync_sg_for_cpu(ha->pdev, scsi_sglist(SCpnt), + scsi_sg_count(SCpnt), pci_dir); if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 5d4ea6f77953..36169d597e98 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -410,6 +410,8 @@ static irqreturn_t do_fdomain_16x0_intr( int irq, void *dev_id ); static char * fdomain = NULL; module_param(fdomain, charp, 0); +#ifndef PCMCIA + static unsigned long addresses[] = { 0xc8000, 0xca000, @@ -426,6 +428,8 @@ static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; +#endif /* !PCMCIA */ + /* READ THIS BEFORE YOU ADD A SIGNATURE! @@ -458,6 +462,8 @@ static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; */ +#ifndef PCMCIA + static struct signature { const char *signature; int sig_offset; @@ -503,6 +509,8 @@ static struct signature { #define SIGNATURE_COUNT ARRAY_SIZE(signatures) +#endif /* !PCMCIA */ + static void print_banner( struct Scsi_Host *shpnt ) { if (!shpnt) return; /* This won't ever happen */ @@ -633,6 +641,8 @@ static int fdomain_test_loopback( void ) return 0; } +#ifndef PCMCIA + /* fdomain_get_irq assumes that we have a valid MCA ID for a TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the bios_base matches these ports. If someone was unlucky enough to have @@ -667,7 +677,6 @@ static int fdomain_get_irq( int base ) static int fdomain_isa_detect( int *irq, int *iobase ) { -#ifndef PCMCIA int i, j; int base = 0xdeadbeef; int flag = 0; @@ -786,11 +795,22 @@ found: *iobase = base; return 1; /* success */ -#else - return 0; -#endif } +#else /* PCMCIA */ + +static int fdomain_isa_detect( int *irq, int *iobase ) +{ + if (irq) + *irq = 0; + if (iobase) + *iobase = 0; + return 0; +} + +#endif /* !PCMCIA */ + + /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* iobase) This function gets the Interrupt Level and I/O base address from the PCI configuration registers. */ @@ -1345,16 +1365,15 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id) #if ERRORS_ONLY if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) { - if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) { + char *buf = scsi_sglist(current_SC); + if ((unsigned char)(*(buf + 2)) & 0x0f) { unsigned char key; unsigned char code; unsigned char qualifier; - key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) - & 0x0f; - code = (unsigned char)(*((char *)current_SC->request_buffer + 12)); - qualifier = (unsigned char)(*((char *)current_SC->request_buffer - + 13)); + key = (unsigned char)(*(buf + 2)) & 0x0f; + code = (unsigned char)(*(buf + 12)); + qualifier = (unsigned char)(*(buf + 13)); if (key != UNIT_ATTENTION && !(key == NOT_READY @@ -1405,8 +1424,8 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt, printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", SCpnt->target, *(unsigned char *)SCpnt->cmnd, - SCpnt->use_sg, - SCpnt->request_bufflen ); + scsi_sg_count(SCpnt), + scsi_bufflen(SCpnt)); #endif fdomain_make_bus_idle(); @@ -1416,20 +1435,19 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt, /* Initialize static data */ - if (current_SC->use_sg) { - current_SC->SCp.buffer = - (struct scatterlist *)current_SC->request_buffer; - current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; - current_SC->SCp.this_residual = current_SC->SCp.buffer->length; - current_SC->SCp.buffers_residual = current_SC->use_sg - 1; + if (scsi_sg_count(current_SC)) { + current_SC->SCp.buffer = scsi_sglist(current_SC); + current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + + current_SC->SCp.buffer->offset; + current_SC->SCp.this_residual = current_SC->SCp.buffer->length; + current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1; } else { - current_SC->SCp.ptr = (char *)current_SC->request_buffer; - current_SC->SCp.this_residual = current_SC->request_bufflen; - current_SC->SCp.buffer = NULL; - current_SC->SCp.buffers_residual = 0; + current_SC->SCp.ptr = 0; + current_SC->SCp.this_residual = 0; + current_SC->SCp.buffer = NULL; + current_SC->SCp.buffers_residual = 0; } - - + current_SC->SCp.Status = 0; current_SC->SCp.Message = 0; current_SC->SCp.have_data_in = 0; @@ -1472,8 +1490,8 @@ static void print_info(struct scsi_cmnd *SCpnt) SCpnt->SCp.phase, SCpnt->device->id, *(unsigned char *)SCpnt->cmnd, - SCpnt->use_sg, - SCpnt->request_bufflen ); + scsi_sg_count(SCpnt), + scsi_bufflen(SCpnt)); printk( "sent_command = %d, have_data_in = %d, timeout = %d\n", SCpnt->SCp.sent_command, SCpnt->SCp.have_data_in, diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 60446b88f721..d0b95ce0ba00 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -876,7 +876,7 @@ static int __init gdth_search_pci(gdth_pci_str *pcistr) /* Vortex only makes RAID controllers. * We do not really want to specify all 550 ids here, so wildcard match. */ -static struct pci_device_id gdthtable[] __attribute_used__ = { +static struct pci_device_id gdthtable[] __maybe_unused = { {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, @@ -1955,7 +1955,7 @@ static int __init gdth_search_drives(int hanum) for (j = 0; j < 12; ++j) rtc[j] = CMOS_READ(j); } while (rtc[0] != CMOS_READ(0)); - spin_lock_irqrestore(&rtc_lock, flags); + spin_unlock_irqrestore(&rtc_lock, flags); TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8])); /* 3. send to controller firmware */ diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 0e57fb6964d5..4275d1b04ced 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -31,14 +31,21 @@ #include <linux/mca.h> #include <linux/spinlock.h> #include <linux/init.h> -#include <linux/mca-legacy.h> #include <asm/system.h> #include <asm/io.h> #include "scsi.h" #include <scsi/scsi_host.h> -#include "ibmmca.h" + +/* Common forward declarations for all Linux-versions: */ +static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +static int ibmmca_abort (Scsi_Cmnd *); +static int ibmmca_host_reset (Scsi_Cmnd *); +static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *); +static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout); + + /* current version of this driver-source: */ #define IBMMCA_SCSI_DRIVER_VERSION "4.0b-ac" @@ -65,11 +72,11 @@ #define IM_DEBUG_CMD_DEVICE TYPE_TAPE /* relative addresses of hardware registers on a subsystem */ -#define IM_CMD_REG(hi) (hosts[(hi)]->io_port) /*Command Interface, (4 bytes long) */ -#define IM_ATTN_REG(hi) (hosts[(hi)]->io_port+4) /*Attention (1 byte) */ -#define IM_CTR_REG(hi) (hosts[(hi)]->io_port+5) /*Basic Control (1 byte) */ -#define IM_INTR_REG(hi) (hosts[(hi)]->io_port+6) /*Interrupt Status (1 byte, r/o) */ -#define IM_STAT_REG(hi) (hosts[(hi)]->io_port+7) /*Basic Status (1 byte, read only) */ +#define IM_CMD_REG(h) ((h)->io_port) /*Command Interface, (4 bytes long) */ +#define IM_ATTN_REG(h) ((h)->io_port+4) /*Attention (1 byte) */ +#define IM_CTR_REG(h) ((h)->io_port+5) /*Basic Control (1 byte) */ +#define IM_INTR_REG(h) ((h)->io_port+6) /*Interrupt Status (1 byte, r/o) */ +#define IM_STAT_REG(h) ((h)->io_port+7) /*Basic Status (1 byte, read only) */ /* basic I/O-port of first adapter */ #define IM_IO_PORT 0x3540 @@ -266,30 +273,36 @@ static int global_adapter_speed = 0; /* full speed by default */ if ((display_mode & LED_ACTIVITY)||(!display_mode)) \ outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); } -/*list of supported subsystems */ -struct subsys_list_struct { - unsigned short mca_id; - char *description; -}; - /* types of different supported hardware that goes to hostdata special */ #define IBM_SCSI2_FW 0 #define IBM_7568_WCACHE 1 #define IBM_EXP_UNIT 2 #define IBM_SCSI_WCACHE 3 #define IBM_SCSI 4 +#define IBM_INTEGSCSI 5 /* other special flags for hostdata structure */ #define FORCED_DETECTION 100 #define INTEGRATED_SCSI 101 /* List of possible IBM-SCSI-adapters */ -static struct subsys_list_struct subsys_list[] = { - {0x8efc, "IBM SCSI-2 F/W Adapter"}, /* special = 0 */ - {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/Cache"}, /* special = 1 */ - {0x8ef8, "IBM Expansion Unit SCSI Controller"}, /* special = 2 */ - {0x8eff, "IBM SCSI Adapter w/Cache"}, /* special = 3 */ - {0x8efe, "IBM SCSI Adapter"}, /* special = 4 */ +static short ibmmca_id_table[] = { + 0x8efc, + 0x8efd, + 0x8ef8, + 0x8eff, + 0x8efe, + /* No entry for integrated SCSI, that's part of the register */ + 0 +}; + +static const char *ibmmca_description[] = { + "IBM SCSI-2 F/W Adapter", /* special = 0 */ + "IBM 7568 Industrial Computer SCSI Adapter w/Cache", /* special = 1 */ + "IBM Expansion Unit SCSI Controller", /* special = 2 */ + "IBM SCSI Adapter w/Cache", /* special = 3 */ + "IBM SCSI Adapter", /* special = 4 */ + "IBM Integrated SCSI Controller", /* special = 5 */ }; /* Max number of logical devices (can be up from 0 to 14). 15 is the address @@ -375,30 +388,30 @@ struct ibmmca_hostdata { }; /* macros to access host data structure */ -#define subsystem_pun(hi) (hosts[(hi)]->this_id) -#define subsystem_maxid(hi) (hosts[(hi)]->max_id) -#define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld) -#define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn) -#define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi) -#define local_checking_phase_flag(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_local_checking_phase_flag) -#define got_interrupt(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_got_interrupt) -#define stat_result(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_stat_result) -#define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status) -#define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command) -#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type) -#define last_scsi_blockcount(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_blockcount) -#define last_scsi_logical_block(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_logical_block) -#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type) -#define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn) -#define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS) -#define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special) -#define subsystem_connector_size(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_connector_size) -#define adapter_speed(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_adapter_speed) -#define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[2]) -#define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[3]) -#define pos4(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[4]) -#define pos5(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[5]) -#define pos6(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos[6]) +#define subsystem_pun(h) ((h)->this_id) +#define subsystem_maxid(h) ((h)->max_id) +#define ld(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_ld) +#define get_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_ldn) +#define get_scsi(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_scsi) +#define local_checking_phase_flag(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_local_checking_phase_flag) +#define got_interrupt(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_got_interrupt) +#define stat_result(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_stat_result) +#define reset_status(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_reset_status) +#define last_scsi_command(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_command) +#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type) +#define last_scsi_blockcount(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_blockcount) +#define last_scsi_logical_block(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_logical_block) +#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type) +#define next_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_next_ldn) +#define IBM_DS(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_IBM_DS) +#define special(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_special) +#define subsystem_connector_size(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_connector_size) +#define adapter_speed(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_adapter_speed) +#define pos2(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[2]) +#define pos3(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[3]) +#define pos4(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[4]) +#define pos5(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[5]) +#define pos6(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[6]) /* Define a arbitrary number as subsystem-marker-type. This number is, as described in the ANSI-SCSI-standard, not occupied by other device-types. */ @@ -459,11 +472,6 @@ MODULE_LICENSE("GPL"); /*counter of concurrent disk read/writes, to turn on/off disk led */ static int disk_rw_in_progress = 0; -/* host information */ -static int found = 0; -static struct Scsi_Host *hosts[IM_MAX_HOSTS + 1] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; static unsigned int pos[8]; /* whole pos register-line for diagnosis */ /* Taking into account the additions, made by ZP Gu. * This selects now the preset value from the configfile and @@ -474,70 +482,68 @@ static char ibm_ansi_order = 1; static char ibm_ansi_order = 0; #endif -static void issue_cmd(int, unsigned long, unsigned char); +static void issue_cmd(struct Scsi_Host *, unsigned long, unsigned char); static void internal_done(Scsi_Cmnd * cmd); -static void check_devices(int, int); -static int immediate_assign(int, unsigned int, unsigned int, unsigned int, unsigned int); -static int immediate_feature(int, unsigned int, unsigned int); +static void check_devices(struct Scsi_Host *, int); +static int immediate_assign(struct Scsi_Host *, unsigned int, unsigned int, unsigned int, unsigned int); +static int immediate_feature(struct Scsi_Host *, unsigned int, unsigned int); #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET -static int immediate_reset(int, unsigned int); +static int immediate_reset(struct Scsi_Host *, unsigned int); #endif -static int device_inquiry(int, int); -static int read_capacity(int, int); -static int get_pos_info(int); +static int device_inquiry(struct Scsi_Host *, int); +static int read_capacity(struct Scsi_Host *, int); +static int get_pos_info(struct Scsi_Host *); static char *ti_p(int); static char *ti_l(int); static char *ibmrate(unsigned int, int); static int probe_display(int); -static int probe_bus_mode(int); -static int device_exists(int, int, int *, int *); -static struct Scsi_Host *ibmmca_register(struct scsi_host_template *, int, int, int, char *); +static int probe_bus_mode(struct Scsi_Host *); +static int device_exists(struct Scsi_Host *, int, int *, int *); static int option_setup(char *); /* local functions needed for proc_info */ -static int ldn_access_load(int, int); -static int ldn_access_total_read_write(int); +static int ldn_access_load(struct Scsi_Host *, int); +static int ldn_access_total_read_write(struct Scsi_Host *); static irqreturn_t interrupt_handler(int irq, void *dev_id) { - int host_index, ihost_index; unsigned int intr_reg; unsigned int cmd_result; unsigned int ldn; + unsigned long flags; Scsi_Cmnd *cmd; int lastSCSI; - struct Scsi_Host *dev = dev_id; + struct device *dev = dev_id; + struct Scsi_Host *shpnt = dev_get_drvdata(dev); - spin_lock(dev->host_lock); - /* search for one adapter-response on shared interrupt */ - for (host_index = 0; hosts[host_index] && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST); host_index++); - /* return if some other device on this IRQ caused the interrupt */ - if (!hosts[host_index]) { - spin_unlock(dev->host_lock); + spin_lock_irqsave(shpnt->host_lock, flags); + + if(!(inb(IM_STAT_REG(shpnt)) & IM_INTR_REQUEST)) { + spin_unlock_irqrestore(shpnt->host_lock, flags); return IRQ_NONE; } /* the reset-function already did all the job, even ints got renabled on the subsystem, so just return */ - if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT)) { - reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS; - spin_unlock(dev->host_lock); + if ((reset_status(shpnt) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(shpnt) == IM_RESET_FINISHED_OK_NO_INT)) { + reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS; + spin_unlock_irqrestore(shpnt->host_lock, flags); return IRQ_HANDLED; } /*must wait for attention reg not busy, then send EOI to subsystem */ while (1) { - if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) + if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY)) break; cpu_relax(); } - ihost_index = host_index; + /*get command result and logical device */ - intr_reg = (unsigned char) (inb(IM_INTR_REG(ihost_index))); + intr_reg = (unsigned char) (inb(IM_INTR_REG(shpnt))); cmd_result = intr_reg & 0xf0; ldn = intr_reg & 0x0f; /* get the last_scsi_command here */ - lastSCSI = last_scsi_command(ihost_index)[ldn]; - outb(IM_EOI | ldn, IM_ATTN_REG(ihost_index)); + lastSCSI = last_scsi_command(shpnt)[ldn]; + outb(IM_EOI | ldn, IM_ATTN_REG(shpnt)); /*these should never happen (hw fails, or a local programming bug) */ if (!global_command_error_excuse) { @@ -547,38 +553,38 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) case IM_SOFTWARE_SEQUENCING_ERROR: case IM_CMD_ERROR: printk(KERN_ERR "IBM MCA SCSI: Fatal Subsystem ERROR!\n"); - printk(KERN_ERR " Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(ihost_index)[ldn].scb.enable); - if (ld(ihost_index)[ldn].cmd) - printk("%ld/%ld,", (long) (ld(ihost_index)[ldn].cmd->request_bufflen), (long) (ld(ihost_index)[ldn].scb.sys_buf_length)); + printk(KERN_ERR " Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(shpnt)[ldn].scb.enable); + if (ld(shpnt)[ldn].cmd) + printk("%ld/%ld,", (long) (scsi_bufflen(ld(shpnt)[ldn].cmd)), (long) (ld(shpnt)[ldn].scb.sys_buf_length)); else printk("none,"); - if (ld(ihost_index)[ldn].cmd) - printk("Blocksize=%d", ld(ihost_index)[ldn].scb.u2.blk.length); + if (ld(shpnt)[ldn].cmd) + printk("Blocksize=%d", ld(shpnt)[ldn].scb.u2.blk.length); else printk("Blocksize=none"); - printk(", host=0x%x, ldn=0x%x\n", ihost_index, ldn); - if (ld(ihost_index)[ldn].cmd) { - printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u2.blk.count); - printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u1.log_blk_adr); + printk(", host=%p, ldn=0x%x\n", shpnt, ldn); + if (ld(shpnt)[ldn].cmd) { + printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(shpnt)[ldn], ld(shpnt)[ldn].scb.u2.blk.count); + printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(shpnt)[ldn], ld(shpnt)[ldn].scb.u1.log_blk_adr); } printk(KERN_ERR "Reason given: %s\n", (cmd_result == IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : (cmd_result == IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN"); /* if errors appear, enter this section to give detailed info */ printk(KERN_ERR "IBM MCA SCSI: Subsystem Error-Status follows:\n"); - printk(KERN_ERR " Command Type................: %x\n", last_scsi_type(ihost_index)[ldn]); - printk(KERN_ERR " Attention Register..........: %x\n", inb(IM_ATTN_REG(ihost_index))); - printk(KERN_ERR " Basic Control Register......: %x\n", inb(IM_CTR_REG(ihost_index))); + printk(KERN_ERR " Command Type................: %x\n", last_scsi_type(shpnt)[ldn]); + printk(KERN_ERR " Attention Register..........: %x\n", inb(IM_ATTN_REG(shpnt))); + printk(KERN_ERR " Basic Control Register......: %x\n", inb(IM_CTR_REG(shpnt))); printk(KERN_ERR " Interrupt Status Register...: %x\n", intr_reg); - printk(KERN_ERR " Basic Status Register.......: %x\n", inb(IM_STAT_REG(ihost_index))); - if ((last_scsi_type(ihost_index)[ldn] == IM_SCB) || (last_scsi_type(ihost_index)[ldn] == IM_LONG_SCB)) { - printk(KERN_ERR " SCB-Command.................: %x\n", ld(ihost_index)[ldn].scb.command); - printk(KERN_ERR " SCB-Enable..................: %x\n", ld(ihost_index)[ldn].scb.enable); - printk(KERN_ERR " SCB-logical block address...: %lx\n", ld(ihost_index)[ldn].scb.u1.log_blk_adr); - printk(KERN_ERR " SCB-system buffer address...: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_adr); - printk(KERN_ERR " SCB-system buffer length....: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_length); - printk(KERN_ERR " SCB-tsb address.............: %lx\n", ld(ihost_index)[ldn].scb.tsb_adr); - printk(KERN_ERR " SCB-Chain address...........: %lx\n", ld(ihost_index)[ldn].scb.scb_chain_adr); - printk(KERN_ERR " SCB-block count.............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.count); - printk(KERN_ERR " SCB-block length............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.length); + printk(KERN_ERR " Basic Status Register.......: %x\n", inb(IM_STAT_REG(shpnt))); + if ((last_scsi_type(shpnt)[ldn] == IM_SCB) || (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB)) { + printk(KERN_ERR " SCB-Command.................: %x\n", ld(shpnt)[ldn].scb.command); + printk(KERN_ERR " SCB-Enable..................: %x\n", ld(shpnt)[ldn].scb.enable); + printk(KERN_ERR " SCB-logical block address...: %lx\n", ld(shpnt)[ldn].scb.u1.log_blk_adr); + printk(KERN_ERR " SCB-system buffer address...: %lx\n", ld(shpnt)[ldn].scb.sys_buf_adr); + printk(KERN_ERR " SCB-system buffer length....: %lx\n", ld(shpnt)[ldn].scb.sys_buf_length); + printk(KERN_ERR " SCB-tsb address.............: %lx\n", ld(shpnt)[ldn].scb.tsb_adr); + printk(KERN_ERR " SCB-Chain address...........: %lx\n", ld(shpnt)[ldn].scb.scb_chain_adr); + printk(KERN_ERR " SCB-block count.............: %x\n", ld(shpnt)[ldn].scb.u2.blk.count); + printk(KERN_ERR " SCB-block length............: %x\n", ld(shpnt)[ldn].scb.u2.blk.length); } printk(KERN_ERR " Send this report to the maintainer.\n"); panic("IBM MCA SCSI: Fatal error message from the subsystem (0x%X,0x%X)!\n", lastSCSI, cmd_result); @@ -600,72 +606,73 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) } } /* if no panic appeared, increase the interrupt-counter */ - IBM_DS(ihost_index).total_interrupts++; + IBM_DS(shpnt).total_interrupts++; /*only for local checking phase */ - if (local_checking_phase_flag(ihost_index)) { - stat_result(ihost_index) = cmd_result; - got_interrupt(ihost_index) = 1; - reset_status(ihost_index) = IM_RESET_FINISHED_OK; - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - spin_unlock(dev->host_lock); + if (local_checking_phase_flag(shpnt)) { + stat_result(shpnt) = cmd_result; + got_interrupt(shpnt) = 1; + reset_status(shpnt) = IM_RESET_FINISHED_OK; + last_scsi_command(shpnt)[ldn] = NO_SCSI; + spin_unlock_irqrestore(shpnt->host_lock, flags); return IRQ_HANDLED; } /* handling of commands coming from upper level of scsi driver */ - if (last_scsi_type(ihost_index)[ldn] == IM_IMM_CMD) { + if (last_scsi_type(shpnt)[ldn] == IM_IMM_CMD) { /* verify ldn, and may handle rare reset immediate command */ - if ((reset_status(ihost_index) == IM_RESET_IN_PROGRESS) && (last_scsi_command(ihost_index)[ldn] == IM_RESET_IMM_CMD)) { + if ((reset_status(shpnt) == IM_RESET_IN_PROGRESS) && (last_scsi_command(shpnt)[ldn] == IM_RESET_IMM_CMD)) { if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) { disk_rw_in_progress = 0; PS2_DISK_LED_OFF(); - reset_status(ihost_index) = IM_RESET_FINISHED_FAIL; + reset_status(shpnt) = IM_RESET_FINISHED_FAIL; } else { /*reset disk led counter, turn off disk led */ disk_rw_in_progress = 0; PS2_DISK_LED_OFF(); - reset_status(ihost_index) = IM_RESET_FINISHED_OK; + reset_status(shpnt) = IM_RESET_FINISHED_OK; } - stat_result(ihost_index) = cmd_result; - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - last_scsi_type(ihost_index)[ldn] = 0; - spin_unlock(dev->host_lock); + stat_result(shpnt) = cmd_result; + last_scsi_command(shpnt)[ldn] = NO_SCSI; + last_scsi_type(shpnt)[ldn] = 0; + spin_unlock_irqrestore(shpnt->host_lock, flags); return IRQ_HANDLED; - } else if (last_scsi_command(ihost_index)[ldn] == IM_ABORT_IMM_CMD) { + } else if (last_scsi_command(shpnt)[ldn] == IM_ABORT_IMM_CMD) { /* react on SCSI abort command */ #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n"); #endif disk_rw_in_progress = 0; PS2_DISK_LED_OFF(); - cmd = ld(ihost_index)[ldn].cmd; - ld(ihost_index)[ldn].cmd = NULL; + cmd = ld(shpnt)[ldn].cmd; + ld(shpnt)[ldn].cmd = NULL; if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) cmd->result = DID_NO_CONNECT << 16; else cmd->result = DID_ABORT << 16; - stat_result(ihost_index) = cmd_result; - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - last_scsi_type(ihost_index)[ldn] = 0; + stat_result(shpnt) = cmd_result; + last_scsi_command(shpnt)[ldn] = NO_SCSI; + last_scsi_type(shpnt)[ldn] = 0; if (cmd->scsi_done) (cmd->scsi_done) (cmd); /* should be the internal_done */ - spin_unlock(dev->host_lock); + spin_unlock_irqrestore(shpnt->host_lock, flags); return IRQ_HANDLED; } else { disk_rw_in_progress = 0; PS2_DISK_LED_OFF(); - reset_status(ihost_index) = IM_RESET_FINISHED_OK; - stat_result(ihost_index) = cmd_result; - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - spin_unlock(dev->host_lock); + reset_status(shpnt) = IM_RESET_FINISHED_OK; + stat_result(shpnt) = cmd_result; + last_scsi_command(shpnt)[ldn] = NO_SCSI; + spin_unlock_irqrestore(shpnt->host_lock, flags); return IRQ_HANDLED; } } - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - last_scsi_type(ihost_index)[ldn] = 0; - cmd = ld(ihost_index)[ldn].cmd; - ld(ihost_index)[ldn].cmd = NULL; + last_scsi_command(shpnt)[ldn] = NO_SCSI; + last_scsi_type(shpnt)[ldn] = 0; + cmd = ld(shpnt)[ldn].cmd; + ld(shpnt)[ldn].cmd = NULL; #ifdef IM_DEBUG_TIMEOUT if (cmd) { if ((cmd->target == TIMEOUT_PUN) && (cmd->device->lun == TIMEOUT_LUN)) { + spin_unlock_irqsave(shpnt->host_lock, flags); printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", cmd->target, cmd->device->lun); return IRQ_HANDLED; } @@ -674,15 +681,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) /*if no command structure, just return, else clear cmd */ if (!cmd) { - spin_unlock(dev->host_lock); + spin_unlock_irqrestore(shpnt->host_lock, flags); return IRQ_HANDLED; } #ifdef IM_DEBUG_INT - printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(ihost_index)[ldn].tsb.dev_status, ld(ihost_index)[ldn].tsb.cmd_status, ld(ihost_index)[ldn].tsb.dev_error, ld(ihost_index)[ldn].tsb.cmd_error); + printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(shpnt)[ldn].tsb.dev_status, ld(shpnt)[ldn].tsb.cmd_status, ld(shpnt)[ldn].tsb.dev_error, ld(shpnt)[ldn].tsb.cmd_error); #endif /*if this is end of media read/write, may turn off PS/2 disk led */ - if ((ld(ihost_index)[ldn].device_type != TYPE_NO_LUN) && (ld(ihost_index)[ldn].device_type != TYPE_NO_DEVICE)) { + if ((ld(shpnt)[ldn].device_type != TYPE_NO_LUN) && (ld(shpnt)[ldn].device_type != TYPE_NO_DEVICE)) { /* only access this, if there was a valid device addressed */ if (--disk_rw_in_progress == 0) PS2_DISK_LED_OFF(); @@ -693,8 +700,8 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) * adapters do not support CMD_TERMINATED, TASK_SET_FULL and * ACA_ACTIVE as returning statusbyte information. (ML) */ if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) { - cmd->result = (unsigned char) (ld(ihost_index)[ldn].tsb.dev_status & 0x1e); - IBM_DS(ihost_index).total_errors++; + cmd->result = (unsigned char) (ld(shpnt)[ldn].tsb.dev_status & 0x1e); + IBM_DS(shpnt).total_errors++; } else cmd->result = 0; /* write device status into cmd->result, and call done function */ @@ -705,24 +712,25 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) cmd->result |= DID_OK << 16; if (cmd->scsi_done) (cmd->scsi_done) (cmd); - spin_unlock(dev->host_lock); + spin_unlock_irqrestore(shpnt->host_lock, flags); return IRQ_HANDLED; } -static void issue_cmd(int host_index, unsigned long cmd_reg, unsigned char attn_reg) +static void issue_cmd(struct Scsi_Host *shpnt, unsigned long cmd_reg, + unsigned char attn_reg) { unsigned long flags; /* must wait for attention reg not busy */ while (1) { - spin_lock_irqsave(hosts[host_index]->host_lock, flags); - if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) + spin_lock_irqsave(shpnt->host_lock, flags); + if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY)) break; - spin_unlock_irqrestore(hosts[host_index]->host_lock, flags); + spin_unlock_irqrestore(shpnt->host_lock, flags); } /* write registers and enable system interrupts */ - outl(cmd_reg, IM_CMD_REG(host_index)); - outb(attn_reg, IM_ATTN_REG(host_index)); - spin_unlock_irqrestore(hosts[host_index]->host_lock, flags); + outl(cmd_reg, IM_CMD_REG(shpnt)); + outb(attn_reg, IM_ATTN_REG(shpnt)); + spin_unlock_irqrestore(shpnt->host_lock, flags); } static void internal_done(Scsi_Cmnd * cmd) @@ -732,34 +740,34 @@ static void internal_done(Scsi_Cmnd * cmd) } /* SCSI-SCB-command for device_inquiry */ -static int device_inquiry(int host_index, int ldn) +static int device_inquiry(struct Scsi_Host *shpnt, int ldn) { int retr; struct im_scb *scb; struct im_tsb *tsb; unsigned char *buf; - scb = &(ld(host_index)[ldn].scb); - tsb = &(ld(host_index)[ldn].tsb); - buf = (unsigned char *) (&(ld(host_index)[ldn].buf)); - ld(host_index)[ldn].tsb.dev_status = 0; /* prepare statusblock */ + scb = &(ld(shpnt)[ldn].scb); + tsb = &(ld(shpnt)[ldn].tsb); + buf = (unsigned char *) (&(ld(shpnt)[ldn].buf)); + ld(shpnt)[ldn].tsb.dev_status = 0; /* prepare statusblock */ for (retr = 0; retr < 3; retr++) { /* fill scb with inquiry command */ scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT; scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; - last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD; - last_scsi_type(host_index)[ldn] = IM_SCB; + last_scsi_command(shpnt)[ldn] = IM_DEVICE_INQUIRY_CMD; + last_scsi_type(shpnt)[ldn] = IM_SCB; scb->sys_buf_adr = isa_virt_to_bus(buf); scb->sys_buf_length = 255; /* maximum bufferlength gives max info */ scb->tsb_adr = isa_virt_to_bus(tsb); /* issue scb to passed ldn, and busy wait for interrupt */ - got_interrupt(host_index) = 0; - issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn); - while (!got_interrupt(host_index)) + got_interrupt(shpnt) = 0; + issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn); + while (!got_interrupt(shpnt)) barrier(); /*if command successful, break */ - if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) + if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) return 1; } /*if all three retries failed, return "no device at this ldn" */ @@ -769,34 +777,34 @@ static int device_inquiry(int host_index, int ldn) return 1; } -static int read_capacity(int host_index, int ldn) +static int read_capacity(struct Scsi_Host *shpnt, int ldn) { int retr; struct im_scb *scb; struct im_tsb *tsb; unsigned char *buf; - scb = &(ld(host_index)[ldn].scb); - tsb = &(ld(host_index)[ldn].tsb); - buf = (unsigned char *) (&(ld(host_index)[ldn].buf)); - ld(host_index)[ldn].tsb.dev_status = 0; + scb = &(ld(shpnt)[ldn].scb); + tsb = &(ld(shpnt)[ldn].tsb); + buf = (unsigned char *) (&(ld(shpnt)[ldn].buf)); + ld(shpnt)[ldn].tsb.dev_status = 0; for (retr = 0; retr < 3; retr++) { /*fill scb with read capacity command */ scb->command = IM_READ_CAPACITY_CMD; scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; - last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD; - last_scsi_type(host_index)[ldn] = IM_SCB; + last_scsi_command(shpnt)[ldn] = IM_READ_CAPACITY_CMD; + last_scsi_type(shpnt)[ldn] = IM_SCB; scb->sys_buf_adr = isa_virt_to_bus(buf); scb->sys_buf_length = 8; scb->tsb_adr = isa_virt_to_bus(tsb); /*issue scb to passed ldn, and busy wait for interrupt */ - got_interrupt(host_index) = 0; - issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn); - while (!got_interrupt(host_index)) + got_interrupt(shpnt) = 0; + issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn); + while (!got_interrupt(shpnt)) barrier(); /*if got capacity, get block length and return one device found */ - if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) + if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) return 1; } /*if all three retries failed, return "no device at this ldn" */ @@ -806,39 +814,39 @@ static int read_capacity(int host_index, int ldn) return 1; } -static int get_pos_info(int host_index) +static int get_pos_info(struct Scsi_Host *shpnt) { int retr; struct im_scb *scb; struct im_tsb *tsb; unsigned char *buf; - scb = &(ld(host_index)[MAX_LOG_DEV].scb); - tsb = &(ld(host_index)[MAX_LOG_DEV].tsb); - buf = (unsigned char *) (&(ld(host_index)[MAX_LOG_DEV].buf)); - ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0; + scb = &(ld(shpnt)[MAX_LOG_DEV].scb); + tsb = &(ld(shpnt)[MAX_LOG_DEV].tsb); + buf = (unsigned char *) (&(ld(shpnt)[MAX_LOG_DEV].buf)); + ld(shpnt)[MAX_LOG_DEV].tsb.dev_status = 0; for (retr = 0; retr < 3; retr++) { /*fill scb with get_pos_info command */ scb->command = IM_GET_POS_INFO_CMD; scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; - last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD; - last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB; + last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD; + last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_SCB; scb->sys_buf_adr = isa_virt_to_bus(buf); - if (special(host_index) == IBM_SCSI2_FW) + if (special(shpnt) == IBM_SCSI2_FW) scb->sys_buf_length = 256; /* get all info from F/W adapter */ else scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */ scb->tsb_adr = isa_virt_to_bus(tsb); /*issue scb to ldn=15, and busy wait for interrupt */ - got_interrupt(host_index) = 0; - issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV); + got_interrupt(shpnt) = 0; + issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV); /* FIXME: timeout */ - while (!got_interrupt(host_index)) + while (!got_interrupt(shpnt)) barrier(); /*if got POS-stuff, get block length and return one device found */ - if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) + if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) return 1; } /* if all three retries failed, return "no device at this ldn" */ @@ -851,14 +859,16 @@ static int get_pos_info(int host_index) /* SCSI-immediate-command for assign. This functions maps/unmaps specific ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the subsystem and for dynamical remapping od ldns. */ -static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, unsigned int ldn, unsigned int operation) +static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun, + unsigned int lun, unsigned int ldn, + unsigned int operation) { int retr; unsigned long imm_cmd; for (retr = 0; retr < 3; retr++) { /* select mutation level of the SCSI-adapter */ - switch (special(host_index)) { + switch (special(shpnt)) { case IBM_SCSI2_FW: imm_cmd = (unsigned long) (IM_ASSIGN_IMM_CMD); imm_cmd |= (unsigned long) ((lun & 7) << 24); @@ -867,7 +877,7 @@ static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, imm_cmd |= (unsigned long) ((ldn & 15) << 16); break; default: - imm_cmd = inl(IM_CMD_REG(host_index)); + imm_cmd = inl(IM_CMD_REG(shpnt)); imm_cmd &= (unsigned long) (0xF8000000); /* keep reserved bits */ imm_cmd |= (unsigned long) (IM_ASSIGN_IMM_CMD); imm_cmd |= (unsigned long) ((lun & 7) << 24); @@ -876,15 +886,15 @@ static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, imm_cmd |= (unsigned long) ((ldn & 15) << 16); break; } - last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD; - last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD; - got_interrupt(host_index) = 0; - issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV); - while (!got_interrupt(host_index)) + last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD; + last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD; + got_interrupt(shpnt) = 0; + issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV); + while (!got_interrupt(shpnt)) barrier(); /*if command successful, break */ - if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) + if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED) return 1; } if (retr >= 3) @@ -893,7 +903,7 @@ static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, return 1; } -static int immediate_feature(int host_index, unsigned int speed, unsigned int timeout) +static int immediate_feature(struct Scsi_Host *shpnt, unsigned int speed, unsigned int timeout) { int retr; unsigned long imm_cmd; @@ -903,16 +913,16 @@ static int immediate_feature(int host_index, unsigned int speed, unsigned int ti imm_cmd = IM_FEATURE_CTR_IMM_CMD; imm_cmd |= (unsigned long) ((speed & 0x7) << 29); imm_cmd |= (unsigned long) ((timeout & 0x1fff) << 16); - last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD; - last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD; - got_interrupt(host_index) = 0; + last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD; + last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD; + got_interrupt(shpnt) = 0; /* we need to run into command errors in order to probe for the * right speed! */ global_command_error_excuse = 1; - issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV); + issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV); /* FIXME: timeout */ - while (!got_interrupt(host_index)) + while (!got_interrupt(shpnt)) barrier(); if (global_command_error_excuse == CMD_FAIL) { global_command_error_excuse = 0; @@ -920,7 +930,7 @@ static int immediate_feature(int host_index, unsigned int speed, unsigned int ti } else global_command_error_excuse = 0; /*if command successful, break */ - if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) + if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED) return 1; } if (retr >= 3) @@ -930,35 +940,35 @@ static int immediate_feature(int host_index, unsigned int speed, unsigned int ti } #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET -static int immediate_reset(int host_index, unsigned int ldn) +static int immediate_reset(struct Scsi_Host *shpnt, unsigned int ldn) { int retries; int ticks; unsigned long imm_command; for (retries = 0; retries < 3; retries++) { - imm_command = inl(IM_CMD_REG(host_index)); + imm_command = inl(IM_CMD_REG(shpnt)); imm_command &= (unsigned long) (0xFFFF0000); /* keep reserved bits */ imm_command |= (unsigned long) (IM_RESET_IMM_CMD); - last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD; - last_scsi_type(host_index)[ldn] = IM_IMM_CMD; - got_interrupt(host_index) = 0; - reset_status(host_index) = IM_RESET_IN_PROGRESS; - issue_cmd(host_index, (unsigned long) (imm_command), IM_IMM_CMD | ldn); + last_scsi_command(shpnt)[ldn] = IM_RESET_IMM_CMD; + last_scsi_type(shpnt)[ldn] = IM_IMM_CMD; + got_interrupt(shpnt) = 0; + reset_status(shpnt) = IM_RESET_IN_PROGRESS; + issue_cmd(shpnt, (unsigned long) (imm_command), IM_IMM_CMD | ldn); ticks = IM_RESET_DELAY * HZ; - while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) { + while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks) { udelay((1 + 999 / HZ) * 1000); barrier(); } /* if reset did not complete, just complain */ if (!ticks) { printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY); - reset_status(host_index) = IM_RESET_FINISHED_OK; + reset_status(shpnt) = IM_RESET_FINISHED_OK; /* did not work, finish */ return 1; } /*if command successful, break */ - if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) + if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED) return 1; } if (retries >= 3) @@ -1060,35 +1070,35 @@ static int probe_display(int what) return 0; } -static int probe_bus_mode(int host_index) +static int probe_bus_mode(struct Scsi_Host *shpnt) { struct im_pos_info *info; int num_bus = 0; int ldn; - info = (struct im_pos_info *) (&(ld(host_index)[MAX_LOG_DEV].buf)); - if (get_pos_info(host_index)) { + info = (struct im_pos_info *) (&(ld(shpnt)[MAX_LOG_DEV].buf)); + if (get_pos_info(shpnt)) { if (info->connector_size & 0xf000) - subsystem_connector_size(host_index) = 16; + subsystem_connector_size(shpnt) = 16; else - subsystem_connector_size(host_index) = 32; + subsystem_connector_size(shpnt) = 32; num_bus |= (info->pos_4b & 8) >> 3; for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) { - if ((special(host_index) == IBM_SCSI_WCACHE) || (special(host_index) == IBM_7568_WCACHE)) { + if ((special(shpnt) == IBM_SCSI_WCACHE) || (special(shpnt) == IBM_7568_WCACHE)) { if (!((info->cache_stat >> ldn) & 1)) - ld(host_index)[ldn].cache_flag = 0; + ld(shpnt)[ldn].cache_flag = 0; } if (!((info->retry_stat >> ldn) & 1)) - ld(host_index)[ldn].retry_flag = 0; + ld(shpnt)[ldn].retry_flag = 0; } #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: SCSI-Cache bits: "); for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) { - printk("%d", ld(host_index)[ldn].cache_flag); + printk("%d", ld(shpnt)[ldn].cache_flag); } printk("\nIBM MCA SCSI: SCSI-Retry bits: "); for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) { - printk("%d", ld(host_index)[ldn].retry_flag); + printk("%d", ld(shpnt)[ldn].retry_flag); } printk("\n"); #endif @@ -1097,7 +1107,7 @@ static int probe_bus_mode(int host_index) } /* probing scsi devices */ -static void check_devices(int host_index, int adaptertype) +static void check_devices(struct Scsi_Host *shpnt, int adaptertype) { int id, lun, ldn, ticks; int count_devices; /* local counter for connected device */ @@ -1108,24 +1118,24 @@ static void check_devices(int host_index, int adaptertype) /* assign default values to certain variables */ ticks = 0; count_devices = 0; - IBM_DS(host_index).dyn_flag = 0; /* normally no need for dynamical ldn management */ - IBM_DS(host_index).total_errors = 0; /* set errorcounter to 0 */ - next_ldn(host_index) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired' */ + IBM_DS(shpnt).dyn_flag = 0; /* normally no need for dynamical ldn management */ + IBM_DS(shpnt).total_errors = 0; /* set errorcounter to 0 */ + next_ldn(shpnt) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired' */ /* initialize the very important driver-informational arrays/structs */ - memset(ld(host_index), 0, sizeof(ld(host_index))); + memset(ld(shpnt), 0, sizeof(ld(shpnt))); for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) { - last_scsi_command(host_index)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */ - last_scsi_type(host_index)[ldn] = 0; - ld(host_index)[ldn].cache_flag = 1; - ld(host_index)[ldn].retry_flag = 1; + last_scsi_command(shpnt)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */ + last_scsi_type(shpnt)[ldn] = 0; + ld(shpnt)[ldn].cache_flag = 1; + ld(shpnt)[ldn].retry_flag = 1; } - memset(get_ldn(host_index), TYPE_NO_DEVICE, sizeof(get_ldn(host_index))); /* this is essential ! */ - memset(get_scsi(host_index), TYPE_NO_DEVICE, sizeof(get_scsi(host_index))); /* this is essential ! */ + memset(get_ldn(shpnt), TYPE_NO_DEVICE, sizeof(get_ldn(shpnt))); /* this is essential ! */ + memset(get_scsi(shpnt), TYPE_NO_DEVICE, sizeof(get_scsi(shpnt))); /* this is essential ! */ for (lun = 0; lun < 8; lun++) { /* mark the adapter at its pun on all luns */ - get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER; - get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV; /* make sure, the subsystem + get_scsi(shpnt)[subsystem_pun(shpnt)][lun] = TYPE_IBM_SCSI_ADAPTER; + get_ldn(shpnt)[subsystem_pun(shpnt)][lun] = MAX_LOG_DEV; /* make sure, the subsystem ldn is active for all luns. */ } @@ -1134,9 +1144,9 @@ static void check_devices(int host_index, int adaptertype) /* monitor connected on model XX95. */ /* STEP 1: */ - adapter_speed(host_index) = global_adapter_speed; - speedrun = adapter_speed(host_index); - while (immediate_feature(host_index, speedrun, adapter_timeout) == 2) { + adapter_speed(shpnt) = global_adapter_speed; + speedrun = adapter_speed(shpnt); + while (immediate_feature(shpnt, speedrun, adapter_timeout) == 2) { probe_display(1); if (speedrun == 7) panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n"); @@ -1144,30 +1154,30 @@ static void check_devices(int host_index, int adaptertype) if (speedrun > 7) speedrun = 7; } - adapter_speed(host_index) = speedrun; + adapter_speed(shpnt) = speedrun; /* Get detailed information about the current adapter, necessary for * device operations: */ - num_bus = probe_bus_mode(host_index); + num_bus = probe_bus_mode(shpnt); /* num_bus contains only valid data for the F/W adapter! */ if (adaptertype == IBM_SCSI2_FW) { /* F/W SCSI adapter: */ /* F/W adapter PUN-space extension evaluation: */ if (num_bus) { printk(KERN_INFO "IBM MCA SCSI: Separate bus mode (wide-addressing enabled)\n"); - subsystem_maxid(host_index) = 16; + subsystem_maxid(shpnt) = 16; } else { printk(KERN_INFO "IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n"); - subsystem_maxid(host_index) = 8; + subsystem_maxid(shpnt) = 8; } printk(KERN_INFO "IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", ibmrate(speedrun, adaptertype)); } else /* all other IBM SCSI adapters: */ printk(KERN_INFO "IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", ibmrate(speedrun, adaptertype)); /* assign correct PUN device space */ - max_pun = subsystem_maxid(host_index); + max_pun = subsystem_maxid(shpnt); #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Current SCSI-host index: %d\n", host_index); + printk("IBM MCA SCSI: Current SCSI-host index: %d\n", shpnt); printk("IBM MCA SCSI: Removing default logical SCSI-device mapping."); #else printk(KERN_INFO "IBM MCA SCSI: Dev. Order: %s, Mapping (takes <2min): ", (ibm_ansi_order) ? "ANSI" : "New"); @@ -1177,7 +1187,7 @@ static void check_devices(int host_index, int adaptertype) #ifdef IM_DEBUG_PROBE printk("."); #endif - immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN); /* remove ldn (wherever) */ + immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN); /* remove ldn (wherever) */ } lun = 0; /* default lun is 0 */ #ifndef IM_DEBUG_PROBE @@ -1196,18 +1206,18 @@ static void check_devices(int host_index, int adaptertype) #ifdef IM_DEBUG_PROBE printk("."); #endif - if (id != subsystem_pun(host_index)) { + if (id != subsystem_pun(shpnt)) { /* if pun is not the adapter: */ /* set ldn=0 to pun,lun */ - immediate_assign(host_index, id, lun, PROBE_LDN, SET_LDN); - if (device_inquiry(host_index, PROBE_LDN)) { /* probe device */ - get_scsi(host_index)[id][lun] = (unsigned char) (ld(host_index)[PROBE_LDN].buf[0]); + immediate_assign(shpnt, id, lun, PROBE_LDN, SET_LDN); + if (device_inquiry(shpnt, PROBE_LDN)) { /* probe device */ + get_scsi(shpnt)[id][lun] = (unsigned char) (ld(shpnt)[PROBE_LDN].buf[0]); /* entry, even for NO_LUN */ - if (ld(host_index)[PROBE_LDN].buf[0] != TYPE_NO_LUN) + if (ld(shpnt)[PROBE_LDN].buf[0] != TYPE_NO_LUN) count_devices++; /* a existing device is found */ } /* remove ldn */ - immediate_assign(host_index, id, lun, PROBE_LDN, REMOVE_LDN); + immediate_assign(shpnt, id, lun, PROBE_LDN, REMOVE_LDN); } } #ifndef IM_DEBUG_PROBE @@ -1227,16 +1237,16 @@ static void check_devices(int host_index, int adaptertype) #ifdef IM_DEBUG_PROBE printk("."); #endif - if (id != subsystem_pun(host_index)) { - if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN && get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE) { + if (id != subsystem_pun(shpnt)) { + if (get_scsi(shpnt)[id][lun] != TYPE_NO_LUN && get_scsi(shpnt)[id][lun] != TYPE_NO_DEVICE) { /* Only map if accepted type. Always enter for lun == 0 to get no gaps into ldn-mapping for ldn<7. */ - immediate_assign(host_index, id, lun, ldn, SET_LDN); - get_ldn(host_index)[id][lun] = ldn; /* map ldn */ - if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) { + immediate_assign(shpnt, id, lun, ldn, SET_LDN); + get_ldn(shpnt)[id][lun] = ldn; /* map ldn */ + if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) { #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET printk("resetting device at ldn=%x ... ", ldn); - immediate_reset(host_index, ldn); + immediate_reset(shpnt, ldn); #endif ldn++; } else { @@ -1244,15 +1254,15 @@ static void check_devices(int host_index, int adaptertype) * handle it or because it has problems */ if (lun > 0) { /* remove mapping */ - get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE; - immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN); + get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE; + immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN); } else ldn++; } } else if (lun == 0) { /* map lun == 0, even if no device exists */ - immediate_assign(host_index, id, lun, ldn, SET_LDN); - get_ldn(host_index)[id][lun] = ldn; /* map ldn */ + immediate_assign(shpnt, id, lun, ldn, SET_LDN); + get_ldn(shpnt)[id][lun] = ldn; /* map ldn */ ldn++; } } @@ -1262,14 +1272,14 @@ static void check_devices(int host_index, int adaptertype) /* map remaining ldns to non-existing devices */ for (lun = 1; lun < 8 && ldn < MAX_LOG_DEV; lun++) for (id = 0; id < max_pun && ldn < MAX_LOG_DEV; id++) { - if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN || get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE) { + if (get_scsi(shpnt)[id][lun] == TYPE_NO_LUN || get_scsi(shpnt)[id][lun] == TYPE_NO_DEVICE) { probe_display(1); /* Map remaining ldns only to NON-existing pun,lun combinations to make sure an inquiry will fail. For MULTI_LUN, it is needed to avoid adapter autonome SCSI-remapping. */ - immediate_assign(host_index, id, lun, ldn, SET_LDN); - get_ldn(host_index)[id][lun] = ldn; + immediate_assign(shpnt, id, lun, ldn, SET_LDN); + get_ldn(shpnt)[id][lun] = ldn; ldn++; } } @@ -1292,51 +1302,51 @@ static void check_devices(int host_index, int adaptertype) for (id = 0; id < max_pun; id++) { printk("%2d ", id); for (lun = 0; lun < 8; lun++) - printk("%2s ", ti_p(get_scsi(host_index)[id][lun])); + printk("%2s ", ti_p(get_scsi(shpnt)[id][lun])); printk(" %2d ", id); for (lun = 0; lun < 8; lun++) - printk("%2s ", ti_l(get_ldn(host_index)[id][lun])); + printk("%2s ", ti_l(get_ldn(shpnt)[id][lun])); printk("\n"); } #endif /* assign total number of found SCSI-devices to the statistics struct */ - IBM_DS(host_index).total_scsi_devices = count_devices; + IBM_DS(shpnt).total_scsi_devices = count_devices; /* decide for output in /proc-filesystem, if the configuration of SCSI-devices makes dynamical reassignment of devices necessary */ if (count_devices >= MAX_LOG_DEV) - IBM_DS(host_index).dyn_flag = 1; /* dynamical assignment is necessary */ + IBM_DS(shpnt).dyn_flag = 1; /* dynamical assignment is necessary */ else - IBM_DS(host_index).dyn_flag = 0; /* dynamical assignment is not necessary */ + IBM_DS(shpnt).dyn_flag = 0; /* dynamical assignment is not necessary */ /* If no SCSI-devices are assigned, return 1 in order to cause message. */ if (ldn == 0) printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n"); /* reset the counters for statistics on the current adapter */ - IBM_DS(host_index).scbs = 0; - IBM_DS(host_index).long_scbs = 0; - IBM_DS(host_index).total_accesses = 0; - IBM_DS(host_index).total_interrupts = 0; - IBM_DS(host_index).dynamical_assignments = 0; - memset(IBM_DS(host_index).ldn_access, 0x0, sizeof(IBM_DS(host_index).ldn_access)); - memset(IBM_DS(host_index).ldn_read_access, 0x0, sizeof(IBM_DS(host_index).ldn_read_access)); - memset(IBM_DS(host_index).ldn_write_access, 0x0, sizeof(IBM_DS(host_index).ldn_write_access)); - memset(IBM_DS(host_index).ldn_inquiry_access, 0x0, sizeof(IBM_DS(host_index).ldn_inquiry_access)); - memset(IBM_DS(host_index).ldn_modeselect_access, 0x0, sizeof(IBM_DS(host_index).ldn_modeselect_access)); - memset(IBM_DS(host_index).ldn_assignments, 0x0, sizeof(IBM_DS(host_index).ldn_assignments)); + IBM_DS(shpnt).scbs = 0; + IBM_DS(shpnt).long_scbs = 0; + IBM_DS(shpnt).total_accesses = 0; + IBM_DS(shpnt).total_interrupts = 0; + IBM_DS(shpnt).dynamical_assignments = 0; + memset(IBM_DS(shpnt).ldn_access, 0x0, sizeof(IBM_DS(shpnt).ldn_access)); + memset(IBM_DS(shpnt).ldn_read_access, 0x0, sizeof(IBM_DS(shpnt).ldn_read_access)); + memset(IBM_DS(shpnt).ldn_write_access, 0x0, sizeof(IBM_DS(shpnt).ldn_write_access)); + memset(IBM_DS(shpnt).ldn_inquiry_access, 0x0, sizeof(IBM_DS(shpnt).ldn_inquiry_access)); + memset(IBM_DS(shpnt).ldn_modeselect_access, 0x0, sizeof(IBM_DS(shpnt).ldn_modeselect_access)); + memset(IBM_DS(shpnt).ldn_assignments, 0x0, sizeof(IBM_DS(shpnt).ldn_assignments)); probe_display(0); return; } -static int device_exists(int host_index, int ldn, int *block_length, int *device_type) +static int device_exists(struct Scsi_Host *shpnt, int ldn, int *block_length, int *device_type) { unsigned char *buf; /* if no valid device found, return immediately with 0 */ - if (!(device_inquiry(host_index, ldn))) + if (!(device_inquiry(shpnt, ldn))) return 0; - buf = (unsigned char *) (&(ld(host_index)[ldn].buf)); + buf = (unsigned char *) (&(ld(shpnt)[ldn].buf)); if (*buf == TYPE_ROM) { *device_type = TYPE_ROM; *block_length = 2048; /* (standard blocksize for yellow-/red-book) */ @@ -1349,7 +1359,7 @@ static int device_exists(int host_index, int ldn, int *block_length, int *device } if (*buf == TYPE_DISK) { *device_type = TYPE_DISK; - if (read_capacity(host_index, ldn)) { + if (read_capacity(shpnt, ldn)) { *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24); return 1; } else @@ -1357,7 +1367,7 @@ static int device_exists(int host_index, int ldn, int *block_length, int *device } if (*buf == TYPE_MOD) { *device_type = TYPE_MOD; - if (read_capacity(host_index, ldn)) { + if (read_capacity(shpnt, ldn)) { *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24); return 1; } else @@ -1430,6 +1440,9 @@ static void internal_ibmmca_scsi_setup(char *str, int *ints) return; } +#if 0 + FIXME NEED TO MOVE TO SYSFS + static int ibmmca_getinfo(char *buf, int slot, void *dev_id) { struct Scsi_Host *shpnt; @@ -1480,58 +1493,34 @@ static int ibmmca_getinfo(char *buf, int slot, void *dev_id) return len; } +#endif -int ibmmca_detect(struct scsi_host_template * scsi_template) +static struct scsi_host_template ibmmca_driver_template = { + .proc_name = "ibmmca", + .proc_info = ibmmca_proc_info, + .name = "IBM SCSI-Subsystem", + .queuecommand = ibmmca_queuecommand, + .eh_abort_handler = ibmmca_abort, + .eh_host_reset_handler = ibmmca_host_reset, + .bios_param = ibmmca_biosparam, + .can_queue = 16, + .this_id = 7, + .sg_tablesize = 16, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, +}; + +static int ibmmca_probe(struct device *dev) { struct Scsi_Host *shpnt; - int port, id, i, j, k, slot; - int devices_on_irq_11 = 0; - int devices_on_irq_14 = 0; - int IRQ14_registered = 0; - int IRQ11_registered = 0; - - found = 0; /* make absolutely sure, that found is set to 0 */ + int port, id, i, j, k, irq, enabled, ret = -EINVAL; + struct mca_device *mca_dev = to_mca_device(dev); + const char *description = ibmmca_description[mca_dev->index]; /* First of all, print the version number of the driver. This is * important to allow better user bugreports in case of already * having problems with the MCA_bus probing. */ printk(KERN_INFO "IBM MCA SCSI: Version %s\n", IBMMCA_SCSI_DRIVER_VERSION); - /* if this is not MCA machine, return "nothing found" */ - if (!MCA_bus) { - printk(KERN_INFO "IBM MCA SCSI: No Microchannel-bus present --> Aborting.\n" " This machine does not have any IBM MCA-bus\n" " or the MCA-Kernel-support is not enabled!\n"); - return 0; - } - -#ifdef MODULE - /* If the driver is run as module, read from conf.modules or cmd-line */ - if (boot_options) - option_setup(boot_options); -#endif - - /* get interrupt request level */ - if (request_irq(IM_IRQ, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) { - printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ); - return 0; - } else - IRQ14_registered++; - - /* if ibmmcascsi setup option was passed to kernel, return "found" */ - for (i = 0; i < IM_MAX_HOSTS; i++) - if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) { - printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", io_port[i], scsi_id[i]); - if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], FORCED_DETECTION, "forced detected SCSI Adapter"))) { - for (k = 2; k < 7; k++) - ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = 0; - ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = FORCED_DETECTION; - mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter"); - mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); - mca_mark_as_used(MCA_INTEGSCSI); - devices_on_irq_14++; - } - } - if (found) - return found; - /* The POS2-register of all PS/2 model SCSI-subsystems has the following * interpretation of bits: * Bit 7 - 4 : Chip Revision ID (Release) @@ -1558,7 +1547,14 @@ int ibmmca_detect(struct scsi_host_template * scsi_template) /* first look for the IBM SCSI integrated subsystem on the motherboard */ for (j = 0; j < 8; j++) /* read the pos-information */ - pos[j] = mca_read_stored_pos(MCA_INTEGSCSI, j); + pos[j] = mca_device_read_pos(mca_dev, j); + id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */ + enabled = (pos[2] &0x01); + if (!enabled) { + printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); + printk(KERN_WARNING " SCSI-operations may not work.\n"); + } + /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but * if we ignore the settings of all surrounding pos registers, it is not * completely sufficient to only check pos2 and pos3. */ @@ -1566,232 +1562,137 @@ int ibmmca_detect(struct scsi_host_template * scsi_template) * make sure, we see a real integrated onboard SCSI-interface and no * internal system information, which gets mapped to some pos registers * on models 95xx. */ - if ((!pos[0] && !pos[1] && pos[2] > 0 && pos[3] > 0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || (pos[0] == 0xff && pos[1] == 0xff && pos[2] < 0xff && pos[3] < 0xff && pos[4] == 0xff && pos[5] == 0xff && pos[6] == 0xff && pos[7] == 0xff)) { - if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ - port = IM_IO_PORT; - else { /* if disabled, no IRQs will be generated, as the chip won't - * listen to the incoming commands and will do really nothing, - * except for listening to the pos-register settings. If this - * happens, I need to hugely think about it, as one has to - * write something to the MCA-Bus pos register in order to - * enable the chip. Normally, IBM-SCSI won't pass the POST, - * when the chip is disabled (see IBM tech. ref.). */ - port = IM_IO_PORT; /* anyway, set the portnumber and warn */ - printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" " SCSI-operations may not work.\n"); + if (mca_dev->slot == MCA_INTEGSCSI && + ((!pos[0] && !pos[1] && pos[2] > 0 && + pos[3] > 0 && !pos[4] && !pos[5] && + !pos[6] && !pos[7]) || + (pos[0] == 0xff && pos[1] == 0xff && + pos[2] < 0xff && pos[3] < 0xff && + pos[4] == 0xff && pos[5] == 0xff && + pos[6] == 0xff && pos[7] == 0xff))) { + irq = IM_IRQ; + port = IM_IO_PORT; + } else { + irq = IM_IRQ; + port = IM_IO_PORT + ((pos[2] &0x0e) << 2); + if ((mca_dev->index == IBM_SCSI2_FW) && (pos[6] != 0)) { + printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n"); + printk(KERN_ERR " Impossible to determine adapter PUN!\n"); + printk(KERN_ERR " Guessing adapter PUN = 7.\n"); + id = 7; + } else { + id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ + if (mca_dev->index == IBM_SCSI2_FW) { + id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit + * for F/W adapters */ + } } - id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */ - /* give detailed information on the subsystem. This helps me - * additionally during debugging and analyzing bug-reports. */ - printk(KERN_INFO "IBM MCA SCSI: IBM Integrated SCSI Controller ffound, io=0x%x, scsi id=%d,\n", port, id); - printk(KERN_INFO " chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled."); - - /* register the found integrated SCSI-subsystem */ - if ((shpnt = ibmmca_register(scsi_template, port, id, INTEGRATED_SCSI, "IBM Integrated SCSI Controller"))) - { - for (k = 2; k < 7; k++) - ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; - ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI; - mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller"); - mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); - mca_mark_as_used(MCA_INTEGSCSI); - devices_on_irq_14++; + if ((mca_dev->index == IBM_SCSI2_FW) && + (pos[4] & 0x01) && (pos[6] == 0)) { + /* IRQ11 is used by SCSI-2 F/W Adapter/A */ + printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); + irq = IM_IRQ_FW; } } - /* now look for other adapters in MCA slots, */ - /* determine the number of known IBM-SCSI-subsystem types */ - /* see the pos[2] dependence to get the adapter port-offset. */ - for (i = 0; i < ARRAY_SIZE(subsys_list); i++) { - /* scan each slot for a fitting adapter id */ - slot = 0; /* start at slot 0 */ - while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot)) - != MCA_NOTFOUND) { /* scan through all slots */ - for (j = 0; j < 8; j++) /* read the pos-information */ - pos[j] = mca_read_stored_pos(slot, j); - if ((pos[2] & 1) == 1) - /* is the subsystem chip enabled ? */ - /* (explanations see above) */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - else { - /* anyway, set the portnumber and warn */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); - printk(KERN_WARNING " SCSI-operations may not work.\n"); - } - if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) { - printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n"); - printk(KERN_ERR " Impossible to determine adapter PUN!\n"); - printk(KERN_ERR " Guessing adapter PUN = 7.\n"); - id = 7; - } else { - id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ - if (i == IBM_SCSI2_FW) { - id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit - * for F/W adapters */ - } - } - if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) { - /* IRQ11 is used by SCSI-2 F/W Adapter/A */ - printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); - /* get interrupt request level */ - if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) { - printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW); - } else - IRQ11_registered++; - } - printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id); - if ((pos[2] & 0xf0) == 0xf0) - printk(KERN_DEBUG" ROM Addr.=off,"); - else - printk(KERN_DEBUG " ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000); - printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled."); - - /* register the hostadapter */ - if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) { - for (k = 2; k < 8; k++) - ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; - ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i; - mca_set_adapter_name(slot, subsys_list[i].description); - mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt); - mca_mark_as_used(slot); - if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) - devices_on_irq_11++; - else - devices_on_irq_14++; - } - slot++; /* advance to next slot */ - } /* advance to next adapter id in the list of IBM-SCSI-subsystems */ - } - /* now check for SCSI-adapters, mapped to the integrated SCSI - * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here, - * as this is a known effect on some models 95xx. */ - for (i = 0; i < ARRAY_SIZE(subsys_list); i++) { - /* scan each slot for a fitting adapter id */ - slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI); - if (slot != MCA_NOTFOUND) { /* scan through all slots */ - for (j = 0; j < 8; j++) /* read the pos-information */ - pos[j] = mca_read_stored_pos(slot, j); - if ((pos[2] & 1) == 1) { /* is the subsystem chip enabled ? */ - /* (explanations see above) */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - } else { /* anyway, set the portnumber and warn */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); - printk(KERN_WARNING " SCSI-operations may not work.\n"); - } - if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) { - printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n"); - printk(KERN_ERR " Impossible to determine adapter PUN!\n"); - printk(KERN_ERR " Guessing adapter PUN = 7.\n"); - id = 7; - } else { - id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ - if (i == IBM_SCSI2_FW) - id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit - * for F/W adapters */ - } - if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) { - /* IRQ11 is used by SCSI-2 F/W Adapter/A */ - printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); - /* get interrupt request level */ - if (request_irq(IM_IRQ_FW, interrupt_handler, IRQF_SHARED, "ibmmcascsi", hosts)) - printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW); - else - IRQ11_registered++; - } - printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id); - if ((pos[2] & 0xf0) == 0xf0) - printk(KERN_DEBUG " ROM Addr.=off,"); - else - printk(KERN_DEBUG " ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000); - printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled."); - - /* register the hostadapter */ - if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) { - for (k = 2; k < 7; k++) - ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; - ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i; - mca_set_adapter_name(slot, subsys_list[i].description); - mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt); - mca_mark_as_used(slot); - if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) - devices_on_irq_11++; - else - devices_on_irq_14++; - } - slot++; /* advance to next slot */ - } /* advance to next adapter id in the list of IBM-SCSI-subsystems */ - } - if (IRQ11_registered && !devices_on_irq_11) - free_irq(IM_IRQ_FW, hosts); /* no devices on IRQ 11 */ - if (IRQ14_registered && !devices_on_irq_14) - free_irq(IM_IRQ, hosts); /* no devices on IRQ 14 */ - if (!devices_on_irq_11 && !devices_on_irq_14) - printk(KERN_WARNING "IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n"); - return found; /* return the number of found SCSI hosts. Should be 1 or 0. */ -} -static struct Scsi_Host *ibmmca_register(struct scsi_host_template * scsi_template, int port, int id, int adaptertype, char *hostname) -{ - struct Scsi_Host *shpnt; - int i, j; - unsigned int ctrl; + /* give detailed information on the subsystem. This helps me + * additionally during debugging and analyzing bug-reports. */ + printk(KERN_INFO "IBM MCA SCSI: %s found, io=0x%x, scsi id=%d,\n", + description, port, id); + if (mca_dev->slot == MCA_INTEGSCSI) + printk(KERN_INFO " chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled."); + else { + if ((pos[2] & 0xf0) == 0xf0) + printk(KERN_DEBUG " ROM Addr.=off,"); + else + printk(KERN_DEBUG " ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000); + + printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled."); + } /* check I/O region */ - if (!request_region(port, IM_N_IO_PORT, hostname)) { + if (!request_region(port, IM_N_IO_PORT, description)) { printk(KERN_ERR "IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n", port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT); - return NULL; + goto out_fail; } /* register host */ - shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata)); + shpnt = scsi_host_alloc(&ibmmca_driver_template, + sizeof(struct ibmmca_hostdata)); if (!shpnt) { printk(KERN_ERR "IBM MCA SCSI: Unable to register host.\n"); - release_region(port, IM_N_IO_PORT); - return NULL; + goto out_release; + } + + dev_set_drvdata(dev, shpnt); + if(request_irq(irq, interrupt_handler, IRQF_SHARED, description, dev)) { + printk(KERN_ERR "IBM MCA SCSI: failed to request interrupt %d\n", irq); + goto out_free_host; } /* request I/O region */ - hosts[found] = shpnt; /* add new found hostadapter to the list */ - special(found) = adaptertype; /* important assignment or else crash! */ - subsystem_connector_size(found) = 0; /* preset slot-size */ - shpnt->irq = IM_IRQ; /* assign necessary stuff for the adapter */ + special(shpnt) = mca_dev->index; /* important assignment or else crash! */ + subsystem_connector_size(shpnt) = 0; /* preset slot-size */ + shpnt->irq = irq; /* assign necessary stuff for the adapter */ shpnt->io_port = port; shpnt->n_io_port = IM_N_IO_PORT; shpnt->this_id = id; shpnt->max_id = 8; /* 8 PUNs are default */ /* now, the SCSI-subsystem is connected to Linux */ - ctrl = (unsigned int) (inb(IM_CTR_REG(found))); /* get control-register status */ #ifdef IM_DEBUG_PROBE + ctrl = (unsigned int) (inb(IM_CTR_REG(found))); /* get control-register status */ printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", ctrl, inb(IM_STAT_REG(found))); printk("IBM MCA SCSI: This adapters' POS-registers: "); for (i = 0; i < 8; i++) printk("%x ", pos[i]); printk("\n"); #endif - reset_status(found) = IM_RESET_NOT_IN_PROGRESS; + reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS; for (i = 0; i < 16; i++) /* reset the tables */ for (j = 0; j < 8; j++) - get_ldn(found)[i][j] = MAX_LOG_DEV; + get_ldn(shpnt)[i][j] = MAX_LOG_DEV; /* check which logical devices exist */ /* after this line, local interrupting is possible: */ - local_checking_phase_flag(found) = 1; - check_devices(found, adaptertype); /* call by value, using the global variable hosts */ - local_checking_phase_flag(found) = 0; - found++; /* now increase index to be prepared for next found subsystem */ + local_checking_phase_flag(shpnt) = 1; + check_devices(shpnt, mca_dev->index); /* call by value, using the global variable hosts */ + local_checking_phase_flag(shpnt) = 0; + /* an ibm mca subsystem has been detected */ - return shpnt; + + for (k = 2; k < 7; k++) + ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; + ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI; + mca_device_set_name(mca_dev, description); + /* FIXME: NEED TO REPLUMB TO SYSFS + mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); + */ + mca_device_set_claim(mca_dev, 1); + if (scsi_add_host(shpnt, dev)) { + dev_printk(KERN_ERR, dev, "IBM MCA SCSI: scsi_add_host failed\n"); + goto out_free_host; + } + scsi_scan_host(shpnt); + + return 0; + out_free_host: + scsi_host_put(shpnt); + out_release: + release_region(port, IM_N_IO_PORT); + out_fail: + return ret; } -static int ibmmca_release(struct Scsi_Host *shpnt) +static int __devexit ibmmca_remove(struct device *dev) { + struct Scsi_Host *shpnt = dev_get_drvdata(dev); + scsi_remove_host(shpnt); release_region(shpnt->io_port, shpnt->n_io_port); - if (!(--found)) - free_irq(shpnt->irq, hosts); + free_irq(shpnt->irq, dev); return 0; } @@ -1805,33 +1706,24 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) int current_ldn; int id, lun; int target; - int host_index; int max_pun; int i; - struct scatterlist *sl; + struct scatterlist *sg; shpnt = cmd->device->host; - /* search for the right hostadapter */ - for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); - if (!hosts[host_index]) { /* invalid hostadapter descriptor address */ - cmd->result = DID_NO_CONNECT << 16; - if (done) - done(cmd); - return 0; - } - max_pun = subsystem_maxid(host_index); + max_pun = subsystem_maxid(shpnt); if (ibm_ansi_order) { target = max_pun - 1 - cmd->device->id; - if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index))) + if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt))) target--; - else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index))) + else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt))) target++; } else target = cmd->device->id; /* if (target,lun) is NO LUN or not existing at all, return error */ - if ((get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(host_index)[target][cmd->device->lun] == TYPE_NO_DEVICE)) { + if ((get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_DEVICE)) { cmd->result = DID_NO_CONNECT << 16; if (done) done(cmd); @@ -1839,16 +1731,16 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) } /*if (target,lun) unassigned, do further checks... */ - ldn = get_ldn(host_index)[target][cmd->device->lun]; + ldn = get_ldn(shpnt)[target][cmd->device->lun]; if (ldn >= MAX_LOG_DEV) { /* on invalid ldn do special stuff */ if (ldn > MAX_LOG_DEV) { /* dynamical remapping if ldn unassigned */ - current_ldn = next_ldn(host_index); /* stop-value for one circle */ - while (ld(host_index)[next_ldn(host_index)].cmd) { /* search for a occupied, but not in */ + current_ldn = next_ldn(shpnt); /* stop-value for one circle */ + while (ld(shpnt)[next_ldn(shpnt)].cmd) { /* search for a occupied, but not in */ /* command-processing ldn. */ - next_ldn(host_index)++; - if (next_ldn(host_index) >= MAX_LOG_DEV) - next_ldn(host_index) = 7; - if (current_ldn == next_ldn(host_index)) { /* One circle done ? */ + next_ldn(shpnt)++; + if (next_ldn(shpnt) >= MAX_LOG_DEV) + next_ldn(shpnt) = 7; + if (current_ldn == next_ldn(shpnt)) { /* One circle done ? */ /* no non-processing ldn found */ scmd_printk(KERN_WARNING, cmd, "IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n" @@ -1864,56 +1756,56 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) /* unmap non-processing ldn */ for (id = 0; id < max_pun; id++) for (lun = 0; lun < 8; lun++) { - if (get_ldn(host_index)[id][lun] == next_ldn(host_index)) { - get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE; - get_scsi(host_index)[id][lun] = TYPE_NO_DEVICE; + if (get_ldn(shpnt)[id][lun] == next_ldn(shpnt)) { + get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE; + get_scsi(shpnt)[id][lun] = TYPE_NO_DEVICE; /* unmap entry */ } } /* set reduced interrupt_handler-mode for checking */ - local_checking_phase_flag(host_index) = 1; + local_checking_phase_flag(shpnt) = 1; /* map found ldn to pun,lun */ - get_ldn(host_index)[target][cmd->device->lun] = next_ldn(host_index); + get_ldn(shpnt)[target][cmd->device->lun] = next_ldn(shpnt); /* change ldn to the right value, that is now next_ldn */ - ldn = next_ldn(host_index); + ldn = next_ldn(shpnt); /* unassign all ldns (pun,lun,ldn does not matter for remove) */ - immediate_assign(host_index, 0, 0, 0, REMOVE_LDN); + immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN); /* set only LDN for remapped device */ - immediate_assign(host_index, target, cmd->device->lun, ldn, SET_LDN); + immediate_assign(shpnt, target, cmd->device->lun, ldn, SET_LDN); /* get device information for ld[ldn] */ - if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) { - ld(host_index)[ldn].cmd = NULL; /* To prevent panic set 0, because + if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) { + ld(shpnt)[ldn].cmd = NULL; /* To prevent panic set 0, because devices that were not assigned, should have nothing in progress. */ - get_scsi(host_index)[target][cmd->device->lun] = ld(host_index)[ldn].device_type; + get_scsi(shpnt)[target][cmd->device->lun] = ld(shpnt)[ldn].device_type; /* increase assignment counters for statistics in /proc */ - IBM_DS(host_index).dynamical_assignments++; - IBM_DS(host_index).ldn_assignments[ldn]++; + IBM_DS(shpnt).dynamical_assignments++; + IBM_DS(shpnt).ldn_assignments[ldn]++; } else /* panic here, because a device, found at boottime has vanished */ panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->device->lun); /* unassign again all ldns (pun,lun,ldn does not matter for remove) */ - immediate_assign(host_index, 0, 0, 0, REMOVE_LDN); + immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN); /* remap all ldns, as written in the pun/lun table */ lun = 0; #ifdef CONFIG_SCSI_MULTI_LUN for (lun = 0; lun < 8; lun++) #endif for (id = 0; id < max_pun; id++) { - if (get_ldn(host_index)[id][lun] <= MAX_LOG_DEV) - immediate_assign(host_index, id, lun, get_ldn(host_index)[id][lun], SET_LDN); + if (get_ldn(shpnt)[id][lun] <= MAX_LOG_DEV) + immediate_assign(shpnt, id, lun, get_ldn(shpnt)[id][lun], SET_LDN); } /* set back to normal interrupt_handling */ - local_checking_phase_flag(host_index) = 0; + local_checking_phase_flag(shpnt) = 0; #ifdef IM_DEBUG_PROBE /* Information on syslog terminal */ printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->device->lun); #endif /* increase next_ldn for next dynamical assignment */ - next_ldn(host_index)++; - if (next_ldn(host_index) >= MAX_LOG_DEV) - next_ldn(host_index) = 7; + next_ldn(shpnt)++; + if (next_ldn(shpnt) >= MAX_LOG_DEV) + next_ldn(shpnt) = 7; } else { /* wall against Linux accesses to the subsystem adapter */ cmd->result = DID_BAD_TARGET << 16; if (done) @@ -1923,34 +1815,32 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) } /*verify there is no command already in progress for this log dev */ - if (ld(host_index)[ldn].cmd) + if (ld(shpnt)[ldn].cmd) panic("IBM MCA SCSI: cmd already in progress for this ldn.\n"); /*save done in cmd, and save cmd for the interrupt handler */ cmd->scsi_done = done; - ld(host_index)[ldn].cmd = cmd; + ld(shpnt)[ldn].cmd = cmd; /*fill scb information independent of the scsi command */ - scb = &(ld(host_index)[ldn].scb); - ld(host_index)[ldn].tsb.dev_status = 0; + scb = &(ld(shpnt)[ldn].scb); + ld(shpnt)[ldn].tsb.dev_status = 0; scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE; - scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb)); + scb->tsb_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].tsb)); scsi_cmd = cmd->cmnd[0]; - if (cmd->use_sg) { - i = cmd->use_sg; - sl = (struct scatterlist *) (cmd->request_buffer); - if (i > 16) - panic("IBM MCA SCSI: scatter-gather list too long.\n"); - while (--i >= 0) { - ld(host_index)[ldn].sge[i].address = (void *) (isa_page_to_bus(sl[i].page) + sl[i].offset); - ld(host_index)[ldn].sge[i].byte_length = sl[i].length; + if (scsi_sg_count(cmd)) { + BUG_ON(scsi_sg_count(cmd) > 16); + + scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) { + ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg->page) + sg->offset); + ld(shpnt)[ldn].sge[i].byte_length = sg->length; } scb->enable |= IM_POINTER_TO_LIST; - scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0])); - scb->sys_buf_length = cmd->use_sg * sizeof(struct im_sge); + scb->sys_buf_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].sge[0])); + scb->sys_buf_length = scsi_sg_count(cmd) * sizeof(struct im_sge); } else { - scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer); + scb->sys_buf_adr = isa_virt_to_bus(scsi_sglist(cmd)); /* recent Linux midlevel SCSI places 1024 byte for inquiry * command. Far too much for old PS/2 hardware. */ switch (scsi_cmd) { @@ -1961,16 +1851,16 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) case REQUEST_SENSE: case MODE_SENSE: case MODE_SELECT: - if (cmd->request_bufflen > 255) + if (scsi_bufflen(cmd) > 255) scb->sys_buf_length = 255; else - scb->sys_buf_length = cmd->request_bufflen; + scb->sys_buf_length = scsi_bufflen(cmd); break; case TEST_UNIT_READY: scb->sys_buf_length = 0; break; default: - scb->sys_buf_length = cmd->request_bufflen; + scb->sys_buf_length = scsi_bufflen(cmd); break; } } @@ -1982,16 +1872,16 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) /* for specific device-type debugging: */ #ifdef IM_DEBUG_CMD_SPEC_DEV - if (ld(host_index)[ldn].device_type == IM_DEBUG_CMD_DEVICE) - printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(host_index)[ldn].device_type, scsi_cmd, ldn); + if (ld(shpnt)[ldn].device_type == IM_DEBUG_CMD_DEVICE) + printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(shpnt)[ldn].device_type, scsi_cmd, ldn); #endif /* for possible panics store current command */ - last_scsi_command(host_index)[ldn] = scsi_cmd; - last_scsi_type(host_index)[ldn] = IM_SCB; + last_scsi_command(shpnt)[ldn] = scsi_cmd; + last_scsi_type(shpnt)[ldn] = IM_SCB; /* update statistical info */ - IBM_DS(host_index).total_accesses++; - IBM_DS(host_index).ldn_access[ldn]++; + IBM_DS(shpnt).total_accesses++; + IBM_DS(shpnt).ldn_access[ldn]++; switch (scsi_cmd) { case READ_6: @@ -2003,17 +1893,17 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) /* Distinguish between disk and other devices. Only disks (that are the most frequently accessed devices) should be supported by the IBM-SCSI-Subsystem commands. */ - switch (ld(host_index)[ldn].device_type) { + switch (ld(shpnt)[ldn].device_type) { case TYPE_DISK: /* for harddisks enter here ... */ case TYPE_MOD: /* ... try it also for MO-drives (send flames as */ /* you like, if this won't work.) */ if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) { /* read command preparations */ scb->enable |= IM_READ_CONTROL; - IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */ + IBM_DS(shpnt).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */ scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT; } else { /* write command preparations */ - IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat. */ + IBM_DS(shpnt).ldn_write_access[ldn]++; /* increase write-count on ldn stat. */ scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT; } if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) { @@ -2023,9 +1913,9 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | (((unsigned) cmd->cmnd[4]) << 8) | (((unsigned) cmd->cmnd[3]) << 16) | (((unsigned) cmd->cmnd[2]) << 24); scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8); } - last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr; - last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count; - scb->u2.blk.length = ld(host_index)[ldn].block_length; + last_scsi_logical_block(shpnt)[ldn] = scb->u1.log_blk_adr; + last_scsi_blockcount(shpnt)[ldn] = scb->u2.blk.count; + scb->u2.blk.length = ld(shpnt)[ldn].block_length; break; /* for other devices, enter here. Other types are not known by Linux! TYPE_NO_LUN is forbidden as valid device. */ @@ -2046,14 +1936,14 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) scb->enable |= IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); - last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + last_scsi_type(shpnt)[ldn] = IM_LONG_SCB; /* Read/write on this non-disk devices is also displayworthy, so flash-up the LED/display. */ break; } break; case INQUIRY: - IBM_DS(host_index).ldn_inquiry_access[ldn]++; + IBM_DS(shpnt).ldn_inquiry_access[ldn]++; scb->command = IM_DEVICE_INQUIRY_CMD; scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; scb->u1.log_blk_adr = 0; @@ -2064,7 +1954,7 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) scb->u1.log_blk_adr = 0; scb->u1.scsi_cmd_length = 6; memcpy(scb->u2.scsi_command, cmd->cmnd, 6); - last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + last_scsi_type(shpnt)[ldn] = IM_LONG_SCB; break; case READ_CAPACITY: /* the length of system memory buffer must be exactly 8 bytes */ @@ -2081,12 +1971,12 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) /* Commands that need write-only-mode (system -> device): */ case MODE_SELECT: case MODE_SELECT_10: - IBM_DS(host_index).ldn_modeselect_access[ldn]++; + IBM_DS(shpnt).ldn_modeselect_access[ldn]++; scb->command = IM_OTHER_SCSI_CMD_CMD; scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; /*Select needs WRITE-enabled */ scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); - last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + last_scsi_type(shpnt)[ldn] = IM_LONG_SCB; break; /* For other commands, read-only is useful. Most other commands are running without an input-data-block. */ @@ -2095,19 +1985,19 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); - last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + last_scsi_type(shpnt)[ldn] = IM_LONG_SCB; break; } /*issue scb command, and return */ if (++disk_rw_in_progress == 1) PS2_DISK_LED_ON(shpnt->host_no, target); - if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) { - issue_cmd(host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn); - IBM_DS(host_index).long_scbs++; + if (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB) { + issue_cmd(shpnt, isa_virt_to_bus(scb), IM_LONG_SCB | ldn); + IBM_DS(shpnt).long_scbs++; } else { - issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn); - IBM_DS(host_index).scbs++; + issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn); + IBM_DS(shpnt).scbs++; } return 0; } @@ -2122,7 +2012,6 @@ static int __ibmmca_abort(Scsi_Cmnd * cmd) unsigned int ldn; void (*saved_done) (Scsi_Cmnd *); int target; - int host_index; int max_pun; unsigned long imm_command; @@ -2131,35 +2020,23 @@ static int __ibmmca_abort(Scsi_Cmnd * cmd) #endif shpnt = cmd->device->host; - /* search for the right hostadapter */ - for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); - if (!hosts[host_index]) { /* invalid hostadapter descriptor address */ - cmd->result = DID_NO_CONNECT << 16; - if (cmd->scsi_done) - (cmd->scsi_done) (cmd); - shpnt = cmd->device->host; -#ifdef IM_DEBUG_PROBE - printk(KERN_DEBUG "IBM MCA SCSI: Abort adapter selection failed!\n"); -#endif - return SUCCESS; - } - max_pun = subsystem_maxid(host_index); + max_pun = subsystem_maxid(shpnt); if (ibm_ansi_order) { target = max_pun - 1 - cmd->device->id; - if ((target <= subsystem_pun(host_index)) && (cmd->device->id <= subsystem_pun(host_index))) + if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt))) target--; - else if ((target >= subsystem_pun(host_index)) && (cmd->device->id >= subsystem_pun(host_index))) + else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt))) target++; } else target = cmd->device->id; /* get logical device number, and disable system interrupts */ printk(KERN_WARNING "IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", target, cmd->device->lun); - ldn = get_ldn(host_index)[target][cmd->device->lun]; + ldn = get_ldn(shpnt)[target][cmd->device->lun]; /*if cmd for this ldn has already finished, no need to abort */ - if (!ld(host_index)[ldn].cmd) { + if (!ld(shpnt)[ldn].cmd) { return SUCCESS; } @@ -2170,20 +2047,20 @@ static int __ibmmca_abort(Scsi_Cmnd * cmd) saved_done = cmd->scsi_done; cmd->scsi_done = internal_done; cmd->SCp.Status = 0; - last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD; - last_scsi_type(host_index)[ldn] = IM_IMM_CMD; - imm_command = inl(IM_CMD_REG(host_index)); + last_scsi_command(shpnt)[ldn] = IM_ABORT_IMM_CMD; + last_scsi_type(shpnt)[ldn] = IM_IMM_CMD; + imm_command = inl(IM_CMD_REG(shpnt)); imm_command &= (unsigned long) (0xffff0000); /* mask reserved stuff */ imm_command |= (unsigned long) (IM_ABORT_IMM_CMD); /* must wait for attention reg not busy */ /* FIXME - timeout, politeness */ while (1) { - if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) + if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY)) break; } /* write registers and enable system interrupts */ - outl(imm_command, IM_CMD_REG(host_index)); - outb(IM_IMM_CMD | ldn, IM_ATTN_REG(host_index)); + outl(imm_command, IM_CMD_REG(shpnt)); + outb(IM_IMM_CMD | ldn, IM_ATTN_REG(shpnt)); #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Abort queued to adapter...\n"); #endif @@ -2202,7 +2079,7 @@ static int __ibmmca_abort(Scsi_Cmnd * cmd) cmd->result |= DID_ABORT << 16; if (cmd->scsi_done) (cmd->scsi_done) (cmd); - ld(host_index)[ldn].cmd = NULL; + ld(shpnt)[ldn].cmd = NULL; #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Abort finished with success.\n"); #endif @@ -2211,7 +2088,7 @@ static int __ibmmca_abort(Scsi_Cmnd * cmd) cmd->result |= DID_NO_CONNECT << 16; if (cmd->scsi_done) (cmd->scsi_done) (cmd); - ld(host_index)[ldn].cmd = NULL; + ld(shpnt)[ldn].cmd = NULL; #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Abort failed.\n"); #endif @@ -2236,71 +2113,65 @@ static int __ibmmca_host_reset(Scsi_Cmnd * cmd) struct Scsi_Host *shpnt; Scsi_Cmnd *cmd_aid; int ticks, i; - int host_index; unsigned long imm_command; BUG_ON(cmd == NULL); ticks = IM_RESET_DELAY * HZ; shpnt = cmd->device->host; - /* search for the right hostadapter */ - for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); - - if (!hosts[host_index]) /* invalid hostadapter descriptor address */ - return FAILED; - if (local_checking_phase_flag(host_index)) { + if (local_checking_phase_flag(shpnt)) { printk(KERN_WARNING "IBM MCA SCSI: unable to reset while checking devices.\n"); return FAILED; } /* issue reset immediate command to subsystem, and wait for interrupt */ printk("IBM MCA SCSI: resetting all devices.\n"); - reset_status(host_index) = IM_RESET_IN_PROGRESS; - last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD; - last_scsi_type(host_index)[0xf] = IM_IMM_CMD; - imm_command = inl(IM_CMD_REG(host_index)); + reset_status(shpnt) = IM_RESET_IN_PROGRESS; + last_scsi_command(shpnt)[0xf] = IM_RESET_IMM_CMD; + last_scsi_type(shpnt)[0xf] = IM_IMM_CMD; + imm_command = inl(IM_CMD_REG(shpnt)); imm_command &= (unsigned long) (0xffff0000); /* mask reserved stuff */ imm_command |= (unsigned long) (IM_RESET_IMM_CMD); /* must wait for attention reg not busy */ while (1) { - if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) + if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY)) break; spin_unlock_irq(shpnt->host_lock); yield(); spin_lock_irq(shpnt->host_lock); } /*write registers and enable system interrupts */ - outl(imm_command, IM_CMD_REG(host_index)); - outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index)); + outl(imm_command, IM_CMD_REG(shpnt)); + outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(shpnt)); /* wait for interrupt finished or intr_stat register to be set, as the * interrupt will not be executed, while we are in here! */ /* FIXME: This is really really icky we so want a sleeping version of this ! */ - while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(host_index)) & 0x8f) != 0x8f)) { + while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(shpnt)) & 0x8f) != 0x8f)) { udelay((1 + 999 / HZ) * 1000); barrier(); } /* if reset did not complete, just return an error */ if (!ticks) { printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY); - reset_status(host_index) = IM_RESET_FINISHED_FAIL; + reset_status(shpnt) = IM_RESET_FINISHED_FAIL; return FAILED; } - if ((inb(IM_INTR_REG(host_index)) & 0x8f) == 0x8f) { + if ((inb(IM_INTR_REG(shpnt)) & 0x8f) == 0x8f) { /* analysis done by this routine and not by the intr-routine */ - if (inb(IM_INTR_REG(host_index)) == 0xaf) - reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT; - else if (inb(IM_INTR_REG(host_index)) == 0xcf) - reset_status(host_index) = IM_RESET_FINISHED_FAIL; + if (inb(IM_INTR_REG(shpnt)) == 0xaf) + reset_status(shpnt) = IM_RESET_FINISHED_OK_NO_INT; + else if (inb(IM_INTR_REG(shpnt)) == 0xcf) + reset_status(shpnt) = IM_RESET_FINISHED_FAIL; else /* failed, 4get it */ - reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT; - outb(IM_EOI | 0xf, IM_ATTN_REG(host_index)); + reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS_NO_INT; + outb(IM_EOI | 0xf, IM_ATTN_REG(shpnt)); } /* if reset failed, just return an error */ - if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) { + if (reset_status(shpnt) == IM_RESET_FINISHED_FAIL) { printk(KERN_ERR "IBM MCA SCSI: reset failed.\n"); return FAILED; } @@ -2308,9 +2179,9 @@ static int __ibmmca_host_reset(Scsi_Cmnd * cmd) /* so reset finished ok - call outstanding done's, and return success */ printk(KERN_INFO "IBM MCA SCSI: Reset successfully completed.\n"); for (i = 0; i < MAX_LOG_DEV; i++) { - cmd_aid = ld(host_index)[i].cmd; + cmd_aid = ld(shpnt)[i].cmd; if (cmd_aid && cmd_aid->scsi_done) { - ld(host_index)[i].cmd = NULL; + ld(shpnt)[i].cmd = NULL; cmd_aid->result = DID_RESET << 16; } } @@ -2351,46 +2222,46 @@ static int ibmmca_biosparam(struct scsi_device *sdev, struct block_device *bdev, } /* calculate percentage of total accesses on a ldn */ -static int ldn_access_load(int host_index, int ldn) +static int ldn_access_load(struct Scsi_Host *shpnt, int ldn) { - if (IBM_DS(host_index).total_accesses == 0) + if (IBM_DS(shpnt).total_accesses == 0) return (0); - if (IBM_DS(host_index).ldn_access[ldn] == 0) + if (IBM_DS(shpnt).ldn_access[ldn] == 0) return (0); - return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses; + return (IBM_DS(shpnt).ldn_access[ldn] * 100) / IBM_DS(shpnt).total_accesses; } /* calculate total amount of r/w-accesses */ -static int ldn_access_total_read_write(int host_index) +static int ldn_access_total_read_write(struct Scsi_Host *shpnt) { int a; int i; a = 0; for (i = 0; i <= MAX_LOG_DEV; i++) - a += IBM_DS(host_index).ldn_read_access[i] + IBM_DS(host_index).ldn_write_access[i]; + a += IBM_DS(shpnt).ldn_read_access[i] + IBM_DS(shpnt).ldn_write_access[i]; return (a); } -static int ldn_access_total_inquiry(int host_index) +static int ldn_access_total_inquiry(struct Scsi_Host *shpnt) { int a; int i; a = 0; for (i = 0; i <= MAX_LOG_DEV; i++) - a += IBM_DS(host_index).ldn_inquiry_access[i]; + a += IBM_DS(shpnt).ldn_inquiry_access[i]; return (a); } -static int ldn_access_total_modeselect(int host_index) +static int ldn_access_total_modeselect(struct Scsi_Host *shpnt) { int a; int i; a = 0; for (i = 0; i <= MAX_LOG_DEV; i++) - a += IBM_DS(host_index).ldn_modeselect_access[i]; + a += IBM_DS(shpnt).ldn_modeselect_access[i]; return (a); } @@ -2398,19 +2269,14 @@ static int ldn_access_total_modeselect(int host_index) static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout) { int len = 0; - int i, id, lun, host_index; + int i, id, lun; unsigned long flags; int max_pun; - for (i = 0; hosts[i] && hosts[i] != shpnt; i++); - spin_lock_irqsave(hosts[i]->host_lock, flags); /* Check it */ - host_index = i; - if (!shpnt) { - len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter"); - return len; - } - max_pun = subsystem_maxid(host_index); + spin_lock_irqsave(shpnt->host_lock, flags); /* Check it */ + + max_pun = subsystem_maxid(shpnt); len += sprintf(buffer + len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", IBMMCA_SCSI_DRIVER_VERSION); len += sprintf(buffer + len, " SCSI Access-Statistics:\n"); @@ -2421,40 +2287,40 @@ static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, len += sprintf(buffer + len, " Multiple LUN probing.....: No\n"); #endif len += sprintf(buffer + len, " This Hostnumber..........: %d\n", shpnt->host_no); - len += sprintf(buffer + len, " Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(host_index))); + len += sprintf(buffer + len, " Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(shpnt))); len += sprintf(buffer + len, " (Shared) IRQ.............: %d\n", IM_IRQ); - len += sprintf(buffer + len, " Total Interrupts.........: %d\n", IBM_DS(host_index).total_interrupts); - len += sprintf(buffer + len, " Total SCSI Accesses......: %d\n", IBM_DS(host_index).total_accesses); - len += sprintf(buffer + len, " Total short SCBs.........: %d\n", IBM_DS(host_index).scbs); - len += sprintf(buffer + len, " Total long SCBs..........: %d\n", IBM_DS(host_index).long_scbs); - len += sprintf(buffer + len, " Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(host_index)); - len += sprintf(buffer + len, " Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(host_index)); - len += sprintf(buffer + len, " Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(host_index)); - len += sprintf(buffer + len, " Total SCSI other cmds..: %d\n", IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index) - - ldn_access_total_modeselect(host_index) - - ldn_access_total_inquiry(host_index)); - len += sprintf(buffer + len, " Total SCSI command fails.: %d\n\n", IBM_DS(host_index).total_errors); + len += sprintf(buffer + len, " Total Interrupts.........: %d\n", IBM_DS(shpnt).total_interrupts); + len += sprintf(buffer + len, " Total SCSI Accesses......: %d\n", IBM_DS(shpnt).total_accesses); + len += sprintf(buffer + len, " Total short SCBs.........: %d\n", IBM_DS(shpnt).scbs); + len += sprintf(buffer + len, " Total long SCBs..........: %d\n", IBM_DS(shpnt).long_scbs); + len += sprintf(buffer + len, " Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(shpnt)); + len += sprintf(buffer + len, " Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(shpnt)); + len += sprintf(buffer + len, " Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(shpnt)); + len += sprintf(buffer + len, " Total SCSI other cmds..: %d\n", IBM_DS(shpnt).total_accesses - ldn_access_total_read_write(shpnt) + - ldn_access_total_modeselect(shpnt) + - ldn_access_total_inquiry(shpnt)); + len += sprintf(buffer + len, " Total SCSI command fails.: %d\n\n", IBM_DS(shpnt).total_errors); len += sprintf(buffer + len, " Logical-Device-Number (LDN) Access-Statistics:\n"); len += sprintf(buffer + len, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n"); len += sprintf(buffer + len, " -----|--------------|-----------|-----------|--------------\n"); for (i = 0; i <= MAX_LOG_DEV; i++) - len += sprintf(buffer + len, " %2X | %3d | %8d | %8d | %8d\n", i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i], IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]); + len += sprintf(buffer + len, " %2X | %3d | %8d | %8d | %8d\n", i, ldn_access_load(shpnt, i), IBM_DS(shpnt).ldn_read_access[i], IBM_DS(shpnt).ldn_write_access[i], IBM_DS(shpnt).ldn_assignments[i]); len += sprintf(buffer + len, " -----------------------------------------------------------\n\n"); len += sprintf(buffer + len, " Dynamical-LDN-Assignment-Statistics:\n"); - len += sprintf(buffer + len, " Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(host_index).total_scsi_devices); - len += sprintf(buffer + len, " Dynamical Assignment necessary...: %s\n", IBM_DS(host_index).dyn_flag ? "Yes" : "No "); - len += sprintf(buffer + len, " Next LDN to be assigned..........: 0x%x\n", next_ldn(host_index)); - len += sprintf(buffer + len, " Dynamical assignments done yet...: %d\n", IBM_DS(host_index).dynamical_assignments); + len += sprintf(buffer + len, " Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(shpnt).total_scsi_devices); + len += sprintf(buffer + len, " Dynamical Assignment necessary...: %s\n", IBM_DS(shpnt).dyn_flag ? "Yes" : "No "); + len += sprintf(buffer + len, " Next LDN to be assigned..........: 0x%x\n", next_ldn(shpnt)); + len += sprintf(buffer + len, " Dynamical assignments done yet...: %d\n", IBM_DS(shpnt).dynamical_assignments); len += sprintf(buffer + len, "\n Current SCSI-Device-Mapping:\n"); len += sprintf(buffer + len, " Physical SCSI-Device Map Logical SCSI-Device Map\n"); len += sprintf(buffer + len, " ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n"); for (id = 0; id < max_pun; id++) { len += sprintf(buffer + len, " %2d ", id); for (lun = 0; lun < 8; lun++) - len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(host_index)[id][lun])); + len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(shpnt)[id][lun])); len += sprintf(buffer + len, " %2d ", id); for (lun = 0; lun < 8; lun++) - len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(host_index)[id][lun])); + len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(shpnt)[id][lun])); len += sprintf(buffer + len, "\n"); } @@ -2488,20 +2354,31 @@ static int option_setup(char *str) __setup("ibmmcascsi=", option_setup); -static struct scsi_host_template driver_template = { - .proc_name = "ibmmca", - .proc_info = ibmmca_proc_info, - .name = "IBM SCSI-Subsystem", - .detect = ibmmca_detect, - .release = ibmmca_release, - .queuecommand = ibmmca_queuecommand, - .eh_abort_handler = ibmmca_abort, - .eh_host_reset_handler = ibmmca_host_reset, - .bios_param = ibmmca_biosparam, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = 16, - .cmd_per_lun = 1, - .use_clustering = ENABLE_CLUSTERING, +static struct mca_driver ibmmca_driver = { + .id_table = ibmmca_id_table, + .driver = { + .name = "ibmmca", + .bus = &mca_bus_type, + .probe = ibmmca_probe, + .remove = __devexit_p(ibmmca_remove), + }, }; -#include "scsi_module.c" + +static int __init ibmmca_init(void) +{ +#ifdef MODULE + /* If the driver is run as module, read from conf.modules or cmd-line */ + if (boot_options) + option_setup(boot_options); +#endif + + return mca_register_driver_integrated(&ibmmca_driver, MCA_INTEGSCSI); +} + +static void __exit ibmmca_exit(void) +{ + mca_unregister_driver(&ibmmca_driver); +} + +module_init(ibmmca_init); +module_exit(ibmmca_exit); diff --git a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h deleted file mode 100644 index 017ee2fa6d63..000000000000 --- a/drivers/scsi/ibmmca.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Low Level Driver for the IBM Microchannel SCSI Subsystem - * (Headerfile, see Documentation/scsi/ibmmca.txt for description of the - * IBM MCA SCSI-driver. - * For use under the GNU General Public License within the Linux-kernel project. - * This include file works only correctly with kernel 2.4.0 or higher!!! */ - -#ifndef _IBMMCA_H -#define _IBMMCA_H - -/* Common forward declarations for all Linux-versions: */ - -/* Interfaces to the midlevel Linux SCSI driver */ -static int ibmmca_detect (struct scsi_host_template *); -static int ibmmca_release (struct Scsi_Host *); -static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -static int ibmmca_abort (Scsi_Cmnd *); -static int ibmmca_host_reset (Scsi_Cmnd *); -static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *); - -#endif /* _IBMMCA_H */ diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index b10eefe735c5..b580af95956b 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1375,6 +1375,23 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev) return 0; } +/** + * ibmvscsi_change_queue_depth - Change the device's queue depth + * @sdev: scsi device struct + * @qdepth: depth to set + * + * Return value: + * actual depth set + **/ +static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth) +{ + if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN) + qdepth = IBMVSCSI_MAX_CMDS_PER_LUN; + + scsi_adjust_queue_depth(sdev, 0, qdepth); + return sdev->queue_depth; +} + /* ------------------------------------------------------------ * sysfs attributes */ @@ -1521,6 +1538,7 @@ static struct scsi_host_template driver_template = { .eh_abort_handler = ibmvscsi_eh_abort_handler, .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, .slave_configure = ibmvscsi_slave_configure, + .change_queue_depth = ibmvscsi_change_queue_depth, .cmd_per_lun = 16, .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, .this_id = -1, diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 77cc1d40f5bb..727ca7c95926 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h @@ -45,6 +45,7 @@ struct Scsi_Host; #define MAX_INDIRECT_BUFS 10 #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100 +#define IBMVSCSI_MAX_CMDS_PER_LUN 64 /* ------------------------------------------------------------ * Data Structures diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 7e7635ca78f1..d9dfb69ae031 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -3,7 +3,8 @@ * * Copyright (c) 1994-1998 Initio Corporation * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl> - * All rights reserved. + * Copyright (c) 2004 Christoph Hellwig <hch@lst.de> + * Copyright (c) 2007 Red Hat <alan@redhat.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,38 +20,6 @@ * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * - * -------------------------------------------------------------------------- - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Where this Software is combined with software released under the terms of - * the GNU General Public License ("GPL") and the terms of the GPL would require the - * combined work to also be released under the terms of the GPL, the terms - * and conditions of this License will apply in addition to those of the - * GPL with the exception of any terms or conditions of this License that - * conflict with, or are expressly prohibited by, the GPL. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. * ************************************************************************* * @@ -70,14 +39,14 @@ * - Fix memory allocation problem * 03/04/98 hc - v1.01l * - Fix tape rewind which will hang the system problem - * - Set can_queue to tul_num_scb + * - Set can_queue to initio_num_scb * 06/25/98 hc - v1.01m * - Get it work for kernel version >= 2.1.75 - * - Dynamic assign SCSI bus reset holding time in init_tulip() + * - Dynamic assign SCSI bus reset holding time in initio_init() * 07/02/98 hc - v1.01n * - Support 0002134A * 08/07/98 hc - v1.01o - * - Change the tul_abort_srb routine to use scsi_done. <01> + * - Change the initio_abort_srb routine to use scsi_done. <01> * 09/07/98 hl - v1.02 * - Change the INI9100U define and proc_dir_entry to * reflect the newer Kernel 2.1.118, but the v1.o1o @@ -150,23 +119,13 @@ static unsigned int i91u_debug = DEBUG_DEFAULT; #endif -#define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) - -typedef struct PCI_ID_Struc { - unsigned short vendor_id; - unsigned short device_id; -} PCI_ID; - -static int tul_num_ch = 4; /* Maximum 4 adapters */ -static int tul_num_scb; -static int tul_tag_enable = 1; -static SCB *tul_scb; +static int initio_tag_enable = 1; #ifdef DEBUG_i91u static int setup_debug = 0; #endif -static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); +static void i91uSCBPost(u8 * pHcb, u8 * pScb); /* PCI Devices supported by this driver */ static struct pci_device_id i91u_pci_devices[] = { @@ -184,74 +143,66 @@ MODULE_DEVICE_TABLE(pci, i91u_pci_devices); #define DEBUG_STATE 0 #define INT_DISC 0 -/*--- external functions --*/ -static void tul_se2_wait(void); - -/*--- forward refrence ---*/ -static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun); -static SCB *tul_find_done_scb(HCS * pCurHcb); - -static int tulip_main(HCS * pCurHcb); - -static int tul_next_state(HCS * pCurHcb); -static int tul_state_1(HCS * pCurHcb); -static int tul_state_2(HCS * pCurHcb); -static int tul_state_3(HCS * pCurHcb); -static int tul_state_4(HCS * pCurHcb); -static int tul_state_5(HCS * pCurHcb); -static int tul_state_6(HCS * pCurHcb); -static int tul_state_7(HCS * pCurHcb); -static int tul_xfer_data_in(HCS * pCurHcb); -static int tul_xfer_data_out(HCS * pCurHcb); -static int tul_xpad_in(HCS * pCurHcb); -static int tul_xpad_out(HCS * pCurHcb); -static int tul_status_msg(HCS * pCurHcb); - -static int tul_msgin(HCS * pCurHcb); -static int tul_msgin_sync(HCS * pCurHcb); -static int tul_msgin_accept(HCS * pCurHcb); -static int tul_msgout_reject(HCS * pCurHcb); -static int tul_msgin_extend(HCS * pCurHcb); - -static int tul_msgout_ide(HCS * pCurHcb); -static int tul_msgout_abort_targ(HCS * pCurHcb); -static int tul_msgout_abort_tag(HCS * pCurHcb); - -static int tul_bus_device_reset(HCS * pCurHcb); -static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb); -static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb); -static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb); -static int int_tul_busfree(HCS * pCurHcb); -static int int_tul_scsi_rst(HCS * pCurHcb); -static int int_tul_bad_seq(HCS * pCurHcb); -static int int_tul_resel(HCS * pCurHcb); -static int tul_sync_done(HCS * pCurHcb); -static int wdtr_done(HCS * pCurHcb); -static int wait_tulip(HCS * pCurHcb); -static int tul_wait_done_disc(HCS * pCurHcb); -static int tul_wait_disc(HCS * pCurHcb); -static void tulip_scsi(HCS * pCurHcb); -static int tul_post_scsi_rst(HCS * pCurHcb); - -static void tul_se2_ew_en(WORD CurBase); -static void tul_se2_ew_ds(WORD CurBase); -static int tul_se2_rd_all(WORD CurBase); -static void tul_se2_update_all(WORD CurBase); /* setup default pattern */ -static void tul_read_eeprom(WORD CurBase); - - /* ---- INTERNAL VARIABLES ---- */ -static HCS tul_hcs[MAX_SUPPORTED_ADAPTERS]; -static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS]; - -/*NVRAM nvram, *nvramp = &nvram; */ +/*--- forward references ---*/ +static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun); +static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host); + +static int tulip_main(struct initio_host * host); + +static int initio_next_state(struct initio_host * host); +static int initio_state_1(struct initio_host * host); +static int initio_state_2(struct initio_host * host); +static int initio_state_3(struct initio_host * host); +static int initio_state_4(struct initio_host * host); +static int initio_state_5(struct initio_host * host); +static int initio_state_6(struct initio_host * host); +static int initio_state_7(struct initio_host * host); +static int initio_xfer_data_in(struct initio_host * host); +static int initio_xfer_data_out(struct initio_host * host); +static int initio_xpad_in(struct initio_host * host); +static int initio_xpad_out(struct initio_host * host); +static int initio_status_msg(struct initio_host * host); + +static int initio_msgin(struct initio_host * host); +static int initio_msgin_sync(struct initio_host * host); +static int initio_msgin_accept(struct initio_host * host); +static int initio_msgout_reject(struct initio_host * host); +static int initio_msgin_extend(struct initio_host * host); + +static int initio_msgout_ide(struct initio_host * host); +static int initio_msgout_abort_targ(struct initio_host * host); +static int initio_msgout_abort_tag(struct initio_host * host); + +static int initio_bus_device_reset(struct initio_host * host); +static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb); +static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb); +static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb); +static int int_initio_busfree(struct initio_host * host); +static int int_initio_scsi_rst(struct initio_host * host); +static int int_initio_bad_seq(struct initio_host * host); +static int int_initio_resel(struct initio_host * host); +static int initio_sync_done(struct initio_host * host); +static int wdtr_done(struct initio_host * host); +static int wait_tulip(struct initio_host * host); +static int initio_wait_done_disc(struct initio_host * host); +static int initio_wait_disc(struct initio_host * host); +static void tulip_scsi(struct initio_host * host); +static int initio_post_scsi_rst(struct initio_host * host); + +static void initio_se2_ew_en(unsigned long base); +static void initio_se2_ew_ds(unsigned long base); +static int initio_se2_rd_all(unsigned long base); +static void initio_se2_update_all(unsigned long base); /* setup default pattern */ +static void initio_read_eeprom(unsigned long base); + +/* ---- INTERNAL VARIABLES ---- */ + static NVRAM i91unvram; static NVRAM *i91unvramp; - - -static UCHAR i91udftNvRam[64] = +static u8 i91udftNvRam[64] = { -/*----------- header -----------*/ + /*----------- header -----------*/ 0x25, 0xc9, /* Signature */ 0x40, /* Size */ 0x01, /* Revision */ @@ -289,7 +240,7 @@ static UCHAR i91udftNvRam[64] = 0, 0}; /* - CheckSum - */ -static UCHAR tul_rate_tbl[8] = /* fast 20 */ +static u8 initio_rate_tbl[8] = /* fast 20 */ { /* nanosecond devide by 4 */ 12, /* 50ns, 20M */ @@ -302,53 +253,17 @@ static UCHAR tul_rate_tbl[8] = /* fast 20 */ 62 /* 250ns, 4M */ }; -static void tul_do_pause(unsigned amount) -{ /* Pause for amount jiffies */ +static void initio_do_pause(unsigned amount) +{ + /* Pause for amount jiffies */ unsigned long the_time = jiffies + amount; - while (time_before_eq(jiffies, the_time)); + while (time_before_eq(jiffies, the_time)) + cpu_relax(); } /*-- forward reference --*/ -/******************************************************************* - Use memeory refresh time ~ 15us * 2 -********************************************************************/ -void tul_se2_wait(void) -{ -#if 1 - udelay(30); -#else - UCHAR readByte; - - readByte = TUL_RD(0, 0x61); - if ((readByte & 0x10) == 0x10) { - for (;;) { - readByte = TUL_RD(0, 0x61); - if ((readByte & 0x10) == 0x10) - break; - } - for (;;) { - readByte = TUL_RD(0, 0x61); - if ((readByte & 0x10) != 0x10) - break; - } - } else { - for (;;) { - readByte = TUL_RD(0, 0x61); - if ((readByte & 0x10) == 0x10) - break; - } - for (;;) { - readByte = TUL_RD(0, 0x61); - if ((readByte & 0x10) != 0x10) - break; - } - } -#endif -} - - /****************************************************************** Input: instruction for Serial E2PROM @@ -379,1174 +294,1019 @@ void tul_se2_wait(void) ******************************************************************/ -static void tul_se2_instr(WORD CurBase, UCHAR instr) + +/** + * initio_se2_instr - bitbang an instruction + * @base: Base of InitIO controller + * @instr: Instruction for serial E2PROM + * + * Bitbang an instruction out to the serial E2Prom + */ + +static void initio_se2_instr(unsigned long base, u8 instr) { int i; - UCHAR b; + u8 b; - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* cs+start bit */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO); /* +CLK */ - tul_se2_wait(); + outb(SE2CS | SE2DO, base + TUL_NVRAM); /* cs+start bit */ + udelay(30); + outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM); /* +CLK */ + udelay(30); for (i = 0; i < 8; i++) { if (instr & 0x80) - b = SE2CS | SE2DO; /* -CLK+dataBit */ + b = SE2CS | SE2DO; /* -CLK+dataBit */ else - b = SE2CS; /* -CLK */ - TUL_WR(CurBase + TUL_NVRAM, b); - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK); /* +CLK */ - tul_se2_wait(); + b = SE2CS; /* -CLK */ + outb(b, base + TUL_NVRAM); + udelay(30); + outb(b | SE2CLK, base + TUL_NVRAM); /* +CLK */ + udelay(30); instr <<= 1; } - TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ - tul_se2_wait(); - return; + outb(SE2CS, base + TUL_NVRAM); /* -CLK */ + udelay(30); } -/****************************************************************** - Function name : tul_se2_ew_en - Description : Enable erase/write state of serial EEPROM -******************************************************************/ -void tul_se2_ew_en(WORD CurBase) +/** + * initio_se2_ew_en - Enable erase/write + * @base: Base address of InitIO controller + * + * Enable erase/write state of serial EEPROM + */ +void initio_se2_ew_en(unsigned long base) { - tul_se2_instr(CurBase, 0x30); /* EWEN */ - TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ - tul_se2_wait(); - return; + initio_se2_instr(base, 0x30); /* EWEN */ + outb(0, base + TUL_NVRAM); /* -CS */ + udelay(30); } -/************************************************************************ - Disable erase/write state of serial EEPROM -*************************************************************************/ -void tul_se2_ew_ds(WORD CurBase) +/** + * initio_se2_ew_ds - Disable erase/write + * @base: Base address of InitIO controller + * + * Disable erase/write state of serial EEPROM + */ +void initio_se2_ew_ds(unsigned long base) { - tul_se2_instr(CurBase, 0); /* EWDS */ - TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ - tul_se2_wait(); - return; + initio_se2_instr(base, 0); /* EWDS */ + outb(0, base + TUL_NVRAM); /* -CS */ + udelay(30); } -/****************************************************************** - Input :address of Serial E2PROM - Output :value stored in Serial E2PROM -*******************************************************************/ -static USHORT tul_se2_rd(WORD CurBase, ULONG adr) +/** + * initio_se2_rd - read E2PROM word + * @base: Base of InitIO controller + * @addr: Address of word in E2PROM + * + * Read a word from the NV E2PROM device + */ +static u16 initio_se2_rd(unsigned long base, u8 addr) { - UCHAR instr, readByte; - USHORT readWord; + u8 instr, rb; + u16 val = 0; int i; - instr = (UCHAR) (adr | 0x80); - tul_se2_instr(CurBase, instr); /* READ INSTR */ - readWord = 0; + instr = (u8) (addr | 0x80); + initio_se2_instr(base, instr); /* READ INSTR */ for (i = 15; i >= 0; i--) { - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ + outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */ + udelay(30); + outb(SE2CS, base + TUL_NVRAM); /* -CLK */ /* sample data after the following edge of clock */ - readByte = TUL_RD(CurBase, TUL_NVRAM); - readByte &= SE2DI; - readWord += (readByte << i); - tul_se2_wait(); /* 6/20/95 */ + rb = inb(base + TUL_NVRAM); + rb &= SE2DI; + val += (rb << i); + udelay(30); /* 6/20/95 */ } - TUL_WR(CurBase + TUL_NVRAM, 0); /* no chip select */ - tul_se2_wait(); - return readWord; + outb(0, base + TUL_NVRAM); /* no chip select */ + udelay(30); + return val; } - -/****************************************************************** - Input: new value in Serial E2PROM, address of Serial E2PROM -*******************************************************************/ -static void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord) +/** + * initio_se2_wr - read E2PROM word + * @base: Base of InitIO controller + * @addr: Address of word in E2PROM + * @val: Value to write + * + * Write a word to the NV E2PROM device. Used when recovering from + * a problem with the NV. + */ +static void initio_se2_wr(unsigned long base, u8 addr, u16 val) { - UCHAR readByte; - UCHAR instr; + u8 rb; + u8 instr; int i; - instr = (UCHAR) (adr | 0x40); - tul_se2_instr(CurBase, instr); /* WRITE INSTR */ + instr = (u8) (addr | 0x40); + initio_se2_instr(base, instr); /* WRITE INSTR */ for (i = 15; i >= 0; i--) { - if (writeWord & 0x8000) - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* -CLK+dataBit 1 */ + if (val & 0x8000) + outb(SE2CS | SE2DO, base + TUL_NVRAM); /* -CLK+dataBit 1 */ else - TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK+dataBit 0 */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ - tul_se2_wait(); - writeWord <<= 1; + outb(SE2CS, base + TUL_NVRAM); /* -CLK+dataBit 0 */ + udelay(30); + outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */ + udelay(30); + val <<= 1; } - TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ - tul_se2_wait(); + outb(SE2CS, base + TUL_NVRAM); /* -CLK */ + udelay(30); + outb(0, base + TUL_NVRAM); /* -CS */ + udelay(30); - TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* +CS */ - tul_se2_wait(); + outb(SE2CS, base + TUL_NVRAM); /* +CS */ + udelay(30); for (;;) { - TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */ - tul_se2_wait(); - TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */ - tul_se2_wait(); - if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI) + outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */ + udelay(30); + outb(SE2CS, base + TUL_NVRAM); /* -CLK */ + udelay(30); + if ((rb = inb(base + TUL_NVRAM)) & SE2DI) break; /* write complete */ } - TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */ - return; + outb(0, base + TUL_NVRAM); /* -CS */ } +/** + * initio_se2_rd_all - read hostadapter NV configuration + * @base: Base address of InitIO controller + * + * Reads the E2PROM data into main memory. Ensures that the checksum + * and header marker are valid. Returns 1 on success -1 on error. + */ -/*********************************************************************** - Read SCSI H/A configuration parameters from serial EEPROM -************************************************************************/ -int tul_se2_rd_all(WORD CurBase) +static int initio_se2_rd_all(unsigned long base) { int i; - ULONG chksum = 0; - USHORT *np; + u16 chksum = 0; + u16 *np; i91unvramp = &i91unvram; - np = (USHORT *) i91unvramp; - for (i = 0; i < 32; i++) { - *np++ = tul_se2_rd(CurBase, i); - } + np = (u16 *) i91unvramp; + for (i = 0; i < 32; i++) + *np++ = initio_se2_rd(base, i); -/*--------------------Is signature "ini" ok ? ----------------*/ + /* Is signature "ini" ok ? */ if (i91unvramp->NVM_Signature != INI_SIGNATURE) return -1; -/*---------------------- Is ckecksum ok ? ----------------------*/ - np = (USHORT *) i91unvramp; + /* Is ckecksum ok ? */ + np = (u16 *) i91unvramp; for (i = 0; i < 31; i++) chksum += *np++; - if (i91unvramp->NVM_CheckSum != (USHORT) chksum) + if (i91unvramp->NVM_CheckSum != chksum) return -1; return 1; } - -/*********************************************************************** - Update SCSI H/A configuration parameters from serial EEPROM -************************************************************************/ -void tul_se2_update_all(WORD CurBase) +/** + * initio_se2_update_all - Update E2PROM + * @base: Base of InitIO controller + * + * Update the E2PROM by wrting any changes into the E2PROM + * chip, rewriting the checksum. + */ +static void initio_se2_update_all(unsigned long base) { /* setup default pattern */ int i; - ULONG chksum = 0; - USHORT *np, *np1; + u16 chksum = 0; + u16 *np, *np1; i91unvramp = &i91unvram; /* Calculate checksum first */ - np = (USHORT *) i91udftNvRam; + np = (u16 *) i91udftNvRam; for (i = 0; i < 31; i++) chksum += *np++; - *np = (USHORT) chksum; - tul_se2_ew_en(CurBase); /* Enable write */ + *np = chksum; + initio_se2_ew_en(base); /* Enable write */ - np = (USHORT *) i91udftNvRam; - np1 = (USHORT *) i91unvramp; + np = (u16 *) i91udftNvRam; + np1 = (u16 *) i91unvramp; for (i = 0; i < 32; i++, np++, np1++) { - if (*np != *np1) { - tul_se2_wr(CurBase, i, *np); - } + if (*np != *np1) + initio_se2_wr(base, i, *np); } - - tul_se2_ew_ds(CurBase); /* Disable write */ - return; + initio_se2_ew_ds(base); /* Disable write */ } -/************************************************************************* - Function name : read_eeprom -**************************************************************************/ -void tul_read_eeprom(WORD CurBase) -{ - UCHAR gctrl; - - i91unvramp = &i91unvram; -/*------Enable EEProm programming ---*/ - gctrl = TUL_RD(CurBase, TUL_GCTRL); - TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT); - if (tul_se2_rd_all(CurBase) != 1) { - tul_se2_update_all(CurBase); /* setup default pattern */ - tul_se2_rd_all(CurBase); /* load again */ - } -/*------ Disable EEProm programming ---*/ - gctrl = TUL_RD(CurBase, TUL_GCTRL); - TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT); -} /* read_eeprom */ +/** + * initio_read_eeprom - Retrieve configuration + * @base: Base of InitIO Host Adapter + * + * Retrieve the host adapter configuration data from E2Prom. If the + * data is invalid then the defaults are used and are also restored + * into the E2PROM. This forms the access point for the SCSI driver + * into the E2PROM layer, the other functions for the E2PROM are all + * internal use. + * + * Must be called single threaded, uses a shared global area. + */ -static int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt, - BYTE bBus, BYTE bDevice) +static void initio_read_eeprom(unsigned long base) { - int i, j; + u8 gctrl; - for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { - if (i91u_adpt[i].ADPT_BIOS < wBIOS) - continue; - if (i91u_adpt[i].ADPT_BIOS == wBIOS) { - if (i91u_adpt[i].ADPT_BASE == wBASE) { - if (i91u_adpt[i].ADPT_Bus != 0xFF) - return 1; - } else if (i91u_adpt[i].ADPT_BASE < wBASE) - continue; - } - for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) { - i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE; - i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR; - i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS; - i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus; - i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device; - } - i91u_adpt[i].ADPT_BASE = wBASE; - i91u_adpt[i].ADPT_INTR = bInterrupt; - i91u_adpt[i].ADPT_BIOS = wBIOS; - i91u_adpt[i].ADPT_Bus = bBus; - i91u_adpt[i].ADPT_Device = bDevice; - return 0; + i91unvramp = &i91unvram; + /* Enable EEProm programming */ + gctrl = inb(base + TUL_GCTRL); + outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL); + if (initio_se2_rd_all(base) != 1) { + initio_se2_update_all(base); /* setup default pattern */ + initio_se2_rd_all(base); /* load again */ } - return 1; + /* Disable EEProm programming */ + gctrl = inb(base + TUL_GCTRL); + outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL); } -static void init_i91uAdapter_table(void) -{ - int i; - - for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { /* Initialize adapter structure */ - i91u_adpt[i].ADPT_BIOS = 0xffff; - i91u_adpt[i].ADPT_BASE = 0xffff; - i91u_adpt[i].ADPT_INTR = 0xff; - i91u_adpt[i].ADPT_Bus = 0xff; - i91u_adpt[i].ADPT_Device = 0xff; - } - return; -} +/** + * initio_stop_bm - stop bus master + * @host: InitIO we are stopping + * + * Stop any pending DMA operation, aborting the DMA if neccessary + */ -static void tul_stop_bm(HCS * pCurHcb) +static void initio_stop_bm(struct initio_host * host) { - if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO); + if (inb(host->addr + TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ + outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd); /* wait Abort DMA xfer done */ - while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0); + while ((inb(host->addr + TUL_Int) & XABT) == 0) + cpu_relax(); } - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); } -/***************************************************************************/ -static void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx) -{ - pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE; /* Supply base address */ - pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */ - pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line */ - return; -} +/** + * initio_reset_scsi - Reset SCSI host controller + * @host: InitIO host to reset + * @seconds: Recovery time + * + * Perform a full reset of the SCSI subsystem. + */ -/***************************************************************************/ -static int tul_reset_scsi(HCS * pCurHcb, int seconds) +static int initio_reset_scsi(struct initio_host * host, int seconds) { - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS); + outb(TSC_RST_BUS, host->addr + TUL_SCtrl0); - while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT)); - /* reset tulip chip */ + while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT)) + cpu_relax(); - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0); + /* reset tulip chip */ + outb(0, host->addr + TUL_SSignal); /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */ /* SONY 5200 tape drive won't work if only stall for 1 sec */ - tul_do_pause(seconds * HZ); - - TUL_RD(pCurHcb->HCS_Base, TUL_SInt); + /* FIXME: this is a very long busy wait right now */ + initio_do_pause(seconds * HZ); - return (SCSI_RESET_SUCCESS); + inb(host->addr + TUL_SInt); + return SCSI_RESET_SUCCESS; } -/***************************************************************************/ -static int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, - BYTE * pbBiosAdr, int seconds) +/** + * initio_init - set up an InitIO host adapter + * @host: InitIO host adapter + * @num_scbs: Number of SCBS + * @bios_addr: BIOS address + * + * Set up the host adapter and devices according to the configuration + * retrieved from the E2PROM. + * + * Locking: Calls E2PROM layer code which is not re-enterable so must + * run single threaded for now. + */ + +static void initio_init(struct initio_host * host, u8 *bios_addr) { int i; - BYTE *pwFlags; - BYTE *pbHeads; - SCB *pTmpScb, *pPrevScb = NULL; - - pCurHcb->HCS_NumScbs = tul_num_scb; - pCurHcb->HCS_Semaph = 1; - spin_lock_init(&pCurHcb->HCS_SemaphLock); - pCurHcb->HCS_JSStatus0 = 0; - pCurHcb->HCS_Scb = scbp; - pCurHcb->HCS_NxtPend = scbp; - pCurHcb->HCS_NxtAvail = scbp; - for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) { - pTmpScb->SCB_TagId = i; - if (i != 0) - pPrevScb->SCB_NxtScb = pTmpScb; - pPrevScb = pTmpScb; - } - pPrevScb->SCB_NxtScb = NULL; - pCurHcb->HCS_ScbEnd = pTmpScb; - pCurHcb->HCS_FirstAvail = scbp; - pCurHcb->HCS_LastAvail = pPrevScb; - spin_lock_init(&pCurHcb->HCS_AvailLock); - pCurHcb->HCS_FirstPend = NULL; - pCurHcb->HCS_LastPend = NULL; - pCurHcb->HCS_FirstBusy = NULL; - pCurHcb->HCS_LastBusy = NULL; - pCurHcb->HCS_FirstDone = NULL; - pCurHcb->HCS_LastDone = NULL; - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; - - tul_read_eeprom(pCurHcb->HCS_Base); -/*---------- get H/A configuration -------------*/ + u8 *flags; + u8 *heads; + + /* Get E2Prom configuration */ + initio_read_eeprom(host->addr); if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8) - pCurHcb->HCS_MaxTar = 8; + host->max_tar = 8; else - pCurHcb->HCS_MaxTar = 16; + host->max_tar = 16; - pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1; + host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1; - pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID; - pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID); + host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID; + host->idmask = ~(1 << host->scsi_id); #ifdef CHK_PARITY /* Enable parity error response */ - TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40); + outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD); #endif /* Mask all the interrupt */ - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + outb(0x1F, host->addr + TUL_Mask); - tul_stop_bm(pCurHcb); + initio_stop_bm(host); /* --- Initialize the tulip --- */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP); + outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0); /* program HBA's SCSI ID */ - TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4); + outb(host->scsi_id << 4, host->addr + TUL_SScsiId); /* Enable Initiator Mode ,phase latch,alternate sync period mode, disable SCSI reset */ - if (pCurHcb->HCS_Config & HCC_EN_PAR) - pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR); + if (host->config & HCC_EN_PAR) + host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR); else - pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1); + host->sconf1 = (TSC_INITDEFAULT); + outb(host->sconf1, host->addr + TUL_SConfig); - /* Enable HW reselect */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); + /* Enable HW reselect */ + outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); - TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0); + outb(0, host->addr + TUL_SPeriod); /* selection time out = 250 ms */ - TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153); + outb(153, host->addr + TUL_STimeOut); -/*--------- Enable SCSI terminator -----*/ - TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2))); - TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1, - ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE)); + /* Enable SCSI terminator */ + outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)), + host->addr + TUL_XCtrl); + outb(((host->config & HCC_AUTO_TERM) >> 4) | + (inb(host->addr + TUL_GCTRL1) & 0xFE), + host->addr + TUL_GCTRL1); for (i = 0, - pwFlags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config), - pbHeads = pbBiosAdr + 0x180; - i < pCurHcb->HCS_MaxTar; - i++, pwFlags++) { - pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE); - if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255) - pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63; + flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config), + heads = bios_addr + 0x180; + i < host->max_tar; + i++, flags++) { + host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE); + if (host->targets[i].flags & TCF_EN_255) + host->targets[i].drv_flags = TCF_DRV_255_63; else - pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0; - pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0; - pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1; - pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++; - if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255) - pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63; + host->targets[i].drv_flags = 0; + host->targets[i].js_period = 0; + host->targets[i].sconfig0 = host->sconf1; + host->targets[i].heads = *heads++; + if (host->targets[i].heads == 255) + host->targets[i].drv_flags = TCF_DRV_255_63; else - pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0; - pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++; - pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY; - pCurHcb->HCS_ActTags[i] = 0; - pCurHcb->HCS_MaxTags[i] = 0xFF; + host->targets[i].drv_flags = 0; + host->targets[i].sectors = *heads++; + host->targets[i].flags &= ~TCF_BUSY; + host->act_tags[i] = 0; + host->max_tags[i] = 0xFF; } /* for */ printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n", - pCurHcb->HCS_Base, pCurHcb->HCS_Intr, - pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID); -/*------------------- reset SCSI Bus ---------------------------*/ - if (pCurHcb->HCS_Config & HCC_SCSI_RESET) { - printk("i91u: Reset SCSI Bus ... \n"); - tul_reset_scsi(pCurHcb, seconds); + host->addr, host->irq, + host->bios_addr, host->scsi_id); + /* Reset SCSI Bus */ + if (host->config & HCC_SCSI_RESET) { + printk(KERN_INFO "i91u: Reset SCSI Bus ... \n"); + initio_reset_scsi(host, 10); } - TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17); - TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9); - return (0); + outb(0x17, host->addr + TUL_SCFG1); + outb(0xE9, host->addr + TUL_SIntEnable); } -/***************************************************************************/ -static SCB *tul_alloc_scb(HCS * hcsp) +/** + * initio_alloc_scb - Allocate an SCB + * @host: InitIO host we are allocating for + * + * Walk the SCB list for the controller and allocate a free SCB if + * one exists. + */ +static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host) { - SCB *pTmpScb; - ULONG flags; - spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags); - if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) { + struct scsi_ctrl_blk *scb; + unsigned long flags; + + spin_lock_irqsave(&host->avail_lock, flags); + if ((scb = host->first_avail) != NULL) { #if DEBUG_QUEUE - printk("find scb at %08lx\n", (ULONG) pTmpScb); + printk("find scb at %p\n", scb); #endif - if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL) - hcsp->HCS_LastAvail = NULL; - pTmpScb->SCB_NxtScb = NULL; - pTmpScb->SCB_Status = SCB_RENT; + if ((host->first_avail = scb->next) == NULL) + host->last_avail = NULL; + scb->next = NULL; + scb->status = SCB_RENT; } - spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags); - return (pTmpScb); + spin_unlock_irqrestore(&host->avail_lock, flags); + return scb; } -/***************************************************************************/ -static void tul_release_scb(HCS * hcsp, SCB * scbp) +/** + * initio_release_scb - Release an SCB + * @host: InitIO host that owns the SCB + * @cmnd: SCB command block being returned + * + * Return an allocated SCB to the host free list + */ + +static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd) { - ULONG flags; + unsigned long flags; #if DEBUG_QUEUE - printk("Release SCB %lx; ", (ULONG) scbp); + printk("Release SCB %p; ", cmnd); #endif - spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags); - scbp->SCB_Srb = NULL; - scbp->SCB_Status = 0; - scbp->SCB_NxtScb = NULL; - if (hcsp->HCS_LastAvail != NULL) { - hcsp->HCS_LastAvail->SCB_NxtScb = scbp; - hcsp->HCS_LastAvail = scbp; + spin_lock_irqsave(&(host->avail_lock), flags); + cmnd->srb = NULL; + cmnd->status = 0; + cmnd->next = NULL; + if (host->last_avail != NULL) { + host->last_avail->next = cmnd; + host->last_avail = cmnd; } else { - hcsp->HCS_FirstAvail = scbp; - hcsp->HCS_LastAvail = scbp; + host->first_avail = cmnd; + host->last_avail = cmnd; } - spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags); + spin_unlock_irqrestore(&(host->avail_lock), flags); } /***************************************************************************/ -static void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp) +static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp) { #if DEBUG_QUEUE - printk("Append pend SCB %lx; ", (ULONG) scbp); + printk("Append pend SCB %p; ", scbp); #endif - scbp->SCB_Status = SCB_PEND; - scbp->SCB_NxtScb = NULL; - if (pCurHcb->HCS_LastPend != NULL) { - pCurHcb->HCS_LastPend->SCB_NxtScb = scbp; - pCurHcb->HCS_LastPend = scbp; + scbp->status = SCB_PEND; + scbp->next = NULL; + if (host->last_pending != NULL) { + host->last_pending->next = scbp; + host->last_pending = scbp; } else { - pCurHcb->HCS_FirstPend = scbp; - pCurHcb->HCS_LastPend = scbp; + host->first_pending = scbp; + host->last_pending = scbp; } } /***************************************************************************/ -static void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp) +static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp) { #if DEBUG_QUEUE - printk("Push pend SCB %lx; ", (ULONG) scbp); + printk("Push pend SCB %p; ", scbp); #endif - scbp->SCB_Status = SCB_PEND; - if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) { - pCurHcb->HCS_FirstPend = scbp; + scbp->status = SCB_PEND; + if ((scbp->next = host->first_pending) != NULL) { + host->first_pending = scbp; } else { - pCurHcb->HCS_FirstPend = scbp; - pCurHcb->HCS_LastPend = scbp; + host->first_pending = scbp; + host->last_pending = scbp; } } -/***************************************************************************/ -static SCB *tul_find_first_pend_scb(HCS * pCurHcb) +static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host) { - SCB *pFirstPend; + struct scsi_ctrl_blk *first; - pFirstPend = pCurHcb->HCS_FirstPend; - while (pFirstPend != NULL) { - if (pFirstPend->SCB_Opcode != ExecSCSI) { - return (pFirstPend); - } - if (pFirstPend->SCB_TagMsg == 0) { - if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) && - !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) { - return (pFirstPend); - } + first = host->first_pending; + while (first != NULL) { + if (first->opcode != ExecSCSI) + return first; + if (first->tagmsg == 0) { + if ((host->act_tags[first->target] == 0) && + !(host->targets[first->target].flags & TCF_BUSY)) + return first; } else { - if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >= - pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) | - (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) { - pFirstPend = pFirstPend->SCB_NxtScb; + if ((host->act_tags[first->target] >= + host->max_tags[first->target]) | + (host->targets[first->target].flags & TCF_BUSY)) { + first = first->next; continue; } - return (pFirstPend); + return first; } - pFirstPend = pFirstPend->SCB_NxtScb; + first = first->next; } - - - return (pFirstPend); + return first; } -/***************************************************************************/ -static void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb) + +static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb) { - SCB *pTmpScb, *pPrevScb; + struct scsi_ctrl_blk *tmp, *prev; #if DEBUG_QUEUE - printk("unlink pend SCB %lx; ", (ULONG) pCurScb); + printk("unlink pend SCB %p; ", scb); #endif - pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; - while (pTmpScb != NULL) { - if (pCurScb == pTmpScb) { /* Unlink this SCB */ - if (pTmpScb == pCurHcb->HCS_FirstPend) { - if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastPend = NULL; + prev = tmp = host->first_pending; + while (tmp != NULL) { + if (scb == tmp) { /* Unlink this SCB */ + if (tmp == host->first_pending) { + if ((host->first_pending = tmp->next) == NULL) + host->last_pending = NULL; } else { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastPend) - pCurHcb->HCS_LastPend = pPrevScb; + prev->next = tmp->next; + if (tmp == host->last_pending) + host->last_pending = prev; } - pTmpScb->SCB_NxtScb = NULL; + tmp->next = NULL; break; } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; + prev = tmp; + tmp = tmp->next; } - return; } -/***************************************************************************/ -static void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp) + +static void initio_append_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp) { #if DEBUG_QUEUE - printk("append busy SCB %lx; ", (ULONG) scbp); + printk("append busy SCB %o; ", scbp); #endif - if (scbp->SCB_TagMsg) - pCurHcb->HCS_ActTags[scbp->SCB_Target]++; + if (scbp->tagmsg) + host->act_tags[scbp->target]++; else - pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY; - scbp->SCB_Status = SCB_BUSY; - scbp->SCB_NxtScb = NULL; - if (pCurHcb->HCS_LastBusy != NULL) { - pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp; - pCurHcb->HCS_LastBusy = scbp; + host->targets[scbp->target].flags |= TCF_BUSY; + scbp->status = SCB_BUSY; + scbp->next = NULL; + if (host->last_busy != NULL) { + host->last_busy->next = scbp; + host->last_busy = scbp; } else { - pCurHcb->HCS_FirstBusy = scbp; - pCurHcb->HCS_LastBusy = scbp; + host->first_busy = scbp; + host->last_busy = scbp; } } /***************************************************************************/ -static SCB *tul_pop_busy_scb(HCS * pCurHcb) +static struct scsi_ctrl_blk *initio_pop_busy_scb(struct initio_host * host) { - SCB *pTmpScb; + struct scsi_ctrl_blk *tmp; - if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; - pTmpScb->SCB_NxtScb = NULL; - if (pTmpScb->SCB_TagMsg) - pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; + if ((tmp = host->first_busy) != NULL) { + if ((host->first_busy = tmp->next) == NULL) + host->last_busy = NULL; + tmp->next = NULL; + if (tmp->tagmsg) + host->act_tags[tmp->target]--; else - pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY; + host->targets[tmp->target].flags &= ~TCF_BUSY; } #if DEBUG_QUEUE - printk("Pop busy SCB %lx; ", (ULONG) pTmpScb); + printk("Pop busy SCB %p; ", tmp); #endif - return (pTmpScb); + return tmp; } /***************************************************************************/ -static void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb) +static void initio_unlink_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scb) { - SCB *pTmpScb, *pPrevScb; + struct scsi_ctrl_blk *tmp, *prev; #if DEBUG_QUEUE - printk("unlink busy SCB %lx; ", (ULONG) pCurScb); + printk("unlink busy SCB %p; ", scb); #endif - pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; - while (pTmpScb != NULL) { - if (pCurScb == pTmpScb) { /* Unlink this SCB */ - if (pTmpScb == pCurHcb->HCS_FirstBusy) { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; + prev = tmp = host->first_busy; + while (tmp != NULL) { + if (scb == tmp) { /* Unlink this SCB */ + if (tmp == host->first_busy) { + if ((host->first_busy = tmp->next) == NULL) + host->last_busy = NULL; } else { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastBusy) - pCurHcb->HCS_LastBusy = pPrevScb; + prev->next = tmp->next; + if (tmp == host->last_busy) + host->last_busy = prev; } - pTmpScb->SCB_NxtScb = NULL; - if (pTmpScb->SCB_TagMsg) - pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; + tmp->next = NULL; + if (tmp->tagmsg) + host->act_tags[tmp->target]--; else - pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY; + host->targets[tmp->target].flags &= ~TCF_BUSY; break; } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; + prev = tmp; + tmp = tmp->next; } return; } -/***************************************************************************/ -SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun) +struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun) { - SCB *pTmpScb, *pPrevScb; - WORD scbp_tarlun; + struct scsi_ctrl_blk *tmp, *prev; + u16 scbp_tarlun; - pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; - while (pTmpScb != NULL) { - scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target); + prev = tmp = host->first_busy; + while (tmp != NULL) { + scbp_tarlun = (tmp->lun << 8) | (tmp->target); if (scbp_tarlun == tarlun) { /* Unlink this SCB */ break; } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; + prev = tmp; + tmp = tmp->next; } #if DEBUG_QUEUE - printk("find busy SCB %lx; ", (ULONG) pTmpScb); + printk("find busy SCB %p; ", tmp); #endif - return (pTmpScb); + return tmp; } -/***************************************************************************/ -static void tul_append_done_scb(HCS * pCurHcb, SCB * scbp) +static void initio_append_done_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp) { - #if DEBUG_QUEUE - printk("append done SCB %lx; ", (ULONG) scbp); + printk("append done SCB %p; ", scbp); #endif - scbp->SCB_Status = SCB_DONE; - scbp->SCB_NxtScb = NULL; - if (pCurHcb->HCS_LastDone != NULL) { - pCurHcb->HCS_LastDone->SCB_NxtScb = scbp; - pCurHcb->HCS_LastDone = scbp; + scbp->status = SCB_DONE; + scbp->next = NULL; + if (host->last_done != NULL) { + host->last_done->next = scbp; + host->last_done = scbp; } else { - pCurHcb->HCS_FirstDone = scbp; - pCurHcb->HCS_LastDone = scbp; + host->first_done = scbp; + host->last_done = scbp; } } -/***************************************************************************/ -SCB *tul_find_done_scb(HCS * pCurHcb) +struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host) { - SCB *pTmpScb; + struct scsi_ctrl_blk *tmp; - - if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) { - if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastDone = NULL; - pTmpScb->SCB_NxtScb = NULL; + if ((tmp = host->first_done) != NULL) { + if ((host->first_done = tmp->next) == NULL) + host->last_done = NULL; + tmp->next = NULL; } #if DEBUG_QUEUE - printk("find done SCB %lx; ", (ULONG) pTmpScb); + printk("find done SCB %p; ",tmp); #endif - return (pTmpScb); + return tmp; } -/***************************************************************************/ -static int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp) +static int initio_abort_srb(struct initio_host * host, struct scsi_cmnd *srbp) { - ULONG flags; - SCB *pTmpScb, *pPrevScb; + unsigned long flags; + struct scsi_ctrl_blk *tmp, *prev; - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); + spin_lock_irqsave(&host->semaph_lock, flags); - if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + if ((host->semaph == 0) && (host->active == NULL)) { /* disable Jasmin SCSI Int */ - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - - tulip_main(pCurHcb); - - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); - - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - + outb(0x1F, host->addr + TUL_Mask); + spin_unlock_irqrestore(&host->semaph_lock, flags); + /* FIXME: synchronize_irq needed ? */ + tulip_main(host); + spin_lock_irqsave(&host->semaph_lock, flags); + host->semaph = 1; + outb(0x0F, host->addr + TUL_Mask); + spin_unlock_irqrestore(&host->semaph_lock, flags); return SCSI_ABORT_SNOOZE; } - pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; /* Check Pend queue */ - while (pTmpScb != NULL) { + prev = tmp = host->first_pending; /* Check Pend queue */ + while (tmp != NULL) { /* 07/27/98 */ - if (pTmpScb->SCB_Srb == srbp) { - if (pTmpScb == pCurHcb->HCS_ActScb) { - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); + if (tmp->srb == srbp) { + if (tmp == host->active) { + spin_unlock_irqrestore(&host->semaph_lock, flags); return SCSI_ABORT_BUSY; - } else if (pTmpScb == pCurHcb->HCS_FirstPend) { - if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastPend = NULL; + } else if (tmp == host->first_pending) { + if ((host->first_pending = tmp->next) == NULL) + host->last_pending = NULL; } else { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastPend) - pCurHcb->HCS_LastPend = pPrevScb; + prev->next = tmp->next; + if (tmp == host->last_pending) + host->last_pending = prev; } - pTmpScb->SCB_HaStat = HOST_ABORTED; - pTmpScb->SCB_Flags |= SCF_DONE; - if (pTmpScb->SCB_Flags & SCF_POST) - (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb); - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); + tmp->hastat = HOST_ABORTED; + tmp->flags |= SCF_DONE; + if (tmp->flags & SCF_POST) + (*tmp->post) ((u8 *) host, (u8 *) tmp); + spin_unlock_irqrestore(&host->semaph_lock, flags); return SCSI_ABORT_SUCCESS; } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; + prev = tmp; + tmp = tmp->next; } - pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ - while (pTmpScb != NULL) { - - if (pTmpScb->SCB_Srb == srbp) { - - if (pTmpScb == pCurHcb->HCS_ActScb) { - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); + prev = tmp = host->first_busy; /* Check Busy queue */ + while (tmp != NULL) { + if (tmp->srb == srbp) { + if (tmp == host->active) { + spin_unlock_irqrestore(&host->semaph_lock, flags); return SCSI_ABORT_BUSY; - } else if (pTmpScb->SCB_TagMsg == 0) { - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); + } else if (tmp->tagmsg == 0) { + spin_unlock_irqrestore(&host->semaph_lock, flags); return SCSI_ABORT_BUSY; } else { - pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; - if (pTmpScb == pCurHcb->HCS_FirstBusy) { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; + host->act_tags[tmp->target]--; + if (tmp == host->first_busy) { + if ((host->first_busy = tmp->next) == NULL) + host->last_busy = NULL; } else { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastBusy) - pCurHcb->HCS_LastBusy = pPrevScb; + prev->next = tmp->next; + if (tmp == host->last_busy) + host->last_busy = prev; } - pTmpScb->SCB_NxtScb = NULL; + tmp->next = NULL; - pTmpScb->SCB_HaStat = HOST_ABORTED; - pTmpScb->SCB_Flags |= SCF_DONE; - if (pTmpScb->SCB_Flags & SCF_POST) - (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb); - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); + tmp->hastat = HOST_ABORTED; + tmp->flags |= SCF_DONE; + if (tmp->flags & SCF_POST) + (*tmp->post) ((u8 *) host, (u8 *) tmp); + spin_unlock_irqrestore(&host->semaph_lock, flags); return SCSI_ABORT_SUCCESS; } } - pPrevScb = pTmpScb; - pTmpScb = pTmpScb->SCB_NxtScb; + prev = tmp; + tmp = tmp->next; } - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - return (SCSI_ABORT_NOT_RUNNING); + spin_unlock_irqrestore(&host->semaph_lock, flags); + return SCSI_ABORT_NOT_RUNNING; } /***************************************************************************/ -static int tul_bad_seq(HCS * pCurHcb) +static int initio_bad_seq(struct initio_host * host) { - SCB *pCurScb; - - printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index); - - if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) { - tul_unlink_busy_scb(pCurHcb, pCurScb); - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - pCurScb->SCB_TaStat = 0; - tul_append_done_scb(pCurHcb, pCurScb); - } - tul_stop_bm(pCurHcb); - - tul_reset_scsi(pCurHcb, 8); /* 7/29/98 */ - - return (tul_post_scsi_rst(pCurHcb)); -} - -#if 0 - -/************************************************************************/ -static int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb, - unsigned int target, unsigned int ResetFlags) -{ - ULONG flags; - SCB *pScb; - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); - - if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) { - - if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - /* disable Jasmin SCSI Int */ - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - - tulip_main(pCurHcb); - - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); - - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - - return SCSI_RESET_SNOOZE; - } - pScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ - while (pScb != NULL) { - if (pScb->SCB_Srb == pSrb) - break; - pScb = pScb->SCB_NxtScb; - } - if (pScb == NULL) { - printk("Unable to Reset - No SCB Found\n"); - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - return SCSI_RESET_NOT_RUNNING; - } - } - if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) { - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - return SCSI_RESET_NOT_RUNNING; - } - pScb->SCB_Opcode = BusDevRst; - pScb->SCB_Flags = SCF_POST; - pScb->SCB_Target = target; - pScb->SCB_Mode = 0; - - pScb->SCB_Srb = NULL; - if (ResetFlags & SCSI_RESET_SYNCHRONOUS) { - pScb->SCB_Srb = pSrb; - } - tul_push_pend_scb(pCurHcb, pScb); /* push this SCB to Pending queue */ - - if (pCurHcb->HCS_Semaph == 1) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - /* disable Jasmin SCSI Int */ - pCurHcb->HCS_Semaph = 0; - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); + struct scsi_ctrl_blk *scb; - tulip_main(pCurHcb); + printk("initio_bad_seg c=%d\n", host->index); - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); - - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); + if ((scb = host->active) != NULL) { + initio_unlink_busy_scb(host, scb); + scb->hastat = HOST_BAD_PHAS; + scb->tastat = 0; + initio_append_done_scb(host, scb); } - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - return SCSI_RESET_PENDING; + initio_stop_bm(host); + initio_reset_scsi(host, 8); /* 7/29/98 */ + return initio_post_scsi_rst(host); } -static int tul_reset_scsi_bus(HCS * pCurHcb) -{ - ULONG flags; - - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - pCurHcb->HCS_Semaph = 0; - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - - tul_stop_bm(pCurHcb); - - tul_reset_scsi(pCurHcb, 2); /* 7/29/98 */ - - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); - tul_post_scsi_rst(pCurHcb); - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - - tulip_main(pCurHcb); - - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); - - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); - return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET); -} - -#endif /* 0 */ /************************************************************************/ -static void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb) +static void initio_exec_scb(struct initio_host * host, struct scsi_ctrl_blk * scb) { - ULONG flags; + unsigned long flags; - pCurScb->SCB_Mode = 0; + scb->mode = 0; - pCurScb->SCB_SGIdx = 0; - pCurScb->SCB_SGMax = pCurScb->SCB_SGLen; + scb->sgidx = 0; + scb->sgmax = scb->sglen; - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); + spin_lock_irqsave(&host->semaph_lock, flags); - tul_append_pend_scb(pCurHcb, pCurScb); /* Append this SCB to Pending queue */ + initio_append_pend_scb(host, scb); /* Append this SCB to Pending queue */ /* VVVVV 07/21/98 */ - if (pCurHcb->HCS_Semaph == 1) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); - /* disable Jasmin SCSI Int */ - pCurHcb->HCS_Semaph = 0; - - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); + if (host->semaph == 1) { + /* Disable Jasmin SCSI Int */ + outb(0x1F, host->addr + TUL_Mask); + host->semaph = 0; + spin_unlock_irqrestore(&host->semaph_lock, flags); - tulip_main(pCurHcb); + tulip_main(host); - spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); - - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); + spin_lock_irqsave(&host->semaph_lock, flags); + host->semaph = 1; + outb(0x0F, host->addr + TUL_Mask); } - spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); + spin_unlock_irqrestore(&host->semaph_lock, flags); return; } /***************************************************************************/ -static int tul_isr(HCS * pCurHcb) +static int initio_isr(struct initio_host * host) { - /* Enter critical section */ - - if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) { - if (pCurHcb->HCS_Semaph == 1) { - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); + if (inb(host->addr + TUL_Int) & TSS_INT_PENDING) { + if (host->semaph == 1) { + outb(0x1F, host->addr + TUL_Mask); /* Disable Tulip SCSI Int */ - pCurHcb->HCS_Semaph = 0; + host->semaph = 0; - tulip_main(pCurHcb); + tulip_main(host); - pCurHcb->HCS_Semaph = 1; - TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); - return (1); + host->semaph = 1; + outb(0x0F, host->addr + TUL_Mask); + return 1; } } - return (0); + return 0; } -/***************************************************************************/ -int tulip_main(HCS * pCurHcb) +static int tulip_main(struct initio_host * host) { - SCB *pCurScb; + struct scsi_ctrl_blk *scb; for (;;) { - - tulip_scsi(pCurHcb); /* Call tulip_scsi */ - - while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) { /* find done entry */ - if (pCurScb->SCB_TaStat == INI_QUEUE_FULL) { - pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] = - pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1; - pCurScb->SCB_TaStat = 0; - tul_append_pend_scb(pCurHcb, pCurScb); + tulip_scsi(host); /* Call tulip_scsi */ + + /* Walk the list of completed SCBs */ + while ((scb = initio_find_done_scb(host)) != NULL) { /* find done entry */ + if (scb->tastat == INI_QUEUE_FULL) { + host->max_tags[scb->target] = + host->act_tags[scb->target] - 1; + scb->tastat = 0; + initio_append_pend_scb(host, scb); continue; } - if (!(pCurScb->SCB_Mode & SCM_RSENS)) { /* not in auto req. sense mode */ - if (pCurScb->SCB_TaStat == 2) { + if (!(scb->mode & SCM_RSENS)) { /* not in auto req. sense mode */ + if (scb->tastat == 2) { /* clr sync. nego flag */ - if (pCurScb->SCB_Flags & SCF_SENSE) { - BYTE len; - len = pCurScb->SCB_SenseLen; + if (scb->flags & SCF_SENSE) { + u8 len; + len = scb->senselen; if (len == 0) len = 1; - pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen; - pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr; - pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR); /* for xfer_data_in */ -/* pCurScb->SCB_Flags |= SCF_NO_DCHK; */ - /* so, we won't report worng direction in xfer_data_in, + scb->buflen = scb->senselen; + scb->bufptr = scb->senseptr; + scb->flags &= ~(SCF_SG | SCF_DIR); /* for xfer_data_in */ + /* so, we won't report wrong direction in xfer_data_in, and won't report HOST_DO_DU in state_6 */ - pCurScb->SCB_Mode = SCM_RSENS; - pCurScb->SCB_Ident &= 0xBF; /* Disable Disconnect */ - pCurScb->SCB_TagMsg = 0; - pCurScb->SCB_TaStat = 0; - pCurScb->SCB_CDBLen = 6; - pCurScb->SCB_CDB[0] = SCSICMD_RequestSense; - pCurScb->SCB_CDB[1] = 0; - pCurScb->SCB_CDB[2] = 0; - pCurScb->SCB_CDB[3] = 0; - pCurScb->SCB_CDB[4] = len; - pCurScb->SCB_CDB[5] = 0; - tul_push_pend_scb(pCurHcb, pCurScb); + scb->mode = SCM_RSENS; + scb->ident &= 0xBF; /* Disable Disconnect */ + scb->tagmsg = 0; + scb->tastat = 0; + scb->cdblen = 6; + scb->cdb[0] = SCSICMD_RequestSense; + scb->cdb[1] = 0; + scb->cdb[2] = 0; + scb->cdb[3] = 0; + scb->cdb[4] = len; + scb->cdb[5] = 0; + initio_push_pend_scb(host, scb); break; } } } else { /* in request sense mode */ - if (pCurScb->SCB_TaStat == 2) { /* check contition status again after sending + if (scb->tastat == 2) { /* check contition status again after sending requset sense cmd 0x3 */ - pCurScb->SCB_HaStat = HOST_BAD_PHAS; + scb->hastat = HOST_BAD_PHAS; } - pCurScb->SCB_TaStat = 2; + scb->tastat = 2; } - pCurScb->SCB_Flags |= SCF_DONE; - if (pCurScb->SCB_Flags & SCF_POST) { - (*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb); + scb->flags |= SCF_DONE; + if (scb->flags & SCF_POST) { + /* FIXME: only one post method and lose casts */ + (*scb->post) ((u8 *) host, (u8 *) scb); } } /* while */ - /* find_active: */ - if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING) + if (inb(host->addr + TUL_SStatus0) & TSS_INT_PENDING) continue; - - if (pCurHcb->HCS_ActScb) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */ + if (host->active) /* return to OS and wait for xfer_done_ISR/Selected_ISR */ return 1; /* return to OS, enable interrupt */ - } /* Check pending SCB */ - if (tul_find_first_pend_scb(pCurHcb) == NULL) { + if (initio_find_first_pend_scb(host) == NULL) return 1; /* return to OS, enable interrupt */ - } } /* End of for loop */ /* statement won't reach here */ } - - - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ - -/***************************************************************************/ -void tulip_scsi(HCS * pCurHcb) +static void tulip_scsi(struct initio_host * host) { - SCB *pCurScb; - TCS *pCurTcb; + struct scsi_ctrl_blk *scb; + struct target_control *active_tc; /* make sure to service interrupt asap */ - - if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) { - - pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK; - pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1); - pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* SCSI bus reset detected */ - int_tul_scsi_rst(pCurHcb); + if ((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING) { + host->phase = host->jsstatus0 & TSS_PH_MASK; + host->jsstatus1 = inb(host->addr + TUL_SStatus1); + host->jsint = inb(host->addr + TUL_SInt); + if (host->jsint & TSS_SCSIRST_INT) { /* SCSI bus reset detected */ + int_initio_scsi_rst(host); return; } - if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) { /* if selected/reselected interrupt */ - if (int_tul_resel(pCurHcb) == 0) - tul_next_state(pCurHcb); + if (host->jsint & TSS_RESEL_INT) { /* if selected/reselected interrupt */ + if (int_initio_resel(host) == 0) + initio_next_state(host); return; } - if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) { - int_tul_busfree(pCurHcb); + if (host->jsint & TSS_SEL_TIMEOUT) { + int_initio_busfree(host); return; } - if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ - int_tul_busfree(pCurHcb); /* unexpected bus free or sel timeout */ + if (host->jsint & TSS_DISC_INT) { /* BUS disconnection */ + int_initio_busfree(host); /* unexpected bus free or sel timeout */ return; } - if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) { /* func complete or Bus service */ - if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) - tul_next_state(pCurHcb); + if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) { /* func complete or Bus service */ + if ((scb = host->active) != NULL) + initio_next_state(host); return; } } - if (pCurHcb->HCS_ActScb != NULL) + if (host->active != NULL) return; - if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL) + if ((scb = initio_find_first_pend_scb(host)) == NULL) return; /* program HBA's SCSI ID & target SCSI ID */ - TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, - (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F)); - if (pCurScb->SCB_Opcode == ExecSCSI) { - pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; + outb((host->scsi_id << 4) | (scb->target & 0x0F), + host->addr + TUL_SScsiId); + if (scb->opcode == ExecSCSI) { + active_tc = &host->targets[scb->target]; - if (pCurScb->SCB_TagMsg) - pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG; + if (scb->tagmsg) + active_tc->drv_flags |= TCF_DRV_EN_TAG; else - pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG; + active_tc->drv_flags &= ~TCF_DRV_EN_TAG; - TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period); - if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { /* do wdtr negotiation */ - tul_select_atn_stop(pCurHcb, pCurScb); + outb(active_tc->js_period, host->addr + TUL_SPeriod); + if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { /* do wdtr negotiation */ + initio_select_atn_stop(host, scb); } else { - if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync negotiation */ - tul_select_atn_stop(pCurHcb, pCurScb); + if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync negotiation */ + initio_select_atn_stop(host, scb); } else { - if (pCurScb->SCB_TagMsg) - tul_select_atn3(pCurHcb, pCurScb); + if (scb->tagmsg) + initio_select_atn3(host, scb); else - tul_select_atn(pCurHcb, pCurScb); + initio_select_atn(host, scb); } } - if (pCurScb->SCB_Flags & SCF_POLL) { - while (wait_tulip(pCurHcb) != -1) { - if (tul_next_state(pCurHcb) == -1) + if (scb->flags & SCF_POLL) { + while (wait_tulip(host) != -1) { + if (initio_next_state(host) == -1) break; } } - } else if (pCurScb->SCB_Opcode == BusDevRst) { - tul_select_atn_stop(pCurHcb, pCurScb); - pCurScb->SCB_NxtStat = 8; - if (pCurScb->SCB_Flags & SCF_POLL) { - while (wait_tulip(pCurHcb) != -1) { - if (tul_next_state(pCurHcb) == -1) + } else if (scb->opcode == BusDevRst) { + initio_select_atn_stop(host, scb); + scb->next_state = 8; + if (scb->flags & SCF_POLL) { + while (wait_tulip(host) != -1) { + if (initio_next_state(host) == -1) break; } } - } else if (pCurScb->SCB_Opcode == AbortCmd) { - if (tul_abort_srb(pCurHcb, pCurScb->SCB_Srb) != 0) { - - - tul_unlink_pend_scb(pCurHcb, pCurScb); - - tul_release_scb(pCurHcb, pCurScb); + } else if (scb->opcode == AbortCmd) { + if (initio_abort_srb(host, scb->srb) != 0) { + initio_unlink_pend_scb(host, scb); + initio_release_scb(host, scb); } else { - pCurScb->SCB_Opcode = BusDevRst; - tul_select_atn_stop(pCurHcb, pCurScb); - pCurScb->SCB_NxtStat = 8; + scb->opcode = BusDevRst; + initio_select_atn_stop(host, scb); + scb->next_state = 8; } - -/* 08/03/98 */ } else { - tul_unlink_pend_scb(pCurHcb, pCurScb); - pCurScb->SCB_HaStat = 0x16; /* bad command */ - tul_append_done_scb(pCurHcb, pCurScb); + initio_unlink_pend_scb(host, scb); + scb->hastat = 0x16; /* bad command */ + initio_append_done_scb(host, scb); } return; } +/** + * initio_next_state - Next SCSI state + * @host: InitIO host we are processing + * + * Progress the active command block along the state machine + * until we hit a state which we must wait for activity to occur. + * + * Returns zero or a negative code. + */ -/***************************************************************************/ -int tul_next_state(HCS * pCurHcb) +static int initio_next_state(struct initio_host * host) { int next; - next = pCurHcb->HCS_ActScb->SCB_NxtStat; + next = host->active->next_state; for (;;) { switch (next) { case 1: - next = tul_state_1(pCurHcb); + next = initio_state_1(host); break; case 2: - next = tul_state_2(pCurHcb); + next = initio_state_2(host); break; case 3: - next = tul_state_3(pCurHcb); + next = initio_state_3(host); break; case 4: - next = tul_state_4(pCurHcb); + next = initio_state_4(host); break; case 5: - next = tul_state_5(pCurHcb); + next = initio_state_5(host); break; case 6: - next = tul_state_6(pCurHcb); + next = initio_state_6(host); break; case 7: - next = tul_state_7(pCurHcb); + next = initio_state_7(host); break; case 8: - return (tul_bus_device_reset(pCurHcb)); + return initio_bus_device_reset(host); default: - return (tul_bad_seq(pCurHcb)); + return initio_bad_seq(host); } if (next <= 0) return next; @@ -1554,338 +1314,363 @@ int tul_next_state(HCS * pCurHcb) } -/***************************************************************************/ -/* sTate after selection with attention & stop */ -int tul_state_1(HCS * pCurHcb) +/** + * initio_state_1 - SCSI state machine + * @host: InitIO host we are controlling + * + * Perform SCSI state processing for Select/Attention/Stop + */ + +static int initio_state_1(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; + struct scsi_ctrl_blk *scb = host->active; + struct target_control *active_tc = host->active_tc; #if DEBUG_STATE printk("-s1-"); #endif - tul_unlink_pend_scb(pCurHcb, pCurScb); - tul_append_busy_scb(pCurHcb, pCurScb); + /* Move the SCB from pending to busy */ + initio_unlink_pend_scb(host, scb); + initio_append_busy_scb(host, scb); - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); + outb(active_tc->sconfig0, host->addr + TUL_SConfig ); /* ATN on */ - if (pCurHcb->HCS_Phase == MSG_OUT) { - - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT)); - - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident); - - if (pCurScb->SCB_TagMsg) { - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId); - } - if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { - - pCurTcb->TCS_Flags |= TCF_WDTR_DONE; - - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2); /* Extended msg length */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* Sync request */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* Start from 16 bits */ - } else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { - - pCurTcb->TCS_Flags |= TCF_SYNC_DONE; - - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* extended msg length */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* sync request */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */ - } - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); - } - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); - return (3); -} - + if (host->phase == MSG_OUT) { + outb(TSC_EN_BUS_IN | TSC_HW_RESELECT, host->addr + TUL_SCtrl1); + outb(scb->ident, host->addr + TUL_SFifo); + + if (scb->tagmsg) { + outb(scb->tagmsg, host->addr + TUL_SFifo); + outb(scb->tagid, host->addr + TUL_SFifo); + } + if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { + active_tc->flags |= TCF_WDTR_DONE; + outb(MSG_EXTEND, host->addr + TUL_SFifo); + outb(2, host->addr + TUL_SFifo); /* Extended msg length */ + outb(3, host->addr + TUL_SFifo); /* Sync request */ + outb(1, host->addr + TUL_SFifo); /* Start from 16 bits */ + } else if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { + active_tc->flags |= TCF_SYNC_DONE; + outb(MSG_EXTEND, host->addr + TUL_SFifo); + outb(3, host->addr + TUL_SFifo); /* extended msg length */ + outb(1, host->addr + TUL_SFifo); /* sync request */ + outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo); + outb(MAX_OFFSET, host->addr + TUL_SFifo); /* REQ/ACK offset */ + } + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; + } + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); + outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal); + /* Into before CDB xfer */ + return 3; +} + + +/** + * initio_state_2 - SCSI state machine + * @host: InitIO host we are controlling + * + * state after selection with attention + * state after selection with attention3 + */ -/***************************************************************************/ -/* state after selection with attention */ -/* state after selection with attention3 */ -int tul_state_2(HCS * pCurHcb) +static int initio_state_2(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; + struct scsi_ctrl_blk *scb = host->active; + struct target_control *active_tc = host->active_tc; #if DEBUG_STATE printk("-s2-"); #endif - tul_unlink_pend_scb(pCurHcb, pCurScb); - tul_append_busy_scb(pCurHcb, pCurScb); + initio_unlink_pend_scb(host, scb); + initio_append_busy_scb(host, scb); - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); + outb(active_tc->sconfig0, host->addr + TUL_SConfig); - if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) { - return (4); - } - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); - return (3); + if (host->jsstatus1 & TSS_CMD_PH_CMP) + return 4; + + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); + outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal); + /* Into before CDB xfer */ + return 3; } -/***************************************************************************/ -/* state before CDB xfer is done */ -int tul_state_3(HCS * pCurHcb) +/** + * initio_state_3 - SCSI state machine + * @host: InitIO host we are controlling + * + * state before CDB xfer is done + */ + +static int initio_state_3(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; + struct scsi_ctrl_blk *scb = host->active; + struct target_control *active_tc = host->active_tc; int i; #if DEBUG_STATE printk("-s3-"); #endif for (;;) { - switch (pCurHcb->HCS_Phase) { + switch (host->phase) { case CMD_OUT: /* Command out phase */ - for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++) - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); - if (pCurHcb->HCS_Phase == CMD_OUT) { - return (tul_bad_seq(pCurHcb)); - } - return (4); + for (i = 0; i < (int) scb->cdblen; i++) + outb(scb->cdb[i], host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; + if (host->phase == CMD_OUT) + return initio_bad_seq(host); + return 4; case MSG_IN: /* Message in phase */ - pCurScb->SCB_NxtStat = 3; - if (tul_msgin(pCurHcb) == -1) - return (-1); + scb->next_state = 3; + if (initio_msgin(host) == -1) + return -1; break; case STATUS_IN: /* Status phase */ - if (tul_status_msg(pCurHcb) == -1) - return (-1); + if (initio_status_msg(host) == -1) + return -1; break; case MSG_OUT: /* Message out phase */ - if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) { - - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); - + if (active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) { + outb(MSG_NOP, host->addr + TUL_SFifo); /* msg nop */ + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; } else { - pCurTcb->TCS_Flags |= TCF_SYNC_DONE; - - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* ext. msg len */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* sync request */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)); + active_tc->flags |= TCF_SYNC_DONE; + + outb(MSG_EXTEND, host->addr + TUL_SFifo); + outb(3, host->addr + TUL_SFifo); /* ext. msg len */ + outb(1, host->addr + TUL_SFifo); /* sync request */ + outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo); + outb(MAX_OFFSET, host->addr + TUL_SFifo); /* REQ/ACK offset */ + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); + outb(inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7), host->addr + TUL_SSignal); } break; - default: - return (tul_bad_seq(pCurHcb)); + return initio_bad_seq(host); } } } +/** + * initio_state_4 - SCSI state machine + * @host: InitIO host we are controlling + * + * SCSI state machine. State 4 + */ -/***************************************************************************/ -int tul_state_4(HCS * pCurHcb) +static int initio_state_4(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + struct scsi_ctrl_blk *scb = host->active; #if DEBUG_STATE printk("-s4-"); #endif - if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) { - return (6); /* Go to state 6 */ + if ((scb->flags & SCF_DIR) == SCF_NO_XF) { + return 6; /* Go to state 6 (After data) */ } for (;;) { - if (pCurScb->SCB_BufLen == 0) - return (6); /* Go to state 6 */ + if (scb->buflen == 0) + return 6; - switch (pCurHcb->HCS_Phase) { + switch (host->phase) { case STATUS_IN: /* Status phase */ - if ((pCurScb->SCB_Flags & SCF_DIR) != 0) { /* if direction bit set then report data underrun */ - pCurScb->SCB_HaStat = HOST_DO_DU; - } - if ((tul_status_msg(pCurHcb)) == -1) - return (-1); + if ((scb->flags & SCF_DIR) != 0) /* if direction bit set then report data underrun */ + scb->hastat = HOST_DO_DU; + if ((initio_status_msg(host)) == -1) + return -1; break; case MSG_IN: /* Message in phase */ - pCurScb->SCB_NxtStat = 0x4; - if (tul_msgin(pCurHcb) == -1) - return (-1); + scb->next_state = 0x4; + if (initio_msgin(host) == -1) + return -1; break; case MSG_OUT: /* Message out phase */ - if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { - pCurScb->SCB_BufLen = 0; - pCurScb->SCB_HaStat = HOST_DO_DU; - if (tul_msgout_ide(pCurHcb) == -1) - return (-1); - return (6); /* Go to state 6 */ + if (host->jsstatus0 & TSS_PAR_ERROR) { + scb->buflen = 0; + scb->hastat = HOST_DO_DU; + if (initio_msgout_ide(host) == -1) + return -1; + return 6; } else { - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); + outb(MSG_NOP, host->addr + TUL_SFifo); /* msg nop */ + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; } break; case DATA_IN: /* Data in phase */ - return (tul_xfer_data_in(pCurHcb)); + return initio_xfer_data_in(host); case DATA_OUT: /* Data out phase */ - return (tul_xfer_data_out(pCurHcb)); + return initio_xfer_data_out(host); default: - return (tul_bad_seq(pCurHcb)); + return initio_bad_seq(host); } } } -/***************************************************************************/ -/* state after dma xfer done or phase change before xfer done */ -int tul_state_5(HCS * pCurHcb) +/** + * initio_state_5 - SCSI state machine + * @host: InitIO host we are controlling + * + * State after dma xfer done or phase change before xfer done + */ + +static int initio_state_5(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + struct scsi_ctrl_blk *scb = host->active; long cnt, xcnt; /* cannot use unsigned !! code: if (xcnt < 0) */ #if DEBUG_STATE printk("-s5-"); #endif -/*------ get remaining count -------*/ - - cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF; + /*------ get remaining count -------*/ + cnt = inl(host->addr + TUL_SCnt0) & 0x0FFFFFF; - if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) { + if (inb(host->addr + TUL_XCmd) & 0x20) { /* ----------------------- DATA_IN ----------------------------- */ /* check scsi parity error */ - if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { - pCurScb->SCB_HaStat = HOST_DO_DU; - } - if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* DMA xfer pending, Send STOP */ + if (host->jsstatus0 & TSS_PAR_ERROR) + scb->hastat = HOST_DO_DU; + if (inb(host->addr + TUL_XStatus) & XPEND) { /* DMA xfer pending, Send STOP */ /* tell Hardware scsi xfer has been terminated */ - TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80); + outb(inb(host->addr + TUL_XCtrl) | 0x80, host->addr + TUL_XCtrl); /* wait until DMA xfer not pending */ - while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND); + while (inb(host->addr + TUL_XStatus) & XPEND) + cpu_relax(); } } else { -/*-------- DATA OUT -----------*/ - if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) { - if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI) - cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1; + /*-------- DATA OUT -----------*/ + if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) { + if (host->active_tc->js_period & TSC_WIDE_SCSI) + cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F) << 1; else - cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F); + cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F); } - if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT); + if (inb(host->addr + TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ + outb(TAX_X_ABT, host->addr + TUL_XCmd); /* wait Abort DMA xfer done */ - while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0); + while ((inb(host->addr + TUL_Int) & XABT) == 0) + cpu_relax(); } - if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) { - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) { - return (-1); - } + if ((cnt == 1) && (host->phase == DATA_OUT)) { + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; cnt = 0; } else { - if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); } } - if (cnt == 0) { - pCurScb->SCB_BufLen = 0; - return (6); /* Go to state 6 */ + scb->buflen = 0; + return 6; /* After Data */ } /* Update active data pointer */ - xcnt = (long) pCurScb->SCB_BufLen - cnt; /* xcnt== bytes already xferred */ - pCurScb->SCB_BufLen = (U32) cnt; /* cnt == bytes left to be xferred */ - if (pCurScb->SCB_Flags & SCF_SG) { - register SG *sgp; - ULONG i; - - sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx]; - for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) { - xcnt -= (long) sgp->SG_Len; + xcnt = (long) scb->buflen - cnt; /* xcnt== bytes already xferred */ + scb->buflen = (u32) cnt; /* cnt == bytes left to be xferred */ + if (scb->flags & SCF_SG) { + struct sg_entry *sgp; + unsigned long i; + + sgp = &scb->sglist[scb->sgidx]; + for (i = scb->sgidx; i < scb->sgmax; sgp++, i++) { + xcnt -= (long) sgp->len; if (xcnt < 0) { /* this sgp xfer half done */ - xcnt += (long) sgp->SG_Len; /* xcnt == bytes xferred in this sgp */ - sgp->SG_Ptr += (U32) xcnt; /* new ptr to be xfer */ - sgp->SG_Len -= (U32) xcnt; /* new len to be xfer */ - pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3); + xcnt += (long) sgp->len; /* xcnt == bytes xferred in this sgp */ + sgp->data += (u32) xcnt; /* new ptr to be xfer */ + sgp->len -= (u32) xcnt; /* new len to be xfer */ + scb->bufptr += ((u32) (i - scb->sgidx) << 3); /* new SG table ptr */ - pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i); + scb->sglen = (u8) (scb->sgmax - i); /* new SG table len */ - pCurScb->SCB_SGIdx = (WORD) i; + scb->sgidx = (u16) i; /* for next disc and come in this loop */ - return (4); /* Go to state 4 */ + return 4; /* Go to state 4 */ } /* else (xcnt >= 0 , i.e. this sgp already xferred */ } /* for */ - return (6); /* Go to state 6 */ + return 6; /* Go to state 6 */ } else { - pCurScb->SCB_BufPtr += (U32) xcnt; + scb->bufptr += (u32) xcnt; } - return (4); /* Go to state 4 */ + return 4; /* Go to state 4 */ } -/***************************************************************************/ -/* state after Data phase */ -int tul_state_6(HCS * pCurHcb) +/** + * initio_state_6 - SCSI state machine + * @host: InitIO host we are controlling + * + * State after Data phase + */ + +static int initio_state_6(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + struct scsi_ctrl_blk *scb = host->active; #if DEBUG_STATE printk("-s6-"); #endif for (;;) { - switch (pCurHcb->HCS_Phase) { + switch (host->phase) { case STATUS_IN: /* Status phase */ - if ((tul_status_msg(pCurHcb)) == -1) - return (-1); + if ((initio_status_msg(host)) == -1) + return -1; break; case MSG_IN: /* Message in phase */ - pCurScb->SCB_NxtStat = 6; - if ((tul_msgin(pCurHcb)) == -1) - return (-1); + scb->next_state = 6; + if ((initio_msgin(host)) == -1) + return -1; break; case MSG_OUT: /* Message out phase */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if (wait_tulip(pCurHcb) == -1) - return (-1); + outb(MSG_NOP, host->addr + TUL_SFifo); /* msg nop */ + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; break; case DATA_IN: /* Data in phase */ - return (tul_xpad_in(pCurHcb)); + return initio_xpad_in(host); case DATA_OUT: /* Data out phase */ - return (tul_xpad_out(pCurHcb)); + return initio_xpad_out(host); default: - return (tul_bad_seq(pCurHcb)); + return initio_bad_seq(host); } } } -/***************************************************************************/ -int tul_state_7(HCS * pCurHcb) +/** + * initio_state_7 - SCSI state machine + * @host: InitIO host we are controlling + * + */ + +int initio_state_7(struct initio_host * host) { int cnt, i; @@ -1893,1139 +1678,1029 @@ int tul_state_7(HCS * pCurHcb) printk("-s7-"); #endif /* flush SCSI FIFO */ - cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F; + cnt = inb(host->addr + TUL_SFifoCnt) & 0x1F; if (cnt) { for (i = 0; i < cnt; i++) - TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + inb(host->addr + TUL_SFifo); } - switch (pCurHcb->HCS_Phase) { + switch (host->phase) { case DATA_IN: /* Data in phase */ case DATA_OUT: /* Data out phase */ - return (tul_bad_seq(pCurHcb)); + return initio_bad_seq(host); default: - return (6); /* Go to state 6 */ + return 6; /* Go to state 6 */ } } -/***************************************************************************/ -int tul_xfer_data_in(HCS * pCurHcb) +/** + * initio_xfer_data_in - Commence data input + * @host: InitIO host in use + * + * Commence a block of data transfer. The transfer itself will + * be managed by the controller and we will get a completion (or + * failure) interrupt. + */ +static int initio_xfer_data_in(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + struct scsi_ctrl_blk *scb = host->active; - if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) { - return (6); /* wrong direction */ - } - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen); + if ((scb->flags & SCF_DIR) == SCF_DOUT) + return 6; /* wrong direction */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN); /* 7/25/95 */ + outl(scb->buflen, host->addr + TUL_SCnt0); + outb(TSC_XF_DMA_IN, host->addr + TUL_SCmd); /* 7/25/95 */ - if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */ - TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3); - TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN); + if (scb->flags & SCF_SG) { /* S/G xfer */ + outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH); + outl(scb->bufptr, host->addr + TUL_XAddH); + outb(TAX_SG_IN, host->addr + TUL_XCmd); } else { - TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen); - TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN); + outl(scb->buflen, host->addr + TUL_XCntH); + outl(scb->bufptr, host->addr + TUL_XAddH); + outb(TAX_X_IN, host->addr + TUL_XCmd); } - pCurScb->SCB_NxtStat = 0x5; - return (0); /* return to OS, wait xfer done , let jas_isr come in */ + scb->next_state = 0x5; + return 0; /* return to OS, wait xfer done , let jas_isr come in */ } +/** + * initio_xfer_data_out - Commence data output + * @host: InitIO host in use + * + * Commence a block of data transfer. The transfer itself will + * be managed by the controller and we will get a completion (or + * failure) interrupt. + */ -/***************************************************************************/ -int tul_xfer_data_out(HCS * pCurHcb) +static int initio_xfer_data_out(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + struct scsi_ctrl_blk *scb = host->active; - if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) { - return (6); /* wrong direction */ - } - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT); + if ((scb->flags & SCF_DIR) == SCF_DIN) + return 6; /* wrong direction */ - if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */ - TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3); - TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT); + outl(scb->buflen, host->addr + TUL_SCnt0); + outb(TSC_XF_DMA_OUT, host->addr + TUL_SCmd); + + if (scb->flags & SCF_SG) { /* S/G xfer */ + outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH); + outl(scb->bufptr, host->addr + TUL_XAddH); + outb(TAX_SG_OUT, host->addr + TUL_XCmd); } else { - TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen); - TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT); + outl(scb->buflen, host->addr + TUL_XCntH); + outl(scb->bufptr, host->addr + TUL_XAddH); + outb(TAX_X_OUT, host->addr + TUL_XCmd); } - pCurScb->SCB_NxtStat = 0x5; - return (0); /* return to OS, wait xfer done , let jas_isr come in */ + scb->next_state = 0x5; + return 0; /* return to OS, wait xfer done , let jas_isr come in */ } - -/***************************************************************************/ -int tul_xpad_in(HCS * pCurHcb) +int initio_xpad_in(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; + struct scsi_ctrl_blk *scb = host->active; + struct target_control *active_tc = host->active_tc; - if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) { - pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */ - } + if ((scb->flags & SCF_DIR) != SCF_NO_DCHK) + scb->hastat = HOST_DO_DU; /* over run */ for (;;) { - if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI) - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2); + if (active_tc->js_period & TSC_WIDE_SCSI) + outl(2, host->addr + TUL_SCnt0); else - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + outl(1, host->addr + TUL_SCnt0); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if ((wait_tulip(pCurHcb)) == -1) { - return (-1); + outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; + if (host->phase != DATA_IN) { + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); + return 6; } - if (pCurHcb->HCS_Phase != DATA_IN) { - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - return (6); - } - TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + inb(host->addr + TUL_SFifo); } } -int tul_xpad_out(HCS * pCurHcb) +int initio_xpad_out(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; + struct scsi_ctrl_blk *scb = host->active; + struct target_control *active_tc = host->active_tc; - if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) { - pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */ - } + if ((scb->flags & SCF_DIR) != SCF_NO_DCHK) + scb->hastat = HOST_DO_DU; /* over run */ for (;;) { - if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI) - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2); + if (active_tc->js_period & TSC_WIDE_SCSI) + outl(2, host->addr + TUL_SCnt0); else - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); + outl(1, host->addr + TUL_SCnt0); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - if ((wait_tulip(pCurHcb)) == -1) { - return (-1); - } - if (pCurHcb->HCS_Phase != DATA_OUT) { /* Disable wide CPU to allow read 16 bits */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - return (6); + outb(0, host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + if ((wait_tulip(host)) == -1) + return -1; + if (host->phase != DATA_OUT) { /* Disable wide CPU to allow read 16 bits */ + outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); + return 6; } } } - -/***************************************************************************/ -int tul_status_msg(HCS * pCurHcb) +int initio_status_msg(struct initio_host * host) { /* status & MSG_IN */ - SCB *pCurScb = pCurHcb->HCS_ActScb; - BYTE msg; + struct scsi_ctrl_blk *scb = host->active; + u8 msg; + + outb(TSC_CMD_COMP, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP); - if ((wait_tulip(pCurHcb)) == -1) { - return (-1); - } /* get status */ - pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); + scb->tastat = inb(host->addr + TUL_SFifo); - if (pCurHcb->HCS_Phase == MSG_OUT) { - if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY); - } else { - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); - } - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); - } - if (pCurHcb->HCS_Phase == MSG_IN) { - msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); - if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { /* Parity error */ - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); - if (pCurHcb->HCS_Phase != MSG_OUT) - return (tul_bad_seq(pCurHcb)); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + if (host->phase == MSG_OUT) { + if (host->jsstatus0 & TSS_PAR_ERROR) + outb(MSG_PARITY, host->addr + TUL_SFifo); + else + outb(MSG_NOP, host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + return wait_tulip(host); + } + if (host->phase == MSG_IN) { + msg = inb(host->addr + TUL_SFifo); + if (host->jsstatus0 & TSS_PAR_ERROR) { /* Parity error */ + if ((initio_msgin_accept(host)) == -1) + return -1; + if (host->phase != MSG_OUT) + return initio_bad_seq(host); + outb(MSG_PARITY, host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + return wait_tulip(host); } if (msg == 0) { /* Command complete */ - if ((pCurScb->SCB_TaStat & 0x18) == 0x10) { /* No link support */ - return (tul_bad_seq(pCurHcb)); - } - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); - return tul_wait_done_disc(pCurHcb); + if ((scb->tastat & 0x18) == 0x10) /* No link support */ + return initio_bad_seq(host); + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); + outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd); + return initio_wait_done_disc(host); } - if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) { - if ((pCurScb->SCB_TaStat & 0x18) == 0x10) - return (tul_msgin_accept(pCurHcb)); + if (msg == MSG_LINK_COMP || msg == MSG_LINK_FLAG) { + if ((scb->tastat & 0x18) == 0x10) + return initio_msgin_accept(host); } } - return (tul_bad_seq(pCurHcb)); + return initio_bad_seq(host); } -/***************************************************************************/ /* scsi bus free */ -int int_tul_busfree(HCS * pCurHcb) +int int_initio_busfree(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; + struct scsi_ctrl_blk *scb = host->active; - if (pCurScb != NULL) { - if (pCurScb->SCB_Status & SCB_SELECT) { /* selection timeout */ - tul_unlink_pend_scb(pCurHcb, pCurScb); - pCurScb->SCB_HaStat = HOST_SEL_TOUT; - tul_append_done_scb(pCurHcb, pCurScb); + if (scb != NULL) { + if (scb->status & SCB_SELECT) { /* selection timeout */ + initio_unlink_pend_scb(host, scb); + scb->hastat = HOST_SEL_TOUT; + initio_append_done_scb(host, scb); } else { /* Unexpected bus free */ - tul_unlink_busy_scb(pCurHcb, pCurScb); - pCurScb->SCB_HaStat = HOST_BUS_FREE; - tul_append_done_scb(pCurHcb, pCurScb); + initio_unlink_busy_scb(host, scb); + scb->hastat = HOST_BUS_FREE; + initio_append_done_scb(host, scb); } - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; + host->active = NULL; + host->active_tc = NULL; } - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ - return (-1); + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */ + outb(TSC_INITDEFAULT, host->addr + TUL_SConfig); + outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */ + return -1; } -/***************************************************************************/ -/* scsi bus reset */ -static int int_tul_scsi_rst(HCS * pCurHcb) +/** + * int_initio_scsi_rst - SCSI reset occurred + * @host: Host seeing the reset + * + * A SCSI bus reset has occurred. Clean up any pending transfer + * the hardware is doing by DMA and then abort all active and + * disconnected commands. The mid layer should sort the rest out + * for us + */ + +static int int_initio_scsi_rst(struct initio_host * host) { - SCB *pCurScb; + struct scsi_ctrl_blk *scb; int i; /* if DMA xfer is pending, abort DMA xfer */ - if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) { - TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO); + if (inb(host->addr + TUL_XStatus) & 0x01) { + outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd); /* wait Abort DMA xfer done */ - while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + while ((inb(host->addr + TUL_Int) & 0x04) == 0) + cpu_relax(); + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); } /* Abort all active & disconnected scb */ - while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) { - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - tul_append_done_scb(pCurHcb, pCurScb); + while ((scb = initio_pop_busy_scb(host)) != NULL) { + scb->hastat = HOST_BAD_PHAS; + initio_append_done_scb(host, scb); } - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; + host->active = NULL; + host->active_tc = NULL; /* clr sync nego. done flag */ - for (i = 0; i < pCurHcb->HCS_MaxTar; i++) { - pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); - } - return (-1); + for (i = 0; i < host->max_tar; i++) + host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); + return -1; } +/** + * int_initio_scsi_resel - Reselection occured + * @host: InitIO host adapter + * + * A SCSI reselection event has been signalled and the interrupt + * is now being processed. Work out which command block needs attention + * and continue processing that command. + */ -/***************************************************************************/ -/* scsi reselection */ -int int_tul_resel(HCS * pCurHcb) +int int_initio_resel(struct initio_host * host) { - SCB *pCurScb; - TCS *pCurTcb; - BYTE tag, msg = 0; - BYTE tar, lun; + struct scsi_ctrl_blk *scb; + struct target_control *active_tc; + u8 tag, msg = 0; + u8 tar, lun; - if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) { - if (pCurScb->SCB_Status & SCB_SELECT) { /* if waiting for selection complete */ - pCurScb->SCB_Status &= ~SCB_SELECT; - } - pCurHcb->HCS_ActScb = NULL; + if ((scb = host->active) != NULL) { + /* FIXME: Why check and not just clear ? */ + if (scb->status & SCB_SELECT) /* if waiting for selection complete */ + scb->status &= ~SCB_SELECT; + host->active = NULL; } /* --------- get target id---------------------- */ - tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId); + tar = inb(host->addr + TUL_SBusId); /* ------ get LUN from Identify message----------- */ - lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F; + lun = inb(host->addr + TUL_SIdent) & 0x0F; /* 07/22/98 from 0x1F -> 0x0F */ - pCurTcb = &pCurHcb->HCS_Tcs[tar]; - pCurHcb->HCS_ActTcs = pCurTcb; - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); - TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period); - + active_tc = &host->targets[tar]; + host->active_tc = active_tc; + outb(active_tc->sconfig0, host->addr + TUL_SConfig); + outb(active_tc->js_period, host->addr + TUL_SPeriod); /* ------------- tag queueing ? ------------------- */ - if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) { - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); - if (pCurHcb->HCS_Phase != MSG_IN) + if (active_tc->drv_flags & TCF_DRV_EN_TAG) { + if ((initio_msgin_accept(host)) == -1) + return -1; + if (host->phase != MSG_IN) goto no_tag; - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if ((wait_tulip(pCurHcb)) == -1) - return (-1); - msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* Read Tag Message */ + outl(1, host->addr + TUL_SCnt0); + outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; + msg = inb(host->addr + TUL_SFifo); /* Read Tag Message */ - if ((msg < MSG_STAG) || (msg > MSG_OTAG)) /* Is simple Tag */ + if (msg < MSG_STAG || msg > MSG_OTAG) /* Is simple Tag */ goto no_tag; - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); + if (initio_msgin_accept(host) == -1) + return -1; - if (pCurHcb->HCS_Phase != MSG_IN) + if (host->phase != MSG_IN) goto no_tag; - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if ((wait_tulip(pCurHcb)) == -1) - return (-1); - tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* Read Tag ID */ - pCurScb = pCurHcb->HCS_Scb + tag; - if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) { - return tul_msgout_abort_tag(pCurHcb); - } - if (pCurScb->SCB_Status != SCB_BUSY) { /* 03/24/95 */ - return tul_msgout_abort_tag(pCurHcb); - } - pCurHcb->HCS_ActScb = pCurScb; - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); + outl(1, host->addr + TUL_SCnt0); + outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; + tag = inb(host->addr + TUL_SFifo); /* Read Tag ID */ + scb = host->scb + tag; + if (scb->target != tar || scb->lun != lun) { + return initio_msgout_abort_tag(host); + } + if (scb->status != SCB_BUSY) { /* 03/24/95 */ + return initio_msgout_abort_tag(host); + } + host->active = scb; + if ((initio_msgin_accept(host)) == -1) + return -1; } else { /* No tag */ no_tag: - if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) { - return tul_msgout_abort_targ(pCurHcb); + if ((scb = initio_find_busy_scb(host, tar | (lun << 8))) == NULL) { + return initio_msgout_abort_targ(host); } - pCurHcb->HCS_ActScb = pCurScb; - if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) { - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); + host->active = scb; + if (!(active_tc->drv_flags & TCF_DRV_EN_TAG)) { + if ((initio_msgin_accept(host)) == -1) + return -1; } } return 0; } +/** + * int_initio_bad_seq - out of phase + * @host: InitIO host flagging event + * + * We have ended up out of phase somehow. Reset the host controller + * and throw all our toys out of the pram. Let the midlayer clean up + */ -/***************************************************************************/ -static int int_tul_bad_seq(HCS * pCurHcb) +static int int_initio_bad_seq(struct initio_host * host) { /* target wrong phase */ - SCB *pCurScb; + struct scsi_ctrl_blk *scb; int i; - tul_reset_scsi(pCurHcb, 10); + initio_reset_scsi(host, 10); - while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) { - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - tul_append_done_scb(pCurHcb, pCurScb); - } - for (i = 0; i < pCurHcb->HCS_MaxTar; i++) { - pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); + while ((scb = initio_pop_busy_scb(host)) != NULL) { + scb->hastat = HOST_BAD_PHAS; + initio_append_done_scb(host, scb); } - return (-1); + for (i = 0; i < host->max_tar; i++) + host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); + return -1; } -/***************************************************************************/ -int tul_msgout_abort_targ(HCS * pCurHcb) +/** + * initio_msgout_abort_targ - abort a tag + * @host: InitIO host + * + * Abort when the target/lun does not match or when our SCB is not + * busy. Used by untagged commands. + */ + +static int initio_msgout_abort_targ(struct initio_host * host) { - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - if (tul_msgin_accept(pCurHcb) == -1) - return (-1); - if (pCurHcb->HCS_Phase != MSG_OUT) - return (tul_bad_seq(pCurHcb)); + outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal); + if (initio_msgin_accept(host) == -1) + return -1; + if (host->phase != MSG_OUT) + return initio_bad_seq(host); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + outb(MSG_ABORT, host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); - return tul_wait_disc(pCurHcb); + return initio_wait_disc(host); } -/***************************************************************************/ -int tul_msgout_abort_tag(HCS * pCurHcb) +/** + * initio_msgout_abort_tag - abort a tag + * @host: InitIO host + * + * Abort when the target/lun does not match or when our SCB is not + * busy. Used for tagged commands. + */ + +static int initio_msgout_abort_tag(struct initio_host * host) { - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - if (tul_msgin_accept(pCurHcb) == -1) - return (-1); - if (pCurHcb->HCS_Phase != MSG_OUT) - return (tul_bad_seq(pCurHcb)); + outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal); + if (initio_msgin_accept(host) == -1) + return -1; + if (host->phase != MSG_OUT) + return initio_bad_seq(host); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); + outb(MSG_ABORT_TAG, host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); - return tul_wait_disc(pCurHcb); + return initio_wait_disc(host); } -/***************************************************************************/ -int tul_msgin(HCS * pCurHcb) +/** + * initio_msgin - Message in + * @host: InitIO Host + * + * Process incoming message + */ +static int initio_msgin(struct initio_host * host) { - TCS *pCurTcb; + struct target_control *active_tc; for (;;) { + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if ((wait_tulip(pCurHcb)) == -1) - return (-1); + outl(1, host->addr + TUL_SCnt0); + outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; - switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) { + switch (inb(host->addr + TUL_SFifo)) { case MSG_DISC: /* Disconnect msg */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); - - return tul_wait_disc(pCurHcb); - + outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd); + return initio_wait_disc(host); case MSG_SDP: case MSG_RESTORE: case MSG_NOP: - tul_msgin_accept(pCurHcb); + initio_msgin_accept(host); break; - case MSG_REJ: /* Clear ATN first */ - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, - (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); - pCurTcb = pCurHcb->HCS_ActTcs; - if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync nego */ - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - } - tul_msgin_accept(pCurHcb); + outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), + host->addr + TUL_SSignal); + active_tc = host->active_tc; + if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) /* do sync nego */ + outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), + host->addr + TUL_SSignal); + initio_msgin_accept(host); break; - case MSG_EXTEND: /* extended msg */ - tul_msgin_extend(pCurHcb); + initio_msgin_extend(host); break; - case MSG_IGNOREWIDE: - tul_msgin_accept(pCurHcb); + initio_msgin_accept(host); break; - - /* get */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if (wait_tulip(pCurHcb) == -1) - return -1; - - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0); /* put pad */ - TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* get IGNORE field */ - TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* get pad */ - - tul_msgin_accept(pCurHcb); - break; - case MSG_COMP: - { - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); - return tul_wait_done_disc(pCurHcb); - } + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); + outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd); + return initio_wait_done_disc(host); default: - tul_msgout_reject(pCurHcb); + initio_msgout_reject(host); break; } - if (pCurHcb->HCS_Phase != MSG_IN) - return (pCurHcb->HCS_Phase); + if (host->phase != MSG_IN) + return host->phase; } /* statement won't reach here */ } - - - -/***************************************************************************/ -int tul_msgout_reject(HCS * pCurHcb) +static int initio_msgout_reject(struct initio_host * host) { + outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal); - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - - if ((tul_msgin_accept(pCurHcb)) == -1) - return (-1); + if (initio_msgin_accept(host) == -1) + return -1; - if (pCurHcb->HCS_Phase == MSG_OUT) { - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ); /* Msg reject */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + if (host->phase == MSG_OUT) { + outb(MSG_REJ, host->addr + TUL_SFifo); /* Msg reject */ + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + return wait_tulip(host); } - return (pCurHcb->HCS_Phase); + return host->phase; } - - -/***************************************************************************/ -int tul_msgout_ide(HCS * pCurHcb) +static int initio_msgout_ide(struct initio_host * host) { - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE); /* Initiator Detected Error */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + outb(MSG_IDE, host->addr + TUL_SFifo); /* Initiator Detected Error */ + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + return wait_tulip(host); } - -/***************************************************************************/ -int tul_msgin_extend(HCS * pCurHcb) +static int initio_msgin_extend(struct initio_host * host) { - BYTE len, idx; + u8 len, idx; - if (tul_msgin_accept(pCurHcb) != MSG_IN) - return (pCurHcb->HCS_Phase); + if (initio_msgin_accept(host) != MSG_IN) + return host->phase; /* Get extended msg length */ - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if (wait_tulip(pCurHcb) == -1) - return (-1); + outl(1, host->addr + TUL_SCnt0); + outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; - len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); - pCurHcb->HCS_Msg[0] = len; + len = inb(host->addr + TUL_SFifo); + host->msg[0] = len; for (idx = 1; len != 0; len--) { - if ((tul_msgin_accept(pCurHcb)) != MSG_IN) - return (pCurHcb->HCS_Phase); - TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); - if (wait_tulip(pCurHcb) == -1) - return (-1); - pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); - } - if (pCurHcb->HCS_Msg[1] == 1) { /* if it's synchronous data transfer request */ - if (pCurHcb->HCS_Msg[0] != 3) /* if length is not right */ - return (tul_msgout_reject(pCurHcb)); - if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) { /* Set OFFSET=0 to do async, nego back */ - pCurHcb->HCS_Msg[3] = 0; + if ((initio_msgin_accept(host)) != MSG_IN) + return host->phase; + outl(1, host->addr + TUL_SCnt0); + outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd); + if (wait_tulip(host) == -1) + return -1; + host->msg[idx++] = inb(host->addr + TUL_SFifo); + } + if (host->msg[1] == 1) { /* if it's synchronous data transfer request */ + u8 r; + if (host->msg[0] != 3) /* if length is not right */ + return initio_msgout_reject(host); + if (host->active_tc->flags & TCF_NO_SYNC_NEGO) { /* Set OFFSET=0 to do async, nego back */ + host->msg[3] = 0; } else { - if ((tul_msgin_sync(pCurHcb) == 0) && - (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) { - tul_sync_done(pCurHcb); - return (tul_msgin_accept(pCurHcb)); + if (initio_msgin_sync(host) == 0 && + (host->active_tc->flags & TCF_SYNC_DONE)) { + initio_sync_done(host); + return initio_msgin_accept(host); } } - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - if ((tul_msgin_accept(pCurHcb)) != MSG_OUT) - return (pCurHcb->HCS_Phase); + r = inb(host->addr + TUL_SSignal); + outb((r & (TSC_SET_ACK | 7)) | TSC_SET_ATN, + host->addr + TUL_SSignal); + if (initio_msgin_accept(host) != MSG_OUT) + return host->phase; /* sync msg out */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); - tul_sync_done(pCurHcb); + initio_sync_done(host); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]); - - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + outb(MSG_EXTEND, host->addr + TUL_SFifo); + outb(3, host->addr + TUL_SFifo); + outb(1, host->addr + TUL_SFifo); + outb(host->msg[2], host->addr + TUL_SFifo); + outb(host->msg[3], host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + return wait_tulip(host); } - if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3)) - return (tul_msgout_reject(pCurHcb)); + if (host->msg[0] != 2 || host->msg[1] != 3) + return initio_msgout_reject(host); /* if it's WIDE DATA XFER REQ */ - if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) { - pCurHcb->HCS_Msg[2] = 0; + if (host->active_tc->flags & TCF_NO_WDTR) { + host->msg[2] = 0; } else { - if (pCurHcb->HCS_Msg[2] > 2) /* > 32 bits */ - return (tul_msgout_reject(pCurHcb)); - if (pCurHcb->HCS_Msg[2] == 2) { /* == 32 */ - pCurHcb->HCS_Msg[2] = 1; + if (host->msg[2] > 2) /* > 32 bits */ + return initio_msgout_reject(host); + if (host->msg[2] == 2) { /* == 32 */ + host->msg[2] = 1; } else { - if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) { - wdtr_done(pCurHcb); - if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); - return (tul_msgin_accept(pCurHcb)); + if ((host->active_tc->flags & TCF_NO_WDTR) == 0) { + wdtr_done(host); + if ((host->active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) + outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal); + return initio_msgin_accept(host); } } } - TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN)); + outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal); - if (tul_msgin_accept(pCurHcb) != MSG_OUT) - return (pCurHcb->HCS_Phase); + if (initio_msgin_accept(host) != MSG_OUT) + return host->phase; /* WDTR msg out */ - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - return (wait_tulip(pCurHcb)); + outb(MSG_EXTEND, host->addr + TUL_SFifo); + outb(2, host->addr + TUL_SFifo); + outb(3, host->addr + TUL_SFifo); + outb(host->msg[2], host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + return wait_tulip(host); } -/***************************************************************************/ -int tul_msgin_sync(HCS * pCurHcb) +static int initio_msgin_sync(struct initio_host * host) { char default_period; - default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE]; - if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) { - pCurHcb->HCS_Msg[3] = MAX_OFFSET; - if (pCurHcb->HCS_Msg[2] < default_period) { - pCurHcb->HCS_Msg[2] = default_period; + default_period = initio_rate_tbl[host->active_tc->flags & TCF_SCSI_RATE]; + if (host->msg[3] > MAX_OFFSET) { + host->msg[3] = MAX_OFFSET; + if (host->msg[2] < default_period) { + host->msg[2] = default_period; return 1; } - if (pCurHcb->HCS_Msg[2] >= 59) { /* Change to async */ - pCurHcb->HCS_Msg[3] = 0; - } + if (host->msg[2] >= 59) /* Change to async */ + host->msg[3] = 0; return 1; } /* offset requests asynchronous transfers ? */ - if (pCurHcb->HCS_Msg[3] == 0) { + if (host->msg[3] == 0) { return 0; } - if (pCurHcb->HCS_Msg[2] < default_period) { - pCurHcb->HCS_Msg[2] = default_period; + if (host->msg[2] < default_period) { + host->msg[2] = default_period; return 1; } - if (pCurHcb->HCS_Msg[2] >= 59) { - pCurHcb->HCS_Msg[3] = 0; + if (host->msg[2] >= 59) { + host->msg[3] = 0; return 1; } return 0; } - -/***************************************************************************/ -int wdtr_done(HCS * pCurHcb) +static int wdtr_done(struct initio_host * host) { - pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE; - pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE; + host->active_tc->flags &= ~TCF_SYNC_DONE; + host->active_tc->flags |= TCF_WDTR_DONE; - pCurHcb->HCS_ActTcs->TCS_JS_Period = 0; - if (pCurHcb->HCS_Msg[2]) { /* if 16 bit */ - pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI; - } - pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD; - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0); - TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period); + host->active_tc->js_period = 0; + if (host->msg[2]) /* if 16 bit */ + host->active_tc->js_period |= TSC_WIDE_SCSI; + host->active_tc->sconfig0 &= ~TSC_ALT_PERIOD; + outb(host->active_tc->sconfig0, host->addr + TUL_SConfig); + outb(host->active_tc->js_period, host->addr + TUL_SPeriod); return 1; } -/***************************************************************************/ -int tul_sync_done(HCS * pCurHcb) +static int initio_sync_done(struct initio_host * host) { int i; - pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE; + host->active_tc->flags |= TCF_SYNC_DONE; - if (pCurHcb->HCS_Msg[3]) { - pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3]; + if (host->msg[3]) { + host->active_tc->js_period |= host->msg[3]; for (i = 0; i < 8; i++) { - if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2]) /* pick the big one */ + if (initio_rate_tbl[i] >= host->msg[2]) /* pick the big one */ break; } - pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4); - pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD; + host->active_tc->js_period |= (i << 4); + host->active_tc->sconfig0 |= TSC_ALT_PERIOD; } - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0); - TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period); + outb(host->active_tc->sconfig0, host->addr + TUL_SConfig); + outb(host->active_tc->js_period, host->addr + TUL_SPeriod); - return (-1); + return -1; } -int tul_post_scsi_rst(HCS * pCurHcb) +static int initio_post_scsi_rst(struct initio_host * host) { - SCB *pCurScb; - TCS *pCurTcb; + struct scsi_ctrl_blk *scb; + struct target_control *active_tc; int i; - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; - pCurHcb->HCS_Flags = 0; + host->active = NULL; + host->active_tc = NULL; + host->flags = 0; - while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) { - pCurScb->SCB_HaStat = HOST_BAD_PHAS; - tul_append_done_scb(pCurHcb, pCurScb); + while ((scb = initio_pop_busy_scb(host)) != NULL) { + scb->hastat = HOST_BAD_PHAS; + initio_append_done_scb(host, scb); } /* clear sync done flag */ - pCurTcb = &pCurHcb->HCS_Tcs[0]; - for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) { - pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); + active_tc = &host->targets[0]; + for (i = 0; i < host->max_tar; active_tc++, i++) { + active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); /* Initialize the sync. xfer register values to an asyn xfer */ - pCurTcb->TCS_JS_Period = 0; - pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1; - pCurHcb->HCS_ActTags[0] = 0; /* 07/22/98 */ - pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY; /* 07/22/98 */ + active_tc->js_period = 0; + active_tc->sconfig0 = host->sconf1; + host->act_tags[0] = 0; /* 07/22/98 */ + host->targets[i].flags &= ~TCF_BUSY; /* 07/22/98 */ } /* for */ - return (-1); + return -1; } -/***************************************************************************/ -void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb) +static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb) { - pCurScb->SCB_Status |= SCB_SELECT; - pCurScb->SCB_NxtStat = 0x1; - pCurHcb->HCS_ActScb = pCurScb; - pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP); - return; + scb->status |= SCB_SELECT; + scb->next_state = 0x1; + host->active = scb; + host->active_tc = &host->targets[scb->target]; + outb(TSC_SELATNSTOP, host->addr + TUL_SCmd); } -/***************************************************************************/ -void tul_select_atn(HCS * pCurHcb, SCB * pCurScb) +static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb) { int i; - pCurScb->SCB_Status |= SCB_SELECT; - pCurScb->SCB_NxtStat = 0x2; + scb->status |= SCB_SELECT; + scb->next_state = 0x2; - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident); - for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++) - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); - pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; - pCurHcb->HCS_ActScb = pCurScb; - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN); - return; + outb(scb->ident, host->addr + TUL_SFifo); + for (i = 0; i < (int) scb->cdblen; i++) + outb(scb->cdb[i], host->addr + TUL_SFifo); + host->active_tc = &host->targets[scb->target]; + host->active = scb; + outb(TSC_SEL_ATN, host->addr + TUL_SCmd); } -/***************************************************************************/ -void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb) +static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb) { int i; - pCurScb->SCB_Status |= SCB_SELECT; - pCurScb->SCB_NxtStat = 0x2; - - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg); - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId); - for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++) - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); - pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; - pCurHcb->HCS_ActScb = pCurScb; - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3); - return; + scb->status |= SCB_SELECT; + scb->next_state = 0x2; + + outb(scb->ident, host->addr + TUL_SFifo); + outb(scb->tagmsg, host->addr + TUL_SFifo); + outb(scb->tagid, host->addr + TUL_SFifo); + for (i = 0; i < scb->cdblen; i++) + outb(scb->cdb[i], host->addr + TUL_SFifo); + host->active_tc = &host->targets[scb->target]; + host->active = scb; + outb(TSC_SEL_ATN3, host->addr + TUL_SCmd); } -/***************************************************************************/ -/* SCSI Bus Device Reset */ -int tul_bus_device_reset(HCS * pCurHcb) +/** + * initio_bus_device_reset - SCSI Bus Device Reset + * @host: InitIO host to reset + * + * Perform a device reset and abort all pending SCBs for the + * victim device + */ +int initio_bus_device_reset(struct initio_host * host) { - SCB *pCurScb = pCurHcb->HCS_ActScb; - TCS *pCurTcb = pCurHcb->HCS_ActTcs; - SCB *pTmpScb, *pPrevScb; - BYTE tar; + struct scsi_ctrl_blk *scb = host->active; + struct target_control *active_tc = host->active_tc; + struct scsi_ctrl_blk *tmp, *prev; + u8 tar; - if (pCurHcb->HCS_Phase != MSG_OUT) { - return (int_tul_bad_seq(pCurHcb)); /* Unexpected phase */ - } - tul_unlink_pend_scb(pCurHcb, pCurScb); - tul_release_scb(pCurHcb, pCurScb); + if (host->phase != MSG_OUT) + return int_initio_bad_seq(host); /* Unexpected phase */ + + initio_unlink_pend_scb(host, scb); + initio_release_scb(host, scb); - tar = pCurScb->SCB_Target; /* target */ - pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY); + tar = scb->target; /* target */ + active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY); /* clr sync. nego & WDTR flags 07/22/98 */ /* abort all SCB with same target */ - pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ - while (pTmpScb != NULL) { - - if (pTmpScb->SCB_Target == tar) { + prev = tmp = host->first_busy; /* Check Busy queue */ + while (tmp != NULL) { + if (tmp->target == tar) { /* unlink it */ - if (pTmpScb == pCurHcb->HCS_FirstBusy) { - if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) - pCurHcb->HCS_LastBusy = NULL; + if (tmp == host->first_busy) { + if ((host->first_busy = tmp->next) == NULL) + host->last_busy = NULL; } else { - pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; - if (pTmpScb == pCurHcb->HCS_LastBusy) - pCurHcb->HCS_LastBusy = pPrevScb; + prev->next = tmp->next; + if (tmp == host->last_busy) + host->last_busy = prev; } - pTmpScb->SCB_HaStat = HOST_ABORTED; - tul_append_done_scb(pCurHcb, pTmpScb); + tmp->hastat = HOST_ABORTED; + initio_append_done_scb(host, tmp); } /* Previous haven't change */ else { - pPrevScb = pTmpScb; + prev = tmp; } - pTmpScb = pTmpScb->SCB_NxtScb; + tmp = tmp->next; } - - TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST); - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); - - return tul_wait_disc(pCurHcb); + outb(MSG_DEVRST, host->addr + TUL_SFifo); + outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd); + return initio_wait_disc(host); } -/***************************************************************************/ -int tul_msgin_accept(HCS * pCurHcb) +static int initio_msgin_accept(struct initio_host * host) { - TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); - return (wait_tulip(pCurHcb)); + outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd); + return wait_tulip(host); } -/***************************************************************************/ -int wait_tulip(HCS * pCurHcb) +static int wait_tulip(struct initio_host * host) { - while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) - & TSS_INT_PENDING)); + while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) + & TSS_INT_PENDING)) + cpu_relax(); - pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK; - pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1); + host->jsint = inb(host->addr + TUL_SInt); + host->phase = host->jsstatus0 & TSS_PH_MASK; + host->jsstatus1 = inb(host->addr + TUL_SStatus1); - if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) { /* if SCSI bus reset detected */ - return (int_tul_resel(pCurHcb)); - } - if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) { /* if selected/reselected timeout interrupt */ - return (int_tul_busfree(pCurHcb)); - } - if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */ - return (int_tul_scsi_rst(pCurHcb)); - } - if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ - if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) { - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb); - pCurHcb->HCS_ActScb->SCB_HaStat = 0; - tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb); - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; - pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC; - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ - return (-1); + if (host->jsint & TSS_RESEL_INT) /* if SCSI bus reset detected */ + return int_initio_resel(host); + if (host->jsint & TSS_SEL_TIMEOUT) /* if selected/reselected timeout interrupt */ + return int_initio_busfree(host); + if (host->jsint & TSS_SCSIRST_INT) /* if SCSI bus reset detected */ + return int_initio_scsi_rst(host); + + if (host->jsint & TSS_DISC_INT) { /* BUS disconnection */ + if (host->flags & HCF_EXPECT_DONE_DISC) { + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */ + initio_unlink_busy_scb(host, host->active); + host->active->hastat = 0; + initio_append_done_scb(host, host->active); + host->active = NULL; + host->active_tc = NULL; + host->flags &= ~HCF_EXPECT_DONE_DISC; + outb(TSC_INITDEFAULT, host->addr + TUL_SConfig); + outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */ + return -1; } - if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) { - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - pCurHcb->HCS_ActScb = NULL; - pCurHcb->HCS_ActTcs = NULL; - pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC; - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ - return (-1); + if (host->flags & HCF_EXPECT_DISC) { + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */ + host->active = NULL; + host->active_tc = NULL; + host->flags &= ~HCF_EXPECT_DISC; + outb(TSC_INITDEFAULT, host->addr + TUL_SConfig); + outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */ + return -1; } - return (int_tul_busfree(pCurHcb)); - } - if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) { - return (pCurHcb->HCS_Phase); + return int_initio_busfree(host); } - return (pCurHcb->HCS_Phase); + /* The old code really does the below. Can probably be removed */ + if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) + return host->phase; + return host->phase; } -/***************************************************************************/ -int tul_wait_disc(HCS * pCurHcb) -{ - - while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) - & TSS_INT_PENDING)); +static int initio_wait_disc(struct initio_host * host) +{ + while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING)) + cpu_relax(); - pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); + host->jsint = inb(host->addr + TUL_SInt); - if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */ - return (int_tul_scsi_rst(pCurHcb)); - } - if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ - pCurHcb->HCS_ActScb = NULL; - return (-1); + if (host->jsint & TSS_SCSIRST_INT) /* if SCSI bus reset detected */ + return int_initio_scsi_rst(host); + if (host->jsint & TSS_DISC_INT) { /* BUS disconnection */ + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */ + outb(TSC_INITDEFAULT, host->addr + TUL_SConfig); + outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */ + host->active = NULL; + return -1; } - return (tul_bad_seq(pCurHcb)); + return initio_bad_seq(host); } -/***************************************************************************/ -int tul_wait_done_disc(HCS * pCurHcb) +static int initio_wait_done_disc(struct initio_host * host) { + while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) + & TSS_INT_PENDING)) + cpu_relax(); + host->jsint = inb(host->addr + TUL_SInt); - while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) - & TSS_INT_PENDING)); - - pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); - - - if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */ - return (int_tul_scsi_rst(pCurHcb)); - } - if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ - TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); - TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ - tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb); + if (host->jsint & TSS_SCSIRST_INT) /* if SCSI bus reset detected */ + return int_initio_scsi_rst(host); + if (host->jsint & TSS_DISC_INT) { /* BUS disconnection */ + outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */ + outb(TSC_INITDEFAULT, host->addr + TUL_SConfig); + outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); /* Enable HW reselect */ + initio_unlink_busy_scb(host, host->active); - tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb); - pCurHcb->HCS_ActScb = NULL; - return (-1); + initio_append_done_scb(host, host->active); + host->active = NULL; + return -1; } - return (tul_bad_seq(pCurHcb)); + return initio_bad_seq(host); } +/** + * i91u_intr - IRQ handler + * @irqno: IRQ number + * @dev_id: IRQ identifier + * + * Take the relevant locks and then invoke the actual isr processing + * code under the lock. + */ + static irqreturn_t i91u_intr(int irqno, void *dev_id) { struct Scsi_Host *dev = dev_id; unsigned long flags; + int r; spin_lock_irqsave(dev->host_lock, flags); - tul_isr((HCS *)dev->base); + r = initio_isr((struct initio_host *)dev->hostdata); spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static int tul_NewReturnNumberOfAdapters(void) -{ - struct pci_dev *pDev = NULL; /* Start from none */ - int iAdapters = 0; - long dRegValue; - WORD wBIOS; - int i = 0; - - init_i91uAdapter_table(); - - for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++) - { - while ((pDev = pci_find_device(i91u_pci_devices[i].vendor, i91u_pci_devices[i].device, pDev)) != NULL) { - if (pci_enable_device(pDev)) - continue; - pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); - wBIOS = (UWORD) (dRegValue & 0xFF); - if (((dRegValue & 0xFF00) >> 8) == 0xFF) - dRegValue = 0; - wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); - if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) { - printk(KERN_WARNING - "i91u: Could not set 32 bit DMA mask\n"); - continue; - } - - if (Addi91u_into_Adapter_table(wBIOS, - (pDev->resource[0].start), - pDev->irq, - pDev->bus->number, - (pDev->devfn >> 3) - ) == 0) - iAdapters++; - } - } - - return (iAdapters); + if (r) + return IRQ_HANDLED; + else + return IRQ_NONE; } -static int i91u_detect(struct scsi_host_template * tpnt) -{ - HCS *pHCB; - struct Scsi_Host *hreg; - unsigned long i; /* 01/14/98 */ - int ok = 0, iAdapters; - ULONG dBiosAdr; - BYTE *pbBiosAdr; - - /* Get total number of adapters in the motherboard */ - iAdapters = tul_NewReturnNumberOfAdapters(); - if (iAdapters == 0) /* If no tulip founded, return */ - return (0); - - tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters; - /* Update actually channel number */ - if (tul_tag_enable) { /* 1.01i */ - tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE; - } else { - tul_num_scb = MAX_TARGETS + 3; /* 1-tape, 1-CD_ROM, 1- extra */ - } /* Update actually SCBs per adapter */ - - /* Get total memory needed for HCS */ - i = tul_num_ch * sizeof(HCS); - memset((unsigned char *) &tul_hcs[0], 0, i); /* Initialize tul_hcs 0 */ - /* Get total memory needed for SCB */ - - for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) { - i = tul_num_ch * tul_num_scb * sizeof(SCB); - if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL) - break; - } - if (tul_scb == NULL) { - printk("i91u: SCB memory allocation error\n"); - return (0); - } - memset((unsigned char *) tul_scb, 0, i); - for (i = 0, pHCB = &tul_hcs[0]; /* Get pointer for control block */ - i < tul_num_ch; - i++, pHCB++) { - get_tulipPCIConfig(pHCB, i); - - dBiosAdr = pHCB->HCS_BIOS; - dBiosAdr = (dBiosAdr << 4); - - pbBiosAdr = phys_to_virt(dBiosAdr); - - init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10); - request_region(pHCB->HCS_Base, 256, "i91u"); /* Register */ - - pHCB->HCS_Index = i; /* 7/29/98 */ - hreg = scsi_register(tpnt, sizeof(HCS)); - if(hreg == NULL) { - release_region(pHCB->HCS_Base, 256); - return 0; - } - hreg->io_port = pHCB->HCS_Base; - hreg->n_io_port = 0xff; - hreg->can_queue = tul_num_scb; /* 03/05/98 */ - hreg->unique_id = pHCB->HCS_Base; - hreg->max_id = pHCB->HCS_MaxTar; - hreg->max_lun = 32; /* 10/21/97 */ - hreg->irq = pHCB->HCS_Intr; - hreg->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */ - hreg->base = (unsigned long)pHCB; - hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32 */ - - /* Initial tulip chip */ - ok = request_irq(pHCB->HCS_Intr, i91u_intr, IRQF_DISABLED | IRQF_SHARED, "i91u", hreg); - if (ok < 0) { - printk(KERN_WARNING "i91u: unable to request IRQ %d\n\n", pHCB->HCS_Intr); - return 0; - } - } - - tpnt->this_id = -1; - tpnt->can_queue = 1; - - return 1; -} +/** + * initio_build_scb - Build the mappings and SCB + * @host: InitIO host taking the command + * @cblk: Firmware command block + * @cmnd: SCSI midlayer command block + * + * Translate the abstract SCSI command into a firmware command block + * suitable for feeding to the InitIO host controller. This also requires + * we build the scatter gather lists and ensure they are mapped properly. + */ -static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, struct scsi_cmnd * SCpnt) +static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * cblk, struct scsi_cmnd * cmnd) { /* Create corresponding SCB */ - struct scatterlist *pSrbSG; - SG *pSG; /* Pointer to SG list */ - int i; - long TotalLen; + struct scatterlist *sglist; + struct sg_entry *sg; /* Pointer to SG list */ + int i, nseg; + long total_len; dma_addr_t dma_addr; - pSCB->SCB_Post = i91uSCBPost; /* i91u's callback routine */ - pSCB->SCB_Srb = SCpnt; - pSCB->SCB_Opcode = ExecSCSI; - pSCB->SCB_Flags = SCF_POST; /* After SCSI done, call post routine */ - pSCB->SCB_Target = SCpnt->device->id; - pSCB->SCB_Lun = SCpnt->device->lun; - pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW; - - pSCB->SCB_Flags |= SCF_SENSE; /* Turn on auto request sense */ - dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->sense_buffer, - SENSE_SIZE, DMA_FROM_DEVICE); - pSCB->SCB_SensePtr = cpu_to_le32((u32)dma_addr); - pSCB->SCB_SenseLen = cpu_to_le32(SENSE_SIZE); - SCpnt->SCp.ptr = (char *)(unsigned long)dma_addr; + /* Fill in the command headers */ + cblk->post = i91uSCBPost; /* i91u's callback routine */ + cblk->srb = cmnd; + cblk->opcode = ExecSCSI; + cblk->flags = SCF_POST; /* After SCSI done, call post routine */ + cblk->target = cmnd->device->id; + cblk->lun = cmnd->device->lun; + cblk->ident = cmnd->device->lun | DISC_ALLOW; - pSCB->SCB_CDBLen = SCpnt->cmd_len; - pSCB->SCB_HaStat = 0; - pSCB->SCB_TaStat = 0; - memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len); + cblk->flags |= SCF_SENSE; /* Turn on auto request sense */ - if (SCpnt->device->tagged_supported) { /* Tag Support */ - pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ + /* Map the sense buffer into bus memory */ + dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer, + SENSE_SIZE, DMA_FROM_DEVICE); + cblk->senseptr = cpu_to_le32((u32)dma_addr); + cblk->senselen = cpu_to_le32(SENSE_SIZE); + cmnd->SCp.ptr = (char *)(unsigned long)dma_addr; + cblk->cdblen = cmnd->cmd_len; + + /* Clear the returned status */ + cblk->hastat = 0; + cblk->tastat = 0; + /* Command the command */ + memcpy(&cblk->cdb[0], &cmnd->cmnd, cmnd->cmd_len); + + /* Set up tags */ + if (cmnd->device->tagged_supported) { /* Tag Support */ + cblk->tagmsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ } else { - pSCB->SCB_TagMsg = 0; /* No tag support */ + cblk->tagmsg = 0; /* No tag support */ } + /* todo handle map_sg error */ - if (SCpnt->use_sg) { - dma_addr = dma_map_single(&pHCB->pci_dev->dev, &pSCB->SCB_SGList[0], - sizeof(struct SG_Struc) * TOTAL_SG_ENTRY, + nseg = scsi_dma_map(cmnd); + BUG_ON(nseg < 0); + if (nseg) { + dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0], + sizeof(struct sg_entry) * TOTAL_SG_ENTRY, DMA_BIDIRECTIONAL); - pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr); - SCpnt->SCp.dma_handle = dma_addr; - - pSrbSG = (struct scatterlist *) SCpnt->request_buffer; - pSCB->SCB_SGLen = dma_map_sg(&pHCB->pci_dev->dev, pSrbSG, - SCpnt->use_sg, SCpnt->sc_data_direction); - - pSCB->SCB_Flags |= SCF_SG; /* Turn on SG list flag */ - for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0]; /* 1.01g */ - i < pSCB->SCB_SGLen; i++, pSG++, pSrbSG++) { - pSG->SG_Ptr = cpu_to_le32((u32)sg_dma_address(pSrbSG)); - TotalLen += pSG->SG_Len = cpu_to_le32((u32)sg_dma_len(pSrbSG)); + cblk->bufptr = cpu_to_le32((u32)dma_addr); + cmnd->SCp.dma_handle = dma_addr; + + + cblk->flags |= SCF_SG; /* Turn on SG list flag */ + total_len = 0; + sg = &cblk->sglist[0]; + scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) { + sg->data = cpu_to_le32((u32)sg_dma_address(sglist)); + total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist)); } - pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ? - TotalLen : SCpnt->request_bufflen; - } else if (SCpnt->request_bufflen) { /* Non SG */ - dma_addr = dma_map_single(&pHCB->pci_dev->dev, SCpnt->request_buffer, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - SCpnt->SCp.dma_handle = dma_addr; - pSCB->SCB_BufPtr = cpu_to_le32((u32)dma_addr); - pSCB->SCB_BufLen = cpu_to_le32((u32)SCpnt->request_bufflen); - pSCB->SCB_SGLen = 0; - } else { - pSCB->SCB_BufLen = 0; - pSCB->SCB_SGLen = 0; + cblk->buflen = (scsi_bufflen(cmnd) > total_len) ? + total_len : scsi_bufflen(cmnd); + } else { /* No data transfer required */ + cblk->buflen = 0; + cblk->sglen = 0; } } +/** + * i91u_queuecommand - Queue a new command if possible + * @cmd: SCSI command block from the mid layer + * @done: Completion handler + * + * Attempts to queue a new command with the host adapter. Will return + * zero if successful or indicate a host busy condition if not (which + * will cause the mid layer to call us again later with the command) + */ + static int i91u_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { - HCS *pHCB = (HCS *) cmd->device->host->base; - register SCB *pSCB; + struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata; + struct scsi_ctrl_blk *cmnd; cmd->scsi_done = done; - pSCB = tul_alloc_scb(pHCB); - if (!pSCB) + cmnd = initio_alloc_scb(host); + if (!cmnd) return SCSI_MLQUEUE_HOST_BUSY; - i91uBuildSCB(pHCB, pSCB, cmd); - tul_exec_scb(pHCB, pSCB); + initio_build_scb(host, cmnd, cmd); + initio_exec_scb(host, cmnd); return 0; } -#if 0 /* no new EH yet */ -/* - * Abort a queued command - * (commands that are on the bus can't be aborted easily) - */ -static int i91u_abort(struct scsi_cmnd * SCpnt) -{ - HCS *pHCB; - - pHCB = (HCS *) SCpnt->device->host->base; - return tul_abort_srb(pHCB, SCpnt); -} - -/* - * Reset registers, reset a hanging bus and - * kill active and disconnected commands for target w/o soft reset +/** + * i91u_bus_reset - reset the SCSI bus + * @cmnd: Command block we want to trigger the reset for + * + * Initiate a SCSI bus reset sequence */ -static int i91u_reset(struct scsi_cmnd * SCpnt, unsigned int reset_flags) -{ /* I need Host Control Block Information */ - HCS *pHCB; - - pHCB = (HCS *) SCpnt->device->host->base; - if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) - return tul_reset_scsi_bus(pHCB); - else - return tul_device_reset(pHCB, SCpnt, SCpnt->device->id, reset_flags); -} -#endif - -static int i91u_bus_reset(struct scsi_cmnd * SCpnt) +static int i91u_bus_reset(struct scsi_cmnd * cmnd) { - HCS *pHCB; + struct initio_host *host; - pHCB = (HCS *) SCpnt->device->host->base; + host = (struct initio_host *) cmnd->device->host->hostdata; - spin_lock_irq(SCpnt->device->host->host_lock); - tul_reset_scsi(pHCB, 0); - spin_unlock_irq(SCpnt->device->host->host_lock); + spin_lock_irq(cmnd->device->host->host_lock); + initio_reset_scsi(host, 0); + spin_unlock_irq(cmnd->device->host->host_lock); return SUCCESS; } -/* - * Return the "logical geometry" +/** + * i91u_biospararm - return the "logical geometry + * @sdev: SCSI device + * @dev; Matching block device + * @capacity: Sector size of drive + * @info_array: Return space for BIOS geometry + * + * Map the device geometry in a manner compatible with the host + * controller BIOS behaviour. + * + * FIXME: limited to 2^32 sector devices. */ + static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int *info_array) { - HCS *pHcb; /* Point to Host adapter control block */ - TCS *pTcb; + struct initio_host *host; /* Point to Host adapter control block */ + struct target_control *tc; - pHcb = (HCS *) sdev->host->base; - pTcb = &pHcb->HCS_Tcs[sdev->id]; + host = (struct initio_host *) sdev->host->hostdata; + tc = &host->targets[sdev->id]; - if (pTcb->TCS_DrvHead) { - info_array[0] = pTcb->TCS_DrvHead; - info_array[1] = pTcb->TCS_DrvSector; - info_array[2] = (unsigned long)capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector; + if (tc->heads) { + info_array[0] = tc->heads; + info_array[1] = tc->sectors; + info_array[2] = (unsigned long)capacity / tc->heads / tc->sectors; } else { - if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) { + if (tc->drv_flags & TCF_DRV_255_63) { info_array[0] = 255; info_array[1] = 63; info_array[2] = (unsigned long)capacity / 255 / 63; @@ -3047,7 +2722,16 @@ static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev, return 0; } -static void i91u_unmap_cmnd(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd) +/** + * i91u_unmap_scb - Unmap a command + * @pci_dev: PCI device the command is for + * @cmnd: The command itself + * + * Unmap any PCI mapping/IOMMU resources allocated when the command + * was mapped originally as part of initio_build_scb + */ + +static void i91u_unmap_scb(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd) { /* auto sense buffer */ if (cmnd->SCp.ptr) { @@ -3058,65 +2742,63 @@ static void i91u_unmap_cmnd(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd) } /* request buffer */ - if (cmnd->use_sg) { + if (scsi_sg_count(cmnd)) { dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle, - sizeof(struct SG_Struc) * TOTAL_SG_ENTRY, + sizeof(struct sg_entry) * TOTAL_SG_ENTRY, DMA_BIDIRECTIONAL); - dma_unmap_sg(&pci_dev->dev, cmnd->request_buffer, - cmnd->use_sg, - cmnd->sc_data_direction); - } else if (cmnd->request_bufflen) { - dma_unmap_single(&pci_dev->dev, cmnd->SCp.dma_handle, - cmnd->request_bufflen, - cmnd->sc_data_direction); + scsi_dma_unmap(cmnd); } } -/***************************************************************************** - Function name : i91uSCBPost - Description : This is callback routine be called when tulip finish one - SCSI command. - Input : pHCB - Pointer to host adapter control block. - pSCB - Pointer to SCSI control block. - Output : None. - Return : None. -*****************************************************************************/ -static void i91uSCBPost(BYTE * pHcb, BYTE * pScb) -{ - struct scsi_cmnd *pSRB; /* Pointer to SCSI request block */ - HCS *pHCB; - SCB *pSCB; +/** + * i91uSCBPost - SCSI callback + * @host: Pointer to host adapter control block. + * @cmnd: Pointer to SCSI control block. + * + * This is callback routine be called when tulip finish one + * SCSI command. + */ - pHCB = (HCS *) pHcb; - pSCB = (SCB *) pScb; - if ((pSRB = pSCB->SCB_Srb) == 0) { - printk("i91uSCBPost: SRB pointer is empty\n"); +static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem) +{ + struct scsi_cmnd *cmnd; /* Pointer to SCSI request block */ + struct initio_host *host; + struct scsi_ctrl_blk *cblk; - tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */ + host = (struct initio_host *) host_mem; + cblk = (struct scsi_ctrl_blk *) cblk_mem; + if ((cmnd = cblk->srb) == NULL) { + printk(KERN_ERR "i91uSCBPost: SRB pointer is empty\n"); + WARN_ON(1); + initio_release_scb(host, cblk); /* Release SCB for current channel */ return; } - switch (pSCB->SCB_HaStat) { + + /* + * Remap the firmware error status into a mid layer one + */ + switch (cblk->hastat) { case 0x0: case 0xa: /* Linked command complete without error and linked normally */ case 0xb: /* Linked command complete without error interrupt generated */ - pSCB->SCB_HaStat = 0; + cblk->hastat = 0; break; case 0x11: /* Selection time out-The initiator selection or target reselection was not complete within the SCSI Time out period */ - pSCB->SCB_HaStat = DID_TIME_OUT; + cblk->hastat = DID_TIME_OUT; break; case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus phase sequence was requested by the target. The host adapter will generate a SCSI Reset Condition, notifying the host with a SCRD interrupt */ - pSCB->SCB_HaStat = DID_RESET; + cblk->hastat = DID_RESET; break; case 0x1a: /* SCB Aborted. 07/21/98 */ - pSCB->SCB_HaStat = DID_ABORT; + cblk->hastat = DID_ABORT; break; case 0x12: /* Data overrun/underrun-The target attempted to transfer more data @@ -3126,49 +2808,196 @@ static void i91uSCBPost(BYTE * pHcb, BYTE * pScb) case 0x16: /* Invalid SCB Operation Code. */ default: - printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat); - pSCB->SCB_HaStat = DID_ERROR; /* Couldn't find any better */ + printk("ini9100u: %x %x\n", cblk->hastat, cblk->tastat); + cblk->hastat = DID_ERROR; /* Couldn't find any better */ break; } - pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16); + cmnd->result = cblk->tastat | (cblk->hastat << 16); + WARN_ON(cmnd == NULL); + i91u_unmap_scb(host->pci_dev, cmnd); + cmnd->scsi_done(cmnd); /* Notify system DONE */ + initio_release_scb(host, cblk); /* Release SCB for current channel */ +} + +static struct scsi_host_template initio_template = { + .proc_name = "INI9100U", + .name = "Initio INI-9X00U/UW SCSI device driver", + .queuecommand = i91u_queuecommand, + .eh_bus_reset_handler = i91u_bus_reset, + .bios_param = i91u_biosparam, + .can_queue = MAX_TARGETS * i91u_MAXQUEUE, + .this_id = 1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, +}; + +static int initio_probe_one(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct Scsi_Host *shost; + struct initio_host *host; + u32 reg; + u16 bios_seg; + struct scsi_ctrl_blk *scb, *tmp, *prev = NULL /* silence gcc */; + int num_scb, i, error; + + error = pci_enable_device(pdev); + if (error) + return error; + + pci_read_config_dword(pdev, 0x44, (u32 *) & reg); + bios_seg = (u16) (reg & 0xFF); + if (((reg & 0xFF00) >> 8) == 0xFF) + reg = 0; + bios_seg = (bios_seg << 8) + ((u16) ((reg & 0xFF00) >> 8)); + + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "i91u: Could not set 32 bit DMA mask\n"); + error = -ENODEV; + goto out_disable_device; + } + shost = scsi_host_alloc(&initio_template, sizeof(struct initio_host)); + if (!shost) { + printk(KERN_WARNING "initio: Could not allocate host structure.\n"); + error = -ENOMEM; + goto out_disable_device; + } + host = (struct initio_host *)shost->hostdata; + memset(host, 0, sizeof(struct initio_host)); - if (pSRB == NULL) { - printk("pSRB is NULL\n"); + if (!request_region(host->addr, 256, "i91u")) { + printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr); + error = -ENODEV; + goto out_host_put; } - i91u_unmap_cmnd(pHCB->pci_dev, pSRB); - pSRB->scsi_done(pSRB); /* Notify system DONE */ + if (initio_tag_enable) /* 1.01i */ + num_scb = MAX_TARGETS * i91u_MAXQUEUE; + else + num_scb = MAX_TARGETS + 3; /* 1-tape, 1-CD_ROM, 1- extra */ - tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */ -} + for (; num_scb >= MAX_TARGETS + 3; num_scb--) { + i = num_scb * sizeof(struct scsi_ctrl_blk); + if ((scb = kzalloc(i, GFP_DMA)) != NULL) + break; + } + + if (!scb) { + printk(KERN_WARNING "initio: Cannot allocate SCB array.\n"); + error = -ENOMEM; + goto out_release_region; + } -/* - * Release ressources + host->num_scbs = num_scb; + host->scb = scb; + host->next_pending = scb; + host->next_avail = scb; + for (i = 0, tmp = scb; i < num_scb; i++, tmp++) { + tmp->tagid = i; + if (i != 0) + prev->next = tmp; + prev = tmp; + } + prev->next = NULL; + host->scb_end = tmp; + host->first_avail = scb; + host->last_avail = prev; + + initio_init(host, phys_to_virt(bios_seg << 4)); + + host->jsstatus0 = 0; + + shost->io_port = host->addr; + shost->n_io_port = 0xff; + shost->can_queue = num_scb; /* 03/05/98 */ + shost->unique_id = host->addr; + shost->max_id = host->max_tar; + shost->max_lun = 32; /* 10/21/97 */ + shost->irq = pdev->irq; + shost->this_id = host->scsi_id; /* Assign HCS index */ + shost->base = host->addr; + shost->sg_tablesize = TOTAL_SG_ENTRY; + + error = request_irq(pdev->irq, i91u_intr, IRQF_DISABLED|IRQF_SHARED, "i91u", shost); + if (error < 0) { + printk(KERN_WARNING "initio: Unable to request IRQ %d\n", pdev->irq); + goto out_free_scbs; + } + + pci_set_drvdata(pdev, shost); + host->pci_dev = pdev; + + error = scsi_add_host(shost, &pdev->dev); + if (error) + goto out_free_irq; + scsi_scan_host(shost); + return 0; +out_free_irq: + free_irq(pdev->irq, shost); +out_free_scbs: + kfree(host->scb); +out_release_region: + release_region(host->addr, 256); +out_host_put: + scsi_host_put(shost); +out_disable_device: + pci_disable_device(pdev); + return error; +} + +/** + * initio_remove_one - control shutdown + * @pdev: PCI device being released + * + * Release the resources assigned to this adapter after it has + * finished being used. */ -static int i91u_release(struct Scsi_Host *hreg) + +static void initio_remove_one(struct pci_dev *pdev) { - free_irq(hreg->irq, hreg); - release_region(hreg->io_port, 256); - return 0; + struct Scsi_Host *host = pci_get_drvdata(pdev); + struct initio_host *s = (struct initio_host *)host->hostdata; + scsi_remove_host(host); + free_irq(pdev->irq, host); + release_region(s->addr, 256); + scsi_host_put(host); + pci_disable_device(pdev); } -MODULE_LICENSE("Dual BSD/GPL"); - -static struct scsi_host_template driver_template = { - .proc_name = "INI9100U", - .name = i91u_REVID, - .detect = i91u_detect, - .release = i91u_release, - .queuecommand = i91u_queuecommand, -// .abort = i91u_abort, -// .reset = i91u_reset, - .eh_bus_reset_handler = i91u_bus_reset, - .bios_param = i91u_biosparam, - .can_queue = 1, - .this_id = 1, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = ENABLE_CLUSTERING, + +MODULE_LICENSE("GPL"); + +static struct pci_device_id initio_pci_tbl[] = { + {PCI_VENDOR_ID_INIT, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_INIT, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_INIT, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_INIT, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_DOMEX, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, initio_pci_tbl); + +static struct pci_driver initio_pci_driver = { + .name = "initio", + .id_table = initio_pci_tbl, + .probe = initio_probe_one, + .remove = __devexit_p(initio_remove_one), }; -#include "scsi_module.c" +static int __init initio_init_driver(void) +{ + return pci_register_driver(&initio_pci_driver); +} + +static void __exit initio_exit_driver(void) +{ + pci_unregister_driver(&initio_pci_driver); +} + +MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver"); +MODULE_AUTHOR("Initio Corporation"); +MODULE_LICENSE("GPL"); + +module_init(initio_init_driver); +module_exit(initio_exit_driver); diff --git a/drivers/scsi/initio.h b/drivers/scsi/initio.h index acb67a4af2cc..cb48efa81fe2 100644 --- a/drivers/scsi/initio.h +++ b/drivers/scsi/initio.h @@ -4,6 +4,8 @@ * Copyright (c) 1994-1998 Initio Corporation * All rights reserved. * + * Cleanups (c) Copyright 2007 Red Hat <alan@redhat.com> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -18,27 +20,6 @@ * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * - * -------------------------------------------------------------------------- - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Where this Software is combined with software released under the terms of - * the GNU General Public License ("GPL") and the terms of the GPL would require the - * combined work to also be released under the terms of the GPL, the terms - * and conditions of this License will apply in addition to those of the - * GPL with the exception of any terms or conditions of this License that - * conflict with, or are expressly prohibited by, the GPL. - * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -56,17 +37,6 @@ #include <linux/types.h> -#define ULONG unsigned long -#define USHORT unsigned short -#define UCHAR unsigned char -#define BYTE unsigned char -#define WORD unsigned short -#define DWORD unsigned long -#define UBYTE unsigned char -#define UWORD unsigned short -#define UDWORD unsigned long -#define U32 u32 - #define TOTAL_SG_ENTRY 32 #define MAX_SUPPORTED_ADAPTERS 8 #define MAX_OFFSET 15 @@ -368,55 +338,55 @@ typedef struct { /************************************************************************/ /* Scatter-Gather Element Structure */ /************************************************************************/ -typedef struct SG_Struc { - U32 SG_Ptr; /* Data Pointer */ - U32 SG_Len; /* Data Length */ -} SG; +struct sg_entry { + u32 data; /* Data Pointer */ + u32 len; /* Data Length */ +}; /*********************************************************************** SCSI Control Block ************************************************************************/ -typedef struct Scsi_Ctrl_Blk { - struct Scsi_Ctrl_Blk *SCB_NxtScb; - UBYTE SCB_Status; /*4 */ - UBYTE SCB_NxtStat; /*5 */ - UBYTE SCB_Mode; /*6 */ - UBYTE SCB_Msgin; /*7 SCB_Res0 */ - UWORD SCB_SGIdx; /*8 */ - UWORD SCB_SGMax; /*A */ +struct scsi_ctrl_blk { + struct scsi_ctrl_blk *next; + u8 status; /*4 */ + u8 next_state; /*5 */ + u8 mode; /*6 */ + u8 msgin; /*7 SCB_Res0 */ + u16 sgidx; /*8 */ + u16 sgmax; /*A */ #ifdef ALPHA - U32 SCB_Reserved[2]; /*C */ + u32 reserved[2]; /*C */ #else - U32 SCB_Reserved[3]; /*C */ + u32 reserved[3]; /*C */ #endif - U32 SCB_XferLen; /*18 Current xfer len */ - U32 SCB_TotXLen; /*1C Total xfer len */ - U32 SCB_PAddr; /*20 SCB phy. Addr. */ - - UBYTE SCB_Opcode; /*24 SCB command code */ - UBYTE SCB_Flags; /*25 SCB Flags */ - UBYTE SCB_Target; /*26 Target Id */ - UBYTE SCB_Lun; /*27 Lun */ - U32 SCB_BufPtr; /*28 Data Buffer Pointer */ - U32 SCB_BufLen; /*2C Data Allocation Length */ - UBYTE SCB_SGLen; /*30 SG list # */ - UBYTE SCB_SenseLen; /*31 Sense Allocation Length */ - UBYTE SCB_HaStat; /*32 */ - UBYTE SCB_TaStat; /*33 */ - UBYTE SCB_CDBLen; /*34 CDB Length */ - UBYTE SCB_Ident; /*35 Identify */ - UBYTE SCB_TagMsg; /*36 Tag Message */ - UBYTE SCB_TagId; /*37 Queue Tag */ - UBYTE SCB_CDB[12]; /*38 */ - U32 SCB_SGPAddr; /*44 SG List/Sense Buf phy. Addr. */ - U32 SCB_SensePtr; /*48 Sense data pointer */ - void (*SCB_Post) (BYTE *, BYTE *); /*4C POST routine */ - struct scsi_cmnd *SCB_Srb; /*50 SRB Pointer */ - SG SCB_SGList[TOTAL_SG_ENTRY]; /*54 Start of SG list */ -} SCB; - -/* Bit Definition for SCB_Status */ + u32 xferlen; /*18 Current xfer len */ + u32 totxlen; /*1C Total xfer len */ + u32 paddr; /*20 SCB phy. Addr. */ + + u8 opcode; /*24 SCB command code */ + u8 flags; /*25 SCB Flags */ + u8 target; /*26 Target Id */ + u8 lun; /*27 Lun */ + u32 bufptr; /*28 Data Buffer Pointer */ + u32 buflen; /*2C Data Allocation Length */ + u8 sglen; /*30 SG list # */ + u8 senselen; /*31 Sense Allocation Length */ + u8 hastat; /*32 */ + u8 tastat; /*33 */ + u8 cdblen; /*34 CDB Length */ + u8 ident; /*35 Identify */ + u8 tagmsg; /*36 Tag Message */ + u8 tagid; /*37 Queue Tag */ + u8 cdb[12]; /*38 */ + u32 sgpaddr; /*44 SG List/Sense Buf phy. Addr. */ + u32 senseptr; /*48 Sense data pointer */ + void (*post) (u8 *, u8 *); /*4C POST routine */ + struct scsi_cmnd *srb; /*50 SRB Pointer */ + struct sg_entry sglist[TOTAL_SG_ENTRY]; /*54 Start of SG list */ +}; + +/* Bit Definition for status */ #define SCB_RENT 0x01 #define SCB_PEND 0x02 #define SCB_CONTIG 0x04 /* Contigent Allegiance */ @@ -425,17 +395,17 @@ typedef struct Scsi_Ctrl_Blk { #define SCB_DONE 0x20 -/* Opcodes of SCB_Opcode */ +/* Opcodes for opcode */ #define ExecSCSI 0x1 #define BusDevRst 0x2 #define AbortCmd 0x3 -/* Bit Definition for SCB_Mode */ +/* Bit Definition for mode */ #define SCM_RSENS 0x01 /* request sense mode */ -/* Bit Definition for SCB_Flags */ +/* Bit Definition for flags */ #define SCF_DONE 0x01 #define SCF_POST 0x02 #define SCF_SENSE 0x04 @@ -492,15 +462,14 @@ typedef struct Scsi_Ctrl_Blk { Target Device Control Structure **********************************************************************/ -typedef struct Tar_Ctrl_Struc { - UWORD TCS_Flags; /* 0 */ - UBYTE TCS_JS_Period; /* 2 */ - UBYTE TCS_SConfig0; /* 3 */ - - UWORD TCS_DrvFlags; /* 4 */ - UBYTE TCS_DrvHead; /* 6 */ - UBYTE TCS_DrvSector; /* 7 */ -} TCS; +struct target_control { + u16 flags; + u8 js_period; + u8 sconfig0; + u16 drv_flags; + u8 heads; + u8 sectors; +}; /*********************************************************************** Target Device Control Structure @@ -523,62 +492,53 @@ typedef struct Tar_Ctrl_Struc { #define TCF_DRV_EN_TAG 0x0800 #define TCF_DRV_255_63 0x0400 -typedef struct I91u_Adpt_Struc { - UWORD ADPT_BIOS; /* 0 */ - UWORD ADPT_BASE; /* 1 */ - UBYTE ADPT_Bus; /* 2 */ - UBYTE ADPT_Device; /* 3 */ - UBYTE ADPT_INTR; /* 4 */ -} INI_ADPT_STRUCT; - - /*********************************************************************** Host Adapter Control Structure ************************************************************************/ -typedef struct Ha_Ctrl_Struc { - UWORD HCS_Base; /* 00 */ - UWORD HCS_BIOS; /* 02 */ - UBYTE HCS_Intr; /* 04 */ - UBYTE HCS_SCSI_ID; /* 05 */ - UBYTE HCS_MaxTar; /* 06 */ - UBYTE HCS_NumScbs; /* 07 */ - - UBYTE HCS_Flags; /* 08 */ - UBYTE HCS_Index; /* 09 */ - UBYTE HCS_HaId; /* 0A */ - UBYTE HCS_Config; /* 0B */ - UWORD HCS_IdMask; /* 0C */ - UBYTE HCS_Semaph; /* 0E */ - UBYTE HCS_Phase; /* 0F */ - UBYTE HCS_JSStatus0; /* 10 */ - UBYTE HCS_JSInt; /* 11 */ - UBYTE HCS_JSStatus1; /* 12 */ - UBYTE HCS_SConf1; /* 13 */ - - UBYTE HCS_Msg[8]; /* 14 */ - SCB *HCS_NxtAvail; /* 1C */ - SCB *HCS_Scb; /* 20 */ - SCB *HCS_ScbEnd; /* 24 */ - SCB *HCS_NxtPend; /* 28 */ - SCB *HCS_NxtContig; /* 2C */ - SCB *HCS_ActScb; /* 30 */ - TCS *HCS_ActTcs; /* 34 */ - - SCB *HCS_FirstAvail; /* 38 */ - SCB *HCS_LastAvail; /* 3C */ - SCB *HCS_FirstPend; /* 40 */ - SCB *HCS_LastPend; /* 44 */ - SCB *HCS_FirstBusy; /* 48 */ - SCB *HCS_LastBusy; /* 4C */ - SCB *HCS_FirstDone; /* 50 */ - SCB *HCS_LastDone; /* 54 */ - UBYTE HCS_MaxTags[16]; /* 58 */ - UBYTE HCS_ActTags[16]; /* 68 */ - TCS HCS_Tcs[MAX_TARGETS]; /* 78 */ - spinlock_t HCS_AvailLock; - spinlock_t HCS_SemaphLock; +struct initio_host { + u16 addr; /* 00 */ + u16 bios_addr; /* 02 */ + u8 irq; /* 04 */ + u8 scsi_id; /* 05 */ + u8 max_tar; /* 06 */ + u8 num_scbs; /* 07 */ + + u8 flags; /* 08 */ + u8 index; /* 09 */ + u8 ha_id; /* 0A */ + u8 config; /* 0B */ + u16 idmask; /* 0C */ + u8 semaph; /* 0E */ + u8 phase; /* 0F */ + u8 jsstatus0; /* 10 */ + u8 jsint; /* 11 */ + u8 jsstatus1; /* 12 */ + u8 sconf1; /* 13 */ + + u8 msg[8]; /* 14 */ + struct scsi_ctrl_blk *next_avail; /* 1C */ + struct scsi_ctrl_blk *scb; /* 20 */ + struct scsi_ctrl_blk *scb_end; /* 24 */ /*UNUSED*/ + struct scsi_ctrl_blk *next_pending; /* 28 */ + struct scsi_ctrl_blk *next_contig; /* 2C */ /*UNUSED*/ + struct scsi_ctrl_blk *active; /* 30 */ + struct target_control *active_tc; /* 34 */ + + struct scsi_ctrl_blk *first_avail; /* 38 */ + struct scsi_ctrl_blk *last_avail; /* 3C */ + struct scsi_ctrl_blk *first_pending; /* 40 */ + struct scsi_ctrl_blk *last_pending; /* 44 */ + struct scsi_ctrl_blk *first_busy; /* 48 */ + struct scsi_ctrl_blk *last_busy; /* 4C */ + struct scsi_ctrl_blk *first_done; /* 50 */ + struct scsi_ctrl_blk *last_done; /* 54 */ + u8 max_tags[16]; /* 58 */ + u8 act_tags[16]; /* 68 */ + struct target_control targets[MAX_TARGETS]; /* 78 */ + spinlock_t avail_lock; + spinlock_t semaph_lock; struct pci_dev *pci_dev; -} HCS; +}; /* Bit Definition for HCB_Config */ #define HCC_SCSI_RESET 0x01 @@ -599,47 +559,47 @@ typedef struct Ha_Ctrl_Struc { *******************************************************************/ typedef struct _NVRAM_SCSI { /* SCSI channel configuration */ - UCHAR NVM_ChSCSIID; /* 0Ch -> Channel SCSI ID */ - UCHAR NVM_ChConfig1; /* 0Dh -> Channel config 1 */ - UCHAR NVM_ChConfig2; /* 0Eh -> Channel config 2 */ - UCHAR NVM_NumOfTarg; /* 0Fh -> Number of SCSI target */ + u8 NVM_ChSCSIID; /* 0Ch -> Channel SCSI ID */ + u8 NVM_ChConfig1; /* 0Dh -> Channel config 1 */ + u8 NVM_ChConfig2; /* 0Eh -> Channel config 2 */ + u8 NVM_NumOfTarg; /* 0Fh -> Number of SCSI target */ /* SCSI target configuration */ - UCHAR NVM_Targ0Config; /* 10h -> Target 0 configuration */ - UCHAR NVM_Targ1Config; /* 11h -> Target 1 configuration */ - UCHAR NVM_Targ2Config; /* 12h -> Target 2 configuration */ - UCHAR NVM_Targ3Config; /* 13h -> Target 3 configuration */ - UCHAR NVM_Targ4Config; /* 14h -> Target 4 configuration */ - UCHAR NVM_Targ5Config; /* 15h -> Target 5 configuration */ - UCHAR NVM_Targ6Config; /* 16h -> Target 6 configuration */ - UCHAR NVM_Targ7Config; /* 17h -> Target 7 configuration */ - UCHAR NVM_Targ8Config; /* 18h -> Target 8 configuration */ - UCHAR NVM_Targ9Config; /* 19h -> Target 9 configuration */ - UCHAR NVM_TargAConfig; /* 1Ah -> Target A configuration */ - UCHAR NVM_TargBConfig; /* 1Bh -> Target B configuration */ - UCHAR NVM_TargCConfig; /* 1Ch -> Target C configuration */ - UCHAR NVM_TargDConfig; /* 1Dh -> Target D configuration */ - UCHAR NVM_TargEConfig; /* 1Eh -> Target E configuration */ - UCHAR NVM_TargFConfig; /* 1Fh -> Target F configuration */ + u8 NVM_Targ0Config; /* 10h -> Target 0 configuration */ + u8 NVM_Targ1Config; /* 11h -> Target 1 configuration */ + u8 NVM_Targ2Config; /* 12h -> Target 2 configuration */ + u8 NVM_Targ3Config; /* 13h -> Target 3 configuration */ + u8 NVM_Targ4Config; /* 14h -> Target 4 configuration */ + u8 NVM_Targ5Config; /* 15h -> Target 5 configuration */ + u8 NVM_Targ6Config; /* 16h -> Target 6 configuration */ + u8 NVM_Targ7Config; /* 17h -> Target 7 configuration */ + u8 NVM_Targ8Config; /* 18h -> Target 8 configuration */ + u8 NVM_Targ9Config; /* 19h -> Target 9 configuration */ + u8 NVM_TargAConfig; /* 1Ah -> Target A configuration */ + u8 NVM_TargBConfig; /* 1Bh -> Target B configuration */ + u8 NVM_TargCConfig; /* 1Ch -> Target C configuration */ + u8 NVM_TargDConfig; /* 1Dh -> Target D configuration */ + u8 NVM_TargEConfig; /* 1Eh -> Target E configuration */ + u8 NVM_TargFConfig; /* 1Fh -> Target F configuration */ } NVRAM_SCSI; typedef struct _NVRAM { /*----------header ---------------*/ - USHORT NVM_Signature; /* 0,1: Signature */ - UCHAR NVM_Size; /* 2: Size of data structure */ - UCHAR NVM_Revision; /* 3: Revision of data structure */ + u16 NVM_Signature; /* 0,1: Signature */ + u8 NVM_Size; /* 2: Size of data structure */ + u8 NVM_Revision; /* 3: Revision of data structure */ /* ----Host Adapter Structure ---- */ - UCHAR NVM_ModelByte0; /* 4: Model number (byte 0) */ - UCHAR NVM_ModelByte1; /* 5: Model number (byte 1) */ - UCHAR NVM_ModelInfo; /* 6: Model information */ - UCHAR NVM_NumOfCh; /* 7: Number of SCSI channel */ - UCHAR NVM_BIOSConfig1; /* 8: BIOS configuration 1 */ - UCHAR NVM_BIOSConfig2; /* 9: BIOS configuration 2 */ - UCHAR NVM_HAConfig1; /* A: Hoat adapter configuration 1 */ - UCHAR NVM_HAConfig2; /* B: Hoat adapter configuration 2 */ + u8 NVM_ModelByte0; /* 4: Model number (byte 0) */ + u8 NVM_ModelByte1; /* 5: Model number (byte 1) */ + u8 NVM_ModelInfo; /* 6: Model information */ + u8 NVM_NumOfCh; /* 7: Number of SCSI channel */ + u8 NVM_BIOSConfig1; /* 8: BIOS configuration 1 */ + u8 NVM_BIOSConfig2; /* 9: BIOS configuration 2 */ + u8 NVM_HAConfig1; /* A: Hoat adapter configuration 1 */ + u8 NVM_HAConfig2; /* B: Hoat adapter configuration 2 */ NVRAM_SCSI NVM_SCSIInfo[2]; - UCHAR NVM_reserved[10]; + u8 NVM_reserved[10]; /* ---------- CheckSum ---------- */ - USHORT NVM_CheckSum; /* 0x3E, 0x3F: Checksum of NVRam */ + u16 NVM_CheckSum; /* 0x3E, 0x3F: Checksum of NVRam */ } NVRAM, *PNVRAM; /* Bios Configuration for nvram->BIOSConfig1 */ @@ -681,19 +641,6 @@ typedef struct _NVRAM { #define DISC_ALLOW 0xC0 /* Disconnect is allowed */ #define SCSICMD_RequestSense 0x03 -typedef struct _HCSinfo { - ULONG base; - UCHAR vec; - UCHAR bios; /* High byte of BIOS address */ - USHORT BaseAndBios; /* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */ -} HCSINFO; - -#define TUL_RD(x,y) (UCHAR)(inb( (int)((ULONG)(x+y)) )) -#define TUL_RDLONG(x,y) (ULONG)(inl((int)((ULONG)(x+y)) )) -#define TUL_WR( adr,data) outb( (UCHAR)(data), (int)(adr)) -#define TUL_WRSHORT(adr,data) outw( (UWORD)(data), (int)(adr)) -#define TUL_WRLONG( adr,data) outl( (ULONG)(data), (int)(adr)) - #define SCSI_ABORT_SNOOZE 0 #define SCSI_ABORT_SUCCESS 1 #define SCSI_ABORT_PENDING 2 diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index fa6ff295e568..072f57715658 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -540,32 +540,6 @@ struct ipr_cmnd *ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg) } /** - * ipr_unmap_sglist - Unmap scatterlist if mapped - * @ioa_cfg: ioa config struct - * @ipr_cmd: ipr command struct - * - * Return value: - * nothing - **/ -static void ipr_unmap_sglist(struct ipr_ioa_cfg *ioa_cfg, - struct ipr_cmnd *ipr_cmd) -{ - struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; - - if (ipr_cmd->dma_use_sg) { - if (scsi_cmd->use_sg > 0) { - pci_unmap_sg(ioa_cfg->pdev, scsi_cmd->request_buffer, - scsi_cmd->use_sg, - scsi_cmd->sc_data_direction); - } else { - pci_unmap_single(ioa_cfg->pdev, ipr_cmd->dma_handle, - scsi_cmd->request_bufflen, - scsi_cmd->sc_data_direction); - } - } -} - -/** * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts * @ioa_cfg: ioa config struct * @clr_ints: interrupts to clear @@ -677,7 +651,7 @@ static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd) scsi_cmd->result |= (DID_ERROR << 16); - ipr_unmap_sglist(ioa_cfg, ipr_cmd); + scsi_dma_unmap(ipr_cmd->scsi_cmd); scsi_cmd->scsi_done(scsi_cmd); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); } @@ -4292,93 +4266,55 @@ static irqreturn_t ipr_isr(int irq, void *devp) static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg, struct ipr_cmnd *ipr_cmd) { - int i; - struct scatterlist *sglist; + int i, nseg; + struct scatterlist *sg; u32 length; u32 ioadl_flags = 0; struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; - length = scsi_cmd->request_bufflen; - - if (length == 0) + length = scsi_bufflen(scsi_cmd); + if (!length) return 0; - if (scsi_cmd->use_sg) { - ipr_cmd->dma_use_sg = pci_map_sg(ioa_cfg->pdev, - scsi_cmd->request_buffer, - scsi_cmd->use_sg, - scsi_cmd->sc_data_direction); - - if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { - ioadl_flags = IPR_IOADL_FLAGS_WRITE; - ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; - ioarcb->write_data_transfer_length = cpu_to_be32(length); - ioarcb->write_ioadl_len = - cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); - } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) { - ioadl_flags = IPR_IOADL_FLAGS_READ; - ioarcb->read_data_transfer_length = cpu_to_be32(length); - ioarcb->read_ioadl_len = - cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); - } - - sglist = scsi_cmd->request_buffer; + nseg = scsi_dma_map(scsi_cmd); + if (nseg < 0) { + dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n"); + return -1; + } - if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) { - ioadl = ioarcb->add_data.u.ioadl; - ioarcb->write_ioadl_addr = - cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) + - offsetof(struct ipr_ioarcb, add_data)); - ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; - } + ipr_cmd->dma_use_sg = nseg; - for (i = 0; i < ipr_cmd->dma_use_sg; i++) { - ioadl[i].flags_and_data_len = - cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i])); - ioadl[i].address = - cpu_to_be32(sg_dma_address(&sglist[i])); - } + if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { + ioadl_flags = IPR_IOADL_FLAGS_WRITE; + ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; + ioarcb->write_data_transfer_length = cpu_to_be32(length); + ioarcb->write_ioadl_len = + cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); + } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) { + ioadl_flags = IPR_IOADL_FLAGS_READ; + ioarcb->read_data_transfer_length = cpu_to_be32(length); + ioarcb->read_ioadl_len = + cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); + } - if (likely(ipr_cmd->dma_use_sg)) { - ioadl[i-1].flags_and_data_len |= - cpu_to_be32(IPR_IOADL_FLAGS_LAST); - return 0; - } else - dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n"); - } else { - if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { - ioadl_flags = IPR_IOADL_FLAGS_WRITE; - ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; - ioarcb->write_data_transfer_length = cpu_to_be32(length); - ioarcb->write_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc)); - } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) { - ioadl_flags = IPR_IOADL_FLAGS_READ; - ioarcb->read_data_transfer_length = cpu_to_be32(length); - ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc)); - } + if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) { + ioadl = ioarcb->add_data.u.ioadl; + ioarcb->write_ioadl_addr = + cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) + + offsetof(struct ipr_ioarcb, add_data)); + ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; + } - ipr_cmd->dma_handle = pci_map_single(ioa_cfg->pdev, - scsi_cmd->request_buffer, length, - scsi_cmd->sc_data_direction); - - if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) { - ioadl = ioarcb->add_data.u.ioadl; - ioarcb->write_ioadl_addr = - cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) + - offsetof(struct ipr_ioarcb, add_data)); - ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; - ipr_cmd->dma_use_sg = 1; - ioadl[0].flags_and_data_len = - cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST); - ioadl[0].address = cpu_to_be32(ipr_cmd->dma_handle); - return 0; - } else - dev_err(&ioa_cfg->pdev->dev, "pci_map_single failed!\n"); + scsi_for_each_sg(scsi_cmd, sg, ipr_cmd->dma_use_sg, i) { + ioadl[i].flags_and_data_len = + cpu_to_be32(ioadl_flags | sg_dma_len(sg)); + ioadl[i].address = cpu_to_be32(sg_dma_address(sg)); } - return -1; + ioadl[i-1].flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST); + return 0; } /** @@ -4441,7 +4377,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) res->needs_sync_complete = 1; res->in_erp = 0; } - ipr_unmap_sglist(ioa_cfg, ipr_cmd); + scsi_dma_unmap(ipr_cmd->scsi_cmd); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); scsi_cmd->scsi_done(scsi_cmd); } @@ -4819,7 +4755,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, break; } - ipr_unmap_sglist(ioa_cfg, ipr_cmd); + scsi_dma_unmap(ipr_cmd->scsi_cmd); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); scsi_cmd->scsi_done(scsi_cmd); } @@ -4840,10 +4776,10 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd) struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); - scsi_cmd->resid = be32_to_cpu(ipr_cmd->ioasa.residual_data_len); + scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len)); if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) { - ipr_unmap_sglist(ioa_cfg, ipr_cmd); + scsi_dma_unmap(ipr_cmd->scsi_cmd); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); scsi_cmd->scsi_done(scsi_cmd); } else diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 8b704f73055a..84f4f5d06f9d 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -211,19 +211,6 @@ module_param(ips, charp, 0); #warning "This driver has only been tested on the x86/ia64/x86_64 platforms" #endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) -#include <linux/blk.h> -#include "sd.h" -#define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags) -#define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags) -#ifndef __devexit_p -#define __devexit_p(x) x -#endif -#else -#define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0) -#define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0) -#endif - #define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \ DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \ PCI_DMA_BIDIRECTIONAL : \ @@ -381,24 +368,13 @@ static struct scsi_host_template ips_driver_template = { .eh_abort_handler = ips_eh_abort, .eh_host_reset_handler = ips_eh_reset, .proc_name = "ips", -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) .proc_info = ips_proc_info, .slave_configure = ips_slave_configure, -#else - .proc_info = ips_proc24_info, - .select_queue_depths = ips_select_queue_depth, -#endif .bios_param = ips_biosparam, .this_id = -1, .sg_tablesize = IPS_MAX_SG, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - .use_new_eh_code = 1, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - .highmem_io = 1, -#endif }; @@ -731,7 +707,7 @@ ips_release(struct Scsi_Host *sh) /* free IRQ */ free_irq(ha->irq, ha); - IPS_REMOVE_HOST(sh); + scsi_remove_host(sh); scsi_host_put(sh); ips_released_controllers++; @@ -813,7 +789,6 @@ int ips_eh_abort(struct scsi_cmnd *SC) ips_ha_t *ha; ips_copp_wait_item_t *item; int ret; - unsigned long cpu_flags; struct Scsi_Host *host; METHOD_TRACE("ips_eh_abort", 1); @@ -830,7 +805,7 @@ int ips_eh_abort(struct scsi_cmnd *SC) if (!ha->active) return (FAILED); - IPS_LOCK_SAVE(host->host_lock, cpu_flags); + spin_lock(host->host_lock); /* See if the command is on the copp queue */ item = ha->copp_waitlist.head; @@ -851,7 +826,7 @@ int ips_eh_abort(struct scsi_cmnd *SC) ret = (FAILED); } - IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); + spin_unlock(host->host_lock); return ret; } @@ -1176,18 +1151,10 @@ static int ips_queue(struct scsi_cmnd *SC, void (*done) (struct scsi_cmnd *)) /* Set bios geometry for the controller */ /* */ /****************************************************************************/ -static int -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -ips_biosparam(Disk * disk, kdev_t dev, int geom[]) -{ - ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata; - unsigned long capacity = disk->capacity; -#else -ips_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]) +static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int geom[]) { ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata; -#endif int heads; int sectors; int cylinders; @@ -1225,70 +1192,6 @@ ips_biosparam(struct scsi_device *sdev, struct block_device *bdev, return (0); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - -/* ips_proc24_info is a wrapper around ips_proc_info * - * for compatibility with the 2.4 scsi parameters */ -static int -ips_proc24_info(char *buffer, char **start, off_t offset, int length, - int hostno, int func) -{ - int i; - - for (i = 0; i < ips_next_controller; i++) { - if (ips_sh[i] && ips_sh[i]->host_no == hostno) { - return ips_proc_info(ips_sh[i], buffer, start, - offset, length, func); - } - } - return -EINVAL; -} - -/****************************************************************************/ -/* */ -/* Routine Name: ips_select_queue_depth */ -/* */ -/* Routine Description: */ -/* */ -/* Select queue depths for the devices on the contoller */ -/* */ -/****************************************************************************/ -static void -ips_select_queue_depth(struct Scsi_Host *host, struct scsi_device * scsi_devs) -{ - struct scsi_device *device; - ips_ha_t *ha; - int count = 0; - int min; - - ha = IPS_HA(host); - min = ha->max_cmds / 4; - - for (device = scsi_devs; device; device = device->next) { - if (device->host == host) { - if ((device->channel == 0) && (device->type == 0)) - count++; - } - } - - for (device = scsi_devs; device; device = device->next) { - if (device->host == host) { - if ((device->channel == 0) && (device->type == 0)) { - device->queue_depth = - (ha->max_cmds - 1) / count; - if (device->queue_depth < min) - device->queue_depth = min; - } else { - device->queue_depth = 2; - } - - if (device->queue_depth < 2) - device->queue_depth = 2; - } - } -} - -#else /****************************************************************************/ /* */ /* Routine Name: ips_slave_configure */ @@ -1316,7 +1219,6 @@ ips_slave_configure(struct scsi_device * SDptr) SDptr->skip_ms_page_3f = 1; return 0; } -#endif /****************************************************************************/ /* */ @@ -1331,7 +1233,6 @@ static irqreturn_t do_ipsintr(int irq, void *dev_id) { ips_ha_t *ha; - unsigned long cpu_flags; struct Scsi_Host *host; int irqstatus; @@ -1347,16 +1248,16 @@ do_ipsintr(int irq, void *dev_id) return IRQ_HANDLED; } - IPS_LOCK_SAVE(host->host_lock, cpu_flags); + spin_lock(host->host_lock); if (!ha->active) { - IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); + spin_unlock(host->host_lock); return IRQ_HANDLED; } irqstatus = (*ha->func.intr) (ha); - IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); + spin_unlock(host->host_lock); /* start the next command */ ips_next(ha, IPS_INTR_ON); @@ -2730,7 +2631,6 @@ ips_next(ips_ha_t * ha, int intr) struct scsi_cmnd *q; ips_copp_wait_item_t *item; int ret; - unsigned long cpu_flags = 0; struct Scsi_Host *host; METHOD_TRACE("ips_next", 1); @@ -2742,7 +2642,7 @@ ips_next(ips_ha_t * ha, int intr) * this command won't time out */ if (intr == IPS_INTR_ON) - IPS_LOCK_SAVE(host->host_lock, cpu_flags); + spin_lock(host->host_lock); if ((ha->subsys->param[3] & 0x300000) && (ha->scb_activelist.count == 0)) { @@ -2769,14 +2669,14 @@ ips_next(ips_ha_t * ha, int intr) item = ips_removeq_copp_head(&ha->copp_waitlist); ha->num_ioctl++; if (intr == IPS_INTR_ON) - IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); + spin_unlock(host->host_lock); scb->scsi_cmd = item->scsi_cmd; kfree(item); ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr); if (intr == IPS_INTR_ON) - IPS_LOCK_SAVE(host->host_lock, cpu_flags); + spin_lock(host->host_lock); switch (ret) { case IPS_FAILURE: if (scb->scsi_cmd) { @@ -2846,7 +2746,7 @@ ips_next(ips_ha_t * ha, int intr) SC = ips_removeq_wait(&ha->scb_waitlist, q); if (intr == IPS_INTR_ON) - IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* Unlock HA after command is taken off queue */ + spin_unlock(host->host_lock); /* Unlock HA after command is taken off queue */ SC->result = DID_OK; SC->host_scribble = NULL; @@ -2919,7 +2819,7 @@ ips_next(ips_ha_t * ha, int intr) scb->dcdb.transfer_length = 0; } if (intr == IPS_INTR_ON) - IPS_LOCK_SAVE(host->host_lock, cpu_flags); + spin_lock(host->host_lock); ret = ips_send_cmd(ha, scb); @@ -2958,7 +2858,7 @@ ips_next(ips_ha_t * ha, int intr) } /* end while */ if (intr == IPS_INTR_ON) - IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); + spin_unlock(host->host_lock); } /****************************************************************************/ @@ -7004,7 +6904,6 @@ ips_register_scsi(int index) kfree(oldha); ips_sh[index] = sh; ips_ha[index] = ha; - IPS_SCSI_SET_DEVICE(sh, ha); /* Store away needed values for later use */ sh->io_port = ha->io_addr; @@ -7016,17 +6915,16 @@ ips_register_scsi(int index) sh->cmd_per_lun = sh->hostt->cmd_per_lun; sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma; sh->use_clustering = sh->hostt->use_clustering; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) sh->max_sectors = 128; -#endif sh->max_id = ha->ntargets; sh->max_lun = ha->nlun; sh->max_channel = ha->nbus - 1; sh->can_queue = ha->max_cmds - 1; - IPS_ADD_HOST(sh, NULL); + scsi_add_host(sh, NULL); + scsi_scan_host(sh); + return 0; } @@ -7069,7 +6967,7 @@ ips_module_init(void) return -ENODEV; ips_driver_template.module = THIS_MODULE; ips_order_controllers(); - if (IPS_REGISTER_HOSTS(&ips_driver_template)) { + if (!ips_detect(&ips_driver_template)) { pci_unregister_driver(&ips_pci_driver); return -ENODEV; } @@ -7087,7 +6985,6 @@ ips_module_init(void) static void __exit ips_module_exit(void) { - IPS_UNREGISTER_HOSTS(&ips_driver_template); pci_unregister_driver(&ips_pci_driver); unregister_reboot_notifier(&ips_notifier); } @@ -7443,15 +7340,9 @@ ips_init_phase2(int index) return SUCCESS; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) MODULE_LICENSE("GPL"); -#endif - MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING); - -#ifdef MODULE_VERSION MODULE_VERSION(IPS_VER_STRING); -#endif /* diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index b726dcc424b1..24123d537c58 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -58,10 +58,6 @@ /* * Some handy macros */ - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || defined CONFIG_HIGHIO - #define IPS_HIGHIO - #endif - #define IPS_HA(x) ((ips_ha_t *) x->hostdata) #define IPS_COMMAND_ID(ha, scb) (int) (scb - ha->scbs) #define IPS_IS_TROMBONE(ha) (((ha->device_id == IPS_DEVICEID_COPPERHEAD) && \ @@ -84,38 +80,8 @@ #define IPS_SGLIST_SIZE(ha) (IPS_USE_ENH_SGLIST(ha) ? \ sizeof(IPS_ENH_SG_LIST) : sizeof(IPS_STD_SG_LIST)) - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) - #define pci_set_dma_mask(dev,mask) ( mask > 0xffffffff ? 1:0 ) - #define scsi_set_pci_device(sh,dev) (0) - #endif - - #ifndef IRQ_NONE - typedef void irqreturn_t; - #define IRQ_NONE - #define IRQ_HANDLED - #define IRQ_RETVAL(x) - #endif - - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - #define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT) - #define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT) - #define IPS_ADD_HOST(shost,device) - #define IPS_REMOVE_HOST(shost) - #define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_pci_device(sh, (ha)->pcidev) - #define IPS_PRINTK(level, pcidev, format, arg...) \ - printk(level "%s %s:" format , "ips" , \ - (pcidev)->slot_name , ## arg) - #define scsi_host_alloc(sh,size) scsi_register(sh,size) - #define scsi_host_put(sh) scsi_unregister(sh) - #else - #define IPS_REGISTER_HOSTS(SHT) (!ips_detect(SHT)) - #define IPS_UNREGISTER_HOSTS(SHT) - #define IPS_ADD_HOST(shost,device) do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0) - #define IPS_REMOVE_HOST(shost) scsi_remove_host(shost) - #define IPS_SCSI_SET_DEVICE(sh,ha) do { } while (0) - #define IPS_PRINTK(level, pcidev, format, arg...) \ + #define IPS_PRINTK(level, pcidev, format, arg...) \ dev_printk(level , &((pcidev)->dev) , format , ## arg) - #endif #define MDELAY(n) \ do { \ @@ -134,7 +100,7 @@ #define pci_dma_hi32(a) ((a >> 16) >> 16) #define pci_dma_lo32(a) (a & 0xffffffff) - #if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO) + #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G) #define IPS_ENABLE_DMA64 (1) #else #define IPS_ENABLE_DMA64 (0) @@ -451,16 +417,10 @@ /* * Scsi_Host Template */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - static int ips_proc24_info(char *, char **, off_t, int, int, int); - static void ips_select_queue_depth(struct Scsi_Host *, struct scsi_device *); - static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]); -#else static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int); static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]); static int ips_slave_configure(struct scsi_device *SDptr); -#endif /* * Raid Command Formats diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c index 81e497d9eae0..0140766c0286 100644 --- a/drivers/scsi/jazz_esp.c +++ b/drivers/scsi/jazz_esp.c @@ -1,6 +1,6 @@ /* jazz_esp.c: ESP front-end for MIPS JAZZ systems. * - * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende) + * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende) */ #include <linux/kernel.h> diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index b4b52694497c..d70ddfda93fc 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -76,8 +76,8 @@ static void sas_scsi_task_done(struct sas_task *task) hs = DID_NO_CONNECT; break; case SAS_DATA_UNDERRUN: - sc->resid = ts->residual; - if (sc->request_bufflen - sc->resid < sc->underflow) + scsi_set_resid(sc, ts->residual); + if (scsi_bufflen(sc) - scsi_get_resid(sc) < sc->underflow) hs = DID_ERROR; break; case SAS_DATA_OVERRUN: @@ -161,9 +161,9 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd, task->ssp_task.task_attr = sas_scsi_get_task_attr(cmd); memcpy(task->ssp_task.cdb, cmd->cmnd, 16); - task->scatter = cmd->request_buffer; - task->num_scatter = cmd->use_sg; - task->total_xfer_len = cmd->request_bufflen; + task->scatter = scsi_sglist(cmd); + task->num_scatter = scsi_sg_count(cmd); + task->total_xfer_len = scsi_bufflen(cmd); task->data_dir = cmd->sc_data_direction; task->task_done = sas_scsi_task_done; diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 5806ede120a4..b12ad7c7c673 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -77,7 +77,7 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd * for (i = 0; i < cmd->cmd_len; ++i) printk(" %.2x", cmd->cmnd[i]); printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", - cmd->use_sg, cmd->request_bufflen, cmd->request_buffer); + scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd)); } #endif @@ -173,8 +173,7 @@ static void mac53c94_start(struct fsc_state *state) writeb(CMD_SELECT, ®s->command); state->phase = selecting; - if (cmd->use_sg > 0 || cmd->request_bufflen != 0) - set_dma_cmds(state, cmd); + set_dma_cmds(state, cmd); } static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id) @@ -262,7 +261,7 @@ static void mac53c94_interrupt(int irq, void *dev_id) writeb(CMD_NOP, ®s->command); /* set DMA controller going if any data to transfer */ if ((stat & (STAT_MSG|STAT_CD)) == 0 - && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) { + && (scsi_sg_count(cmd) > 0 || scsi_bufflen(cmd))) { nb = cmd->SCp.this_residual; if (nb > 0xfff0) nb = 0xfff0; @@ -310,14 +309,7 @@ static void mac53c94_interrupt(int irq, void *dev_id) printk(KERN_DEBUG "intr %x before data xfer complete\n", intr); } writel(RUN << 16, &dma->control); /* stop dma */ - if (cmd->use_sg != 0) { - pci_unmap_sg(state->pdev, - (struct scatterlist *)cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); - } else { - pci_unmap_single(state->pdev, state->dma_addr, - cmd->request_bufflen, cmd->sc_data_direction); - } + scsi_dma_unmap(cmd); /* should check dma status */ writeb(CMD_I_COMPLETE, ®s->command); state->phase = completing; @@ -365,47 +357,35 @@ static void cmd_done(struct fsc_state *state, int result) */ static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd) { - int i, dma_cmd, total; + int i, dma_cmd, total, nseg; struct scatterlist *scl; struct dbdma_cmd *dcmds; dma_addr_t dma_addr; u32 dma_len; + nseg = scsi_dma_map(cmd); + BUG_ON(nseg < 0); + if (!nseg) + return; + dma_cmd = cmd->sc_data_direction == DMA_TO_DEVICE ? OUTPUT_MORE : INPUT_MORE; dcmds = state->dma_cmds; - if (cmd->use_sg > 0) { - int nseg; - - total = 0; - scl = (struct scatterlist *) cmd->request_buffer; - nseg = pci_map_sg(state->pdev, scl, cmd->use_sg, - cmd->sc_data_direction); - for (i = 0; i < nseg; ++i) { - dma_addr = sg_dma_address(scl); - dma_len = sg_dma_len(scl); - if (dma_len > 0xffff) - panic("mac53c94: scatterlist element >= 64k"); - total += dma_len; - st_le16(&dcmds->req_count, dma_len); - st_le16(&dcmds->command, dma_cmd); - st_le32(&dcmds->phy_addr, dma_addr); - dcmds->xfer_status = 0; - ++scl; - ++dcmds; - } - } else { - total = cmd->request_bufflen; - if (total > 0xffff) - panic("mac53c94: transfer size >= 64k"); - dma_addr = pci_map_single(state->pdev, cmd->request_buffer, - total, cmd->sc_data_direction); - state->dma_addr = dma_addr; - st_le16(&dcmds->req_count, total); + total = 0; + + scsi_for_each_sg(cmd, scl, nseg, i) { + dma_addr = sg_dma_address(scl); + dma_len = sg_dma_len(scl); + if (dma_len > 0xffff) + panic("mac53c94: scatterlist element >= 64k"); + total += dma_len; + st_le16(&dcmds->req_count, dma_len); + st_le16(&dcmds->command, dma_cmd); st_le32(&dcmds->phy_addr, dma_addr); dcmds->xfer_status = 0; ++dcmds; } + dma_cmd += OUTPUT_LAST - OUTPUT_MORE; st_le16(&dcmds[-1].command, dma_cmd); st_le16(&dcmds->command, DBDMA_STOP); diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 3cce75d70263..40ee07dab450 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -3571,7 +3571,7 @@ megadev_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, /* * The user passthru structure */ - upthru = (mega_passthru __user *)MBOX(uioc)->xferaddr; + upthru = (mega_passthru __user *)(unsigned long)MBOX(uioc)->xferaddr; /* * Copy in the user passthru here. @@ -3623,7 +3623,7 @@ megadev_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, /* * Get the user data */ - if( copy_from_user(data, (char __user *)uxferaddr, + if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr, pthru->dataxferlen) ) { rval = (-EFAULT); goto freemem_and_return; @@ -3649,7 +3649,7 @@ megadev_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, * Is data going up-stream */ if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) { - if( copy_to_user((char __user *)uxferaddr, data, + if( copy_to_user((char __user *)(unsigned long) uxferaddr, data, pthru->dataxferlen) ) { rval = (-EFAULT); } @@ -3702,7 +3702,7 @@ freemem_and_return: /* * Get the user data */ - if( copy_from_user(data, (char __user *)uxferaddr, + if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr, uioc.xferlen) ) { pci_free_consistent(pdev, @@ -3742,7 +3742,7 @@ freemem_and_return: * Is data going up-stream */ if( uioc.xferlen && (uioc.flags & UIOC_RD) ) { - if( copy_to_user((char __user *)uxferaddr, data, + if( copy_to_user((char __user *)(unsigned long) uxferaddr, data, uioc.xferlen) ) { rval = (-EFAULT); diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c deleted file mode 100644 index 575fe6f7e0ec..000000000000 --- a/drivers/scsi/mvme16x.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Detection routine for the NCR53c710 based MVME16x SCSI Controllers for Linux. - * - * Based on work by Alan Hourihane - */ -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/blkdev.h> - -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/mvme16xhw.h> -#include <asm/irq.h> - -#include "scsi.h" -#include <scsi/scsi_host.h> -#include "53c7xx.h" -#include "mvme16x.h" - -#include<linux/stat.h> - - -int mvme16x_scsi_detect(struct scsi_host_template *tpnt) -{ - static unsigned char called = 0; - int clock; - long long options; - - if (!MACH_IS_MVME16x) - return 0; - if (mvme16x_config & MVME16x_CONFIG_NO_SCSICHIP) { - printk ("SCSI detection disabled, SCSI chip not present\n"); - return 0; - } - if (called) - return 0; - - tpnt->proc_name = "MVME16x"; - - options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT; - - clock = 66000000; /* 66MHz SCSI Clock */ - - ncr53c7xx_init(tpnt, 0, 710, (unsigned long)0xfff47000, - 0, MVME16x_IRQ_SCSI, DMA_NONE, - options, clock); - called = 1; - return 1; -} - -static int mvme16x_scsi_release(struct Scsi_Host *shost) -{ - if (shost->irq) - free_irq(shost->irq, NULL); - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - scsi_unregister(shost); - return 0; -} - -static struct scsi_host_template driver_template = { - .name = "MVME16x NCR53c710 SCSI", - .detect = mvme16x_scsi_detect, - .release = mvme16x_scsi_release, - .queuecommand = NCR53c7xx_queue_command, - .abort = NCR53c7xx_abort, - .reset = NCR53c7xx_reset, - .can_queue = 24, - .this_id = 7, - .sg_tablesize = 63, - .cmd_per_lun = 3, - .use_clustering = DISABLE_CLUSTERING -}; - - -#include "scsi_module.c" diff --git a/drivers/scsi/mvme16x.h b/drivers/scsi/mvme16x.h deleted file mode 100644 index 73e33b37a3f8..000000000000 --- a/drivers/scsi/mvme16x.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MVME16x_SCSI_H -#define MVME16x_SCSI_H - -#include <linux/types.h> - -int mvme16x_scsi_detect(struct scsi_host_template *); -const char *NCR53c7x0_info(void); -int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int NCR53c7xx_abort(Scsi_Cmnd *); -int NCR53c7x0_release (struct Scsi_Host *); -int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int); -void NCR53c7x0_intr(int irq, void *dev_id); - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 3 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 24 -#endif - -#include <scsi/scsicam.h> - -#endif /* MVME16x_SCSI_H */ diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index f6f561d26bf0..8cc9e64bbdff 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -49,10 +49,6 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_ioctl.h> -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -# include <linux/blk.h> -#endif - #include "nsp32.h" @@ -199,17 +195,9 @@ static int __init init_nsp32 (void); static void __exit exit_nsp32 (void); /* struct struct scsi_host_template */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) static int nsp32_proc_info (struct Scsi_Host *, char *, char **, off_t, int, int); -#else -static int nsp32_proc_info (char *, char **, off_t, int, int, int); -#endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) static int nsp32_detect (struct pci_dev *pdev); -#else -static int nsp32_detect (struct scsi_host_template *); -#endif static int nsp32_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); static const char *nsp32_info (struct Scsi_Host *); @@ -296,15 +284,7 @@ static struct scsi_host_template nsp32_template = { .eh_abort_handler = nsp32_eh_abort, .eh_bus_reset_handler = nsp32_eh_bus_reset, .eh_host_reset_handler = nsp32_eh_host_reset, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)) - .detect = nsp32_detect, - .release = nsp32_release, -#endif -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)) - .use_new_eh_code = 1, -#else /* .highmem_io = 1, */ -#endif }; #include "nsp32_io.h" @@ -739,7 +719,7 @@ static int nsp32_selection_autoscsi(struct scsi_cmnd *SCpnt) command = 0; command |= (TRANSFER_GO | ALL_COUNTER_CLR); if (data->trans_method & NSP32_TRANSFER_BUSMASTER) { - if (SCpnt->request_bufflen > 0) { + if (scsi_bufflen(SCpnt) > 0) { command |= BM_START; } } else if (data->trans_method & NSP32_TRANSFER_MMIO) { @@ -888,31 +868,28 @@ static int nsp32_reselection(struct scsi_cmnd *SCpnt, unsigned char newlun) static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; - struct scatterlist *sgl; + struct scatterlist *sg; nsp32_sgtable *sgt = data->cur_lunt->sglun->sgt; int num, i; u32_le l; - if (SCpnt->request_bufflen == 0) { - return TRUE; - } - if (sgt == NULL) { nsp32_dbg(NSP32_DEBUG_SGLIST, "SGT == null"); return FALSE; } - if (SCpnt->use_sg) { - sgl = (struct scatterlist *)SCpnt->request_buffer; - num = pci_map_sg(data->Pci, sgl, SCpnt->use_sg, - SCpnt->sc_data_direction); - for (i = 0; i < num; i++) { + num = scsi_dma_map(SCpnt); + if (!num) + return TRUE; + else if (num < 0) + return FALSE; + else { + scsi_for_each_sg(SCpnt, sg, num, i) { /* * Build nsp32_sglist, substitute sg dma addresses. */ - sgt[i].addr = cpu_to_le32(sg_dma_address(sgl)); - sgt[i].len = cpu_to_le32(sg_dma_len(sgl)); - sgl++; + sgt[i].addr = cpu_to_le32(sg_dma_address(sg)); + sgt[i].len = cpu_to_le32(sg_dma_len(sg)); if (le32_to_cpu(sgt[i].len) > 0x10000) { nsp32_msg(KERN_ERR, @@ -929,23 +906,6 @@ static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt) /* set end mark */ l = le32_to_cpu(sgt[num-1].len); sgt[num-1].len = cpu_to_le32(l | SGTEND); - - } else { - SCpnt->SCp.have_data_in = pci_map_single(data->Pci, - SCpnt->request_buffer, SCpnt->request_bufflen, - SCpnt->sc_data_direction); - - sgt[0].addr = cpu_to_le32(SCpnt->SCp.have_data_in); - sgt[0].len = cpu_to_le32(SCpnt->request_bufflen | SGTEND); /* set end mark */ - - if (SCpnt->request_bufflen > 0x10000) { - nsp32_msg(KERN_ERR, - "can't transfer over 64KB at a time, size=0x%lx", SCpnt->request_bufflen); - return FALSE; - } - nsp32_dbg(NSP32_DEBUG_SGLIST, "single : addr 0x%lx len=0x%lx", - le32_to_cpu(sgt[0].addr), - le32_to_cpu(sgt[0].len )); } return TRUE; @@ -962,7 +922,7 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x " "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x", SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len, - SCpnt->use_sg, SCpnt->request_buffer, SCpnt->request_bufflen); + scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt)); if (data->CurrentSC != NULL) { nsp32_msg(KERN_ERR, "Currentsc != NULL. Cancel this command request"); @@ -994,10 +954,10 @@ static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ data->CurrentSC = SCpnt; SCpnt->SCp.Status = CHECK_CONDITION; SCpnt->SCp.Message = 0; - SCpnt->resid = SCpnt->request_bufflen; + scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); - SCpnt->SCp.ptr = (char *) SCpnt->request_buffer; - SCpnt->SCp.this_residual = SCpnt->request_bufflen; + SCpnt->SCp.ptr = (char *)scsi_sglist(SCpnt); + SCpnt->SCp.this_residual = scsi_bufflen(SCpnt); SCpnt->SCp.buffer = NULL; SCpnt->SCp.buffers_residual = 0; @@ -1210,13 +1170,9 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id) unsigned long flags; int ret; int handled = 0; - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) struct Scsi_Host *host = data->Host; + spin_lock_irqsave(host->host_lock, flags); -#else - spin_lock_irqsave(&io_request_lock, flags); -#endif /* * IRQ check, then enable IRQ mask @@ -1312,7 +1268,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id) } if ((auto_stat & DATA_IN_PHASE) && - (SCpnt->resid > 0) && + (scsi_get_resid(SCpnt) > 0) && ((nsp32_read2(base, FIFO_REST_CNT) & FIFO_REST_MASK) != 0)) { printk( "auto+fifo\n"); //nsp32_pio_read(SCpnt); @@ -1333,7 +1289,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id) nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", nsp32_read4(base, SAVED_SACK_CNT)); - SCpnt->resid = 0; /* all data transfered! */ + scsi_set_resid(SCpnt, 0); /* all data transfered! */ } /* @@ -1480,11 +1436,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id) nsp32_write2(base, IRQ_CONTROL, 0); out2: -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) spin_unlock_irqrestore(host->host_lock, flags); -#else - spin_unlock_irqrestore(&io_request_lock, flags); -#endif nsp32_dbg(NSP32_DEBUG_INTR, "exit"); @@ -1499,28 +1451,15 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id) nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length, length - (pos - buffer));\ } \ } while(0) -static int nsp32_proc_info( -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - struct Scsi_Host *host, -#endif - char *buffer, - char **start, - off_t offset, - int length, -#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - int hostno, -#endif - int inout) + +static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start, + off_t offset, int length, int inout) { char *pos = buffer; int thislength; unsigned long flags; nsp32_hw_data *data; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) int hostno; -#else - struct Scsi_Host *host; -#endif unsigned int base; unsigned char mode_reg; int id, speed; @@ -1531,15 +1470,7 @@ static int nsp32_proc_info( return -EINVAL; } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) hostno = host->host_no; -#else - /* search this HBA host */ - host = scsi_host_hn_get(hostno); - if (host == NULL) { - return -ESRCH; - } -#endif data = (nsp32_hw_data *)host->hostdata; base = host->io_port; @@ -1626,25 +1557,8 @@ static void nsp32_scsi_done(struct scsi_cmnd *SCpnt) nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; - /* - * unmap pci - */ - if (SCpnt->request_bufflen == 0) { - goto skip; - } + scsi_dma_unmap(SCpnt); - if (SCpnt->use_sg) { - pci_unmap_sg(data->Pci, - (struct scatterlist *)SCpnt->request_buffer, - SCpnt->use_sg, SCpnt->sc_data_direction); - } else { - pci_unmap_single(data->Pci, - (u32)SCpnt->SCp.have_data_in, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - } - - skip: /* * clear TRANSFERCONTROL_BM_START */ @@ -1800,7 +1714,7 @@ static int nsp32_busfree_occur(struct scsi_cmnd *SCpnt, unsigned short execph) SCpnt->SCp.Message = 0; nsp32_dbg(NSP32_DEBUG_BUSFREE, "normal end stat=0x%x resid=0x%x\n", - SCpnt->SCp.Status, SCpnt->resid); + SCpnt->SCp.Status, scsi_get_resid(SCpnt)); SCpnt->result = (DID_OK << 16) | (SCpnt->SCp.Message << 8) | (SCpnt->SCp.Status << 0); @@ -1844,7 +1758,7 @@ static void nsp32_adjust_busfree(struct scsi_cmnd *SCpnt, unsigned int s_sacklen unsigned int restlen, sentlen; u32_le len, addr; - nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", SCpnt->resid); + nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", scsi_get_resid(SCpnt)); /* adjust saved SACK count with 4 byte start address boundary */ s_sacklen -= le32_to_cpu(sgt[old_entry].addr) & 3; @@ -1888,12 +1802,12 @@ static void nsp32_adjust_busfree(struct scsi_cmnd *SCpnt, unsigned int s_sacklen return; last: - if (SCpnt->resid < sentlen) { + if (scsi_get_resid(SCpnt) < sentlen) { nsp32_msg(KERN_ERR, "resid underflow"); } - SCpnt->resid -= sentlen; - nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", SCpnt->resid); + scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) - sentlen); + nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", scsi_get_resid(SCpnt)); /* update hostdata and lun */ @@ -2022,7 +1936,7 @@ static void nsp32_restart_autoscsi(struct scsi_cmnd *SCpnt, unsigned short comma transfer = 0; transfer |= (TRANSFER_GO | ALL_COUNTER_CLR); if (data->trans_method & NSP32_TRANSFER_BUSMASTER) { - if (SCpnt->request_bufflen > 0) { + if (scsi_bufflen(SCpnt) > 0) { transfer |= BM_START; } } else if (data->trans_method & NSP32_TRANSFER_MMIO) { @@ -2674,17 +2588,7 @@ static void nsp32_sack_negate(nsp32_hw_data *data) * 0x900-0xbff: (map same 0x800-0x8ff I/O port image repeatedly) * 0xc00-0xfff: CardBus status registers */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) -#define DETECT_OK 0 -#define DETECT_NG 1 -#define PCIDEV pdev static int nsp32_detect(struct pci_dev *pdev) -#else -#define DETECT_OK 1 -#define DETECT_NG 0 -#define PCIDEV (data->Pci) -static int nsp32_detect(struct scsi_host_template *sht) -#endif { struct Scsi_Host *host; /* registered host structure */ struct resource *res; @@ -2697,11 +2601,7 @@ static int nsp32_detect(struct scsi_host_template *sht) /* * register this HBA as SCSI device */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data)); -#else - host = scsi_register(sht, sizeof(nsp32_hw_data)); -#endif if (host == NULL) { nsp32_msg (KERN_ERR, "failed to scsi register"); goto err; @@ -2719,9 +2619,6 @@ static int nsp32_detect(struct scsi_host_template *sht) host->unique_id = data->BaseAddress; host->n_io_port = data->NumAddress; host->base = (unsigned long)data->MmioAddress; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,63)) - scsi_set_pci_device(host, PCIDEV); -#endif data->Host = host; spin_lock_init(&(data->Lock)); @@ -2776,7 +2673,7 @@ static int nsp32_detect(struct scsi_host_template *sht) /* * setup DMA */ - if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) { nsp32_msg (KERN_ERR, "failed to set PCI DMA mask"); goto scsi_unregister; } @@ -2784,7 +2681,7 @@ static int nsp32_detect(struct scsi_host_template *sht) /* * allocate autoparam DMA resource. */ - data->autoparam = pci_alloc_consistent(PCIDEV, sizeof(nsp32_autoparam), &(data->auto_paddr)); + data->autoparam = pci_alloc_consistent(pdev, sizeof(nsp32_autoparam), &(data->auto_paddr)); if (data->autoparam == NULL) { nsp32_msg(KERN_ERR, "failed to allocate DMA memory"); goto scsi_unregister; @@ -2793,7 +2690,7 @@ static int nsp32_detect(struct scsi_host_template *sht) /* * allocate scatter-gather DMA resource. */ - data->sg_list = pci_alloc_consistent(PCIDEV, NSP32_SG_TABLE_SIZE, + data->sg_list = pci_alloc_consistent(pdev, NSP32_SG_TABLE_SIZE, &(data->sg_paddr)); if (data->sg_list == NULL) { nsp32_msg(KERN_ERR, "failed to allocate DMA memory"); @@ -2883,16 +2780,14 @@ static int nsp32_detect(struct scsi_host_template *sht) goto free_irq; } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - ret = scsi_add_host(host, &PCIDEV->dev); + ret = scsi_add_host(host, &pdev->dev); if (ret) { nsp32_msg(KERN_ERR, "failed to add scsi host"); goto free_region; } scsi_scan_host(host); -#endif - pci_set_drvdata(PCIDEV, host); - return DETECT_OK; + pci_set_drvdata(pdev, host); + return 0; free_region: release_region(host->io_port, host->n_io_port); @@ -2901,22 +2796,19 @@ static int nsp32_detect(struct scsi_host_template *sht) free_irq(host->irq, data); free_sg_list: - pci_free_consistent(PCIDEV, NSP32_SG_TABLE_SIZE, + pci_free_consistent(pdev, NSP32_SG_TABLE_SIZE, data->sg_list, data->sg_paddr); free_autoparam: - pci_free_consistent(PCIDEV, sizeof(nsp32_autoparam), + pci_free_consistent(pdev, sizeof(nsp32_autoparam), data->autoparam, data->auto_paddr); scsi_unregister: scsi_host_put(host); err: - return DETECT_NG; + return 1; } -#undef DETECT_OK -#undef DETECT_NG -#undef PCIDEV static int nsp32_release(struct Scsi_Host *host) { @@ -3525,11 +3417,7 @@ static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_i pci_set_master(pdev); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) ret = nsp32_detect(pdev); -#else - ret = scsi_register_host(&nsp32_template); -#endif nsp32_msg(KERN_INFO, "irq: %i mmio: %p+0x%lx slot: %s model: %s", pdev->irq, @@ -3544,25 +3432,17 @@ static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_i static void __devexit nsp32_remove(struct pci_dev *pdev) { -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) struct Scsi_Host *host = pci_get_drvdata(pdev); -#endif nsp32_dbg(NSP32_DEBUG_REGISTER, "enter"); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) scsi_remove_host(host); nsp32_release(host); scsi_host_put(host); -#else - scsi_unregister_host(&nsp32_template); -#endif } - - static struct pci_driver nsp32_driver = { .name = "nsp32", .id_table = nsp32_pci_table, diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index ffe75c431b25..2695b7187b2f 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -370,8 +370,6 @@ SYM53C500_intr(int irq, void *dev_id) DEB(unsigned char seq_reg;) unsigned char status, int_reg; unsigned char pio_status; - struct scatterlist *sglist; - unsigned int sgcount; int port_base = dev->io_port; struct sym53c500_data *data = (struct sym53c500_data *)dev->hostdata; @@ -434,20 +432,19 @@ SYM53C500_intr(int irq, void *dev_id) switch (status & 0x07) { /* scsi phase */ case 0x00: /* DATA-OUT */ if (int_reg & 0x10) { /* Target requesting info transfer */ + struct scatterlist *sg; + int i; + curSC->SCp.phase = data_out; VDEB(printk("SYM53C500: Data-Out phase\n")); outb(FLUSH_FIFO, port_base + CMD_REG); - LOAD_DMA_COUNT(port_base, curSC->request_bufflen); /* Max transfer size */ + LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */ outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG); - if (!curSC->use_sg) /* Don't use scatter-gather */ - SYM53C500_pio_write(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen); - else { /* use scatter-gather */ - sgcount = curSC->use_sg; - sglist = curSC->request_buffer; - while (sgcount--) { - SYM53C500_pio_write(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length); - sglist++; - } + + scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) { + SYM53C500_pio_write(fast_pio, port_base, + page_address(sg->page) + sg->offset, + sg->length); } REG0(port_base); } @@ -455,20 +452,19 @@ SYM53C500_intr(int irq, void *dev_id) case 0x01: /* DATA-IN */ if (int_reg & 0x10) { /* Target requesting info transfer */ + struct scatterlist *sg; + int i; + curSC->SCp.phase = data_in; VDEB(printk("SYM53C500: Data-In phase\n")); outb(FLUSH_FIFO, port_base + CMD_REG); - LOAD_DMA_COUNT(port_base, curSC->request_bufflen); /* Max transfer size */ + LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */ outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG); - if (!curSC->use_sg) /* Don't use scatter-gather */ - SYM53C500_pio_read(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen); - else { /* Use scatter-gather */ - sgcount = curSC->use_sg; - sglist = curSC->request_buffer; - while (sgcount--) { - SYM53C500_pio_read(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length); - sglist++; - } + + scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) { + SYM53C500_pio_read(fast_pio, port_base, + page_address(sg->page) + sg->offset, + sg->length); } REG0(port_base); } @@ -578,7 +574,7 @@ SYM53C500_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, - SCpnt->device->lun, SCpnt->request_bufflen)); + SCpnt->device->lun, scsi_bufflen(SCpnt))); VDEB(for (i = 0; i < SCpnt->cmd_len; i++) printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ca463469063d..0f04258becbf 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1633,7 +1633,7 @@ struct qla_init_msix_entry { uint16_t entry; uint16_t index; const char *name; - irqreturn_t (*handler)(int, void *); + irq_handler_t handler; }; static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = { diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c index 6437d024b0dd..fcc184cd066d 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c @@ -6,176 +6,9 @@ */ #include "ql4_def.h" -#include <scsi/scsi_dbg.h> - -#if 0 - -static void qla4xxx_print_srb_info(struct srb * srb) -{ - printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags); - printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n", - __func__, srb->cmd, (unsigned long) srb->dma_handle); - printk("%s: fw_ddb_index = %d, lun = %d\n", - __func__, srb->fw_ddb_index, srb->cmd->device->lun); - printk("%s: iocb_tov = %d\n", - __func__, srb->iocb_tov); - printk("%s: cc_stat = 0x%x, r_start = 0x%lx, u_start = 0x%lx\n\n", - __func__, srb->cc_stat, srb->r_start, srb->u_start); -} - -void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd) -{ - printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble); - printk(" b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n", - cmd->device->channel, cmd->device->id, cmd->device->lun, - cmd->cmd_len); - scsi_print_command(cmd); - printk(" seg_cnt = %d\n", cmd->use_sg); - printk(" request buffer = 0x%p, request buffer len = 0x%x\n", - cmd->request_buffer, cmd->request_bufflen); - if (cmd->use_sg) { - struct scatterlist *sg; - sg = (struct scatterlist *)cmd->request_buffer; - printk(" SG buffer: \n"); - qla4xxx_dump_buffer((caddr_t) sg, - (cmd->use_sg * sizeof(*sg))); - } - printk(" tag = %d, transfersize = 0x%x \n", cmd->tag, - cmd->transfersize); - printk(" Pid = %d, SP = 0x%p\n", (int)cmd->pid, cmd->SCp.ptr); - printk(" underflow size = 0x%x, direction=0x%x\n", cmd->underflow, - cmd->sc_data_direction); - printk(" Current time (jiffies) = 0x%lx, " - "timeout expires = 0x%lx\n", jiffies, cmd->eh_timeout.expires); - qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr); -} - -void __dump_registers(struct scsi_qla_host *ha) -{ - uint8_t i; - for (i = 0; i < MBOX_REG_COUNT; i++) { - printk(KERN_INFO "0x%02X mailbox[%d] = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, mailbox[i]), i, - readw(&ha->reg->mailbox[i])); - } - printk(KERN_INFO "0x%02X flash_address = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, flash_address), - readw(&ha->reg->flash_address)); - printk(KERN_INFO "0x%02X flash_data = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, flash_data), - readw(&ha->reg->flash_data)); - printk(KERN_INFO "0x%02X ctrl_status = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, ctrl_status), - readw(&ha->reg->ctrl_status)); - if (is_qla4010(ha)) { - printk(KERN_INFO "0x%02X nvram = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, u1.isp4010.nvram), - readw(&ha->reg->u1.isp4010.nvram)); - } - - else if (is_qla4022(ha) | is_qla4032(ha)) { - printk(KERN_INFO "0x%02X intr_mask = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u1.isp4022.intr_mask), - readw(&ha->reg->u1.isp4022.intr_mask)); - printk(KERN_INFO "0x%02X nvram = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, u1.isp4022.nvram), - readw(&ha->reg->u1.isp4022.nvram)); - printk(KERN_INFO "0x%02X semaphore = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u1.isp4022.semaphore), - readw(&ha->reg->u1.isp4022.semaphore)); - } - printk(KERN_INFO "0x%02X req_q_in = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, req_q_in), - readw(&ha->reg->req_q_in)); - printk(KERN_INFO "0x%02X rsp_q_out = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, rsp_q_out), - readw(&ha->reg->rsp_q_out)); - if (is_qla4010(ha)) { - printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4010.ext_hw_conf), - readw(&ha->reg->u2.isp4010.ext_hw_conf)); - printk(KERN_INFO "0x%02X port_ctrl = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4010.port_ctrl), - readw(&ha->reg->u2.isp4010.port_ctrl)); - printk(KERN_INFO "0x%02X port_status = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4010.port_status), - readw(&ha->reg->u2.isp4010.port_status)); - printk(KERN_INFO "0x%02X req_q_out = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4010.req_q_out), - readw(&ha->reg->u2.isp4010.req_q_out)); - printk(KERN_INFO "0x%02X gp_out = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_out), - readw(&ha->reg->u2.isp4010.gp_out)); - printk(KERN_INFO "0x%02X gp_in = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_in), - readw(&ha->reg->u2.isp4010.gp_in)); - printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4010.port_err_status), - readw(&ha->reg->u2.isp4010.port_err_status)); - } - - else if (is_qla4022(ha) | is_qla4032(ha)) { - printk(KERN_INFO "Page 0 Registers:\n"); - printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4022.p0.ext_hw_conf), - readw(&ha->reg->u2.isp4022.p0.ext_hw_conf)); - printk(KERN_INFO "0x%02X port_ctrl = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4022.p0.port_ctrl), - readw(&ha->reg->u2.isp4022.p0.port_ctrl)); - printk(KERN_INFO "0x%02X port_status = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4022.p0.port_status), - readw(&ha->reg->u2.isp4022.p0.port_status)); - printk(KERN_INFO "0x%02X gp_out = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4022.p0.gp_out), - readw(&ha->reg->u2.isp4022.p0.gp_out)); - printk(KERN_INFO "0x%02X gp_in = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, u2.isp4022.p0.gp_in), - readw(&ha->reg->u2.isp4022.p0.gp_in)); - printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4022.p0.port_err_status), - readw(&ha->reg->u2.isp4022.p0.port_err_status)); - printk(KERN_INFO "Page 1 Registers:\n"); - writel(HOST_MEM_CFG_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT), - &ha->reg->ctrl_status); - printk(KERN_INFO "0x%02X req_q_out = 0x%08X\n", - (uint8_t) offsetof(struct isp_reg, - u2.isp4022.p1.req_q_out), - readw(&ha->reg->u2.isp4022.p1.req_q_out)); - writel(PORT_CTRL_STAT_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT), - &ha->reg->ctrl_status); - } -} - -void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha) -{ - unsigned long flags = 0; - int i = 0; - spin_lock_irqsave(&ha->hardware_lock, flags); - for (i = 1; i < MBOX_REG_COUNT; i++) - printk(KERN_INFO " Mailbox[%d] = %08x\n", i, - readw(&ha->reg->mailbox[i])); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - -void qla4xxx_dump_registers(struct scsi_qla_host *ha) -{ - unsigned long flags = 0; - spin_lock_irqsave(&ha->hardware_lock, flags); - __dump_registers(ha); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" void qla4xxx_dump_buffer(void *b, uint32_t size) { @@ -198,4 +31,3 @@ void qla4xxx_dump_buffer(void *b, uint32_t size) printk(KERN_DEBUG "\n"); } -#endif /* 0 */ diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 6f4cf2dd2f4a..accaf690eaf0 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -122,8 +122,7 @@ #define ISCSI_IPADDR_SIZE 4 /* IP address size */ #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alais name size */ -#define ISCSI_NAME_SIZE 255 /* ISCSI Name size - - * usually a string */ +#define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ #define LSDW(x) ((u32)((u64)(x))) #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) @@ -187,9 +186,21 @@ struct srb { u_long u_start; /* Time when we handed the cmd to F/W */ }; - /* - * Device Database (DDB) structure - */ +/* + * Asynchronous Event Queue structure + */ +struct aen { + uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; +}; + +struct ql4_aen_log { + int count; + struct aen entry[MAX_AEN_ENTRIES]; +}; + +/* + * Device Database (DDB) structure + */ struct ddb_entry { struct list_head list; /* ddb list */ struct scsi_qla_host *ha; @@ -254,13 +265,6 @@ struct ddb_entry { #define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */ #define DF_FO_MASKED 3 -/* - * Asynchronous Event Queue structure - */ -struct aen { - uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; -}; - #include "ql4_fw.h" #include "ql4_nvram.h" @@ -270,31 +274,31 @@ struct aen { */ struct scsi_qla_host { /* Linux adapter configuration data */ - struct Scsi_Host *host; /* pointer to host data */ - uint32_t tot_ddbs; unsigned long flags; -#define AF_ONLINE 0 /* 0x00000001 */ -#define AF_INIT_DONE 1 /* 0x00000002 */ -#define AF_MBOX_COMMAND 2 /* 0x00000004 */ -#define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ -#define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */ -#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ -#define AF_LINK_UP 8 /* 0x00000100 */ -#define AF_IRQ_ATTACHED 10 /* 0x00000400 */ -#define AF_ISNS_CMD_IN_PROCESS 12 /* 0x00001000 */ -#define AF_ISNS_CMD_DONE 13 /* 0x00002000 */ +#define AF_ONLINE 0 /* 0x00000001 */ +#define AF_INIT_DONE 1 /* 0x00000002 */ +#define AF_MBOX_COMMAND 2 /* 0x00000004 */ +#define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ +#define AF_INTERRUPTS_ON 6 /* 0x00000040 */ +#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ +#define AF_LINK_UP 8 /* 0x00000100 */ +#define AF_IRQ_ATTACHED 10 /* 0x00000400 */ +#define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ unsigned long dpc_flags; -#define DPC_RESET_HA 1 /* 0x00000002 */ -#define DPC_RETRY_RESET_HA 2 /* 0x00000004 */ -#define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */ -#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */ -#define DPC_RESET_HA_INTR 5 /* 0x00000020 */ -#define DPC_ISNS_RESTART 7 /* 0x00000080 */ -#define DPC_AEN 9 /* 0x00000200 */ -#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ +#define DPC_RESET_HA 1 /* 0x00000002 */ +#define DPC_RETRY_RESET_HA 2 /* 0x00000004 */ +#define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */ +#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */ +#define DPC_RESET_HA_INTR 5 /* 0x00000020 */ +#define DPC_ISNS_RESTART 7 /* 0x00000080 */ +#define DPC_AEN 9 /* 0x00000200 */ +#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ + + struct Scsi_Host *host; /* pointer to host data */ + uint32_t tot_ddbs; uint16_t iocb_cnt; uint16_t iocb_hiwat; @@ -344,6 +348,7 @@ struct scsi_qla_host { uint32_t firmware_version[2]; uint32_t patch_number; uint32_t build_number; + uint32_t board_id; /* --- From Init_FW --- */ /* init_cb_t *init_cb; */ @@ -363,7 +368,6 @@ struct scsi_qla_host { /* --- From GetFwState --- */ uint32_t firmware_state; - uint32_t board_id; uint32_t addl_fw_state; /* Linux kernel thread */ @@ -414,6 +418,8 @@ struct scsi_qla_host { uint16_t aen_out; struct aen aen_q[MAX_AEN_ENTRIES]; + struct ql4_aen_log aen_log;/* tracks all aens */ + /* This mutex protects several threads to do mailbox commands * concurrently. */ @@ -585,10 +591,4 @@ static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a) #define FLUSH_DDB_CHANGED_AENS 1 #define RELOGIN_DDB_CHANGED_AENS 2 -#include "ql4_version.h" -#include "ql4_glbl.h" -#include "ql4_dbg.h" -#include "ql4_inline.h" - - #endif /*_QLA4XXX_H */ diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 4eea8c571916..9bb3d1d2a925 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -20,143 +20,23 @@ *************************************************************************/ struct port_ctrl_stat_regs { - __le32 ext_hw_conf; /* 80 x50 R/W */ - __le32 intChipConfiguration; /* 84 x54 */ - __le32 port_ctrl; /* 88 x58 */ - __le32 port_status; /* 92 x5c */ - __le32 HostPrimMACHi; /* 96 x60 */ - __le32 HostPrimMACLow; /* 100 x64 */ - __le32 HostSecMACHi; /* 104 x68 */ - __le32 HostSecMACLow; /* 108 x6c */ - __le32 EPPrimMACHi; /* 112 x70 */ - __le32 EPPrimMACLow; /* 116 x74 */ - __le32 EPSecMACHi; /* 120 x78 */ - __le32 EPSecMACLow; /* 124 x7c */ - __le32 HostPrimIPHi; /* 128 x80 */ - __le32 HostPrimIPMidHi; /* 132 x84 */ - __le32 HostPrimIPMidLow; /* 136 x88 */ - __le32 HostPrimIPLow; /* 140 x8c */ - __le32 HostSecIPHi; /* 144 x90 */ - __le32 HostSecIPMidHi; /* 148 x94 */ - __le32 HostSecIPMidLow; /* 152 x98 */ - __le32 HostSecIPLow; /* 156 x9c */ - __le32 EPPrimIPHi; /* 160 xa0 */ - __le32 EPPrimIPMidHi; /* 164 xa4 */ - __le32 EPPrimIPMidLow; /* 168 xa8 */ - __le32 EPPrimIPLow; /* 172 xac */ - __le32 EPSecIPHi; /* 176 xb0 */ - __le32 EPSecIPMidHi; /* 180 xb4 */ - __le32 EPSecIPMidLow; /* 184 xb8 */ - __le32 EPSecIPLow; /* 188 xbc */ - __le32 IPReassemblyTimeout; /* 192 xc0 */ - __le32 EthMaxFramePayload; /* 196 xc4 */ - __le32 TCPMaxWindowSize; /* 200 xc8 */ - __le32 TCPCurrentTimestampHi; /* 204 xcc */ - __le32 TCPCurrentTimestampLow; /* 208 xd0 */ - __le32 LocalRAMAddress; /* 212 xd4 */ - __le32 LocalRAMData; /* 216 xd8 */ - __le32 PCSReserved1; /* 220 xdc */ - __le32 gp_out; /* 224 xe0 */ - __le32 gp_in; /* 228 xe4 */ - __le32 ProbeMuxAddr; /* 232 xe8 */ - __le32 ProbeMuxData; /* 236 xec */ - __le32 ERMQueueBaseAddr0; /* 240 xf0 */ - __le32 ERMQueueBaseAddr1; /* 244 xf4 */ - __le32 MACConfiguration; /* 248 xf8 */ - __le32 port_err_status; /* 252 xfc COR */ + __le32 ext_hw_conf; /* 0x50 R/W */ + __le32 rsrvd0; /* 0x54 */ + __le32 port_ctrl; /* 0x58 */ + __le32 port_status; /* 0x5c */ + __le32 rsrvd1[32]; /* 0x60-0xdf */ + __le32 gp_out; /* 0xe0 */ + __le32 gp_in; /* 0xe4 */ + __le32 rsrvd2[5]; /* 0xe8-0xfb */ + __le32 port_err_status; /* 0xfc */ }; struct host_mem_cfg_regs { - __le32 NetRequestQueueOut; /* 80 x50 */ - __le32 NetRequestQueueOutAddrHi; /* 84 x54 */ - __le32 NetRequestQueueOutAddrLow; /* 88 x58 */ - __le32 NetRequestQueueBaseAddrHi; /* 92 x5c */ - __le32 NetRequestQueueBaseAddrLow; /* 96 x60 */ - __le32 NetRequestQueueLength; /* 100 x64 */ - __le32 NetResponseQueueIn; /* 104 x68 */ - __le32 NetResponseQueueInAddrHi; /* 108 x6c */ - __le32 NetResponseQueueInAddrLow; /* 112 x70 */ - __le32 NetResponseQueueBaseAddrHi; /* 116 x74 */ - __le32 NetResponseQueueBaseAddrLow; /* 120 x78 */ - __le32 NetResponseQueueLength; /* 124 x7c */ - __le32 req_q_out; /* 128 x80 */ - __le32 RequestQueueOutAddrHi; /* 132 x84 */ - __le32 RequestQueueOutAddrLow; /* 136 x88 */ - __le32 RequestQueueBaseAddrHi; /* 140 x8c */ - __le32 RequestQueueBaseAddrLow; /* 144 x90 */ - __le32 RequestQueueLength; /* 148 x94 */ - __le32 ResponseQueueIn; /* 152 x98 */ - __le32 ResponseQueueInAddrHi; /* 156 x9c */ - __le32 ResponseQueueInAddrLow; /* 160 xa0 */ - __le32 ResponseQueueBaseAddrHi; /* 164 xa4 */ - __le32 ResponseQueueBaseAddrLow; /* 168 xa8 */ - __le32 ResponseQueueLength; /* 172 xac */ - __le32 NetRxLargeBufferQueueOut; /* 176 xb0 */ - __le32 NetRxLargeBufferQueueBaseAddrHi; /* 180 xb4 */ - __le32 NetRxLargeBufferQueueBaseAddrLow; /* 184 xb8 */ - __le32 NetRxLargeBufferQueueLength; /* 188 xbc */ - __le32 NetRxLargeBufferLength; /* 192 xc0 */ - __le32 NetRxSmallBufferQueueOut; /* 196 xc4 */ - __le32 NetRxSmallBufferQueueBaseAddrHi; /* 200 xc8 */ - __le32 NetRxSmallBufferQueueBaseAddrLow; /* 204 xcc */ - __le32 NetRxSmallBufferQueueLength; /* 208 xd0 */ - __le32 NetRxSmallBufferLength; /* 212 xd4 */ - __le32 HMCReserved0[10]; /* 216 xd8 */ + __le32 rsrvd0[12]; /* 0x50-0x79 */ + __le32 req_q_out; /* 0x80 */ + __le32 rsrvd1[31]; /* 0x84-0xFF */ }; -struct local_ram_cfg_regs { - __le32 BufletSize; /* 80 x50 */ - __le32 BufletMaxCount; /* 84 x54 */ - __le32 BufletCurrCount; /* 88 x58 */ - __le32 BufletPauseThresholdCount; /* 92 x5c */ - __le32 BufletTCPWinThresholdHi; /* 96 x60 */ - __le32 BufletTCPWinThresholdLow; /* 100 x64 */ - __le32 IPHashTableBaseAddr; /* 104 x68 */ - __le32 IPHashTableSize; /* 108 x6c */ - __le32 TCPHashTableBaseAddr; /* 112 x70 */ - __le32 TCPHashTableSize; /* 116 x74 */ - __le32 NCBAreaBaseAddr; /* 120 x78 */ - __le32 NCBMaxCount; /* 124 x7c */ - __le32 NCBCurrCount; /* 128 x80 */ - __le32 DRBAreaBaseAddr; /* 132 x84 */ - __le32 DRBMaxCount; /* 136 x88 */ - __le32 DRBCurrCount; /* 140 x8c */ - __le32 LRCReserved[28]; /* 144 x90 */ -}; - -struct prot_stat_regs { - __le32 MACTxFrameCount; /* 80 x50 R */ - __le32 MACTxByteCount; /* 84 x54 R */ - __le32 MACRxFrameCount; /* 88 x58 R */ - __le32 MACRxByteCount; /* 92 x5c R */ - __le32 MACCRCErrCount; /* 96 x60 R */ - __le32 MACEncErrCount; /* 100 x64 R */ - __le32 MACRxLengthErrCount; /* 104 x68 R */ - __le32 IPTxPacketCount; /* 108 x6c R */ - __le32 IPTxByteCount; /* 112 x70 R */ - __le32 IPTxFragmentCount; /* 116 x74 R */ - __le32 IPRxPacketCount; /* 120 x78 R */ - __le32 IPRxByteCount; /* 124 x7c R */ - __le32 IPRxFragmentCount; /* 128 x80 R */ - __le32 IPDatagramReassemblyCount; /* 132 x84 R */ - __le32 IPV6RxPacketCount; /* 136 x88 R */ - __le32 IPErrPacketCount; /* 140 x8c R */ - __le32 IPReassemblyErrCount; /* 144 x90 R */ - __le32 TCPTxSegmentCount; /* 148 x94 R */ - __le32 TCPTxByteCount; /* 152 x98 R */ - __le32 TCPRxSegmentCount; /* 156 x9c R */ - __le32 TCPRxByteCount; /* 160 xa0 R */ - __le32 TCPTimerExpCount; /* 164 xa4 R */ - __le32 TCPRxAckCount; /* 168 xa8 R */ - __le32 TCPTxAckCount; /* 172 xac R */ - __le32 TCPRxErrOOOCount; /* 176 xb0 R */ - __le32 PSReserved0; /* 180 xb4 */ - __le32 TCPRxWindowProbeUpdateCount; /* 184 xb8 R */ - __le32 ECCErrCorrectionCount; /* 188 xbc R */ - __le32 PSReserved1[16]; /* 192 xc0 */ -}; - - /* remote register set (access via PCI memory read/write) */ struct isp_reg { #define MBOX_REG_COUNT 8 @@ -207,11 +87,7 @@ struct isp_reg { union { struct port_ctrl_stat_regs p0; struct host_mem_cfg_regs p1; - struct local_ram_cfg_regs p2; - struct prot_stat_regs p3; - __le32 r_union[44]; }; - } __attribute__ ((packed)) isp4022; } u2; }; /* 256 x100 */ @@ -296,6 +172,7 @@ static inline uint32_t clr_rmask(uint32_t val) /* ISP Semaphore definitions */ /* ISP General Purpose Output definitions */ +#define GPOR_TOPCAT_RESET 0x00000004 /* shadow registers (DMA'd from HA to system memory. read only) */ struct shadow_regs { @@ -337,6 +214,7 @@ union external_hw_config_reg { /* Mailbox command definitions */ #define MBOX_CMD_ABOUT_FW 0x0009 +#define MBOX_CMD_PING 0x000B #define MBOX_CMD_LUN_RESET 0x0016 #define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E #define MBOX_CMD_GET_FW_STATUS 0x001F @@ -364,6 +242,17 @@ union external_hw_config_reg { #define MBOX_CMD_GET_FW_STATE 0x0069 #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 +#define MBOX_CMD_SET_ACB 0x0088 +#define MBOX_CMD_GET_ACB 0x0089 +#define MBOX_CMD_DISABLE_ACB 0x008A +#define MBOX_CMD_GET_IPV6_NEIGHBOR_CACHE 0x008B +#define MBOX_CMD_GET_IPV6_DEST_CACHE 0x008C +#define MBOX_CMD_GET_IPV6_DEF_ROUTER_LIST 0x008D +#define MBOX_CMD_GET_IPV6_LCL_PREFIX_LIST 0x008E +#define MBOX_CMD_SET_IPV6_NEIGHBOR_CACHE 0x0090 +#define MBOX_CMD_GET_IP_ADDR_STATE 0x0091 +#define MBOX_CMD_SEND_IPV6_ROUTER_SOL 0x0092 +#define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093 /* Mailbox 1 */ #define FW_STATE_READY 0x0000 @@ -409,6 +298,16 @@ union external_hw_config_reg { #define MBOX_ASTS_DHCP_LEASE_EXPIRED 0x801D #define MBOX_ASTS_DHCP_LEASE_ACQUIRED 0x801F #define MBOX_ASTS_ISNS_UNSOLICITED_PDU_RECEIVED 0x8021 +#define MBOX_ASTS_DUPLICATE_IP 0x8025 +#define MBOX_ASTS_ARP_COMPLETE 0x8026 +#define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027 +#define MBOX_ASTS_RESPONSE_QUEUE_FULL 0x8028 +#define MBOX_ASTS_IP_ADDR_STATE_CHANGED 0x8029 +#define MBOX_ASTS_IPV6_PREFIX_EXPIRED 0x802B +#define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED 0x802C +#define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED 0x802D +#define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD 0x802E + #define ISNS_EVENT_DATA_RECEIVED 0x0000 #define ISNS_EVENT_CONNECTION_OPENED 0x0001 #define ISNS_EVENT_CONNECTION_FAILED 0x0002 @@ -418,137 +317,166 @@ union external_hw_config_reg { /*************************************************************************/ /* Host Adapter Initialization Control Block (from host) */ -struct init_fw_ctrl_blk { - uint8_t Version; /* 00 */ - uint8_t Control; /* 01 */ +struct addr_ctrl_blk { + uint8_t version; /* 00 */ + uint8_t control; /* 01 */ - uint16_t FwOptions; /* 02-03 */ + uint16_t fw_options; /* 02-03 */ #define FWOPT_HEARTBEAT_ENABLE 0x1000 #define FWOPT_SESSION_MODE 0x0040 #define FWOPT_INITIATOR_MODE 0x0020 #define FWOPT_TARGET_MODE 0x0010 - uint16_t ExecThrottle; /* 04-05 */ - uint8_t RetryCount; /* 06 */ - uint8_t RetryDelay; /* 07 */ - uint16_t MaxEthFrPayloadSize; /* 08-09 */ - uint16_t AddFwOptions; /* 0A-0B */ - - uint8_t HeartbeatInterval; /* 0C */ - uint8_t InstanceNumber; /* 0D */ - uint16_t RES2; /* 0E-0F */ - uint16_t ReqQConsumerIndex; /* 10-11 */ - uint16_t ComplQProducerIndex; /* 12-13 */ - uint16_t ReqQLen; /* 14-15 */ - uint16_t ComplQLen; /* 16-17 */ - uint32_t ReqQAddrLo; /* 18-1B */ - uint32_t ReqQAddrHi; /* 1C-1F */ - uint32_t ComplQAddrLo; /* 20-23 */ - uint32_t ComplQAddrHi; /* 24-27 */ - uint32_t ShadowRegBufAddrLo; /* 28-2B */ - uint32_t ShadowRegBufAddrHi; /* 2C-2F */ - - uint16_t iSCSIOptions; /* 30-31 */ - - uint16_t TCPOptions; /* 32-33 */ - - uint16_t IPOptions; /* 34-35 */ - - uint16_t MaxPDUSize; /* 36-37 */ - uint16_t RcvMarkerInt; /* 38-39 */ - uint16_t SndMarkerInt; /* 3A-3B */ - uint16_t InitMarkerlessInt; /* 3C-3D */ - uint16_t FirstBurstSize; /* 3E-3F */ - uint16_t DefaultTime2Wait; /* 40-41 */ - uint16_t DefaultTime2Retain; /* 42-43 */ - uint16_t MaxOutStndngR2T; /* 44-45 */ - uint16_t KeepAliveTimeout; /* 46-47 */ - uint16_t PortNumber; /* 48-49 */ - uint16_t MaxBurstSize; /* 4A-4B */ - uint32_t RES4; /* 4C-4F */ - uint8_t IPAddr[4]; /* 50-53 */ - uint8_t RES5[12]; /* 54-5F */ - uint8_t SubnetMask[4]; /* 60-63 */ - uint8_t RES6[12]; /* 64-6F */ - uint8_t GatewayIPAddr[4]; /* 70-73 */ - uint8_t RES7[12]; /* 74-7F */ - uint8_t PriDNSIPAddr[4]; /* 80-83 */ - uint8_t SecDNSIPAddr[4]; /* 84-87 */ - uint8_t RES8[8]; /* 88-8F */ - uint8_t Alias[32]; /* 90-AF */ - uint8_t TargAddr[8]; /* B0-B7 *//* /FIXME: Remove?? */ - uint8_t CHAPNameSecretsTable[8]; /* B8-BF */ - uint8_t EthernetMACAddr[6]; /* C0-C5 */ - uint16_t TargetPortalGroup; /* C6-C7 */ - uint8_t SendScale; /* C8 */ - uint8_t RecvScale; /* C9 */ - uint8_t TypeOfService; /* CA */ - uint8_t Time2Live; /* CB */ - uint16_t VLANPriority; /* CC-CD */ - uint16_t Reserved8; /* CE-CF */ - uint8_t SecIPAddr[4]; /* D0-D3 */ - uint8_t Reserved9[12]; /* D4-DF */ - uint8_t iSNSIPAddr[4]; /* E0-E3 */ - uint16_t iSNSServerPortNumber; /* E4-E5 */ - uint8_t Reserved10[10]; /* E6-EF */ - uint8_t SLPDAIPAddr[4]; /* F0-F3 */ - uint8_t Reserved11[12]; /* F4-FF */ - uint8_t iSCSINameString[256]; /* 100-1FF */ + uint16_t exec_throttle; /* 04-05 */ + uint8_t zio_count; /* 06 */ + uint8_t res0; /* 07 */ + uint16_t eth_mtu_size; /* 08-09 */ + uint16_t add_fw_options; /* 0A-0B */ + + uint8_t hb_interval; /* 0C */ + uint8_t inst_num; /* 0D */ + uint16_t res1; /* 0E-0F */ + uint16_t rqq_consumer_idx; /* 10-11 */ + uint16_t compq_producer_idx; /* 12-13 */ + uint16_t rqq_len; /* 14-15 */ + uint16_t compq_len; /* 16-17 */ + uint32_t rqq_addr_lo; /* 18-1B */ + uint32_t rqq_addr_hi; /* 1C-1F */ + uint32_t compq_addr_lo; /* 20-23 */ + uint32_t compq_addr_hi; /* 24-27 */ + uint32_t shdwreg_addr_lo; /* 28-2B */ + uint32_t shdwreg_addr_hi; /* 2C-2F */ + + uint16_t iscsi_opts; /* 30-31 */ + uint16_t ipv4_tcp_opts; /* 32-33 */ + uint16_t ipv4_ip_opts; /* 34-35 */ + + uint16_t iscsi_max_pdu_size; /* 36-37 */ + uint8_t ipv4_tos; /* 38 */ + uint8_t ipv4_ttl; /* 39 */ + uint8_t acb_version; /* 3A */ + uint8_t res2; /* 3B */ + uint16_t def_timeout; /* 3C-3D */ + uint16_t iscsi_fburst_len; /* 3E-3F */ + uint16_t iscsi_def_time2wait; /* 40-41 */ + uint16_t iscsi_def_time2retain; /* 42-43 */ + uint16_t iscsi_max_outstnd_r2t; /* 44-45 */ + uint16_t conn_ka_timeout; /* 46-47 */ + uint16_t ipv4_port; /* 48-49 */ + uint16_t iscsi_max_burst_len; /* 4A-4B */ + uint32_t res5; /* 4C-4F */ + uint8_t ipv4_addr[4]; /* 50-53 */ + uint16_t ipv4_vlan_tag; /* 54-55 */ + uint8_t ipv4_addr_state; /* 56 */ + uint8_t ipv4_cacheid; /* 57 */ + uint8_t res6[8]; /* 58-5F */ + uint8_t ipv4_subnet[4]; /* 60-63 */ + uint8_t res7[12]; /* 64-6F */ + uint8_t ipv4_gw_addr[4]; /* 70-73 */ + uint8_t res8[0xc]; /* 74-7F */ + uint8_t pri_dns_srvr_ip[4];/* 80-83 */ + uint8_t sec_dns_srvr_ip[4];/* 84-87 */ + uint16_t min_eph_port; /* 88-89 */ + uint16_t max_eph_port; /* 8A-8B */ + uint8_t res9[4]; /* 8C-8F */ + uint8_t iscsi_alias[32];/* 90-AF */ + uint8_t res9_1[0x16]; /* B0-C5 */ + uint16_t tgt_portal_grp;/* C6-C7 */ + uint8_t abort_timer; /* C8 */ + uint8_t ipv4_tcp_wsf; /* C9 */ + uint8_t res10[6]; /* CA-CF */ + uint8_t ipv4_sec_ip_addr[4]; /* D0-D3 */ + uint8_t ipv4_dhcp_vid_len; /* D4 */ + uint8_t ipv4_dhcp_vid[11]; /* D5-DF */ + uint8_t res11[20]; /* E0-F3 */ + uint8_t ipv4_dhcp_alt_cid_len; /* F4 */ + uint8_t ipv4_dhcp_alt_cid[11]; /* F5-FF */ + uint8_t iscsi_name[224]; /* 100-1DF */ + uint8_t res12[32]; /* 1E0-1FF */ + uint32_t cookie; /* 200-203 */ + uint16_t ipv6_port; /* 204-205 */ + uint16_t ipv6_opts; /* 206-207 */ + uint16_t ipv6_addtl_opts; /* 208-209 */ + uint16_t ipv6_tcp_opts; /* 20A-20B */ + uint8_t ipv6_tcp_wsf; /* 20C */ + uint16_t ipv6_flow_lbl; /* 20D-20F */ + uint8_t ipv6_gw_addr[16]; /* 210-21F */ + uint16_t ipv6_vlan_tag; /* 220-221 */ + uint8_t ipv6_lnk_lcl_addr_state;/* 222 */ + uint8_t ipv6_addr0_state; /* 223 */ + uint8_t ipv6_addr1_state; /* 224 */ + uint8_t ipv6_gw_state; /* 225 */ + uint8_t ipv6_traffic_class; /* 226 */ + uint8_t ipv6_hop_limit; /* 227 */ + uint8_t ipv6_if_id[8]; /* 228-22F */ + uint8_t ipv6_addr0[16]; /* 230-23F */ + uint8_t ipv6_addr1[16]; /* 240-24F */ + uint32_t ipv6_nd_reach_time; /* 250-253 */ + uint32_t ipv6_nd_rexmit_timer; /* 254-257 */ + uint32_t ipv6_nd_stale_timeout; /* 258-25B */ + uint8_t ipv6_dup_addr_detect_count; /* 25C */ + uint8_t ipv6_cache_id; /* 25D */ + uint8_t res13[18]; /* 25E-26F */ + uint32_t ipv6_gw_advrt_mtu; /* 270-273 */ + uint8_t res14[140]; /* 274-2FF */ +}; + +struct init_fw_ctrl_blk { + struct addr_ctrl_blk pri; + struct addr_ctrl_blk sec; }; /*************************************************************************/ struct dev_db_entry { - uint8_t options; /* 00 */ + uint16_t options; /* 00-01 */ #define DDB_OPT_DISC_SESSION 0x10 #define DDB_OPT_TARGET 0x02 /* device is a target */ - uint8_t control; /* 01 */ - - uint16_t exeThrottle; /* 02-03 */ - uint16_t exeCount; /* 04-05 */ - uint8_t retryCount; /* 06 */ - uint8_t retryDelay; /* 07 */ - uint16_t iSCSIOptions; /* 08-09 */ - - uint16_t TCPOptions; /* 0A-0B */ - - uint16_t IPOptions; /* 0C-0D */ - - uint16_t maxPDUSize; /* 0E-0F */ - uint16_t rcvMarkerInt; /* 10-11 */ - uint16_t sndMarkerInt; /* 12-13 */ - uint16_t iSCSIMaxSndDataSegLen; /* 14-15 */ - uint16_t firstBurstSize; /* 16-17 */ - uint16_t minTime2Wait; /* 18-19 : RA :default_time2wait */ - uint16_t maxTime2Retain; /* 1A-1B */ - uint16_t maxOutstndngR2T; /* 1C-1D */ - uint16_t keepAliveTimeout; /* 1E-1F */ - uint8_t ISID[6]; /* 20-25 big-endian, must be converted + uint16_t exec_throttle; /* 02-03 */ + uint16_t exec_count; /* 04-05 */ + uint16_t res0; /* 06-07 */ + uint16_t iscsi_options; /* 08-09 */ + uint16_t tcp_options; /* 0A-0B */ + uint16_t ip_options; /* 0C-0D */ + uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */ + uint32_t res1; /* 10-13 */ + uint16_t iscsi_max_snd_data_seg_len; /* 14-15 */ + uint16_t iscsi_first_burst_len; /* 16-17 */ + uint16_t iscsi_def_time2wait; /* 18-19 */ + uint16_t iscsi_def_time2retain; /* 1A-1B */ + uint16_t iscsi_max_outsnd_r2t; /* 1C-1D */ + uint16_t ka_timeout; /* 1E-1F */ + uint8_t isid[6]; /* 20-25 big-endian, must be converted * to little-endian */ - uint16_t TSID; /* 26-27 */ - uint16_t portNumber; /* 28-29 */ - uint16_t maxBurstSize; /* 2A-2B */ - uint16_t taskMngmntTimeout; /* 2C-2D */ - uint16_t reserved1; /* 2E-2F */ - uint8_t ipAddr[0x10]; /* 30-3F */ - uint8_t iSCSIAlias[0x20]; /* 40-5F */ - uint8_t targetAddr[0x20]; /* 60-7F */ - uint8_t userID[0x20]; /* 80-9F */ - uint8_t password[0x20]; /* A0-BF */ - uint8_t iscsiName[0x100]; /* C0-1BF : xxzzy Make this a + uint16_t tsid; /* 26-27 */ + uint16_t port; /* 28-29 */ + uint16_t iscsi_max_burst_len; /* 2A-2B */ + uint16_t def_timeout; /* 2C-2D */ + uint16_t res2; /* 2E-2F */ + uint8_t ip_addr[0x10]; /* 30-3F */ + uint8_t iscsi_alias[0x20]; /* 40-5F */ + uint8_t tgt_addr[0x20]; /* 60-7F */ + uint16_t mss; /* 80-81 */ + uint16_t res3; /* 82-83 */ + uint16_t lcl_port; /* 84-85 */ + uint8_t ipv4_tos; /* 86 */ + uint16_t ipv6_flow_lbl; /* 87-89 */ + uint8_t res4[0x36]; /* 8A-BF */ + uint8_t iscsi_name[0xE0]; /* C0-19F : xxzzy Make this a * pointer to a string so we * don't have to reserve soooo * much RAM */ - uint16_t ddbLink; /* 1C0-1C1 */ - uint16_t CHAPTableIndex; /* 1C2-1C3 */ - uint16_t TargetPortalGroup; /* 1C4-1C5 */ - uint16_t reserved2[2]; /* 1C6-1C7 */ - uint32_t statSN; /* 1C8-1CB */ - uint32_t expStatSN; /* 1CC-1CF */ - uint16_t reserved3[0x2C]; /* 1D0-1FB */ - uint16_t ddbValidCookie; /* 1FC-1FD */ - uint16_t ddbValidSize; /* 1FE-1FF */ + uint8_t ipv6_addr[0x10];/* 1A0-1AF */ + uint8_t res5[0x10]; /* 1B0-1BF */ + uint16_t ddb_link; /* 1C0-1C1 */ + uint16_t chap_tbl_idx; /* 1C2-1C3 */ + uint16_t tgt_portal_grp; /* 1C4-1C5 */ + uint8_t tcp_xmt_wsf; /* 1C6 */ + uint8_t tcp_rcv_wsf; /* 1C7 */ + uint32_t stat_sn; /* 1C8-1CB */ + uint32_t exp_stat_sn; /* 1CC-1CF */ + uint8_t res6[0x30]; /* 1D0-1FF */ }; /*************************************************************************/ diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 5b00cb04e7c0..a3608e028bf6 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -8,6 +8,9 @@ #ifndef __QLA4x_GBL_H #define __QLA4x_GBL_H +struct iscsi_cls_conn; + +void qla4xxx_hw_reset(struct scsi_qla_host *ha); int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb); @@ -58,11 +61,13 @@ int qla4xxx_get_fw_version(struct scsi_qla_host * ha); void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha, uint32_t intr_status); int qla4xxx_init_rings(struct scsi_qla_host * ha); -struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index); +struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, + uint32_t index); void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb); int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, uint32_t fw_ddb_index, uint32_t state); +void qla4xxx_dump_buffer(void *b, uint32_t size); extern int ql4xextended_error_logging; extern int ql4xdiscoverywait; diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 6365df268612..d8c064c2afc3 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -6,6 +6,9 @@ */ #include "ql4_def.h" +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, uint32_t fw_ddb_index); @@ -300,12 +303,12 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) if (!qla4xxx_fw_ready(ha)) return status; - set_bit(AF_ONLINE, &ha->flags); return qla4xxx_get_firmware_status(ha); } static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, - uint32_t fw_ddb_index) + uint32_t fw_ddb_index, + uint32_t *new_tgt) { struct dev_db_entry *fw_ddb_entry = NULL; dma_addr_t fw_ddb_entry_dma; @@ -313,6 +316,7 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, int found = 0; uint32_t device_state; + *new_tgt = 0; /* Make sure the dma buffer is valid */ fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), @@ -337,7 +341,7 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no, __func__, fw_ddb_index)); list_for_each_entry(ddb_entry, &ha->ddb_list, list) { - if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsiName, + if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name, ISCSI_NAME_SIZE) == 0) { found++; break; @@ -348,6 +352,7 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating " "new ddb\n", ha->host_no, __func__, fw_ddb_index)); + *new_tgt = 1; ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); } @@ -409,26 +414,26 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, } status = QLA_SUCCESS; - ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->TSID); + ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid); ddb_entry->task_mgmt_timeout = - le16_to_cpu(fw_ddb_entry->taskMngmntTimeout); + le16_to_cpu(fw_ddb_entry->def_timeout); ddb_entry->CmdSn = 0; - ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exeThrottle); + ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle); ddb_entry->default_relogin_timeout = - le16_to_cpu(fw_ddb_entry->taskMngmntTimeout); - ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->minTime2Wait); + le16_to_cpu(fw_ddb_entry->def_timeout); + ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); /* Update index in case it changed */ ddb_entry->fw_ddb_index = fw_ddb_index; ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry; - ddb_entry->port = le16_to_cpu(fw_ddb_entry->portNumber); - ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->TargetPortalGroup); - memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsiName[0], + ddb_entry->port = le16_to_cpu(fw_ddb_entry->port); + ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); + memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0], min(sizeof(ddb_entry->iscsi_name), - sizeof(fw_ddb_entry->iscsiName))); - memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ipAddr[0], - min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ipAddr))); + sizeof(fw_ddb_entry->iscsi_name))); + memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0], + min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr))); DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n", ha->host_no, __func__, fw_ddb_index, @@ -495,6 +500,7 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) uint32_t ddb_state; uint32_t conn_err, err_code; struct ddb_entry *ddb_entry; + uint32_t new_tgt; dev_info(&ha->pdev->dev, "Initializing DDBs ...\n"); for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; @@ -526,8 +532,19 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) "completed " "or access denied failure\n", ha->host_no, __func__)); - } else + } else { qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0); + if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, + NULL, 0, NULL, &next_fw_ddb_index, + &ddb_state, &conn_err, NULL, NULL) + == QLA_ERROR) { + DEBUG2(printk("scsi%ld: %s:" + "get_ddb_entry %d failed\n", + ha->host_no, + __func__, fw_ddb_index)); + return QLA_ERROR; + } + } } if (ddb_state != DDB_DS_SESSION_ACTIVE) @@ -540,7 +557,7 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) ha->host_no, __func__, fw_ddb_index)); /* Add DDB to internal our ddb list. */ - ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index); + ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt); if (ddb_entry == NULL) { DEBUG2(printk("scsi%ld: %s: Unable to allocate memory " "for device at fw_ddb_index %d\n", @@ -865,21 +882,19 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha) static void qla4x00_pci_config(struct scsi_qla_host *ha) { - uint16_t w, mwi; + uint16_t w; dev_info(&ha->pdev->dev, "Configuring PCI space...\n"); pci_set_master(ha->pdev); - mwi = 0; - if (pci_set_mwi(ha->pdev)) - mwi = PCI_COMMAND_INVALIDATE; + pci_set_mwi(ha->pdev); /* * We want to respect framework's setting of PCI configuration space * command register and also want to make sure that all bits of * interest to us are properly set in command register. */ pci_read_config_word(ha->pdev, PCI_COMMAND, &w); - w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); + w |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; w &= ~PCI_COMMAND_INTX_DISABLE; pci_write_config_word(ha->pdev, PCI_COMMAND, w); } @@ -911,6 +926,9 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) writel(set_rmask(NVR_WRITE_ENABLE), &ha->reg->u1.isp4022.nvram); + writel(2, &ha->reg->mailbox[6]); + readl(&ha->reg->mailbox[6]); + writel(set_rmask(CSR_BOOT_ENABLE), &ha->reg->ctrl_status); readl(&ha->reg->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -958,25 +976,25 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) return status; } -int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha) +int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) { -#define QL4_LOCK_DRVR_WAIT 30 +#define QL4_LOCK_DRVR_WAIT 60 #define QL4_LOCK_DRVR_SLEEP 1 int drvr_wait = QL4_LOCK_DRVR_WAIT; while (drvr_wait) { - if (ql4xxx_lock_drvr(ha) == 0) { + if (ql4xxx_lock_drvr(a) == 0) { ssleep(QL4_LOCK_DRVR_SLEEP); if (drvr_wait) { DEBUG2(printk("scsi%ld: %s: Waiting for " - "Global Init Semaphore(%d)...n", - ha->host_no, + "Global Init Semaphore(%d)...\n", + a->host_no, __func__, drvr_wait)); } drvr_wait -= QL4_LOCK_DRVR_SLEEP; } else { DEBUG2(printk("scsi%ld: %s: Global Init Semaphore " - "acquired.n", ha->host_no, __func__)); + "acquired\n", a->host_no, __func__)); return QLA_SUCCESS; } } @@ -1142,8 +1160,10 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, * the ddb_list and wait for DHCP lease acquired aen to come in * followed by 0x8014 aen" to trigger the tgt discovery process. */ - if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS) + if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS){ + set_bit(AF_ONLINE, &ha->flags); return status; + } /* Skip device discovery if ip and subnet is zero */ if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 || @@ -1177,6 +1197,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, ha->host_no)); } + set_bit(AF_ONLINE, &ha->flags); exit_init_hba: return status; @@ -1193,9 +1214,10 @@ static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha, uint32_t fw_ddb_index) { struct ddb_entry * ddb_entry; + uint32_t new_tgt; /* First allocate a device structure */ - ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index); + ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt); if (ddb_entry == NULL) { DEBUG2(printk(KERN_WARNING "scsi%ld: Unable to allocate memory to add " @@ -1203,6 +1225,18 @@ static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha, return; } + if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) { + /* Target has been bound to a new fw_ddb_index */ + qla4xxx_free_ddb(ha, ddb_entry); + ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); + if (ddb_entry == NULL) { + DEBUG2(printk(KERN_WARNING + "scsi%ld: Unable to allocate memory" + " to add fw_ddb_index %d\n", + ha->host_no, fw_ddb_index)); + return; + } + } if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) == QLA_ERROR) { ha->fw_ddb_index_map[fw_ddb_index] = diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index a216a1781afb..5006ecb3ef5e 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -6,6 +6,10 @@ */ #include "ql4_def.h" +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" + #include <scsi/scsi_tcq.h> @@ -141,11 +145,13 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb, uint16_t avail_dsds; struct data_seg_a64 *cur_dsd; struct scsi_cmnd *cmd; + struct scatterlist *sg; + int i; cmd = srb->cmd; ha = srb->ha; - if (cmd->request_bufflen == 0 || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { /* No data being transferred */ cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0); return; @@ -154,40 +160,27 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb, avail_dsds = COMMAND_SEG; cur_dsd = (struct data_seg_a64 *) & (cmd_entry->dataseg[0]); - /* Load data segments */ - if (cmd->use_sg) { - struct scatterlist *cur_seg; - struct scatterlist *end_seg; - - cur_seg = (struct scatterlist *)cmd->request_buffer; - end_seg = cur_seg + tot_dsds; - while (cur_seg < end_seg) { - dma_addr_t sle_dma; - - /* Allocate additional continuation packets? */ - if (avail_dsds == 0) { - struct continuation_t1_entry *cont_entry; - - cont_entry = qla4xxx_alloc_cont_entry(ha); - cur_dsd = - (struct data_seg_a64 *) - &cont_entry->dataseg[0]; - avail_dsds = CONTINUE_SEG; - } - - sle_dma = sg_dma_address(cur_seg); - cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma)); - cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma)); - cur_dsd->count = cpu_to_le32(sg_dma_len(cur_seg)); - avail_dsds--; - - cur_dsd++; - cur_seg++; + scsi_for_each_sg(cmd, sg, tot_dsds, i) { + dma_addr_t sle_dma; + + /* Allocate additional continuation packets? */ + if (avail_dsds == 0) { + struct continuation_t1_entry *cont_entry; + + cont_entry = qla4xxx_alloc_cont_entry(ha); + cur_dsd = + (struct data_seg_a64 *) + &cont_entry->dataseg[0]; + avail_dsds = CONTINUE_SEG; } - } else { - cur_dsd->base.addrLow = cpu_to_le32(LSDW(srb->dma_handle)); - cur_dsd->base.addrHigh = cpu_to_le32(MSDW(srb->dma_handle)); - cur_dsd->count = cpu_to_le32(cmd->request_bufflen); + + sle_dma = sg_dma_address(sg); + cur_dsd->base.addrLow = cpu_to_le32(LSDW(sle_dma)); + cur_dsd->base.addrHigh = cpu_to_le32(MSDW(sle_dma)); + cur_dsd->count = cpu_to_le32(sg_dma_len(sg)); + avail_dsds--; + + cur_dsd++; } } @@ -204,8 +197,8 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) struct scsi_cmnd *cmd = srb->cmd; struct ddb_entry *ddb_entry; struct command_t3_entry *cmd_entry; - struct scatterlist *sg = NULL; + int nseg; uint16_t tot_dsds; uint16_t req_cnt; @@ -233,24 +226,11 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) index = (uint32_t)cmd->request->tag; /* Calculate the number of request entries needed. */ - if (cmd->use_sg) { - sg = (struct scatterlist *)cmd->request_buffer; - tot_dsds = pci_map_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - if (tot_dsds == 0) - goto queuing_error; - } else if (cmd->request_bufflen) { - dma_addr_t req_dma; - - req_dma = pci_map_single(ha->pdev, cmd->request_buffer, - cmd->request_bufflen, - cmd->sc_data_direction); - if (dma_mapping_error(req_dma)) - goto queuing_error; - - srb->dma_handle = req_dma; - tot_dsds = 1; - } + nseg = scsi_dma_map(cmd); + if (nseg < 0) + goto queuing_error; + tot_dsds = nseg; + req_cnt = qla4xxx_calc_request_entries(tot_dsds); if (ha->req_q_count < (req_cnt + 2)) { @@ -279,7 +259,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) int_to_scsilun(cmd->device->lun, &cmd_entry->lun); cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn); - cmd_entry->ttlByteCnt = cpu_to_le32(cmd->request_bufflen); + cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd)); memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len); cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds); cmd_entry->hdr.entryCount = req_cnt; @@ -289,13 +269,13 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) * transferred, as the data direction bit is sometimed filled * in when there is no data to be transferred */ cmd_entry->control_flags = CF_NO_DATA; - if (cmd->request_bufflen) { + if (scsi_bufflen(cmd)) { if (cmd->sc_data_direction == DMA_TO_DEVICE) cmd_entry->control_flags = CF_WRITE; else if (cmd->sc_data_direction == DMA_FROM_DEVICE) cmd_entry->control_flags = CF_READ; - ha->bytes_xfered += cmd->request_bufflen; + ha->bytes_xfered += scsi_bufflen(cmd); if (ha->bytes_xfered & ~0xFFFFF){ ha->total_mbytes_xferred += ha->bytes_xfered >> 20; ha->bytes_xfered &= 0xFFFFF; @@ -359,14 +339,9 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) return QLA_SUCCESS; queuing_error: + if (tot_dsds) + scsi_dma_unmap(cmd); - if (cmd->use_sg && tot_dsds) { - sg = (struct scatterlist *) cmd->request_buffer; - pci_unmap_sg(ha->pdev, sg, cmd->use_sg, - cmd->sc_data_direction); - } else if (tot_dsds) - pci_unmap_single(ha->pdev, srb->dma_handle, - cmd->request_bufflen, cmd->sc_data_direction); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_ERROR; diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 35b9e36a0e8d..b47bd85f114d 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -6,6 +6,9 @@ */ #include "ql4_def.h" +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" /** * qla2x00_process_completed_request() - Process a Fast Post response. @@ -92,7 +95,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, if (sts_entry->iscsiFlags & (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER)) - cmd->resid = residual; + scsi_set_resid(cmd, residual); cmd->result = DID_OK << 16 | scsi_status; @@ -176,14 +179,14 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, * Firmware detected a SCSI transport underrun * condition */ - cmd->resid = residual; + scsi_set_resid(cmd, residual); DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status " "detected, xferlen = 0x%x, residual = " "0x%x\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__, - cmd->request_bufflen, + scsi_bufflen(cmd), residual)); } @@ -227,7 +230,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) == 0) { cmd->result = DID_BUS_BUSY << 16; - } else if ((cmd->request_bufflen - residual) < + } else if ((scsi_bufflen(cmd) - residual) < cmd->underflow) { /* * Handle mid-layer underflow??? @@ -248,7 +251,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__, - cmd->request_bufflen, residual)); + scsi_bufflen(cmd), residual)); cmd->result = DID_ERROR << 16; } else { @@ -417,6 +420,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, uint32_t mbox_status) { int i; + uint32_t mbox_stat2, mbox_stat3; if ((mbox_status == MBOX_STS_BUSY) || (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) || @@ -437,6 +441,12 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { /* Immediately process the AENs that don't require much work. * Only queue the database_changed AENs */ + if (ha->aen_log.count < MAX_AEN_ENTRIES) { + for (i = 0; i < MBOX_AEN_REG_COUNT; i++) + ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] = + readl(&ha->reg->mailbox[i]); + ha->aen_log.count++; + } switch (mbox_status) { case MBOX_ASTS_SYSTEM_ERROR: /* Log Mailbox registers */ @@ -493,6 +503,16 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, mbox_status)); break; + case MBOX_ASTS_IP_ADDR_STATE_CHANGED: + mbox_stat2 = readl(&ha->reg->mailbox[2]); + mbox_stat3 = readl(&ha->reg->mailbox[3]); + + if ((mbox_stat3 == 5) && (mbox_stat2 == 3)) + set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); + else if ((mbox_stat3 == 2) && (mbox_stat2 == 5)) + set_bit(DPC_RESET_HA, &ha->dpc_flags); + break; + case MBOX_ASTS_MAC_ADDRESS_CHANGED: case MBOX_ASTS_DNS: /* No action */ @@ -518,11 +538,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, /* Queue AEN information and process it in the DPC * routine */ if (ha->aen_q_count > 0) { - /* advance pointer */ - if (ha->aen_in == (MAX_AEN_ENTRIES - 1)) - ha->aen_in = 0; - else - ha->aen_in++; /* decrement available counter */ ha->aen_q_count--; @@ -542,6 +557,10 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, ha->aen_q[ha->aen_in].mbox_sts[2], ha->aen_q[ha->aen_in].mbox_sts[3], ha->aen_q[ha->aen_in]. mbox_sts[4])); + /* advance pointer */ + ha->aen_in++; + if (ha->aen_in == MAX_AEN_ENTRIES) + ha->aen_in = 0; /* The DPC routine will process the aen */ set_bit(DPC_AEN, &ha->dpc_flags); @@ -724,25 +743,24 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) spin_lock_irqsave(&ha->hardware_lock, flags); while (ha->aen_out != ha->aen_in) { - /* Advance pointers for next entry */ - if (ha->aen_out == (MAX_AEN_ENTRIES - 1)) - ha->aen_out = 0; - else - ha->aen_out++; - - ha->aen_q_count++; aen = &ha->aen_q[ha->aen_out]; - /* copy aen information to local structure */ for (i = 0; i < MBOX_AEN_REG_COUNT; i++) mbox_sts[i] = aen->mbox_sts[i]; + ha->aen_q_count++; + ha->aen_out++; + + if (ha->aen_out == MAX_AEN_ENTRIES) + ha->aen_out = 0; + spin_unlock_irqrestore(&ha->hardware_lock, flags); - DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x " - "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out, - mbox_sts[0], mbox_sts[2], mbox_sts[3], - mbox_sts[1], mbox_sts[4])); + DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x" + " mbx3=0x%08x mbx4=0x%08x\n", ha->host_no, + (ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)), + mbox_sts[0], mbox_sts[1], mbox_sts[2], + mbox_sts[3], mbox_sts[4])); switch (mbox_sts[0]) { case MBOX_ASTS_DATABASE_CHANGED: @@ -792,6 +810,5 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) spin_lock_irqsave(&ha->hardware_lock, flags); } spin_unlock_irqrestore(&ha->hardware_lock, flags); - } diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index f116ff917237..35cd73c72a68 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -6,6 +6,9 @@ */ #include "ql4_def.h" +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" /** @@ -169,84 +172,6 @@ mbox_exit: return status; } - -#if 0 - -/** - * qla4xxx_issue_iocb - issue mailbox iocb command - * @ha: adapter state pointer. - * @buffer: buffer pointer. - * @phys_addr: physical address of buffer. - * @size: size of buffer. - * - * Issues iocbs via mailbox commands. - * TARGET_QUEUE_LOCK must be released. - * ADAPTER_STATE_LOCK must be released. - **/ -int -qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer, - dma_addr_t phys_addr, size_t size) -{ - uint32_t mbox_cmd[MBOX_REG_COUNT]; - uint32_t mbox_sts[MBOX_REG_COUNT]; - int status; - - memset(&mbox_cmd, 0, sizeof(mbox_cmd)); - memset(&mbox_sts, 0, sizeof(mbox_sts)); - mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64; - mbox_cmd[1] = 0; - mbox_cmd[2] = LSDW(phys_addr); - mbox_cmd[3] = MSDW(phys_addr); - status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]); - return status; -} - -int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha, - uint16_t fw_ddb_index, - uint16_t connection_id, - uint16_t option) -{ - uint32_t mbox_cmd[MBOX_REG_COUNT]; - uint32_t mbox_sts[MBOX_REG_COUNT]; - - memset(&mbox_cmd, 0, sizeof(mbox_cmd)); - memset(&mbox_sts, 0, sizeof(mbox_sts)); - mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; - mbox_cmd[1] = fw_ddb_index; - mbox_cmd[2] = connection_id; - mbox_cmd[3] = LOGOUT_OPTION_RELOGIN; - if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) != - QLA_SUCCESS) { - DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT " - "option %04x failed sts %04X %04X", - ha->host_no, __func__, - option, mbox_sts[0], mbox_sts[1])); - if (mbox_sts[0] == 0x4005) - DEBUG2(printk("%s reason %04X\n", __func__, - mbox_sts[1])); - } - return QLA_SUCCESS; -} - -int qla4xxx_clear_database_entry(struct scsi_qla_host * ha, - uint16_t fw_ddb_index) -{ - uint32_t mbox_cmd[MBOX_REG_COUNT]; - uint32_t mbox_sts[MBOX_REG_COUNT]; - - memset(&mbox_cmd, 0, sizeof(mbox_cmd)); - memset(&mbox_sts, 0, sizeof(mbox_sts)); - mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY; - mbox_cmd[1] = fw_ddb_index; - if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) != - QLA_SUCCESS) - return QLA_ERROR; - - return QLA_SUCCESS; -} - -#endif /* 0 */ - /** * qla4xxx_initialize_fw_cb - initializes firmware control block. * @ha: Pointer to host adapter structure. @@ -272,10 +197,13 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) /* Get Initialize Firmware Control Block. */ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; mbox_cmd[2] = LSDW(init_fw_cb_dma); mbox_cmd[3] = MSDW(init_fw_cb_dma); - if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != + mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk); + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk), @@ -287,51 +215,56 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha) qla4xxx_init_rings(ha); /* Fill in the request and response queue information. */ - init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out); - init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in); - init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH); - init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH); - init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma)); - init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma)); - init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma)); - init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma)); - init_fw_cb->ShadowRegBufAddrLo = + init_fw_cb->pri.rqq_consumer_idx = cpu_to_le16(ha->request_out); + init_fw_cb->pri.compq_producer_idx = cpu_to_le16(ha->response_in); + init_fw_cb->pri.rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH); + init_fw_cb->pri.compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH); + init_fw_cb->pri.rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma)); + init_fw_cb->pri.rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma)); + init_fw_cb->pri.compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma)); + init_fw_cb->pri.compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma)); + init_fw_cb->pri.shdwreg_addr_lo = cpu_to_le32(LSDW(ha->shadow_regs_dma)); - init_fw_cb->ShadowRegBufAddrHi = + init_fw_cb->pri.shdwreg_addr_hi = cpu_to_le32(MSDW(ha->shadow_regs_dma)); /* Set up required options. */ - init_fw_cb->FwOptions |= + init_fw_cb->pri.fw_options |= __constant_cpu_to_le16(FWOPT_SESSION_MODE | FWOPT_INITIATOR_MODE); - init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE); + init_fw_cb->pri.fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE); /* Save some info in adapter structure. */ - ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions); - ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions); - ha->heartbeat_interval = init_fw_cb->HeartbeatInterval; - memcpy(ha->ip_address, init_fw_cb->IPAddr, - min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr))); - memcpy(ha->subnet_mask, init_fw_cb->SubnetMask, - min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask))); - memcpy(ha->gateway, init_fw_cb->GatewayIPAddr, - min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr))); - memcpy(ha->name_string, init_fw_cb->iSCSINameString, + ha->firmware_options = le16_to_cpu(init_fw_cb->pri.fw_options); + ha->tcp_options = le16_to_cpu(init_fw_cb->pri.ipv4_tcp_opts); + ha->heartbeat_interval = init_fw_cb->pri.hb_interval; + memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr, + min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr))); + memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet, + min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet))); + memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr, + min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr))); + memcpy(ha->name_string, init_fw_cb->pri.iscsi_name, min(sizeof(ha->name_string), - sizeof(init_fw_cb->iSCSINameString))); - memcpy(ha->alias, init_fw_cb->Alias, - min(sizeof(ha->alias), sizeof(init_fw_cb->Alias))); + sizeof(init_fw_cb->pri.iscsi_name))); + /*memcpy(ha->alias, init_fw_cb->Alias, + min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ /* Save Command Line Paramater info */ - ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout); + ha->port_down_retry_count = le16_to_cpu(init_fw_cb->pri.conn_ka_timeout); ha->discovery_wait = ql4xdiscoverywait; /* Send Initialize Firmware Control Block. */ + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE; mbox_cmd[1] = 0; mbox_cmd[2] = LSDW(init_fw_cb_dma); mbox_cmd[3] = MSDW(init_fw_cb_dma); - if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) == + mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk); + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) == QLA_SUCCESS) status = QLA_SUCCESS; else { @@ -368,12 +301,14 @@ int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha) /* Get Initialize Firmware Control Block. */ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_sts)); + memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk)); mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; mbox_cmd[2] = LSDW(init_fw_cb_dma); mbox_cmd[3] = MSDW(init_fw_cb_dma); + mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk); - if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", ha->host_no, __func__)); @@ -384,12 +319,12 @@ int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha) } /* Save IP Address. */ - memcpy(ha->ip_address, init_fw_cb->IPAddr, - min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr))); - memcpy(ha->subnet_mask, init_fw_cb->SubnetMask, - min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask))); - memcpy(ha->gateway, init_fw_cb->GatewayIPAddr, - min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr))); + memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr, + min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr))); + memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet, + min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet))); + memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr, + min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr))); dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk), init_fw_cb, init_fw_cb_dma); @@ -409,8 +344,10 @@ int qla4xxx_get_firmware_state(struct scsi_qla_host * ha) /* Get firmware version */ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_GET_FW_STATE; - if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) != + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ " "status %04X\n", ha->host_no, __func__, @@ -438,8 +375,10 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) /* Get firmware version */ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS; - if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) != + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ " "status %04X\n", ha->host_no, __func__, @@ -491,11 +430,14 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, } memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY; mbox_cmd[1] = (uint32_t) fw_ddb_index; mbox_cmd[2] = LSDW(fw_ddb_entry_dma); mbox_cmd[3] = MSDW(fw_ddb_entry_dma); - if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) == + mbox_cmd[4] = sizeof(struct dev_db_entry); + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) == QLA_ERROR) { DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed" " with status 0x%04X\n", ha->host_no, __func__, @@ -512,11 +454,11 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d " "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n", fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3], - mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0], - fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2], - fw_ddb_entry->ipAddr[3], - le16_to_cpu(fw_ddb_entry->portNumber), - fw_ddb_entry->iscsiName); + mbox_sts[4], mbox_sts[5], fw_ddb_entry->ip_addr[0], + fw_ddb_entry->ip_addr[1], fw_ddb_entry->ip_addr[2], + fw_ddb_entry->ip_addr[3], + le16_to_cpu(fw_ddb_entry->port), + fw_ddb_entry->iscsi_name); } if (num_valid_ddb_entries) *num_valid_ddb_entries = mbox_sts[2]; @@ -571,35 +513,10 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, mbox_cmd[1] = (uint32_t) fw_ddb_index; mbox_cmd[2] = LSDW(fw_ddb_entry_dma); mbox_cmd[3] = MSDW(fw_ddb_entry_dma); - return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]); -} + mbox_cmd[4] = sizeof(struct dev_db_entry); -#if 0 -int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha, - uint16_t fw_ddb_index) -{ - int status = QLA_ERROR; - uint32_t mbox_cmd[MBOX_REG_COUNT]; - uint32_t mbox_sts[MBOX_REG_COUNT]; - - /* Do not wait for completion. The firmware will send us an - * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. - */ - memset(&mbox_cmd, 0, sizeof(mbox_cmd)); - memset(&mbox_sts, 0, sizeof(mbox_sts)); - mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN; - mbox_cmd[1] = (uint32_t) fw_ddb_index; - mbox_cmd[2] = 0; - mbox_cmd[3] = 0; - mbox_cmd[4] = 0; - status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]); - DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n", - __func__, fw_ddb_index, status, mbox_sts[0], - mbox_sts[1]);) - - return status; + return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); } -#endif /* 0 */ /** * qla4xxx_get_crash_record - retrieves crash record. @@ -614,12 +531,14 @@ void qla4xxx_get_crash_record(struct scsi_qla_host * ha) struct crash_record *crash_record = NULL; dma_addr_t crash_record_dma = 0; uint32_t crash_record_size = 0; + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_cmd)); /* Get size of crash record. */ mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; - if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) != + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n", ha->host_no, __func__)); @@ -639,11 +558,15 @@ void qla4xxx_get_crash_record(struct scsi_qla_host * ha) goto exit_get_crash_record; /* Get Crash Record. */ + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_cmd)); + mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; mbox_cmd[2] = LSDW(crash_record_dma); mbox_cmd[3] = MSDW(crash_record_dma); mbox_cmd[4] = crash_record_size; - if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) != + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) goto exit_get_crash_record; @@ -655,7 +578,6 @@ exit_get_crash_record: crash_record, crash_record_dma); } -#if 0 /** * qla4xxx_get_conn_event_log - retrieves connection event log * @ha: Pointer to host adapter structure. @@ -678,7 +600,8 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha) /* Get size of crash record. */ mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; - if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) goto exit_get_event_log; @@ -693,10 +616,14 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha) goto exit_get_event_log; /* Get Crash Record. */ + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_cmd)); + mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; mbox_cmd[2] = LSDW(event_log_dma); mbox_cmd[3] = MSDW(event_log_dma); - if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event " "log!\n", ha->host_no, __func__)); @@ -745,7 +672,6 @@ exit_get_event_log: dma_free_coherent(&ha->pdev->dev, event_log_size, event_log, event_log_dma); } -#endif /* 0 */ /** * qla4xxx_reset_lun - issues LUN Reset @@ -773,11 +699,13 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, */ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_LUN_RESET; mbox_cmd[1] = ddb_entry->fw_ddb_index; mbox_cmd[2] = lun << 8; mbox_cmd[5] = 0x01; /* Immediate Command Enable */ - qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]); + + qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && mbox_sts[0] != MBOX_STS_COMMAND_ERROR) status = QLA_ERROR; @@ -794,12 +722,14 @@ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_READ_FLASH; mbox_cmd[1] = LSDW(dma_addr); mbox_cmd[2] = MSDW(dma_addr); mbox_cmd[3] = offset; mbox_cmd[4] = len; - if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) != + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ " "status %04X %04X, offset %08x, len %08x\n", ha->host_no, @@ -825,8 +755,10 @@ int qla4xxx_get_fw_version(struct scsi_qla_host * ha) /* Get firmware version. */ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); memset(&mbox_sts, 0, sizeof(mbox_sts)); + mbox_cmd[0] = MBOX_CMD_ABOUT_FW; - if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != + + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ " "status %04X\n", ha->host_no, __func__, mbox_sts[0])); @@ -855,7 +787,7 @@ static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, mbox_cmd[2] = LSDW(dma_addr); mbox_cmd[3] = MSDW(dma_addr); - if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: failed status %04X\n", ha->host_no, __func__, mbox_sts[0])); @@ -875,7 +807,7 @@ static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index) mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY; mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES; - if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) != + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) != QLA_SUCCESS) { if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) { *ddb_index = mbox_sts[2]; @@ -918,23 +850,23 @@ int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port) if (ret_val != QLA_SUCCESS) goto qla4xxx_send_tgts_exit; - memset((void *)fw_ddb_entry->iSCSIAlias, 0, - sizeof(fw_ddb_entry->iSCSIAlias)); + memset(fw_ddb_entry->iscsi_alias, 0, + sizeof(fw_ddb_entry->iscsi_alias)); - memset((void *)fw_ddb_entry->iscsiName, 0, - sizeof(fw_ddb_entry->iscsiName)); + memset(fw_ddb_entry->iscsi_name, 0, + sizeof(fw_ddb_entry->iscsi_name)); - memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr)); - memset((void *)fw_ddb_entry->targetAddr, 0, - sizeof(fw_ddb_entry->targetAddr)); + memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr)); + memset(fw_ddb_entry->tgt_addr, 0, + sizeof(fw_ddb_entry->tgt_addr)); fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET); - fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port)); + fw_ddb_entry->port = cpu_to_le16(ntohs(port)); - fw_ddb_entry->ipAddr[0] = *ip; - fw_ddb_entry->ipAddr[1] = *(ip + 1); - fw_ddb_entry->ipAddr[2] = *(ip + 2); - fw_ddb_entry->ipAddr[3] = *(ip + 3); + fw_ddb_entry->ip_addr[0] = *ip; + fw_ddb_entry->ip_addr[1] = *(ip + 1); + fw_ddb_entry->ip_addr[2] = *(ip + 2); + fw_ddb_entry->ip_addr[3] = *(ip + 3); ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma); diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c index 58afd135aa1d..7fe0482ecf03 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.c +++ b/drivers/scsi/qla4xxx/ql4_nvram.c @@ -6,6 +6,9 @@ */ #include "ql4_def.h" +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha) { diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index da21f5fbbf87..e09fc4241970 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -10,6 +10,10 @@ #include <scsi/scsicam.h> #include "ql4_def.h" +#include "ql4_version.h" +#include "ql4_glbl.h" +#include "ql4_dbg.h" +#include "ql4_inline.h" /* * Driver version @@ -369,14 +373,7 @@ static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb) struct scsi_cmnd *cmd = srb->cmd; if (srb->flags & SRB_DMA_VALID) { - if (cmd->use_sg) { - pci_unmap_sg(ha->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); - } else if (cmd->request_bufflen) { - pci_unmap_single(ha->pdev, srb->dma_handle, - cmd->request_bufflen, - cmd->sc_data_direction); - } + scsi_dma_unmap(cmd); srb->flags &= ~SRB_DMA_VALID; } cmd->SCp.ptr = NULL; @@ -711,7 +708,7 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) return stat; } -static void qla4xxx_hw_reset(struct scsi_qla_host *ha) +void qla4xxx_hw_reset(struct scsi_qla_host *ha) { uint32_t ctrl_status; unsigned long flags = 0; @@ -1081,13 +1078,13 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) if (ha->timer_active) qla4xxx_stop_timer(ha); - /* free extra memory */ - qla4xxx_mem_free(ha); - /* Detach interrupts */ if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) free_irq(ha->pdev->irq, ha); + /* free extra memory */ + qla4xxx_mem_free(ha); + pci_disable_device(ha->pdev); } @@ -1332,6 +1329,11 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) ha = pci_get_drvdata(pdev); + qla4xxx_disable_intrs(ha); + + while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) + ssleep(1); + /* remove devs from iscsi_sessions to scsi_devices */ qla4xxx_free_ddb_list(ha); diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index e5183a697d1f..2149069689bd 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,5 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.00.07-k1" +#define QLA4XXX_DRIVER_VERSION "5.01.00-k7" + diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c index 2e7db18f5aef..2bfbf26c00ed 100644 --- a/drivers/scsi/qlogicfas408.c +++ b/drivers/scsi/qlogicfas408.c @@ -265,8 +265,6 @@ static unsigned int ql_pcmd(struct scsi_cmnd *cmd) unsigned int message; /* scsi returned message */ unsigned int phase; /* recorded scsi phase */ unsigned int reqlen; /* total length of transfer */ - struct scatterlist *sglist; /* scatter-gather list pointer */ - unsigned int sgcount; /* sg counter */ char *buf; struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); int qbase = priv->qbase; @@ -301,9 +299,10 @@ static unsigned int ql_pcmd(struct scsi_cmnd *cmd) if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */ outb(1, qbase + 3); /* clear fifo */ /* note that request_bufflen is the total xfer size when sg is used */ - reqlen = cmd->request_bufflen; + reqlen = scsi_bufflen(cmd); /* note that it won't work if transfers > 16M are requested */ if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */ + struct scatterlist *sg; rtrc(2) outb(reqlen, qbase); /* low-mid xfer cnt */ outb(reqlen >> 8, qbase + 1); /* low-mid xfer cnt */ @@ -311,23 +310,16 @@ static unsigned int ql_pcmd(struct scsi_cmnd *cmd) outb(0x90, qbase + 3); /* command do xfer */ /* PIO pseudo DMA to buffer or sglist */ REG1; - if (!cmd->use_sg) - ql_pdma(priv, phase, cmd->request_buffer, - cmd->request_bufflen); - else { - sgcount = cmd->use_sg; - sglist = cmd->request_buffer; - while (sgcount--) { - if (priv->qabort) { - REG0; - return ((priv->qabort == 1 ? - DID_ABORT : DID_RESET) << 16); - } - buf = page_address(sglist->page) + sglist->offset; - if (ql_pdma(priv, phase, buf, sglist->length)) - break; - sglist++; + + scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) { + if (priv->qabort) { + REG0; + return ((priv->qabort == 1 ? + DID_ABORT : DID_RESET) << 16); } + buf = page_address(sg->page) + sg->offset; + if (ql_pdma(priv, phase, buf, sg->length)) + break; } REG0; rtrc(2) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index e8350c562d24..9adb64ac054c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -18,12 +18,12 @@ #include <linux/sched.h> #include <linux/timer.h> #include <linux/string.h> -#include <linux/slab.h> #include <linux/kernel.h> #include <linux/kthread.h> #include <linux/interrupt.h> #include <linux/blkdev.h> #include <linux/delay.h> +#include <linux/scatterlist.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -640,16 +640,8 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, memcpy(scmd->cmnd, cmnd, cmnd_size); if (copy_sense) { - gfp_t gfp_mask = GFP_ATOMIC; - - if (shost->hostt->unchecked_isa_dma) - gfp_mask |= __GFP_DMA; - - sgl.page = alloc_page(gfp_mask); - if (!sgl.page) - return FAILED; - sgl.offset = 0; - sgl.length = 252; + sg_init_one(&sgl, scmd->sense_buffer, + sizeof(scmd->sense_buffer)); scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->request_bufflen = sgl.length; @@ -720,18 +712,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, /* - * Last chance to have valid sense data. - */ - if (copy_sense) { - if (!SCSI_SENSE_VALID(scmd)) { - memcpy(scmd->sense_buffer, page_address(sgl.page), - sizeof(scmd->sense_buffer)); - } - __free_page(sgl.page); - } - - - /* * Restore original data */ scmd->request_buffer = old_buffer; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1f5a07bf2a75..70454b4e8485 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2290,3 +2290,41 @@ void scsi_kunmap_atomic_sg(void *virt) kunmap_atomic(virt, KM_BIO_SRC_IRQ); } EXPORT_SYMBOL(scsi_kunmap_atomic_sg); + +/** + * scsi_dma_map - perform DMA mapping against command's sg lists + * @cmd: scsi command + * + * Returns the number of sg lists actually used, zero if the sg lists + * is NULL, or -ENOMEM if the mapping failed. + */ +int scsi_dma_map(struct scsi_cmnd *cmd) +{ + int nseg = 0; + + if (scsi_sg_count(cmd)) { + struct device *dev = cmd->device->host->shost_gendev.parent; + + nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd), + cmd->sc_data_direction); + if (unlikely(!nseg)) + return -ENOMEM; + } + return nseg; +} +EXPORT_SYMBOL(scsi_dma_map); + +/** + * scsi_dma_unmap - unmap command's sg lists mapped by scsi_dma_map + * @cmd: scsi command + */ +void scsi_dma_unmap(struct scsi_cmnd *cmd) +{ + if (scsi_sg_count(cmd)) { + struct device *dev = cmd->device->host->shost_gendev.parent; + + dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd), + cmd->sc_data_direction); + } +} +EXPORT_SYMBOL(scsi_dma_unmap); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 67a38a1409ba..ed720863ab97 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -293,30 +293,18 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state) { struct device_driver *drv = dev->driver; struct scsi_device *sdev = to_scsi_device(dev); - struct scsi_host_template *sht = sdev->host->hostt; int err; err = scsi_device_quiesce(sdev); if (err) return err; - /* call HLD suspend first */ if (drv && drv->suspend) { err = drv->suspend(dev, state); if (err) return err; } - /* then, call host suspend */ - if (sht->suspend) { - err = sht->suspend(sdev, state); - if (err) { - if (drv && drv->resume) - drv->resume(dev); - return err; - } - } - return 0; } @@ -324,21 +312,14 @@ static int scsi_bus_resume(struct device * dev) { struct device_driver *drv = dev->driver; struct scsi_device *sdev = to_scsi_device(dev); - struct scsi_host_template *sht = sdev->host->hostt; - int err = 0, err2 = 0; - - /* call host resume first */ - if (sht->resume) - err = sht->resume(sdev); + int err = 0; - /* then, call HLD resume */ if (drv && drv->resume) - err2 = drv->resume(dev); + err = drv->resume(dev); scsi_device_resume(sdev); - /* favor LLD failure */ - return err ? err : err2;; + return err; } struct bus_type scsi_bus_type = { diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index b4d1ece46f78..4953f0dca029 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -1,4 +1,4 @@ -/* +/* * FiberChannel transport specific attributes exported to sysfs. * * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. @@ -19,9 +19,10 @@ * * ======== * - * Copyright (C) 2004-2005 James Smart, Emulex Corporation + * Copyright (C) 2004-2007 James Smart, Emulex Corporation * Rewrite for host, target, device, and remote port attributes, * statistics, and service functions... + * Add vports, etc * */ #include <linux/module.h> @@ -37,6 +38,34 @@ #include "scsi_priv.h" static int fc_queue_work(struct Scsi_Host *, struct work_struct *); +static void fc_vport_sched_delete(struct work_struct *work); + +/* + * This is a temporary carrier for creating a vport. It will eventually + * be replaced by a real message definition for sgio or netlink. + * + * fc_vport_identifiers: This set of data contains all elements + * to uniquely identify and instantiate a FC virtual port. + * + * Notes: + * symbolic_name: The driver is to append the symbolic_name string data + * to the symbolic_node_name data that it generates by default. + * the resulting combination should then be registered with the switch. + * It is expected that things like Xen may stuff a VM title into + * this field. + */ +struct fc_vport_identifiers { + u64 node_name; + u64 port_name; + u32 roles; + bool disable; + enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */ + char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN]; +}; + +static int fc_vport_create(struct Scsi_Host *shost, int channel, + struct device *pdev, struct fc_vport_identifiers *ids, + struct fc_vport **vport); /* * Redefine so that we can have same named attributes in the @@ -90,10 +119,14 @@ static struct { { FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" }, { FC_PORTTYPE_LPORT, "LPort (private loop)" }, { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection" }, + { FC_PORTTYPE_NPIV, "NPIV VPORT" }, }; fc_enum_name_search(port_type, fc_port_type, fc_port_type_names) #define FC_PORTTYPE_MAX_NAMELEN 50 +/* Reuse fc_port_type enum function for vport_type */ +#define get_fc_vport_type_name get_fc_port_type_name + /* Convert fc_host_event_code values to ascii string name */ static const struct { @@ -139,6 +172,29 @@ fc_enum_name_search(port_state, fc_port_state, fc_port_state_names) #define FC_PORTSTATE_MAX_NAMELEN 20 +/* Convert fc_vport_state values to ascii string name */ +static struct { + enum fc_vport_state value; + char *name; +} fc_vport_state_names[] = { + { FC_VPORT_UNKNOWN, "Unknown" }, + { FC_VPORT_ACTIVE, "Active" }, + { FC_VPORT_DISABLED, "Disabled" }, + { FC_VPORT_LINKDOWN, "Linkdown" }, + { FC_VPORT_INITIALIZING, "Initializing" }, + { FC_VPORT_NO_FABRIC_SUPP, "No Fabric Support" }, + { FC_VPORT_NO_FABRIC_RSCS, "No Fabric Resources" }, + { FC_VPORT_FABRIC_LOGOUT, "Fabric Logout" }, + { FC_VPORT_FABRIC_REJ_WWN, "Fabric Rejected WWN" }, + { FC_VPORT_FAILED, "VPort Failed" }, +}; +fc_enum_name_search(vport_state, fc_vport_state, fc_vport_state_names) +#define FC_VPORTSTATE_MAX_NAMELEN 24 + +/* Reuse fc_vport_state enum function for vport_last_state */ +#define get_fc_vport_last_state_name get_fc_vport_state_name + + /* Convert fc_tgtid_binding_type values to ascii string name */ static const struct { enum fc_tgtid_binding_type value; @@ -219,16 +275,16 @@ show_fc_fc4s (char *buf, u8 *fc4_list) } -/* Convert FC_RPORT_ROLE bit values to ascii string name */ +/* Convert FC_PORT_ROLE bit values to ascii string name */ static const struct { u32 value; char *name; -} fc_remote_port_role_names[] = { - { FC_RPORT_ROLE_FCP_TARGET, "FCP Target" }, - { FC_RPORT_ROLE_FCP_INITIATOR, "FCP Initiator" }, - { FC_RPORT_ROLE_IP_PORT, "IP Port" }, +} fc_port_role_names[] = { + { FC_PORT_ROLE_FCP_TARGET, "FCP Target" }, + { FC_PORT_ROLE_FCP_INITIATOR, "FCP Initiator" }, + { FC_PORT_ROLE_IP_PORT, "IP Port" }, }; -fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names) +fc_bitfield_name_search(port_roles, fc_port_role_names) /* * Define roles that are specific to port_id. Values are relative to ROLE_MASK. @@ -252,7 +308,8 @@ static void fc_scsi_scan_rport(struct work_struct *work); */ #define FC_STARGET_NUM_ATTRS 3 #define FC_RPORT_NUM_ATTRS 10 -#define FC_HOST_NUM_ATTRS 17 +#define FC_VPORT_NUM_ATTRS 9 +#define FC_HOST_NUM_ATTRS 21 struct fc_internal { struct scsi_transport_template t; @@ -278,6 +335,10 @@ struct fc_internal { struct transport_container rport_attr_cont; struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS]; struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1]; + + struct transport_container vport_attr_cont; + struct class_device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS]; + struct class_device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1]; }; #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t) @@ -318,7 +379,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, struct Scsi_Host *shost = dev_to_shost(dev); struct fc_host_attrs *fc_host = shost_to_fc_host(shost); - /* + /* * Set default values easily detected by the midlayer as * failure cases. The scsi lldd is responsible for initializing * all transport attributes to valid values per host. @@ -331,6 +392,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, sizeof(fc_host->supported_fc4s)); fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN; fc_host->maxframe_size = -1; + fc_host->max_npiv_vports = 0; memset(fc_host->serial_number, 0, sizeof(fc_host->serial_number)); @@ -348,8 +410,11 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, INIT_LIST_HEAD(&fc_host->rports); INIT_LIST_HEAD(&fc_host->rport_bindings); + INIT_LIST_HEAD(&fc_host->vports); fc_host->next_rport_number = 0; fc_host->next_target_id = 0; + fc_host->next_vport_number = 0; + fc_host->npiv_vports_inuse = 0; snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d", shost->host_no); @@ -388,6 +453,16 @@ static DECLARE_TRANSPORT_CLASS(fc_rport_class, NULL); /* + * Setup and Remove actions for virtual ports are handled + * in the service functions below. + */ +static DECLARE_TRANSPORT_CLASS(fc_vport_class, + "fc_vports", + NULL, + NULL, + NULL); + +/* * Module Parameters */ @@ -585,6 +660,9 @@ static __init int fc_transport_init(void) error = transport_class_register(&fc_host_class); if (error) return error; + error = transport_class_register(&fc_vport_class); + if (error) + return error; error = transport_class_register(&fc_rport_class); if (error) return error; @@ -596,6 +674,7 @@ static void __exit fc_transport_exit(void) transport_class_unregister(&fc_transport_class); transport_class_unregister(&fc_rport_class); transport_class_unregister(&fc_host_class); + transport_class_unregister(&fc_vport_class); } /* @@ -800,9 +879,9 @@ show_fc_rport_roles (struct class_device *cdev, char *buf) return snprintf(buf, 30, "Unknown Fabric Entity\n"); } } else { - if (rport->roles == FC_RPORT_ROLE_UNKNOWN) + if (rport->roles == FC_PORT_ROLE_UNKNOWN) return snprintf(buf, 20, "unknown\n"); - return get_fc_remote_port_roles_names(rport->roles, buf); + return get_fc_port_roles_names(rport->roles, buf); } } static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO, @@ -857,7 +936,7 @@ static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR, /* * Note: in the target show function we recognize when the remote - * port is in the hierarchy and do not allow the driver to get + * port is in the heirarchy and do not allow the driver to get * involved in sysfs functions. The driver only gets involved if * it's the "old" style that doesn't use rports. */ @@ -912,6 +991,257 @@ fc_starget_rd_attr(port_id, "0x%06x\n", 20); /* + * FC Virtual Port Attribute Management + */ + +#define fc_vport_show_function(field, format_string, sz, cast) \ +static ssize_t \ +show_fc_vport_##field (struct class_device *cdev, char *buf) \ +{ \ + struct fc_vport *vport = transport_class_to_vport(cdev); \ + struct Scsi_Host *shost = vport_to_shost(vport); \ + struct fc_internal *i = to_fc_internal(shost->transportt); \ + if ((i->f->get_vport_##field) && \ + !(vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))) \ + i->f->get_vport_##field(vport); \ + return snprintf(buf, sz, format_string, cast vport->field); \ +} + +#define fc_vport_store_function(field) \ +static ssize_t \ +store_fc_vport_##field(struct class_device *cdev, const char *buf, \ + size_t count) \ +{ \ + int val; \ + struct fc_vport *vport = transport_class_to_vport(cdev); \ + struct Scsi_Host *shost = vport_to_shost(vport); \ + struct fc_internal *i = to_fc_internal(shost->transportt); \ + char *cp; \ + if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \ + return -EBUSY; \ + val = simple_strtoul(buf, &cp, 0); \ + if (*cp && (*cp != '\n')) \ + return -EINVAL; \ + i->f->set_vport_##field(vport, val); \ + return count; \ +} + +#define fc_vport_store_str_function(field, slen) \ +static ssize_t \ +store_fc_vport_##field(struct class_device *cdev, const char *buf, \ + size_t count) \ +{ \ + struct fc_vport *vport = transport_class_to_vport(cdev); \ + struct Scsi_Host *shost = vport_to_shost(vport); \ + struct fc_internal *i = to_fc_internal(shost->transportt); \ + unsigned int cnt=count; \ + \ + /* count may include a LF at end of string */ \ + if (buf[cnt-1] == '\n') \ + cnt--; \ + if (cnt > ((slen) - 1)) \ + return -EINVAL; \ + memcpy(vport->field, buf, cnt); \ + i->f->set_vport_##field(vport); \ + return count; \ +} + +#define fc_vport_rd_attr(field, format_string, sz) \ + fc_vport_show_function(field, format_string, sz, ) \ +static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \ + show_fc_vport_##field, NULL) + +#define fc_vport_rd_attr_cast(field, format_string, sz, cast) \ + fc_vport_show_function(field, format_string, sz, (cast)) \ +static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \ + show_fc_vport_##field, NULL) + +#define fc_vport_rw_attr(field, format_string, sz) \ + fc_vport_show_function(field, format_string, sz, ) \ + fc_vport_store_function(field) \ +static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \ + show_fc_vport_##field, \ + store_fc_vport_##field) + +#define fc_private_vport_show_function(field, format_string, sz, cast) \ +static ssize_t \ +show_fc_vport_##field (struct class_device *cdev, char *buf) \ +{ \ + struct fc_vport *vport = transport_class_to_vport(cdev); \ + return snprintf(buf, sz, format_string, cast vport->field); \ +} + +#define fc_private_vport_store_u32_function(field) \ +static ssize_t \ +store_fc_vport_##field(struct class_device *cdev, const char *buf, \ + size_t count) \ +{ \ + u32 val; \ + struct fc_vport *vport = transport_class_to_vport(cdev); \ + char *cp; \ + if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \ + return -EBUSY; \ + val = simple_strtoul(buf, &cp, 0); \ + if (*cp && (*cp != '\n')) \ + return -EINVAL; \ + vport->field = val; \ + return count; \ +} + + +#define fc_private_vport_rd_attr(field, format_string, sz) \ + fc_private_vport_show_function(field, format_string, sz, ) \ +static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \ + show_fc_vport_##field, NULL) + +#define fc_private_vport_rd_attr_cast(field, format_string, sz, cast) \ + fc_private_vport_show_function(field, format_string, sz, (cast)) \ +static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \ + show_fc_vport_##field, NULL) + +#define fc_private_vport_rw_u32_attr(field, format_string, sz) \ + fc_private_vport_show_function(field, format_string, sz, ) \ + fc_private_vport_store_u32_function(field) \ +static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \ + show_fc_vport_##field, \ + store_fc_vport_##field) + + +#define fc_private_vport_rd_enum_attr(title, maxlen) \ +static ssize_t \ +show_fc_vport_##title (struct class_device *cdev, char *buf) \ +{ \ + struct fc_vport *vport = transport_class_to_vport(cdev); \ + const char *name; \ + name = get_fc_##title##_name(vport->title); \ + if (!name) \ + return -EINVAL; \ + return snprintf(buf, maxlen, "%s\n", name); \ +} \ +static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO, \ + show_fc_vport_##title, NULL) + + +#define SETUP_VPORT_ATTRIBUTE_RD(field) \ + i->private_vport_attrs[count] = class_device_attr_vport_##field; \ + i->private_vport_attrs[count].attr.mode = S_IRUGO; \ + i->private_vport_attrs[count].store = NULL; \ + i->vport_attrs[count] = &i->private_vport_attrs[count]; \ + if (i->f->get_##field) \ + count++ + /* NOTE: Above MACRO differs: checks function not show bit */ + +#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field) \ + i->private_vport_attrs[count] = class_device_attr_vport_##field; \ + i->private_vport_attrs[count].attr.mode = S_IRUGO; \ + i->private_vport_attrs[count].store = NULL; \ + i->vport_attrs[count] = &i->private_vport_attrs[count]; \ + count++ + +#define SETUP_VPORT_ATTRIBUTE_WR(field) \ + i->private_vport_attrs[count] = class_device_attr_vport_##field; \ + i->vport_attrs[count] = &i->private_vport_attrs[count]; \ + if (i->f->field) \ + count++ + /* NOTE: Above MACRO differs: checks function */ + +#define SETUP_VPORT_ATTRIBUTE_RW(field) \ + i->private_vport_attrs[count] = class_device_attr_vport_##field; \ + if (!i->f->set_vport_##field) { \ + i->private_vport_attrs[count].attr.mode = S_IRUGO; \ + i->private_vport_attrs[count].store = NULL; \ + } \ + i->vport_attrs[count] = &i->private_vport_attrs[count]; \ + count++ + /* NOTE: Above MACRO differs: does not check show bit */ + +#define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field) \ +{ \ + i->private_vport_attrs[count] = class_device_attr_vport_##field; \ + i->vport_attrs[count] = &i->private_vport_attrs[count]; \ + count++; \ +} + + +/* The FC Transport Virtual Port Attributes: */ + +/* Fixed Virtual Port Attributes */ + +/* Dynamic Virtual Port Attributes */ + +/* Private Virtual Port Attributes */ + +fc_private_vport_rd_enum_attr(vport_state, FC_VPORTSTATE_MAX_NAMELEN); +fc_private_vport_rd_enum_attr(vport_last_state, FC_VPORTSTATE_MAX_NAMELEN); +fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); +fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); + +static ssize_t +show_fc_vport_roles (struct class_device *cdev, char *buf) +{ + struct fc_vport *vport = transport_class_to_vport(cdev); + + if (vport->roles == FC_PORT_ROLE_UNKNOWN) + return snprintf(buf, 20, "unknown\n"); + return get_fc_port_roles_names(vport->roles, buf); +} +static FC_CLASS_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL); + +fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN); + +fc_private_vport_show_function(symbolic_name, "%s\n", + FC_VPORT_SYMBOLIC_NAMELEN + 1, ) +fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN) +static FC_CLASS_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR, + show_fc_vport_symbolic_name, store_fc_vport_symbolic_name); + +static ssize_t +store_fc_vport_delete(struct class_device *cdev, const char *buf, + size_t count) +{ + struct fc_vport *vport = transport_class_to_vport(cdev); + struct Scsi_Host *shost = vport_to_shost(vport); + + fc_queue_work(shost, &vport->vport_delete_work); + return count; +} +static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR, + NULL, store_fc_vport_delete); + + +/* + * Enable/Disable vport + * Write "1" to disable, write "0" to enable + */ +static ssize_t +store_fc_vport_disable(struct class_device *cdev, const char *buf, + size_t count) +{ + struct fc_vport *vport = transport_class_to_vport(cdev); + struct Scsi_Host *shost = vport_to_shost(vport); + struct fc_internal *i = to_fc_internal(shost->transportt); + int stat; + + if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) + return -EBUSY; + + if (*buf == '0') { + if (vport->vport_state != FC_VPORT_DISABLED) + return -EALREADY; + } else if (*buf == '1') { + if (vport->vport_state == FC_VPORT_DISABLED) + return -EALREADY; + } else + return -EINVAL; + + stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true)); + return stat ? stat : count; +} +static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR, + NULL, store_fc_vport_disable); + + +/* * Host Attribute Management */ @@ -1003,6 +1333,13 @@ static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL) if (i->f->show_host_##field) \ count++ +#define SETUP_HOST_ATTRIBUTE_RD_NS(field) \ + i->private_host_attrs[count] = class_device_attr_host_##field; \ + i->private_host_attrs[count].attr.mode = S_IRUGO; \ + i->private_host_attrs[count].store = NULL; \ + i->host_attrs[count] = &i->private_host_attrs[count]; \ + count++ + #define SETUP_HOST_ATTRIBUTE_RW(field) \ i->private_host_attrs[count] = class_device_attr_host_##field; \ if (!i->f->set_host_##field) { \ @@ -1090,6 +1427,7 @@ fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20, unsigned long long); fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); +fc_private_host_rd_attr(max_npiv_vports, "%u\n", 20); fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); @@ -1210,6 +1548,9 @@ store_fc_private_host_issue_lip(struct class_device *cdev, static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL, store_fc_private_host_issue_lip); +fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20); + + /* * Host Statistics Management */ @@ -1285,7 +1626,6 @@ fc_reset_statistics(struct class_device *cdev, const char *buf, static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL, fc_reset_statistics); - static struct attribute *fc_statistics_attrs[] = { &class_device_attr_host_seconds_since_last_reset.attr, &class_device_attr_host_tx_frames.attr, @@ -1316,6 +1656,142 @@ static struct attribute_group fc_statistics_group = { .attrs = fc_statistics_attrs, }; + +/* Host Vport Attributes */ + +static int +fc_parse_wwn(const char *ns, u64 *nm) +{ + unsigned int i, j; + u8 wwn[8]; + + memset(wwn, 0, sizeof(wwn)); + + /* Validate and store the new name */ + for (i=0, j=0; i < 16; i++) { + if ((*ns >= 'a') && (*ns <= 'f')) + j = ((j << 4) | ((*ns++ -'a') + 10)); + else if ((*ns >= 'A') && (*ns <= 'F')) + j = ((j << 4) | ((*ns++ -'A') + 10)); + else if ((*ns >= '0') && (*ns <= '9')) + j = ((j << 4) | (*ns++ -'0')); + else + return -EINVAL; + if (i % 2) { + wwn[i/2] = j & 0xff; + j = 0; + } + } + + *nm = wwn_to_u64(wwn); + + return 0; +} + + +/* + * "Short-cut" sysfs variable to create a new vport on a FC Host. + * Input is a string of the form "<WWPN>:<WWNN>". Other attributes + * will default to a NPIV-based FCP_Initiator; The WWNs are specified + * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc) + */ +static ssize_t +store_fc_host_vport_create(struct class_device *cdev, const char *buf, + size_t count) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + struct fc_vport_identifiers vid; + struct fc_vport *vport; + unsigned int cnt=count; + int stat; + + memset(&vid, 0, sizeof(vid)); + + /* count may include a LF at end of string */ + if (buf[cnt-1] == '\n') + cnt--; + + /* validate we have enough characters for WWPN */ + if ((cnt != (16+1+16)) || (buf[16] != ':')) + return -EINVAL; + + stat = fc_parse_wwn(&buf[0], &vid.port_name); + if (stat) + return stat; + + stat = fc_parse_wwn(&buf[17], &vid.node_name); + if (stat) + return stat; + + vid.roles = FC_PORT_ROLE_FCP_INITIATOR; + vid.vport_type = FC_PORTTYPE_NPIV; + /* vid.symbolic_name is already zero/NULL's */ + vid.disable = false; /* always enabled */ + + /* we only allow support on Channel 0 !!! */ + stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport); + return stat ? stat : count; +} +static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL, + store_fc_host_vport_create); + + +/* + * "Short-cut" sysfs variable to delete a vport on a FC Host. + * Vport is identified by a string containing "<WWPN>:<WWNN>". + * The WWNs are specified as hex characters, and may *not* contain + * any prefixes (e.g. 0x, x, etc) + */ +static ssize_t +store_fc_host_vport_delete(struct class_device *cdev, const char *buf, + size_t count) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); + struct fc_vport *vport; + u64 wwpn, wwnn; + unsigned long flags; + unsigned int cnt=count; + int stat, match; + + /* count may include a LF at end of string */ + if (buf[cnt-1] == '\n') + cnt--; + + /* validate we have enough characters for WWPN */ + if ((cnt != (16+1+16)) || (buf[16] != ':')) + return -EINVAL; + + stat = fc_parse_wwn(&buf[0], &wwpn); + if (stat) + return stat; + + stat = fc_parse_wwn(&buf[17], &wwnn); + if (stat) + return stat; + + spin_lock_irqsave(shost->host_lock, flags); + match = 0; + /* we only allow support on Channel 0 !!! */ + list_for_each_entry(vport, &fc_host->vports, peers) { + if ((vport->channel == 0) && + (vport->port_name == wwpn) && (vport->node_name == wwnn)) { + match = 1; + break; + } + } + spin_unlock_irqrestore(shost->host_lock, flags); + + if (!match) + return -ENODEV; + + stat = fc_vport_terminate(vport); + return stat ? stat : count; +} +static FC_CLASS_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL, + store_fc_host_vport_delete); + + static int fc_host_match(struct attribute_container *cont, struct device *dev) { @@ -1387,6 +1863,40 @@ static int fc_rport_match(struct attribute_container *cont, } +static void fc_vport_dev_release(struct device *dev) +{ + struct fc_vport *vport = dev_to_vport(dev); + put_device(dev->parent); /* release kobj parent */ + kfree(vport); +} + +int scsi_is_fc_vport(const struct device *dev) +{ + return dev->release == fc_vport_dev_release; +} +EXPORT_SYMBOL(scsi_is_fc_vport); + +static int fc_vport_match(struct attribute_container *cont, + struct device *dev) +{ + struct fc_vport *vport; + struct Scsi_Host *shost; + struct fc_internal *i; + + if (!scsi_is_fc_vport(dev)) + return 0; + vport = dev_to_vport(dev); + + shost = vport_to_shost(vport); + if (!shost->transportt || shost->transportt->host_attrs.ac.class + != &fc_host_class.class) + return 0; + + i = to_fc_internal(shost->transportt); + return &i->vport_attr_cont.ac == cont; +} + + /** * fc_timed_out - FC Transport I/O timeout intercept handler * @@ -1472,6 +1982,11 @@ fc_attach_transport(struct fc_function_template *ft) i->rport_attr_cont.ac.match = fc_rport_match; transport_container_register(&i->rport_attr_cont); + i->vport_attr_cont.ac.attrs = &i->vport_attrs[0]; + i->vport_attr_cont.ac.class = &fc_vport_class.class; + i->vport_attr_cont.ac.match = fc_vport_match; + transport_container_register(&i->vport_attr_cont); + i->f = ft; /* Transport uses the shost workq for scsi scanning */ @@ -1480,7 +1995,7 @@ fc_attach_transport(struct fc_function_template *ft) i->t.eh_timed_out = fc_timed_out; i->t.user_scan = fc_user_scan; - + /* * Setup SCSI Target Attributes. */ @@ -1505,6 +2020,10 @@ fc_attach_transport(struct fc_function_template *ft) SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); SETUP_HOST_ATTRIBUTE_RD(supported_speeds); SETUP_HOST_ATTRIBUTE_RD(maxframe_size); + if (ft->vport_create) { + SETUP_HOST_ATTRIBUTE_RD_NS(max_npiv_vports); + SETUP_HOST_ATTRIBUTE_RD_NS(npiv_vports_inuse); + } SETUP_HOST_ATTRIBUTE_RD(serial_number); SETUP_HOST_ATTRIBUTE_RD(port_id); @@ -1520,6 +2039,10 @@ fc_attach_transport(struct fc_function_template *ft) SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); if (ft->issue_fc_host_lip) SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip); + if (ft->vport_create) + SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_create); + if (ft->vport_delete) + SETUP_PRIVATE_HOST_ATTRIBUTE_RW(vport_delete); BUG_ON(count > FC_HOST_NUM_ATTRS); @@ -1545,6 +2068,24 @@ fc_attach_transport(struct fc_function_template *ft) i->rport_attrs[count] = NULL; + /* + * Setup Virtual Port Attributes. + */ + count=0; + SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_state); + SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_last_state); + SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(node_name); + SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(port_name); + SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(roles); + SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(vport_type); + SETUP_VPORT_ATTRIBUTE_RW(symbolic_name); + SETUP_VPORT_ATTRIBUTE_WR(vport_delete); + SETUP_VPORT_ATTRIBUTE_WR(vport_disable); + + BUG_ON(count > FC_VPORT_NUM_ATTRS); + + i->vport_attrs[count] = NULL; + return &i->t; } EXPORT_SYMBOL(fc_attach_transport); @@ -1556,6 +2097,7 @@ void fc_release_transport(struct scsi_transport_template *t) transport_container_unregister(&i->t.target_attrs); transport_container_unregister(&i->t.host_attrs); transport_container_unregister(&i->rport_attr_cont); + transport_container_unregister(&i->vport_attr_cont); kfree(i); } @@ -1667,9 +2209,17 @@ fc_flush_devloss(struct Scsi_Host *shost) void fc_remove_host(struct Scsi_Host *shost) { - struct fc_rport *rport, *next_rport; + struct fc_vport *vport = NULL, *next_vport = NULL; + struct fc_rport *rport = NULL, *next_rport = NULL; struct workqueue_struct *work_q; struct fc_host_attrs *fc_host = shost_to_fc_host(shost); + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + + /* Remove any vports */ + list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) + fc_queue_work(shost, &vport->vport_delete_work); /* Remove any remote ports */ list_for_each_entry_safe(rport, next_rport, @@ -1686,6 +2236,8 @@ fc_remove_host(struct Scsi_Host *shost) fc_queue_work(shost, &rport->rport_delete_work); } + spin_unlock_irqrestore(shost->host_lock, flags); + /* flush all scan work items */ scsi_flush_work(shost); @@ -1744,7 +2296,7 @@ fc_rport_final_delete(struct work_struct *work) unsigned long flags; /* - * if a scan is pending, flush the SCSI Host work_q so that + * if a scan is pending, flush the SCSI Host work_q so that * that we can reclaim the rport scan work element. */ if (rport->flags & FC_RPORT_SCAN_PENDING) @@ -1844,7 +2396,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel, spin_lock_irqsave(shost->host_lock, flags); rport->number = fc_host->next_rport_number++; - if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) + if (rport->roles & FC_PORT_ROLE_FCP_TARGET) rport->scsi_target_id = fc_host->next_target_id++; else rport->scsi_target_id = -1; @@ -1869,7 +2421,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel, transport_add_device(dev); transport_configure_device(dev); - if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) { + if (rport->roles & FC_PORT_ROLE_FCP_TARGET) { /* initiate a scan of the target */ rport->flags |= FC_RPORT_SCAN_PENDING; scsi_queue_work(shost, &rport->scan_work); @@ -2003,7 +2555,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, /* was a target, not in roles */ if ((rport->scsi_target_id != -1) && - (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET))) + (!(ids->roles & FC_PORT_ROLE_FCP_TARGET))) return rport; /* @@ -2086,7 +2638,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, memset(rport->dd_data, 0, fci->f->dd_fcrport_size); - if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) { + if (rport->roles & FC_PORT_ROLE_FCP_TARGET) { /* initiate a scan of the target */ rport->flags |= FC_RPORT_SCAN_PENDING; scsi_queue_work(shost, &rport->scan_work); @@ -2243,11 +2795,11 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) int create = 0; spin_lock_irqsave(shost->host_lock, flags); - if (roles & FC_RPORT_ROLE_FCP_TARGET) { + if (roles & FC_PORT_ROLE_FCP_TARGET) { if (rport->scsi_target_id == -1) { rport->scsi_target_id = fc_host->next_target_id++; create = 1; - } else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) + } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET)) create = 1; } @@ -2294,7 +2846,7 @@ EXPORT_SYMBOL(fc_remote_port_rolechg); * fc_timeout_deleted_rport - Timeout handler for a deleted remote port, * which we blocked, and has now failed to return * in the allotted time. - * + * * @work: rport target that failed to reappear in the allotted time. **/ static void @@ -2317,7 +2869,7 @@ fc_timeout_deleted_rport(struct work_struct *work) */ if ((rport->port_state == FC_PORTSTATE_ONLINE) && (rport->scsi_target_id != -1) && - !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { + !(rport->roles & FC_PORT_ROLE_FCP_TARGET)) { dev_printk(KERN_ERR, &rport->dev, "blocked FC remote port time out: no longer" " a FCP target, removing starget\n"); @@ -2367,7 +2919,7 @@ fc_timeout_deleted_rport(struct work_struct *work) */ rport->maxframe_size = -1; rport->supported_classes = FC_COS_UNSPECIFIED; - rport->roles = FC_RPORT_ROLE_UNKNOWN; + rport->roles = FC_PORT_ROLE_UNKNOWN; rport->port_state = FC_PORTSTATE_NOTPRESENT; /* remove the identifiers that aren't used in the consisting binding */ @@ -2436,7 +2988,7 @@ fc_scsi_scan_rport(struct work_struct *work) unsigned long flags; if ((rport->port_state == FC_PORTSTATE_ONLINE) && - (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { + (rport->roles & FC_PORT_ROLE_FCP_TARGET)) { scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id, SCAN_WILD_CARD, 1); } @@ -2447,7 +2999,227 @@ fc_scsi_scan_rport(struct work_struct *work) } -MODULE_AUTHOR("Martin Hicks"); +/** + * fc_vport_create - allocates and creates a FC virtual port. + * @shost: scsi host the virtual port is connected to. + * @channel: Channel on shost port connected to. + * @pdev: parent device for vport + * @ids: The world wide names, FC4 port roles, etc for + * the virtual port. + * @ret_vport: The pointer to the created vport. + * + * Allocates and creates the vport structure, calls the parent host + * to instantiate the vport, the completes w/ class and sysfs creation. + * + * Notes: + * This routine assumes no locks are held on entry. + **/ +static int +fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev, + struct fc_vport_identifiers *ids, struct fc_vport **ret_vport) +{ + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); + struct fc_internal *fci = to_fc_internal(shost->transportt); + struct fc_vport *vport; + struct device *dev; + unsigned long flags; + size_t size; + int error; + + *ret_vport = NULL; + + if ( ! fci->f->vport_create) + return -ENOENT; + + size = (sizeof(struct fc_vport) + fci->f->dd_fcvport_size); + vport = kzalloc(size, GFP_KERNEL); + if (unlikely(!vport)) { + printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); + return -ENOMEM; + } + + vport->vport_state = FC_VPORT_UNKNOWN; + vport->vport_last_state = FC_VPORT_UNKNOWN; + vport->node_name = ids->node_name; + vport->port_name = ids->port_name; + vport->roles = ids->roles; + vport->vport_type = ids->vport_type; + if (fci->f->dd_fcvport_size) + vport->dd_data = &vport[1]; + vport->shost = shost; + vport->channel = channel; + vport->flags = FC_VPORT_CREATING; + INIT_WORK(&vport->vport_delete_work, fc_vport_sched_delete); + + spin_lock_irqsave(shost->host_lock, flags); + + if (fc_host->npiv_vports_inuse >= fc_host->max_npiv_vports) { + spin_unlock_irqrestore(shost->host_lock, flags); + kfree(vport); + return -ENOSPC; + } + fc_host->npiv_vports_inuse++; + vport->number = fc_host->next_vport_number++; + list_add_tail(&vport->peers, &fc_host->vports); + get_device(&shost->shost_gendev); /* for fc_host->vport list */ + + spin_unlock_irqrestore(shost->host_lock, flags); + + dev = &vport->dev; + device_initialize(dev); /* takes self reference */ + dev->parent = get_device(pdev); /* takes parent reference */ + dev->release = fc_vport_dev_release; + sprintf(dev->bus_id, "vport-%d:%d-%d", + shost->host_no, channel, vport->number); + transport_setup_device(dev); + + error = device_add(dev); + if (error) { + printk(KERN_ERR "FC Virtual Port device_add failed\n"); + goto delete_vport; + } + transport_add_device(dev); + transport_configure_device(dev); + + error = fci->f->vport_create(vport, ids->disable); + if (error) { + printk(KERN_ERR "FC Virtual Port LLDD Create failed\n"); + goto delete_vport_all; + } + + /* + * if the parent isn't the physical adapter's Scsi_Host, ensure + * the Scsi_Host at least contains ia symlink to the vport. + */ + if (pdev != &shost->shost_gendev) { + error = sysfs_create_link(&shost->shost_gendev.kobj, + &dev->kobj, dev->bus_id); + if (error) + printk(KERN_ERR + "%s: Cannot create vport symlinks for " + "%s, err=%d\n", + __FUNCTION__, dev->bus_id, error); + } + spin_lock_irqsave(shost->host_lock, flags); + vport->flags &= ~FC_VPORT_CREATING; + spin_unlock_irqrestore(shost->host_lock, flags); + + dev_printk(KERN_NOTICE, pdev, + "%s created via shost%d channel %d\n", dev->bus_id, + shost->host_no, channel); + + *ret_vport = vport; + + return 0; + +delete_vport_all: + transport_remove_device(dev); + device_del(dev); +delete_vport: + transport_destroy_device(dev); + spin_lock_irqsave(shost->host_lock, flags); + list_del(&vport->peers); + put_device(&shost->shost_gendev); /* for fc_host->vport list */ + fc_host->npiv_vports_inuse--; + spin_unlock_irqrestore(shost->host_lock, flags); + put_device(dev->parent); + kfree(vport); + + return error; +} + + +/** + * fc_vport_terminate - Admin App or LLDD requests termination of a vport + * @vport: fc_vport to be terminated + * + * Calls the LLDD vport_delete() function, then deallocates and removes + * the vport from the shost and object tree. + * + * Notes: + * This routine assumes no locks are held on entry. + **/ +int +fc_vport_terminate(struct fc_vport *vport) +{ + struct Scsi_Host *shost = vport_to_shost(vport); + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); + struct fc_internal *i = to_fc_internal(shost->transportt); + struct device *dev = &vport->dev; + unsigned long flags; + int stat; + + spin_lock_irqsave(shost->host_lock, flags); + if (vport->flags & FC_VPORT_CREATING) { + spin_unlock_irqrestore(shost->host_lock, flags); + return -EBUSY; + } + if (vport->flags & (FC_VPORT_DEL)) { + spin_unlock_irqrestore(shost->host_lock, flags); + return -EALREADY; + } + vport->flags |= FC_VPORT_DELETING; + spin_unlock_irqrestore(shost->host_lock, flags); + + if (i->f->vport_delete) + stat = i->f->vport_delete(vport); + else + stat = -ENOENT; + + spin_lock_irqsave(shost->host_lock, flags); + vport->flags &= ~FC_VPORT_DELETING; + if (!stat) { + vport->flags |= FC_VPORT_DELETED; + list_del(&vport->peers); + fc_host->npiv_vports_inuse--; + put_device(&shost->shost_gendev); /* for fc_host->vport list */ + } + spin_unlock_irqrestore(shost->host_lock, flags); + + if (stat) + return stat; + + if (dev->parent != &shost->shost_gendev) + sysfs_remove_link(&shost->shost_gendev.kobj, dev->bus_id); + transport_remove_device(dev); + device_del(dev); + transport_destroy_device(dev); + + /* + * Removing our self-reference should mean our + * release function gets called, which will drop the remaining + * parent reference and free the data structure. + */ + put_device(dev); /* for self-reference */ + + return 0; /* SUCCESS */ +} +EXPORT_SYMBOL(fc_vport_terminate); + +/** + * fc_vport_sched_delete - workq-based delete request for a vport + * + * @work: vport to be deleted. + **/ +static void +fc_vport_sched_delete(struct work_struct *work) +{ + struct fc_vport *vport = + container_of(work, struct fc_vport, vport_delete_work); + int stat; + + stat = fc_vport_terminate(vport); + if (stat) + dev_printk(KERN_ERR, vport->dev.parent, + "%s: %s could not be deleted created via " + "shost%d channel %d - error %d\n", __FUNCTION__, + vport->dev.bus_id, vport->shost->host_no, + vport->channel, stat); +} + + +/* Original Author: Martin Hicks */ +MODULE_AUTHOR("James Smart"); MODULE_DESCRIPTION("FC Transport Attributes"); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3d8c9cb24f91..448d316f12d7 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1515,7 +1515,7 @@ static int sd_revalidate_disk(struct gendisk *disk) if (!scsi_device_online(sdp)) goto out; - buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA); + buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL); if (!buffer) { sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory " "allocation failure.\n"); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 0c691a60a756..85d38940a6c9 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1842,7 +1842,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) int blk_size = buff_size; struct page *p = NULL; - if ((blk_size < 0) || (!sfp)) + if (blk_size < 0) return -EFAULT; if (0 == blk_size) ++blk_size; /* don't know why */ diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 9ac83abc4028..adda296b594b 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -395,53 +395,34 @@ static struct req_msg *stex_alloc_req(struct st_hba *hba) static int stex_map_sg(struct st_hba *hba, struct req_msg *req, struct st_ccb *ccb) { - struct pci_dev *pdev = hba->pdev; struct scsi_cmnd *cmd; - dma_addr_t dma_handle; - struct scatterlist *src; + struct scatterlist *sg; struct st_sgtable *dst; - int i; + int i, nseg; cmd = ccb->cmd; dst = (struct st_sgtable *)req->variable; dst->max_sg_count = cpu_to_le16(ST_MAX_SG); - dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen); - - if (cmd->use_sg) { - int n_elem; + dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd)); - src = (struct scatterlist *) cmd->request_buffer; - n_elem = pci_map_sg(pdev, src, - cmd->use_sg, cmd->sc_data_direction); - if (n_elem <= 0) - return -EIO; + nseg = scsi_dma_map(cmd); + if (nseg < 0) + return -EIO; + if (nseg) { + ccb->sg_count = nseg; + dst->sg_count = cpu_to_le16((u16)nseg); - ccb->sg_count = n_elem; - dst->sg_count = cpu_to_le16((u16)n_elem); - - for (i = 0; i < n_elem; i++, src++) { - dst->table[i].count = cpu_to_le32((u32)sg_dma_len(src)); + scsi_for_each_sg(cmd, sg, nseg, i) { + dst->table[i].count = cpu_to_le32((u32)sg_dma_len(sg)); dst->table[i].addr = - cpu_to_le32(sg_dma_address(src) & 0xffffffff); + cpu_to_le32(sg_dma_address(sg) & 0xffffffff); dst->table[i].addr_hi = - cpu_to_le32((sg_dma_address(src) >> 16) >> 16); + cpu_to_le32((sg_dma_address(sg) >> 16) >> 16); dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST; } dst->table[--i].ctrl |= SG_CF_EOT; - return 0; } - dma_handle = pci_map_single(pdev, cmd->request_buffer, - cmd->request_bufflen, cmd->sc_data_direction); - cmd->SCp.dma_handle = dma_handle; - - ccb->sg_count = 1; - dst->sg_count = cpu_to_le16(1); - dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff); - dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16); - dst->table[0].count = cpu_to_le32((u32)cmd->request_bufflen); - dst->table[0].ctrl = SG_CF_EOT | SG_CF_64B | SG_CF_HOST; - return 0; } @@ -451,24 +432,24 @@ static void stex_internal_copy(struct scsi_cmnd *cmd, size_t lcount; size_t len; void *s, *d, *base = NULL; - if (*count > cmd->request_bufflen) - *count = cmd->request_bufflen; + size_t offset; + + if (*count > scsi_bufflen(cmd)) + *count = scsi_bufflen(cmd); lcount = *count; while (lcount) { len = lcount; s = (void *)src; - if (cmd->use_sg) { - size_t offset = *count - lcount; - s += offset; - base = scsi_kmap_atomic_sg(cmd->request_buffer, - sg_count, &offset, &len); - if (base == NULL) { - *count -= lcount; - return; - } - d = base + offset; - } else - d = cmd->request_buffer; + + offset = *count - lcount; + s += offset; + base = scsi_kmap_atomic_sg(scsi_sglist(cmd), + sg_count, &offset, &len); + if (!base) { + *count -= lcount; + return; + } + d = base + offset; if (direction == ST_TO_CMD) memcpy(d, s, len); @@ -476,30 +457,24 @@ static void stex_internal_copy(struct scsi_cmnd *cmd, memcpy(s, d, len); lcount -= len; - if (cmd->use_sg) - scsi_kunmap_atomic_sg(base); + scsi_kunmap_atomic_sg(base); } } static int stex_direct_copy(struct scsi_cmnd *cmd, const void *src, size_t count) { - struct st_hba *hba = (struct st_hba *) &cmd->device->host->hostdata[0]; size_t cp_len = count; int n_elem = 0; - if (cmd->use_sg) { - n_elem = pci_map_sg(hba->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); - if (n_elem <= 0) - return 0; - } + n_elem = scsi_dma_map(cmd); + if (n_elem < 0) + return 0; stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD); - if (cmd->use_sg) - pci_unmap_sg(hba->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); + scsi_dma_unmap(cmd); + return cp_len == count; } @@ -678,18 +653,6 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) return 0; } -static void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd) -{ - if (cmd->sc_data_direction != DMA_NONE) { - if (cmd->use_sg) - pci_unmap_sg(hba->pdev, cmd->request_buffer, - cmd->use_sg, cmd->sc_data_direction); - else - pci_unmap_single(hba->pdev, cmd->SCp.dma_handle, - cmd->request_bufflen, cmd->sc_data_direction); - } -} - static void stex_scsi_done(struct st_ccb *ccb) { struct scsi_cmnd *cmd = ccb->cmd; @@ -756,7 +719,7 @@ static void stex_ys_commands(struct st_hba *hba, if (ccb->cmd->cmnd[0] == MGT_CMD && resp->scsi_status != SAM_STAT_CHECK_CONDITION) { - ccb->cmd->request_bufflen = + scsi_bufflen(ccb->cmd) = le32_to_cpu(*(__le32 *)&resp->variable[0]); return; } @@ -855,7 +818,7 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell) ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER)) stex_controller_info(hba, ccb); - stex_unmap_sg(hba, ccb->cmd); + scsi_dma_unmap(ccb->cmd); stex_scsi_done(ccb); hba->out_req_cnt--; } else if (ccb->req_type & PASSTHRU_REQ_TYPE) { @@ -1028,7 +991,7 @@ static int stex_abort(struct scsi_cmnd *cmd) } fail_out: - stex_unmap_sg(hba, cmd); + scsi_dma_unmap(cmd); hba->wait_ccb->req = NULL; /* nullify the req's future return */ hba->wait_ccb = NULL; result = FAILED; diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c index 2ca950582bc3..92bfaeafe30d 100644 --- a/drivers/scsi/sym53c416.c +++ b/drivers/scsi/sym53c416.c @@ -332,8 +332,7 @@ static irqreturn_t sym53c416_intr_handle(int irq, void *dev_id) int i; unsigned long flags = 0; unsigned char status_reg, pio_int_reg, int_reg; - struct scatterlist *sglist; - unsigned int sgcount; + struct scatterlist *sg; unsigned int tot_trans = 0; /* We search the base address of the host adapter which caused the interrupt */ @@ -429,19 +428,15 @@ static irqreturn_t sym53c416_intr_handle(int irq, void *dev_id) { current_command->SCp.phase = data_out; outb(FLUSH_FIFO, base + COMMAND_REG); - sym53c416_set_transfer_counter(base, current_command->request_bufflen); + sym53c416_set_transfer_counter(base, + scsi_bufflen(current_command)); outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); - if(!current_command->use_sg) - tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen); - else - { - sgcount = current_command->use_sg; - sglist = current_command->request_buffer; - while(sgcount--) - { - tot_trans += sym53c416_write(base, SG_ADDRESS(sglist), sglist->length); - sglist++; - } + + scsi_for_each_sg(current_command, + sg, scsi_sg_count(current_command), i) { + tot_trans += sym53c416_write(base, + SG_ADDRESS(sg), + sg->length); } if(tot_trans < current_command->underflow) printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow); @@ -455,19 +450,16 @@ static irqreturn_t sym53c416_intr_handle(int irq, void *dev_id) { current_command->SCp.phase = data_in; outb(FLUSH_FIFO, base + COMMAND_REG); - sym53c416_set_transfer_counter(base, current_command->request_bufflen); + sym53c416_set_transfer_counter(base, + scsi_bufflen(current_command)); + outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); - if(!current_command->use_sg) - tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen); - else - { - sgcount = current_command->use_sg; - sglist = current_command->request_buffer; - while(sgcount--) - { - tot_trans += sym53c416_read(base, SG_ADDRESS(sglist), sglist->length); - sglist++; - } + + scsi_for_each_sg(current_command, + sg, scsi_sg_count(current_command), i) { + tot_trans += sym53c416_read(base, + SG_ADDRESS(sg), + sg->length); } if(tot_trans < current_command->underflow) printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow); diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index e7b85e832eb5..73c5ca082e65 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -457,28 +457,21 @@ static int dc390_pci_map (struct dc390_srb* pSRB) error = 1; DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle)); /* Map SG list */ - } else if (pcmd->use_sg) { - pSRB->pSegmentList = (struct scatterlist *) pcmd->request_buffer; - pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, pcmd->use_sg, - pcmd->sc_data_direction); + } else if (scsi_sg_count(pcmd)) { + int nseg; + + nseg = scsi_dma_map(pcmd); + + pSRB->pSegmentList = scsi_sglist(pcmd); + pSRB->SGcount = nseg; + /* TODO: error handling */ - if (!pSRB->SGcount) + if (nseg < 0) error = 1; DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\ - __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg)); + __FUNCTION__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd))); /* Map single segment */ - } else if (pcmd->request_buffer && pcmd->request_bufflen) { - pSRB->pSegmentList = dc390_sg_build_single(&pSRB->Segmentx, pcmd->request_buffer, pcmd->request_bufflen); - pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, 1, - pcmd->sc_data_direction); - cmdp->saved_dma_handle = sg_dma_address(pSRB->pSegmentList); - - /* TODO: error handling */ - if (pSRB->SGcount != 1) - error = 1; - DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle)); - /* No mapping !? */ - } else + } else pSRB->SGcount = 0; return error; @@ -494,12 +487,10 @@ static void dc390_pci_unmap (struct dc390_srb* pSRB) if (pSRB->SRBFlag) { pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE); DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle)); - } else if (pcmd->use_sg) { - pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, pcmd->sc_data_direction); - DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", __FUNCTION__, pcmd->request_buffer, pcmd->use_sg)); - } else if (pcmd->request_buffer && pcmd->request_bufflen) { - pci_unmap_sg(pdev, &pSRB->Segmentx, 1, pcmd->sc_data_direction); - DEBUG1(printk("%s(): Unmapped request buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle)); + } else { + scsi_dma_unmap(pcmd); + DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", + __FUNCTION__, scsi_sglist(pcmd), scsi_sg_count(pcmd))); } } @@ -1153,9 +1144,9 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) struct scatterlist *psgl; pSRB->TotalXferredLen = 0; pSRB->SGIndex = 0; - if (pcmd->use_sg) { + if (scsi_sg_count(pcmd)) { size_t saved; - pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer; + pSRB->pSegmentList = scsi_sglist(pcmd); psgl = pSRB->pSegmentList; //dc390_pci_sync(pSRB); @@ -1179,12 +1170,6 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr); - } else if(pcmd->request_buffer) { - //dc390_pci_sync(pSRB); - - sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr; - pSRB->SGcount = 1; - pSRB->pSegmentList = (struct scatterlist *) &pSRB->Segmentx; } else { pSRB->SGcount = 0; printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n"); @@ -1612,7 +1597,7 @@ dc390_Reselect( struct dc390_acb* pACB ) if( !( pACB->scan_devices ) ) { struct scsi_cmnd *pcmd = pSRB->pcmd; - pcmd->resid = pcmd->request_bufflen; + scsi_set_resid(pcmd, scsi_bufflen(pcmd)); SET_RES_DID(pcmd->result, DID_SOFT_ERROR); dc390_Going_remove(pDCB, pSRB); dc390_Free_insert(pACB, pSRB); @@ -1695,7 +1680,7 @@ dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_ pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN)); pSRB->SRBFlag |= AUTO_REQSENSE; - pSRB->SavedSGCount = pcmd->use_sg; + pSRB->SavedSGCount = scsi_sg_count(pcmd); pSRB->SavedTotXLen = pSRB->TotalXferredLen; pSRB->AdaptStatus = 0; pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */ @@ -1743,7 +1728,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* (u32) pcmd->result, (u32) pSRB->TotalXferredLen)); } else { SET_RES_DRV(pcmd->result, DRIVER_SENSE); - pcmd->use_sg = pSRB->SavedSGCount; + scsi_sg_count(pcmd) = pSRB->SavedSGCount; //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8); DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); pSRB->TotalXferredLen = 0; @@ -1765,7 +1750,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* else if( status_byte(status) == QUEUE_FULL ) { scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1); - pcmd->use_sg = pSRB->SavedSGCount; + scsi_sg_count(pcmd) = pSRB->SavedSGCount; DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); @@ -1816,7 +1801,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* } cmd_done: - pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen; + scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen); dc390_Going_remove (pDCB, pSRB); /* Add to free list */ diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 3de08a15de40..9e8232a1f169 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1111,7 +1111,7 @@ static int u14_34f_detect(struct scsi_host_template *tpnt) { static void map_dma(unsigned int i, unsigned int j) { unsigned int data_len = 0; unsigned int k, count, pci_dir; - struct scatterlist *sgpnt; + struct scatterlist *sg; struct mscp *cpp; struct scsi_cmnd *SCpnt; @@ -1124,33 +1124,28 @@ static void map_dma(unsigned int i, unsigned int j) { cpp->sense_len = sizeof SCpnt->sense_buffer; - if (!SCpnt->use_sg) { - - /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */ - if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL; - - if (SCpnt->request_buffer) - cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, - SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir)); - - cpp->data_len = H2DEV(SCpnt->request_bufflen); - return; - } - - sgpnt = (struct scatterlist *) SCpnt->request_buffer; - count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir); - - for (k = 0; k < count; k++) { - cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k])); - cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k])); - data_len += sgpnt[k].length; - } - - cpp->sg = TRUE; - cpp->use_sg = SCpnt->use_sg; - cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist, - SCpnt->use_sg * sizeof(struct sg_list), pci_dir)); - cpp->data_len = H2DEV(data_len); + if (scsi_bufflen(SCpnt)) { + count = scsi_dma_map(SCpnt); + BUG_ON(count < 0); + + scsi_for_each_sg(SCpnt, sg, count, k) { + cpp->sglist[k].address = H2DEV(sg_dma_address(sg)); + cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(sg)); + data_len += sg->length; + } + + cpp->sg = TRUE; + cpp->use_sg = scsi_sg_count(SCpnt); + cpp->data_address = + H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist, + cpp->use_sg * sizeof(struct sg_list), + pci_dir)); + cpp->data_len = H2DEV(data_len); + + } else { + pci_dir = PCI_DMA_BIDIRECTIONAL; + cpp->data_len = H2DEV(scsi_bufflen(SCpnt)); + } } static void unmap_dma(unsigned int i, unsigned int j) { @@ -1165,8 +1160,7 @@ static void unmap_dma(unsigned int i, unsigned int j) { pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr), DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - if (SCpnt->use_sg) - pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir); + scsi_dma_unmap(SCpnt); if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; @@ -1187,9 +1181,9 @@ static void sync_dma(unsigned int i, unsigned int j) { pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr), DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE); - if (SCpnt->use_sg) - pci_dma_sync_sg_for_cpu(HD(j)->pdev, SCpnt->request_buffer, - SCpnt->use_sg, pci_dir); + if (scsi_sg_count(SCpnt)) + pci_dma_sync_sg_for_cpu(HD(j)->pdev, scsi_sglist(SCpnt), + scsi_sg_count(SCpnt), pci_dir); if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL; diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 56906aba5ee3..c08235d5afc9 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -675,16 +675,15 @@ static const char *ultrastor_info(struct Scsi_Host * shpnt) static inline void build_sg_list(struct mscp *mscp, struct scsi_cmnd *SCpnt) { - struct scatterlist *sl; + struct scatterlist *sg; long transfer_length = 0; int i, max; - sl = (struct scatterlist *) SCpnt->request_buffer; - max = SCpnt->use_sg; - for (i = 0; i < max; i++) { - mscp->sglist[i].address = isa_page_to_bus(sl[i].page) + sl[i].offset; - mscp->sglist[i].num_bytes = sl[i].length; - transfer_length += sl[i].length; + max = scsi_sg_count(SCpnt); + scsi_for_each_sg(SCpnt, sg, max, i) { + mscp->sglist[i].address = isa_page_to_bus(sg->page) + sg->offset; + mscp->sglist[i].num_bytes = sg->length; + transfer_length += sg->length; } mscp->number_of_sg_list = max; mscp->transfer_data = isa_virt_to_bus(mscp->sglist); @@ -730,15 +729,15 @@ static int ultrastor_queuecommand(struct scsi_cmnd *SCpnt, my_mscp->target_id = SCpnt->device->id; my_mscp->ch_no = 0; my_mscp->lun = SCpnt->device->lun; - if (SCpnt->use_sg) { + if (scsi_sg_count(SCpnt)) { /* Set scatter/gather flag in SCSI command packet */ my_mscp->sg = TRUE; build_sg_list(my_mscp, SCpnt); } else { /* Unset scatter/gather flag in SCSI command packet */ my_mscp->sg = FALSE; - my_mscp->transfer_data = isa_virt_to_bus(SCpnt->request_buffer); - my_mscp->transfer_data_length = SCpnt->request_bufflen; + my_mscp->transfer_data = isa_virt_to_bus(scsi_sglist(SCpnt)); + my_mscp->transfer_data_length = scsi_bufflen(SCpnt); } my_mscp->command_link = 0; /*???*/ my_mscp->scsi_command_link_id = 0; /*???*/ diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index 30be76514c43..d6fd4259c56b 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -1091,6 +1091,7 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt, unchar *cdb = (unchar *) SCpnt->cmnd; unchar idlun; short cdblen; + int nseg; Adapter *host = (Adapter *) SCpnt->device->host->hostdata; cdblen = SCpnt->cmd_len; @@ -1106,28 +1107,29 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt, SCpnt->host_scribble = (unchar *) scb; scb->host = host; - if (SCpnt->use_sg) { - struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer; + nseg = scsi_sg_count(SCpnt); + if (nseg) { + struct scatterlist *sg; unsigned i; if (SCpnt->device->host->sg_tablesize == SG_NONE) { panic("wd7000_queuecommand: scatter/gather not supported.\n"); } - dprintk("Using scatter/gather with %d elements.\n", SCpnt->use_sg); + dprintk("Using scatter/gather with %d elements.\n", nseg); sgb = scb->sgb; scb->op = 1; any2scsi(scb->dataptr, (int) sgb); - any2scsi(scb->maxlen, SCpnt->use_sg * sizeof(Sgb)); + any2scsi(scb->maxlen, nseg * sizeof(Sgb)); - for (i = 0; i < SCpnt->use_sg; i++) { - any2scsi(sgb[i].ptr, isa_page_to_bus(sg[i].page) + sg[i].offset); - any2scsi(sgb[i].len, sg[i].length); + scsi_for_each_sg(SCpnt, sg, nseg, i) { + any2scsi(sgb[i].ptr, isa_page_to_bus(sg->page) + sg->offset); + any2scsi(sgb[i].len, sg->length); } } else { scb->op = 0; - any2scsi(scb->dataptr, isa_virt_to_bus(SCpnt->request_buffer)); - any2scsi(scb->maxlen, SCpnt->request_bufflen); + any2scsi(scb->dataptr, isa_virt_to_bus(scsi_sglist(SCpnt))); + any2scsi(scb->maxlen, scsi_bufflen(SCpnt)); } /* FIXME: drop lock and yield here ? */ |