diff options
Diffstat (limited to 'drivers/scsi/arm')
-rw-r--r-- | drivers/scsi/arm/acornscsi.c | 14 | ||||
-rw-r--r-- | drivers/scsi/arm/scsi.h | 87 |
2 files changed, 58 insertions, 43 deletions
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index eceacf6d49ea..3bedf2466bd1 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c | |||
@@ -1790,7 +1790,7 @@ int acornscsi_starttransfer(AS_Host *host) | |||
1790 | return 0; | 1790 | return 0; |
1791 | } | 1791 | } |
1792 | 1792 | ||
1793 | residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred; | 1793 | residual = scsi_bufflen(host->SCpnt) - host->scsi.SCp.scsi_xferred; |
1794 | 1794 | ||
1795 | sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); | 1795 | sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); |
1796 | sbic_arm_writenext(host->scsi.io_port, residual >> 16); | 1796 | sbic_arm_writenext(host->scsi.io_port, residual >> 16); |
@@ -2270,7 +2270,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) | |||
2270 | case 0x4b: /* -> PHASE_STATUSIN */ | 2270 | case 0x4b: /* -> PHASE_STATUSIN */ |
2271 | case 0x8b: /* -> PHASE_STATUSIN */ | 2271 | case 0x8b: /* -> PHASE_STATUSIN */ |
2272 | /* DATA IN -> STATUS */ | 2272 | /* DATA IN -> STATUS */ |
2273 | host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - | 2273 | host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - |
2274 | acornscsi_sbic_xfcount(host); | 2274 | acornscsi_sbic_xfcount(host); |
2275 | acornscsi_dma_stop(host); | 2275 | acornscsi_dma_stop(host); |
2276 | acornscsi_readstatusbyte(host); | 2276 | acornscsi_readstatusbyte(host); |
@@ -2281,7 +2281,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) | |||
2281 | case 0x4e: /* -> PHASE_MSGOUT */ | 2281 | case 0x4e: /* -> PHASE_MSGOUT */ |
2282 | case 0x8e: /* -> PHASE_MSGOUT */ | 2282 | case 0x8e: /* -> PHASE_MSGOUT */ |
2283 | /* DATA IN -> MESSAGE OUT */ | 2283 | /* DATA IN -> MESSAGE OUT */ |
2284 | host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - | 2284 | host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - |
2285 | acornscsi_sbic_xfcount(host); | 2285 | acornscsi_sbic_xfcount(host); |
2286 | acornscsi_dma_stop(host); | 2286 | acornscsi_dma_stop(host); |
2287 | acornscsi_sendmessage(host); | 2287 | acornscsi_sendmessage(host); |
@@ -2291,7 +2291,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) | |||
2291 | case 0x4f: /* message in */ | 2291 | case 0x4f: /* message in */ |
2292 | case 0x8f: /* message in */ | 2292 | case 0x8f: /* message in */ |
2293 | /* DATA IN -> MESSAGE IN */ | 2293 | /* DATA IN -> MESSAGE IN */ |
2294 | host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - | 2294 | host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - |
2295 | acornscsi_sbic_xfcount(host); | 2295 | acornscsi_sbic_xfcount(host); |
2296 | acornscsi_dma_stop(host); | 2296 | acornscsi_dma_stop(host); |
2297 | acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ | 2297 | acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ |
@@ -2319,7 +2319,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) | |||
2319 | case 0x4b: /* -> PHASE_STATUSIN */ | 2319 | case 0x4b: /* -> PHASE_STATUSIN */ |
2320 | case 0x8b: /* -> PHASE_STATUSIN */ | 2320 | case 0x8b: /* -> PHASE_STATUSIN */ |
2321 | /* DATA OUT -> STATUS */ | 2321 | /* DATA OUT -> STATUS */ |
2322 | host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - | 2322 | host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - |
2323 | acornscsi_sbic_xfcount(host); | 2323 | acornscsi_sbic_xfcount(host); |
2324 | acornscsi_dma_stop(host); | 2324 | acornscsi_dma_stop(host); |
2325 | acornscsi_dma_adjust(host); | 2325 | acornscsi_dma_adjust(host); |
@@ -2331,7 +2331,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) | |||
2331 | case 0x4e: /* -> PHASE_MSGOUT */ | 2331 | case 0x4e: /* -> PHASE_MSGOUT */ |
2332 | case 0x8e: /* -> PHASE_MSGOUT */ | 2332 | case 0x8e: /* -> PHASE_MSGOUT */ |
2333 | /* DATA OUT -> MESSAGE OUT */ | 2333 | /* DATA OUT -> MESSAGE OUT */ |
2334 | host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - | 2334 | host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - |
2335 | acornscsi_sbic_xfcount(host); | 2335 | acornscsi_sbic_xfcount(host); |
2336 | acornscsi_dma_stop(host); | 2336 | acornscsi_dma_stop(host); |
2337 | acornscsi_dma_adjust(host); | 2337 | acornscsi_dma_adjust(host); |
@@ -2342,7 +2342,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) | |||
2342 | case 0x4f: /* message in */ | 2342 | case 0x4f: /* message in */ |
2343 | case 0x8f: /* message in */ | 2343 | case 0x8f: /* message in */ |
2344 | /* DATA OUT -> MESSAGE IN */ | 2344 | /* DATA OUT -> MESSAGE IN */ |
2345 | host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - | 2345 | host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - |
2346 | acornscsi_sbic_xfcount(host); | 2346 | acornscsi_sbic_xfcount(host); |
2347 | acornscsi_dma_stop(host); | 2347 | acornscsi_dma_stop(host); |
2348 | acornscsi_dma_adjust(host); | 2348 | acornscsi_dma_adjust(host); |
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h index bb6550e31926..138a521ba1a8 100644 --- a/drivers/scsi/arm/scsi.h +++ b/drivers/scsi/arm/scsi.h | |||
@@ -18,17 +18,32 @@ | |||
18 | * The scatter-gather list handling. This contains all | 18 | * The scatter-gather list handling. This contains all |
19 | * the yucky stuff that needs to be fixed properly. | 19 | * the yucky stuff that needs to be fixed properly. |
20 | */ | 20 | */ |
21 | |||
22 | /* | ||
23 | * copy_SCp_to_sg() Assumes contiguous allocation at @sg of at-most @max | ||
24 | * entries of uninitialized memory. SCp is from scsi-ml and has a valid | ||
25 | * (possibly chained) sg-list | ||
26 | */ | ||
21 | static inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max) | 27 | static inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max) |
22 | { | 28 | { |
23 | int bufs = SCp->buffers_residual; | 29 | int bufs = SCp->buffers_residual; |
24 | 30 | ||
31 | /* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg(). | ||
32 | * and to remove this BUG_ON. Use min() in-its-place | ||
33 | */ | ||
25 | BUG_ON(bufs + 1 > max); | 34 | BUG_ON(bufs + 1 > max); |
26 | 35 | ||
27 | sg_set_buf(sg, SCp->ptr, SCp->this_residual); | 36 | sg_set_buf(sg, SCp->ptr, SCp->this_residual); |
28 | 37 | ||
29 | if (bufs) | 38 | if (bufs) { |
30 | memcpy(sg + 1, SCp->buffer + 1, | 39 | struct scatterlist *src_sg; |
31 | sizeof(struct scatterlist) * bufs); | 40 | unsigned i; |
41 | |||
42 | for_each_sg(sg_next(SCp->buffer), src_sg, bufs, i) | ||
43 | *(++sg) = *src_sg; | ||
44 | sg_mark_end(sg); | ||
45 | } | ||
46 | |||
32 | return bufs + 1; | 47 | return bufs + 1; |
33 | } | 48 | } |
34 | 49 | ||
@@ -36,7 +51,7 @@ static inline int next_SCp(struct scsi_pointer *SCp) | |||
36 | { | 51 | { |
37 | int ret = SCp->buffers_residual; | 52 | int ret = SCp->buffers_residual; |
38 | if (ret) { | 53 | if (ret) { |
39 | SCp->buffer++; | 54 | SCp->buffer = sg_next(SCp->buffer); |
40 | SCp->buffers_residual--; | 55 | SCp->buffers_residual--; |
41 | SCp->ptr = sg_virt(SCp->buffer); | 56 | SCp->ptr = sg_virt(SCp->buffer); |
42 | SCp->this_residual = SCp->buffer->length; | 57 | SCp->this_residual = SCp->buffer->length; |
@@ -68,46 +83,46 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt) | |||
68 | { | 83 | { |
69 | memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); | 84 | memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); |
70 | 85 | ||
71 | if (SCpnt->use_sg) { | 86 | if (scsi_bufflen(SCpnt)) { |
72 | unsigned long len = 0; | 87 | unsigned long len = 0; |
73 | int buf; | ||
74 | 88 | ||
75 | SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; | 89 | SCpnt->SCp.buffer = scsi_sglist(SCpnt); |
76 | SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; | 90 | SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1; |
77 | SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer); | 91 | SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer); |
78 | SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; | 92 | SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; |
79 | SCpnt->SCp.phase = SCpnt->request_bufflen; | 93 | SCpnt->SCp.phase = scsi_bufflen(SCpnt); |
80 | 94 | ||
81 | #ifdef BELT_AND_BRACES | 95 | #ifdef BELT_AND_BRACES |
82 | /* | 96 | { /* |
83 | * Calculate correct buffer length. Some commands | 97 | * Calculate correct buffer length. Some commands |
84 | * come in with the wrong request_bufflen. | 98 | * come in with the wrong scsi_bufflen. |
85 | */ | 99 | */ |
86 | for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) | 100 | struct scatterlist *sg; |
87 | len += SCpnt->SCp.buffer[buf].length; | 101 | unsigned i, sg_count = scsi_sg_count(SCpnt); |
88 | 102 | ||
89 | if (SCpnt->request_bufflen != len) | 103 | scsi_for_each_sg(SCpnt, sg, sg_count, i) |
90 | printk(KERN_WARNING "scsi%d.%c: bad request buffer " | 104 | len += sg->length; |
91 | "length %d, should be %ld\n", SCpnt->device->host->host_no, | 105 | |
92 | '0' + SCpnt->device->id, SCpnt->request_bufflen, len); | 106 | if (scsi_bufflen(SCpnt) != len) { |
93 | SCpnt->request_bufflen = len; | 107 | printk(KERN_WARNING |
108 | "scsi%d.%c: bad request buffer " | ||
109 | "length %d, should be %ld\n", | ||
110 | SCpnt->device->host->host_no, | ||
111 | '0' + SCpnt->device->id, | ||
112 | scsi_bufflen(SCpnt), len); | ||
113 | /* | ||
114 | * FIXME: Totaly naive fixup. We should abort | ||
115 | * with error | ||
116 | */ | ||
117 | SCpnt->SCp.phase = | ||
118 | min_t(unsigned long, len, | ||
119 | scsi_bufflen(SCpnt)); | ||
120 | } | ||
121 | } | ||
94 | #endif | 122 | #endif |
95 | } else { | 123 | } else { |
96 | SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; | ||
97 | SCpnt->SCp.this_residual = SCpnt->request_bufflen; | ||
98 | SCpnt->SCp.phase = SCpnt->request_bufflen; | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * If the upper SCSI layers pass a buffer, but zero length, | ||
103 | * we aren't interested in the buffer pointer. | ||
104 | */ | ||
105 | if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { | ||
106 | #if 0 //def BELT_AND_BRACES | ||
107 | printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " | ||
108 | "command ", SCpnt->host->host_no, '0' + SCpnt->target); | ||
109 | __scsi_print_command(SCpnt->cmnd); | ||
110 | #endif | ||
111 | SCpnt->SCp.ptr = NULL; | 124 | SCpnt->SCp.ptr = NULL; |
125 | SCpnt->SCp.this_residual = 0; | ||
126 | SCpnt->SCp.phase = 0; | ||
112 | } | 127 | } |
113 | } | 128 | } |