diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2001-06-25 19:31:52 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2001-06-25 19:31:52 +0000 |
commit | 0fb7cb023c7bfa718f99434614457de95f8c42a3 (patch) | |
tree | 3c47187905d4b7219117676956b5e78695f2dc58 /sys/dev | |
parent | 0adcef35c587a06d6141cdf97085590422facafd (diff) |
Fix excessive resets and device probes by storing IDENTIFY results in the
drvp structure
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ata/atareg.h | 7 | ||||
-rw-r--r-- | sys/dev/ata/atavar.h | 72 | ||||
-rw-r--r-- | sys/dev/atapiscsi/atapiscsi.c | 199 | ||||
-rw-r--r-- | sys/dev/ic/wdc.c | 57 | ||||
-rw-r--r-- | sys/dev/ic/wdcvar.h | 3 |
5 files changed, 109 insertions, 229 deletions
diff --git a/sys/dev/ata/atareg.h b/sys/dev/ata/atareg.h index 75977de25d6..16f7b82c152 100644 --- a/sys/dev/ata/atareg.h +++ b/sys/dev/ata/atareg.h @@ -1,6 +1,9 @@ -/* $OpenBSD: atareg.h,v 1.3 2001/03/23 02:16:41 deraadt Exp $ */ +/* $OpenBSD: atareg.h,v 1.4 2001/06/25 19:31:47 csapuntz Exp $ */ /* $NetBSD: atareg.h,v 1.5 1999/01/18 20:06:24 bouyer Exp $ */ +#ifndef __DEV_ATA_ATAREG_H__ +#define __DEV_ATA_ATAREG_H__ + /* * Drive parameter structure for ATA/ATAPI. * Bit fields: WDC_* : common to ATA/ATAPI @@ -219,3 +222,5 @@ struct ataparams { u_int8_t atap_signature; /* 255: Signature */ #endif }; + +#endif diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h index 3cade4ed03a..0221e4a9add 100644 --- a/sys/dev/ata/atavar.h +++ b/sys/dev/ata/atavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: atavar.h,v 1.7 2001/05/01 00:07:25 csapuntz Exp $ */ +/* $OpenBSD: atavar.h,v 1.8 2001/06/25 19:31:48 csapuntz Exp $ */ /* $NetBSD: atavar.h,v 1.13 1999/03/10 13:11:43 bouyer Exp $ */ /* @@ -34,15 +34,14 @@ * */ -/* Hight-level functions and structures used by both ATA and ATAPI devices */ - -struct ataparams; +/* High-level functions and structures used by both ATA and ATAPI devices */ +#include <dev/ata/atareg.h> /* Datas common to drives and controller drivers */ struct ata_drive_datas { - u_int8_t drive; /* drive number */ - int8_t ata_vers; /* ATA version supported */ - u_int16_t drive_flags; /* bitmask for drives present/absent and cap */ + u_int8_t drive; /* drive number */ + int8_t ata_vers; /* ATA version supported */ + u_int16_t drive_flags; /* bitmask for drives present/absent and cap */ #define DRIVE_ATA 0x0001 #define DRIVE_ATAPI 0x0002 #define DRIVE_OLD 0x0004 @@ -56,40 +55,42 @@ struct ata_drive_datas { #define DRIVE_DSCBA 0x0200 /* DSC in buffer availability mode */ #define DRIVE_DSCWAIT 0x0400 /* In wait for DSC to be asserted */ #define DRIVE_DEVICE_RESET 0x0800 /* Drive supports DEVICE RESET command */ - /* - * Current setting of drive's PIO, DMA and UDMA modes. - * Is initialised by the disks drivers at attach time, and may be - * changed later by the controller's code if needed - */ - u_int8_t PIO_mode; /* Current setting of drive's PIO mode */ - u_int8_t DMA_mode; /* Current setting of drive's DMA mode */ - u_int8_t UDMA_mode; /* Current setting of drive's UDMA mode */ - /* Supported modes for this drive */ - u_int8_t PIO_cap; /* supported drive's PIO mode */ - u_int8_t DMA_cap; /* supported drive's DMA mode */ - u_int8_t UDMA_cap; /* supported drive's UDMA mode */ - /* - * Drive state. This is drive-type (ATA or ATAPI) dependant - * This is reset to 0 after a channel reset. - */ - u_int8_t state; + /* + * Current setting of drive's PIO, DMA and UDMA modes. + * Is initialised by the disks drivers at attach time, and may be + * changed later by the controller's code if needed + */ + u_int8_t PIO_mode; /* Current setting of drive's PIO mode */ + u_int8_t DMA_mode; /* Current setting of drive's DMA mode */ + u_int8_t UDMA_mode; /* Current setting of drive's UDMA mode */ + /* Supported modes for this drive */ + u_int8_t PIO_cap; /* supported drive's PIO mode */ + u_int8_t DMA_cap; /* supported drive's DMA mode */ + u_int8_t UDMA_cap; /* supported drive's UDMA mode */ + /* + * Drive state. This is drive-type (ATA or ATAPI) dependant + * This is reset to 0 after a channel reset. + */ + u_int8_t state; #define ACAP_LEN 0x01 /* 16 byte commands */ #define ACAP_DSC 0x02 /* use DSC signalling */ - /* 0x20-0x40 reserved for ATAPI_CFG_DRQ_MASK */ - u_int8_t atapi_cap; - - /* Keeps track of the number of resets that have occured in a row - without a succesful command completion. */ - u_int8_t n_resets; - u_int8_t n_dmaerrs; - u_int32_t n_xfers; + /* 0x20-0x40 reserved for ATAPI_CFG_DRQ_MASK */ + u_int8_t atapi_cap; + + /* Keeps track of the number of resets that have occured in a row + without a succesful command completion. */ + u_int8_t n_resets; + u_int8_t n_dmaerrs; + u_int32_t n_xfers; #define NERRS_MAX 4 #define NXFER 1000 - char drive_name[31]; - int cf_flags; - void *chnl_softc; /* channel softc */ + char drive_name[31]; + int cf_flags; + void *chnl_softc; /* channel softc */ + + struct ataparams id; }; /* ATA/ATAPI common attachement datas */ @@ -173,7 +174,6 @@ int wdc_ata_addref __P((struct ata_drive_datas *)); void wdc_ata_delref __P((struct ata_drive_datas *)); void wdc_ata_kill_pending __P((struct ata_drive_datas *)); -struct ataparams; int ata_get_params __P((struct ata_drive_datas*, u_int8_t, struct ataparams *)); int ata_set_mode __P((struct ata_drive_datas*, u_int8_t, u_int8_t)); diff --git a/sys/dev/atapiscsi/atapiscsi.c b/sys/dev/atapiscsi/atapiscsi.c index b440ad1338e..921b1d12ba8 100644 --- a/sys/dev/atapiscsi/atapiscsi.c +++ b/sys/dev/atapiscsi/atapiscsi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atapiscsi.c,v 1.42 2001/05/27 18:45:29 csapuntz Exp $ */ +/* $OpenBSD: atapiscsi.c,v 1.43 2001/06/25 19:31:51 csapuntz Exp $ */ /* * This code is derived from code with the copyright below. @@ -146,9 +146,6 @@ struct atapiscsi_xfer; int atapiscsi_match __P((struct device *, void *, void *)); void atapiscsi_attach __P((struct device *, struct device *, void *)); - -int wdc_atapi_get_params __P((struct channel_softc *, u_int8_t, - struct ataparams *)); int atapi_to_scsi_sense __P((struct scsi_xfer *, u_int8_t)); struct atapiscsi_softc { @@ -158,6 +155,7 @@ struct atapiscsi_softc { enum atapi_state { as_none, as_cmdout, as_data, as_completed }; enum atapi_state protocol_phase; + int drive; int retries; int diagnostics_printed; #define ATAPI_DIAG_UNEXP_CMD 0x01 @@ -227,10 +225,9 @@ atapiscsi_attach(parent, self, aux) { struct atapiscsi_softc *as = (struct atapiscsi_softc *)self; struct ata_atapi_attach *aa_link = aux; - struct channel_softc *chp = aa_link->aa_bus_private; - struct ataparams ids; - struct ataparams *id = &ids; - int drive; + struct ata_drive_datas *drvp = aa_link->aa_drv_data; + struct channel_softc *chp = drvp->chnl_softc; + struct ataparams *id = &drvp->id; printf("\n"); @@ -240,6 +237,7 @@ atapiscsi_attach(parent, self, aux) #endif as->chp = chp; + as->drive = drvp->drive; as->sc_adapterlink.adapter_softc = as; as->sc_adapterlink.adapter_target = 7; as->sc_adapterlink.adapter_buswidth = 2; @@ -249,43 +247,33 @@ atapiscsi_attach(parent, self, aux) as->sc_adapterlink.flags = SDEV_ATAPI; as->sc_adapterlink.quirks = SDEV_NOLUNS; - for (drive = 0; drive < 2 ; drive++ ) { - struct ata_drive_datas *drvp = &chp->ch_drive[drive]; - - if ((drvp->drive_flags & DRIVE_ATAPI) && - (wdc_atapi_get_params(chp, drive, id) == COMPLETE)) { - /* Temporarily, the device will be called - atapiscsi. */ - strncpy(drvp->drive_name, as->sc_dev.dv_xname, - sizeof(drvp->drive_name) - 1); - drvp->cf_flags = as->sc_dev.dv_cfdata->cf_flags; - - wdc_probe_caps(drvp, id); - - WDCDEBUG_PRINT( - ("general config %04x capabilities %04x ", - id->atap_config, id->atap_capabilities1), - DEBUG_PROBE); + strncpy(drvp->drive_name, as->sc_dev.dv_xname, + sizeof(drvp->drive_name) - 1); + drvp->cf_flags = as->sc_dev.dv_cfdata->cf_flags; - drvp->drive_flags |= DRIVE_DEVICE_RESET; - - /* Tape drives do funny DSC stuff */ - if (ATAPI_CFG_TYPE(id->atap_config) == - ATAPI_CFG_TYPE_SEQUENTIAL) - drvp->atapi_cap |= ACAP_DSC; - - if ((id->atap_config & ATAPI_CFG_CMD_MASK) == - ATAPI_CFG_CMD_16) - drvp->atapi_cap |= ACAP_LEN; - - drvp->atapi_cap |= - (id->atap_config & ATAPI_CFG_DRQ_MASK); - - WDCDEBUG_PRINT(("driver caps %04x\n", drvp->atapi_cap), - DEBUG_PROBE); - } else - drvp->drive_flags &= ~DRIVE_ATAPI; - } + wdc_probe_caps(drvp, id); + + WDCDEBUG_PRINT( + ("general config %04x capabilities %04x ", + id->atap_config, id->atap_capabilities1), + DEBUG_PROBE); + + drvp->drive_flags |= DRIVE_DEVICE_RESET; + + /* Tape drives do funny DSC stuff */ + if (ATAPI_CFG_TYPE(id->atap_config) == + ATAPI_CFG_TYPE_SEQUENTIAL) + drvp->atapi_cap |= ACAP_DSC; + + if ((id->atap_config & ATAPI_CFG_CMD_MASK) == + ATAPI_CFG_CMD_16) + drvp->atapi_cap |= ACAP_LEN; + + drvp->atapi_cap |= + (id->atap_config & ATAPI_CFG_DRQ_MASK); + + WDCDEBUG_PRINT(("driver caps %04x\n", drvp->atapi_cap), + DEBUG_PROBE); as->sc_adapterlink.scsibus = (u_int8_t)-1; @@ -295,142 +283,54 @@ atapiscsi_attach(parent, self, aux) if (as->sc_adapterlink.scsibus != (u_int8_t)-1) { int bus = as->sc_adapterlink.scsibus; + extern struct cfdriver scsibus_cd; - for (drive = 0; drive < 2; drive++) { - extern struct cfdriver scsibus_cd; - - struct scsibus_softc *scsi = scsibus_cd.cd_devs[bus]; - struct scsi_link *link = scsi->sc_link[drive][0]; - struct ata_drive_datas *drvp = &chp->ch_drive[drive]; - - if (!link) continue; - + struct scsibus_softc *scsi = scsibus_cd.cd_devs[bus]; + struct scsi_link *link = scsi->sc_link[drvp->drive][0]; + struct ata_drive_datas *drvp = &chp->ch_drive[drvp->drive]; + + if (!link) { strncpy(drvp->drive_name, - ((struct device *)(link->device_softc))->dv_xname, - sizeof(drvp->drive_name) - 1); + ((struct device *)(link->device_softc))->dv_xname, + sizeof(drvp->drive_name) - 1); wdc_print_caps(drvp); } } - + #ifdef WDCDEBUG if (chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE) wdcdebug_atapi_mask &= ~DEBUG_PROBE; #endif } -void -wdc_atapibus_attach(chp) - struct channel_softc *chp; -{ - struct wdc_softc *wdc = chp->wdc; - int channel = chp->channel; - struct ata_atapi_attach aa_link; - - /* - * Fill in the adapter. - */ - bzero(&aa_link, sizeof(struct ata_atapi_attach)); - aa_link.aa_type = T_ATAPI; - aa_link.aa_channel = channel; - aa_link.aa_openings = 1; - aa_link.aa_drv_data = NULL; - aa_link.aa_bus_private = chp; - - (void)config_found(&wdc->sc_dev, (void *)&aa_link, atapi_print); -} - -int -wdc_atapi_get_params(chp, drive, id) - struct channel_softc *chp; - u_int8_t drive; - struct ataparams *id; -{ - struct ata_drive_datas *drvp = &chp->ch_drive[drive]; - struct wdc_command wdc_c; - int retries = 3; - - /* if no ATAPI device detected at wdc attach time, skip */ - /* - * XXX this will break scsireprobe if this is of any interest for - * ATAPI devices one day. - */ - if ((drvp->drive_flags & DRIVE_ATAPI) == 0) { - WDCDEBUG_PRINT(("wdc_atapi_get_params: drive %d not present\n", - drive), DEBUG_PROBE); - return (-1); - } - bzero(&wdc_c, sizeof(struct wdc_command)); - wdc_c.r_command = ATAPI_SOFT_RESET; - wdc_c.r_st_bmask = 0; - wdc_c.r_st_pmask = 0; - wdc_c.flags = at_poll; - wdc_c.timeout = ATAPI_RESET_WAIT; - if (wdc_exec_command(drvp, &wdc_c) != WDC_COMPLETE) { - printf("wdc_atapi_get_params: ATAPI_SOFT_RESET failed for" - " drive %s:%d:%d: driver failed\n", - chp->wdc->sc_dev.dv_xname, chp->channel, drive); - panic("wdc_atapi_get_params"); - } - if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { - WDCDEBUG_PRINT(("wdc_atapi_get_params: ATAPI_SOFT_RESET " - "failed for drive %s:%d:%d: error 0x%x\n", - chp->wdc->sc_dev.dv_xname, chp->channel, drive, - wdc_c.r_error), DEBUG_PROBE); - return (-1); - } - drvp->state = 0; - - CHP_READ_REG(chp, wdr_status); - - /* Some ATAPI devices need a bit more time after software reset. */ - delay(5000); - - retry: - if (ata_get_params(drvp, at_poll, id) != 0) { - WDCDEBUG_PRINT(("wdc_atapi_get_params: ATAPI_IDENTIFY_DEVICE " - "failed for drive %s:%d:%d\n", - chp->wdc->sc_dev.dv_xname, chp->channel, drive), - DEBUG_PROBE); - - if (retries--) { - delay(100000); - goto retry; - } - - return (-1); - } - - return (COMPLETE); -} int wdc_atapi_send_cmd(sc_xfer) struct scsi_xfer *sc_xfer; { struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc; - int drive = sc_xfer->sc_link->target; - struct channel_softc *chp = as->chp; - struct ata_drive_datas *drvp = &chp->ch_drive[drive]; + struct channel_softc *chp = as->chp; + struct ata_drive_datas *drvp = &chp->ch_drive[as->drive]; struct wdc_xfer *xfer; - int flags = sc_xfer->flags; int s, ret; WDCDEBUG_PRINT(("wdc_atapi_send_cmd %s:%d:%d\n", chp->wdc->sc_dev.dv_xname, chp->channel, drive), DEBUG_XFERS); - if (drive > 1 || !(drvp->drive_flags & DRIVE_ATAPI)) { + if (sc_xfer->sc_link->target != 0) { sc_xfer->error = XS_DRIVER_STUFFUP; return (COMPLETE); } - xfer = wdc_get_xfer(flags & SCSI_NOSLEEP ? WDC_NOSLEEP : WDC_CANSLEEP); + xfer = wdc_get_xfer(sc_xfer->flags & SCSI_NOSLEEP + ? WDC_NOSLEEP : WDC_CANSLEEP); if (xfer == NULL) { return (TRY_AGAIN_LATER); } if (sc_xfer->flags & SCSI_POLL) xfer->c_flags |= C_POLL; - xfer->drive = drive; + xfer->drive = as->drive; xfer->c_flags |= C_ATAPI; xfer->cmd = sc_xfer; xfer->databuf = sc_xfer->data; @@ -522,11 +422,10 @@ wdc_atapi_ioctl (sc_link, cmd, addr, flag) int flag; { struct atapiscsi_softc *as = sc_link->adapter_softc; - int drive = sc_link->target; struct channel_softc *chp = as->chp; - struct ata_drive_datas *drvp = &chp->ch_drive[drive]; + struct ata_drive_datas *drvp = &chp->ch_drive[as->drive]; - if (drive > 1) + if (sc_link->target != 0) return ENOTTY; return (wdc_ioctl(drvp, cmd, addr, flag)); diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c index 7e5f84877e5..9566ae63d1a 100644 --- a/sys/dev/ic/wdc.c +++ b/sys/dev/ic/wdc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wdc.c,v 1.35 2001/06/24 20:59:40 fgsch Exp $ */ +/* $OpenBSD: wdc.c,v 1.36 2001/06/25 19:31:49 csapuntz Exp $ */ /* $NetBSD: wdc.c,v 1.68 1999/06/23 19:00:17 bouyer Exp $ */ @@ -611,7 +611,6 @@ wdcattach(chp) int error; #endif struct ata_atapi_attach aa_link; - struct ataparams params; static int inited = 0; #ifdef WDCDEBUG int savedmask = wdcdebug_mask; @@ -665,15 +664,17 @@ wdcattach(chp) timeout_set(&chp->ch_timo, wdctimeout, chp); for (i = 0; i < 2; i++) { - chp->ch_drive[i].chnl_softc = chp; - chp->ch_drive[i].drive = i; + struct ata_drive_datas *drvp = &chp->ch_drive[i]; + + drvp->chnl_softc = chp; + drvp->drive = i; /* If controller can't do 16bit flag the drives as 32bit */ if ((chp->wdc->cap & (WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32)) == WDC_CAPABILITY_DATA32) - chp->ch_drive[i].drive_flags |= DRIVE_CAP32; + drvp->drive_flags |= DRIVE_CAP32; - if ((chp->ch_drive[i].drive_flags & DRIVE) == 0) + if ((drvp->drive_flags & DRIVE) == 0) continue; if (i == 1 && ((chp->ch_drive[0].drive_flags & DRIVE) == 0)) @@ -682,20 +683,20 @@ wdcattach(chp) * Issue an IDENTIFY command in order to distinct ATA from OLD. * This also kill ATAPI ghost. */ - if (ata_get_params(&chp->ch_drive[i], at_poll, ¶ms) == + if (ata_get_params(&chp->ch_drive[i], at_poll, &drvp->id) == CMD_OK) { /* If IDENTIFY succeded, this is not an OLD ctrl */ - chp->ch_drive[i].drive_flags &= ~DRIVE_OLD; + drvp->drive_flags &= ~DRIVE_OLD; } else { - chp->ch_drive[i].drive_flags &= + drvp->drive_flags &= ~(DRIVE_ATA | DRIVE_ATAPI); WDCDEBUG_PRINT(("%s:%d:%d: IDENTIFY failed\n", chp->wdc->sc_dev.dv_xname, chp->channel, i), DEBUG_PROBE); - if ((chp->ch_drive[i].drive_flags & DRIVE_OLD) && + if ((drvp->drive_flags & DRIVE_OLD) && !wdc_preata_drive(chp, i)) - chp->ch_drive[i].drive_flags &= ~DRIVE_OLD; + drvp->drive_flags &= ~DRIVE_OLD; } } ctrl_flags = chp->wdc->sc_dev.dv_cfdata->cf_flags; @@ -710,37 +711,15 @@ wdcattach(chp) (chp->ch_drive[1].drive_flags & DRIVE) == 0) goto exit; - /* - * Attach an ATAPI bus, if needed. - */ - if ((chp->ch_drive[0].drive_flags & DRIVE_ATAPI) || - (chp->ch_drive[1].drive_flags & DRIVE_ATAPI)) { -#if NATAPISCSI > 0 - wdc_atapibus_attach(chp); -#else - /* - * Fills in a fake aa_link and call config_found, so that - * the config machinery will print - * "atapibus at xxx not configured" - */ - bzero(&aa_link, sizeof(struct ata_atapi_attach)); - aa_link.aa_type = T_ATAPI; - aa_link.aa_channel = chp->channel; - aa_link.aa_openings = 1; - aa_link.aa_drv_data = 0; - aa_link.aa_bus_private = NULL; - (void)config_found(&chp->wdc->sc_dev, (void *)&aa_link, - atapi_print); -#endif - } - for (i = 0; i < 2; i++) { - if ((chp->ch_drive[i].drive_flags & - (DRIVE_ATA | DRIVE_OLD)) == 0) { + if ((chp->ch_drive[i].drive_flags & DRIVE) == 0) { continue; } bzero(&aa_link, sizeof(struct ata_atapi_attach)); - aa_link.aa_type = T_ATA; + if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI) + aa_link.aa_type = T_ATAPI; + else + aa_link.aa_type = T_ATA; aa_link.aa_channel = chp->channel; aa_link.aa_openings = 1; aa_link.aa_drv_data = &chp->ch_drive[i]; @@ -754,8 +733,6 @@ wdcattach(chp) for (i = 0; i < 2; i++) { if (chp->ch_drive[i].drive_name[0] == 0) chp->ch_drive[i].drive_flags = 0; - else - chp->ch_drive[i].state = 0; } #ifndef __OpenBSD__ diff --git a/sys/dev/ic/wdcvar.h b/sys/dev/ic/wdcvar.h index 8bbce67eead..25cc4140ff4 100644 --- a/sys/dev/ic/wdcvar.h +++ b/sys/dev/ic/wdcvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wdcvar.h,v 1.18 2001/04/30 21:17:41 csapuntz Exp $ */ +/* $OpenBSD: wdcvar.h,v 1.19 2001/06/25 19:31:50 csapuntz Exp $ */ /* $NetBSD: wdcvar.h,v 1.17 1999/04/11 20:50:29 bouyer Exp $ */ /*- @@ -279,7 +279,6 @@ void wdc_delref __P((struct channel_softc *)); /* ATA/ATAPI specs says a device can take 31s to reset */ #define WDC_RESET_WAIT 31000 -void wdc_atapibus_attach __P((struct channel_softc *)); int atapi_print __P((void *, const char *)); void wdc_disable_intr __P((struct channel_softc *)); |