1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
6
* Libbrasero-media is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* The Libbrasero-media authors hereby grant permission for non-GPL compatible
12
* GStreamer plugins to be used and distributed together with GStreamer
13
* and Libbrasero-media. This permission is above and beyond the permissions granted
14
* by the GPL license by which Libbrasero-media is covered. If you modify this code
15
* you may extend this exception to your version of the code, but you are not
16
* obligated to do so. If you do not wish to do so, delete this exception
17
* statement from your version.
19
* Libbrasero-media is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU Library General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, write to:
26
* The Free Software Foundation, Inc.,
27
* 51 Franklin Street, Fifth Floor
28
* Boston, MA 02110-1301, USA.
37
#include "brasero-media-private.h"
39
#include "scsi-error.h"
40
#include "scsi-utils.h"
41
#include "scsi-command.h"
42
#include "scsi-opcodes.h"
43
#include "scsi-get-performance.h"
46
* GET PERMORMANCE command description (MMC2)
49
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
51
struct _BraseroGetPerformanceCDB {
71
struct _BraseroGetPerformanceCDB {
91
typedef struct _BraseroGetPerformanceCDB BraseroGetPerformanceCDB;
93
BRASERO_SCSI_COMMAND_DEFINE (BraseroGetPerformanceCDB,
97
/* used to choose which GET PERFORMANCE response we want */
98
#define BRASERO_GET_PERFORMANCE_PERF_TYPE 0x00
99
#define BRASERO_GET_PERFORMANCE_UNUSABLE_AREA_TYPE 0x01
100
#define BRASERO_GET_PERFORMANCE_DEFECT_STATUS_TYPE 0x02
101
#define BRASERO_GET_PERFORMANCE_WR_SPEED_TYPE 0x03
102
#define BRASERO_GET_PERFORMANCE_DBI_TYPE 0x04
103
#define BRASERO_GET_PERFORMANCE_DBI_CACHE_TYPE 0x05
105
static BraseroScsiGetPerfData *
106
brasero_get_performance_get_buffer (BraseroGetPerformanceCDB *cdb,
107
gint sizeof_descriptors,
108
BraseroScsiGetPerfHdr *hdr,
109
BraseroScsiErrCode *error)
111
BraseroScsiGetPerfData *buffer;
112
BraseroScsiResult res;
116
/* ... check the request size ... */
117
request_size = BRASERO_GET_32 (hdr->len) +
118
G_STRUCT_OFFSET (BraseroScsiGetPerfHdr, len) +
121
/* ... check the request size ... */
122
if (request_size > 2048) {
123
BRASERO_MEDIA_LOG ("Oversized data (%i) setting to max (2048)", request_size);
126
else if ((request_size - sizeof (hdr)) % sizeof_descriptors) {
127
BRASERO_MEDIA_LOG ("Unaligned data (%i) setting to max (2048)", request_size);
130
else if (request_size < sizeof (hdr)) {
131
BRASERO_MEDIA_LOG ("Undersized data (%i) setting to max (2048)", request_size);
135
desc_num = (request_size - sizeof (BraseroScsiGetPerfHdr)) / sizeof_descriptors;
137
/* ... allocate a buffer and re-issue the command */
138
buffer = (BraseroScsiGetPerfData *) g_new0 (uchar, request_size);
140
BRASERO_SET_16 (cdb->max_desc, desc_num);
141
res = brasero_scsi_command_issue_sync (cdb, buffer, request_size, error);
150
static BraseroScsiResult
151
brasero_get_performance (BraseroGetPerformanceCDB *cdb,
152
gint sizeof_descriptors,
153
BraseroScsiGetPerfData **data,
155
BraseroScsiErrCode *error)
157
BraseroScsiGetPerfData *buffer;
158
BraseroScsiGetPerfHdr hdr;
159
BraseroScsiResult res;
163
if (!data || !data_size) {
164
BRASERO_SCSI_SET_ERRCODE (error, BRASERO_SCSI_BAD_ARGUMENT);
165
return BRASERO_SCSI_FAILURE;
168
/* Issue the command once to get the size ... */
169
memset (&hdr, 0, sizeof (hdr));
170
BRASERO_SET_16 (cdb->max_desc, 0);
171
res = brasero_scsi_command_issue_sync (cdb, &hdr, sizeof (hdr), error);
175
/* ... get the request size ... */
176
request_size = BRASERO_GET_32 (hdr.len) +
177
G_STRUCT_OFFSET (BraseroScsiGetPerfHdr, len) +
180
/* ... get the answer itself. */
181
buffer = brasero_get_performance_get_buffer (cdb,
186
return BRASERO_SCSI_FAILURE;
188
/* make sure the response has the requested size */
189
buffer_size = BRASERO_GET_32 (buffer->hdr.len) +
190
G_STRUCT_OFFSET (BraseroScsiGetPerfHdr, len) +
191
sizeof (buffer->hdr.len);
193
if (request_size < buffer_size) {
194
BraseroScsiGetPerfHdr *tmp_hdr;
196
/* Strangely some drives returns a buffer size that is bigger
197
* than the one they returned on the first time. So redo whole
198
* operation again but this time with the new size we got */
199
BRASERO_MEDIA_LOG ("Sizes mismatch asked %i / received %i\n"
200
"Re-issuing the command with received size",
204
tmp_hdr = &buffer->hdr;
205
request_size = buffer_size;
206
buffer = brasero_get_performance_get_buffer (cdb,
210
buffer_size = BRASERO_GET_32 (buffer->hdr.len) +
211
G_STRUCT_OFFSET (BraseroScsiGetPerfHdr, len) +
212
sizeof (buffer->hdr.len);
216
else if (request_size > buffer_size)
217
BRASERO_MEDIA_LOG ("Sizes mismatch asked %i / received %i",
221
*data_size = MIN (buffer_size, request_size);
227
* MMC3 command extension
231
brasero_mmc3_get_performance_wrt_spd_desc (BraseroDeviceHandle *handle,
232
BraseroScsiGetPerfData **data,
234
BraseroScsiErrCode *error)
236
BraseroGetPerformanceCDB *cdb;
237
BraseroScsiResult res;
239
cdb = brasero_scsi_command_new (&info, handle);
240
cdb->type = BRASERO_GET_PERFORMANCE_WR_SPEED_TYPE;
242
res = brasero_get_performance (cdb, sizeof (BraseroScsiWrtSpdDesc), data, size, error);
243
brasero_scsi_command_free (cdb);