ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Linux/scsi_linux.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/Linux/scsi_linux.cpp (file contents):
Revision 1.2 by cebix, 2000-04-10T18:53:17Z vs.
Revision 1.6 by cebix, 2002-01-26T18:10:13Z

# Line 1 | Line 1
1   /*
2   *  scsi_linux.cpp - SCSI Manager, Linux specific stuff
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2002 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 26 | Line 26
26   #include <unistd.h>
27   #include <errno.h>
28  
29 + #define DRIVER_SENSE 0x08
30 +
31   #include "main.h"
32   #include "prefs.h"
33   #include "user_strings.h"
# Line 63 | Line 65 | void SCSIInit(void)
65                  sprintf(prefs_name, "scsi%d", id);
66                  const char *str = PrefsFindString(prefs_name);
67                  if (str) {
68 <                        int fd = fds[id] = open(str, O_RDWR);
68 >                        int fd = fds[id] = open(str, O_RDWR | O_EXCL);
69                          if (fd > 0) {
70                                  // Is it really a Generic SCSI device?
71                                  int timeout = ioctl(fd, SG_GET_TIMEOUT);
# Line 120 | Line 122 | void SCSIExit(void)
122   *  Check if requested data size fits into buffer, allocate new buffer if needed
123   */
124  
125 < static bool try_buffer(int size)
125 > static bool try_buffer(uint32 size)
126   {
127 <        size += sizeof(struct sg_header) + 12;
127 >        size += sizeof(sg_header) + 12;
128          if (size <= buffer_size)
129                  return true;
130  
# Line 166 | Line 168 | bool scsi_set_target(int id, int lun)
168          if (new_fd < 0)
169                  return false;
170          if (new_fd != fd) {
171 <                // Clear autosense data
172 <                struct sg_header *h = (struct sg_header *)buffer;
173 <                h->sense_buffer[2] = 0;
171 >                // New target, clear autosense data
172 >                sg_header *h = (sg_header *)buffer;
173 >                h->driver_status &= ~DRIVER_SENSE;
174          }
175          fd = new_fd;
176          return true;
# Line 195 | Line 197 | bool scsi_send_cmd(size_t data_length, b
197          // Process S/G table when writing
198          if (!reading) {
199                  D(bug(" writing to buffer\n"));
200 <                uint8 *buffer_ptr = buffer + sizeof(struct sg_header) + the_cmd_len;
200 >                uint8 *buffer_ptr = buffer + sizeof(sg_header) + the_cmd_len;
201                  for (int i=0; i<sg_size; i++) {
202                          uint32 len = sg_len[i];
203                          D(bug("  %d bytes from %08lx\n", len, sg_ptr[i]));
# Line 205 | Line 207 | bool scsi_send_cmd(size_t data_length, b
207          }
208  
209          // Request Sense and autosense data valid?
210 <        struct sg_header *h = (struct sg_header *)buffer;
210 >        sg_header *h = (sg_header *)buffer;
211          int res;
212 <        if (the_cmd[0] == 0x03 && (h->sense_buffer[2] & 0x0f)) {
212 >        if (reading && the_cmd[0] == 0x03 && (h->target_status & DRIVER_SENSE)) {
213  
214                  // Yes, fake command
215                  D(bug(" autosense\n"));
216 <                memcpy(buffer + sizeof(struct sg_header), h->sense_buffer, 16);
216 >                memcpy(buffer + sizeof(sg_header), h->sense_buffer, 16);
217 >                h->target_status &= ~DRIVER_SENSE;
218                  res = 0;
219                  *stat = 0;
220  
221          } else {
222  
223                  // No, send regular command
224 <                int to = timeout * HZ / 60;
225 <                ioctl(fd, SG_SET_TIMEOUT, &to);
224 >                if (timeout) {
225 >                        int to = timeout * HZ / 60;
226 >                        ioctl(fd, SG_SET_TIMEOUT, &to);
227 >                }
228 >                ioctl(fd, SG_NEXT_CMD_LEN, &the_cmd_len);
229 >
230                  D(bug(" sending command, length %d\n", data_length));
231 +
232                  int request_size, reply_size;
233                  if (reading) {
234 <                        h->pack_len = request_size = sizeof(struct sg_header) + the_cmd_len;
235 <                        h->reply_len = reply_size = sizeof(struct sg_header) + data_length;
234 >                        h->pack_len = request_size = sizeof(sg_header) + the_cmd_len;
235 >                        h->reply_len = reply_size = sizeof(sg_header) + data_length;
236                  } else {
237 <                        h->pack_len = request_size = sizeof(struct sg_header) + the_cmd_len + data_length;
238 <                        h->reply_len = reply_size = sizeof(struct sg_header);
237 >                        h->pack_len = request_size = sizeof(sg_header) + the_cmd_len + data_length;
238 >                        h->reply_len = reply_size = sizeof(sg_header);
239                  }
240                  h->pack_id = pack_id++;
241                  h->result = 0;
242                  h->twelve_byte = (the_cmd_len == 12);
243 <                h->sense_buffer[2] = 0;
244 <                memcpy(buffer + sizeof(struct sg_header), the_cmd, the_cmd_len);
243 >                h->target_status = 0;
244 >                h->host_status = 0;
245 >                h->driver_status = 0;
246 >                h->other_flags = 0;
247 >                memcpy(buffer + sizeof(sg_header), the_cmd, the_cmd_len);
248 >
249                  res = write(fd, buffer, request_size);
250                  D(bug(" request sent, actual %d, result %d\n", res, h->result));
251                  if (res >= 0) {
252                          res = read(fd, buffer, reply_size);
253 <                        D(bug(" reply read, actual %d, result %d\n", res, h->result));
253 >                        D(bug(" reply read, actual %d, result %d, status %02x\n", res, h->result, h->target_status << 1));
254                  }
255 <                if (h->sense_buffer[2] & 0x0f)
256 <                        *stat = 2;      // Check condition
245 <                else
246 <                        *stat = 0;      // No error
255 >
256 >                *stat = h->target_status << 1;
257          }
258  
259          // Process S/G table when reading
260          if (reading && h->result == 0) {
261                  D(bug(" reading from buffer\n"));
262 <                uint8 *buffer_ptr = buffer + sizeof(struct sg_header);
262 >                uint8 *buffer_ptr = buffer + sizeof(sg_header);
263                  for (int i=0; i<sg_size; i++) {
264                          uint32 len = sg_len[i];
265                          D(bug("  %d bytes to %08lx\n", len, sg_ptr[i]));

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines