static int chopen(dev_t dev, int flags, int fmt, struct lwp *l) { struct ch_softc *sc; struct scsipi_periph *periph; struct scsipi_adapter *adapt; int unit, error; unit = CHUNIT(dev); sc = device_lookup_private(&ch_cd, unit); if (sc == NULL) return (ENXIO); periph = sc->sc_periph; adapt = periph->periph_channel->chan_adapter; /* * Only allow one open at a time. */ if (periph->periph_flags & PERIPH_OPEN) return (EBUSY); if ((error = scsipi_adapter_addref(adapt)) != 0) return (error); /* * Make sure the unit is on-line. If a UNIT ATTENTION * occurs, we will mark that an Init-Element-Status is * needed in ch_get_params(). * * We ignore NOT READY in case e.g a magazine isn't actually * loaded into the changer or a tape isn't in the drive. */ error = scsipi_test_unit_ready(periph, XS_CTL_IGNORE_NOT_READY); if (error) goto bad; periph->periph_flags |= PERIPH_OPEN; /* * Make sure our parameters are up to date. */ if ((error = ch_get_params(sc, 0)) != 0) goto bad; return (0); bad: scsipi_adapter_delref(adapt); periph->periph_flags &= ~PERIPH_OPEN; return (error); }
static void chattach(device_t parent, device_t self, void *aux) { struct ch_softc *sc = device_private(self); struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; sc->sc_dev = self; selinit(&sc->sc_selq); /* Glue into the SCSI bus */ sc->sc_periph = periph; periph->periph_dev = sc->sc_dev; periph->periph_switch = &ch_switch; printf("\n"); /* * Find out our device's quirks. */ ch_get_quirks(sc, &sa->sa_inqbuf); /* * Some changers require a long time to settle out, to do * tape inventory, for instance. */ if (sc->sc_settledelay) { printf("%s: waiting %d seconds for changer to settle...\n", device_xname(sc->sc_dev), sc->sc_settledelay); delay(1000000 * sc->sc_settledelay); } /* * Get information about the device. Note we can't use * interrupts yet. */ if (ch_get_params(sc, XS_CTL_DISCOVERY|XS_CTL_IGNORE_MEDIA_CHANGE)) printf("%s: offline\n", device_xname(sc->sc_dev)); else { #define PLURAL(c) (c) == 1 ? "" : "s" printf("%s: %d slot%s, %d drive%s, %d picker%s, %d portal%s\n", device_xname(sc->sc_dev), sc->sc_counts[CHET_ST], PLURAL(sc->sc_counts[CHET_ST]), sc->sc_counts[CHET_DT], PLURAL(sc->sc_counts[CHET_DT]), sc->sc_counts[CHET_MT], PLURAL(sc->sc_counts[CHET_MT]), sc->sc_counts[CHET_IE], PLURAL(sc->sc_counts[CHET_IE])); #undef PLURAL #ifdef CHANGER_DEBUG printf("%s: move mask: 0x%x 0x%x 0x%x 0x%x\n", device_xname(sc->sc_dev), sc->sc_movemask[CHET_MT], sc->sc_movemask[CHET_ST], sc->sc_movemask[CHET_IE], sc->sc_movemask[CHET_DT]); printf("%s: exchange mask: 0x%x 0x%x 0x%x 0x%x\n", device_xname(sc->sc_dev), sc->sc_exchangemask[CHET_MT], sc->sc_exchangemask[CHET_ST], sc->sc_exchangemask[CHET_IE], sc->sc_exchangemask[CHET_DT]); #endif /* CHANGER_DEBUG */ } /* Default the current picker. */ sc->sc_picker = sc->sc_firsts[CHET_MT]; }
int chopen(dev_t dev, int flags, int fmt, struct proc *p) { struct ch_softc *sc; int oldcounts[4]; int i, unit, error = 0; unit = CHUNIT(dev); if ((unit >= ch_cd.cd_ndevs) || ((sc = ch_cd.cd_devs[unit]) == NULL)) return (ENXIO); /* * Only allow one open at a time. */ if (sc->sc_link->flags & SDEV_OPEN) return (EBUSY); sc->sc_link->flags |= SDEV_OPEN; /* * Absorb any unit attention errors. We must notice * "Not ready" errors as a changer will report "In the * process of getting ready" any time it must rescan * itself to determine the state of the changer. */ error = scsi_test_unit_ready(sc->sc_link, TEST_READY_RETRIES, SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_MEDIA_CHANGE); if (error) goto bad; /* * Get information about the device. Save old information * so we can decide whether to be verbose about new parameters. */ for (i = 0; i < 4; i++) { oldcounts[i] = sc->sc_counts[i]; } error = ch_get_params(sc, scsi_autoconf); if (error) goto bad; for (i = 0; i < 4; i++) { if (oldcounts[i] != sc->sc_counts[i]) { break; } } if (i < 4) { #ifdef CHANGER_DEBUG #define PLURAL(c) (c) == 1 ? "" : "s" printf("%s: %d slot%s, %d drive%s, %d picker%s, %d portal%s\n", sc->sc_dev.dv_xname, sc->sc_counts[CHET_ST], PLURAL(sc->sc_counts[CHET_ST]), sc->sc_counts[CHET_DT], PLURAL(sc->sc_counts[CHET_DT]), sc->sc_counts[CHET_MT], PLURAL(sc->sc_counts[CHET_MT]), sc->sc_counts[CHET_IE], PLURAL(sc->sc_counts[CHET_IE])); #undef PLURAL printf("%s: move mask: 0x%x 0x%x 0x%x 0x%x\n", sc->sc_dev.dv_xname, sc->sc_movemask[CHET_MT], sc->sc_movemask[CHET_ST], sc->sc_movemask[CHET_IE], sc->sc_movemask[CHET_DT]); printf("%s: exchange mask: 0x%x 0x%x 0x%x 0x%x\n", sc->sc_dev.dv_xname, sc->sc_exchangemask[CHET_MT], sc->sc_exchangemask[CHET_ST], sc->sc_exchangemask[CHET_IE], sc->sc_exchangemask[CHET_DT]); #endif /* CHANGER_DEBUG */ } /* Default the current picker. */ sc->sc_picker = sc->sc_firsts[CHET_MT]; return (0); bad: sc->sc_link->flags &= ~SDEV_OPEN; return (error); }