aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/hp/sim/simscsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/hp/sim/simscsi.c')
-rw-r--r--arch/ia64/hp/sim/simscsi.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index 56405dbfd739..a3fe97531134 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -205,10 +205,11 @@ simscsi_get_disk_size (int fd)
205 char buf[512]; 205 char buf[512];
206 206
207 /* 207 /*
208 * This is a bit kludgey: the simulator doesn't provide a direct way of determining 208 * This is a bit kludgey: the simulator doesn't provide a
209 * the disk size, so we do a binary search, assuming a maximum disk size of 4GB. 209 * direct way of determining the disk size, so we do a binary
210 * search, assuming a maximum disk size of 128GB.
210 */ 211 */
211 for (bit = (4UL << 30)/512; bit != 0; bit >>= 1) { 212 for (bit = (128UL << 30)/512; bit != 0; bit >>= 1) {
212 req.addr = __pa(&buf); 213 req.addr = __pa(&buf);
213 req.len = sizeof(buf); 214 req.len = sizeof(buf);
214 ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ); 215 ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ);
@@ -225,14 +226,33 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
225{ 226{
226 unsigned long offset; 227 unsigned long offset;
227 228
228 offset = ( (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16) 229 offset = (((unsigned long)sc->cmnd[2] << 24)
229 | (sc->cmnd[4] << 8) | (sc->cmnd[5] << 0))*512; 230 | ((unsigned long)sc->cmnd[3] << 16)
231 | ((unsigned long)sc->cmnd[4] << 8)
232 | ((unsigned long)sc->cmnd[5] << 0))*512UL;
230 if (sc->use_sg > 0) 233 if (sc->use_sg > 0)
231 simscsi_sg_readwrite(sc, mode, offset); 234 simscsi_sg_readwrite(sc, mode, offset);
232 else 235 else
233 simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); 236 simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512);
234} 237}
235 238
239static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
240{
241
242 int scatterlen = sc->use_sg;
243 struct scatterlist *slp;
244
245 if (scatterlen == 0)
246 memcpy(sc->request_buffer, buf, len);
247 else for (slp = (struct scatterlist *)sc->buffer; scatterlen-- > 0 && len > 0; slp++) {
248 unsigned thislen = min(len, slp->length);
249
250 memcpy(page_address(slp->page) + slp->offset, buf, thislen);
251 slp++;
252 len -= thislen;
253 }
254}
255
236static int 256static int
237simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) 257simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
238{ 258{
@@ -240,6 +260,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
240 char fname[MAX_ROOT_LEN+16]; 260 char fname[MAX_ROOT_LEN+16];
241 size_t disk_size; 261 size_t disk_size;
242 char *buf; 262 char *buf;
263 char localbuf[36];
243#if DEBUG_SIMSCSI 264#if DEBUG_SIMSCSI
244 register long sp asm ("sp"); 265 register long sp asm ("sp");
245 266
@@ -263,7 +284,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
263 /* disk doesn't exist... */ 284 /* disk doesn't exist... */
264 break; 285 break;
265 } 286 }
266 buf = sc->request_buffer; 287 buf = localbuf;
267 buf[0] = 0; /* magnetic disk */ 288 buf[0] = 0; /* magnetic disk */
268 buf[1] = 0; /* not a removable medium */ 289 buf[1] = 0; /* not a removable medium */
269 buf[2] = 2; /* SCSI-2 compliant device */ 290 buf[2] = 2; /* SCSI-2 compliant device */
@@ -273,6 +294,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
273 buf[6] = 0; /* reserved */ 294 buf[6] = 0; /* reserved */
274 buf[7] = 0; /* various flags */ 295 buf[7] = 0; /* various flags */
275 memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); 296 memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28);
297 simscsi_fillresult(sc, buf, 36);
276 sc->result = GOOD; 298 sc->result = GOOD;
277 break; 299 break;
278 300
@@ -304,16 +326,13 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
304 simscsi_readwrite10(sc, SSC_WRITE); 326 simscsi_readwrite10(sc, SSC_WRITE);
305 break; 327 break;
306 328
307
308 case READ_CAPACITY: 329 case READ_CAPACITY:
309 if (desc[target_id] < 0 || sc->request_bufflen < 8) { 330 if (desc[target_id] < 0 || sc->request_bufflen < 8) {
310 break; 331 break;
311 } 332 }
312 buf = sc->request_buffer; 333 buf = localbuf;
313
314 disk_size = simscsi_get_disk_size(desc[target_id]); 334 disk_size = simscsi_get_disk_size(desc[target_id]);
315 335
316 /* pretend to be a 1GB disk (partition table contains real stuff): */
317 buf[0] = (disk_size >> 24) & 0xff; 336 buf[0] = (disk_size >> 24) & 0xff;
318 buf[1] = (disk_size >> 16) & 0xff; 337 buf[1] = (disk_size >> 16) & 0xff;
319 buf[2] = (disk_size >> 8) & 0xff; 338 buf[2] = (disk_size >> 8) & 0xff;
@@ -323,13 +342,14 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
323 buf[5] = 0; 342 buf[5] = 0;
324 buf[6] = 2; 343 buf[6] = 2;
325 buf[7] = 0; 344 buf[7] = 0;
345 simscsi_fillresult(sc, buf, 8);
326 sc->result = GOOD; 346 sc->result = GOOD;
327 break; 347 break;
328 348
329 case MODE_SENSE: 349 case MODE_SENSE:
330 case MODE_SENSE_10: 350 case MODE_SENSE_10:
331 /* sd.c uses this to determine whether disk does write-caching. */ 351 /* sd.c uses this to determine whether disk does write-caching. */
332 memset(sc->request_buffer, 0, 128); 352 simscsi_fillresult(sc, (char *)empty_zero_page, sc->request_bufflen);
333 sc->result = GOOD; 353 sc->result = GOOD;
334 break; 354 break;
335 355