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

📄 53c7xx.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 so we only need one here, and don't need to allocate NCR53c7x0_cmd	 structures for each target until we are no longer in scan_scsis	 and kmalloc() has become functional (memory_init() happens 	 after all device driver initialization).    */    size = sizeof(struct NCR53c7x0_hostdata) + script_len +     /* Note that alignment will be guaranteed, since we put the command       allocated at probe time after the fixed-up SCSI script, which        consists of 32 bit words, aligned on a 32 bit boundary.  But       on a 64bit machine we need 8 byte alignment for hostdata->free, so       we add in another 4 bytes to take care of potential misalignment       */	(sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size;    page = __get_free_pages(GFP_ATOMIC,1);    if(page==0)    {    	printk(KERN_ERR "53c7xx: out of memory.\n");    	return -ENOMEM;    }#ifdef FORCE_DSA_ALIGNMENT    /*     * 53c710 rev.0 doesn't have an add-with-carry instruction.     * Ensure we allocate enough memory to force DSA alignment.    */    size += 256;#endif    /* Size should be < 8K, so we can fit it in two pages. */    if (size > 8192)      panic("53c7xx: hostdata > 8K");    instance = scsi_register (tpnt, 4);    if (!instance)    {        free_page(page);	return -1;    }    instance->hostdata[0] = page;    memset((void *)instance->hostdata[0], 0, 8192);    cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192);    cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192);    kernel_set_cachemode(instance->hostdata[0], 8192, IOMAP_NOCACHE_SER);    /* FIXME : if we ever support an ISA NCR53c7xx based board, we       need to check if the chip is running in a 16 bit mode, and if so        unregister it if it is past the 16M (0x1000000) mark */    hostdata = (struct NCR53c7x0_hostdata *)instance->hostdata[0];    hostdata->size = size;    hostdata->script_count = script_len / sizeof(u32);    hostdata->board = board;    hostdata->chip = chip;    /*     * Being memory mapped is more desirable, since      *     * - Memory accesses may be faster.     *     * - The destination and source address spaces are the same for      *	 all instructions, meaning we don't have to twiddle dmode or      *	 any other registers.     *     * So, we try for memory mapped, and if we don't get it,     * we go for port mapped, and that failing we tell the user     * it can't work.     */    if (base) {	instance->base = (unsigned char *) (unsigned long) base;	/* Check for forced I/O mapping */    	if (!(options & OPTION_IO_MAPPED)) {	    options |= OPTION_MEMORY_MAPPED;	    ok = 1;	}    } else {	options &= ~OPTION_MEMORY_MAPPED;    }    if (io_port) {	instance->io_port = io_port;	options |= OPTION_IO_MAPPED;	ok = 1;    } else {	options &= ~OPTION_IO_MAPPED;    }    if (!ok) {	printk ("scsi%d : not initializing, no I/O or memory mapping known \n",	    instance->host_no);	scsi_unregister (instance);	return -1;    }    instance->irq = irq;    instance->dma_channel = dma;    hostdata->options = options;    hostdata->dsa_len = dsa_len;    hostdata->max_cmd_size = max_cmd_size;    hostdata->num_cmds = 1;    hostdata->scsi_clock = clock;    /* Initialize single command */    tmp = (hostdata->script + hostdata->script_count);#ifdef FORCE_DSA_ALIGNMENT    {	void *t = ROUNDUP(tmp, void *);	if (((u32)t & 0xff) > CmdPageStart)	    t = (void *)((u32)t + 255);	t = (void *)(((u32)t & ~0xff) + CmdPageStart);        hostdata->free = t;#if 0	printk ("scsi: Registered size increased by 256 to %d\n", size);	printk ("scsi: CmdPageStart = 0x%02x\n", CmdPageStart);	printk ("scsi: tmp = 0x%08x, hostdata->free set to 0x%08x\n",			(u32)tmp, (u32)t);#endif    }#else    hostdata->free = ROUNDUP(tmp, void *);#endif    hostdata->free->real = tmp;    hostdata->free->size = max_cmd_size;    hostdata->free->free = NULL;    hostdata->free->next = NULL;    hostdata->extra_allocate = 0;    /* Allocate command start code space */    hostdata->schedule = (chip == 700 || chip == 70066) ?	NULL : (u32 *) ((char *)hostdata->free + max_cmd_size);/*  * For diagnostic purposes, we don't really care how fast things blaze. * For profiling, we want to access the 800ns resolution system clock, * using a 'C' call on the host processor. * * Therefore, there's no need for the NCR chip to directly manipulate * this data, and we should put it wherever is most convenient for  * Linux. */    if (track_events) 	hostdata->events = (struct NCR53c7x0_event *) (track_events ? 	    vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL);    else	hostdata->events = NULL;    if (hostdata->events) {	memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) *	    track_events);		hostdata->event_size = track_events;	hostdata->event_index = 0;    } else 	hostdata->event_size = 0;    return NCR53c7x0_init(instance);}/*  * Function : static void NCR53c7x0_init_fixup (struct Scsi_Host *host) * * Purpose :  copy and fixup the SCSI SCRIPTS(tm) code for this device. * * Inputs : host - pointer to this host adapter's structure * */static void NCR53c7x0_init_fixup (struct Scsi_Host *host) {    NCR53c7x0_local_declare();    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)	host->hostdata[0];    unsigned char tmp;    int i, ncr_to_memory, memory_to_ncr;    u32 base;    NCR53c7x0_local_setup(host);    /* XXX - NOTE : this code MUST be made endian aware */    /*  Copy code into buffer that was allocated at detection time.  */    memcpy ((void *) hostdata->script, (void *) SCRIPT, 	sizeof(SCRIPT));    /* Fixup labels */    for (i = 0; i < PATCHES; ++i) 	hostdata->script[LABELPATCHES[i]] +=     	    virt_to_bus(hostdata->script);    /* Fixup addresses of constants that used to be EXTERNAL */    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_abort,     	virt_to_bus(&(hostdata->NCR53c7xx_msg_abort)));    patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_reject,     	virt_to_bus(&(hostdata->NCR53c7xx_msg_reject)));    patch_abs_32 (hostdata->script, 0, NCR53c7xx_zero,     	virt_to_bus(&(hostdata->NCR53c7xx_zero)));    patch_abs_32 (hostdata->script, 0, NCR53c7xx_sink,     	virt_to_bus(&(hostdata->NCR53c7xx_sink)));    patch_abs_32 (hostdata->script, 0, NOP_insn,	virt_to_bus(&(hostdata->NOP_insn)));    patch_abs_32 (hostdata->script, 0, schedule,	virt_to_bus((void *) hostdata->schedule));    /* Fixup references to external variables: */    for (i = 0; i < EXTERNAL_PATCHES_LEN; ++i)       hostdata->script[EXTERNAL_PATCHES[i].offset] +=         virt_to_bus(EXTERNAL_PATCHES[i].address);    /*      * Fixup absolutes set at boot-time.     *      * All non-code absolute variables suffixed with "dsa_" and "int_"     * are constants, and need no fixup provided the assembler has done      * it for us (I don't know what the "real" NCR assembler does in      * this case, my assembler does the right magic).     */    patch_abs_rwri_data (hostdata->script, 0, dsa_save_data_pointer,     	Ent_dsa_code_save_data_pointer - Ent_dsa_zero);    patch_abs_rwri_data (hostdata->script, 0, dsa_restore_pointers,    	Ent_dsa_code_restore_pointers - Ent_dsa_zero);    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect,    	Ent_dsa_code_check_reselect - Ent_dsa_zero);    /*     * Just for the hell of it, preserve the settings of      * Burst Length and Enable Read Line bits from the DMODE      * register.  Make sure SCRIPTS start automagically.     */#if defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)    /* We know better what we want than 16xBug does! */    tmp = DMODE_10_BL_8 | DMODE_10_FC2;#else    tmp = NCR53c7x0_read8(DMODE_REG_10);    tmp &= (DMODE_BL_MASK | DMODE_10_FC2 | DMODE_10_FC1 | DMODE_710_PD |								DMODE_710_UO);#endif    if (!(hostdata->options & OPTION_MEMORY_MAPPED)) {    	base = (u32) host->io_port;    	memory_to_ncr = tmp|DMODE_800_DIOM;    	ncr_to_memory = tmp|DMODE_800_SIOM;    } else {    	base = virt_to_bus(host->base);	memory_to_ncr = ncr_to_memory = tmp;    }    /* SCRATCHB_REG_10 == SCRATCHA_REG_800, as it happens */    patch_abs_32 (hostdata->script, 0, addr_scratch, base + SCRATCHA_REG_800);    patch_abs_32 (hostdata->script, 0, addr_temp, base + TEMP_REG);    patch_abs_32 (hostdata->script, 0, addr_dsa, base + DSA_REG);    /*     * I needed some variables in the script to be accessible to      * both the NCR chip and the host processor. For these variables,     * I made the arbitrary decision to store them directly in the      * hostdata structure rather than in the RELATIVE area of the      * SCRIPTS.     */        patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp);    patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr);    patch_abs_rwri_data (hostdata->script, 0, dmode_ncr_to_memory, ncr_to_memory);    patch_abs_32 (hostdata->script, 0, msg_buf, 	virt_to_bus((void *)&(hostdata->msg_buf)));    patch_abs_32 (hostdata->script, 0, reconnect_dsa_head,     	virt_to_bus((void *)&(hostdata->reconnect_dsa_head)));    patch_abs_32 (hostdata->script, 0, addr_reconnect_dsa_head, 	virt_to_bus((void *)&(hostdata->addr_reconnect_dsa_head)));    patch_abs_32 (hostdata->script, 0, reselected_identify,     	virt_to_bus((void *)&(hostdata->reselected_identify)));/* reselected_tag is currently unused */#if 0    patch_abs_32 (hostdata->script, 0, reselected_tag,     	virt_to_bus((void *)&(hostdata->reselected_tag)));#endif    patch_abs_32 (hostdata->script, 0, test_dest, 	virt_to_bus((void*)&hostdata->test_dest));    patch_abs_32 (hostdata->script, 0, test_src, 	virt_to_bus(&hostdata->test_source));    patch_abs_32 (hostdata->script, 0, saved_dsa,	virt_to_bus(&hostdata->saved2_dsa));    patch_abs_32 (hostdata->script, 0, emulfly,	virt_to_bus(&hostdata->emulated_intfly));    patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, 	(unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero));/* These are for event logging; the ncr_event enum contains the    actual interrupt numbers. */#ifdef A_int_EVENT_SELECT   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT, (u32) EVENT_SELECT);#endif#ifdef A_int_EVENT_DISCONNECT   patch_abs_32 (hostdata->script, 0, int_EVENT_DISCONNECT, (u32) EVENT_DISCONNECT);#endif#ifdef A_int_EVENT_RESELECT   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT, (u32) EVENT_RESELECT);#endif#ifdef A_int_EVENT_COMPLETE   patch_abs_32 (hostdata->script, 0, int_EVENT_COMPLETE, (u32) EVENT_COMPLETE);#endif#ifdef A_int_EVENT_IDLE   patch_abs_32 (hostdata->script, 0, int_EVENT_IDLE, (u32) EVENT_IDLE);#endif#ifdef A_int_EVENT_SELECT_FAILED   patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT_FAILED, 	(u32) EVENT_SELECT_FAILED);#endif#ifdef A_int_EVENT_BEFORE_SELECT   patch_abs_32 (hostdata->script, 0, int_EVENT_BEFORE_SELECT,	(u32) EVENT_BEFORE_SELECT);#endif#ifdef A_int_EVENT_RESELECT_FAILED   patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT_FAILED, 	(u32) EVENT_RESELECT_FAILED);#endif    /*     * Make sure the NCR and Linux code agree on the location of      * certain fields.     */    hostdata->E_accept_message = Ent_accept_message;    hostdata->E_command_complete = Ent_command_complete;		    hostdata->E_cmdout_cmdout = Ent_cmdout_cmdout;    hostdata->E_data_transfer = Ent_data_transfer;    hostdata->E_debug_break = Ent_debug_break;	    hostdata->E_dsa_code_template = Ent_dsa_code_template;    hostdata->E_dsa_code_template_end = Ent_dsa_code_template_end;    hostdata->E_end_data_transfer = Ent_end_data_transfer;    hostdata->E_initiator_abort = Ent_initiator_abort;    hostdata->E_msg_in = Ent_msg_in;    hostdata->E_other_transfer = Ent_other_transfer;    hostdata->E_other_in = Ent_other_in;    hostdata->E_other_out = Ent_other_out;    hostdata->E_reject_message = Ent_reject_message;    hostdata->E_respond_message = Ent_respond_message;    hostdata->E_select = Ent_select;    hostdata->E_select_msgout = Ent_select_msgout;    hostdata->E_target_abort = Ent_target_abort;#ifdef Ent_test_0    hostdata->E_test_0 = Ent_test_0;#endif    hostdata->E_test_1 = Ent_test_1;    hostdata->E_test_2 = Ent_test_2;#ifdef Ent_test_3    hostdata->E_test_3 = Ent_test_3;#endif    hostdata->E_wait_reselect = Ent_wait_reselect;    hostdata->E_dsa_code_begin = Ent_dsa_code_begin;    hostdata->dsa_cmdout = A_dsa_cmdout;    hostdata->dsa_cmnd = A_dsa_cmnd;    hostdata->dsa_datain = A_dsa_datain;    hostdata->dsa_dataout = A_dsa_dataout;    hostdata->dsa_end = A_dsa_end;			    hostdata->dsa_msgin = A_dsa_msgin;    hostdata->dsa_msgout = A_dsa_msgout;    hostdata->dsa_msgout_other = A_dsa_msgout_other;    hostdata->dsa_next = A_dsa_next;    hostdata->dsa_select = A_dsa_select;    hostdata->dsa_start = Ent_dsa_code_template - Ent_dsa_zero;    hostdata->dsa_status = A_dsa_status;    hostdata->dsa_jump_dest = Ent_dsa_code_fix_jump - Ent_dsa_zero + 	8 /* destination operand */;    /* sanity check */    if (A_dsa_fields_start != Ent_dsa_code_template_end -     	Ent_dsa_zero)     	printk("scsi%d : NCR dsa_fields start is %d not %d\n",    	    host->host_no, A_dsa_fields_start, Ent_dsa_code_template_end -     	    Ent_dsa_zero);    printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no,	virt_to_bus(hostdata->script), hostdata->script);}/* * Function : static int NCR53c7xx_run_tests (struct Scsi_Host *host) * * Purpose : run various verification tests on the NCR chip,  *	including interrupt generation, and proper bus mastering * 	operation. *  * Inputs : host - a properly initialized Scsi_Host structure * * Preconditions : the NCR chip must be in a halted state. * * Returns : 0 if all tests were successful, -1 on error. *  */

⌨️ 快捷键说明

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