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

📄 53c7xx.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
         }      }   for (i=0; i<MAX_SETUP_STRINGS; i++)      setup_used[i] = 0;}/* check_setup_strings() returns index if key found, 0 if not */static int check_setup_strings(char *key, int *flags, int *val, char *buf){int x;char *cp;   for  (x=0; x<MAX_SETUP_STRINGS; x++) {      if (setup_used[x])         continue;      if (!strncmp(setup_strings[x], key, strlen(key)))         break;      if (!strncmp(setup_strings[x], "next", strlen("next")))         return 0;      }   if (x == MAX_SETUP_STRINGS)      return 0;   setup_used[x] = 1;   cp = setup_strings[x] + strlen(key);   *val = -1;   if (*cp != ':')      return ++x;   cp++;   if ((*cp >= '0') && (*cp <= '9')) {      *val = simple_strtoul(cp,NULL,0);      }   return ++x;}/* * KNOWN BUGS : * - There is some sort of conflict when the PPP driver is compiled with  * 	support for 16 channels? *  * - On systems which predate the 1.3.x initialization order change, *      the NCR driver will cause Cannot get free page messages to appear.   *      These are harmless, but I don't know of an easy way to avoid them. * * - With OPTION_DISCONNECT, on two systems under unknown circumstances, *	we get a PHASE MISMATCH with DSA set to zero (suggests that we  *	are occurring somewhere in the reselection code) where  *	DSP=some value DCMD|DBC=same value.   * 	 *	Closer inspection suggests that we may be trying to execute *	some portion of the DSA? * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) * scsi0 : no current command : unexpected phase MSGIN. *         DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0 *         DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80 * scsi0 : DSP-> * 001c46cc : 0x001c46cc 0x00000000 * 001c46d4 : 0x001c5ea0 0x000011f8 * *	Changed the print code in the phase_mismatch handler so *	that we call print_lots to try to diagnose this. * *//*  * Possible future direction of architecture for max performance : * * We're using a single start array for the NCR chip.  This is  * sub-optimal, because we cannot add a command which would conflict with  * an executing command to this start queue, and therefore must insert the  * next command for a given I/T/L combination after the first has completed; * incurring our interrupt latency between SCSI commands. * * To allow further pipelining of the NCR and host CPU operation, we want  * to set things up so that immediately on termination of a command destined  * for a given LUN, we get that LUN busy again.   *  * To do this, we need to add a 32 bit pointer to which is jumped to  * on completion of a command.  If no new command is available, this  * would point to the usual DSA issue queue select routine. * * If one were, it would point to a per-NCR53c7x0_cmd select routine  * which starts execution immediately, inserting the command at the head  * of the start queue if the NCR chip is selected or reselected. * * We would change so that we keep a list of outstanding commands  * for each unit, rather than a single running_list.  We'd insert  * a new command into the right running list; if the NCR didn't  * have something running for that yet, we'd put it in the  * start queue as well.  Some magic needs to happen to handle the  * race condition between the first command terminating before the  * new one is written. * * Potential for profiling :  * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution. *//* * TODO :  * 1.  To support WIDE transfers, not much needs to happen.  We *	should do CHMOVE instructions instead of MOVEs when *	we have scatter/gather segments of uneven length.  When * 	we do this, we need to handle the case where we disconnect *	between segments. *  * 2.  Currently, when Icky things happen we do a FATAL().  Instead, *     we want to do an integrity check on the parts of the NCR hostdata *     structure which were initialized at boot time; FATAL() if that  *     fails, and otherwise try to recover.  Keep track of how many *     times this has happened within a single SCSI command; if it  *     gets excessive, then FATAL(). * * 3.  Parity checking is currently disabled, and a few things should  *     happen here now that we support synchronous SCSI transfers : *     1.  On soft-reset, we shoould set the EPC (Enable Parity Checking) *	   and AAP (Assert SATN/ on parity error) bits in SCNTL0. *	 *     2.  We should enable the parity interrupt in the SIEN0 register. *  *     3.  intr_phase_mismatch() needs to believe that message out is  *	   always an "acceptable" phase to have a mismatch in.  If  *	   the old phase was MSG_IN, we should send a MESSAGE PARITY  *	   error.  If the old phase was something else, we should send *	   a INITIATOR_DETECTED_ERROR message.  Note that this could *	   cause a RESTORE POINTERS message; so we should handle that  *	   correctly first.  Instead, we should probably do an  *	   initiator_abort. * * 4.  MPEE bit of CTEST4 should be set so we get interrupted if  *     we detect an error. * *   * 5.  The initial code has been tested on the NCR53c810.  I don't  *     have access to NCR53c700, 700-66 (Forex boards), NCR53c710 *     (NCR Pentium systems), NCR53c720, NCR53c820, or NCR53c825 boards to  *     finish development on those platforms. * *     NCR53c820/825/720 - need to add wide transfer support, including WDTR  *     		negotiation, programming of wide transfer capabilities *		on reselection and table indirect selection. * *     NCR53c710 - need to add fatal interrupt or GEN code for  *		command completion signaling.   Need to modify all  *		SDID, SCID, etc. registers, and table indirect select code  *		since these use bit fielded (ie 1<<target) instead of  *		binary encoded target ids.  Need to accommodate *		different register mappings, probably scan through *		the SCRIPT code and change the non SFBR register operand *		of all MOVE instructions. * *		It is rather worse than this actually, the 710 corrupts *		both TEMP and DSA when you do a MOVE MEMORY.  This *		screws you up all over the place.  MOVE MEMORY 4 with a *		destination of DSA seems to work OK, which helps some. *		Richard Hirst  richard@sleepie.demon.co.uk *  *     NCR53c700/700-66 - need to add code to refix addresses on  *		every nexus change, eliminate all table indirect code, *		very messy. * * 6.  The NCR53c7x0 series is very popular on other platforms that  *     could be running Linux - ie, some high performance AMIGA SCSI  *     boards use it.   *	 *     So, I should include #ifdef'd code so that it is  *     compatible with these systems. *	 *     Specifically, the little Endian assumptions I made in my  *     bit fields need to change, and if the NCR doesn't see memory *     the right way, we need to provide options to reverse words *     when the scripts are relocated. * * 7.  Use vremap() to access memory mapped boards.   *//*  * Allow for simultaneous existence of multiple SCSI scripts so we  * can have a single driver binary for all of the family. * * - one for NCR53c700 and NCR53c700-66 chips	(not yet supported) * - one for rest (only the NCR53c810, 815, 820, and 825 are currently  *	supported) *  * So that we only need two SCSI scripts, we need to modify things so * that we fixup register accesses in READ/WRITE instructions, and  * we'll also have to accommodate the bit vs. binary encoding of IDs * with the 7xx chips. */#define ROUNDUP(adr,type)	\  ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1)))/* * Function: issue_to_cmd * * Purpose: convert jump instruction in issue array to NCR53c7x0_cmd *	structure pointer.   * * Inputs; issue - pointer to start of NOP or JUMP instruction *	in issue array. * * Returns: pointer to command on success; 0 if opcode is NOP. */static inline struct NCR53c7x0_cmd *issue_to_cmd (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,    u32 *issue){    return (issue[0] != hostdata->NOP_insn) ?     /*      * If the IF TRUE bit is set, it's a JUMP instruction.  The     * operand is a bus pointer to the dsa_begin routine for this DSA.  The     * dsa field of the NCR53c7x0_cmd structure starts with the      * DSA code template.  By converting to a virtual address,     * subtracting the code template size, and offset of the      * dsa field, we end up with a pointer to the start of the      * structure (alternatively, we could use the      * dsa_cmnd field, an anachronism from when we weren't     * sure what the relationship between the NCR structures     * and host structures were going to be.     */	(struct NCR53c7x0_cmd *) ((char *) bus_to_virt (issue[1]) - 	    (hostdata->E_dsa_code_begin - hostdata->E_dsa_code_template) -	    offsetof(struct NCR53c7x0_cmd, dsa))     /* If the IF TRUE bit is not set, it's a NOP */	: NULL;}/*  * FIXME: we should junk these, in favor of synchronous_want and  * wide_want in the NCR53c7x0_hostdata structure. *//* Template for "preferred" synchronous transfer parameters. */static const unsigned char sdtr_message[] = {#ifdef CONFIG_SCSI_NCR53C7xx_FAST    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 25 /* *4ns */, 8 /* off */#else    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 50 /* *4ns */, 8 /* off */ #endif};/* Template to request asynchronous transfers */static const unsigned char async_message[] = {    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */};/* Template for "preferred" WIDE transfer parameters */static const unsigned char wdtr_message[] = {    EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */};#if 0/* * Function : struct Scsi_Host *find_host (int host) *  * Purpose : KGDB support function which translates a host number  * 	to a host structure.  * * Inputs : host - number of SCSI host * * Returns : NULL on failure, pointer to host structure on success. */static struct Scsi_Host *find_host (int host) {    struct Scsi_Host *h;    for (h = first_host; h && h->host_no != host; h = h->next);    if (!h) {	printk (KERN_ALERT "scsi%d not found\n", host);	return NULL;    } else if (h->hostt != the_template) {	printk (KERN_ALERT "scsi%d is not a NCR board\n", host);	return NULL;    }    return h;}#if 0/* * Function : request_synchronous (int host, int target) *  * Purpose : KGDB interface which will allow us to negotiate for  * 	synchronous transfers.  This ill be replaced with a more  * 	integrated function; perhaps a new entry in the scsi_host  *	structure, accessible via an ioctl() or perhaps /proc/scsi. * * Inputs : host - number of SCSI host; target - number of target. * * Returns : 0 when negotiation has been setup for next SCSI command, *	-1 on failure. */static intrequest_synchronous (int host, int target) {    struct Scsi_Host *h;    struct NCR53c7x0_hostdata *hostdata;    unsigned long flags;    if (target < 0) {	printk (KERN_ALERT "target %d is bogus\n", target);	return -1;    }    if (!(h = find_host (host)))	return -1;    else if (h->this_id == target) {	printk (KERN_ALERT "target %d is host ID\n", target);	return -1;    }     else if (target > h->max_id) {	printk (KERN_ALERT "target %d exceeds maximum of %d\n", target,	    h->max_id);	return -1;    }    hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0];    save_flags(flags);    cli();    if (hostdata->initiate_sdtr & (1 << target)) {	restore_flags(flags);	printk (KERN_ALERT "target %d already doing SDTR\n", target);	return -1;    }     hostdata->initiate_sdtr |= (1 << target);    restore_flags(flags);    return 0;}#endif/* * Function : request_disconnect (int host, int on_or_off) *  * Purpose : KGDB support function, tells us to allow or disallow  *	disconnections. * * Inputs : host - number of SCSI host; on_or_off - non-zero to allow, *	zero to disallow. * * Returns : 0 on success, *	-1 on failure. */static int request_disconnect (int host, int on_or_off) {    struct Scsi_Host *h;    struct NCR53c7x0_hostdata *hostdata;    if (!(h = find_host (host)))	return -1;    hostdata = (struct NCR53c7x0_hostdata *) h->hostdata[0];    if (on_or_off) 	hostdata->options |= OPTION_DISCONNECT;    else	hostdata->options &= ~OPTION_DISCONNECT;    return 0;}#endif/* * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host) * * Purpose : Initialize internal structures, as required on startup, or  *	after a SCSI bus reset. *  * Inputs : host - pointer to this host adapter's structure */static void NCR53c7x0_driver_init (struct Scsi_Host *host) {    struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)	host->hostdata[0];    int i, j;    u32 *ncrcurrent;    for (i = 0; i < 16; ++i) {	hostdata->request_sense[i] = 0;    	for (j = 0; j < 8; ++j) 	    hostdata->busy[i][j] = 0;	set_synchronous (host, i, /* sxfer */ 0, hostdata->saved_scntl3, 0);    }    hostdata->issue_queue = NULL;    hostdata->running_list = hostdata->finished_queue = 	hostdata->ncrcurrent = NULL;    for (i = 0, ncrcurrent = (u32 *) hostdata->schedule; 	i < host->can_queue; ++i, ncrcurrent += 2) {

⌨️ 快捷键说明

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