diff options
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/hp/sim/simscsi.c | 66 |
1 files changed, 15 insertions, 51 deletions
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c index 64248b58f63f..e62694f8ef75 100644 --- a/arch/ia64/hp/sim/simscsi.c +++ b/arch/ia64/hp/sim/simscsi.c | |||
@@ -122,48 +122,22 @@ simscsi_biosparam (struct scsi_device *sdev, struct block_device *n, | |||
122 | } | 122 | } |
123 | 123 | ||
124 | static void | 124 | static void |
125 | simscsi_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset, unsigned long len) | ||
126 | { | ||
127 | struct disk_stat stat; | ||
128 | struct disk_req req; | ||
129 | |||
130 | req.addr = __pa(sc->request_buffer); | ||
131 | req.len = len; /* # of bytes to transfer */ | ||
132 | |||
133 | if (sc->request_bufflen < req.len) | ||
134 | return; | ||
135 | |||
136 | stat.fd = desc[sc->device->id]; | ||
137 | if (DBG) | ||
138 | printk("simscsi_%s @ %lx (off %lx)\n", | ||
139 | mode == SSC_READ ? "read":"write", req.addr, offset); | ||
140 | ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); | ||
141 | ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); | ||
142 | |||
143 | if (stat.count == req.len) { | ||
144 | sc->result = GOOD; | ||
145 | } else { | ||
146 | sc->result = DID_ERROR << 16; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static void | ||
151 | simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset) | 125 | simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset) |
152 | { | 126 | { |
153 | int list_len = sc->use_sg; | 127 | int i; |
154 | struct scatterlist *sl = (struct scatterlist *)sc->request_buffer; | 128 | struct scatterlist *sl; |
155 | struct disk_stat stat; | 129 | struct disk_stat stat; |
156 | struct disk_req req; | 130 | struct disk_req req; |
157 | 131 | ||
158 | stat.fd = desc[sc->device->id]; | 132 | stat.fd = desc[sc->device->id]; |
159 | 133 | ||
160 | while (list_len) { | 134 | scsi_for_each_sg(sc, sl, scsi_sg_count(sc), i) { |
161 | req.addr = __pa(page_address(sl->page) + sl->offset); | 135 | req.addr = __pa(page_address(sl->page) + sl->offset); |
162 | req.len = sl->length; | 136 | req.len = sl->length; |
163 | if (DBG) | 137 | if (DBG) |
164 | printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n", | 138 | printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n", |
165 | mode == SSC_READ ? "read":"write", req.addr, offset, | 139 | mode == SSC_READ ? "read":"write", req.addr, offset, |
166 | list_len, sl->length); | 140 | scsi_sg_count(sc) - i, sl->length); |
167 | ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); | 141 | ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); |
168 | ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); | 142 | ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); |
169 | 143 | ||
@@ -173,8 +147,6 @@ simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset) | |||
173 | return; | 147 | return; |
174 | } | 148 | } |
175 | offset += sl->length; | 149 | offset += sl->length; |
176 | sl++; | ||
177 | list_len--; | ||
178 | } | 150 | } |
179 | sc->result = GOOD; | 151 | sc->result = GOOD; |
180 | } | 152 | } |
@@ -190,10 +162,7 @@ simscsi_readwrite6 (struct scsi_cmnd *sc, int mode) | |||
190 | unsigned long offset; | 162 | unsigned long offset; |
191 | 163 | ||
192 | offset = (((sc->cmnd[1] & 0x1f) << 16) | (sc->cmnd[2] << 8) | sc->cmnd[3])*512; | 164 | offset = (((sc->cmnd[1] & 0x1f) << 16) | (sc->cmnd[2] << 8) | sc->cmnd[3])*512; |
193 | if (sc->use_sg > 0) | 165 | simscsi_sg_readwrite(sc, mode, offset); |
194 | simscsi_sg_readwrite(sc, mode, offset); | ||
195 | else | ||
196 | simscsi_readwrite(sc, mode, offset, sc->cmnd[4]*512); | ||
197 | } | 166 | } |
198 | 167 | ||
199 | static size_t | 168 | static size_t |
@@ -230,26 +199,21 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode) | |||
230 | | ((unsigned long)sc->cmnd[3] << 16) | 199 | | ((unsigned long)sc->cmnd[3] << 16) |
231 | | ((unsigned long)sc->cmnd[4] << 8) | 200 | | ((unsigned long)sc->cmnd[4] << 8) |
232 | | ((unsigned long)sc->cmnd[5] << 0))*512UL; | 201 | | ((unsigned long)sc->cmnd[5] << 0))*512UL; |
233 | if (sc->use_sg > 0) | 202 | simscsi_sg_readwrite(sc, mode, offset); |
234 | simscsi_sg_readwrite(sc, mode, offset); | ||
235 | else | ||
236 | simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); | ||
237 | } | 203 | } |
238 | 204 | ||
239 | static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len) | 205 | static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len) |
240 | { | 206 | { |
241 | 207 | ||
242 | int scatterlen = sc->use_sg; | 208 | int i; |
209 | unsigned thislen; | ||
243 | struct scatterlist *slp; | 210 | struct scatterlist *slp; |
244 | 211 | ||
245 | if (scatterlen == 0) | 212 | scsi_for_each_sg(sc, slp, scsi_sg_count(sc), i) { |
246 | memcpy(sc->request_buffer, buf, len); | 213 | if (!len) |
247 | else for (slp = (struct scatterlist *)sc->request_buffer; | 214 | break; |
248 | scatterlen-- > 0 && len > 0; slp++) { | 215 | thislen = min(len, slp->length); |
249 | unsigned thislen = min(len, slp->length); | ||
250 | |||
251 | memcpy(page_address(slp->page) + slp->offset, buf, thislen); | 216 | memcpy(page_address(slp->page) + slp->offset, buf, thislen); |
252 | slp++; | ||
253 | len -= thislen; | 217 | len -= thislen; |
254 | } | 218 | } |
255 | } | 219 | } |
@@ -275,7 +239,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
275 | if (target_id <= 15 && sc->device->lun == 0) { | 239 | if (target_id <= 15 && sc->device->lun == 0) { |
276 | switch (sc->cmnd[0]) { | 240 | switch (sc->cmnd[0]) { |
277 | case INQUIRY: | 241 | case INQUIRY: |
278 | if (sc->request_bufflen < 35) { | 242 | if (scsi_bufflen(sc) < 35) { |
279 | break; | 243 | break; |
280 | } | 244 | } |
281 | sprintf (fname, "%s%c", simscsi_root, 'a' + target_id); | 245 | sprintf (fname, "%s%c", simscsi_root, 'a' + target_id); |
@@ -328,7 +292,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
328 | break; | 292 | break; |
329 | 293 | ||
330 | case READ_CAPACITY: | 294 | case READ_CAPACITY: |
331 | if (desc[target_id] < 0 || sc->request_bufflen < 8) { | 295 | if (desc[target_id] < 0 || scsi_bufflen(sc) < 8) { |
332 | break; | 296 | break; |
333 | } | 297 | } |
334 | buf = localbuf; | 298 | buf = localbuf; |
@@ -350,7 +314,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
350 | case MODE_SENSE: | 314 | case MODE_SENSE: |
351 | case MODE_SENSE_10: | 315 | case MODE_SENSE_10: |
352 | /* sd.c uses this to determine whether disk does write-caching. */ | 316 | /* sd.c uses this to determine whether disk does write-caching. */ |
353 | simscsi_fillresult(sc, (char *)empty_zero_page, sc->request_bufflen); | 317 | simscsi_fillresult(sc, (char *)empty_zero_page, scsi_bufflen(sc)); |
354 | sc->result = GOOD; | 318 | sc->result = GOOD; |
355 | break; | 319 | break; |
356 | 320 | ||