int cd_setchan(struct cd_softc *cd, int p0, int p1, int p2, int p3, int flags) { union scsi_mode_sense_buf *data; struct cd_audio_page *audio = NULL; int error, big; data = malloc(sizeof(*data), M_TEMP, M_NOWAIT); if (data == NULL) return (ENOMEM); error = scsi_do_mode_sense(cd->sc_link, AUDIO_PAGE, data, (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big); if (error == 0 && audio == NULL) error = EIO; if (error == 0) { audio->port[LEFT_PORT].channels = p0; audio->port[RIGHT_PORT].channels = p1; audio->port[2].channels = p2; audio->port[3].channels = p3; if (big) error = scsi_mode_select_big(cd->sc_link, SMS_PF, &data->hdr_big, flags, 20000); else error = scsi_mode_select(cd->sc_link, SMS_PF, &data->hdr, flags, 20000); } free(data, M_TEMP); return (error); }
int cd_setvol(struct cd_softc *cd, const struct ioc_vol *arg, int flags) { union scsi_mode_sense_buf *data; struct cd_audio_page *audio = NULL; u_int8_t mask_volume[4]; int error, big; data = malloc(sizeof(*data), M_TEMP, M_NOWAIT); if (data == NULL) return (ENOMEM); error = scsi_do_mode_sense(cd->sc_link, AUDIO_PAGE | SMS_PAGE_CTRL_CHANGEABLE, data, (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, NULL); if (error == 0 && audio == NULL) error = EIO; if (error != 0) { free(data, M_TEMP); return (error); } mask_volume[0] = audio->port[0].volume; mask_volume[1] = audio->port[1].volume; mask_volume[2] = audio->port[2].volume; mask_volume[3] = audio->port[3].volume; error = scsi_do_mode_sense(cd->sc_link, AUDIO_PAGE, data, (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big); if (error == 0 && audio == NULL) error = EIO; if (error != 0) { free(data, M_TEMP); return (error); } audio->port[0].volume = arg->vol[0] & mask_volume[0]; audio->port[1].volume = arg->vol[1] & mask_volume[1]; audio->port[2].volume = arg->vol[2] & mask_volume[2]; audio->port[3].volume = arg->vol[3] & mask_volume[3]; if (big) error = scsi_mode_select_big(cd->sc_link, SMS_PF, &data->hdr_big, flags, 20000); else error = scsi_mode_select(cd->sc_link, SMS_PF, &data->hdr, flags, 20000); free(data, M_TEMP); return (error); }
int cd_set_pa_immed(struct cd_softc *cd, int flags) { union scsi_mode_sense_buf *data; struct cd_audio_page *audio = NULL; int error, oflags, big; if (cd->sc_link->flags & SDEV_ATAPI) /* XXX Noop? */ return (0); data = malloc(sizeof(*data), M_TEMP, M_NOWAIT); if (data == NULL) return (ENOMEM); error = scsi_do_mode_sense(cd->sc_link, AUDIO_PAGE, data, (void **)&audio, NULL, NULL, NULL, sizeof(*audio), flags, &big); if (error == 0 && audio == NULL) error = EIO; if (error == 0) { oflags = audio->flags; audio->flags &= ~CD_PA_SOTC; audio->flags |= CD_PA_IMMED; if (audio->flags != oflags) { if (big) error = scsi_mode_select_big(cd->sc_link, SMS_PF, &data->hdr_big, flags, 20000); else error = scsi_mode_select(cd->sc_link, SMS_PF, &data->hdr, flags, 20000); } } free(data, M_TEMP); return (error); }
int sd_ioctl_cache(struct sd_softc *sc, long cmd, struct dk_cache *dkc) { union scsi_mode_sense_buf *buf; struct page_caching_mode *mode = NULL; u_int wrcache, rdcache; int big; int rv; if (ISSET(sc->sc_link->flags, SDEV_UMASS)) return (EOPNOTSUPP); /* see if the adapter has special handling */ rv = scsi_do_ioctl(sc->sc_link, cmd, (caddr_t)dkc, 0); if (rv != ENOTTY) return (rv); buf = dma_alloc(sizeof(*buf), PR_WAITOK); if (buf == NULL) return (ENOMEM); rv = scsi_do_mode_sense(sc->sc_link, PAGE_CACHING_MODE, buf, (void **)&mode, NULL, NULL, NULL, sizeof(*mode) - 4, scsi_autoconf | SCSI_SILENT, &big); if (rv != 0) goto done; if ((mode == NULL) || (!DISK_PGCODE(mode, PAGE_CACHING_MODE))) { rv = EIO; goto done; } wrcache = (ISSET(mode->flags, PG_CACHE_FL_WCE) ? 1 : 0); rdcache = (ISSET(mode->flags, PG_CACHE_FL_RCD) ? 0 : 1); switch (cmd) { case DIOCGCACHE: dkc->wrcache = wrcache; dkc->rdcache = rdcache; break; case DIOCSCACHE: if (dkc->wrcache == wrcache && dkc->rdcache == rdcache) break; if (dkc->wrcache) SET(mode->flags, PG_CACHE_FL_WCE); else CLR(mode->flags, PG_CACHE_FL_WCE); if (dkc->rdcache) CLR(mode->flags, PG_CACHE_FL_RCD); else SET(mode->flags, PG_CACHE_FL_RCD); if (big) { rv = scsi_mode_select_big(sc->sc_link, SMS_PF, &buf->hdr_big, scsi_autoconf | SCSI_SILENT, 20000); } else { rv = scsi_mode_select(sc->sc_link, SMS_PF, &buf->hdr, scsi_autoconf | SCSI_SILENT, 20000); } break; } done: dma_free(buf, sizeof(*buf)); return (rv); }