diff options
author | groudier <groudier@FreeBSD.org> | 2000-01-01 15:24:44 +0000 |
---|---|---|
committer | groudier <groudier@FreeBSD.org> | 2000-01-01 15:24:44 +0000 |
commit | 1b3fcf60f708b5e99c9ba2dd18c14caa6346fe82 (patch) | |
tree | 634fe7f9befe7c3fbec233f5a77caa9f700de158 /sys/dev/sym | |
parent | a5e8250f8cd3d7d14638c62ec2b7337f4a4b34da (diff) | |
download | FreeBSD-src-1b3fcf60f708b5e99c9ba2dd18c14caa6346fe82.zip FreeBSD-src-1b3fcf60f708b5e99c9ba2dd18c14caa6346fe82.tar.gz |
- Add device entry for the next generation of C1010 device
(pci dev_id 0x21).
- Start the SCRIPTS processor without resetting the SCSI BUS
at initialization.
- Remove the "Host adapter CCB chain" (got useless given the
new queuing scheme).
- Display correctly the state of SCSI signals, when SCSI BUS
looks bad.
- Cosmetic changes in messages printed out at initialization.
- Notifications and messages on RESET conditions slightly
reworked.
- TEKRAM 24C16 NVRAM support fixed (also reported ok).
Diffstat (limited to 'sys/dev/sym')
-rw-r--r-- | sys/dev/sym/sym_defs.h | 1 | ||||
-rw-r--r-- | sys/dev/sym/sym_hipd.c | 160 |
2 files changed, 97 insertions, 64 deletions
diff --git a/sys/dev/sym/sym_defs.h b/sys/dev/sym/sym_defs.h index 23f94c5..ee33f6d 100644 --- a/sys/dev/sym/sym_defs.h +++ b/sys/dev/sym/sym_defs.h @@ -82,6 +82,7 @@ #define PCI_ID_SYM53C896 0xb #define PCI_ID_SYM53C895A 0x12 #define PCI_ID_LSI53C1010 0x20 +#define PCI_ID_LSI53C1010_2 0x21 #define PCI_ID_LSI53C1510D 0xa /* diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c index 7acb1b6..4591ca1 100644 --- a/sys/dev/sym/sym_hipd.c +++ b/sys/dev/sym/sym_hipd.c @@ -58,7 +58,7 @@ /* $FreeBSD$ */ -#define SYM_DRIVER_NAME "sym-1.0.0-19991205" +#define SYM_DRIVER_NAME "sym-1.1.1-20000101" #include <pci.h> #include <stddef.h> /* For offsetof */ @@ -595,6 +595,19 @@ static void sym_printl_hex (char *label, u_char *p, int n) } /* + * Return a string for SCSI BUS mode. + */ +static char *sym_scsi_bus_mode(int mode) +{ + switch(mode) { + case SMODE_HVD: return "HVD"; + case SMODE_SE: return "SE"; + case SMODE_LVD: return "LVD"; + } + return "??"; +} + +/* * Some poor sync table that refers to Tekram NVRAM layout. */ #ifdef SYM_CONF_NVRAM_SUPPORT @@ -1172,7 +1185,6 @@ struct sym_ccb { /* NO_TAG means no tag */ u_char target; u_char lun; - ccb_p link_ccb; /* Host adapter CCB chain */ ccb_p link_ccbh; /* Host adapter CCB hash chain */ SYM_QUEHEAD link_ccbq; /* Link to free/busy CCB queue */ @@ -1369,7 +1381,6 @@ struct sym_hcb { * CCB lists and queue. */ ccb_p ccbh[CCB_HASH_SIZE]; /* CCB hashed by DSA value */ - ccb_p ccbc; /* CCB chain */ SYM_QUEHEAD free_ccbq; /* Queue of available CCBs */ SYM_QUEHEAD busy_ccbq; /* Queue of busy CCBs */ @@ -1616,7 +1627,7 @@ static int sym_reset_scsi_bus (hcb_p np, int enab_int); static int sym_wakeup_done (hcb_p np); static void sym_flush_busy_queue (hcb_p np, int cam_status); static void sym_flush_comp_queue (hcb_p np, int cam_status); -static void sym_init (hcb_p np, int reset, char *msg); +static void sym_init (hcb_p np, int reason); static int sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp); static void sym_setsync (hcb_p np, ccb_p cp, u_char ofs, u_char per, @@ -4226,22 +4237,27 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) * Let user know about the settings. */ i = nvram->type; - printf("%s: %s NVRAM, ID %d, Fast-%d, %s%s\n", sym_name(np), + printf("%s: %s NVRAM, ID %d, Fast-%d, %s, %s\n", sym_name(np), i == SYM_SYMBIOS_NVRAM ? "Symbios" : (i == SYM_TEKRAM_NVRAM ? "Tekram" : "No"), np->myaddr, - np->minsync < 10 ? 80 : (np->minsync < 12 ? 40 : - (np->minsync < 25 ? 20 : 10)), - (np->rv_scntl0 & 0xa) ? "parity checking" : "NO parity", - np->scsi_mode == SMODE_HVD ? ", HVD" : ""); + (np->features & FE_ULTRA3) ? 80 : + (np->features & FE_ULTRA2) ? 40 : + (np->features & FE_ULTRA) ? 20 : 10, + sym_scsi_bus_mode(np->scsi_mode), + (np->rv_scntl0 & 0xa) ? "parity checking" : "NO parity"); /* * Tell him more on demand. */ - if (sym_verbose) + if (sym_verbose) { printf("%s: %s IRQ line driver%s\n", sym_name(np), np->rv_dcntl & IRQM ? "totem pole" : "open drain", np->ram_ba ? ", using on-chip SRAM" : ""); + if (np->features & FE_NOPM) + printf("%s: handling phase mismatch from SCRIPTS.\n", + sym_name(np)); + } /* * And still more. */ @@ -4410,13 +4426,16 @@ static void sym_put_start_queue(hcb_p np, ccb_p cp) * Soft reset the chip. * * Raising SRST when the chip is running may cause - * problems on dual function chips (see below). + * problems on dual function chips (see below). + * On the other hand, LVD devices need some delay + * to settle and report actual BUS mode in STEST4. */ static void sym_chip_reset (hcb_p np) { OUTB (nc_istat, SRST); UDELAY (10); OUTB (nc_istat, 0); + UDELAY(2000); /* For BUS MODE to settle */ } /* @@ -4468,7 +4487,6 @@ static int sym_reset_scsi_bus(hcb_p np, int enab_int) int retv = 0; sym_soft_reset(np); /* Soft reset the chip */ - UDELAY (2000); /* The 895/6 need time for the bus mode to settle */ if (enab_int) OUTW (nc_sien, RST); /* @@ -4488,11 +4506,12 @@ static int sym_reset_scsi_bus(hcb_p np, int enab_int) * We are expecting RESET to be TRUE and other signals to be * FALSE. */ - term = INB(nc_sstat0); /* rst, sdp0 */ - term = ((term & 2) << 7) + ((term & 1) << 16); - term |= ((INB(nc_sstat2) & 0x01) << 25) | /* sdp1 */ - (INW(nc_sbdl) << 9) | /* d15-0 */ - INB(nc_sbcl); /* req, ack, bsy, sel, atn, msg, cd, io */ + term = INB(nc_sstat0); + term = ((term & 2) << 7) + ((term & 1) << 17); /* rst sdp0 */ + term |= ((INB(nc_sstat2) & 0x01) << 26) | /* sdp1 */ + ((INW(nc_sbdl) & 0xff) << 9) | /* d7-0 */ + ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */ + INB(nc_sbcl); /* req ack bsy sel atn msg cd io */ if (!(np->features & FE_WIDE)) term &= 0x3ffff; @@ -4564,8 +4583,13 @@ static void sym_flush_busy_queue (hcb_p np, int cam_status) /* * Start chip. + * + * 'reason' means: + * 0: initialisation. + * 1: SCSI BUS RESET delivered or received. + * 2: SCSI BUS MODE changed. */ -static void sym_init (hcb_p np, int reset, char *msg) +static void sym_init (hcb_p np, int reason) { int i; u_long phys; @@ -4573,7 +4597,7 @@ static void sym_init (hcb_p np, int reset, char *msg) /* * Reset chip if asked, otherwise just clear fifos. */ - if (reset) + if (reason == 1) sym_soft_reset(np); else { OUTB (nc_stest3, TE|CSF); @@ -4581,11 +4605,6 @@ static void sym_init (hcb_p np, int reset, char *msg) } /* - * Message. - */ - if (msg) printf ("%s: restart (%s).\n", sym_name (np), msg); - - /* * Clear Start Queue */ phys = vtobus(np->squeue); @@ -4689,9 +4708,6 @@ static void sym_init (hcb_p np, int reset, char *msg) * set PM jump addresses. */ if (np->features & FE_NOPM) { - if (sym_verbose) - printf("%s: handling phase mismatch from SCRIPTS.\n", - sym_name(np)); OUTL (nc_pmjad1, SCRIPTH_BA (np, pm_handle)); OUTL (nc_pmjad2, SCRIPTH_BA (np, pm_handle)); } @@ -4713,9 +4729,15 @@ static void sym_init (hcb_p np, int reset, char *msg) /* * For 895/6 enable SBMC interrupt and save current SCSI bus mode. + * Try to eat the spurious SBMC interrupt that may occur when + * we reset the chip but not the SCSI BUS (at initialization). */ if (np->features & (FE_ULTRA2|FE_ULTRA3)) { OUTONW (nc_sien, SBMC); + if (reason == 0) { + MDELAY(100); + INW (nc_sist); + } np->scsi_mode = INB (nc_stest4) & SMODE; } @@ -4744,7 +4766,7 @@ static void sym_init (hcb_p np, int reset, char *msg) * and start script processor. */ if (np->ram_ba) { - if (sym_verbose) + if (sym_verbose > 1) printf ("%s: Downloading SCSI SCRIPTS.\n", sym_name(np)); if (np->ram_ws == 8192) { @@ -4769,9 +4791,10 @@ static void sym_init (hcb_p np, int reset, char *msg) OUTL (nc_dsp, phys); /* - * Notify the XPT of the event. + * Notify the XPT about the RESET condition. */ - xpt_async(AC_BUS_RESET, np->path, NULL); + if (reason != 0) + xpt_async(AC_BUS_RESET, np->path, NULL); } /* @@ -5039,6 +5062,7 @@ out: static void sym_settrans(hcb_p np, ccb_p cp, u_char dt, u_char ofs, u_char per, u_char wide, u_char div, u_char fak) { + SYM_QUEHEAD *qp; union ccb *ccb; tcb_p tp; u_char target = INB (nc_sdid) & 0x0f; @@ -5138,11 +5162,10 @@ static void sym_settrans(hcb_p np, ccb_p cp, u_char dt, u_char ofs, } /* - * patch ALL ccbs of this target. + * patch ALL busy ccbs of this target. */ - for (cp = np->ccbc; cp; cp = cp->link_ccb) { - if (cp->host_status == HS_IDLE) - continue; + FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) { + cp = sym_que_entry(qp, struct sym_ccb, link_ccbq); if (cp->target != target) continue; cp->phys.select.sel_scntl3 = tp->wval; @@ -5407,7 +5430,9 @@ static void sym_intr1 (hcb_p np) * ponding status and restart the SCRIPTS. */ if (sist & RST) { - sym_init (np, 1, sym_verbose ? "scsi reset" : NULL); + xpt_print_path(np->path); + printf("SCSI BUS reset detected.\n"); + sym_init (np, 1); return; }; @@ -5576,17 +5601,18 @@ static void sym_int_sbmc (hcb_p np) { u_char scsi_mode = INB (nc_stest4) & SMODE; - printf("%s: SCSI bus mode change from %x to %x.\n", - sym_name(np), np->scsi_mode, scsi_mode); - - np->scsi_mode = scsi_mode; - + /* + * Notify user. + */ + xpt_print_path(np->path); + printf("SCSI BUS mode change from %s to %s.\n", + sym_scsi_bus_mode(np->scsi_mode), sym_scsi_bus_mode(scsi_mode)); /* - * Should suspend command processing for 1 second and + * Should suspend command processing for a few seconds and * reinitialize all except the chip. */ - sym_init (np, 0, sym_verbose ? "scsi mode change" : NULL); + sym_init (np, 2); } /* @@ -7759,7 +7785,7 @@ static ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order) * Get a tag for this SCSI IO and set up * the CCB bus address for reselection, * and count it for this LUN. - * Toggle reselect patch to tagged. + * Toggle reselect path to tagged. */ if (lp->busy_itlq < SYM_CONF_MAX_TASK) { tag = lp->cb_tags[lp->ia_tag]; @@ -7952,10 +7978,8 @@ static ccb_p sym_alloc_ccb(hcb_p np) cp->phys.smsg_ext.addr = cpu_to_scr(vtobus(&np->msgin[2])); /* - * Chain into wakeup list and into free ccb queue. + * Chain into free ccb queue. */ - cp->link_ccb = np->ccbc; - np->ccbc = cp; sym_insque_head(&cp->link_ccbq, &np->free_ccbq); return cp; @@ -8714,13 +8738,18 @@ static void sym_timeout(void *arg) static int sym_abort_scsiio(hcb_p np, union ccb *ccb, int timed_out) { ccb_p cp; + SYM_QUEHEAD *qp; /* * Look up our CCB control block. */ - for (cp=np->ccbc; cp; cp=cp->link_ccb) { - if (cp->host_status != HS_IDLE && cp->cam_ccb == ccb) + cp = 0; + FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) { + ccb_p cp2 = sym_que_entry(qp, struct sym_ccb, link_ccbq); + if (cp2->cam_ccb == ccb) { + cp = cp2; break; + } } if (!cp) return -1; @@ -9167,8 +9196,6 @@ end_scatter: /* * Activate this job. - * If we have awaiting commands for that unit, 2 max - * at a time is enough to flush the CCB wait queue. */ sym_put_start_queue(np, cp); @@ -9401,11 +9428,11 @@ static void sym_action2(struct cam_sim *sim, union ccb *ccb) case XPT_RESET_BUS: { sym_reset_scsi_bus(np, 0); - sym_init (np, 1, NULL); if (sym_verbose) { xpt_print_path(np->path); - printf("SCSI bus reset delivered.\n"); + printf("SCSI BUS reset delivered.\n"); } + sym_init (np, 1); sym_xpt_done2(np, ccb, CAM_REQ_CMP); break; } @@ -9569,6 +9596,11 @@ static struct sym_pci_chip sym_pci_dev_table[] = { , {PCI_ID_LSI53C1010, 0xff, "1010", 6, 62, 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_IO256|FE_NOPM|FE_LEDC|FE_CRC| + FE_C10|FE_U3EN} + , + {PCI_ID_LSI53C1010_2, 0xff, "1010", 6, 62, 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_IO256|FE_NOPM|FE_LEDC|FE_PCI66|FE_CRC| FE_C10|FE_U3EN} , @@ -9638,7 +9670,7 @@ sym_pci_probe(device_t dev) chip = sym_find_pci_chip(dev); if (chip) { device_set_desc(dev, chip->name); - return (chip->lp_probe_bit & SYM_SETUP_LP_PROBE_MAP) ? -2000 : 0; + return (chip->lp_probe_bit & SYM_SETUP_LP_PROBE_MAP)? -2000 : 0; } return ENXIO; } @@ -10104,14 +10136,6 @@ sym_pci_attach2(pcici_t pci_tag, int unit) } /* - * Reset the chip. - * We should use sym_soft_reset(), but we donnot want to do - * so, since we may not be safe if ABRT interrupt occurs due - * to the BIOS or previous O/S having enable this interrupt. - */ - sym_chip_reset (np); - - /* * Now check the cache handling of the pci chipset. */ if (sym_snooptest (np)) { @@ -10152,6 +10176,7 @@ attach_failed: */ static void sym_pci_free(hcb_p np) { + SYM_QUEHEAD *qp; ccb_p cp; tcb_p tp; lcb_p lp; @@ -10198,8 +10223,8 @@ static void sym_pci_free(hcb_p np) if (np->dqueue) sym_mfree(np->dqueue, sizeof(u32)*(MAX_QUEUE*2), "DQUEUE"); - while ((cp = np->ccbc) != NULL) { - np->ccbc = cp->link_ccb; + while ((qp = sym_remque_head(&np->free_ccbq)) != 0) { + cp = sym_que_entry(qp, struct sym_ccb, link_ccbq); sym_mfree(cp, sizeof(*cp), "CCB"); } @@ -10317,6 +10342,13 @@ int sym_cam_attach(hcb_p np) xpt_action((union ccb *)&csa); } #endif + /* + * Start the chip now, without resetting the BUS, since + * it seems that this must stay under control of CAM. + * With LVD/SE capable chips and BUS in SE mode, we may + * get a spurious SMBC interrupt. + */ + sym_init (np, 0); splx(s); return 1; @@ -10746,7 +10778,7 @@ static int sym_read_S24C16_nvram (hcb_p np, int offset, u_char *data, int len) /* write random address LSB */ S24C16_write_byte(np, &ack_data, - (offset & 0x7f) << 1, &gpreg, &gpcntl); + offset & 0xff, &gpreg, &gpcntl); if (ack_data & 0x01) goto out; |