1/* 2 * Simulated SCSI driver. 3 * 4 * Copyright (C) 1999, 2001-2003 Hewlett-Packard Co 5 * David Mosberger-Tang <davidm@hpl.hp.com> 6 * Stephane Eranian <eranian@hpl.hp.com> 7 * 8 * 02/01/15 David Mosberger Updated for v2.5.1 9 * 99/12/18 David Mosberger Added support for READ10/WRITE10 needed by linux v2.3.33 10 */ 11#include <linux/blkdev.h> 12#include <linux/init.h> 13#include <linux/interrupt.h> 14#include <linux/kernel.h> 15#include <linux/timer.h> 16#include <asm/irq.h> 17#include "hpsim_ssc.h" 18 19#include <scsi/scsi.h> 20#include <scsi/scsi_cmnd.h> 21#include <scsi/scsi_device.h> 22#include <scsi/scsi_host.h> 23 24#define DEBUG_SIMSCSI 0 25 26#define SIMSCSI_REQ_QUEUE_LEN 64 27#define DEFAULT_SIMSCSI_ROOT "/var/ski-disks/sd" 28 29/* Simulator system calls: */ 30 31#define SSC_OPEN 50 32#define SSC_CLOSE 51 33#define SSC_READ 52 34#define SSC_WRITE 53 35#define SSC_GET_COMPLETION 54 36#define SSC_WAIT_COMPLETION 55 37 38#define SSC_WRITE_ACCESS 2 39#define SSC_READ_ACCESS 1 40 41#if DEBUG_SIMSCSI 42 int simscsi_debug; 43# define DBG simscsi_debug 44#else 45# define DBG 0 46#endif 47 48static struct Scsi_Host *host; 49 50static void simscsi_interrupt (unsigned long val); 51static DECLARE_TASKLET(simscsi_tasklet, simscsi_interrupt, 0); 52 53struct disk_req { 54 unsigned long addr; 55 unsigned len; 56}; 57 58struct disk_stat { 59 int fd; 60 unsigned count; 61}; 62 63static int desc[16] = { 64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 65}; 66 67static struct queue_entry { 68 struct scsi_cmnd *sc; 69} queue[SIMSCSI_REQ_QUEUE_LEN]; 70 71static int rd, wr; 72static atomic_t num_reqs = ATOMIC_INIT(0); 73 74/* base name for default disks */ 75static char *simscsi_root = DEFAULT_SIMSCSI_ROOT; 76 77#define MAX_ROOT_LEN 128 78 79/* 80 * used to setup a new base for disk images 81 * to use /foo/bar/disk[a-z] as disk images 82 * you have to specify simscsi=/foo/bar/disk on the command line 83 */ 84static int __init 85simscsi_setup (char *s) 86{ 87 /* XXX Fix me we may need to strcpy() ? */ 88 if (strlen(s) > MAX_ROOT_LEN) { 89 printk(KERN_ERR "simscsi_setup: prefix too long---using default %s\n", 90 simscsi_root); 91 } else 92 simscsi_root = s; 93 return 1; 94} 95 96__setup("simscsi=", simscsi_setup); 97 98static void 99simscsi_interrupt (unsigned long val) 100{ 101 struct scsi_cmnd *sc; 102 103 while ((sc = queue[rd].sc) != NULL) { 104 atomic_dec(&num_reqs); 105 queue[rd].sc = NULL; 106 if (DBG) 107 printk("simscsi_interrupt: done with %ld\n", sc->serial_number); 108 (*sc->scsi_done)(sc); 109 rd = (rd + 1) % SIMSCSI_REQ_QUEUE_LEN; 110 } 111} 112 113static int 114simscsi_biosparam (struct scsi_device *sdev, struct block_device *n, 115 sector_t capacity, int ip[]) 116{ 117 ip[0] = 64; /* heads */ 118 ip[1] = 32; /* sectors */ 119 ip[2] = capacity >> 11; /* cylinders */ 120 return 0; 121} 122 123static void 124simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset) 125{ 126 int i; 127 struct scatterlist *sl; 128 struct disk_stat stat; 129 struct disk_req req; 130 131 stat.fd = desc[sc->device->id]; 132 133 scsi_for_each_sg(sc, sl, scsi_sg_count(sc), i) { 134 req.addr = __pa(sg_virt(sl)); 135 req.len = sl->length; 136 if (DBG) 137 printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n", 138 mode == SSC_READ ? "read":"write", req.addr, offset, 139 scsi_sg_count(sc) - i, sl->length); 140 ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); 141 ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); 142 143 /* should not happen in our case */ 144 if (stat.count != req.len) { 145 sc->result = DID_ERROR << 16; 146 return; 147 } 148 offset += sl->length; 149 } 150 sc->result = GOOD; 151} 152 153/* 154 * function handling both READ_6/WRITE_6 (non-scatter/gather mode) 155 * commands. 156 * Added 02/26/99 S.Eranian 157 */ 158static void 159simscsi_readwrite6 (struct scsi_cmnd *sc, int mode) 160{ 161 unsigned long offset; 162 163 offset = (((sc->cmnd[1] & 0x1f) << 16) | (sc->cmnd[2] << 8) | sc->cmnd[3])*512; 164 simscsi_sg_readwrite(sc, mode, offset); 165} 166 167static size_t 168simscsi_get_disk_size (int fd) 169{ 170 struct disk_stat stat; 171 size_t bit, sectors = 0; 172 struct disk_req req; 173 char buf[512]; 174 175 /* 176 * This is a bit kludgey: the simulator doesn't provide a 177 * direct way of determining the disk size, so we do a binary 178 * search, assuming a maximum disk size of 128GB. 179 */ 180 for (bit = (128UL << 30)/512; bit != 0; bit >>= 1) { 181 req.addr = __pa(&buf); 182 req.len = sizeof(buf); 183 ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ); 184 stat.fd = fd; 185 ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); 186 if (stat.count == sizeof(buf)) 187 sectors |= bit; 188 } 189 return sectors - 1; /* return last valid sector number */ 190} 191 192static void 193simscsi_readwrite10 (struct scsi_cmnd *sc, int mode) 194{ 195 unsigned long offset; 196 197 offset = (((unsigned long)sc->cmnd[2] << 24) 198 | ((unsigned long)sc->cmnd[3] << 16) 199 | ((unsigned long)sc->cmnd[4] << 8) 200 | ((unsigned long)sc->cmnd[5] << 0))*512UL; 201 simscsi_sg_readwrite(sc, mode, offset); 202} 203 204static int 205simscsi_queuecommand_lck (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) 206{ 207 unsigned int target_id = sc->device->id; 208 char fname[MAX_ROOT_LEN+16]; 209 size_t disk_size; 210 char *buf; 211 char localbuf[36]; 212#if DEBUG_SIMSCSI 213 register long sp asm ("sp"); 214 215 if (DBG) 216 printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n", 217 target_id, sc->cmnd[0], sc->serial_number, sp, done); 218#endif 219 220 sc->result = DID_BAD_TARGET << 16; 221 sc->scsi_done = done; 222 if (target_id <= 15 && sc->device->lun == 0) { 223 switch (sc->cmnd[0]) { 224 case INQUIRY: 225 if (scsi_bufflen(sc) < 35) { 226 break; 227 } 228 sprintf (fname, "%s%c", simscsi_root, 'a' + target_id); 229 desc[target_id] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, 230 0, 0, SSC_OPEN); 231 if (desc[target_id] < 0) { 232 /* disk doesn't exist... */ 233 break; 234 } 235 buf = localbuf; 236 buf[0] = 0; /* magnetic disk */ 237 buf[1] = 0; /* not a removable medium */ 238 buf[2] = 2; /* SCSI-2 compliant device */ 239 buf[3] = 2; /* SCSI-2 response data format */ 240 buf[4] = 31; /* additional length (bytes) */ 241 buf[5] = 0; /* reserved */ 242 buf[6] = 0; /* reserved */ 243 buf[7] = 0; /* various flags */ 244 memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); 245 scsi_sg_copy_from_buffer(sc, buf, 36); 246 sc->result = GOOD; 247 break; 248 249 case TEST_UNIT_READY: 250 sc->result = GOOD; 251 break; 252 253 case READ_6: 254 if (desc[target_id] < 0 ) 255 break; 256 simscsi_readwrite6(sc, SSC_READ); 257 break; 258 259 case READ_10: 260 if (desc[target_id] < 0 ) 261 break; 262 simscsi_readwrite10(sc, SSC_READ); 263 break; 264 265 case WRITE_6: 266 if (desc[target_id] < 0) 267 break; 268 simscsi_readwrite6(sc, SSC_WRITE); 269 break; 270 271 case WRITE_10: 272 if (desc[target_id] < 0) 273 break; 274 simscsi_readwrite10(sc, SSC_WRITE); 275 break; 276 277 case READ_CAPACITY: 278 if (desc[target_id] < 0 || scsi_bufflen(sc) < 8) { 279 break; 280 } 281 buf = localbuf; 282 disk_size = simscsi_get_disk_size(desc[target_id]); 283 284 buf[0] = (disk_size >> 24) & 0xff; 285 buf[1] = (disk_size >> 16) & 0xff; 286 buf[2] = (disk_size >> 8) & 0xff; 287 buf[3] = (disk_size >> 0) & 0xff; 288 /* set block size of 512 bytes: */ 289 buf[4] = 0; 290 buf[5] = 0; 291 buf[6] = 2; 292 buf[7] = 0; 293 scsi_sg_copy_from_buffer(sc, buf, 8); 294 sc->result = GOOD; 295 break; 296 297 case MODE_SENSE: 298 case MODE_SENSE_10: 299 /* sd.c uses this to determine whether disk does write-caching. */ 300 scsi_sg_copy_from_buffer(sc, (char *)empty_zero_page, 301 PAGE_SIZE); 302 sc->result = GOOD; 303 break; 304 305 case START_STOP: 306 printk(KERN_ERR "START_STOP\n"); 307 break; 308 309 default: 310 panic("simscsi: unknown SCSI command %u\n", sc->cmnd[0]); 311 } 312 } 313 if (sc->result == DID_BAD_TARGET) { 314 sc->result |= DRIVER_SENSE << 24; 315 sc->sense_buffer[0] = 0x70; 316 sc->sense_buffer[2] = 0x00; 317 } 318 if (atomic_read(&num_reqs) >= SIMSCSI_REQ_QUEUE_LEN) { 319 panic("Attempt to queue command while command is pending!!"); 320 } 321 atomic_inc(&num_reqs); 322 queue[wr].sc = sc; 323 wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN; 324 325 tasklet_schedule(&simscsi_tasklet); 326 return 0; 327} 328 329static DEF_SCSI_QCMD(simscsi_queuecommand) 330 331static int 332simscsi_host_reset (struct scsi_cmnd *sc) 333{ 334 printk(KERN_ERR "simscsi_host_reset: not implemented\n"); 335 return 0; 336} 337 338static struct scsi_host_template driver_template = { 339 .name = "simulated SCSI host adapter", 340 .proc_name = "simscsi", 341 .queuecommand = simscsi_queuecommand, 342 .eh_host_reset_handler = simscsi_host_reset, 343 .bios_param = simscsi_biosparam, 344 .can_queue = SIMSCSI_REQ_QUEUE_LEN, 345 .this_id = -1, 346 .sg_tablesize = SG_ALL, 347 .max_sectors = 1024, 348 .cmd_per_lun = SIMSCSI_REQ_QUEUE_LEN, 349 .use_clustering = DISABLE_CLUSTERING, 350}; 351 352static int __init 353simscsi_init(void) 354{ 355 int error; 356 357 host = scsi_host_alloc(&driver_template, 0); 358 if (!host) 359 return -ENOMEM; 360 361 error = scsi_add_host(host, NULL); 362 if (error) 363 goto free_host; 364 scsi_scan_host(host); 365 return 0; 366 367 free_host: 368 scsi_host_put(host); 369 return error; 370} 371 372static void __exit 373simscsi_exit(void) 374{ 375 scsi_remove_host(host); 376 scsi_host_put(host); 377} 378 379module_init(simscsi_init); 380module_exit(simscsi_exit); 381