BraseroScsiResult brasero_scsi_command_issue_sync (gpointer command, gpointer buffer, int size, BraseroScsiErrCode *error) { scsireq_t req; BraseroScsiResult res; BraseroScsiCmd *cmd; cmd = command; brasero_sg_command_setup (&req, cmd, buffer, size); res = ioctl (cmd->handle->fd, SCIOCCOMMAND, &req); if (res == -1) { BRASERO_SCSI_SET_ERRCODE (error, BRASERO_SCSI_ERRNO); return BRASERO_SCSI_FAILURE; } if (req.retsts == SCCMD_OK) return BRASERO_SCSI_OK; if (req.retsts == SCCMD_SENSE) return brasero_sense_data_process (req.sense, error); return BRASERO_SCSI_FAILURE; }
BraseroScsiResult brasero_scsi_command_issue_sync (gpointer command, gpointer buffer, int size, BraseroScsiErrCode *error) { uchar sense_buffer [BRASERO_SENSE_DATA_SIZE]; struct sg_io_hdr transport; BraseroScsiResult res; BraseroScsiCmd *cmd; g_return_val_if_fail (command != NULL, BRASERO_SCSI_FAILURE); cmd = command; brasero_sg_command_setup (&transport, sense_buffer, cmd, buffer, size); /* NOTE on SG_IO: only for TEST UNIT READY, REQUEST/MODE SENSE, INQUIRY, * READ CAPACITY, READ BUFFER, READ and LOG SENSE are allowed with it */ res = ioctl (cmd->handle->fd, SG_IO, &transport); if (res) { BRASERO_SCSI_SET_ERRCODE (error, BRASERO_SCSI_ERRNO); return BRASERO_SCSI_FAILURE; } if ((transport.info & SG_INFO_OK_MASK) == SG_INFO_OK) return BRASERO_SCSI_OK; if ((transport.masked_status & CHECK_CONDITION) && transport.sb_len_wr) return brasero_sense_data_process (sense_buffer, error); return BRASERO_SCSI_FAILURE; }
static BraseroScsiResult brasero_get_performance (BraseroGetPerformanceCDB *cdb, gint sizeof_descriptors, BraseroScsiGetPerfData **data, int *data_size, BraseroScsiErrCode *error) { BraseroScsiGetPerfData *buffer; BraseroScsiGetPerfHdr hdr; BraseroScsiResult res; int request_size; int buffer_size; if (!data || !data_size) { BRASERO_SCSI_SET_ERRCODE (error, BRASERO_SCSI_BAD_ARGUMENT); return BRASERO_SCSI_FAILURE; } /* Issue the command once to get the size ... */ memset (&hdr, 0, sizeof (hdr)); BRASERO_SET_16 (cdb->max_desc, 0); res = brasero_scsi_command_issue_sync (cdb, &hdr, sizeof (hdr), error); if (res != BRASERO_SCSI_OK) return res; /* ... get the request size ... */ request_size = BRASERO_GET_32 (hdr.len) + G_STRUCT_OFFSET (BraseroScsiGetPerfHdr, len) + sizeof (hdr.len); /* ... get the answer itself. */ buffer = brasero_get_performance_get_buffer (cdb, sizeof_descriptors, &hdr, error); if (!buffer) return BRASERO_SCSI_FAILURE; /* make sure the response has the requested size */ buffer_size = BRASERO_GET_32 (buffer->hdr.len) + G_STRUCT_OFFSET (BraseroScsiGetPerfHdr, len) + sizeof (buffer->hdr.len); if (request_size < buffer_size) { BraseroScsiGetPerfData *new_buffer; /* Strangely some drives returns a buffer size that is bigger * than the one they returned on the first time. So redo whole * operation again but this time with the new size we got */ BRASERO_MEDIA_LOG ("Sizes mismatch asked %i / received %i\n" "Re-issuing the command with received size", request_size, buffer_size); /* Try to get a new buffer of the new size */ memcpy (&hdr, &buffer->hdr, sizeof (hdr)); new_buffer = brasero_get_performance_get_buffer (cdb, sizeof_descriptors, &hdr, error); if (new_buffer) { g_free (buffer); buffer = new_buffer; request_size = buffer_size; buffer_size = BRASERO_GET_32 (buffer->hdr.len) + G_STRUCT_OFFSET (BraseroScsiGetPerfHdr, len) + sizeof (buffer->hdr.len); } } else if (request_size > buffer_size) BRASERO_MEDIA_LOG ("Sizes mismatch asked %i / received %i", request_size, buffer_size); *data = buffer; *data_size = MIN (buffer_size, request_size); return res; }