diff options
Diffstat (limited to 'arch/ia64/hp/sim/simscsi.c')
-rw-r--r-- | arch/ia64/hp/sim/simscsi.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c index 56405dbfd73..a3fe9753113 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) char buf[512]; /* - * This is a bit kludgey: the simulator doesn't provide a direct way of determining - * the disk size, so we do a binary search, assuming a maximum disk size of 4GB. + * This is a bit kludgey: the simulator doesn't provide a + * direct way of determining the disk size, so we do a binary + * search, assuming a maximum disk size of 128GB. */ - for (bit = (4UL << 30)/512; bit != 0; bit >>= 1) { + for (bit = (128UL << 30)/512; bit != 0; bit >>= 1) { req.addr = __pa(&buf); req.len = sizeof(buf); ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ); @@ -225,14 +226,33 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode) { unsigned long offset; - offset = ( (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16) - | (sc->cmnd[4] << 8) | (sc->cmnd[5] << 0))*512; + offset = (((unsigned long)sc->cmnd[2] << 24) + | ((unsigned long)sc->cmnd[3] << 16) + | ((unsigned long)sc->cmnd[4] << 8) + | ((unsigned long)sc->cmnd[5] << 0))*512UL; if (sc->use_sg > 0) simscsi_sg_readwrite(sc, mode, offset); else simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); } +static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len) +{ + + int scatterlen = sc->use_sg; + struct scatterlist *slp; + + if (scatterlen == 0) + memcpy(sc->request_buffer, buf, len); + else for (slp = (struct scatterlist *)sc->buffer; scatterlen-- > 0 && len > 0; slp++) { + unsigned thislen = min(len, slp->length); + + memcpy(page_address(slp->page) + slp->offset, buf, thislen); + slp++; + len -= thislen; + } +} + static int simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) { @@ -240,6 +260,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) char fname[MAX_ROOT_LEN+16]; size_t disk_size; char *buf; + char localbuf[36]; #if DEBUG_SIMSCSI register long sp asm ("sp"); @@ -263,7 +284,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) /* disk doesn't exist... */ break; } - buf = sc->request_buffer; + buf = localbuf; buf[0] = 0; /* magnetic disk */ buf[1] = 0; /* not a removable medium */ buf[2] = 2; /* SCSI-2 compliant device */ @@ -273,6 +294,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) buf[6] = 0; /* reserved */ buf[7] = 0; /* various flags */ memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); + simscsi_fillresult(sc, buf, 36); sc->result = GOOD; break; @@ -304,16 +326,13 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) simscsi_readwrite10(sc, SSC_WRITE); break; - case READ_CAPACITY: if (desc[target_id] < 0 || sc->request_bufflen < 8) { break; } - buf = sc->request_buffer; - + buf = localbuf; disk_size = simscsi_get_disk_size(desc[target_id]); - /* pretend to be a 1GB disk (partition table contains real stuff): */ buf[0] = (disk_size >> 24) & 0xff; buf[1] = (disk_size >> 16) & 0xff; buf[2] = (disk_size >> 8) & 0xff; @@ -323,13 +342,14 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) buf[5] = 0; buf[6] = 2; buf[7] = 0; + simscsi_fillresult(sc, buf, 8); sc->result = GOOD; break; case MODE_SENSE: case MODE_SENSE_10: /* sd.c uses this to determine whether disk does write-caching. */ - memset(sc->request_buffer, 0, 128); + simscsi_fillresult(sc, (char *)empty_zero_page, sc->request_bufflen); sc->result = GOOD; break; |