- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / scsi / scsi_debug.c
blob8a9a6d92eb380cf3bb525e5994e89a65c2c9bd65
1 /* $Id: scsi_debug.c,v 1.1 1992/07/24 06:27:38 root Exp root $
2 * linux/kernel/scsi_debug.c
4 * Copyright (C) 1992 Eric Youngdale
5 * Simulate a host adapter with 2 disks attached. Do a lot of checking
6 * to make sure that we are not getting blocks mixed up, and panic if
7 * anything out of the ordinary is seen.
8 */
10 #include <linux/config.h>
11 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/errno.h>
16 #include <linux/timer.h>
17 #include <linux/types.h>
18 #include <linux/string.h>
19 #include <linux/genhd.h>
20 #include <linux/fs.h>
21 #include <linux/proc_fs.h>
23 #include <asm/system.h>
24 #include <asm/io.h>
26 #include <linux/blk.h>
27 #include "scsi.h"
28 #include "hosts.h"
30 #include "sd.h"
32 #include<linux/stat.h>
34 /* A few options that we want selected */
36 #define NR_HOSTS_PRESENT 1
37 #define NR_FAKE_DISKS 3
38 #define N_HEAD 255
39 #define N_SECTOR 63
40 #define N_CYLINDER 524
41 #define DISK_READONLY(TGT) (0)
42 #define DISK_REMOVEABLE(TGT) (1)
43 #define DEVICE_TYPE(TGT) (TGT == 2 ? TYPE_TAPE : TYPE_DISK);
45 /* Do not attempt to use a timer to simulate a real disk with latency */
46 /* Only use this in the actual kernel, not in the simulator. */
47 #define IMMEDIATE
49 /* Skip some consistency checking. Good for benchmarking */
50 #define SPEEDY
51 /* Read return zeros. Undefine for benchmarking */
52 #define CLEAR
54 /* Number of real scsi disks that will be detected ahead of time */
55 static int NR_REAL = -1;
57 #define NR_BLK_DEV 12
58 #ifndef MAJOR_NR
59 #define MAJOR_NR 8
60 #endif
61 #define START_PARTITION 4
63 /* Time to wait before completing a command */
64 #define DISK_SPEED (HZ/10) /* 100ms */
65 #define CAPACITY (N_HEAD * N_SECTOR * N_CYLINDER)
66 #define SIZE(TGT) (TGT == 2 ? 2248 : 512)
68 static int starts[] =
69 {N_SECTOR,
70 N_HEAD * N_SECTOR, /* Single cylinder */
71 N_HEAD * N_SECTOR * 4,
72 CAPACITY, 0};
73 static int npart = 0;
75 #include "scsi_debug.h"
76 #ifdef DEBUG
77 #define DEB(x) x
78 #else
79 #define DEB(x)
80 #endif
82 #ifdef SPEEDY
83 #define VERIFY1_DEBUG(RW)
84 #define VERIFY_DEBUG(RW)
85 #else
87 #define VERIFY1_DEBUG(RW) \
88 if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");}; \
89 start = 0; \
90 if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \
91 if (bh){ \
92 if (bh->b_size != 1024) panic ("Wrong bh size"); \
93 if ((bh->b_blocknr << 1) + start != block) \
94 { printk("Wrong bh block# %d %d ",bh->b_blocknr, block); \
95 panic ("Wrong bh block#"); \
96 }; \
97 if (bh->b_dev != SCpnt->request.rq_dev) \
98 panic ("Bad bh target"); \
101 #define VERIFY_DEBUG(RW) \
102 if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");}; \
103 start = 0; \
104 if ((MINOR(SCpnt->request.rq_dev) & 0xf) > npart) panic ("Bad partition"); \
105 if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \
106 if (SCpnt->request.cmd != RW) panic ("Wrong operation"); \
107 if (SCpnt->request.sector + start != block) panic("Wrong block."); \
108 if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks"); \
109 if (SCpnt->request.bh){ \
110 if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size"); \
111 if ((SCpnt->request.bh->b_blocknr << 1) + start != block) \
112 { printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block); \
113 panic ("Wrong bh block#"); \
114 }; \
115 if (SCpnt->request.bh->b_dev != SCpnt->request.rq_dev) \
116 panic ("Bad bh target");\
118 #endif
120 typedef void (*done_fct_t) (Scsi_Cmnd *);
122 static volatile done_fct_t do_done[SCSI_DEBUG_MAILBOXES] =
123 {NULL,};
125 struct Scsi_Host * SHpnt = NULL;
127 static void scsi_debug_send_self_command(struct Scsi_Host * shpnt);
128 static void scsi_debug_intr_handle(unsigned long);
130 static struct timer_list timeout[SCSI_DEBUG_MAILBOXES];
132 Scsi_Cmnd *SCint[SCSI_DEBUG_MAILBOXES] =
133 {NULL,};
134 static char SCrst[SCSI_DEBUG_MAILBOXES] =
135 {0,};
138 * Semaphore used to simulate bus lockups.
140 static int scsi_debug_lockup = 0;
142 static char sense_buffer[128] =
143 {0,};
145 static void scsi_dump(Scsi_Cmnd * SCpnt, int flag)
147 int i;
148 #if 0
149 unsigned char *pnt;
150 #endif
151 unsigned int *lpnt;
152 struct scatterlist *sgpnt = NULL;
153 printk("use_sg: %d", SCpnt->use_sg);
154 if (SCpnt->use_sg) {
155 sgpnt = (struct scatterlist *) SCpnt->buffer;
156 for (i = 0; i < SCpnt->use_sg; i++) {
157 lpnt = (int *) sgpnt[i].alt_address;
158 printk(":%p %p %d\n", sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
159 if (lpnt)
160 printk(" (Alt %x) ", lpnt[15]);
162 } else {
163 printk("nosg: %p %p %d\n", SCpnt->request.buffer, SCpnt->buffer,
164 SCpnt->bufflen);
165 lpnt = (int *) SCpnt->request.buffer;
166 if (lpnt)
167 printk(" (Alt %x) ", lpnt[15]);
169 lpnt = (unsigned int *) SCpnt;
170 for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) {
171 if ((i & 7) == 0)
172 printk("\n");
173 printk("%x ", *lpnt++);
175 printk("\n");
176 if (flag == 0)
177 return;
178 lpnt = (unsigned int *) sgpnt[0].alt_address;
179 for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) {
180 if ((i & 7) == 0)
181 printk("\n");
182 printk("%x ", *lpnt++);
184 #if 0
185 printk("\n");
186 lpnt = (unsigned int *) sgpnt[0].address;
187 for (i = 0; i < sizeof(Scsi_Cmnd) / 4 + 1; i++) {
188 if ((i & 7) == 0)
189 printk("\n");
190 printk("%x ", *lpnt++);
192 printk("\n");
193 #endif
194 printk("DMA free %d sectors.\n", scsi_dma_free_sectors);
197 int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
199 unchar *cmd = (unchar *) SCpnt->cmnd;
200 struct partition *p;
201 int block;
202 struct buffer_head *bh = NULL;
203 unsigned char *buff;
204 int nbytes, sgcount;
205 int scsi_debug_errsts;
206 struct scatterlist *sgpnt;
207 int target = SCpnt->target;
208 int bufflen = SCpnt->request_bufflen;
209 unsigned long flags;
210 int i;
211 sgcount = 0;
212 sgpnt = NULL;
214 #ifdef CONFIG_SMP
216 * The io_request_lock *must* be held at this point.
218 if( io_request_lock.lock == 0 )
220 printk("Warning - io_request_lock is not held in queuecommand\n");
222 #endif
225 * If we are being notified of the mid-level reposessing a command due to timeout,
226 * just return.
228 if (done == NULL) {
229 return 0;
231 DEB(if (target >= NR_FAKE_DISKS) {
232 SCpnt->result = DID_TIME_OUT << 16; done(SCpnt); return 0;
236 buff = (unsigned char *) SCpnt->request_buffer;
239 * If a command comes for the ID of the host itself, just print
240 * a silly message and return.
242 if( target == 7 ) {
243 printk("How do you do!\n");
244 SCpnt->result = 0;
245 done(SCpnt);
246 return 0;
249 if (target >= NR_FAKE_DISKS || SCpnt->lun != 0) {
250 SCpnt->result = DID_NO_CONNECT << 16;
251 done(SCpnt);
252 return 0;
254 if (SCrst[target] != 0 && !scsi_debug_lockup) {
255 SCrst[target] = 0;
256 memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
257 SCpnt->sense_buffer[0] = 0x70;
258 SCpnt->sense_buffer[2] = UNIT_ATTENTION;
259 SCpnt->result = (CHECK_CONDITION << 1);
260 done(SCpnt);
262 switch (*cmd) {
263 case REQUEST_SENSE:
264 SCSI_LOG_LLQUEUE(3, printk("Request sense...\n"));
265 #ifndef DEBUG
267 int i;
268 printk("scsi_debug: Requesting sense buffer (%p %p %p %d):", SCpnt, buff, done, bufflen);
269 for (i = 0; i < 12; i++)
270 printk("%d ", sense_buffer[i]);
271 printk("\n");
273 #endif
274 memset(buff, 0, bufflen);
275 memcpy(buff, sense_buffer, bufflen);
276 memset(sense_buffer, 0, sizeof(sense_buffer));
277 SCpnt->result = 0;
278 done(SCpnt);
279 return 0;
280 case START_STOP:
281 SCSI_LOG_LLQUEUE(3, printk("START_STOP\n"));
282 scsi_debug_errsts = 0;
283 break;
284 case ALLOW_MEDIUM_REMOVAL:
285 if (cmd[4]) {
286 SCSI_LOG_LLQUEUE(2, printk("Medium removal inhibited..."));
287 } else {
288 SCSI_LOG_LLQUEUE(2, printk("Medium removal enabled..."));
290 scsi_debug_errsts = 0;
291 break;
292 case INQUIRY:
293 SCSI_LOG_LLQUEUE(3, printk("Inquiry...(%p %d)\n", buff, bufflen));
294 memset(buff, 0, bufflen);
295 buff[0] = DEVICE_TYPE(target);
296 buff[1] = DISK_REMOVEABLE(target) ? 0x80 : 0; /* Removable disk */
297 buff[2] = 1;
298 buff[4] = 33 - 5;
299 memcpy(&buff[8], "Foo Inc", 7);
300 memcpy(&buff[16], "XYZZY", 5);
301 memcpy(&buff[32], "1", 1);
302 scsi_debug_errsts = 0;
303 break;
304 case TEST_UNIT_READY:
305 SCSI_LOG_LLQUEUE(3, printk("Test unit ready(%p %d)\n", buff, bufflen));
306 if (buff)
307 memset(buff, 0, bufflen);
308 scsi_debug_errsts = 0;
309 break;
310 case READ_CAPACITY:
311 SCSI_LOG_LLQUEUE(3, printk("Read Capacity\n"));
312 SHpnt = SCpnt->host;
313 if (NR_REAL < 0)
314 NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f;
315 memset(buff, 0, bufflen);
316 buff[0] = (CAPACITY >> 24);
317 buff[1] = (CAPACITY >> 16) & 0xff;
318 buff[2] = (CAPACITY >> 8) & 0xff;
319 buff[3] = CAPACITY & 0xff;
320 buff[4] = 0;
321 buff[5] = 0;
322 buff[6] = (SIZE(target) >> 8) & 0xff; /* 512 byte sectors */
323 buff[7] = SIZE(target) & 0xff;
325 scsi_debug_errsts = 0;
326 break;
327 case READ_10:
328 case READ_6:
329 #ifdef DEBUG
330 printk("Read...");
331 #endif
332 if ((*cmd) == READ_10)
333 block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
334 else
335 block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
336 VERIFY_DEBUG(READ);
337 #if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
339 int delay = SCSI_SETUP_LATENCY;
341 delay += SCpnt->request.nr_sectors * SCSI_DATARATE;
342 if (delay)
343 usleep(delay);
345 #endif
347 #ifdef DEBUG
348 printk("(r%d)", SCpnt->request.nr_sectors);
349 #endif
350 nbytes = bufflen;
351 if (SCpnt->use_sg) {
352 sgcount = 0;
353 sgpnt = (struct scatterlist *) buff;
354 buff = sgpnt[sgcount].address;
355 bufflen = sgpnt[sgcount].length;
356 bh = SCpnt->request.bh;
358 scsi_debug_errsts = 0;
359 do {
360 VERIFY1_DEBUG(READ);
361 /* For the speedy test, we do not even want to fill the buffer with anything */
362 #ifdef CLEAR
363 memset(buff, 0, bufflen);
364 #endif
365 /* If this is block 0, then we want to read the partition table for this
366 * device. Let's make one up */
367 if (block == 0) {
368 int i;
369 memset(buff, 0, bufflen);
370 *((unsigned short *) (buff + 510)) = 0xAA55;
371 p = (struct partition *) (buff + 0x1be);
372 i = 0;
373 while (starts[i + 1]) {
374 int start_cyl, end_cyl;
376 start_cyl = starts[i] / N_HEAD / N_SECTOR;
377 end_cyl = (starts[i + 1] - 1) / N_HEAD / N_SECTOR;
378 p->boot_ind = 0;
380 p->head = (i == 0 ? 1 : 0);
381 p->sector = 1 | ((start_cyl >> 8) << 6);
382 p->cyl = (start_cyl & 0xff);
384 p->end_head = N_HEAD - 1;
385 p->end_sector = N_SECTOR | ((end_cyl >> 8) << 6);
386 p->end_cyl = (end_cyl & 0xff);
388 p->start_sect = starts[i];
389 p->nr_sects = starts[i + 1] - starts[i];
390 p->sys_ind = 0x81; /* Linux partition */
391 p++;
392 i++;
394 if (!npart)
395 npart = i;
396 scsi_debug_errsts = 0;
397 break;
399 #ifdef DEBUG
400 if (SCpnt->use_sg)
401 printk("Block %x (%d %d)\n", block, SCpnt->request.nr_sectors,
402 SCpnt->request.current_nr_sectors);
403 #endif
405 #if 0
406 /* Simulate a disk change */
407 if (block == 0xfff0) {
408 sense_buffer[0] = 0x70;
409 sense_buffer[2] = UNIT_ATTENTION;
410 starts[0] += 10;
411 starts[1] += 10;
412 starts[2] += 10;
414 #ifdef DEBUG
416 int i;
417 printk("scsi_debug: Filling sense buffer:");
418 for (i = 0; i < 12; i++)
419 printk("%d ", sense_buffer[i]);
420 printk("\n");
422 #endif
423 scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
424 break;
425 } /* End phony disk change code */
426 #endif
428 #ifdef CLEAR
429 memcpy(buff, &target, sizeof(target));
430 memcpy(buff + sizeof(target), cmd, 24);
431 memcpy(buff + 60, &block, sizeof(block));
432 memcpy(buff + 64, SCpnt, sizeof(Scsi_Cmnd));
433 #endif
434 nbytes -= bufflen;
435 if (SCpnt->use_sg) {
436 #ifdef CLEAR
437 memcpy(buff + 128, bh, sizeof(struct buffer_head));
438 #endif
439 block += bufflen >> 9;
440 bh = bh->b_reqnext;
441 sgcount++;
442 if (nbytes) {
443 if (!bh)
444 panic("Too few blocks for linked request.");
445 buff = sgpnt[sgcount].address;
446 bufflen = sgpnt[sgcount].length;
449 } while (nbytes);
451 SCpnt->result = 0;
452 (done) (SCpnt);
453 return 0;
455 if (SCpnt->use_sg && !scsi_debug_errsts)
456 if (bh)
457 scsi_dump(SCpnt, 0);
458 break;
459 case WRITE_10:
460 case WRITE_6:
461 #ifdef DEBUG
462 printk("Write\n");
463 #endif
464 if ((*cmd) == WRITE_10)
465 block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
466 else
467 block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
468 VERIFY_DEBUG(WRITE);
469 /* printk("(w%d)",SCpnt->request.nr_sectors); */
470 if (SCpnt->use_sg) {
471 if ((bufflen >> 9) != SCpnt->request.nr_sectors)
472 panic("Trying to write wrong number of blocks\n");
473 sgpnt = (struct scatterlist *) buff;
474 buff = sgpnt[sgcount].address;
476 #if 0
477 if (block != *((unsigned long *) (buff + 60))) {
478 printk("%x %x :", block, *((unsigned long *) (buff + 60)));
479 scsi_dump(SCpnt, 1);
480 panic("Bad block written.\n");
482 #endif
483 scsi_debug_errsts = 0;
484 break;
485 case MODE_SENSE:
487 * Used to detect write protected status.
489 scsi_debug_errsts = 0;
490 memset(buff, 0, 6);
491 break;
492 default:
493 SCSI_LOG_LLQUEUE(3, printk("Unknown command %d\n", *cmd));
494 SCpnt->result = DID_NO_CONNECT << 16;
495 done(SCpnt);
496 return 0;
499 save_flags(flags);
500 cli();
501 for (i = 0; i < SCSI_DEBUG_MAILBOXES; i++) {
502 if (timeout[i].function == NULL)
503 break;
507 * If all of the slots are full, just return 1. The new error handling scheme
508 * allows this, and the mid-level should queue things.
510 if (i >= SCSI_DEBUG_MAILBOXES || timeout[i].function != 0) {
511 SCSI_LOG_LLQUEUE(1, printk("Command rejected - host busy\n"));
512 restore_flags(flags);
513 return 1;
515 SCSI_LOG_LLQUEUE(1, printk("Command accepted - slot %d\n", i));
517 #ifdef IMMEDIATE
518 if (!scsi_debug_lockup) {
519 SCpnt->result = scsi_debug_errsts;
520 SCint[i] = SCpnt;
521 do_done[i] = done;
522 scsi_debug_intr_handle(i); /* No timer - do this one right away */
524 restore_flags(flags);
525 #else
527 SCpnt->result = scsi_debug_errsts;
528 timeout[i].function = scsi_debug_intr_handle;
529 timeout[i].data = i;
530 timeout[i].expires = jiffies + DISK_SPEED;
531 SCint[i] = SCpnt;
532 do_done[i] = done;
534 restore_flags(flags);
535 add_timer(&timeout[i]);
536 if (!done)
537 panic("scsi_debug_queuecommand: done can't be NULL\n");
539 #if 0
540 printk("Sending command (%d %x %d %d)...", i, done, timeout[i].expires, jiffies);
541 #endif
542 #endif
544 return 0;
547 static void scsi_debug_send_self_command(struct Scsi_Host * shpnt)
549 static unsigned char cmd[6] =
550 {TEST_UNIT_READY, 0, 0, 0, 0, 0};
552 Scsi_Request * scp;
553 Scsi_Device * sdev;
555 printk("Allocating host dev\n");
556 sdev = scsi_get_host_dev(shpnt);
557 if(sdev==NULL)
559 printk("Out of memory.\n");
560 return;
563 printk("Got %p. Allocating command block\n", sdev);
564 scp = scsi_allocate_request(sdev);
565 printk("Got %p\n", scp);
567 if(scp==NULL)
569 printk("Out of memory.\n");
570 goto bail;
573 scp->sr_cmd_len = 6;
574 scp->sr_use_sg = 0;
576 printk("Sending command\n");
577 scsi_wait_req (scp, (void *) cmd, (void *) NULL,
578 0, 100, 3);
580 printk("Releasing command\n");
581 scsi_release_request(scp);
582 bail:
583 printk("Freeing device\n");
584 scsi_free_host_dev(sdev);
587 /* A "high" level interrupt handler. This should be called once per jiffy
588 * to simulate a regular scsi disk. We use a timer to do this. */
590 static void scsi_debug_intr_handle(unsigned long indx)
592 Scsi_Cmnd *SCtmp;
593 void (*my_done) (Scsi_Cmnd *);
594 #ifdef DEBUG
595 int to;
596 #endif
598 #if 0
599 del_timer(&timeout[indx]);
600 #endif
602 SCtmp = (Scsi_Cmnd *) SCint[indx];
603 my_done = do_done[indx];
604 do_done[indx] = NULL;
605 timeout[indx].function = NULL;
606 SCint[indx] = NULL;
608 if (!my_done) {
609 printk("scsi_debug_intr_handle: Unexpected interrupt\n");
610 return;
612 #ifdef DEBUG
613 printk("In intr_handle...");
614 printk("...done %d %x %d %d\n", i, my_done, to, jiffies);
615 printk("In intr_handle: %d %x %x\n", i, SCtmp, my_done);
616 #endif
618 my_done(SCtmp);
619 #ifdef DEBUG
620 printk("Called done.\n");
621 #endif
625 int scsi_debug_detect(Scsi_Host_Template * tpnt)
627 int i;
629 for (i = 0; i < NR_HOSTS_PRESENT; i++) {
630 tpnt->proc_name = "scsi_debug"; /* Huh? In the loop??? */
631 scsi_register(tpnt, 0);
633 return NR_HOSTS_PRESENT;
636 int scsi_debug_abort(Scsi_Cmnd * SCpnt)
638 #if 0
639 int j;
640 void (*my_done) (Scsi_Cmnd *);
641 unsigned long flags;
642 #endif
644 DEB(printk("scsi_debug_abort\n"));
645 #if 0
646 SCpnt->result = SCpnt->abort_reason << 16;
647 for (j = 0; j < SCSI_DEBUG_MAILBOXES; j++) {
648 if (SCpnt == SCint[j]) {
649 my_done = do_done[j];
650 my_done(SCpnt);
651 save_flags(flags);
652 cli();
653 timeout[j] = 0;
654 SCint[j] = NULL;
655 do_done[j] = NULL;
656 restore_flags(flags);
659 #endif
660 return SCSI_ABORT_SNOOZE;
663 int scsi_debug_biosparam(Disk * disk, kdev_t dev, int *info)
665 int size = disk->capacity;
666 info[0] = N_HEAD;
667 info[1] = N_SECTOR;
668 info[2] = N_CYLINDER;
669 if (info[2] >= 1024)
670 info[2] = 1024;
671 return 0;
674 int scsi_debug_reset(Scsi_Cmnd * SCpnt, unsigned int why)
676 int i;
677 unsigned long flags;
679 void (*my_done) (Scsi_Cmnd *);
680 printk("Bus unlocked by reset - %d\n", why);
681 scsi_debug_lockup = 0;
682 DEB(printk("scsi_debug_reset called\n"));
683 for (i = 0; i < SCSI_DEBUG_MAILBOXES; i++) {
684 if (SCint[i] == NULL)
685 continue;
686 SCint[i]->result = DID_RESET << 16;
687 my_done = do_done[i];
688 my_done(SCint[i]);
689 save_flags(flags);
690 cli();
691 SCint[i] = NULL;
692 do_done[i] = NULL;
693 timeout[i].function = NULL;
694 restore_flags(flags);
696 return SCSI_RESET_SUCCESS;
699 const char *scsi_debug_info(void)
701 static char buffer[] = " "; /* looks nicer without anything here */
702 return buffer;
705 /* scsi_debug_proc_info
706 * Used if the driver currently has no own support for /proc/scsi
708 int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
709 int length, int inode, int inout)
711 int len, pos, begin;
712 int orig_length;
714 orig_length = length;
716 if (inout == 1) {
717 /* First check for the Signature */
718 if (length >= 10 && strncmp(buffer, "scsi_debug", 10) == 0) {
719 buffer += 11;
720 length -= 11;
722 if (buffer[length - 1] == '\n') {
723 buffer[length - 1] = '\0';
724 length--;
727 * OK, we are getting some kind of command. Figure out
728 * what we are supposed to do here. Simulate bus lockups
729 * to test our reset capability.
731 if (length == 4 && strncmp(buffer, "test", length) == 0) {
732 printk("Testing send self command %p\n", SHpnt);
733 scsi_debug_send_self_command(SHpnt);
734 return orig_length;
736 if (length == 6 && strncmp(buffer, "lockup", length) == 0) {
737 scsi_debug_lockup = 1;
738 return orig_length;
740 if (length == 6 && strncmp(buffer, "unlock", length) == 0) {
741 scsi_debug_lockup = 0;
742 return orig_length;
744 printk("Unknown command:%s (%d)\n", buffer, length);
745 } else
746 printk("Wrong Signature:%10s\n", (char *) buffer);
748 return -EINVAL;
751 begin = 0;
752 pos = len = sprintf(buffer,
753 "This driver is not a real scsi driver, but it plays one on TV.\n"
754 "It is very handy for debugging specific problems because you\n"
755 "can simulate a variety of error conditions\n");
756 if (pos < offset) {
757 len = 0;
758 begin = pos;
760 *start = buffer + (offset - begin); /* Start of wanted data */
761 len -= (offset - begin);
762 if (len > length)
763 len = length;
765 return (len);
768 #ifdef CONFIG_USER_DEBUG
770 * This is a hack for the user space emulator. It allows us to
771 * "insert" arbitrary numbers of additional drivers.
773 void *scsi_debug_get_handle(void)
775 static Scsi_Host_Template driver_copy = SCSI_DEBUG;
776 void *rtn;
777 rtn = kmalloc(sizeof(driver_copy), GFP_ATOMIC);
778 if(rtn==NULL)
779 return NULL;
780 memcpy(rtn, (void *) &driver_copy, sizeof(driver_copy));
781 return rtn;
783 #endif
785 /* Eventually this will go into an include file, but this will be later */
786 static Scsi_Host_Template driver_template = SCSI_DEBUG;
788 #include "scsi_module.c"
791 * Overrides for Emacs so that we almost follow Linus's tabbing style.
792 * Emacs will notice this stuff at the end of the file and automatically
793 * adjust the settings for this buffer only. This must remain at the end
794 * of the file.
795 * ---------------------------------------------------------------------------
796 * Local variables:
797 * c-indent-level: 4
798 * c-brace-imaginary-offset: 0
799 * c-brace-offset: -4
800 * c-argdecl-indent: 4
801 * c-label-offset: -4
802 * c-continued-statement-offset: 4
803 * c-continued-brace-offset: 0
804 * indent-tabs-mode: nil
805 * tab-width: 8
806 * End: