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

📄 ncr5380.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef PAS16_PUBLIC_RELEASE        pas_wmaxi = pas_maxi = 0;#endif      return(-ENOSYS);  /* Currently this is a no-op */   }   SPRINTF("NCR5380 core release=%d.   ", NCR5380_PUBLIC_RELEASE);   if (((struct NCR5380_hostdata *)instance->hostdata)->flags & FLAG_NCR53C400)        SPRINTF("ncr53c400 release=%d.  ", NCR53C400_PUBLIC_RELEASE);#ifdef DTC_PUBLIC_RELEASE   SPRINTF("DTC 3180/3280 release %d", DTC_PUBLIC_RELEASE);#endif#ifdef T128_PUBLIC_RELEASE   SPRINTF("T128 release %d", T128_PUBLIC_RELEASE);#endif#ifdef GENERIC_NCR5380_PUBLIC_RELEASE   SPRINTF("Generic5380 release %d", GENERIC_NCR5380_PUBLIC_RELEASE);#endif#ifdef PAS16_PUBLIC_RELEASESPRINTF("PAS16 release=%d", PAS16_PUBLIC_RELEASE);#endif   SPRINTF("\nBase Addr: 0x%05lX    ", (long)instance->base);   SPRINTF("io_port: %04x      ", (int)instance->io_port);   if (instance->irq == IRQ_NONE)      SPRINTF("IRQ: None.\n");   else      SPRINTF("IRQ: %d.\n", instance->irq);#ifdef DTC_PUBLIC_RELEASE   SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n",        dtc_wmaxi, dtc_maxi);#endif#ifdef PAS16_PUBLIC_RELEASE   SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n",        pas_wmaxi, pas_maxi);#endif    cli();    SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");    if (!hostdata->connected)      SPRINTF("scsi%d: no currently connected command\n", instance->host_no);   else      pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected,        pos, buffer, length);   SPRINTF("scsi%d: issue_queue\n", instance->host_no);   for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr;        ptr = (Scsi_Cmnd *) ptr->host_scribble)        pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);   SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);   for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;        ptr = (Scsi_Cmnd *) ptr->host_scribble)        pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);   sti();   *start=buffer;  if (pos - buffer < offset)    return 0;  else if (pos - buffer - offset < length)    return pos - buffer - offset;  return length;}static char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) {   SPRINTF("scsi%d : destination target %d, lun %d\n",        cmd->host->host_no, cmd->target, cmd->lun);   SPRINTF("        command = ");   pos = lprint_command (cmd->cmnd, pos, buffer, length);   return (pos);}static char *lprint_command (unsigned char *command,     char *pos, char *buffer, int length) {   int i, s;   pos = lprint_opcode(command[0], pos, buffer, length);   for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)      SPRINTF("%02x ", command[i]);   SPRINTF("\n");   return(pos);}static char *lprint_opcode(int opcode, char *pos, char *buffer, int length) {   SPRINTF("%2d (0x%02x)", opcode, opcode);   return(pos);}/*  * Function : void NCR5380_init (struct Scsi_Host *instance, flags) * * Purpose : initializes *instance and corresponding 5380 chip, *	with flags OR'd into the initial flags value. * * Inputs : instance - instantiation of the 5380 driver.   * * Notes : I assume that the host, hostno, and id bits have been * 	set correctly.  I don't care about the irq and other fields.  *  */static void NCR5380_init (struct Scsi_Host *instance, int flags) {    NCR5380_local_declare();    int i, pass;    unsigned long timeout;    struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) 	instance->hostdata;    /*      * On NCR53C400 boards, NCR5380 registers are mapped 8 past      * the base address.     */#ifdef NCR53C400    if (flags & FLAG_NCR53C400)	instance->NCR5380_instance_name += NCR53C400_address_adjust;#endif    NCR5380_setup(instance);    NCR5380_all_init();    hostdata->aborted = 0;    hostdata->id_mask = 1 << instance->this_id;    for (i = hostdata->id_mask; i <= 0x80; i <<= 1)	if (i > hostdata->id_mask)	    hostdata->id_higher_mask |= i;    for (i = 0; i < 8; ++i)	hostdata->busy[i] = 0;#ifdef REAL_DMA    hostdata->dmalen = 0;#endif    hostdata->targets_present = 0;    hostdata->connected = NULL;    hostdata->issue_queue = NULL;    hostdata->disconnected_queue = NULL;#ifdef NCR5380_STATS    for (i = 0; i < 8; ++i) {	hostdata->time_read[i] = 0;	hostdata->time_write[i] = 0;	hostdata->bytes_read[i] = 0;	hostdata->bytes_write[i] = 0;    }    hostdata->timebase = 0;    hostdata->pendingw = 0;    hostdata->pendingr = 0;#endif    /* The CHECK code seems to break the 53C400. Will check it later maybe */    if (flags & FLAG_NCR53C400)	hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags;    else	hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;    if (!the_template) {	the_template = instance->hostt;	first_instance = instance;    }	#ifdef USLEEP    hostdata->time_expires = 0;    hostdata->next_timer = NULL;#endif#ifndef AUTOSENSE    if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)) 	 printk("scsi%d : WARNING : support for multiple outstanding commands enabled\n"		"         without AUTOSENSE option, contingent allegiance conditions may\n"		"         be incorrectly cleared.\n", instance->host_no);#endif /* def AUTOSENSE */    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);    NCR5380_write(MODE_REG, MR_BASE);    NCR5380_write(TARGET_COMMAND_REG, 0);    NCR5380_write(SELECT_ENABLE_REG, 0);#ifdef NCR53C400    if (hostdata->flags & FLAG_NCR53C400) {	NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);    }#endif    /*      * Detect and correct bus wedge problems.     *     * If the system crashed, it may have crashed in a state      * where a SCSI command was still executing, and the      * SCSI bus is not in a BUS FREE STATE.     *     * If this is the case, we'll try to abort the currently     * established nexus which we know nothing about, and that     * failing, do a hard reset of the SCSI bus      */    for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) &&	  pass <= 6 ; ++pass) {	switch (pass) {	case 1:	case 3:	case 5:	    printk("scsi%d: SCSI bus busy, waiting up to five seconds\n",		instance->host_no);	    timeout = jiffies + 5*HZ;	    while (jiffies < timeout && (NCR5380_read(STATUS_REG) & SR_BSY));	    break;	case 2:	    printk("scsi%d: bus busy, attempting abort\n",		instance->host_no);	    do_abort (instance);	    break;	case 4:	    printk("scsi%d: bus busy, attempting reset\n",		instance->host_no);	    do_reset (instance);	    break;	case 6:	    printk("scsi%d: bus locked solid or invalid override\n",		instance->host_no);	}    }}/*  * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,  *	void (*done)(Scsi_Cmnd *))  * * Purpose :  enqueues a SCSI command * * Inputs : cmd - SCSI command, done - function called on completion, with *	a pointer to the command descriptor. *  * Returns : 0 * * 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. * *//* Only make static if a wrapper function is used */#ifndef NCR5380_queue_commandstatic#endifint NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) {    struct Scsi_Host *instance = cmd->host;    struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)	instance->hostdata;    Scsi_Cmnd *tmp;#if (NDEBUG & NDEBUG_NO_WRITE)    switch (cmd->cmnd[0]) {    case WRITE_6:    case WRITE_10:	printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",	    instance->host_no);	cmd->result = (DID_ERROR << 16);	done(cmd);	return 0;    }#endif /* (NDEBUG & NDEBUG_NO_WRITE) */#ifdef NCR5380_STATS# if 0    if (!hostdata->connected && !hostdata->issue_queue &&	!hostdata->disconnected_queue) {	hostdata->timebase = jiffies;    }# endif# ifdef NCR5380_STAT_LIMIT    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)# endif	switch (cmd->cmnd[0])	{	    case WRITE:	    case WRITE_6:	    case WRITE_10:		hostdata->time_write[cmd->target] -= (jiffies - hostdata->timebase);		hostdata->bytes_write[cmd->target] += cmd->request_bufflen;		hostdata->pendingw++;		break;	    case READ:	    case READ_6:	    case READ_10:		hostdata->time_read[cmd->target] -= (jiffies - hostdata->timebase);		hostdata->bytes_read[cmd->target] += cmd->request_bufflen;		hostdata->pendingr++;		break;	}#endif    /*      * 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;    /*      * 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.     */    cli();    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;    }#if (NDEBUG & NDEBUG_QUEUES)    printk("scsi%d : command added to %s of queue\n", instance->host_no,	(cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");#endif/* Run the coroutine if it isn't already running. */    run_main();    return 0;}/* * Function : NCR5380_main (void)  * * Purpose : NCR5380_main is a coroutine that runs as long as more work can  *	be done on the NCR5380 host adapters in a system.  Both  *	NCR5380_queue_command() and NCR5380_intr() will try to start it  *	in case it is not running. *  * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should  *  reenable them.  This prevents reentrancy and kernel stack overflow. */ 	    static void NCR5380_main (void) {    Scsi_Cmnd *tmp, *prev;    struct Scsi_Host *instance;    struct NCR5380_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.     *     * Interrupts are enabled before doing various other internal      * instructions, after we've decided that we need to run through     * the loop again.     *     * this should prevent any race conditions.     */    do {	cli(); /* Freeze request queues */	done = 1;	for (instance = first_instance; instance && 	    instance->hostt == the_template; instance=instance->next) {	    hostdata = (struct NCR5380_hostdata *) instance->hostdata;	    cli();	    if (!hostdata->connected) {#if (NDEBUG & NDEBUG_MAIN)		printk("scsi%d : not connected\n", instance->host_no);#endif		/*		 * Search through the issue_queue for a command destined		 * for a target that's not busy.		 */#if (NDEBUG & NDEBUG_LISTS)		for (tmp= (Scsi_Cmnd *) hostdata->issue_queue, prev=NULL; tmp && (tmp != prev); prev=tmp, tmp=(Scsi_Cmnd*)tmp->host_scribble)		    ;		    /*printk("%p  ", tmp);*/		if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/#endif		for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 		    prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) 		    tmp->host_scribble) {#if (NDEBUG & NDEBUG_LISTS)		    if (prev != tmp)			printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun);#endif		    /*  When we find one, remove it from the issue queue. */		    if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {			if (prev) {			    REMOVE(prev,prev->host_scribble,tmp,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;			/* reenable interrupts after finding one */			sti();			/* 			 * Attempt to establish an I_T_L nexus here. 			 * On success, instance->hostdata->connected is set.			 * On failure, we must add the command back to the			 *   issue queue so we can keep trying.				 */#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))			printk("scsi%d : main() : command for target %d lun %d removed from issue_queue\n",			    instance->host_no, tmp->target, tmp->lun);#endif    					/*			 * A successful selection is defined as one that 			 * leaves us with the command connected and 			 * in hostdata->connected, OR has terminated the			 * command.

⌨️ 快捷键说明

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