📄 sym_hipd.c
字号:
"(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", sym_name(np), np->sv_scntl3, np->sv_dmode, np->sv_dcntl, np->sv_ctest3, np->sv_ctest4, np->sv_ctest5); printf ("%s: final SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", sym_name(np), np->rv_scntl3, np->rv_dmode, np->rv_dcntl, np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); } /* * Let user be aware of targets that have some disable flags set. */ sym_print_targets_flag(np, SYM_SCAN_BOOT_DISABLED, "SCAN AT BOOT"); if (sym_verbose) sym_print_targets_flag(np, SYM_SCAN_LUNS_DISABLED, "SCAN FOR LUNS"); return 0;}/* * Test the pci bus snoop logic :-( * * Has to be called with interrupts disabled. */#ifndef SYM_CONF_IOMAPPEDstatic int sym_regtest (struct sym_hcb *np){ register volatile u32 data; /* * chip registers may NOT be cached. * write 0xffffffff to a read only register area, * and try to read it back. */ data = 0xffffffff; OUTL_OFF(offsetof(struct sym_reg, nc_dstat), data); data = INL_OFF(offsetof(struct sym_reg, nc_dstat));#if 1 if (data == 0xffffffff) {#else if ((data & 0xe2f0fffd) != 0x02000080) {#endif printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n", (unsigned) data); return (0x10); }; return (0);}#endifstatic int sym_snooptest (struct sym_hcb *np){ u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat; int i, err=0;#ifndef SYM_CONF_IOMAPPED err |= sym_regtest (np); if (err) return (err);#endifrestart_test: /* * Enable Master Parity Checking as we intend * to enable it for normal operations. */ OUTB (nc_ctest4, (np->rv_ctest4 & MPEE)); /* * init */ pc = SCRIPTZ_BA (np, snooptest); host_wr = 1; sym_wr = 2; /* * Set memory and register. */ np->scratch = cpu_to_scr(host_wr); OUTL (nc_temp, sym_wr); /* * Start script (exchange values) */ OUTL (nc_dsa, np->hcb_ba); OUTL_DSP (pc); /* * Wait 'til done (with timeout) */ for (i=0; i<SYM_SNOOP_TIMEOUT; i++) if (INB(nc_istat) & (INTF|SIP|DIP)) break; if (i>=SYM_SNOOP_TIMEOUT) { printf ("CACHE TEST FAILED: timeout.\n"); return (0x20); }; /* * Check for fatal DMA errors. */ dstat = INB (nc_dstat);#if 1 /* Band aiding for broken hardwares that fail PCI parity */ if ((dstat & MDPE) && (np->rv_ctest4 & MPEE)) { printf ("%s: PCI DATA PARITY ERROR DETECTED - " "DISABLING MASTER DATA PARITY CHECKING.\n", sym_name(np)); np->rv_ctest4 &= ~MPEE; goto restart_test; }#endif if (dstat & (MDPE|BF|IID)) { printf ("CACHE TEST FAILED: DMA error (dstat=0x%02x).", dstat); return (0x80); } /* * Save termination position. */ pc = INL (nc_dsp); /* * Read memory and register. */ host_rd = scr_to_cpu(np->scratch); sym_rd = INL (nc_scratcha); sym_bk = INL (nc_temp); /* * Check termination position. */ if (pc != SCRIPTZ_BA (np, snoopend)+8) { printf ("CACHE TEST FAILED: script execution failed.\n"); printf ("start=%08lx, pc=%08lx, end=%08lx\n", (u_long) SCRIPTZ_BA (np, snooptest), (u_long) pc, (u_long) SCRIPTZ_BA (np, snoopend) +8); return (0x40); }; /* * Show results. */ if (host_wr != sym_rd) { printf ("CACHE TEST FAILED: host wrote %d, chip read %d.\n", (int) host_wr, (int) sym_rd); err |= 1; }; if (host_rd != sym_wr) { printf ("CACHE TEST FAILED: chip wrote %d, host read %d.\n", (int) sym_wr, (int) host_rd); err |= 2; }; if (sym_bk != sym_wr) { printf ("CACHE TEST FAILED: chip wrote %d, read back %d.\n", (int) sym_wr, (int) sym_bk); err |= 4; }; return (err);}/* * log message for real hard errors * * sym0 targ 0?: ERROR (ds:si) (so-si-sd) (sx/s3/s4) @ name (dsp:dbc). * reg: r0 r1 r2 r3 r4 r5 r6 ..... rf. * * exception register: * ds: dstat * si: sist * * SCSI bus lines: * so: control lines as driven by chip. * si: control lines as seen by chip. * sd: scsi data lines as seen by chip. * * wide/fastmode: * sx: sxfer (see the manual) * s3: scntl3 (see the manual) * s4: scntl4 (see the manual) * * current script command: * dsp: script address (relative to start of script). * dbc: first word of script command. * * First 24 register of the chip: * r0..rf */static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat){ u32 dsp; int script_ofs; int script_size; char *script_name; u_char *script_base; int i; dsp = INL (nc_dsp); if (dsp > np->scripta_ba && dsp <= np->scripta_ba + np->scripta_sz) { script_ofs = dsp - np->scripta_ba; script_size = np->scripta_sz; script_base = (u_char *) np->scripta0; script_name = "scripta"; } else if (np->scriptb_ba < dsp && dsp <= np->scriptb_ba + np->scriptb_sz) { script_ofs = dsp - np->scriptb_ba; script_size = np->scriptb_sz; script_base = (u_char *) np->scriptb0; script_name = "scriptb"; } else { script_ofs = dsp; script_size = 0; script_base = NULL; script_name = "mem"; } printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x/%x) @ (%s %x:%08x).\n", sym_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist, (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl), (unsigned)INB (nc_sxfer), (unsigned)INB (nc_scntl3), (np->features & FE_C10) ? (unsigned)INB (nc_scntl4) : 0, script_name, script_ofs, (unsigned)INL (nc_dbc)); if (((script_ofs & 3) == 0) && (unsigned)script_ofs < script_size) { printf ("%s: script cmd = %08x\n", sym_name(np), scr_to_cpu((int) *(u32 *)(script_base + script_ofs))); } printf ("%s: regdump:", sym_name(np)); for (i=0; i<24;i++) printf (" %02x", (unsigned)INB_OFF(i)); printf (".\n"); /* * PCI BUS error. */ if (dstat & (MDPE|BF)) sym_log_bus_error(np);}static struct sym_pci_chip sym_pci_dev_table[] = { {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, 64, FE_ERL} ,#ifdef SYM_DEBUG_GENERIC_SUPPORT {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, 1, FE_BOF} ,#else {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, 1, FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF} ,#endif {PCI_DEVICE_ID_NCR_53C815, 0xff, "815", 4, 8, 4, 64, FE_BOF|FE_ERL} , {PCI_DEVICE_ID_NCR_53C825, 0x0f, "825", 6, 8, 4, 64, FE_WIDE|FE_BOF|FE_ERL|FE_DIFF} , {PCI_DEVICE_ID_NCR_53C825, 0xff, "825a", 6, 8, 4, 2, FE_WIDE|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|FE_DIFF} , {PCI_DEVICE_ID_NCR_53C860, 0xff, "860", 4, 8, 5, 1, FE_ULTRA|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN} , {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 6, 16, 5, 2, FE_WIDE|FE_ULTRA|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_DIFF|FE_VARCLK} , {PCI_DEVICE_ID_NCR_53C875, 0xff, "875", 6, 16, 5, 2, FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_DIFF|FE_VARCLK} , {PCI_DEVICE_ID_NCR_53C875J, 0xff, "875J", 6, 16, 5, 2, FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_DIFF|FE_VARCLK} , {PCI_DEVICE_ID_NCR_53C885, 0xff, "885", 6, 16, 5, 2, FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_DIFF|FE_VARCLK} ,#ifdef SYM_DEBUG_GENERIC_SUPPORT {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, 2, FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS| FE_RAM|FE_LCKFRQ} ,#else {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, 2, FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_LCKFRQ} ,#endif {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 6, 31, 7, 4, FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ} , {PCI_DEVICE_ID_LSI_53C895A, 0xff, "895a", 6, 31, 7, 4, FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ} , {PCI_DEVICE_ID_LSI_53C875A, 0xff, "875a", 6, 31, 7, 4, FE_WIDE|FE_ULTRA|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ} , {PCI_DEVICE_ID_LSI_53C1010_33, 0x00, "1010-33", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC| FE_C10} , {PCI_DEVICE_ID_LSI_53C1010_33, 0xff, "1010-33", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC| FE_C10|FE_U3EN} , {PCI_DEVICE_ID_LSI_53C1010_66, 0xff, "1010-66", 6, 31, 7, 8, FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN| FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_66MHZ|FE_CRC| FE_C10|FE_U3EN} , {PCI_DEVICE_ID_LSI_53C1510, 0xff, "1510d", 6, 31, 7, 4, FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| FE_RAM|FE_IO256|FE_LEDC}};#define sym_pci_num_devs \ (sizeof(sym_pci_dev_table) / sizeof(sym_pci_dev_table[0]))/* * Look up the chip table. * * Return a pointer to the chip entry if found, * zero otherwise. */struct sym_pci_chip *sym_lookup_pci_chip_table (u_short device_id, u_char revision){ struct sym_pci_chip *chip; int i; for (i = 0; i < sym_pci_num_devs; i++) { chip = &sym_pci_dev_table[i]; if (device_id != chip->device_id) continue; if (revision > chip->revision_id) continue; return chip; } return NULL;}#if SYM_CONF_DMA_ADDRESSING_MODE == 2/* * Lookup the 64 bit DMA segments map. * This is only used if the direct mapping * has been unsuccessful. */int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s){ int i; if (!np->use_dac) goto weird; /* Look up existing mappings */ for (i = SYM_DMAP_SIZE-1; i > 0; i--) { if (h == np->dmap_bah[i]) return i; } /* If direct mapping is free, get it */ if (!np->dmap_bah[s]) goto new; /* Collision -> lookup free mappings */ for (s = SYM_DMAP_SIZE-1; s > 0; s--) { if (!np->dmap_bah[s]) goto new; }weird: panic("sym: ran out of 64 bit DMA segment registers"); return -1;new: np->dmap_bah[s] = h; np->dmap_dirty = 1; return s;}/* * Update IO registers scratch C..R so they will be * in sync. with queued CCB expectations. */static void sym_update_dmap_regs(struct sym_hcb *np){ int o, i; if (!np->dmap_dirty) return; o = offsetof(struct sym_reg, nc_scrx[0]); for (i = 0; i < SYM_DMAP_SIZE; i++) { OUTL_OFF(o, np->dmap_bah[i]); o += 4; } np->dmap_dirty = 0;}#endif/* Enforce all the fiddly SPI rules and the chip limitations */static void sym_check_goals(struct scsi_device *sdev){ struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; struct sym_trans *st = &np->target[sdev->id].tinfo.goal; if (!scsi_device_wide(sdev)) st->width = 0; if (!scsi_device_sync(sdev)) { st->options = 0; st->period = 0; st->offset = 0; return; } if (scsi_device_dt(sdev)) { if (scsi_device_dt_only(sdev)) st->options |= PPR_OPT_DT; if (st->offset == 0) st->options &= ~PPR_OPT_DT; } else { st->options &= ~PPR_OPT_DT; } /* Some targets fail to properly negotiate DT in SE mode */ if ((np->scsi_mode != SMODE_LVD) || !(np->features & FE_U3EN)) st->options &= ~PPR_OPT_DT; if (st->options & PPR_OPT_DT) { /* all DT transfers must be wide */ st->width = 1; if (st->offset > np->maxoffs_dt) st->offset = np->maxoffs_dt; if (st->period < np->minsync_dt) st->period = np->minsync_dt; if (st->period > np->maxsync_dt) st->period = np->maxsync_dt; } else { st->options &= ~PPR_OPT_MASK; if (st->offset > np->maxoffs) st->offset = np->maxoffs; if (st->period < np->minsync) st->period = np->minsync; if (st->period > np->maxsync) st->period = np->maxsync; }}/* * Prepare the next negotiation message if needed. * * Fill in the part of message buffer that contains the * negotiation and the nego_status field of the CCB. * Returns the size of the message in bytes. */static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, u_char *msgptr){ tcb_p tp = &np->target[cp->target]; struct scsi_device *sdev = tp->sdev; struct sym_trans *goal = &tp->tinfo.goal; struct sym_trans *curr = &tp->tinfo.curr; int msglen = 0; int nego; if (likely(sdev)) sym_check_goals(sdev); /* * Many devices implement PPR in a buggy way, so only use it if we * really want to. */ if ((goal->options & PPR_OPT_MASK) || (goal->period < 0xa)) { nego = NS_PPR; } else if (curr->width != goal->width) { nego = NS_WIDE; } else if (curr->period != goal->period || curr->offset != goal->offset) { nego = NS_SYNC; } else { nego = 0; } switch (nego) { case NS_SYNC: msgptr[msglen++] = M_EXTENDED; msgptr[msglen++] = 3; msgptr[msglen++] = M_X_SYNC_REQ; msgptr[msglen++] = goal->period; msgptr[msglen++] = goal->offset; break; case NS_WIDE: msgptr[msglen++] = M_EXTENDED; msgptr[msglen++] = 2; msgptr[msglen++] = M_X_WIDE_REQ; msgptr[msglen++] = goal->width; break; case NS_PPR: msgptr[msglen++] = M_EXTENDED; msgptr[msglen++] = 6; msgptr[msglen++] = M_X_PPR_REQ; msgptr[msglen++] = goal->period; msgptr[msglen++] = 0; msgptr[msglen++] = goal->offset; msgptr[msglen++] = goal->width; msgptr[msglen++] = goal->options & PPR_OPT_MASK; break; }; cp->nego_status = nego; if (nego) { tp->nego_cp = cp; /* Keep track a nego will be performed */ if (DEBUG_FLAGS & DEBUG_NEGO) { sym_print_nego_msg(np, cp->target, nego == NS_SYNC ? "sync msgout" : nego == NS_WIDE ? "wide msgout" :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -