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

📄 am53c974.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
** Purpose : initializes instance and corresponding AM53/79C974 chip,** Inputs : tpnt - template, pci_config - PCI configuration,* * Returns : 1 on success, 0 on failure.* * NOTE: If no override for the controller's SCSI id is given and AM53C974_SCSI_ID *       is not defined we assume that the SCSI address of this controller is correctly*       set up by the BIOS (as reflected by contents of register CNTLREG1).*       This is the only BIOS assistance we need.**************************************************************************/__initfunc(static int AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *pdev)){	AM53C974_local_declare();	int i, j;	struct Scsi_Host *instance, *search;	struct AM53C974_hostdata *hostdata;#ifdef AM53C974_OPTION_DEBUG_PROBE_ONLY	printk("AM53C974: probe only enabled, aborting initialization\n");	return 0;#endif	instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata));	hostdata = (struct AM53C974_hostdata *) instance->hostdata;	instance->base = NULL;	instance->io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;	instance->irq = pdev->irq;	instance->dma_channel = -1;	AM53C974_setio(instance);#ifdef AM53C974_SCSI_ID	instance->this_id = AM53C974_SCSI_ID;	AM53C974_write_8(CNTLREG1, instance->this_id & CNTLREG1_SID);#else	instance->this_id = AM53C974_read_8(CNTLREG1) & CNTLREG1_SID;	if (instance->this_id != 7)		printk("scsi%d: WARNING: unusual hostadapter SCSI id %d; please verify!\n",		       instance->host_no, instance->this_id);#endif	for (i = 0; i < sizeof(hostdata->msgout); i++) {		hostdata->msgout[i] = NOP;		hostdata->last_message[i] = NOP;	}	for (i = 0; i < 8; i++) {		hostdata->busy[i] = 0;		hostdata->sync_per[i] = DEF_STP;		hostdata->sync_off[i] = 0;		hostdata->sync_neg[i] = 0;		hostdata->sync_en[i] = DEFAULT_SYNC_NEGOTIATION_ENABLED;		hostdata->max_rate[i] = DEFAULT_RATE;		hostdata->max_offset[i] = DEFAULT_SYNC_OFFSET;	}/* overwrite defaults by LILO overrides */	for (i = 0; i < commandline_current; i++) {		if (overrides[i].host_scsi_id == instance->this_id) {			j = overrides[i].target_scsi_id;			hostdata->sync_en[j] = 1;			hostdata->max_rate[j] = overrides[i].max_rate;			hostdata->max_offset[j] = overrides[i].max_offset;		}	}	hostdata->sel_cmd = NULL;	hostdata->connected = NULL;	hostdata->issue_queue = NULL;	hostdata->disconnected_queue = NULL;	hostdata->in_reset = 0;	hostdata->aborted = 0;	hostdata->selecting = 0;	hostdata->disconnecting = 0;	hostdata->dma_busy = 0;/* Set up an interrupt handler if we aren't already sharing an IRQ with another board */	for (search = first_host;	     search && (((the_template != NULL) && (search->hostt != the_template)) ||		 (search->irq != instance->irq) || (search == instance));	     search = search->next);	if (!search) {		if (request_irq(instance->irq, do_AM53C974_intr, SA_SHIRQ, "AM53C974", instance)) {			printk("scsi%d: IRQ%d not free, detaching\n", instance->host_no, instance->irq);			scsi_unregister(instance);			return 0;		}	} else {		printk("scsi%d: using interrupt handler previously installed for scsi%d\n",		       instance->host_no, search->host_no);	}	if (!the_template) {		the_template = instance->hostt;		first_instance = instance;	}/* do hard reset */	AM53C974_write_8(CMDREG, CMDREG_RDEV);	/* reset device */	udelay(5);	AM53C974_write_8(CMDREG, CMDREG_NOP);	AM53C974_write_8(CNTLREG1, CNTLREG1_DISR | instance->this_id);	AM53C974_write_8(CMDREG, CMDREG_RBUS);	/* reset SCSI bus */	udelay(10);	AM53C974_config_after_reset(instance);	mdelay(500);	return (1);}/********************************************************************** Function : AM53C974_config_after_reset(struct Scsi_Host *instance) **                                                                    ** Purpose : initializes chip registers after reset                   **                                                                    ** Inputs : instance - which AM53C974                                 **                                                                    ** Returns : nothing                                                  ***********************************************************************/static void AM53C974_config_after_reset(struct Scsi_Host *instance){	AM53C974_local_declare();	AM53C974_setio(instance);/* clear SCSI FIFO */	AM53C974_write_8(CMDREG, CMDREG_CFIFO);/* configure device */	AM53C974_write_8(STIMREG, DEF_SCSI_TIMEOUT);	AM53C974_write_8(STPREG, DEF_STP & STPREG_STP);	AM53C974_write_8(SOFREG, (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4));	AM53C974_write_8(CLKFREG, DEF_CLKF & CLKFREG_MASK);	AM53C974_write_8(CNTLREG1, (DEF_ETM << 7) | CNTLREG1_DISR | (DEF_PERE << 4) | instance->this_id);	AM53C974_write_8(CNTLREG2, (DEF_ENF << 6));	AM53C974_write_8(CNTLREG3, (DEF_ADIDCHK << 7) | (DEF_FASTSCSI << 4) | (DEF_FASTCLK << 3));	AM53C974_write_8(CNTLREG4, (DEF_GLITCH << 6) | (DEF_PWD << 5) | (DEF_RAE << 3) | (DEF_RADE << 2) | CNTLREG4_RES);}/************************************************************************ Function : const char *AM53C974_info(struct Scsi_Host *instance)     **                                                                      ** Purpose : return device driver information                           **                                                                      ** Inputs : instance - which AM53C974                                   **                                                                      ** Returns : info string                                                *************************************************************************/const char *AM53C974_info(struct Scsi_Host *instance){	static char info[100];	sprintf(info, "AM53/79C974 PCscsi driver rev. %d.%d; host I/O address: 0x%lx; irq: %d\n",	  AM53C974_DRIVER_REVISION_MAJOR, AM53C974_DRIVER_REVISION_MINOR,		instance->io_port, instance->irq);	return (info);}/************************************************************************** * Function : int AM53C974_command (Scsi_Cmnd *SCpnt)                      **                                                                         ** Purpose : the unqueued SCSI command function, replaced by the           **           AM53C974_queue_command function                               **                                                                         ** Inputs : SCpnt - pointer to command structure                           **                                                                         ** Returns :status, see hosts.h for details                                ****************************************************************************/int AM53C974_command(Scsi_Cmnd * SCpnt){	DEB(printk("AM53C974_command called\n"));	return 0;}/*************************************************************************** Function : void initialize_SCp(Scsi_Cmnd *cmd)                          **                                                                         ** Purpose : initialize the saved data pointers for cmd to point to the    **	    start of the buffer.                                          *                              *                                                                         ** Inputs : cmd - Scsi_Cmnd structure to have pointers reset.              **                                                                         ** Returns : nothing                                                       ***************************************************************************/static __inline__ void initialize_SCp(Scsi_Cmnd * cmd){	if (cmd->use_sg) {		cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;		cmd->SCp.buffers_residual = cmd->use_sg - 1;		cmd->SCp.ptr = (char *) cmd->SCp.buffer->address;		cmd->SCp.this_residual = cmd->SCp.buffer->length;	} else {		cmd->SCp.buffer = NULL;		cmd->SCp.buffers_residual = 0;		cmd->SCp.ptr = (char *) cmd->request_buffer;		cmd->SCp.this_residual = cmd->request_bufflen;	}}/*************************************************************************** Function : run_main(void)                                               **                                                                         ** Purpose : insure that the coroutine is running and will process our     ** 	    request.  main_running is checked/set here (in an inline      **           function rather than in AM53C974_main itself to reduce the    **           chances of stack overflow.                                    **                                                                         **                                                                         ** Inputs : none                                                           **                                                                         ** Returns : nothing                                                       ***************************************************************************/static __inline__ void run_main(void){	unsigned long flags;	save_flags(flags);	cli();	if (!main_running) {		/* main_running is cleared in AM53C974_main once it can't do 		   more work, and AM53C974_main exits with interrupts disabled. */		main_running = 1;		AM53C974_main();	}	restore_flags(flags);}/************************************************************************** * Function : int AM53C974_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))** Purpose : writes SCSI command into AM53C974 FIFO ** Inputs : cmd - SCSI command, done - function called on completion, with*	a pointer to the command descriptor.* * Returns : status, see hosts.h for details** Side effects : *      cmd is added to the per instance issue_queue, with minor *	twiddling done to the host specific fields of cmd.  If the *	main coroutine is not running, it is restarted.**************************************************************************/int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)){	unsigned long flags;	struct Scsi_Host *instance = cmd->host;	struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata;	Scsi_Cmnd *tmp;	save_flags(flags);	cli();	DEB_QUEUE(printk(SEPARATOR_LINE));	DEB_QUEUE(printk("scsi%d: AM53C974_queue_command called\n", instance->host_no));	DEB_QUEUE(printk("cmd=%02x target=%02x lun=%02x bufflen=%d use_sg = %02x\n",			 cmd->cmnd[0], cmd->target, cmd->lun, cmd->request_bufflen, cmd->use_sg));/* We use the host_scribble field as a pointer to the next command in a queue */	cmd->host_scribble = NULL;	cmd->scsi_done = done;	cmd->result = 0;	cmd->device->disconnect = 0;/* Insert the cmd into the issue queue. Note that REQUEST SENSE  * commands are added to the head of the queue since any command will * clear the contingent allegiance condition that exists and the  * sense data is only guaranteed to be valid while the condition exists. */	if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {		LIST(cmd, hostdata->issue_queue);		cmd->host_scribble = (unsigned char *) hostdata->issue_queue;		hostdata->issue_queue = cmd;	} else {		for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble;		     tmp = (Scsi_Cmnd *) tmp->host_scribble);		LIST(cmd, tmp);		tmp->host_scribble = (unsigned char *) cmd;	}	DEB_QUEUE(printk("scsi%d : command added to %s of queue\n", instance->host_no,		     (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));/* Run the coroutine if it isn't already running. */	run_main();	restore_flags(flags);	return 0;}/************************************************************************** * Function : AM53C974_main (void)  * * Purpose : AM53C974_main is a coroutine that runs as long as more work can  *	be done on the AM53C974 host adapters in a system.  Both  *	AM53C974_queue_command() and AM53C974_intr() will try to start it  *	in case it is not running. *  * NOTE : AM53C974_main exits with interrupts *disabled*, the caller should  *  reenable them.  This prevents reentrancy and kernel stack overflow. **************************************************************************/static void AM53C974_main(void){	AM53C974_local_declare();	unsigned long flags;	Scsi_Cmnd *tmp, *prev;	struct Scsi_Host *instance;	struct AM53C974_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 main_running to 0 and exit. */	save_flags(flags);	cli();		/* Freeze request queues */	do {		done = 1;		for (instance = first_instance; instance && instance->hostt == the_template;		     instance = instance->next) {			hostdata = (struct AM53C974_hostdata *) instance->hostdata;			AM53C974_setio(instance);			/* start to select target if we are not connected and not in the 			   selection process */			if (!hostdata->connected && !hostdata->sel_cmd) {				/* Search through the issue_queue for a command destined for a target 				   that is not busy. */				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp;				     prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) {					/*  When we find one, remove it from the issue queue. */					if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {						if (prev) {							REMOVE(prev, (Scsi_Cmnd *) (prev->host_scribble), tmp,							       (Scsi_Cmnd *) (tmp->host_scribble));							prev->host_scribble = tmp->host_scribble;						} else {							REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble);							hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;						}						tmp->host_scribble = NULL;						/* go into selection mode, disable reselection and wait for						   SO interrupt which will continue with the selection process */						hostdata->selecting = 1;						hostdata->sel_cmd = tmp;						AM53C974_write_8(CMDREG, CMDREG_DSR);

⌨️ 快捷键说明

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