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

📄 am53c974.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
						break;					}	/* if target/lun is not busy */				}	/* for */			}			/* if (!hostdata->connected) */ 			else {				DEB(printk("main: connected; cmd = 0x%lx, sel_cmd = 0x%lx\n",					   (long) hostdata->connected, (long) hostdata->sel_cmd));			}		}		/* for instance */	} while (!done);	main_running = 0;	restore_flags(flags);}/************************************************************************* Function : AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs) **                                                                       ** Purpose : interrupt handler                                           **                                                                       ** Inputs : irq - interrupt line, regs - ?                               **                                                                       ** Returns : nothing                                                     *************************************************************************/static void do_AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs){	unsigned long flags;	spin_lock_irqsave(&io_request_lock, flags);	AM53C974_intr(irq, dev_id, regs);	spin_unlock_irqrestore(&io_request_lock, flags);}/************************************************************************* Function : AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs) **                                                                       ** Purpose : interrupt handler                                           **                                                                       ** Inputs : irq - interrupt line, regs - ?                               **                                                                       ** Returns : nothing                                                     *************************************************************************/static void AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs){	AM53C974_local_declare();	struct Scsi_Host *instance;	struct AM53C974_hostdata *hostdata;	unsigned char cmdreg, dmastatus, statreg, isreg, instreg, cfifo;/* find AM53C974 hostadapter responsible for this interrupt */	for (instance = first_instance; instance; instance = instance->next)		if ((instance->irq == irq) && (instance->hostt == the_template))			goto FOUND;	return;/* found; now decode and process */	FOUND:	    hostdata = (struct AM53C974_hostdata *) instance->hostdata;	AM53C974_setio(instance);	dmastatus = AM53C974_read_8(DMASTATUS);	DEB_INTR(printk(SEPARATOR_LINE));	DEB_INTR(printk("AM53C974 interrupt; dmastatus=0x%02x\n", dmastatus));	KEYWAIT();/*** DMA related interrupts ***/	if (hostdata->connected && (dmastatus & (DMASTATUS_ERROR | DMASTATUS_PWDN |						 DMASTATUS_ABORT))) {		/* DMA error or POWERDOWN */		printk("scsi%d: DMA error or powerdown; dmastatus: 0x%02x\n",		       instance->host_no, dmastatus);#ifdef AM53C974_DEBUG		deb_stop = 1;#endif		panic("scsi%d: cannot recover\n", instance->host_no);	}	if (hostdata->connected && (dmastatus & DMASTATUS_DONE)) {		/* DMA transfer done */		unsigned long residual;		unsigned long flags;		save_flags(flags);		cli();		if (!(AM53C974_read_8(DMACMD) & DMACMD_DIR)) {			do {				dmastatus = AM53C974_read_8(DMASTATUS);				residual = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) |				    (AM53C974_read_8(CTCHREG) << 16);				residual += AM53C974_read_8(CFIREG) & CFIREG_CF;			} while (!(dmastatus & DMASTATUS_SCSIINT) && residual);			residual = AM53C974_read_8(CTCLREG) | (AM53C974_read_8(CTCMREG) << 8) |			    (AM53C974_read_8(CTCHREG) << 16);			residual += AM53C974_read_8(CFIREG) & CFIREG_CF;		} else			residual = 0;		hostdata->connected->SCp.ptr += hostdata->connected->SCp.this_residual - residual;		hostdata->connected->SCp.this_residual = residual;		AM53C974_write_8(DMACMD, DMACMD_IDLE);		/* if service request missed before, process it now (ugly) */		if (hostdata->dma_busy) {			hostdata->dma_busy = 0;			cmdreg = AM53C974_read_8(CMDREG);			statreg = AM53C974_read_8(STATREG);			isreg = AM53C974_read_8(ISREG);			instreg = AM53C974_read_8(INSTREG);			cfifo = AM53C974_cfifo();			AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo,						      dmastatus);		}		restore_flags(flags);	}	if (!(dmastatus & DMASTATUS_SCSIINT)) {		return;	}/*** SCSI related interrupts ***/	cmdreg = AM53C974_read_8(CMDREG);	statreg = AM53C974_read_8(STATREG);	isreg = AM53C974_read_8(ISREG);	instreg = AM53C974_read_8(INSTREG);	cfifo = AM53C974_cfifo();	DEB_INTR(printk("scsi%d: statreg: 0x%02x; isreg: 0x%02x; instreg: 0x%02x; cfifo: 0x%02x\n",		     instance->host_no, statreg, isreg, instreg, cfifo));	if (statreg & STATREG_PE) {		/* parity error */#ifdef AM53C974_DEBUG		deb_stop = 1;#endif		printk("scsi%d : PARITY error\n", instance->host_no);		if (hostdata->connected)			hostdata->sync_off[hostdata->connected->target] = 0;	/* setup asynchronous transfer */		hostdata->aborted = 1;	}	if (statreg & STATREG_IOE) {		/* illegal operation error */#ifdef AM53C974_DEBUG		deb_stop = 1;#endif		printk("scsi%d : ILLEGAL OPERATION error\n", instance->host_no);		printk("cmdreg:  0x%02x; dmacmd:  0x%02x; statreg: 0x%02x; \n"		   "isreg:   0x%02x; instreg: 0x%02x; cfifo:   0x%02x\n",		       cmdreg, AM53C974_read_8(DMACMD), statreg, isreg, instreg, cfifo);	}	if (hostdata->in_reset && (instreg & INSTREG_SRST)) {		unsigned long flags;		/* RESET INTERRUPT */#ifdef AM53C974_DEBUG		deb_stop = 1;#endif		DEB(printk("Bus reset interrupt received\n"));		AM53C974_intr_bus_reset(instance);		save_flags(flags);		cli();		if (hostdata->connected) {			hostdata->connected->result = DID_RESET << 16;			hostdata->connected->scsi_done((Scsi_Cmnd *) hostdata->connected);			hostdata->connected = NULL;		} else {			if (hostdata->sel_cmd) {				hostdata->sel_cmd->result = DID_RESET << 16;				hostdata->sel_cmd->scsi_done((Scsi_Cmnd *) hostdata->sel_cmd);				hostdata->sel_cmd = NULL;			}		}		restore_flags(flags);		if (hostdata->in_reset == 1)			goto EXIT;		else			return;	}	if (instreg & INSTREG_ICMD) {		/* INVALID COMMAND INTERRUPT */#ifdef AM53C974_DEBUG		deb_stop = 1;#endif		printk("scsi%d: Invalid command interrupt\n", instance->host_no);		printk("cmdreg:  0x%02x; dmacmd:  0x%02x; statreg: 0x%02x; dmastatus: 0x%02x; \n"		   "isreg:   0x%02x; instreg: 0x%02x; cfifo:   0x%02x\n",		       cmdreg, AM53C974_read_8(DMACMD), statreg, dmastatus, isreg, instreg, cfifo);		panic("scsi%d: cannot recover\n", instance->host_no);	}	if (instreg & INSTREG_DIS) {		unsigned long flags;		/* DISCONNECT INTERRUPT */		DEB_INTR(printk("Disconnect interrupt received; "));		save_flags(flags);		cli();		AM53C974_intr_disconnect(instance);		restore_flags(flags);		goto EXIT;	}	if (instreg & INSTREG_RESEL) {		unsigned long flags;		/* RESELECTION INTERRUPT */		DEB_INTR(printk("Reselection interrupt received\n"));		save_flags(flags);		cli();		AM53C974_intr_reselect(instance, statreg);		restore_flags(flags);		goto EXIT;	}	if (instreg & INSTREG_SO) {		DEB_INTR(printk("Successful operation interrupt received\n"));		if (hostdata->selecting) {			unsigned long flags;			DEB_INTR(printk("DSR completed, starting select\n"));			save_flags(flags);			cli();			AM53C974_select(instance, (Scsi_Cmnd *) hostdata->sel_cmd,			  (hostdata->sel_cmd->cmnd[0] == REQUEST_SENSE) ?					TAG_NONE : TAG_NEXT);			hostdata->selecting = 0;			AM53C974_set_sync(instance, hostdata->sel_cmd->target);			restore_flags(flags);			return;		}		if (hostdata->sel_cmd != NULL) {			if (((isreg & ISREG_IS) != ISREG_OK_NO_STOP) &&			    ((isreg & ISREG_IS) != ISREG_OK_STOP)) {				unsigned long flags;				/* UNSUCCESSFUL SELECTION */				DEB_INTR(printk("unsuccessful selection\n"));				save_flags(flags);				cli();				hostdata->dma_busy = 0;				LIST(hostdata->sel_cmd, hostdata->issue_queue);				hostdata->sel_cmd->host_scribble = (unsigned char *) hostdata->issue_queue;				hostdata->issue_queue = hostdata->sel_cmd;				hostdata->sel_cmd = NULL;				hostdata->selecting = 0;				restore_flags(flags);				goto EXIT;			} else {				unsigned long flags;				/* SUCCESSFUL SELECTION */				DEB(printk("successful selection; cmd=0x%02lx\n", (long) hostdata->sel_cmd));				save_flags(flags);				cli();				hostdata->dma_busy = 0;				hostdata->disconnecting = 0;				hostdata->connected = hostdata->sel_cmd;				hostdata->sel_cmd = NULL;				hostdata->selecting = 0;#ifdef SCSI2				if (!hostdata->connected->device->tagged_queue)#endif					hostdata->busy[hostdata->connected->target] |= (1 << hostdata->connected->lun);				/* very strange -- use_sg is sometimes nonzero for request sense commands !! */				if ((hostdata->connected->cmnd[0] == REQUEST_SENSE) && hostdata->connected->use_sg) {					DEB(printk("scsi%d: REQUEST_SENSE command with nonzero use_sg\n", instance->host_no));					KEYWAIT();					hostdata->connected->use_sg = 0;				}				initialize_SCp((Scsi_Cmnd *) hostdata->connected);				hostdata->connected->SCp.phase = PHASE_CMDOUT;				AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus);				restore_flags(flags);				return;			}		} else {			unsigned long flags;			save_flags(flags);			cli();			AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus);			restore_flags(flags);			return;		}	}	if (instreg & INSTREG_SR) {		DEB_INTR(printk("Service request interrupt received, "));		if (hostdata->connected) {			unsigned long flags;			DEB_INTR(printk("calling information_transfer\n"));			save_flags(flags);			cli();			AM53C974_information_transfer(instance, statreg, isreg, instreg, cfifo, dmastatus);			restore_flags(flags);		} else {			printk("scsi%d: weird: service request when no command connected\n", instance->host_no);			AM53C974_write_8(CMDREG, CMDREG_CFIFO);		}		/* clear FIFO */		return;	}	EXIT:	    DEB_INTR(printk("intr: starting main\n"));	run_main();	DEB_INTR(printk("end of intr\n"));}/************************************************************************** * Function : AM53C974_intr_disconnect(struct Scsi_Host *instance)** Purpose : manage target disconnection** Inputs : instance -- which AM53C974* * Returns : nothing**************************************************************************/static void AM53C974_intr_disconnect(struct Scsi_Host *instance){	AM53C974_local_declare();	struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata;	Scsi_Cmnd *cmd;	AM53C974_setio(instance);	if (hostdata->sel_cmd != NULL) {		/* normal selection timeout, typical for nonexisting targets */		cmd = (Scsi_Cmnd *) hostdata->sel_cmd;		DEB_INTR(printk("bad target\n"));		cmd->result = DID_BAD_TARGET << 16;		goto EXIT_FINISHED;	}	if (!hostdata->connected) {		/* can happen if controller was reset, a device tried to reconnect,		   failed and disconnects now */		AM53C974_write_8(CMDREG, CMDREG_CFIFO);		return;	}	if (hostdata->disconnecting) {		/* target sent disconnect message, so we are prepared */		cmd = (Scsi_Cmnd *) hostdata->connected;		AM53C974_set_async(instance, cmd->target);		DEB_INTR(printk("scsi%d : disc. from cmnd %d for ta %d, lun %d\n",		instance->host_no, cmd->cmnd[0], cmd->target, cmd->lun));		if (cmd->device->disconnect) {			/* target wants to reselect later */			DEB_INTR(printk("ok, re-enabling selection\n"));			LIST(cmd, hostdata->disconnected_queue);			cmd->host_scribble = (unsigned char *) hostdata->disconnected_queue;			hostdata->disconnected_queue = cmd;			DEB_QUEUE(printk("scsi%d : command for target %d lun %d this %d was moved from connected to"					 "  the disconnected_queue\n", instance->host_no, cmd->target,					 cmd->lun, hostdata->disconnected_queue->SCp.this_residual));			DEB_QUEUE(AM53C974_print_queues(instance));			goto EXIT_UNFINISHED;		} else {

⌨️ 快捷键说明

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