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

📄 qlogicisp.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	hostdata = (struct isp1020_hostdata *) host->hostdata;	DEBUG_INTR(printk("qlogicisp : interrupt on line %d\n", irq));	if (!(inw(host->io_port + PCI_INTF_STS) & 0x04)) {		/* spurious interrupts can happen legally */		DEBUG_INTR(printk("qlogicisp: got spurious interrupt\n"));		return;	}	in_ptr = inw(host->io_port + MBOX5);	outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);	if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {		status = inw(host->io_port + MBOX0);		DEBUG_INTR(printk("qlogicisp : mbox completion status: %x\n",				  status));		switch (status) {		      case ASYNC_SCSI_BUS_RESET:		      case EXECUTION_TIMEOUT_RESET:			hostdata->send_marker = 1;			break;		      case INVALID_COMMAND:		      case HOST_INTERFACE_ERROR:		      case COMMAND_ERROR:		      case COMMAND_PARAM_ERROR:			printk("qlogicisp : bad mailbox return status\n");			break;		}		outw(0x0, host->io_port + PCI_SEMAPHORE);	}	out_ptr = hostdata->res_out_ptr;	DEBUG_INTR(printk("qlogicisp : response queue update\n"));	DEBUG_INTR(printk("qlogicisp : response queue depth %d\n",			  QUEUE_DEPTH(in_ptr, out_ptr)));	while (out_ptr != in_ptr) {		sts = (struct Status_Entry *) &hostdata->res[out_ptr][0];		out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;		Cmnd = (Scsi_Cmnd *) bus_to_virt(sts->handle);		TRACE("done", out_ptr, Cmnd);		if (sts->completion_status == CS_RESET_OCCURRED		    || sts->completion_status == CS_ABORTED		    || (sts->status_flags & STF_BUS_RESET))			hostdata->send_marker = 1;		if (sts->state_flags & SF_GOT_SENSE)			memcpy(Cmnd->sense_buffer, sts->req_sense_data,			       sizeof(Cmnd->sense_buffer));		DEBUG_INTR(isp1020_print_status_entry(sts));		if (sts->hdr.entry_type == ENTRY_STATUS)			Cmnd->result = isp1020_return_status(sts);		else			Cmnd->result = DID_ERROR << 16;		outw(out_ptr, host->io_port + MBOX5);		(*Cmnd->scsi_done)(Cmnd);	}	hostdata->res_out_ptr = out_ptr;	LEAVE_INTR("isp1020_intr_handler");}static int isp1020_return_status(struct Status_Entry *sts){	int host_status = DID_ERROR;#if DEBUG_ISP1020_INTR	static char *reason[] = {		"DID_OK",		"DID_NO_CONNECT",		"DID_BUS_BUSY",		"DID_TIME_OUT",		"DID_BAD_TARGET",		"DID_ABORT",		"DID_PARITY",		"DID_ERROR",		"DID_RESET",		"DID_BAD_INTR"	};#endif /* DEBUG_ISP1020_INTR */	ENTER("isp1020_return_status");	DEBUG(printk("qlogicisp : completion status = 0x%04x\n",		     sts->completion_status));	switch(sts->completion_status) {	      case CS_COMPLETE:		host_status = DID_OK;		break;	      case CS_INCOMPLETE:		if (!(sts->state_flags & SF_GOT_BUS))			host_status = DID_NO_CONNECT;		else if (!(sts->state_flags & SF_GOT_TARGET))			host_status = DID_BAD_TARGET;		else if (!(sts->state_flags & SF_SENT_CDB))			host_status = DID_ERROR;		else if (!(sts->state_flags & SF_TRANSFERRED_DATA))			host_status = DID_ERROR;		else if (!(sts->state_flags & SF_GOT_STATUS))			host_status = DID_ERROR;		else if (!(sts->state_flags & SF_GOT_SENSE))			host_status = DID_ERROR;		break;	      case CS_DMA_ERROR:	      case CS_TRANSPORT_ERROR:		host_status = DID_ERROR;		break;	      case CS_RESET_OCCURRED:		host_status = DID_RESET;		break;	      case CS_ABORTED:		host_status = DID_ABORT;		break;	      case CS_TIMEOUT:		host_status = DID_TIME_OUT;		break;	      case CS_DATA_OVERRUN:	      case CS_COMMAND_OVERRUN:	      case CS_STATUS_OVERRUN:	      case CS_BAD_MESSAGE:	      case CS_NO_MESSAGE_OUT:	      case CS_EXT_ID_FAILED:	      case CS_IDE_MSG_FAILED:	      case CS_ABORT_MSG_FAILED:	      case CS_NOP_MSG_FAILED:	      case CS_PARITY_ERROR_MSG_FAILED:	      case CS_DEVICE_RESET_MSG_FAILED:	      case CS_ID_MSG_FAILED:	      case CS_UNEXP_BUS_FREE:	      case CS_INVALID_ENTRY_TYPE:	      case CS_DEVICE_QUEUE_FULL:	      case CS_SCSI_PHASE_SKIPPED:	      case CS_ARS_FAILED:		host_status = DID_ERROR;		break;	      case CS_DATA_UNDERRUN:		host_status = DID_OK;		break;	      default:		printk("qlogicisp : unknown completion status 0x%04x\n",		       sts->completion_status);		host_status = DID_ERROR;		break;	}	DEBUG_INTR(printk("qlogicisp : host status (%s) scsi status %x\n",			  reason[host_status], sts->scsi_status));	LEAVE("isp1020_return_status");	return (sts->scsi_status & STATUS_MASK) | (host_status << 16);}int isp1020_abort(Scsi_Cmnd *Cmnd){	u_short param[6];	struct Scsi_Host *host;	struct isp1020_hostdata *hostdata;	int return_status = SCSI_ABORT_SUCCESS;	u_int cmdaddr = virt_to_bus(Cmnd);	ENTER("isp1020_abort");	host = Cmnd->host;	hostdata = (struct isp1020_hostdata *) host->hostdata;	isp1020_disable_irqs(host);	param[0] = MBOX_ABORT;	param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;	param[2] = cmdaddr >> 16;	param[3] = cmdaddr & 0xffff;	isp1020_mbox_command(host, param);	if (param[0] != MBOX_COMMAND_COMPLETE) {		printk("qlogicisp : scsi abort failure: %x\n", param[0]);		return_status = SCSI_ABORT_ERROR;	}	isp1020_enable_irqs(host);	LEAVE("isp1020_abort");	return return_status;}int isp1020_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags){	u_short param[6];	struct Scsi_Host *host;	struct isp1020_hostdata *hostdata;	int return_status = SCSI_RESET_SUCCESS;	ENTER("isp1020_reset");	host = Cmnd->host;	hostdata = (struct isp1020_hostdata *) host->hostdata;	param[0] = MBOX_BUS_RESET;	param[1] = hostdata->host_param.bus_reset_delay;	isp1020_disable_irqs(host);	isp1020_mbox_command(host, param);	if (param[0] != MBOX_COMMAND_COMPLETE) {		printk("qlogicisp : scsi bus reset failure: %x\n", param[0]);		return_status = SCSI_RESET_ERROR;	}	isp1020_enable_irqs(host);	LEAVE("isp1020_reset");	return return_status;;}int isp1020_biosparam(Disk *disk, kdev_t n, int ip[]){	int size = disk->capacity;	ENTER("isp1020_biosparam");	ip[0] = 64;	ip[1] = 32;	ip[2] = size >> 11;	if (ip[2] > 1024) {		ip[0] = 255;		ip[1] = 63;		ip[2] = size / (ip[0] * ip[1]);		if (ip[2] > 1023)			ip[2] = 1023;	}	LEAVE("isp1020_biosparam");	return 0;}static int isp1020_reset_hardware(struct Scsi_Host *host){	u_short param[6];	int loop_count;	ENTER("isp1020_reset_hardware");	outw(ISP_RESET, host->io_port + PCI_INTF_CTL);	outw(HCCR_RESET, host->io_port + HOST_HCCR);	outw(HCCR_RELEASE, host->io_port + HOST_HCCR);	outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR);	loop_count = DEFAULT_LOOP_COUNT;	while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY)		barrier();	if (!loop_count)		printk("qlogicisp: reset_hardware loop timeout\n");	outw(0, host->io_port + ISP_CFG1);#if DEBUG_ISP1020	printk("qlogicisp : mbox 0 0x%04x \n", inw(host->io_port + MBOX0));	printk("qlogicisp : mbox 1 0x%04x \n", inw(host->io_port + MBOX1));	printk("qlogicisp : mbox 2 0x%04x \n", inw(host->io_port + MBOX2));	printk("qlogicisp : mbox 3 0x%04x \n", inw(host->io_port + MBOX3));	printk("qlogicisp : mbox 4 0x%04x \n", inw(host->io_port + MBOX4));	printk("qlogicisp : mbox 5 0x%04x \n", inw(host->io_port + MBOX5));#endif /* DEBUG_ISP1020 */	DEBUG(printk("qlogicisp : loading risc ram\n"));#if RELOAD_FIRMWARE	{		int i;		for (i = 0; i < risc_code_length01; i++) {			param[0] = MBOX_WRITE_RAM_WORD;			param[1] = risc_code_addr01 + i;			param[2] = risc_code01[i];			isp1020_mbox_command(host, param);			if (param[0] != MBOX_COMMAND_COMPLETE) {				printk("qlogicisp : firmware load failure\n");				return 1;			}		}	}#endif /* RELOAD_FIRMWARE */	DEBUG(printk("qlogicisp : verifying checksum\n"));	param[0] = MBOX_VERIFY_CHECKSUM;	param[1] = risc_code_addr01;	isp1020_mbox_command(host, param);	if (param[0] != MBOX_COMMAND_COMPLETE) {		printk("qlogicisp : ram checksum failure\n");		return 1;	}	DEBUG(printk("qlogicisp : executing firmware\n"));	param[0] = MBOX_EXEC_FIRMWARE;	param[1] = risc_code_addr01;	isp1020_mbox_command(host, param);	param[0] = MBOX_ABOUT_FIRMWARE;	isp1020_mbox_command(host, param);	if (param[0] != MBOX_COMMAND_COMPLETE) {		printk("qlogicisp : about firmware failure\n");		return 1;	}	DEBUG(printk("qlogicisp : firmware major revision %d\n", param[1]));	DEBUG(printk("qlogicisp : firmware minor revision %d\n", param[2]));	LEAVE("isp1020_reset_hardware");	return 0;}static int isp1020_init(struct Scsi_Host *sh){	u_int io_base;	struct isp1020_hostdata *hostdata;	u_char bus, device_fn, revision, irq;	u_short vendor_id, device_id, command;	ENTER("isp1020_init");	hostdata = (struct isp1020_hostdata *) sh->hostdata;	bus = hostdata->bus;	device_fn = hostdata->device_fn;	if (pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id)            || pcibios_read_config_word(bus, device_fn,					PCI_DEVICE_ID, &device_id)            || pcibios_read_config_word(bus, device_fn,					PCI_COMMAND, &command)            || pcibios_read_config_dword(bus, device_fn,					 PCI_BASE_ADDRESS_0, &io_base)	    || pcibios_read_config_byte(bus, device_fn,					PCI_CLASS_REVISION, &revision)            || pcibios_read_config_byte(bus, device_fn,					PCI_INTERRUPT_LINE, &irq))	{		printk("qlogicisp : error reading PCI configuration\n");		return 1;	}	if (vendor_id != PCI_VENDOR_ID_QLOGIC) {		printk("qlogicisp : 0x%04x is not QLogic vendor ID\n",		       vendor_id);		return 1;	}	if (device_id != PCI_DEVICE_ID_QLOGIC_ISP1020) {		printk("qlogicisp : 0x%04x does not match ISP1020 device id\n",		       device_id);		return 1;	}	if (command & PCI_COMMAND_IO && (io_base & 3) == 1)		io_base &= PCI_BASE_ADDRESS_IO_MASK;	else {		printk("qlogicisp : i/o mapping is disabled\n");		return 1;	}	if (!(command & PCI_COMMAND_MASTER)) {		printk("qlogicisp : bus mastering is disabled\n");		return 1;	}	if (revision != ISP1020_REV_ID)		printk("qlogicisp : new isp1020 revision ID (%d)\n", revision);	if (inw(io_base + PCI_ID_LOW) != PCI_VENDOR_ID_QLOGIC	    || inw(io_base + PCI_ID_HIGH) != PCI_DEVICE_ID_QLOGIC_ISP1020)	{		printk("qlogicisp : can't decode i/o address space at 0x%x\n",		       io_base);		return 1;	}	hostdata->revision = revision;	sh->irq = irq;	sh->io_port = io_base;	LEAVE("isp1020_init");	return 0;}#if USE_NVRAM_DEFAULTSstatic int isp1020_get_defaults(struct Scsi_Host *host){	int i;	u_short value;	struct isp1020_hostdata *hostdata =		(struct isp1020_hostdata *) host->hostdata;	ENTER("isp1020_get_defaults");	if (!isp1020_verify_nvram(host)) {		printk("qlogicisp : nvram checksum failure\n");		printk("qlogicisp : attempting to use default parameters\n");		return isp1020_set_defaults(host);	}	value = isp1020_read_nvram_word(host, 2);	hostdata->host_param.fifo_threshold = (value >> 8) & 0x03;	hostdata->host_param.host_adapter_enable = (value >> 11) & 0x01;	hostdata->host_param.initiator_scsi_id = (value >> 12) & 0x0f;	value = isp1020_read_nvram_word(host, 3);	hostdata->host_param.bus_reset_delay = value & 0xff;	hostdata->host_param.retry_count = value >> 8;	value = isp1020_read_nvram_word(host, 4);	hostdata->host_param.retry_delay = value & 0xff;	hostdata->host_param.async_data_setup_time = (value >> 8) & 0x0f;	hostdata->host_param.req_ack_active_negation = (value >> 12) & 0x01;	hostdata->host_param.data_line_active_negation = (value >> 13) & 0x01;	hostdata->host_param.data_dma_burst_enable = (value >> 14) & 0x01;	hostdata->host_param.command_dma_burst_enable = (value >> 15);	value = isp1020_read_nvram_word(host, 5);	hostdata->host_param.tag_aging = value & 0xff;	value = isp1020_read_nvram_word(host, 6);	hostdata->host_param.selection_timeout = value & 0xffff;	value = isp1020_read_nvram_word(host, 7);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -