int safte_bio_blink(struct safte_softc *sc, struct bioc_blink *blink) { struct safte_writebuf_cmd cmd; struct safte_slotop *op; int slot; int flags; int wantblink; switch (blink->bb_status) { case BIOC_SBBLINK: wantblink = 1; break; case BIOC_SBUNBLINK: wantblink = 0; break; default: return (EINVAL); } rw_enter_read(&sc->sc_lock); for (slot = 0; slot < sc->sc_nslots; slot++) { if (sc->sc_slots[slot] == blink->bb_target) break; } rw_exit_read(&sc->sc_lock); if (slot >= sc->sc_nslots) return (ENODEV); op = malloc(sizeof(struct safte_slotop), M_TEMP, 0); memset(op, 0, sizeof(struct safte_slotop)); op->opcode = SAFTE_WRITE_SLOTOP; op->slot = slot; op->flags |= wantblink ? SAFTE_SLOTOP_IDENTIFY : 0; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = WRITE_BUFFER; cmd.flags |= SAFTE_WR_MODE; cmd.length = htobe16(sizeof(struct safte_slotop)); flags = SCSI_DATA_OUT; #ifndef SCSIDEBUG flags |= SCSI_SILENT; #endif if (cold) flags |= SCSI_AUTOCONF; if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd, sizeof(cmd), (u_char *)op, sizeof(struct safte_slotop), 2, 30000, NULL, flags) != 0) { free(op, M_TEMP); return (EIO); } free(op, M_TEMP); return (0); }
/* * Get scsi driver to send a "start up" command */ int cd_pause(struct cd_softc *cd, int go) { struct scsi_pause scsi_cmd; bzero(&scsi_cmd, sizeof(scsi_cmd)); scsi_cmd.opcode = PAUSE; scsi_cmd.resume = go; return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd), 0, 0, SCSI_RETRIES, 2000, NULL, 0); }
/* * Get scsi driver to send a "start playing" command */ int cd_play(struct cd_softc *cd, int blkno, int nblks) { struct scsi_play scsi_cmd; bzero(&scsi_cmd, sizeof(scsi_cmd)); scsi_cmd.opcode = PLAY; _lto4b(blkno, scsi_cmd.blk_addr); _lto2b(nblks, scsi_cmd.xfer_len); return (scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd), 0, 0, SCSI_RETRIES, 200000, NULL, 0)); }
int cd_load_unload(struct cd_softc *cd, int options, int slot) { struct scsi_load_unload cmd; bzero(&cmd, sizeof(cmd)); cmd.opcode = LOAD_UNLOAD; cmd.options = options; /* ioctl uses ATAPI values */ cmd.slot = slot; return (scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&cmd, sizeof(cmd), 0, 0, SCSI_RETRIES, 200000, NULL, 0)); }
int safte_match(struct device *parent, void *match, void *aux) { struct scsi_attach_args *sa = aux; struct scsi_inquiry_data *inq = sa->sa_inqbuf; struct scsi_inquiry_data inqbuf; struct scsi_inquiry cmd; struct safte_inq *si = (struct safte_inq *)&inqbuf.extra; int length, flags; if (inq == NULL) return (0); /* match on dell enclosures */ if ((inq->device & SID_TYPE) == T_PROCESSOR && SCSISPC(inq->version) == 3) return (2); if ((inq->device & SID_TYPE) != T_PROCESSOR || SCSISPC(inq->version) != 2 || (inq->response_format & SID_ANSII) != 2) return (0); length = inq->additional_length + SAFTE_EXTRA_OFFSET; if (length < SAFTE_INQ_LEN) return (0); if (length > sizeof(inqbuf)) length = sizeof(inqbuf); memset(&cmd, 0, sizeof(cmd)); cmd.opcode = INQUIRY; _lto2b(length, cmd.length); memset(&inqbuf, 0, sizeof(inqbuf)); memset(&inqbuf.extra, ' ', sizeof(inqbuf.extra)); flags = SCSI_DATA_IN; if (cold) flags |= SCSI_AUTOCONF; if (scsi_scsi_cmd(sa->sa_sc_link, (struct scsi_generic *)&cmd, sizeof(cmd), (u_char *)&inqbuf, length, 2, 10000, NULL, flags) != 0) return (0); if (memcmp(si->ident, SAFTE_IDENT, sizeof(si->ident)) == 0) return (2); return (0); }
/* * Read subchannel */ int cd_read_subchannel(struct cd_softc *cd, int mode, int format, int track, struct cd_sub_channel_info *data, int len) { struct scsi_read_subchannel scsi_cmd; bzero(&scsi_cmd, sizeof(scsi_cmd)); scsi_cmd.opcode = READ_SUBCHANNEL; if (mode == CD_MSF_FORMAT) scsi_cmd.byte2 |= CD_MSF; scsi_cmd.byte3 = SRS_SUBQ; scsi_cmd.subchan_format = format; scsi_cmd.track = track; _lto2b(len, scsi_cmd.data_len); return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, sizeof(struct scsi_read_subchannel), (u_char *)data, len, SCSI_RETRIES, 5000, NULL, SCSI_DATA_IN|SCSI_SILENT); }
/* * Get scsi driver to send a "play msf" command */ int cd_play_msf(struct cd_softc *cd, int startm, int starts, int startf, int endm, int ends, int endf) { struct scsi_play_msf scsi_cmd; bzero(&scsi_cmd, sizeof(scsi_cmd)); scsi_cmd.opcode = PLAY_MSF; scsi_cmd.start_m = startm; scsi_cmd.start_s = starts; scsi_cmd.start_f = startf; scsi_cmd.end_m = endm; scsi_cmd.end_s = ends; scsi_cmd.end_f = endf; return (scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd), 0, 0, SCSI_RETRIES, 20000, NULL, 0)); }
/* * Read table of contents */ int cd_read_toc(struct cd_softc *cd, int mode, int start, void *data, int len, int control) { struct scsi_read_toc scsi_cmd; bzero(&scsi_cmd, sizeof(scsi_cmd)); bzero(data, len); scsi_cmd.opcode = READ_TOC; if (mode == CD_MSF_FORMAT) scsi_cmd.byte2 |= CD_MSF; scsi_cmd.from_track = start; _lto2b(len, scsi_cmd.data_len); scsi_cmd.control = control; return scsi_scsi_cmd(cd->sc_link, (struct scsi_generic *)&scsi_cmd, sizeof(struct scsi_read_toc), (u_char *)data, len, SCSI_RETRIES, 5000, NULL, SCSI_DATA_IN | SCSI_IGNORE_ILLEGAL_REQUEST); }
void safte_read_encstat(void *arg) { struct safte_softc *sc = (struct safte_softc *)arg; struct safte_readbuf_cmd cmd; int flags, i; struct safte_sensor *s; u_int16_t oot; rw_enter_write(&sc->sc_lock); memset(&cmd, 0, sizeof(cmd)); cmd.opcode = READ_BUFFER; cmd.flags |= SAFTE_RD_MODE; cmd.bufferid = SAFTE_RD_ENCSTAT; cmd.length = htobe16(sc->sc_encbuflen); flags = SCSI_DATA_IN; #ifndef SCSIDEBUG flags |= SCSI_SILENT; #endif if (cold) flags |= SCSI_AUTOCONF; if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd, sizeof(cmd), sc->sc_encbuf, sc->sc_encbuflen, 2, 30000, NULL, flags) != 0) { rw_exit_write(&sc->sc_lock); return; } for (i = 0; i < sc->sc_nsensors; i++) { s = &sc->sc_sensors[i]; s->se_sensor.flags &= ~SENSOR_FUNKNOWN; DPRINTF(("%s: %d type: %d field: 0x%02x\n", DEVNAME(sc), i, s->se_type, *s->se_field)); switch (s->se_type) { case SAFTE_T_FAN: switch (*s->se_field) { case SAFTE_FAN_OP: s->se_sensor.value = 1; s->se_sensor.status = SENSOR_S_OK; break; case SAFTE_FAN_MF: s->se_sensor.value = 0; s->se_sensor.status = SENSOR_S_CRIT; break; case SAFTE_FAN_NOTINST: case SAFTE_FAN_UNKNOWN: default: s->se_sensor.value = 0; s->se_sensor.status = SENSOR_S_UNKNOWN; s->se_sensor.flags |= SENSOR_FUNKNOWN; break; } break; case SAFTE_T_PWRSUP: switch (*s->se_field) { case SAFTE_PWR_OP_ON: s->se_sensor.value = 1; s->se_sensor.status = SENSOR_S_OK; break; case SAFTE_PWR_OP_OFF: s->se_sensor.value = 0; s->se_sensor.status = SENSOR_S_OK; break; case SAFTE_PWR_MF_ON: s->se_sensor.value = 1; s->se_sensor.status = SENSOR_S_CRIT; break; case SAFTE_PWR_MF_OFF: s->se_sensor.value = 0; s->se_sensor.status = SENSOR_S_CRIT; break; case SAFTE_PWR_NOTINST: case SAFTE_PWR_PRESENT: case SAFTE_PWR_UNKNOWN: s->se_sensor.value = 0; s->se_sensor.status = SENSOR_S_UNKNOWN; s->se_sensor.flags |= SENSOR_FUNKNOWN; break; } break; case SAFTE_T_DOORLOCK: switch (*s->se_field) { case SAFTE_DOOR_LOCKED: s->se_sensor.value = 1; s->se_sensor.status = SENSOR_S_OK; break; case SAFTE_DOOR_UNLOCKED: s->se_sensor.value = 0; s->se_sensor.status = SENSOR_S_CRIT; break; case SAFTE_DOOR_UNKNOWN: s->se_sensor.value = 0; s->se_sensor.status = SENSOR_S_CRIT; s->se_sensor.flags |= SENSOR_FUNKNOWN; break; } break; case SAFTE_T_ALARM: switch (*s->se_field) { case SAFTE_SPKR_OFF: s->se_sensor.value = 0; s->se_sensor.status = SENSOR_S_OK; break; case SAFTE_SPKR_ON: s->se_sensor.value = 1; s->se_sensor.status = SENSOR_S_CRIT; break; } break; case SAFTE_T_TEMP: s->se_sensor.value = safte_temp2uK(*s->se_field, sc->sc_celsius); break; } } oot = betoh16(*sc->sc_temperrs); for (i = 0; i < sc->sc_ntemps; i++) sc->sc_temps[i].se_sensor.status = (oot & (1 << i)) ? SENSOR_S_CRIT : SENSOR_S_OK; rw_exit_write(&sc->sc_lock); }
int safte_read_config(struct safte_softc *sc) { struct safte_readbuf_cmd cmd; struct safte_config config; struct safte_sensor *s; int flags, i, j; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = READ_BUFFER; cmd.flags |= SAFTE_RD_MODE; cmd.bufferid = SAFTE_RD_CONFIG; cmd.length = htobe16(sizeof(config)); flags = SCSI_DATA_IN; #ifndef SCSIDEBUG flags |= SCSI_SILENT; #endif if (cold) flags |= SCSI_AUTOCONF; if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd, sizeof(cmd), (u_char *)&config, sizeof(config), 2, 30000, NULL, flags) != 0) return (1); DPRINTF(("%s: nfans: %d npwrsup: %d nslots: %d doorlock: %d ntemps: %d" " alarm: %d celsius: %d ntherm: %d\n", DEVNAME(sc), config.nfans, config.npwrsup, config.nslots, config.doorlock, config.ntemps, config.alarm, SAFTE_CFG_CELSIUS(config.therm), SAFTE_CFG_NTHERM(config.therm))); sc->sc_encbuflen = config.nfans * sizeof(u_int8_t) + /* fan status */ config.npwrsup * sizeof(u_int8_t) + /* power supply status */ config.nslots * sizeof(u_int8_t) + /* device scsi id (lun) */ sizeof(u_int8_t) + /* door lock status */ sizeof(u_int8_t) + /* speaker status */ config.ntemps * sizeof(u_int8_t) + /* temp sensors */ sizeof(u_int16_t); /* temp out of range sensors */ sc->sc_encbuf = malloc(sc->sc_encbuflen, M_DEVBUF, M_NOWAIT); if (sc->sc_encbuf == NULL) return (1); sc->sc_nsensors = config.nfans + config.npwrsup + config.ntemps + (config.doorlock ? 1 : 0) + (config.alarm ? 1 : 0); sc->sc_sensors = malloc(sc->sc_nsensors * sizeof(struct safte_sensor), M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_sensors == NULL) { free(sc->sc_encbuf, M_DEVBUF); sc->sc_encbuf = NULL; sc->sc_nsensors = 0; return (1); } strlcpy(sc->sc_sensordev.xname, DEVNAME(sc), sizeof(sc->sc_sensordev.xname)); s = sc->sc_sensors; for (i = 0; i < config.nfans; i++) { s->se_type = SAFTE_T_FAN; s->se_field = (u_int8_t *)(sc->sc_encbuf + i); s->se_sensor.type = SENSOR_INDICATOR; snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc), "Fan%d", i); s++; } j = config.nfans; for (i = 0; i < config.npwrsup; i++) { s->se_type = SAFTE_T_PWRSUP; s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i); s->se_sensor.type = SENSOR_INDICATOR; snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc), "PSU%d", i); s++; } j += config.npwrsup; #if NBIO > 0 sc->sc_nslots = config.nslots; sc->sc_slots = (u_int8_t *)(sc->sc_encbuf + j); #endif j += config.nslots; if (config.doorlock) { s->se_type = SAFTE_T_DOORLOCK; s->se_field = (u_int8_t *)(sc->sc_encbuf + j); s->se_sensor.type = SENSOR_INDICATOR; strlcpy(s->se_sensor.desc, "doorlock", sizeof(s->se_sensor.desc)); s++; } j++; if (config.alarm) { s->se_type = SAFTE_T_ALARM; s->se_field = (u_int8_t *)(sc->sc_encbuf + j); s->se_sensor.type = SENSOR_INDICATOR; strlcpy(s->se_sensor.desc, "alarm", sizeof(s->se_sensor.desc)); s++; } j++; /* * stash the temp info so we can get out of range status. limit the * number so the out of temp checks cant go into memory it doesnt own */ sc->sc_ntemps = (config.ntemps > 15) ? 15 : config.ntemps; sc->sc_temps = s; sc->sc_celsius = SAFTE_CFG_CELSIUS(config.therm); for (i = 0; i < config.ntemps; i++) { s->se_type = SAFTE_T_TEMP; s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i); s->se_sensor.type = SENSOR_TEMP; s++; } j += config.ntemps; sc->sc_temperrs = (u_int16_t *)(sc->sc_encbuf + j); return (0); }
/* * cdstart looks to see if there is a buf waiting for the device * and that the device is not already busy. If both are true, * It deques the buf and creates a scsi command to perform the * transfer in the buf. The transfer request will call scsi_done * on completion, which will in turn call this routine again * so that the next queued transfer is performed. * The bufs are queued by the strategy routine (cdstrategy) * * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. * * must be called at the correct (highish) spl level * cdstart() is called at splbio from cdstrategy, cdrestart and scsi_done */ void cdstart(void *v) { struct cd_softc *cd = v; struct scsi_link *sc_link = cd->sc_link; struct buf *bp = 0; struct buf *dp; struct scsi_rw_big cmd_big; struct scsi_rw cmd_small; struct scsi_generic *cmdp; int blkno, nblks, cmdlen, error; struct partition *p; splassert(IPL_BIO); SC_DEBUG(sc_link, SDEV_DB2, ("cdstart\n")); /* * Check if the device has room for another command */ while (sc_link->openings > 0) { /* * there is excess capacity, but a special waits * It'll need the adapter as soon as we clear out of the * way and let it run (user level wait). */ if (sc_link->flags & SDEV_WAITING) { sc_link->flags &= ~SDEV_WAITING; wakeup((caddr_t)sc_link); return; } /* * See if there is a buf with work for us to do.. */ dp = &cd->buf_queue; if ((bp = dp->b_actf) == NULL) /* yes, an assign */ return; dp->b_actf = bp->b_actf; /* * If the device has become invalid, abort all the * reads and writes until all files have been closed and * re-opened */ if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { bp->b_error = EIO; bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; biodone(bp); continue; } /* * We have a buf, now we should make a command * * First, translate the block to absolute and put it in terms * of the logical blocksize of the device. */ blkno = bp->b_blkno / (cd->sc_dk.dk_label->d_secsize / DEV_BSIZE); p = &cd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]; blkno += DL_GETPOFFSET(p); nblks = howmany(bp->b_bcount, cd->sc_dk.dk_label->d_secsize); /* * Fill out the scsi command. If the transfer will * fit in a "small" cdb, use it. */ if (!(sc_link->flags & SDEV_ATAPI) && !(sc_link->quirks & SDEV_ONLYBIG) && ((blkno & 0x1fffff) == blkno) && ((nblks & 0xff) == nblks)) { /* * We can fit in a small cdb. */ bzero(&cmd_small, sizeof(cmd_small)); cmd_small.opcode = (bp->b_flags & B_READ) ? READ_COMMAND : WRITE_COMMAND; _lto3b(blkno, cmd_small.addr); cmd_small.length = nblks & 0xff; cmdlen = sizeof(cmd_small); cmdp = (struct scsi_generic *)&cmd_small; } else { /* * Need a large cdb. */ bzero(&cmd_big, sizeof(cmd_big)); cmd_big.opcode = (bp->b_flags & B_READ) ? READ_BIG : WRITE_BIG; _lto4b(blkno, cmd_big.addr); _lto2b(nblks, cmd_big.length); cmdlen = sizeof(cmd_big); cmdp = (struct scsi_generic *)&cmd_big; } /* Instrumentation. */ disk_busy(&cd->sc_dk); /* * Call the routine that chats with the adapter. * Note: we cannot sleep as we may be an interrupt */ error = scsi_scsi_cmd(sc_link, cmdp, cmdlen, (u_char *) bp->b_data, bp->b_bcount, SCSI_RETRIES, 30000, bp, SCSI_NOSLEEP | ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT)); switch (error) { case 0: timeout_del(&cd->sc_timeout); break; case EAGAIN: /* * The device can't start another i/o. Try again later. */ dp->b_actf = bp; disk_unbusy(&cd->sc_dk, 0, 0); timeout_add(&cd->sc_timeout, 1); return; default: disk_unbusy(&cd->sc_dk, 0, 0); printf("%s: not queued, error %d\n", cd->sc_dev.dv_xname, error); break; } } }
int dvd_auth(struct cd_softc *cd, union dvd_authinfo *a) { struct scsi_generic cmd; u_int8_t buf[20]; int error; bzero(cmd.bytes, sizeof(cmd.bytes)); bzero(buf, sizeof(buf)); switch (a->type) { case DVD_LU_SEND_AGID: cmd.opcode = GPCMD_REPORT_KEY; cmd.bytes[8] = 8; cmd.bytes[9] = 0 | (0 << 6); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8, SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN); if (error) return (error); a->lsa.agid = buf[7] >> 6; return (0); case DVD_LU_SEND_CHALLENGE: cmd.opcode = GPCMD_REPORT_KEY; cmd.bytes[8] = 16; cmd.bytes[9] = 1 | (a->lsc.agid << 6); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16, SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN); if (error) return (error); dvd_copy_challenge(a->lsc.chal, &buf[4]); return (0); case DVD_LU_SEND_KEY1: cmd.opcode = GPCMD_REPORT_KEY; cmd.bytes[8] = 12; cmd.bytes[9] = 2 | (a->lsk.agid << 6); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12, SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN); if (error) return (error); dvd_copy_key(a->lsk.key, &buf[4]); return (0); case DVD_LU_SEND_TITLE_KEY: cmd.opcode = GPCMD_REPORT_KEY; _lto4b(a->lstk.lba, &cmd.bytes[1]); cmd.bytes[8] = 12; cmd.bytes[9] = 4 | (a->lstk.agid << 6); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12, SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN); if (error) return (error); a->lstk.cpm = (buf[4] >> 7) & 1; a->lstk.cp_sec = (buf[4] >> 6) & 1; a->lstk.cgms = (buf[4] >> 4) & 3; dvd_copy_key(a->lstk.title_key, &buf[5]); return (0); case DVD_LU_SEND_ASF: cmd.opcode = GPCMD_REPORT_KEY; cmd.bytes[8] = 8; cmd.bytes[9] = 5 | (a->lsasf.agid << 6); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8, SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN); if (error) return (error); a->lsasf.asf = buf[7] & 1; return (0); case DVD_HOST_SEND_CHALLENGE: cmd.opcode = GPCMD_SEND_KEY; cmd.bytes[8] = 16; cmd.bytes[9] = 1 | (a->hsc.agid << 6); buf[1] = 14; dvd_copy_challenge(&buf[4], a->hsc.chal); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16, SCSI_RETRIES, 30000, NULL, SCSI_DATA_OUT); if (error) return (error); a->type = DVD_LU_SEND_KEY1; return (0); case DVD_HOST_SEND_KEY2: cmd.opcode = GPCMD_SEND_KEY; cmd.bytes[8] = 12; cmd.bytes[9] = 3 | (a->hsk.agid << 6); buf[1] = 10; dvd_copy_key(&buf[4], a->hsk.key); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 12, SCSI_RETRIES, 30000, NULL, SCSI_DATA_OUT); if (error) { a->type = DVD_AUTH_FAILURE; return (error); } a->type = DVD_AUTH_ESTABLISHED; return (0); case DVD_INVALIDATE_AGID: cmd.opcode = GPCMD_REPORT_KEY; cmd.bytes[9] = 0x3f | (a->lsa.agid << 6); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 16, SCSI_RETRIES, 30000, NULL, 0); if (error) return (error); return (0); case DVD_LU_SEND_RPC_STATE: cmd.opcode = GPCMD_REPORT_KEY; cmd.bytes[8] = 8; cmd.bytes[9] = 8 | (0 << 6); error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8, SCSI_RETRIES, 30000, NULL, SCSI_DATA_IN); if (error) return (error); a->lrpcs.type = (buf[4] >> 6) & 3; a->lrpcs.vra = (buf[4] >> 3) & 7; a->lrpcs.ucca = (buf[4]) & 7; a->lrpcs.region_mask = buf[5]; a->lrpcs.rpc_scheme = buf[6]; return (0); case DVD_HOST_SEND_RPC_STATE: cmd.opcode = GPCMD_SEND_KEY; cmd.bytes[8] = 8; cmd.bytes[9] = 6 | (0 << 6); buf[1] = 6; buf[4] = a->hrpcs.pdrc; error = scsi_scsi_cmd(cd->sc_link, &cmd, sizeof(cmd), buf, 8, SCSI_RETRIES, 30000, NULL, SCSI_DATA_OUT); if (error) return (error); return (0); default: return (ENOTTY); } }
/* * Get scsi driver to send a "RESET" command */ int cd_reset(struct cd_softc *cd) { return scsi_scsi_cmd(cd->sc_link, 0, 0, 0, 0, SCSI_RETRIES, 2000, NULL, SCSI_RESET); }