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

📄 53c7xx.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	ncrcurrent[0] = hostdata->NOP_insn;	ncrcurrent[1] = 0xdeadbeef;    }    ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE;    ncrcurrent[1] = (u32) virt_to_bus (hostdata->script) +	hostdata->E_wait_reselect;    hostdata->reconnect_dsa_head = 0;    hostdata->addr_reconnect_dsa_head = (u32) 	virt_to_bus((void *) &(hostdata->reconnect_dsa_head));    hostdata->expecting_iid = 0;    hostdata->expecting_sto = 0;    if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS) 	hostdata->initiate_sdtr = 0xffff;     else    	hostdata->initiate_sdtr = 0;    hostdata->talked_to = 0;    hostdata->idle = 1;}/*  * Function : static int clock_to_ccf_710 (int clock) * * Purpose :  Return the clock conversion factor for a given SCSI clock. * * Inputs : clock - SCSI clock expressed in Hz. * * Returns : ccf on success, -1 on failure. */static int clock_to_ccf_710 (int clock) {    if (clock <= 16666666)	return -1;    if (clock <= 25000000)	return 2; 	/* Divide by 1.0 */    else if (clock <= 37500000)	return 1; 	/* Divide by 1.5 */    else if (clock <= 50000000)	return 0;	/* Divide by 2.0 */    else if (clock <= 66000000)	return 3;	/* Divide by 3.0 */    else 	return -1;}    /*  * Function : static int NCR53c7x0_init (struct Scsi_Host *host) * * Purpose :  initialize the internal structures for a given SCSI host * * Inputs : host - pointer to this host adapter's structure * * Preconditions : when this function is called, the chip_type  * 	field of the hostdata structure MUST have been set. * * Returns : 0 on success, -1 on failure. */int NCR53c7x0_init (struct Scsi_Host *host) {    NCR53c7x0_local_declare();    int i, ccf;    unsigned char revision;    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)	host->hostdata[0];    /*      * There are some things which we need to know about in order to provide     * a semblance of support.  Print 'em if they aren't what we expect,      * otherwise don't add to the noise.     *      * -1 means we don't know what to expect.     */    int val, flags;    char buf[32];    int expected_id = -1;    int expected_clock = -1;    int uninitialized = 0;#ifdef NO_IO_SPACE    int expected_mapping = OPTION_MEMORY_MAPPED;#else    int expected_mapping = OPTION_IO_MAPPED;#endif    for (i=0;i<7;i++)	hostdata->valid_ids[i] = 1;	/* Default all ID's to scan */    /* Parse commandline flags */    if (check_setup_strings("noasync",&flags,&val,buf))    {	hostdata->options |= OPTION_NO_ASYNC;	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);    }    if (check_setup_strings("nosync",&flags,&val,buf))    {	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);    }    if (check_setup_strings("nodisconnect",&flags,&val,buf))	hostdata->options &= ~OPTION_DISCONNECT;    if (check_setup_strings("validids",&flags,&val,buf))    {	for (i=0;i<7;i++) 		hostdata->valid_ids[i] = val & (1<<i);    }     if  ((i = check_setup_strings("next",&flags,&val,buf)))    {	while (i)		setup_used[--i] = 1;    }    if (check_setup_strings("opthi",&flags,&val,buf))	hostdata->options = (long long)val << 32;    if (check_setup_strings("optlo",&flags,&val,buf))	hostdata->options |= val;    NCR53c7x0_local_setup(host);    switch (hostdata->chip) {    case 710:    case 770:    	hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr;    	hostdata->init_save_regs = NULL;    	hostdata->dsa_fixup = NCR53c7xx_dsa_fixup;    	hostdata->init_fixup = NCR53c7x0_init_fixup;    	hostdata->soft_reset = NCR53c7x0_soft_reset;	hostdata->run_tests = NCR53c7xx_run_tests;	expected_clock = hostdata->scsi_clock;	expected_id = 7;    	break;    default:	printk ("scsi%d : chip type of %d is not supported yet, detaching.\n",	    host->host_no, hostdata->chip);	scsi_unregister (host);	return -1;    }    /* Assign constants accessed by NCR */    hostdata->NCR53c7xx_zero = 0;			    hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT;    hostdata->NCR53c7xx_msg_abort = ABORT;    hostdata->NCR53c7xx_msg_nop = NOP;    hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24;    if (expected_mapping == -1 || 	(hostdata->options & (OPTION_MEMORY_MAPPED)) != 	(expected_mapping & OPTION_MEMORY_MAPPED))	printk ("scsi%d : using %s mapped access\n", host->host_no, 	    (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" : 	    "io");    hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ? 	DMODE_REG_00 : DMODE_REG_10;    hostdata->istat = ((hostdata->chip / 100) == 8) ?     	ISTAT_REG_800 : ISTAT_REG_700;/* We have to assume that this may be the first access to the chip, so * we must set EA in DCNTL. */    NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM);/* Only the ISTAT register is readable when the NCR is running, so make    sure it's halted. */    ncr_halt(host);/*  * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc, *	as does the 710 with one bit per SCSI ID.  Conversely, the NCR * 	uses a normal, 3 bit binary representation of these values. * * Get the rest of the NCR documentation, and FIND OUT where the change * was. */#if 0	/* May not be able to do this - chip my not have been set up yet */	tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG);	for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id);#else	host->this_id = 7;#endif/* * Note : we should never encounter a board setup for ID0.  So, * 	if we see ID0, assume that it was uninitialized and set it * 	to the industry standard 7. */    if (!host->this_id) {	printk("scsi%d : initiator ID was %d, changing to 7\n",	    host->host_no, host->this_id);	host->this_id = 7;	hostdata->this_id_mask = 1 << 7;	uninitialized = 1;    };    if (expected_id == -1 || host->this_id != expected_id)    	printk("scsi%d : using initiator ID %d\n", host->host_no,    	    host->this_id);    /*     * Save important registers to allow a soft reset.     */    /*     * CTEST7 controls cache snooping, burst mode, and support for      * external differential drivers.  This isn't currently used - the     * default value may not be optimal anyway.     * Even worse, it may never have been set up since reset.     */    hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE;    revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4;    switch (revision) {	case 1: revision = 0;    break;	case 2: revision = 1;    break;	case 4: revision = 2;    break;	case 8: revision = 3;    break;	default: revision = 255; break;    }    printk("scsi%d: Revision 0x%x\n",host->host_no,revision);    if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS)))    {	printk ("scsi%d: Disabling sync working and disconnect/reselect\n",							host->host_no);	hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS);    }    /*     * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor,     * on 800 series chips, it allows for a totem-pole IRQ driver.     * NOTE saved_dcntl currently overwritten in init function.     * The value read here may be garbage anyway, MVME16x board at least     * does not initialise chip if kernel arrived via tftp.     */    hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG);    /*     * DMODE controls DMA burst length, and on 700 series chips,     * 286 mode and bus width       * NOTE:  On MVME16x, chip may have been reset, so this could be a     * power-on/reset default value.     */    hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode);    /*      * Now that burst length and enabled/disabled status is known,      * clue the user in on it.       */       ccf = clock_to_ccf_710 (expected_clock);    for (i = 0; i < 16; ++i) 	hostdata->cmd_allocated[i] = 0;    if (hostdata->init_save_regs)    	hostdata->init_save_regs (host);    if (hostdata->init_fixup)    	hostdata->init_fixup (host);    if (!the_template) {	the_template = host->hostt;	first_host = host;    }    /*      * Linux SCSI drivers have always been plagued with initialization      * problems - some didn't work with the BIOS disabled since they expected     * initialization from it, some didn't work when the networking code     * was enabled and registers got scrambled, etc.     *     * To avoid problems like this, in the future, we will do a soft      * reset on the SCSI chip, taking it back to a sane state.     */    hostdata->soft_reset (host);#if 1    hostdata->debug_count_limit = -1;#else    hostdata->debug_count_limit = 1;#endif    hostdata->intrs = -1;    hostdata->resets = -1;    memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message, 	sizeof (hostdata->synchronous_want));    NCR53c7x0_driver_init (host);    if (request_irq(host->irq, NCR53c7x0_intr, SA_SHIRQ, "53c7xx", host))    {	printk("scsi%d : IRQ%d not free, detaching\n",		host->host_no, host->irq);	scsi_unregister (host);	return -1;    }     if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||        (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {    	/* XXX Should disable interrupts, etc. here */	scsi_unregister (host);    	return -1;    } else {	if (host->io_port)  {	    host->n_io_port = 128;	    request_region (host->io_port, host->n_io_port, "ncr53c7xx");	}    }        if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) {	printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no);	hard_reset (host);    }    return 0;}/*  * Function : static int ncr53c7xx_init(Scsi_Host_Template *tpnt, int board,  *	int chip, u32 base, int io_port, int irq, int dma, long long options, *	int clock); * * Purpose : initializes a NCR53c7,8x0 based on base addresses, *	IRQ, and DMA channel.	 *	 * Inputs : tpnt - Template for this SCSI adapter, board - board level *	product, chip - 710 *  * Returns : 0 on success, -1 on failure. * */int ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip,     u32 base, int io_port, int irq, int dma, long long options, int clock){    struct Scsi_Host *instance;    struct NCR53c7x0_hostdata *hostdata;    char chip_str[80];    int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0,	schedule_size = 0, ok = 0;    void *tmp;    unsigned long page;    switch (chip) {    case 710:    case 770:	schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */;	script_len = NCR53c7xx_script_len;    	dsa_len = NCR53c7xx_dsa_len;    	options |= OPTION_INTFLY;    	sprintf (chip_str, "NCR53c%d", chip);    	break;    default:    	printk("scsi-ncr53c7xx : unsupported SCSI chip %d\n", chip);    	return -1;    }    printk("scsi-ncr53c7xx : %s at memory 0x%x, io 0x%x, irq %d",    	chip_str, (unsigned) base, io_port, irq);    if (dma == DMA_NONE)    	printk("\n");    else     	printk(", dma %d\n", dma);    if (options & OPTION_DEBUG_PROBE_ONLY) {    	printk ("scsi-ncr53c7xx : probe only enabled, aborting initialization\n");    	return -1;    }    max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len +    	/* Size of dynamic part of command structure : */	2 * /* Worst case : we don't know if we need DATA IN or DATA out */		( 2 * /* Current instructions per scatter/gather segment */         	  tpnt->sg_tablesize +                   3 /* Current startup / termination required per phase */		) *	8 /* Each instruction is eight bytes */;    /* Allocate fixed part of hostdata, dynamic part to hold appropriate       SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure.       We need a NCR53c7x0_cmd structure for scan_scsis() when we are        not loaded as a module, and when we're loaded as a module, we        can't use a non-dynamically allocated structure because modules       are vmalloc()'d, which can allow structures to cross page        boundaries and breaks our physical/virtual address assumptions       for DMA.       So, we stick it past the end of our hostdata structure.       ASSUMPTION :        	 Regardless of how many simultaneous SCSI commands we allow,	 the probe code only executes a _single_ instruction at a time,

⌨️ 快捷键说明

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