void wdattach(struct device *parent, struct device *self, void *aux) { struct wd_softc *wd = (void *)self; struct ata_atapi_attach *aa_link= aux; struct wdc_command wdc_c; int i, blank; char buf[41], c, *p, *q; WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); wd->openings = aa_link->aa_openings; wd->drvp = aa_link->aa_drv_data; strlcpy(wd->drvp->drive_name, wd->sc_dev.dv_xname, sizeof(wd->drvp->drive_name)); wd->drvp->cf_flags = wd->sc_dev.dv_cfdata->cf_flags; if ((NERRS_MAX - 2) > 0) wd->drvp->n_dmaerrs = NERRS_MAX - 2; else wd->drvp->n_dmaerrs = 0; /* read our drive info */ if (wd_get_params(wd, at_poll, &wd->sc_params) != 0) { printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname); return; } for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0; i < sizeof(wd->sc_params.atap_model); i++) { c = *p++; if (c == '\0') break; if (c != ' ') { if (blank) { *q++ = ' '; blank = 0; } *q++ = c; } else blank = 1; } *q++ = '\0'; printf(": <%s>\n", buf); wdc_probe_caps(wd->drvp, &wd->sc_params); wdc_print_caps(wd->drvp); if ((wd->sc_params.atap_multi & 0xff) > 1) { wd->sc_multi = wd->sc_params.atap_multi & 0xff; } else { wd->sc_multi = 1; } printf("%s: %d-sector PIO,", wd->sc_dev.dv_xname, wd->sc_multi); /* use 48-bit LBA if enabled */ /* XXX: shall we use it if drive capacity < 137Gb? */ if ((wd->sc_params.atap_cmd2_en & ATAPI_CMD2_48AD) != 0) wd->sc_flags |= WDF_LBA48; /* Prior to ATA-4, LBA was optional. */ if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) wd->sc_flags |= WDF_LBA; #if 0 /* ATA-4 requires LBA. */ if (wd->sc_params.atap_ataversion != 0xffff && wd->sc_params.atap_ataversion >= WDC_VER_ATA4) wd->sc_flags |= WDF_LBA; #endif if ((wd->sc_flags & WDF_LBA48) != 0) { wd->sc_capacity = (((u_int64_t)wd->sc_params.atap_max_lba[3] << 48) | ((u_int64_t)wd->sc_params.atap_max_lba[2] << 32) | ((u_int64_t)wd->sc_params.atap_max_lba[1] << 16) | (u_int64_t)wd->sc_params.atap_max_lba[0]); printf(" LBA48, %lluMB, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_capacity); } else if ((wd->sc_flags & WDF_LBA) != 0) { wd->sc_capacity = (wd->sc_params.atap_capacity[1] << 16) | wd->sc_params.atap_capacity[0]; printf(" LBA, %lluMB, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_capacity); } else { wd->sc_capacity = wd->sc_params.atap_cylinders * wd->sc_params.atap_heads * wd->sc_params.atap_sectors; printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n", wd->sc_capacity / (1048576 / DEV_BSIZE), wd->sc_params.atap_cylinders, wd->sc_params.atap_heads, wd->sc_params.atap_sectors, wd->sc_capacity); } WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n", self->dv_xname, wd->sc_params.atap_dmatiming_mimi, wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE); /* use read look ahead if supported */ if (wd->sc_params.atap_cmd_set1 & WDC_CMD1_AHEAD) { bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = SET_FEATURES; wdc_c.r_precomp = WDSF_READAHEAD_EN; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: enable look ahead command didn't " "complete\n", wd->sc_dev.dv_xname); } } /* use write cache if supported */ if (wd->sc_params.atap_cmd_set1 & WDC_CMD1_CACHE) { bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = SET_FEATURES; wdc_c.r_precomp = WDSF_EN_WR_CACHE; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: enable write cache command didn't " "complete\n", wd->sc_dev.dv_xname); } } /* * FREEZE LOCK the drive so malicous users can't lock it on us. * As there is no harm in issuing this to drives that don't * support the security feature set we just send it, and don't * bother checking if the drive sends a command abort to tell us it * doesn't support it. */ bzero(&wdc_c, sizeof(struct wdc_command)); wdc_c.r_command = WDCC_SEC_FREEZE_LOCK; wdc_c.timeout = 1000; wdc_c.flags = at_poll; if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { printf("%s: freeze lock command didn't complete\n", wd->sc_dev.dv_xname); } /* * Initialize disk structures. */ wd->sc_dk.dk_name = wd->sc_dev.dv_xname; bufq_init(&wd->sc_bufq, BUFQ_DEFAULT); timeout_set(&wd->sc_restart_timeout, wdrestart, wd); /* Attach disk. */ disk_attach(&wd->sc_dev, &wd->sc_dk); wd->sc_wdc_bio.lp = wd->sc_dk.dk_label; }
void atapiscsi_attach(struct device *parent, struct device *self, void *aux) { struct atapiscsi_softc *as = (struct atapiscsi_softc *)self; struct ata_atapi_attach *aa_link = aux; struct scsibus_attach_args saa; struct ata_drive_datas *drvp = aa_link->aa_drv_data; struct channel_softc *chp = drvp->chnl_softc; struct ataparams *id = &drvp->id; struct device *child; extern struct scsi_iopool wdc_xfer_iopool; printf("\n"); /* Initialize shared data. */ scsi_init(); #ifdef WDCDEBUG if (chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE) wdcdebug_atapi_mask |= DEBUG_PROBE; #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; as->sc_adapterlink.adapter = &atapiscsi_switch; as->sc_adapterlink.luns = 1; as->sc_adapterlink.openings = 1; as->sc_adapterlink.flags = SDEV_ATAPI; as->sc_adapterlink.pool = &wdc_xfer_iopool; strlcpy(drvp->drive_name, as->sc_dev.dv_xname, sizeof(drvp->drive_name)); 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); #if (NERRS_MAX > 2) drvp->n_dmaerrs = NERRS_MAX - 2; #else drvp->n_dmaerrs = 0; #endif 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); bzero(&saa, sizeof(saa)); saa.saa_sc_link = &as->sc_adapterlink; child = config_found((struct device *)as, &saa, scsiprint); if (child != NULL) { struct scsibus_softc *scsi = (struct scsibus_softc *)child; struct scsi_link *link = scsi_get_link(scsi, 0, 0); if (link) { strlcpy(drvp->drive_name, ((struct device *)(link->device_softc))->dv_xname, sizeof(drvp->drive_name)); 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 }