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

📄 sim710.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    case READ_TOC:        datain = 1;	dataout = 0;        break;    case MODE_SELECT:    case WRITE_6:    case WRITE_10:        datain = 0;        dataout = 1;        break;    case TEST_UNIT_READY:    case ALLOW_MEDIUM_REMOVAL:    case START_STOP:        datain = dataout = 0;        break;    default:        datain = dataout = 1;    }    memcpy(targdata->dsa_cdb, cmd->cmnd, MAX_CMND);    targdata->dsa_msgout[0] =		IDENTIFY((opt_nodisc & (1<<cmd->target)) ? 0 : 1 ,0);    if (hostdata->negotiate & (1 << cmd->target)) {	if (opt_noneg & (1 << cmd->target)) {	    hostdata->negotiate ^= (1 << cmd->target);	    targdata->dsa[DSA_MSGOUT] = 1;	}	else {	    DEB(DEB_SYNC, printk("scsi%d: Negotiating async transfers "		"for ID %d\n",		host->host_no, cmd->target));	    memcpy(targdata->dsa_msgout+1, async_message, sizeof(async_message));	    targdata->dsa[DSA_MSGOUT] = sizeof(async_message) + 1;	}    }    else	targdata->dsa[DSA_MSGOUT] = 1;    targdata->dsa_msgin[0] = 0xff;    targdata->dsa_status[0] = 0xff;    targdata->dsa[DSA_SELECT]		= (1 << cmd->target) << 16;    targdata->dsa[DSA_MSGOUT+1]		= virt_to_bus(targdata->dsa_msgout);    targdata->dsa[DSA_CMND]		= cmd->cmd_len;    targdata->dsa[DSA_CMND+1]		= virt_to_bus(targdata->dsa_cdb);    targdata->dsa[DSA_STATUS]		= 1;    targdata->dsa[DSA_STATUS+1]		= virt_to_bus(targdata->dsa_status);    targdata->dsa[DSA_MSGIN]		= 1;    targdata->dsa[DSA_MSGIN+1]		= virt_to_bus(targdata->dsa_msgin);    sg_start = (MAX_SG - (cmd->use_sg ? cmd->use_sg : 1)) * 2;    dip = targdata->dsa + DSA_DATAIN + sg_start;    dop = targdata->dsa + DSA_DATAOUT + sg_start;    for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; i++) {	u32 vbuf = cmd->use_sg ?		(u32)(((struct scatterlist *)cmd->buffer)[i].address) :		(u32)(cmd->request_buffer);	u32 bbuf = virt_to_bus((void *)vbuf);	u32 cnt = cmd->use_sg ?		((struct scatterlist *)cmd->buffer)[i].length :		cmd->request_bufflen;	if (datain) {#ifdef CONFIG_TP34V_SCSI	    cache_clear(virt_to_phys((void *)vbuf), cnt);#endif	    *dip++	= cnt;	    *dip++	= bbuf;	}	if (dataout) {#ifdef CONFIG_TP34V_SCSI	    cache_push(virt_to_phys((void *)vbuf), cnt);#endif	    *dop++	= cnt;	    *dop++	= bbuf;	}    }    targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =	virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_start + 2);    targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =	virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_start + 2);    for (i = 0, dsa = virt_to_bus(targdata->dsa); i < 4; i++) {	u32 v = hostdata->script[Ent_patch_new_dsa/4 + i * 2];	v &= ~0x0000ff00;	v |= (dsa & 0xff) << 8;	hostdata->script[Ent_patch_new_dsa/4 + i * 2] = v;	dsa >>= 8;    }    hostdata->running = targdata->cur_cmd = cmd;    hostdata->state = STATE_BUSY;    NCR_write8(ISTAT_REG, ISTAT_10_SIGP);}static volatile int process_issue_queue_running = 0; static __inline__ void run_process_issue_queue(struct sim710_hostdata *hostdata){    unsigned long flags;    save_flags (flags);    cli();    if (!process_issue_queue_running) {	process_issue_queue_running = 1;	process_issue_queue(hostdata, 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 : process_issue_queue (hostdata, flags) * * Purpose : Start next command for any idle target. *  * NOTE : process_issue_queue exits with interrupts *disabled*, so the  *	caller must reenable them if it desires. *  * NOTE : process_issue_queue should be called from both  *	sim710_queue_command() and from the interrupt handler  *	after command completion. */static void process_issue_queue (struct sim710_hostdata *hostdata, unsigned long flags){    Scsi_Cmnd *tmp, *prev;    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 process_issue_queue_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.     *     */    do {	cli(); /* Freeze request queues */	done = 1;	if (hostdata->issue_queue) {	    if (hostdata->state == STATE_DISABLED) {		tmp = (Scsi_Cmnd *) hostdata->issue_queue;		hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;		tmp->result = (DID_BAD_TARGET << 16);		tmp->scsi_done (tmp);		done = 0;	    }	    else if (hostdata->state == STATE_IDLE) {		for (tmp = hostdata->issue_queue, prev = NULL; tmp;				prev = tmp, tmp = (Scsi_Cmnd *) tmp->SCp.ptr) {		    if (hostdata->target[tmp->target].cur_cmd == NULL) {			if (prev)			    prev->SCp.ptr = tmp->SCp.ptr;			else			    hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;			tmp->SCp.ptr = NULL;			run_command (hostdata, tmp);			done = 0;		    } /* if target/lun is not busy */		} /* scan issue queue for work */	    } /* host is idle */	} /* if hostdata->issue_queue */	if (!done)	    restore_flags (flags);    } while (!done);    process_issue_queue_running = 0;}intsim710_queuecommand(Scsi_Cmnd * cmd, void (*done)(Scsi_Cmnd *)){    struct Scsi_Host *host = cmd->host;    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];    Scsi_Cmnd *tmp;    unsigned long flags;    if (cmd->lun) {	/* Silently ignore luns other than zero! */	cmd->result = (DID_BAD_TARGET << 16);	done(cmd);	return 0;    }    DEB(DEB_CMND, printk("scsi%d: id%d queuing ", host->host_no,		cmd->target));    DEB(DEB_CMND, print_command(cmd->cmnd));    cmd->scsi_done = done;    cmd->host_scribble = NULL;    cmd->SCp.ptr = NULL;    cmd->SCp.buffer = NULL;    save_flags(flags);    cli();    if (ignore_ids & (1 << cmd->target)) {	printk("scsi%d: ignoring target %d\n", host->host_no, cmd->target);	cmd->result = (DID_BAD_TARGET << 16);	done(cmd);	restore_flags (flags);	return 0;    }#ifdef DEBUG_LIMIT_INTS    if (sim710_intrs > DEBUG_LIMIT_INTS) {	cmd->result = (DID_BAD_TARGET << 16);	done(cmd);	restore_flags (flags);	return 0;    }#endif    if (cmd->use_sg > MAX_SG)	panic ("cmd->use_sg = %d\n", cmd->use_sg);    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {        cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;        hostdata->issue_queue = cmd;    } else {        for (tmp = hostdata->issue_queue; tmp->SCp.ptr;                tmp = (Scsi_Cmnd *) tmp->SCp.ptr);        tmp->SCp.ptr = (unsigned char *) cmd;    }    restore_flags (flags);    run_process_issue_queue(hostdata);    return 0;}intsim710_detect(Scsi_Host_Template * tpnt){    unsigned char irq_vector;    unsigned char scsi_id;    unsigned int base_addr;    struct Scsi_Host * host = NULL;    struct sim710_hostdata *hostdata;    int chips = 0;    int indx;    int revision;    int order, size;#ifdef MODULE    if (sim710)	param_setup(sim710);#endif    if (no_of_boards < 0) {	printk("sim710: NCR53C710 driver disabled\n");	return 0;    }#ifdef CONFIG_MCA    /* If board details have been specified via boot/module parameters,     * then don't bother probing.     */    if (no_of_boards == 0) {	int slot;	int pos[3];	int mca_53c710_ids[] = MCA_53C710_IDS;	int *id_to_check = mca_53c710_ids;	static int io_004f_by_pos[] = MCA_004F_IO_PORTS;	static int irq_004f_by_pos[] = MCA_004F_IRQS;	static int io_01bb_by_pos[] = MCA_01BB_IO_PORTS;	static int irq_01bb_by_pos[] = MCA_01BB_IRQS;	while ( *id_to_check && no_of_boards < MAXBOARDS) {	    if (!MCA_bus)		return 0;	    if ((slot = mca_find_adapter(*id_to_check, 0)) != MCA_NOTFOUND) {		pos[0] = mca_read_stored_pos(slot, 2);		pos[1] = mca_read_stored_pos(slot, 3);		pos[2] = mca_read_stored_pos(slot, 4);		/*		 * 01BB & 01BA port base by bits 7,6,5,4,3,2 in pos[2]		 *		 *    000000  <disabled>   001010  0x2800		 *    000001  <invalid>    001011  0x2C00		 *    000010  0x0800       001100  0x3000		 *    000011  0x0C00       001101  0x3400		 *    000100  0x1000       001110  0x3800		 *    000101  0x1400       001111  0x3C00		 *    000110  0x1800       010000  0x4000		 *    000111  0x1C00       010001  0x4400		 *    001000  0x2000       010010  0x4800		 *    001001  0x2400       010011  0x4C00		 *                         010100  0x5000		 *		 * 00F4 port base by bits 3,2,1 in pos[0]		 *		 *    000  <disabled>      001    0x200		 *    010  0x300           011    0x400		 *    100  0x500           101    0x600		 *		 * 01BB & 01BA IRQ is specified in pos[0] bits 7 and 6:		 *		 *    00   3               10   11		 *    01   5               11   14		 *		 * 00F4 IRQ specified by bits 6,5,4 in pos[0]		 *		 *    100   5              101    9		 *    110   14		 */		if ( *id_to_check == 0x01bb || *id_to_check == 0x01ba ) {		    bases[no_of_boards] = io_01bb_by_pos[(pos[2] & 0xFC) >> 2];		    irq_vectors[no_of_boards] =				irq_01bb_by_pos[((pos[0] & 0xC0) >> 6)];		    if (bases[no_of_boards] == 0x0000)			printk("sim710: NCR53C710 Adapter ID 0x01bb is disabled.\n");		    else {			no_of_boards++;			if ( *id_to_check == 0x01bb )			    mca_set_adapter_name( slot,				    "NCR 3360/3430 SCSI SubSystem" );			else			    mca_set_adapter_name(slot,				    "NCR Dual SIOP SCSI Host Adapter Board");		    }		}		else if ( *id_to_check == 0x004f ) {		    bases[no_of_boards] = io_004f_by_pos[((pos[0] & 0x0E) >> 1)];		    irq_vectors[no_of_boards] =				irq_004f_by_pos[((pos[0] & 0x70) >> 4) - 4];		    if (bases[no_of_boards] == 0x0000)			printk("sim710: NCR53C710 Adapter ID 0x004f is disabled.\n");		    else {			no_of_boards++;			mca_set_adapter_name(slot,				"NCR 53c710 SCSI Host Adapter Board");		    }		}	    }	    id_to_check++;	}    }#endif    if (!no_of_boards) {       printk("sim710: No NCR53C710 adapter found.\n");       return 0;    }    size = sizeof(struct sim710_hostdata);    order = 0;    while (size > (PAGE_SIZE << order))	order++;    size = PAGE_SIZE << order;    DEB(DEB_ANY, printk("sim710: hostdata %d bytes, size %d, order %d\n",	sizeof(struct sim710_hostdata), size, order));    tpnt->proc_name = "sim710";    for(indx = 0; indx < no_of_boards; indx++) {        unsigned long page = __get_free_pages(GFP_ATOMIC, order);        if(page == 0UL)        {        	printk(KERN_WARNING "sim710: out of memory registering board %d.\n", indx);        	break;        }	host = scsi_register(tpnt, 4);	if(host == NULL)		break;	host->hostdata[0] = page;	hostdata = (struct sim710_hostdata *)host->hostdata[0];	memset(hostdata, 0, size);#ifdef CONFIG_TP34V_SCSI	cache_push(virt_to_phys(hostdata), size);	cache_clear(virt_to_phys(hostdata), size);	kernel_set_cachemode((void *)hostdata,size,IOMAP_NOCACHE_SER);#endif	scsi_id = 7;	base_addr = bases[indx];	irq_vector = irq_vectors[indx];	printk("sim710: Configuring Sim710 (SCSI-ID %d) at %x, IRQ %d\n",	    		scsi_id, base_addr, irq_vector);	DEB(DEB_ANY, printk("sim710: hostdata = %p (%d bytes), dsa0 = %p\n",			hostdata, sizeof(struct sim710_hostdata),			 hostdata->target[0].dsa));	hostdata->chip = indx;	host->irq = irq_vector;	host->this_id = scsi_id;	host->unique_id = base_addr;	host->base = base_addr;	ncr_halt(host);	revision = (NCR_read8(CTEST8_REG) & 0xF0) >> 4;	printk("scsi%d: Revision 0x%x\n",host->host_no,revision);	sim710_soft_reset(host);	sim710_driver_init(host);#ifdef CONFIG_TP34V_SCSI	if (request_irq(irq_vector,do_sim710_intr_handle, 0, "sim710", host))#else	if (request_irq(irq_vector,do_sim710_intr_handle, SA_INTERRUPT, "sim710", host))#endif	{	    printk("scsi%d : IRQ%d not free, detaching\n",	    		host->host_no, host->irq);	    scsi_unregister (host);	}	else {#ifdef IO_MAPPED	    request_region((u32)host->base, 64, "sim710");#endif	    chips++;	}	NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));	hostdata->state = STATE_IDLE;    }    return chips;}intsim710_abort(Scsi_Cmnd * cmd){    struct Scsi_Host * host = cmd->host;    printk("scsi%d: Unable to abort command for target %d\n",	   host->host_no, cmd->target);    return FAILED;}/* * This is a device reset.  Need to select and send a Bus Device Reset msg. */intsim710_dev_reset(Scsi_Cmnd * SCpnt){    struct Scsi_Host * host = SCpnt->host;    printk("scsi%d: Unable to send Bus Device Reset for target %d\n",	   host->host_no, SCpnt->target);    return FAILED;}/* * This is bus reset.  We need to reset the bus and fail any active commands. */intsim710_bus_reset(Scsi_Cmnd * SCpnt){    struct Scsi_Host * host = SCpnt->host;    printk("scsi%d: Unable to do SCSI bus reset\n", host->host_no);    return FAILED;}static intfull_reset(struct Scsi_Host * host){    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)	    host->hostdata[0];    int target;    Scsi_Cmnd *cmd;    ncr_halt(host);    printk("scsi%d: dsp = %08x (script[0x%04x]), scratch = %08x\n",	host->host_no, NCR_read32(DSP_REG),	((u32)bus_to_virt(NCR_read32(DSP_REG)) - (u32)hostdata->script)/4,	NCR_read32(SCRATCH_REG));    for (target = 0; target < 7; target++) {	if ((cmd = hostdata->target[target].cur_cmd)) {	    printk("scsi%d: Failing command for ID%d\n",			host->host_no, target);	    cmd->result = DID_RESET << 16;	    cmd->scsi_done(cmd);	    hostdata->target[target].cur_cmd = NULL;	}    }    sim710_soft_reset(host);    sim710_driver_init(host);    NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));    hostdata->state = STATE_IDLE;    run_process_issue_queue(hostdata);    return SUCCESS;}/* * This is host reset.  We need to reset the chip and the bus. */intsim710_host_reset(Scsi_Cmnd * SCpnt){    struct Scsi_Host * host = SCpnt->host;    printk("scsi%d: >>>>>>>>>>>> Host reset <<<<<<<<<<<<\n", host->host_no);    return full_reset(host);}#ifdef MODULEintsim710_release(struct Scsi_Host *host){    free_irq(host->irq, host);#ifdef IO_MAPPED    release_region((u32)host->base, 64);#endif    return 1;}#endifstatic Scsi_Host_Template driver_template = SIM710_SCSI;#include "scsi_module.c"

⌨️ 快捷键说明

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