📄 53c7xx.c
字号:
} } 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 + -