10#include "module_debug.h"
12#define getBI32(__buf) ((((u8 *)(__buf))[3] << 0) | (((u8 *)(__buf))[2] << 8) | (((u8 *)(__buf))[1] << 16) | (((u8 *)(__buf))[0] << 24))
13#define SCSI_MAX_RETRIES 16
17 u8 peripheral_device_type;
20 u8 response_data_format;
53static int scsi_cmd(
struct block_device *bd,
unsigned char cmd,
void *buffer,
int buf_size,
int cmd_size)
55 unsigned char comData[12] = {0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
61 comData[4] = cmd_size;
63 return scsi->queue_cmd(scsi, comData, 12, buffer, buf_size, 0);
66static inline int scsi_cmd_test_unit_ready(
struct block_device *bd)
68 M_DEBUG(
"%s\n", __func__);
70 return scsi_cmd(bd, 0x00, NULL, 0, 0);
73static inline int scsi_cmd_request_sense(
struct block_device *bd,
void *buffer,
int size)
75 M_DEBUG(
"%s\n", __func__);
77 return scsi_cmd(bd, 0x03, buffer, size, size);
80static inline int scsi_cmd_inquiry(
struct block_device *bd,
void *buffer,
int size)
82 M_DEBUG(
"%s\n", __func__);
84 return scsi_cmd(bd, 0x12, buffer, size, size);
87static int scsi_cmd_start_stop_unit(
struct block_device *bd, u8 param)
89 M_DEBUG(
"%s\n", __func__);
91 return scsi_cmd(bd, 0x1b, NULL, 0, param);
94static inline int scsi_cmd_read_capacity(
struct block_device *bd,
void *buffer,
int size)
96 M_DEBUG(
"%s\n", __func__);
98 return scsi_cmd(bd, 0x25, buffer, size, 0);
101static int scsi_cmd_rw_sector(
struct block_device *bd, u64 lba,
const void *buffer,
unsigned short int sectorCount,
unsigned int write)
103 unsigned char comData[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
106 DEBUG_U64_2XU32(lba);
107 M_DEBUG(
"scsi_cmd_rw_sector - 0x%08x%08x %p 0x%04x\n", lba_u32[1], lba_u32[0], buffer, sectorCount);
112 comData[0] = write ? 0x2a : 0x28;
113 comData[2] = (lba & 0xFF000000) >> 24;
114 comData[3] = (lba & 0xFF0000) >> 16;
115 comData[4] = (lba & 0xFF00) >> 8;
116 comData[5] = (lba & 0xFF);
117 comData[7] = (sectorCount & 0xFF00) >> 8;
118 comData[8] = (sectorCount & 0xFF);
119 return scsi->queue_cmd(scsi, comData, 12, (
void *)buffer, bd->sectorSize * sectorCount, write);
133 M_DEBUG(
"%s\n", __func__);
135 stat = scsi->get_max_lun(scsi);
136 M_DEBUG(
"scsi->get_max_lun %d\n", stat);
139 if ((stat = scsi_cmd_inquiry(bd, &
id,
sizeof(
inquiry_data))) < 0) {
140 M_PRINTF(
"ERROR: scsi_cmd_inquiry %d\n", stat);
144 M_PRINTF(
"Vendor: %.8s\n",
id.vendor);
145 M_PRINTF(
"Product: %.16s\n",
id.product);
146 M_PRINTF(
"Revision: %.4s\n",
id.revision);
148 while ((stat = scsi_cmd_test_unit_ready(bd)) != 0) {
149 M_PRINTF(
"ERROR: scsi_cmd_test_unit_ready %d\n", stat);
151 stat = scsi_cmd_request_sense(bd, &sd,
sizeof(
sense_data));
153 M_PRINTF(
"ERROR: scsi_cmd_request_sense %d\n", stat);
156 if ((sd.error_code == 0x70) && (sd.sense_key != 0x00)) {
157 M_PRINTF(
"Sense Data key: %02X code: %02X qual: %02X\n", sd.sense_key, sd.add_sense_code, sd.add_sense_qual);
159 if ((sd.sense_key == 0x02) && (sd.add_sense_code == 0x04) && (sd.add_sense_qual == 0x02)) {
160 M_PRINTF(
"ERROR: Additional initalization is required for this device!\n");
161 if ((stat = scsi_cmd_start_stop_unit(bd, 1)) != 0) {
162 M_PRINTF(
"ERROR: scsi_cmd_start_stop_unit %d\n", stat);
170 M_PRINTF(
"ERROR: scsi_cmd_read_capacity %d\n", stat);
174 bd->sectorSize = getBI32(&rcd.block_length);
175 bd->sectorOffset = 0;
176 bd->sectorCount = getBI32(&rcd.last_lba);
177 M_PRINTF(
"%u %u-byte logical blocks: (%uMB / %uMiB)\n", bd->sectorCount, bd->sectorSize, bd->sectorCount / ((1000 * 1000) / bd->sectorSize), bd->sectorCount / ((1024 * 1024) / bd->sectorSize));
185static int scsi_read(
struct block_device *bd, u64 sector,
void *buffer, u16
count)
188 u16 sc_remaining =
count;
191 DEBUG_U64_2XU32(sector);
192 M_DEBUG(
"%s: sector=0x%08x%08x, count=%d\n", __func__, sector_u32[1], sector_u32[0],
count);
194 while (sc_remaining > 0) {
195 u16 sc = sc_remaining > scsi->max_sectors ? scsi->max_sectors : sc_remaining;
197 for (retries = SCSI_MAX_RETRIES; retries > 0; retries--) {
198 if (scsi_cmd_rw_sector(bd, sector, buffer, sc, 0) == 0)
204 M_PRINTF(
"ERROR: unable to read sector after %d tries (sector=0x%08x%08x, count=%d)\n", SCSI_MAX_RETRIES, sector_u32[1], sector_u32[0],
count);
210 buffer = (u8 *)buffer + (sc * bd->sectorSize);
216static int scsi_write(
struct block_device *bd, u64 sector,
const void *buffer, u16
count)
219 u16 sc_remaining =
count;
220 unsigned int sectorSize = bd->sectorSize;
221 void *misalign_buffer = NULL;
224 DEBUG_U64_2XU32(sector);
225 M_DEBUG(
"%s: sector=0x%08x%08x, count=%d\n", __func__, sector_u32[1], sector_u32[0],
count);
227 if (((uiptr)buffer & 3) != 0) {
229 misalign_buffer = __builtin_alloca(sectorSize + 4);
231 if (((uiptr)misalign_buffer & 3) != 0)
233 misalign_buffer = (u8 *)misalign_buffer + (4 - ((uiptr)misalign_buffer & 3));
237 while (sc_remaining > 0) {
238 u16 sc = sc_remaining > scsi->max_sectors ? scsi->max_sectors : sc_remaining;
239 const void *dst_buffer = buffer;
241 if (misalign_buffer != NULL) {
242 memcpy(misalign_buffer, buffer, sectorSize);
243 dst_buffer = misalign_buffer;
247 for (retries = SCSI_MAX_RETRIES; retries > 0; retries--) {
248 if (scsi_cmd_rw_sector(bd, sector, dst_buffer, sc, 1) == 0)
254 M_PRINTF(
"ERROR: unable to write sector after %d tries (sector=0x%08x%08x, count=%d)\n", SCSI_MAX_RETRIES, sector_u32[1], sector_u32[0],
count);
260 buffer = (u8 *)buffer + (sc * sectorSize);
270 M_DEBUG(
"%s\n", __func__);
279 M_DEBUG(
"%s\n", __func__);
281 if ((stat = scsi_cmd_start_stop_unit(bd, 0)) != 0) {
282 M_PRINTF(
"ERROR: scsi_cmd_start_stop_unit %d\n", stat);
295 M_DEBUG(
"%s\n", __func__);
297 for (i = 0; i < NUM_DEVICES; ++i) {
298 if (g_scsi_bd[i].priv == NULL) {
302 bd->name = scsi->name;
314 M_DEBUG(
"%s\n", __func__);
316 for (i = 0; i < NUM_DEVICES; ++i) {
317 if (g_scsi_bd[i].priv == scsi) {
319 bdm_disconnect_bd(bd);
330 M_DEBUG(
"%s\n", __func__);
332 for (i = 0; i < NUM_DEVICES; ++i) {
333 g_scsi_bd[i].devNr = i;
334 g_scsi_bd[i].parNr = 0;
335 g_scsi_bd[i].parId = 0x00;
337 g_scsi_bd[i].priv = NULL;
338 g_scsi_bd[i].read = scsi_read;
339 g_scsi_bd[i].write = scsi_write;
340 g_scsi_bd[i].flush = scsi_flush;
341 g_scsi_bd[i].stop = scsi_stop;
u32 count
start sector of fragmented bd/file