summaryrefslogtreecommitdiffstats
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 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;