- scsi_linux.cpp uses SCSI generic interface version 2

- slightly more verbose SCSI debugging messages
This commit is contained in:
cebix 2002-01-26 18:10:13 +00:00
parent 0662d7a1f1
commit d6d7976939
3 changed files with 65 additions and 26 deletions

View File

@ -41,7 +41,6 @@ Unix:
- clip_unix.cpp: use X selections instead of cut buffer
- sys_unix.cpp: SysFormat(), SysIsFixedDisk(), SysIsDiskInserted(),
prevent/allow for non-floppy/CDROM devices
- scsi_linux.cpp: adapt to SCSI Generic driver V2.0
- ESD is also available on Solaris
- serial_unix.cpp: provide a way to pipe input/output to programs
- display progress bar during disk file creation in prefs editor

View File

@ -26,6 +26,8 @@
#include <unistd.h>
#include <errno.h>
#define DRIVER_SENSE 0x08
#include "main.h"
#include "prefs.h"
#include "user_strings.h"
@ -63,7 +65,7 @@ void SCSIInit(void)
sprintf(prefs_name, "scsi%d", id);
const char *str = PrefsFindString(prefs_name);
if (str) {
int fd = fds[id] = open(str, O_RDWR);
int fd = fds[id] = open(str, O_RDWR | O_EXCL);
if (fd > 0) {
// Is it really a Generic SCSI device?
int timeout = ioctl(fd, SG_GET_TIMEOUT);
@ -122,7 +124,7 @@ void SCSIExit(void)
static bool try_buffer(uint32 size)
{
size += sizeof(struct sg_header) + 12;
size += sizeof(sg_header) + 12;
if (size <= buffer_size)
return true;
@ -166,9 +168,9 @@ bool scsi_set_target(int id, int lun)
if (new_fd < 0)
return false;
if (new_fd != fd) {
// Clear autosense data
struct sg_header *h = (struct sg_header *)buffer;
h->sense_buffer[2] = 0;
// New target, clear autosense data
sg_header *h = (sg_header *)buffer;
h->driver_status &= ~DRIVER_SENSE;
}
fd = new_fd;
return true;
@ -195,7 +197,7 @@ bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr
// Process S/G table when writing
if (!reading) {
D(bug(" writing to buffer\n"));
uint8 *buffer_ptr = buffer + sizeof(struct sg_header) + the_cmd_len;
uint8 *buffer_ptr = buffer + sizeof(sg_header) + the_cmd_len;
for (int i=0; i<sg_size; i++) {
uint32 len = sg_len[i];
D(bug(" %d bytes from %08lx\n", len, sg_ptr[i]));
@ -205,51 +207,59 @@ bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr
}
// Request Sense and autosense data valid?
struct sg_header *h = (struct sg_header *)buffer;
sg_header *h = (sg_header *)buffer;
int res;
if (the_cmd[0] == 0x03 && (h->sense_buffer[2] & 0x0f)) {
if (reading && the_cmd[0] == 0x03 && (h->target_status & DRIVER_SENSE)) {
// Yes, fake command
D(bug(" autosense\n"));
memcpy(buffer + sizeof(struct sg_header), h->sense_buffer, 16);
memcpy(buffer + sizeof(sg_header), h->sense_buffer, 16);
h->target_status &= ~DRIVER_SENSE;
res = 0;
*stat = 0;
} else {
// No, send regular command
int to = timeout * HZ / 60;
ioctl(fd, SG_SET_TIMEOUT, &to);
if (timeout) {
int to = timeout * HZ / 60;
ioctl(fd, SG_SET_TIMEOUT, &to);
}
ioctl(fd, SG_NEXT_CMD_LEN, &the_cmd_len);
D(bug(" sending command, length %d\n", data_length));
int request_size, reply_size;
if (reading) {
h->pack_len = request_size = sizeof(struct sg_header) + the_cmd_len;
h->reply_len = reply_size = sizeof(struct sg_header) + data_length;
h->pack_len = request_size = sizeof(sg_header) + the_cmd_len;
h->reply_len = reply_size = sizeof(sg_header) + data_length;
} else {
h->pack_len = request_size = sizeof(struct sg_header) + the_cmd_len + data_length;
h->reply_len = reply_size = sizeof(struct sg_header);
h->pack_len = request_size = sizeof(sg_header) + the_cmd_len + data_length;
h->reply_len = reply_size = sizeof(sg_header);
}
h->pack_id = pack_id++;
h->result = 0;
h->twelve_byte = (the_cmd_len == 12);
h->sense_buffer[2] = 0;
memcpy(buffer + sizeof(struct sg_header), the_cmd, the_cmd_len);
h->target_status = 0;
h->host_status = 0;
h->driver_status = 0;
h->other_flags = 0;
memcpy(buffer + sizeof(sg_header), the_cmd, the_cmd_len);
res = write(fd, buffer, request_size);
D(bug(" request sent, actual %d, result %d\n", res, h->result));
if (res >= 0) {
res = read(fd, buffer, reply_size);
D(bug(" reply read, actual %d, result %d\n", res, h->result));
D(bug(" reply read, actual %d, result %d, status %02x\n", res, h->result, h->target_status << 1));
}
if (h->sense_buffer[2] & 0x0f)
*stat = 2; // Check condition
else
*stat = 0; // No error
*stat = h->target_status << 1;
}
// Process S/G table when reading
if (reading && h->result == 0) {
D(bug(" reading from buffer\n"));
uint8 *buffer_ptr = buffer + sizeof(struct sg_header);
uint8 *buffer_ptr = buffer + sizeof(sg_header);
for (int i=0; i<sg_size; i++) {
uint32 len = sg_len[i];
D(bug(" %d bytes to %08lx\n", len, sg_ptr[i]));

View File

@ -96,7 +96,21 @@ static int16 exec_tib(uint32 tib)
uint32 ptr = ReadMacInt32(tib); tib += 4;
uint32 len = ReadMacInt32(tib); tib += 4;
D(bug(" %d %08x %d\n", cmd, ptr, len));
#if DEBUG
const char *cmd_str;
switch (cmd) {
case scInc: cmd_str = "INC "; break;
case scNoInc: cmd_str = "NOINC"; break;
case scAdd: cmd_str = "ADD "; break;
case scMove: cmd_str = "MOVE "; break;
case scLoop: cmd_str = "LOOP "; break;
case scNop: cmd_str = "NOP "; break;
case scStop: cmd_str = "STOP "; break;
case scComp: cmd_str = "COMP "; break;
default: cmd_str = "??? "; break;
}
D(bug(" %s(%d) %08x %d\n", cmd_str, cmd, ptr, len));
#endif
switch (cmd) {
case scInc:
@ -218,7 +232,23 @@ int16 SCSISelect(int id)
int16 SCSICmd(int cmd_length, uint8 *cmd)
{
D(bug("SCSICmd len %d, cmd %08x%08x%08x\n", cmd_length, ntohl(0[(uint32 *)cmd]), ntohl(1[(uint32 *)cmd]), ntohl(2[(uint32 *)cmd])));
#if DEBUG
switch (cmd_length) {
case 6:
D(bug("SCSICmd len 6, cmd %02x %02x %02x %02x %02x %02x\n", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]));
break;
case 10:
D(bug("SCSICmd len 10, cmd %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9]));
break;
case 12:
D(bug("SCSICmd len 12, cmd %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9], cmd[10], cmd[11]));
break;
default:
D(bug("SCSICmd bogus length %d\n", cmd_length));
break;
}
#endif
if (phase != PH_SELECTED)
return scPhaseErr;