📄 qlogicfc.c
字号:
#endif param[0] = MBOX_GET_INIT_SCSI_ID; isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { hostdata->port_id = ((u_int) param[3]) << 16; hostdata->port_id |= param[2]; temp[0].loop_id = param[1]; temp[0].wwn = hostdata->wwn; } else { printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id); } for (i = 0; i <=QLOGICFC_MAX_ID; i++) temp[i].loop_id = temp[0].loop_id; for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) { param[0] = MBOX_GET_PORT_NAME; param[1] = (i << 8) & 0xff00; isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { temp[j].loop_id = i; temp[j].wwn = ((u64) (param[2] & 0xff)) << 56; temp[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48; temp[j].wwn |= ((u64) (param[3] & 0xff)) << 40; temp[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32; temp[j].wwn |= ((u64) (param[6] & 0xff)) << 24; temp[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16; temp[j].wwn |= ((u64) (param[7] & 0xff)) << 8; temp[j].wwn |= ((u64) ((param[7] >> 8) & 0xff)); j++; } }#if ISP2x00_FABRIC isp2x00_init_fabric(host, temp, j);#endif for (i = 0; i <= QLOGICFC_MAX_ID; i++) { if (temp[i].wwn != hostdata->port_db[i].wwn) { for (j = 0; j <= QLOGICFC_MAX_ID; j++) { if (temp[j].wwn == hostdata->port_db[i].wwn) { hostdata->port_db[i].loop_id = temp[j].loop_id; break; } } if (j == QLOGICFC_MAX_ID + 1) hostdata->port_db[i].loop_id = temp[0].loop_id; for (j = 0; j <= QLOGICFC_MAX_ID; j++) { if (hostdata->port_db[j].wwn == temp[i].wwn || !hostdata->port_db[j].wwn) { break; } } if (j == QLOGICFC_MAX_ID + 1) printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id); if (!hostdata->port_db[j].wwn) { hostdata->port_db[j].loop_id = temp[i].loop_id; hostdata->port_db[j].wwn = temp[i].wwn; } } else hostdata->port_db[i].loop_id = temp[i].loop_id; } isp2x00_enable_irqs(host); return 0;}#if ISP2x00_FABRIC#define FABRIC_PORT 0x7e#define FABRIC_CONTROLLER 0x7f#define FABRIC_SNS 0x80int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int cur_scsi_id){ u_short param[8]; u64 wwn; int done = 0; u_short loop_id = 0x81; u_short scsi_id = cur_scsi_id; u_int port_id; struct sns_cb *req; u_char *sns_response; dma64_addr_t busaddr; struct isp2x00_hostdata *hostdata; hostdata = (struct isp2x00_hostdata *) host->hostdata; DEBUG_FABRIC(printk("qlogicfc%d : Checking for a fabric.\n", hostdata->host_id)); param[0] = MBOX_GET_PORT_NAME; param[1] = (u16)FABRIC_PORT << 8; isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { DEBUG_FABRIC(printk("qlogicfc%d : fabric check result %x\n", hostdata->host_id, param[0])); return 0; } printk("qlogicfc%d : Fabric found.\n", hostdata->host_id); req = (struct sns_cb *)pci64_alloc_consistent(hostdata->pci_dev, sizeof(*req) + 608, &busaddr); if (!req){ printk("qlogicfc%d : Could not allocate DMA resources for fabric initialization\n", hostdata->host_id); return 0; } sns_response = (u_char *)(req + 1); if (hostdata->adapter_state & AS_REDO_LOOP_PORTDB){ memset(req, 0, sizeof(*req)); req->len = cpu_to_le16(8); req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req))); req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req))); req->sub_len = cpu_to_le16(22); req->data[0] = 0x17; req->data[1] = 0x02; req->data[8] = (u_char) (hostdata->port_id & 0xff); req->data[9] = (u_char) (hostdata->port_id >> 8 & 0xff); req->data[10] = (u_char) (hostdata->port_id >> 16 & 0xff); req->data[13] = 0x01; param[0] = MBOX_SEND_SNS; param[1] = 30; param[2] = pci64_dma_lo32(busaddr) >> 16; param[3] = pci64_dma_lo32(busaddr); param[6] = pci64_dma_hi32(busaddr) >> 16; param[7] = pci64_dma_hi32(busaddr); isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id); } port_id = hostdata->port_id; while (!done) { memset(req, 0, sizeof(*req)); req->len = cpu_to_le16(304); req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req))); req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req))); req->sub_len = cpu_to_le16(6); req->data[0] = 0x00; req->data[1] = 0x01; req->data[8] = (u_char) (port_id & 0xff); req->data[9] = (u_char) (port_id >> 8 & 0xff); req->data[10] = (u_char) (port_id >> 16 & 0xff); param[0] = MBOX_SEND_SNS; param[1] = 14; param[2] = pci64_dma_lo32(busaddr) >> 16; param[3] = pci64_dma_lo32(busaddr); param[6] = pci64_dma_hi32(busaddr) >> 16; param[7] = pci64_dma_hi32(busaddr); isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { DEBUG_FABRIC(printk("qlogicfc%d : found node %02x%02x%02x%02x%02x%02x%02x%02x ", hostdata->host_id, sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27])); DEBUG_FABRIC(printk(" port id: %02x%02x%02x\n", sns_response[17], sns_response[18], sns_response[19])); port_id = ((u_int) sns_response[17]) << 16; port_id |= ((u_int) sns_response[18]) << 8; port_id |= ((u_int) sns_response[19]); wwn = ((u64) sns_response[20]) << 56; wwn |= ((u64) sns_response[21]) << 48; wwn |= ((u64) sns_response[22]) << 40; wwn |= ((u64) sns_response[23]) << 32; wwn |= ((u64) sns_response[24]) << 24; wwn |= ((u64) sns_response[25]) << 16; wwn |= ((u64) sns_response[26]) << 8; wwn |= ((u64) sns_response[27]); if (hostdata->port_id >> 8 != port_id >> 8) { DEBUG_FABRIC(printk("qlogicfc%d : adding a fabric port: %x\n", hostdata->host_id, port_id)); param[0] = MBOX_PORT_LOGIN; param[1] = loop_id << 8; param[2] = (u_short) (port_id >> 16); param[3] = (u_short) (port_id); isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { port_db[scsi_id].wwn = wwn; port_db[scsi_id].loop_id = loop_id; loop_id++; scsi_id++; } else { printk("qlogicfc%d : Error performing port login %x\n", hostdata->host_id, param[0]); DEBUG_FABRIC(printk("qlogicfc%d : loop_id: %x\n", hostdata->host_id, loop_id)); param[0] = MBOX_PORT_LOGOUT; param[1] = loop_id << 8; param[2] = 0; param[3] = 0; isp2x00_mbox_command(host, param); } } if (hostdata->port_id == port_id) done = 1; } else { printk("qlogicfc%d : Get All Next failed %x.\n", hostdata->host_id, param[0]); pci64_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr); return 0; } } pci64_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr); return 1;}#endif /* ISP2x00_FABRIC */int isp2x00_release(struct Scsi_Host *host){ struct isp2x00_hostdata *hostdata; dma64_addr_t busaddr; ENTER("isp2x00_release"); hostdata = (struct isp2x00_hostdata *) host->hostdata; outw(0x0, host->io_port + PCI_INTER_CTL); free_irq(host->irq, host); release_region(host->io_port, 0xff); busaddr = pci64_dma_build(le32_to_cpu(hostdata->control_block.res_queue_addr_high), le32_to_cpu(hostdata->control_block.res_queue_addr_lo)); pci64_free_consistent(hostdata->pci_dev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr); LEAVE("isp2x00_release"); return 0;}const char *isp2x00_info(struct Scsi_Host *host){ static char buf[80]; struct isp2x00_hostdata *hostdata; ENTER("isp2x00_info"); hostdata = (struct isp2x00_hostdata *) host->hostdata; sprintf(buf, "QLogic ISP%04x SCSI on PCI bus %02x device %02x irq %d base 0x%lx", hostdata->pci_dev->device, hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq, host->io_port); LEAVE("isp2x00_info"); return buf;}/* * The middle SCSI layer ensures that queuecommand never gets invoked * concurrently with itself or the interrupt handler (though the * interrupt handler may call this routine as part of * request-completion handling). */int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)){ int i, sg_count, n, num_free; u_int in_ptr, out_ptr; struct dataseg *ds; struct scatterlist *sg; struct Command_Entry *cmd; struct Continuation_Entry *cont; struct Scsi_Host *host; struct isp2x00_hostdata *hostdata; ENTER("isp2x00_queuecommand"); host = Cmnd->host; hostdata = (struct isp2x00_hostdata *) host->hostdata; Cmnd->scsi_done = done; DEBUG(isp2x00_print_scsi_cmd(Cmnd)); if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) { isp2x00_make_portdb(host); hostdata->adapter_state = AS_LOOP_GOOD; printk("qlogicfc%d : Port Database\n", hostdata->host_id); for (i = 0; hostdata->port_db[i].wwn != 0; i++) { printk("wwn: %08x%08x scsi_id: %x loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i); if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0) printk("%x", hostdata->port_db[i].loop_id); else printk("Not Available"); printk("\n"); } } if (hostdata->adapter_state == AS_FIRMWARE_DEAD) { printk("qlogicfc%d : The firmware is dead, just return.\n", hostdata->host_id); host->max_id = 0; return 0; } out_ptr = inw(host->io_port + MBOX4); in_ptr = hostdata->req_in_ptr; DEBUG(printk("qlogicfc%d : request queue depth %d\n", hostdata->host_id, REQ_QUEUE_DEPTH(in_ptr, out_ptr))); cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN]; in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN; if (in_ptr == out_ptr) { DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id)); return 1; } if (hostdata->send_marker) { struct Marker_Entry *marker; TRACE("queue marker", in_ptr, 0); DEBUG(printk("qlogicfc%d : adding marker entry\n", hostdata->host_id)); marker = (struct Marker_Entry *) cmd; memset(marker, 0, sizeof(struct Marker_Entry)); marker->hdr.entry_type = ENTRY_MARKER; marker->hdr.entry_cnt = 1; marker->modifier = SYNC_ALL; hostdata->send_marker = 0; if (((in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN) == out_ptr) { outw(in_ptr, host->io_port + MBOX4); hostdata->req_in_ptr = in_ptr; DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id)); return 1; } cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN]; in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN; } TRACE("queue command", in_ptr, Cmnd); memset(cmd, 0, sizeof(struct Command_Entry)); /* find a free handle mapping slot */ for (i = in_ptr; i != (in_ptr - 1) && hostdata->handle_ptrs[i]; i = ((i + 1) % (QLOGICFC_REQ_QUEUE_LEN + 1))); if (!hostdata->handle_ptrs[i]) { cmd->handle = cpu_to_le32(i); hostdata->handle_ptrs[i] = Cmnd; hostdata->handle_serials[i] = Cmnd->serial_number; } else { printk("qlogicfc%d : no handle slots, this should not happen.\n", hostdata->host_id); printk("hostdata->queued is %x, in_ptr: %x\n", hostdata->queued, in_ptr); for (i = 0; i <= QLOGICFC_REQ_QUEUE_LEN; i++){ if (!hostdata->handle_ptrs[i]){ printk("slot %d has %p\n", i, hostdata->handle_ptrs[i]); } } return 1; } cmd->hdr.entry_type = ENTRY_COMMAND; cmd->hdr.entry_cnt = 1; cmd->target_lun = Cmnd->lun; cmd->expanded_lun = cpu_to_le16(Cmnd->lun);#if ISP2x00_PORTDB cmd->target_id = hostdata->port_db[Cmnd->target].loop_id;#else cmd->target_id = Cmnd->target;#endif cmd->total_byte_cnt = cpu_to_le32(Cmnd->request_bufflen); cmd->time_out = 0; memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len); if (Cmnd->use_sg) { sg = (struct scatterlist *) Cmnd->request_buffer; sg_count = pci64_map_sg(hostdata->pci_dev, sg, Cmnd->use_sg, scsi_to_pci_dma_dir(Cmnd->sc_data_direction)); cmd->segment_cnt = cpu_to_le16(sg_count); ds = cmd->dataseg; /* fill in first two sg entries: */ n = sg_count; if (n > DATASEGS_PER_COMMAND) n = DATASEGS_PER_COMMAND; for (i = 0; i < n; i++) { ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma64_address(sg)));#if PCI64_DMA_BITS > 32 ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma64_address(sg)));#endif ds[i].d_count = cpu_to_le32(sg_dma64_len(sg)); ++sg; } sg_count -= DATASEGS_PER_COMMAND; while (sg_count > 0) { ++cmd->hdr.entry_cnt; cont = (struct Continuation_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN]; memset(cont, 0, sizeof(struct Continuation_Entry)); in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN; if (in_ptr == out_ptr) { DEBUG(printk("qlogicfc%d : unexpected request queue overflow\n", hostdata->host_id)); return 1; } TRACE("queue continuation", in_ptr, 0); cont->hdr.entry_type = ENTRY_CONTINUATION; ds = cont->dataseg; n = sg_count; if (n > DATASEGS_PER_CONT) n = DATASEGS_PER_CONT; for (i = 0; i < n; ++i) { ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma64_address(sg)));#if PCI64_DMA_BITS > 32 ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma64_address(sg)));#endif ds[i].d_count = cpu_to_le32(sg_dma64_len(sg)); ++sg; } sg_count -= n; } } else if (Cmnd->request_bufflen && Cmnd->sc_data_direction != PCI_DMA_NONE) { dma64_addr_t busaddr = pci64_map_single(hostdata->pci_dev, Cmnd->request_buffer, Cmnd->request_bufflen, scsi_to_pci_dma_dir(Cmnd->sc_data_direction)); *(dma64_addr_t *)&Cmnd->SCp = busaddr; cmd->dataseg[0].d_base = cpu_to_le32(pci64_dma_lo32(busaddr));#if PCI64_DMA_BITS > 32 cmd->dataseg[0].d_base_hi = cpu_to_le32(pci64_dma_hi32(busaddr));#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -