SCSI_DATA_OUT|SCSI_DATA_IN);
SCSI_DATA_OUT);
dvd_auth(cd, a)	struct cd_softc *cd;	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,				      CDRETRIES, 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,				      CDRETRIES, 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,				      CDRETRIES, 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,				      CDRETRIES, 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,				      CDRETRIES, 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,				      CDRETRIES, 30000, NULL,				      SCSI_DATA_OUT|SCSI_DATA_IN);		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,				      CDRETRIES, 30000, NULL,				      SCSI_DATA_OUT|SCSI_DATA_IN);		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,				      CDRETRIES, 30000, NULL, 0);		if (error)			return (error);		return (0);	default:		return (ENOTTY);	}}