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

📄 ncr5380.c

📁 <Linux1.0核心游记>电子书+书后源码+Linux1.0源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static volatile int main_running = 0;/*  * Function : run_main(void) *  * Purpose : insure that the coroutine is running and will process our  * 	request.  main_running is checked/set here (in an inline function) *	rather than in NCR5380_main itself to reduce the chances of stack *	overflow. * */static __inline__ void run_main(void) {    cli();    if (!main_running) {	main_running = 1;        NCR5380_main();	/*          * main_running is cleared in NCR5380_main once it can't do 	 * more work, and NCR5380_main exits with interrupts disabled.	 */	sti();    } else 	sti();}#ifdef USLEEP#ifndef NCR5380_TIMER#error "NCR5380_TIMER must be defined so that this type of NCR5380 driver gets a unique timer."#endif/* * These need tweaking, and would probably work best as per-device  * flags initialized differently for disk, tape, cd, etc devices. * People with broken devices are free to experiment as to what gives * the best results for them. * * USLEEP_SLEEP should be a minimum seek time. * * USLEEP_POLL should be a maximum rotational latency. */#ifndef USLEEP_SLEEP/* 20 ms (reasonable hard disk speed) */#define USLEEP_SLEEP 2#endif/* 300 RPM (floppy speed) */#ifndef USLEEP_POLL#define USLEEP_POLL 20#endifstatic struct Scsi_Host * expires_first = NULL;/*  * Function : int should_disconnect (unsigned char cmd) * * Purpose : decide weather a commmand would normally disconnect or  *	not, since if it won't disconnect we should go to sleep. * * Input : cmd - opcode of SCSI command * * Returns : DISCONNECT_LONG if we should disconnect for a really long  * 	time (ie always, sleep, look for REQ active, sleep),  *	DISCONNECT_TIME_TO_DATA if we would only disconnect for a normal * 	time-to-data dealy, DISCONNECT_NONE if this command would return * 	immediately. * *      Future sleep algorithms based on time to data can exploit  *      something like this so they can differentiate between "normal"  *	(ie, read, write, seek) and unusual commands (ie, * format). * * Note : We don't deal with commands that handle an immediate disconnect, *         */static int should_disconnect (unsigned char cmd) {    switch (cmd) {    case READ_6:    case WRITE_6:    case SEEK_6:    case READ_10:    case WRITE_10:    case SEEK_10:	return DISCONNECT_TIME_TO_DATA;    case FORMAT_UNIT:    case SEARCH_HIGH:    case SEARCH_LOW:    case SEARCH_EQUAL:	return DISCONNECT_LONG;    default:	return DISCONNECT_NONE;    }}/* * Assumes instance->time_expires has been set in higher level code. */static int NCR5380_set_timer (struct Scsi_Host *instance) {    struct Scsi_Host *tmp, **prev;        cli();    if (((struct NCR5380_hostdata *) (instance->host_data))->next_timer) {	sti();	return -1;    }    for (prev = &expires_first, tmp = expires_first; tmp; 	prev = &(((struct NCR5380_hostdata *) tmp->host_data)->next_timer), 	tmp = ((struct NCR5380_hostdata *) tmp->host_data)->next_timer)	if (instance->time_expires < tmp->time_expires) 	    break;	       instance->next_timer = tmp;    *prev = instance;    timer_table[NCR5380_TIMER].expires = expires_first->time_expires;    timer_active |= 1 << NCR5380_TIMER;    sti;    return 0;}    /* Doing something about unwanted rentrancy here might be useful */void NCR5380_timer_fn(void) {    struct Scsi_Host *instance;    cli();    for (; expires_first && expires_first->time_expires >= jiffies; ) {	instance = ((NCR5380_hostdata *) expires_first->host_data)->	    expires_next;	((NCR5380_hostdata *) expires_first->host_data)->expires_next = 	    NULL;	((NCR5380_hostdata *) expires_first->host_data)->time_expires = 	    0;	expires_first = instance;    }    if (expires_first) {	timer_table[NCR5380_TIMER].expires = ((NCR5380_hostdata *) 	    expires_first->host_data)->time_expires;	timer_active |= (1 << NCR5380_TIMER);    } else {	timer_table[NCR5380_TIMER].expires = 0;	timer_active &= ~(1 << MCR5380_TIMER);    }    sti();    run_main();}#endif /* def USLEEP */static void NCR5380_all_init (void) {    static int done = 0;    if (!done) {#if (NDEBUG & NDEBUG_INIT)	printk("scsi : NCR5380_all_init()\n");#endif	done = 1;#ifdef USLEEP	timer_table[NCR5380_TIMER].expires = 0;	timer_table[NCR5380_TIMER].fn = NCR5380_timer_fn;#endif    }}#ifdef AUTOPROBE_IRQ/* * Function : int NCR5380_probe_irq (struct Scsi_Host *instance, int possible) *  * Purpose : autoprobe for the IRQ line used by the NCR5380.   * * Inputs : instance - pointer to this instance of the NCR5380 driver, *          possible - bitmask of permissable interrupts. * * Returns : number of the IRQ selected, IRQ_NONE if no interrupt fired. *  * XXX no effort is made to deal with spurious interrupts.  */static int probe_irq;static void probe_intr (int sig) {    probe_irq = sig;};static struct sigaction probe_sigaction = { probe_intr, 0, SA_INTERRUPT,    NULL};static int NCR5380_probe_irq (struct Scsi_Host *instance, int possible) {    NCR5380_local_declare();    struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)	 instance->hostdata;    unsigned long timeout;    int trying_irqs, i, mask;    NCR5380_setup(instance);    for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1) 	if ((mask & possible) &&  (irqaction (i, &probe_sigaction) 	    == 0)) 	    trying_irqs |= mask;    timeout = jiffies + 25;    probe_irq = IRQ_NONE;/* * A interrupt is triggered whenever BSY = false, SEL = true * and a bit set in the SELECT_ENABLE_REG is asserted on the  * SCSI bus. * * Note that the bus is only driven when the phase control signals * (I/O, C/D, and MSG) match those in the TCR, so we must reset that * to zero. */    NCR5380_write(TARGET_COMMAND_REG, 0);    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);    NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | 	ICR_ASSERT_SEL);    while (probe_irq == IRQ_NONE && jiffies < timeout);    NCR5380_write(SELECT_ENABLE_REG, 0);    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);    for (i = 0, mask = 1; i < 16; ++i, mask <<= 1)	if (trying_irqs & mask) 	    free_irq(i);    return probe_irq;}#endif /* AUTOPROBE_IRQ */ /* * Function : void NCR58380_print_options (struct Scsi_Host *instance) * * Purpose : called by probe code indicating the NCR5380 driver *	     options that were selected. * * Inputs : instance, pointer to this instance.  Unused. */static void NCR5380_print_options (struct Scsi_Host *instance) {    printk(" generic options"#ifdef AUTOPROBE_IRQ    " AUTOPROBE_IRQ"#endif#ifdef AUTOSENSE     " AUTOSENSE"#endif#ifdef DIFFERENTIAL    " DIFFERENTIAL"#endif#ifdef REAL_DMA    " REAL DMA"#endif#ifdef REAL_DMA_POLL    " REAL DMA POLL"#endif#ifdef PARITY    " PARITY"#endif#ifdef PSEUDO_DMA    " PSEUDO DMA"#endif#ifdef SCSI2    " SCSI-2"#endif#ifdef UNSAFE    " UNSAFE "#endif    );#ifdef USLEEP    printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);#endif    printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);}/*  * Function : void NCR5380_init (struct Scsi_Host *instance) * * Purpose : initializies *instance and corresponding 5380 chip. * * 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) {    NCR5380_local_declare();    int i;    struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) 	instance->hostdata;    NCR5380_setup(instance);    NCR5380_all_init();    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->connected = NULL;    hostdata->issue_queue = NULL;    hostdata->disconnected_queue = NULL;    hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;    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, contigent alligence 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);}/*  * 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 NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)	cmd->host->hostdata;    Scsi_Cmnd *tmp;#if (NDEBUG & NDEBUG_NO_WRITE)    switch (cmd->cmnd[0]) {    case WRITE:    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) */    /*      * 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 allegience condition that exists and the      * sense data is only guranteed to be valid while the condition exists.     */    cli();    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {	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);	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 allready running. */    run_main();    return 0;}/* * Function : NCR5380_main (void)  *

⌨️ 快捷键说明

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