📄 53c7xx.c
字号:
ncrcurrent[0] = hostdata->NOP_insn; ncrcurrent[1] = 0xdeadbeef; } ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE; ncrcurrent[1] = (u32) virt_to_bus (hostdata->script) + hostdata->E_wait_reselect; hostdata->reconnect_dsa_head = 0; hostdata->addr_reconnect_dsa_head = (u32) virt_to_bus((void *) &(hostdata->reconnect_dsa_head)); hostdata->expecting_iid = 0; hostdata->expecting_sto = 0; if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS) hostdata->initiate_sdtr = 0xffff; else hostdata->initiate_sdtr = 0; hostdata->talked_to = 0; hostdata->idle = 1;}/* * Function : static int clock_to_ccf_710 (int clock) * * Purpose : Return the clock conversion factor for a given SCSI clock. * * Inputs : clock - SCSI clock expressed in Hz. * * Returns : ccf on success, -1 on failure. */static int clock_to_ccf_710 (int clock) { if (clock <= 16666666) return -1; if (clock <= 25000000) return 2; /* Divide by 1.0 */ else if (clock <= 37500000) return 1; /* Divide by 1.5 */ else if (clock <= 50000000) return 0; /* Divide by 2.0 */ else if (clock <= 66000000) return 3; /* Divide by 3.0 */ else return -1;} /* * Function : static int NCR53c7x0_init (struct Scsi_Host *host) * * Purpose : initialize the internal structures for a given SCSI host * * Inputs : host - pointer to this host adapter's structure * * Preconditions : when this function is called, the chip_type * field of the hostdata structure MUST have been set. * * Returns : 0 on success, -1 on failure. */int NCR53c7x0_init (struct Scsi_Host *host) { NCR53c7x0_local_declare(); int i, ccf; unsigned char revision; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; /* * There are some things which we need to know about in order to provide * a semblance of support. Print 'em if they aren't what we expect, * otherwise don't add to the noise. * * -1 means we don't know what to expect. */ int val, flags; char buf[32]; int expected_id = -1; int expected_clock = -1; int uninitialized = 0;#ifdef NO_IO_SPACE int expected_mapping = OPTION_MEMORY_MAPPED;#else int expected_mapping = OPTION_IO_MAPPED;#endif for (i=0;i<7;i++) hostdata->valid_ids[i] = 1; /* Default all ID's to scan */ /* Parse commandline flags */ if (check_setup_strings("noasync",&flags,&val,buf)) { hostdata->options |= OPTION_NO_ASYNC; hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS); } if (check_setup_strings("nosync",&flags,&val,buf)) { hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS); } if (check_setup_strings("nodisconnect",&flags,&val,buf)) hostdata->options &= ~OPTION_DISCONNECT; if (check_setup_strings("validids",&flags,&val,buf)) { for (i=0;i<7;i++) hostdata->valid_ids[i] = val & (1<<i); } if ((i = check_setup_strings("next",&flags,&val,buf))) { while (i) setup_used[--i] = 1; } if (check_setup_strings("opthi",&flags,&val,buf)) hostdata->options = (long long)val << 32; if (check_setup_strings("optlo",&flags,&val,buf)) hostdata->options |= val; NCR53c7x0_local_setup(host); switch (hostdata->chip) { case 710: case 770: hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr; hostdata->init_save_regs = NULL; hostdata->dsa_fixup = NCR53c7xx_dsa_fixup; hostdata->init_fixup = NCR53c7x0_init_fixup; hostdata->soft_reset = NCR53c7x0_soft_reset; hostdata->run_tests = NCR53c7xx_run_tests; expected_clock = hostdata->scsi_clock; expected_id = 7; break; default: printk ("scsi%d : chip type of %d is not supported yet, detaching.\n", host->host_no, hostdata->chip); scsi_unregister (host); return -1; } /* Assign constants accessed by NCR */ hostdata->NCR53c7xx_zero = 0; hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT; hostdata->NCR53c7xx_msg_abort = ABORT; hostdata->NCR53c7xx_msg_nop = NOP; hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24; if (expected_mapping == -1 || (hostdata->options & (OPTION_MEMORY_MAPPED)) != (expected_mapping & OPTION_MEMORY_MAPPED)) printk ("scsi%d : using %s mapped access\n", host->host_no, (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" : "io"); hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ? DMODE_REG_00 : DMODE_REG_10; hostdata->istat = ((hostdata->chip / 100) == 8) ? ISTAT_REG_800 : ISTAT_REG_700;/* We have to assume that this may be the first access to the chip, so * we must set EA in DCNTL. */ NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM);/* Only the ISTAT register is readable when the NCR is running, so make sure it's halted. */ ncr_halt(host);/* * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc, * as does the 710 with one bit per SCSI ID. Conversely, the NCR * uses a normal, 3 bit binary representation of these values. * * Get the rest of the NCR documentation, and FIND OUT where the change * was. */#if 0 /* May not be able to do this - chip my not have been set up yet */ tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG); for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id);#else host->this_id = 7;#endif/* * Note : we should never encounter a board setup for ID0. So, * if we see ID0, assume that it was uninitialized and set it * to the industry standard 7. */ if (!host->this_id) { printk("scsi%d : initiator ID was %d, changing to 7\n", host->host_no, host->this_id); host->this_id = 7; hostdata->this_id_mask = 1 << 7; uninitialized = 1; }; if (expected_id == -1 || host->this_id != expected_id) printk("scsi%d : using initiator ID %d\n", host->host_no, host->this_id); /* * Save important registers to allow a soft reset. */ /* * CTEST7 controls cache snooping, burst mode, and support for * external differential drivers. This isn't currently used - the * default value may not be optimal anyway. * Even worse, it may never have been set up since reset. */ hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE; revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4; switch (revision) { case 1: revision = 0; break; case 2: revision = 1; break; case 4: revision = 2; break; case 8: revision = 3; break; default: revision = 255; break; } printk("scsi%d: Revision 0x%x\n",host->host_no,revision); if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS))) { printk ("scsi%d: Disabling sync working and disconnect/reselect\n", host->host_no); hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS); } /* * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor, * on 800 series chips, it allows for a totem-pole IRQ driver. * NOTE saved_dcntl currently overwritten in init function. * The value read here may be garbage anyway, MVME16x board at least * does not initialise chip if kernel arrived via tftp. */ hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG); /* * DMODE controls DMA burst length, and on 700 series chips, * 286 mode and bus width * NOTE: On MVME16x, chip may have been reset, so this could be a * power-on/reset default value. */ hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode); /* * Now that burst length and enabled/disabled status is known, * clue the user in on it. */ ccf = clock_to_ccf_710 (expected_clock); for (i = 0; i < 16; ++i) hostdata->cmd_allocated[i] = 0; if (hostdata->init_save_regs) hostdata->init_save_regs (host); if (hostdata->init_fixup) hostdata->init_fixup (host); if (!the_template) { the_template = host->hostt; first_host = host; } /* * Linux SCSI drivers have always been plagued with initialization * problems - some didn't work with the BIOS disabled since they expected * initialization from it, some didn't work when the networking code * was enabled and registers got scrambled, etc. * * To avoid problems like this, in the future, we will do a soft * reset on the SCSI chip, taking it back to a sane state. */ hostdata->soft_reset (host);#if 1 hostdata->debug_count_limit = -1;#else hostdata->debug_count_limit = 1;#endif hostdata->intrs = -1; hostdata->resets = -1; memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message, sizeof (hostdata->synchronous_want)); NCR53c7x0_driver_init (host); if (request_irq(host->irq, NCR53c7x0_intr, SA_SHIRQ, "53c7xx", host)) { printk("scsi%d : IRQ%d not free, detaching\n", host->host_no, host->irq); scsi_unregister (host); return -1; } if ((hostdata->run_tests && hostdata->run_tests(host) == -1) || (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) { /* XXX Should disable interrupts, etc. here */ scsi_unregister (host); return -1; } else { if (host->io_port) { host->n_io_port = 128; request_region (host->io_port, host->n_io_port, "ncr53c7xx"); } } if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) { printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no); hard_reset (host); } return 0;}/* * Function : static int ncr53c7xx_init(Scsi_Host_Template *tpnt, int board, * int chip, u32 base, int io_port, int irq, int dma, long long options, * int clock); * * Purpose : initializes a NCR53c7,8x0 based on base addresses, * IRQ, and DMA channel. * * Inputs : tpnt - Template for this SCSI adapter, board - board level * product, chip - 710 * * Returns : 0 on success, -1 on failure. * */int ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, u32 base, int io_port, int irq, int dma, long long options, int clock){ struct Scsi_Host *instance; struct NCR53c7x0_hostdata *hostdata; char chip_str[80]; int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0, schedule_size = 0, ok = 0; void *tmp; unsigned long page; switch (chip) { case 710: case 770: schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */; script_len = NCR53c7xx_script_len; dsa_len = NCR53c7xx_dsa_len; options |= OPTION_INTFLY; sprintf (chip_str, "NCR53c%d", chip); break; default: printk("scsi-ncr53c7xx : unsupported SCSI chip %d\n", chip); return -1; } printk("scsi-ncr53c7xx : %s at memory 0x%x, io 0x%x, irq %d", chip_str, (unsigned) base, io_port, irq); if (dma == DMA_NONE) printk("\n"); else printk(", dma %d\n", dma); if (options & OPTION_DEBUG_PROBE_ONLY) { printk ("scsi-ncr53c7xx : probe only enabled, aborting initialization\n"); return -1; } max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len + /* Size of dynamic part of command structure : */ 2 * /* Worst case : we don't know if we need DATA IN or DATA out */ ( 2 * /* Current instructions per scatter/gather segment */ tpnt->sg_tablesize + 3 /* Current startup / termination required per phase */ ) * 8 /* Each instruction is eight bytes */; /* Allocate fixed part of hostdata, dynamic part to hold appropriate SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure. We need a NCR53c7x0_cmd structure for scan_scsis() when we are not loaded as a module, and when we're loaded as a module, we can't use a non-dynamically allocated structure because modules are vmalloc()'d, which can allow structures to cross page boundaries and breaks our physical/virtual address assumptions for DMA. So, we stick it past the end of our hostdata structure. ASSUMPTION : Regardless of how many simultaneous SCSI commands we allow, the probe code only executes a _single_ instruction at a time,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -