aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/dc395x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/dc395x.c')
-rw-r--r--drivers/scsi/dc395x.c276
1 files changed, 150 insertions, 126 deletions
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index cbf825263f3b..183245254931 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -230,13 +230,12 @@ struct ScsiReqBlk {
230 struct scsi_cmnd *cmd; 230 struct scsi_cmnd *cmd;
231 231
232 struct SGentry *segment_x; /* Linear array of hw sg entries (up to 64 entries) */ 232 struct SGentry *segment_x; /* Linear array of hw sg entries (up to 64 entries) */
233 u32 sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */ 233 dma_addr_t sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */
234 234
235 u8 sg_count; /* No of HW sg entries for this request */ 235 u8 sg_count; /* No of HW sg entries for this request */
236 u8 sg_index; /* Index of HW sg entry for this request */ 236 u8 sg_index; /* Index of HW sg entry for this request */
237 u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ 237 size_t total_xfer_length; /* Total number of bytes remaining to be transfered */
238 unsigned char *virt_addr; /* Virtual address of current transfer position */ 238 size_t request_length; /* Total number of bytes in this request */
239
240 /* 239 /*
241 * The sense buffer handling function, request_sense, uses 240 * The sense buffer handling function, request_sense, uses
242 * the first hw sg entry (segment_x[0]) and the transfer 241 * the first hw sg entry (segment_x[0]) and the transfer
@@ -246,8 +245,7 @@ struct ScsiReqBlk {
246 * total_xfer_length in xferred. These values are restored in 245 * total_xfer_length in xferred. These values are restored in
247 * pci_unmap_srb_sense. This is the only place xferred is used. 246 * pci_unmap_srb_sense. This is the only place xferred is used.
248 */ 247 */
249 unsigned char *virt_addr_req; /* Saved virtual address of the request buffer */ 248 size_t xferred; /* Saved copy of total_xfer_length */
250 u32 xferred; /* Saved copy of total_xfer_length */
251 249
252 u16 state; 250 u16 state;
253 251
@@ -977,17 +975,6 @@ static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
977 } 975 }
978} 976}
979 977
980static inline void pio_trigger(void)
981{
982 static int feedback_requested;
983
984 if (!feedback_requested) {
985 feedback_requested = 1;
986 printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> "
987 "to help improve support for your system.\n", __FILE__);
988 }
989}
990
991/* Prepare SRB for being sent to Device DCB w/ command *cmd */ 978/* Prepare SRB for being sent to Device DCB w/ command *cmd */
992static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, 979static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
993 struct ScsiReqBlk *srb) 980 struct ScsiReqBlk *srb)
@@ -1001,7 +988,6 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
1001 srb->sg_count = 0; 988 srb->sg_count = 0;
1002 srb->total_xfer_length = 0; 989 srb->total_xfer_length = 0;
1003 srb->sg_bus_addr = 0; 990 srb->sg_bus_addr = 0;
1004 srb->virt_addr = NULL;
1005 srb->sg_index = 0; 991 srb->sg_index = 0;
1006 srb->adapter_status = 0; 992 srb->adapter_status = 0;
1007 srb->target_status = 0; 993 srb->target_status = 0;
@@ -1032,7 +1018,6 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
1032 reqlen, cmd->request_buffer, cmd->use_sg, 1018 reqlen, cmd->request_buffer, cmd->use_sg,
1033 srb->sg_count); 1019 srb->sg_count);
1034 1020
1035 srb->virt_addr = page_address(sl->page);
1036 for (i = 0; i < srb->sg_count; i++) { 1021 for (i = 0; i < srb->sg_count; i++) {
1037 u32 busaddr = (u32)sg_dma_address(&sl[i]); 1022 u32 busaddr = (u32)sg_dma_address(&sl[i]);
1038 u32 seglen = (u32)sl[i].length; 1023 u32 seglen = (u32)sl[i].length;
@@ -1077,12 +1062,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
1077 srb->total_xfer_length++; 1062 srb->total_xfer_length++;
1078 1063
1079 srb->segment_x[0].length = srb->total_xfer_length; 1064 srb->segment_x[0].length = srb->total_xfer_length;
1080 srb->virt_addr = cmd->request_buffer; 1065
1081 dprintkdbg(DBG_0, 1066 dprintkdbg(DBG_0,
1082 "build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n", 1067 "build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n",
1083 srb->total_xfer_length, cmd->request_buffer, 1068 srb->total_xfer_length, cmd->request_buffer,
1084 cmd->use_sg, srb->segment_x[0].address); 1069 cmd->use_sg, srb->segment_x[0].address);
1085 } 1070 }
1071
1072 srb->request_length = srb->total_xfer_length;
1086} 1073}
1087 1074
1088 1075
@@ -1414,10 +1401,10 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd)
1414 } 1401 }
1415 srb = find_cmd(cmd, &dcb->srb_going_list); 1402 srb = find_cmd(cmd, &dcb->srb_going_list);
1416 if (srb) { 1403 if (srb) {
1417 dprintkl(KERN_DEBUG, "eh_abort: Command in progress"); 1404 dprintkl(KERN_DEBUG, "eh_abort: Command in progress\n");
1418 /* XXX: Should abort the command here */ 1405 /* XXX: Should abort the command here */
1419 } else { 1406 } else {
1420 dprintkl(KERN_DEBUG, "eh_abort: Command not found"); 1407 dprintkl(KERN_DEBUG, "eh_abort: Command not found\n");
1421 } 1408 }
1422 return FAILED; 1409 return FAILED;
1423} 1410}
@@ -1976,14 +1963,11 @@ static void sg_verify_length(struct ScsiReqBlk *srb)
1976 1963
1977/* 1964/*
1978 * Compute the next Scatter Gather list index and adjust its length 1965 * Compute the next Scatter Gather list index and adjust its length
1979 * and address if necessary; also compute virt_addr 1966 * and address if necessary
1980 */ 1967 */
1981static void sg_update_list(struct ScsiReqBlk *srb, u32 left) 1968static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
1982{ 1969{
1983 u8 idx; 1970 u8 idx;
1984 struct scatterlist *sg;
1985 struct scsi_cmnd *cmd = srb->cmd;
1986 int segment = cmd->use_sg;
1987 u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ 1971 u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
1988 struct SGentry *psge = srb->segment_x + srb->sg_index; 1972 struct SGentry *psge = srb->segment_x + srb->sg_index;
1989 1973
@@ -2016,29 +2000,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
2016 psge++; 2000 psge++;
2017 } 2001 }
2018 sg_verify_length(srb); 2002 sg_verify_length(srb);
2019
2020 /* we need the corresponding virtual address */
2021 if (!segment || (srb->flag & AUTO_REQSENSE)) {
2022 srb->virt_addr += xferred;
2023 return;
2024 }
2025
2026 /* We have to walk the scatterlist to find it */
2027 sg = (struct scatterlist *)cmd->request_buffer;
2028 while (segment--) {
2029 unsigned long mask =
2030 ~((unsigned long)sg->length - 1) & PAGE_MASK;
2031 if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
2032 srb->virt_addr = (page_address(sg->page)
2033 + psge->address -
2034 (psge->address & PAGE_MASK));
2035 return;
2036 }
2037 ++sg;
2038 }
2039
2040 dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
2041 srb->virt_addr = NULL;
2042} 2003}
2043 2004
2044 2005
@@ -2050,15 +2011,7 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
2050 */ 2011 */
2051static void sg_subtract_one(struct ScsiReqBlk *srb) 2012static void sg_subtract_one(struct ScsiReqBlk *srb)
2052{ 2013{
2053 srb->total_xfer_length--; 2014 sg_update_list(srb, srb->total_xfer_length - 1);
2054 srb->segment_x[srb->sg_index].length--;
2055 if (srb->total_xfer_length &&
2056 !srb->segment_x[srb->sg_index].length) {
2057 if (debug_enabled(DBG_PIO))
2058 printk(" (next segment)");
2059 srb->sg_index++;
2060 sg_update_list(srb, srb->total_xfer_length);
2061 }
2062} 2015}
2063 2016
2064 2017
@@ -2118,7 +2071,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2118 * If we need more data, the DMA SG list will be freshly set up, anyway 2071 * If we need more data, the DMA SG list will be freshly set up, anyway
2119 */ 2072 */
2120 dprintkdbg(DBG_PIO, "data_out_phase0: " 2073 dprintkdbg(DBG_PIO, "data_out_phase0: "
2121 "DMA{fifcnt=0x%02x fifostat=0x%02x} " 2074 "DMA{fifocnt=0x%02x fifostat=0x%02x} "
2122 "SCSI{fifocnt=0x%02x cnt=0x%06x status=0x%04x} total=0x%06x\n", 2075 "SCSI{fifocnt=0x%02x cnt=0x%06x status=0x%04x} total=0x%06x\n",
2123 DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), 2076 DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT),
2124 DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), 2077 DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT),
@@ -2239,12 +2192,11 @@ static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2239 data_io_transfer(acb, srb, XFERDATAOUT); 2192 data_io_transfer(acb, srb, XFERDATAOUT);
2240} 2193}
2241 2194
2242
2243static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, 2195static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2244 u16 *pscsi_status) 2196 u16 *pscsi_status)
2245{ 2197{
2246 u16 scsi_status = *pscsi_status; 2198 u16 scsi_status = *pscsi_status;
2247 u32 d_left_counter = 0; 2199
2248 dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n", 2200 dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n",
2249 srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); 2201 srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
2250 2202
@@ -2262,6 +2214,9 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2262 * seem to be a bad idea, actually. 2214 * seem to be a bad idea, actually.
2263 */ 2215 */
2264 if (!(srb->state & SRB_XFERPAD)) { 2216 if (!(srb->state & SRB_XFERPAD)) {
2217 u32 d_left_counter;
2218 unsigned int sc, fc;
2219
2265 if (scsi_status & PARITYERROR) { 2220 if (scsi_status & PARITYERROR) {
2266 dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) " 2221 dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) "
2267 "Parity Error\n", srb->cmd->pid); 2222 "Parity Error\n", srb->cmd->pid);
@@ -2298,18 +2253,19 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2298 DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT)); 2253 DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT));
2299 } 2254 }
2300 /* Now: Check remainig data: The SCSI counters should tell us ... */ 2255 /* Now: Check remainig data: The SCSI counters should tell us ... */
2301 d_left_counter = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER) 2256 sc = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER);
2302 + ((DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f) 2257 fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT);
2258 d_left_counter = sc + ((fc & 0x1f)
2303 << ((srb->dcb->sync_period & WIDE_SYNC) ? 1 : 2259 << ((srb->dcb->sync_period & WIDE_SYNC) ? 1 :
2304 0)); 2260 0));
2305 dprintkdbg(DBG_KG, "data_in_phase0: " 2261 dprintkdbg(DBG_KG, "data_in_phase0: "
2306 "SCSI{fifocnt=0x%02x%s ctr=0x%08x} " 2262 "SCSI{fifocnt=0x%02x%s ctr=0x%08x} "
2307 "DMA{fifocnt=0x%02x fifostat=0x%02x ctr=0x%08x} " 2263 "DMA{fifocnt=0x%02x fifostat=0x%02x ctr=0x%08x} "
2308 "Remain{totxfer=%i scsi_fifo+ctr=%i}\n", 2264 "Remain{totxfer=%i scsi_fifo+ctr=%i}\n",
2309 DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), 2265 fc,
2310 (srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes", 2266 (srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes",
2311 DC395x_read32(acb, TRM_S1040_SCSI_COUNTER), 2267 sc,
2312 DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), 2268 fc,
2313 DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), 2269 DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT),
2314 DC395x_read32(acb, TRM_S1040_DMA_CXCNT), 2270 DC395x_read32(acb, TRM_S1040_DMA_CXCNT),
2315 srb->total_xfer_length, d_left_counter); 2271 srb->total_xfer_length, d_left_counter);
@@ -2317,40 +2273,79 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
2317 /* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */ 2273 /* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */
2318 if (d_left_counter 2274 if (d_left_counter
2319 && srb->total_xfer_length <= DC395x_LASTPIO) { 2275 && srb->total_xfer_length <= DC395x_LASTPIO) {
2276 size_t left_io = srb->total_xfer_length;
2277
2320 /*u32 addr = (srb->segment_x[srb->sg_index].address); */ 2278 /*u32 addr = (srb->segment_x[srb->sg_index].address); */
2321 /*sg_update_list (srb, d_left_counter); */ 2279 /*sg_update_list (srb, d_left_counter); */
2322 dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) to " 2280 dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) "
2323 "%p for remaining %i bytes:", 2281 "for remaining %i bytes:",
2324 DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f, 2282 fc & 0x1f,
2325 (srb->dcb->sync_period & WIDE_SYNC) ? 2283 (srb->dcb->sync_period & WIDE_SYNC) ?
2326 "words" : "bytes", 2284 "words" : "bytes",
2327 srb->virt_addr,
2328 srb->total_xfer_length); 2285 srb->total_xfer_length);
2329 if (srb->dcb->sync_period & WIDE_SYNC) 2286 if (srb->dcb->sync_period & WIDE_SYNC)
2330 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 2287 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
2331 CFG2_WIDEFIFO); 2288 CFG2_WIDEFIFO);
2332 while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) { 2289 while (left_io) {
2333 u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); 2290 unsigned char *virt, *base = NULL;
2334 pio_trigger(); 2291 unsigned long flags = 0;
2335 *(srb->virt_addr)++ = byte; 2292 size_t len = left_io;
2336 if (debug_enabled(DBG_PIO)) 2293
2337 printk(" %02x", byte); 2294 if (srb->cmd->use_sg) {
2338 d_left_counter--; 2295 size_t offset = srb->request_length - left_io;
2339 sg_subtract_one(srb); 2296 local_irq_save(flags);
2340 } 2297 /* Assumption: it's inside one page as it's at most 4 bytes and
2341 if (srb->dcb->sync_period & WIDE_SYNC) { 2298 I just assume it's on a 4-byte boundary */
2342#if 1 2299 base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
2343 /* Read the last byte ... */ 2300 srb->sg_count, &offset, &len);
2344 if (srb->total_xfer_length > 0) { 2301 virt = base + offset;
2345 u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); 2302 } else {
2346 pio_trigger(); 2303 virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
2347 *(srb->virt_addr)++ = byte; 2304 len = left_io;
2348 srb->total_xfer_length--; 2305 }
2306 left_io -= len;
2307
2308 while (len) {
2309 u8 byte;
2310 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
2311 *virt++ = byte;
2312
2349 if (debug_enabled(DBG_PIO)) 2313 if (debug_enabled(DBG_PIO))
2350 printk(" %02x", byte); 2314 printk(" %02x", byte);
2315
2316 d_left_counter--;
2317 sg_subtract_one(srb);
2318
2319 len--;
2320
2321 fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT);
2322
2323 if (fc == 0x40) {
2324 left_io = 0;
2325 break;
2326 }
2327 }
2328
2329 WARN_ON((fc != 0x40) == !d_left_counter);
2330
2331 if (fc == 0x40 && (srb->dcb->sync_period & WIDE_SYNC)) {
2332 /* Read the last byte ... */
2333 if (srb->total_xfer_length > 0) {
2334 u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
2335
2336 *virt++ = byte;
2337 srb->total_xfer_length--;
2338 if (debug_enabled(DBG_PIO))
2339 printk(" %02x", byte);
2340 }
2341
2342 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
2343 }
2344
2345 if (srb->cmd->use_sg) {
2346 scsi_kunmap_atomic_sg(base);
2347 local_irq_restore(flags);
2351 } 2348 }
2352#endif
2353 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
2354 } 2349 }
2355 /*printk(" %08x", *(u32*)(bus_to_virt (addr))); */ 2350 /*printk(" %08x", *(u32*)(bus_to_virt (addr))); */
2356 /*srb->total_xfer_length = 0; */ 2351 /*srb->total_xfer_length = 0; */
@@ -2509,22 +2504,43 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
2509 SCMD_FIFO_IN); 2504 SCMD_FIFO_IN);
2510 } else { /* write */ 2505 } else { /* write */
2511 int ln = srb->total_xfer_length; 2506 int ln = srb->total_xfer_length;
2507 size_t left_io = srb->total_xfer_length;
2508
2512 if (srb->dcb->sync_period & WIDE_SYNC) 2509 if (srb->dcb->sync_period & WIDE_SYNC)
2513 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 2510 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
2514 CFG2_WIDEFIFO); 2511 CFG2_WIDEFIFO);
2515 dprintkdbg(DBG_PIO,
2516 "data_io_transfer: PIO %i bytes from %p:",
2517 srb->total_xfer_length, srb->virt_addr);
2518 2512
2519 while (srb->total_xfer_length) { 2513 while (left_io) {
2520 if (debug_enabled(DBG_PIO)) 2514 unsigned char *virt, *base = NULL;
2521 printk(" %02x", (unsigned char) *(srb->virt_addr)); 2515 unsigned long flags = 0;
2516 size_t len = left_io;
2517
2518 if (srb->cmd->use_sg) {
2519 size_t offset = srb->request_length - left_io;
2520 local_irq_save(flags);
2521 /* Again, max 4 bytes */
2522 base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
2523 srb->sg_count, &offset, &len);
2524 virt = base + offset;
2525 } else {
2526 virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
2527 len = left_io;
2528 }
2529 left_io -= len;
2530
2531 while (len--) {
2532 if (debug_enabled(DBG_PIO))
2533 printk(" %02x", *virt);
2534
2535 DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *virt++);
2522 2536
2523 pio_trigger(); 2537 sg_subtract_one(srb);
2524 DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 2538 }
2525 *(srb->virt_addr)++);
2526 2539
2527 sg_subtract_one(srb); 2540 if (srb->cmd->use_sg) {
2541 scsi_kunmap_atomic_sg(base);
2542 local_irq_restore(flags);
2543 }
2528 } 2544 }
2529 if (srb->dcb->sync_period & WIDE_SYNC) { 2545 if (srb->dcb->sync_period & WIDE_SYNC) {
2530 if (ln % 2) { 2546 if (ln % 2) {
@@ -3319,7 +3335,6 @@ static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb,
3319 srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address; 3335 srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address;
3320 srb->segment_x[0].length = 3336 srb->segment_x[0].length =
3321 srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length; 3337 srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length;
3322 srb->virt_addr = srb->virt_addr_req;
3323} 3338}
3324 3339
3325 3340
@@ -3332,21 +3347,14 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
3332{ 3347{
3333 u8 tempcnt, status; 3348 u8 tempcnt, status;
3334 struct scsi_cmnd *cmd = srb->cmd; 3349 struct scsi_cmnd *cmd = srb->cmd;
3335 struct ScsiInqData *ptr;
3336 enum dma_data_direction dir = cmd->sc_data_direction; 3350 enum dma_data_direction dir = cmd->sc_data_direction;
3337 3351 int ckc_only = 1;
3338 if (cmd->use_sg) {
3339 struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
3340 ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
3341 } else {
3342 ptr = (struct ScsiInqData *)(cmd->request_buffer);
3343 }
3344 3352
3345 dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid, 3353 dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid,
3346 srb->cmd->device->id, srb->cmd->device->lun); 3354 srb->cmd->device->id, srb->cmd->device->lun);
3347 dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p addr=%p\n", 3355 dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
3348 srb, cmd->use_sg, srb->sg_index, srb->sg_count, 3356 srb, cmd->use_sg, srb->sg_index, srb->sg_count,
3349 cmd->request_buffer, ptr); 3357 cmd->request_buffer);
3350 status = srb->target_status; 3358 status = srb->target_status;
3351 if (srb->flag & AUTO_REQSENSE) { 3359 if (srb->flag & AUTO_REQSENSE) {
3352 dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n"); 3360 dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n");
@@ -3485,29 +3493,47 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
3485 srb->segment_x[0].address, 3493 srb->segment_x[0].address,
3486 cmd->request_bufflen, dir); 3494 cmd->request_bufflen, dir);
3487 } 3495 }
3488 3496 ckc_only = 0;
3489 if ((cmd->result & RES_DID) == 0 && cmd->cmnd[0] == INQUIRY
3490 && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8
3491 && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
3492 dcb->inquiry7 = ptr->Flags;
3493/* Check Error Conditions */ 3497/* Check Error Conditions */
3494 ckc_e: 3498 ckc_e:
3495 3499
3500 if (cmd->cmnd[0] == INQUIRY) {
3501 unsigned char *base = NULL;
3502 struct ScsiInqData *ptr;
3503 unsigned long flags = 0;
3504
3505 if (cmd->use_sg) {
3506 struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
3507 size_t offset = 0, len = sizeof(struct ScsiInqData);
3508
3509 local_irq_save(flags);
3510 base = scsi_kmap_atomic_sg(sg, cmd->use_sg, &offset, &len);
3511 ptr = (struct ScsiInqData *)(base + offset);
3512 } else
3513 ptr = (struct ScsiInqData *)(cmd->request_buffer);
3514
3515 if (!ckc_only && (cmd->result & RES_DID) == 0
3516 && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8
3517 && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
3518 dcb->inquiry7 = ptr->Flags;
3519
3496 /*if( srb->cmd->cmnd[0] == INQUIRY && */ 3520 /*if( srb->cmd->cmnd[0] == INQUIRY && */
3497 /* (host_byte(cmd->result) == DID_OK || status_byte(cmd->result) & CHECK_CONDITION) ) */ 3521 /* (host_byte(cmd->result) == DID_OK || status_byte(cmd->result) & CHECK_CONDITION) ) */
3498 if (cmd->cmnd[0] == INQUIRY && (cmd->result == (DID_OK << 16) 3522 if ((cmd->result == (DID_OK << 16)
3499 || status_byte(cmd-> 3523 || status_byte(cmd->result) &
3500 result) & 3524 CHECK_CONDITION)) {
3501 CHECK_CONDITION)) { 3525 if (!dcb->init_tcq_flag) {
3502 3526 add_dev(acb, dcb, ptr);
3503 if (!dcb->init_tcq_flag) { 3527 dcb->init_tcq_flag = 1;
3504 add_dev(acb, dcb, ptr); 3528 }
3505 dcb->init_tcq_flag = 1;
3506 } 3529 }
3507 3530
3531 if (cmd->use_sg) {
3532 scsi_kunmap_atomic_sg(base);
3533 local_irq_restore(flags);
3534 }
3508 } 3535 }
3509 3536
3510
3511 /* Here is the info for Doug Gilbert's sg3 ... */ 3537 /* Here is the info for Doug Gilbert's sg3 ... */
3512 cmd->resid = srb->total_xfer_length; 3538 cmd->resid = srb->total_xfer_length;
3513 /* This may be interpreted by sb. or not ... */ 3539 /* This may be interpreted by sb. or not ... */
@@ -3713,8 +3739,6 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
3713 srb->xferred = srb->total_xfer_length; 3739 srb->xferred = srb->total_xfer_length;
3714 /* srb->segment_x : a one entry of S/G list table */ 3740 /* srb->segment_x : a one entry of S/G list table */
3715 srb->total_xfer_length = sizeof(cmd->sense_buffer); 3741 srb->total_xfer_length = sizeof(cmd->sense_buffer);
3716 srb->virt_addr_req = srb->virt_addr;
3717 srb->virt_addr = cmd->sense_buffer;
3718 srb->segment_x[0].length = sizeof(cmd->sense_buffer); 3742 srb->segment_x[0].length = sizeof(cmd->sense_buffer);
3719 /* Map sense buffer */ 3743 /* Map sense buffer */
3720 srb->segment_x[0].address = 3744 srb->segment_x[0].address =