⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qlogicfc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 + -