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.
10 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/errno.h>
15 #include <linux/timer.h>
16 #include <linux/types.h>
17 #include <linux/string.h>
18 #include <linux/genhd.h>
20 #include <linux/proc_fs.h>
22 #include <asm/system.h>
25 #include <linux/blk.h>
31 #include<linux/stat.h>
33 struct proc_dir_entry proc_scsi_scsi_debug
=
35 PROC_SCSI_SCSI_DEBUG
, 10, "scsi_debug",
36 S_IFDIR
| S_IRUGO
| S_IXUGO
, 2
40 /* A few options that we want selected */
42 #define NR_HOSTS_PRESENT 20
43 #define NR_FAKE_DISKS 6
46 #define DISK_READONLY(TGT) (1)
47 #define DISK_REMOVEABLE(TGT) (1)
49 /* Do not attempt to use a timer to simulate a real disk with latency */
50 /* Only use this in the actual kernel, not in the simulator. */
51 /* #define IMMEDIATE */
53 /* Skip some consistency checking. Good for benchmarking */
55 /* Read return zeros. Undefine for benchmarking */
58 /* Number of real scsi disks that will be detected ahead of time */
59 static int NR_REAL
= -1;
65 #define START_PARTITION 4
67 /* Number of jiffies to wait before completing a command */
69 #define CAPACITY (0x80000)
72 {N_HEAD
, N_HEAD
* N_SECTOR
, 50000, CAPACITY
, 0};
75 #include "scsi_debug.h"
83 #define VERIFY1_DEBUG(RW)
84 #define VERIFY_DEBUG(RW)
87 #define VERIFY1_DEBUG(RW) \
88 if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");}; \
90 if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \
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#"); \
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");}; \
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#"); \
115 if (SCpnt->request.bh->b_dev != SCpnt->request.rq_dev) \
116 panic ("Bad bh target");\
120 typedef void (*done_fct_t
) (Scsi_Cmnd
*);
122 static volatile done_fct_t do_done
[SCSI_DEBUG_MAILBOXES
] = {NULL
,};
124 static void scsi_debug_intr_handle(unsigned long);
126 static struct timer_list timeout
[SCSI_DEBUG_MAILBOXES
];
128 Scsi_Cmnd
*SCint
[SCSI_DEBUG_MAILBOXES
] = {NULL
,};
129 static char SCrst
[SCSI_DEBUG_MAILBOXES
] = {0,};
132 * Semaphore used to simulate bus lockups.
134 static int scsi_debug_lockup
= 0;
136 static char sense_buffer
[128] = {0,};
138 static void scsi_dump(Scsi_Cmnd
* SCpnt
, int flag
)
145 struct scatterlist
*sgpnt
= NULL
;
146 printk("use_sg: %d", SCpnt
->use_sg
);
148 sgpnt
= (struct scatterlist
*) SCpnt
->buffer
;
149 for (i
= 0; i
< SCpnt
->use_sg
; i
++) {
150 lpnt
= (int *) sgpnt
[i
].alt_address
;
151 printk(":%p %p %d\n", sgpnt
[i
].alt_address
, sgpnt
[i
].address
, sgpnt
[i
].length
);
153 printk(" (Alt %x) ", lpnt
[15]);
156 printk("nosg: %p %p %d\n", SCpnt
->request
.buffer
, SCpnt
->buffer
,
158 lpnt
= (int *) SCpnt
->request
.buffer
;
160 printk(" (Alt %x) ", lpnt
[15]);
162 lpnt
= (unsigned int *) SCpnt
;
163 for (i
= 0; i
< sizeof(Scsi_Cmnd
) / 4 + 1; i
++) {
166 printk("%x ", *lpnt
++);
171 lpnt
= (unsigned int *) sgpnt
[0].alt_address
;
172 for (i
= 0; i
< sizeof(Scsi_Cmnd
) / 4 + 1; i
++) {
175 printk("%x ", *lpnt
++);
179 lpnt
= (unsigned int *) sgpnt
[0].address
;
180 for (i
= 0; i
< sizeof(Scsi_Cmnd
) / 4 + 1; i
++) {
183 printk("%x ", *lpnt
++);
187 printk("DMA free %d sectors.\n", scsi_dma_free_sectors
);
190 int scsi_debug_queuecommand(Scsi_Cmnd
* SCpnt
, void (*done
) (Scsi_Cmnd
*))
192 unchar
*cmd
= (unchar
*) SCpnt
->cmnd
;
195 struct buffer_head
*bh
= NULL
;
198 int scsi_debug_errsts
;
199 struct scatterlist
*sgpnt
;
200 int target
= SCpnt
->target
;
201 int bufflen
= SCpnt
->request_bufflen
;
208 * If we are being notified of the mid-level reposessing a command due to timeout,
214 DEB(if (target
>= NR_FAKE_DISKS
) {
215 SCpnt
->result
= DID_TIME_OUT
<< 16; done(SCpnt
); return 0;
219 buff
= (unsigned char *) SCpnt
->request_buffer
;
221 if (target
>= NR_FAKE_DISKS
|| SCpnt
->lun
!= 0) {
222 SCpnt
->result
= DID_NO_CONNECT
<< 16;
226 if (SCrst
[target
] != 0 && !scsi_debug_lockup
) {
228 memset(SCpnt
->sense_buffer
, 0, sizeof(SCpnt
->sense_buffer
));
229 SCpnt
->sense_buffer
[0] = 0x70;
230 SCpnt
->sense_buffer
[2] = UNIT_ATTENTION
;
231 SCpnt
->result
= (CHECK_CONDITION
<< 1);
236 SCSI_LOG_LLQUEUE(3, printk("Request sense...\n"));
240 printk("scsi_debug: Requesting sense buffer (%p %p %p %d):", SCpnt
, buff
, done
, bufflen
);
241 for (i
= 0; i
< 12; i
++)
242 printk("%d ", sense_buffer
[i
]);
246 memset(buff
, 0, bufflen
);
247 memcpy(buff
, sense_buffer
, bufflen
);
248 memset(sense_buffer
, 0, sizeof(sense_buffer
));
252 case ALLOW_MEDIUM_REMOVAL
:
254 SCSI_LOG_LLQUEUE(2, printk("Medium removal inhibited..."));
256 SCSI_LOG_LLQUEUE(2, printk("Medium removal enabled..."));
258 scsi_debug_errsts
= 0;
261 SCSI_LOG_LLQUEUE(3, printk("Inquiry...(%p %d)\n", buff
, bufflen
));
262 memset(buff
, 0, bufflen
);
264 buff
[1] = DISK_REMOVEABLE(target
) ? 0x80 : 0; /* Removable disk */
267 memcpy(&buff
[8], "Foo Inc", 7);
268 memcpy(&buff
[16], "XYZZY", 5);
269 memcpy(&buff
[32], "1", 1);
270 scsi_debug_errsts
= 0;
272 case TEST_UNIT_READY
:
273 SCSI_LOG_LLQUEUE(3, printk("Test unit ready(%p %d)\n", buff
, bufflen
));
275 memset(buff
, 0, bufflen
);
276 scsi_debug_errsts
= 0;
279 SCSI_LOG_LLQUEUE(3, printk("Read Capacity\n"));
281 NR_REAL
= (MINOR(SCpnt
->request
.rq_dev
) >> 4) & 0x0f;
282 memset(buff
, 0, bufflen
);
283 buff
[0] = (CAPACITY
>> 24);
284 buff
[1] = (CAPACITY
>> 16) & 0xff;
285 buff
[2] = (CAPACITY
>> 8) & 0xff;
286 buff
[3] = CAPACITY
& 0xff;
287 buff
[6] = 2; /* 512 byte sectors */
288 scsi_debug_errsts
= 0;
295 if ((*cmd
) == READ_10
)
296 block
= cmd
[5] + (cmd
[4] << 8) + (cmd
[3] << 16) + (cmd
[2] << 24);
298 block
= cmd
[3] + (cmd
[2] << 8) + ((cmd
[1] & 0x1f) << 16);
300 #if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
302 int delay
= SCSI_SETUP_LATENCY
;
304 delay
+= SCpnt
->request
.nr_sectors
* SCSI_DATARATE
;
311 printk("(r%d)", SCpnt
->request
.nr_sectors
);
316 sgpnt
= (struct scatterlist
*) buff
;
317 buff
= sgpnt
[sgcount
].address
;
318 bufflen
= sgpnt
[sgcount
].length
;
319 bh
= SCpnt
->request
.bh
;
321 scsi_debug_errsts
= 0;
324 /* For the speedy test, we do not even want to fill the buffer with anything */
326 memset(buff
, 0, bufflen
);
328 /* If this is block 0, then we want to read the partition table for this
329 * device. Let's make one up */
332 memset(buff
, 0, bufflen
);
333 *((unsigned short *) (buff
+ 510)) = 0xAA55;
334 p
= (struct partition
*) (buff
+ 0x1be);
336 while (starts
[i
+ 1]) {
337 p
->start_sect
= starts
[i
];
338 p
->nr_sects
= starts
[i
+ 1] - starts
[i
];
339 p
->sys_ind
= 0x81; /* Linux partition */
340 p
->head
= (i
== 0 ? 1 : 0);
342 p
->cyl
= starts
[i
] / N_HEAD
/ N_SECTOR
;
343 p
->end_head
= N_HEAD
- 1;
344 p
->end_sector
= N_SECTOR
;
345 p
->end_cyl
= starts
[i
+ 1] / N_HEAD
/ N_SECTOR
;
351 scsi_debug_errsts
= 0;
356 printk("Block %x (%d %d)\n", block
, SCpnt
->request
.nr_sectors
,
357 SCpnt
->request
.current_nr_sectors
);
361 /* Simulate a disk change */
362 if (block
== 0xfff0) {
363 sense_buffer
[0] = 0x70;
364 sense_buffer
[2] = UNIT_ATTENTION
;
372 printk("scsi_debug: Filling sense buffer:");
373 for (i
= 0; i
< 12; i
++)
374 printk("%d ", sense_buffer
[i
]);
378 scsi_debug_errsts
= (COMMAND_COMPLETE
<< 8) | (CHECK_CONDITION
<< 1);
380 } /* End phony disk change code */
384 memcpy(buff
, &target
, sizeof(target
));
385 memcpy(buff
+ sizeof(target
), cmd
, 24);
386 memcpy(buff
+ 60, &block
, sizeof(block
));
387 memcpy(buff
+ 64, SCpnt
, sizeof(Scsi_Cmnd
));
392 memcpy(buff
+ 128, bh
, sizeof(struct buffer_head
));
394 block
+= bufflen
>> 9;
399 panic("Too few blocks for linked request.");
400 buff
= sgpnt
[sgcount
].address
;
401 bufflen
= sgpnt
[sgcount
].length
;
410 if (SCpnt
->use_sg
&& !scsi_debug_errsts
)
419 if ((*cmd
) == WRITE_10
)
420 block
= cmd
[5] + (cmd
[4] << 8) + (cmd
[3] << 16) + (cmd
[2] << 24);
422 block
= cmd
[3] + (cmd
[2] << 8) + ((cmd
[1] & 0x1f) << 16);
424 /* printk("(w%d)",SCpnt->request.nr_sectors); */
426 if ((bufflen
>> 9) != SCpnt
->request
.nr_sectors
)
427 panic("Trying to write wrong number of blocks\n");
428 sgpnt
= (struct scatterlist
*) buff
;
429 buff
= sgpnt
[sgcount
].address
;
432 if (block
!= *((unsigned long *) (buff
+ 60))) {
433 printk("%x %x :", block
, *((unsigned long *) (buff
+ 60)));
435 panic("Bad block written.\n");
438 scsi_debug_errsts
= 0;
442 * Used to detect write protected status.
444 scsi_debug_errsts
= 0;
448 SCSI_LOG_LLQUEUE(3, printk("Unknown command %d\n", *cmd
));
449 SCpnt
->result
= DID_NO_CONNECT
<< 16;
456 for (i
= 0; i
< SCSI_DEBUG_MAILBOXES
; i
++) {
457 if (timeout
[i
].function
== NULL
)
462 * If all of the slots are full, just return 1. The new error handling scheme
463 * allows this, and the mid-level should queue things.
465 if (i
>= SCSI_DEBUG_MAILBOXES
|| timeout
[i
].function
!= 0) {
466 SCSI_LOG_LLQUEUE(1, printk("Command rejected - host busy\n"));
467 restore_flags(flags
);
470 SCSI_LOG_LLQUEUE(1, printk("Command accepted - slot %d\n", i
));
473 if (!scsi_debug_lockup
) {
474 SCpnt
->result
= scsi_debug_errsts
;
475 scsi_debug_intr_handle(i
); /* No timer - do this one right away */
477 restore_flags(flags
);
480 SCpnt
->result
= scsi_debug_errsts
;
481 timeout
[i
].function
= scsi_debug_intr_handle
;
483 timeout
[i
].expires
= jiffies
+ DISK_SPEED
;
487 restore_flags(flags
);
488 add_timer(&timeout
[i
]);
490 panic("scsi_debug_queuecommand: done can't be NULL\n");
493 printk("Sending command (%d %x %d %d)...", i
, done
, timeout
[i
].expires
, jiffies
);
500 volatile static int internal_done_flag
= 0;
501 volatile static int internal_done_errcode
= 0;
502 static void internal_done(Scsi_Cmnd
* SCpnt
)
504 internal_done_errcode
= SCpnt
->result
;
505 ++internal_done_flag
;
508 int scsi_debug_command(Scsi_Cmnd
* SCpnt
)
510 DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n"));
511 scsi_debug_queuecommand(SCpnt
, internal_done
);
513 while (!internal_done_flag
);
514 internal_done_flag
= 0;
515 return internal_done_errcode
;
518 /* A "high" level interrupt handler. This should be called once per jiffy
519 * to simulate a regular scsi disk. We use a timer to do this. */
521 static void scsi_debug_intr_handle(unsigned long indx
)
524 void (*my_done
) (Scsi_Cmnd
*);
530 del_timer(&timeout
[indx
]);
533 SCtmp
= (Scsi_Cmnd
*) SCint
[indx
];
534 my_done
= do_done
[indx
];
535 do_done
[indx
] = NULL
;
536 timeout
[indx
].function
= NULL
;
540 printk("scsi_debug_intr_handle: Unexpected interrupt\n");
544 printk("In intr_handle...");
545 printk("...done %d %x %d %d\n", i
, my_done
, to
, jiffies
);
546 printk("In intr_handle: %d %x %x\n", i
, SCtmp
, my_done
);
551 printk("Called done.\n");
556 int scsi_debug_detect(Scsi_Host_Template
* tpnt
)
560 for (i
= 0; i
< NR_HOSTS_PRESENT
; i
++) {
561 tpnt
->proc_dir
= &proc_scsi_scsi_debug
;
562 scsi_register(tpnt
, 0);
564 return NR_HOSTS_PRESENT
;
567 int scsi_debug_abort(Scsi_Cmnd
* SCpnt
)
571 void (*my_done
) (Scsi_Cmnd
*);
575 DEB(printk("scsi_debug_abort\n"));
577 SCpnt
->result
= SCpnt
->abort_reason
<< 16;
578 for (j
= 0; j
< SCSI_DEBUG_MAILBOXES
; j
++) {
579 if (SCpnt
== SCint
[j
]) {
580 my_done
= do_done
[j
];
587 restore_flags(flags
);
591 return SCSI_ABORT_SNOOZE
;
594 int scsi_debug_biosparam(Disk
* disk
, kdev_t dev
, int *info
)
596 int size
= disk
->capacity
;
599 info
[2] = (size
+ 2047) >> 11;
605 int scsi_debug_reset(Scsi_Cmnd
* SCpnt
, unsigned int why
)
610 void (*my_done
) (Scsi_Cmnd
*);
611 printk("Bus unlocked by reset - %d\n", why
);
612 scsi_debug_lockup
= 0;
613 DEB(printk("scsi_debug_reset called\n"));
614 for (i
= 0; i
< SCSI_DEBUG_MAILBOXES
; i
++) {
615 if (SCint
[i
] == NULL
)
617 SCint
[i
]->result
= DID_RESET
<< 16;
618 my_done
= do_done
[i
];
624 timeout
[i
].function
= NULL
;
625 restore_flags(flags
);
627 return SCSI_RESET_SUCCESS
;
630 const char *scsi_debug_info(void)
632 static char buffer
[] = " "; /* looks nicer without anything here */
636 /* scsi_debug_proc_info
637 * Used if the driver currently has no own support for /proc/scsi
639 int scsi_debug_proc_info(char *buffer
, char **start
, off_t offset
,
640 int length
, int inode
, int inout
)
645 orig_length
= length
;
648 /* First check for the Signature */
649 if (length
>= 10 && strncmp(buffer
, "scsi_debug", 10) == 0) {
653 if (buffer
[length
- 1] == '\n') {
654 buffer
[length
- 1] = '\0';
658 * OK, we are getting some kind of command. Figure out
659 * what we are supposed to do here. Simulate bus lockups
660 * to test our reset capability.
662 if (length
== 6 && strncmp(buffer
, "lockup", length
) == 0) {
663 scsi_debug_lockup
= 1;
666 if (length
== 6 && strncmp(buffer
, "unlock", length
) == 0) {
667 scsi_debug_lockup
= 0;
670 printk("Unknown command:%s (%d)\n", buffer
, length
);
672 printk("Wrong Signature:%10s\n", (char *) buffer
);
678 pos
= len
= sprintf(buffer
,
679 "This driver is not a real scsi driver, but it plays one on TV.\n"
680 "It is very handy for debugging specific problems because you\n"
681 "can simulate a variety of error conditions\n");
686 *start
= buffer
+ (offset
- begin
); /* Start of wanted data */
687 len
-= (offset
- begin
);
695 /* Eventually this will go into an include file, but this will be later */
696 Scsi_Host_Template driver_template
= SCSI_DEBUG
;
698 #include "scsi_module.c"
702 * Overrides for Emacs so that we almost follow Linus's tabbing style.
703 * Emacs will notice this stuff at the end of the file and automatically
704 * adjust the settings for this buffer only. This must remain at the end
706 * ---------------------------------------------------------------------------
709 * c-brace-imaginary-offset: 0
711 * c-argdecl-indent: 4
713 * c-continued-statement-offset: 4
714 * c-continued-brace-offset: 0
715 * indent-tabs-mode: nil