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

📄 53c7xx.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static int NCR53c7xx_run_tests (struct Scsi_Host *host) {    NCR53c7x0_local_declare();    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)	host->hostdata[0];    unsigned long timeout;    u32 start;    int failed, i;    unsigned long flags;    NCR53c7x0_local_setup(host);    /* The NCR chip _must_ be idle to run the test scripts */    save_flags(flags);    cli();    if (!hostdata->idle) {	printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);	restore_flags(flags);	return -1;    }    /*      * Check for functional interrupts, this could work as an     * autoprobe routine.     */    if ((hostdata->options & OPTION_DEBUG_TEST1) && 	    hostdata->state != STATE_DISABLED) {	hostdata->idle = 0;	hostdata->test_running = 1;	hostdata->test_completed = -1;	hostdata->test_dest = 0;	hostdata->test_source = 0xdeadbeef;	start = virt_to_bus (hostdata->script) + hostdata->E_test_1;    	hostdata->state = STATE_RUNNING;	printk ("scsi%d : test 1", host->host_no);	NCR53c7x0_write32 (DSP_REG, start);	if (hostdata->options & OPTION_DEBUG_TRACE)	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM |						DCNTL_STD);	printk (" started\n");	restore_flags(flags);	/* 	 * This is currently a .5 second timeout, since (in theory) no slow 	 * board will take that long.  In practice, we've seen one 	 * pentium which occassionally fails with this, but works with 	 * 10 times as much?	 */	timeout = jiffies + 5 * HZ / 10;	while ((hostdata->test_completed == -1) && jiffies < timeout)		barrier();	failed = 1;	if (hostdata->test_completed == -1)	    printk ("scsi%d : driver test 1 timed out%s\n",host->host_no ,		(hostdata->test_dest == 0xdeadbeef) ? 		    " due to lost interrupt.\n"		    "         Please verify that the correct IRQ is being used for your board,\n"		    : "");	else if (hostdata->test_completed != 1) 	    printk ("scsi%d : test 1 bad interrupt value (%d)\n", 		host->host_no, hostdata->test_completed);	else 	    failed = (hostdata->test_dest != 0xdeadbeef);	if (hostdata->test_dest != 0xdeadbeef) {	    printk ("scsi%d : driver test 1 read 0x%x instead of 0xdeadbeef indicating a\n"                    "         probable cache invalidation problem.  Please configure caching\n"		    "         as write-through or disabled\n",		host->host_no, hostdata->test_dest);	}	if (failed) {	    printk ("scsi%d : DSP = 0x%p (script at 0x%p, start at 0x%x)\n",		host->host_no, bus_to_virt(NCR53c7x0_read32(DSP_REG)),		hostdata->script, start);	    printk ("scsi%d : DSPS = 0x%x\n", host->host_no,		NCR53c7x0_read32(DSPS_REG));	    restore_flags(flags);	    return -1;	}    	hostdata->test_running = 0;    }    if ((hostdata->options & OPTION_DEBUG_TEST2) && 	hostdata->state != STATE_DISABLED) {	u32 dsa[48];    	unsigned char identify = IDENTIFY(0, 0);	unsigned char cmd[6];	unsigned char data[36];    	unsigned char status = 0xff;    	unsigned char msg = 0xff;    	cmd[0] = INQUIRY;    	cmd[1] = cmd[2] = cmd[3] = cmd[5] = 0;    	cmd[4] = sizeof(data);     	dsa[2] = 1;    	dsa[3] = virt_to_bus(&identify);    	dsa[4] = 6;    	dsa[5] = virt_to_bus(&cmd);    	dsa[6] = sizeof(data);    	dsa[7] = virt_to_bus(&data);    	dsa[8] = 1;    	dsa[9] = virt_to_bus(&status);    	dsa[10] = 1;    	dsa[11] = virt_to_bus(&msg);	for (i = 0; i < 6; ++i) {#ifdef VALID_IDS	    if (!hostdata->valid_ids[i])		continue;#endif	    cli();	    if (!hostdata->idle) {		printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);		restore_flags(flags);		return -1;	    }	    /* 710: bit mapped scsi ID, async   */            dsa[0] = (1 << i) << 16;	    hostdata->idle = 0;	    hostdata->test_running = 2;	    hostdata->test_completed = -1;	    start = virt_to_bus(hostdata->script) + hostdata->E_test_2;	    hostdata->state = STATE_RUNNING;	    NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa));	    NCR53c7x0_write32 (DSP_REG, start);	    if (hostdata->options & OPTION_DEBUG_TRACE)	        NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |				DCNTL_SSM | DCNTL_STD);	    restore_flags(flags);	    timeout = jiffies + 5 * HZ;	/* arbitrary */	    while ((hostdata->test_completed == -1) && jiffies < timeout)	    	barrier();	    NCR53c7x0_write32 (DSA_REG, 0);	    if (hostdata->test_completed == 2) {		data[35] = 0;		printk ("scsi%d : test 2 INQUIRY to target %d, lun 0 : %s\n",		    host->host_no, i, data + 8);		printk ("scsi%d : status ", host->host_no);		print_status (status);		printk ("\nscsi%d : message ", host->host_no);		print_msg (&msg);		printk ("\n");	    } else if (hostdata->test_completed == 3) {		printk("scsi%d : test 2 no connection with target %d\n",		    host->host_no, i);		if (!hostdata->idle) {		    printk("scsi%d : not idle\n", host->host_no);		    restore_flags(flags);		    return -1;		}	    } else if (hostdata->test_completed == -1) {		printk ("scsi%d : test 2 timed out\n", host->host_no);		restore_flags(flags);		return -1;	    } 	    hostdata->test_running = 0;	}    }    restore_flags(flags);    return 0;}/* * Function : static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) * * Purpose : copy the NCR53c8xx dsa structure into cmd's dsa buffer, * 	performing all necessary relocation. * * Inputs : cmd, a NCR53c7x0_cmd structure with a dsa area large *	enough to hold the NCR53c8xx dsa. */static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) {    Scsi_Cmnd *c = cmd->cmd;    struct Scsi_Host *host = c->host;    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)    	host->hostdata[0];    int i;    memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4),    	hostdata->E_dsa_code_template_end - hostdata->E_dsa_code_template);    /*      * Note : within the NCR 'C' code, dsa points to the _start_     * of the DSA structure, and _not_ the offset of dsa_zero within     * that structure used to facilitate shorter signed offsets     * for the 8 bit ALU.     *      * The implications of this are that      *      * - 32 bit A_dsa_* absolute values require an additional      * 	 dsa_zero added to their value to be correct, since they are      *   relative to dsa_zero which is in essentially a separate     *   space from the code symbols.     *     * - All other symbols require no special treatment.     */    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),    	dsa_temp_lun, c->lun);    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),	dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr));    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),    	dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero -	Ent_dsa_code_template + A_dsa_next);    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),     	dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->target].script));    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),     	dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->target].sscf_710));    patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32),    	    dsa_temp_target, 1 << c->target);    /* XXX - new pointer stuff */    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),    	dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer));    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),    	dsa_temp_addr_saved_residual, virt_to_bus(&cmd->saved_residual));    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),    	dsa_temp_addr_residual, virt_to_bus(&cmd->residual));    /*  XXX - new start stuff */    patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),	dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr));}/*  * Function : run_process_issue_queue (void) *  * Purpose : insure that the coroutine is running and will process our  * 	request.  process_issue_queue_running is checked/set here (in an  *	inline function) rather than in process_issue_queue itself to reduce  * 	the chances of stack overflow. * */static volatile int process_issue_queue_running = 0;static __inline__ void run_process_issue_queue(void) {    unsigned long flags;    save_flags (flags);    cli();    if (!process_issue_queue_running) {	process_issue_queue_running = 1;        process_issue_queue(flags);	/*          * process_issue_queue_running is cleared in process_issue_queue 	 * once it can't do more work, and process_issue_queue exits with 	 * interrupts disabled.	 */    }    restore_flags (flags);}/* * Function : static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int *	result) * * Purpose : mark SCSI command as finished, OR'ing the host portion  *	of the result word into the result field of the corresponding *	Scsi_Cmnd structure, and removing it from the internal queues. * * Inputs : cmd - command, result - entire result field * * Preconditions : the 	NCR chip should be in a halted state when  *	abnormal_finished is run, since it modifies structures which *	the NCR expects to have exclusive access to. */static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {    Scsi_Cmnd *c = cmd->cmd;    struct Scsi_Host *host = c->host;    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)    	host->hostdata[0];    unsigned long flags;    int left, found;    volatile struct NCR53c7x0_cmd * linux_search;    volatile struct NCR53c7x0_cmd * volatile *linux_prev;    volatile u32 *ncr_prev, *ncrcurrent, ncr_search;#if 0    printk ("scsi%d: abnormal finished\n", host->host_no);#endif    save_flags(flags);    cli();    found = 0;    /*      * Traverse the NCR issue array until we find a match or run out      * of instructions.  Instructions in the NCR issue array are      * either JUMP or NOP instructions, which are 2 words in length.     */    for (found = 0, left = host->can_queue, ncrcurrent = hostdata->schedule; 	left > 0; --left, ncrcurrent += 2)    {	if (issue_to_cmd (host, hostdata, (u32 *) ncrcurrent) == cmd) 	{	    ncrcurrent[0] = hostdata->NOP_insn;	    ncrcurrent[1] = 0xdeadbeef;	    ++found;	    break;	}    }	    /*      * Traverse the NCR reconnect list of DSA structures until we find      * a pointer to this dsa or have found too many command structures.       * We let prev point at the next field of the previous element or      * head of the list, so we don't do anything different for removing      * the head element.       */    for (left = host->can_queue,	    ncr_search = hostdata->reconnect_dsa_head, 	    ncr_prev = &hostdata->reconnect_dsa_head;	left >= 0 && ncr_search && 	    ((char*)bus_to_virt(ncr_search) + hostdata->dsa_start) 		!= (char *) cmd->dsa;	ncr_prev = (u32*) ((char*)bus_to_virt(ncr_search) + 	    hostdata->dsa_next), ncr_search = *ncr_prev, --left);    if (left < 0) 	printk("scsi%d: loop detected in ncr reconncect list\n",	    host->host_no);    else if (ncr_search) {	if (found)	    printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n",		host->host_no, c->pid);	else {	    volatile u32 * next = (u32 *) 	    	((char *)bus_to_virt(ncr_search) + hostdata->dsa_next);	    *ncr_prev = *next;/* If we're at the tail end of the issue queue, update that pointer too. */	    found = 1;	}    }    /*     * Traverse the host running list until we find this command or discover     * we have too many elements, pointing linux_prev at the next field of the      * linux_previous element or head of the list, search at this element.     */    for (left = host->can_queue, linux_search = hostdata->running_list, 	    linux_prev = &hostdata->running_list;	left >= 0 && linux_search && linux_search != cmd;	linux_prev = &(linux_search->next), 	    linux_search = linux_search->next, --left);        if (left < 0) 	printk ("scsi%d: loop detected in host running list for scsi pid %ld\n",	    host->host_no, c->pid);    else if (linux_search) {	*linux_prev = linux_search->next;	--hostdata->busy[c->target][c->lun];    }    /* Return the NCR command structure to the free list */    cmd->next = hostdata->free;    hostdata->free = cmd;    c->host_scribble = NULL;    /* And return */    c->result = result;    c->scsi_done(c);    restore_flags(flags);    run_process_issue_queue();}/*  * Function : static void intr_break (struct Scsi_Host *host, * 	struct NCR53c7x0_cmd *cmd) * * Purpose :  Handler for breakpoint interrupts from a SCSI script * * Inputs : host - pointer to this host adapter's structure, * 	cmd - poi

⌨️ 快捷键说明

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