File: /usr/src/linux/drivers/scsi/scsi_debug.c

1     /* $Id: scsi_debug.c,v 1.1 1992/07/24 06:27:38 root Exp root $
2      *  linux/kernel/scsi_debug.c
3      *
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      */
9     
10     #include <linux/config.h>
11     #include <linux/module.h>
12     
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>
22     
23     #include <asm/system.h>
24     #include <asm/io.h>
25     
26     #include <linux/blk.h>
27     #include "scsi.h"
28     #include "hosts.h"
29     
30     #include "sd.h"
31     
32     #include<linux/stat.h>
33     
34     /* A few options that we want selected */
35     
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);
44     
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
48     
49     /* Skip some consistency checking.  Good for benchmarking */
50     #define SPEEDY
51     /* Read return zeros. Undefine for benchmarking */
52     #define CLEAR
53     
54     /* Number of real scsi disks that will be detected ahead of time */
55     static int NR_REAL = -1;
56     
57     #define NR_BLK_DEV  12
58     #ifndef MAJOR_NR
59     #define MAJOR_NR 8
60     #endif
61     #define START_PARTITION 4
62     
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)
67     
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;
74     
75     #include "scsi_debug.h"
76     #ifdef DEBUG
77     #define DEB(x) x
78     #else
79     #define DEB(x)
80     #endif
81     
82     #ifdef SPEEDY
83     #define VERIFY1_DEBUG(RW)
84     #define VERIFY_DEBUG(RW)
85     #else
86     
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"); \
99         };
100     
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");\
117         };
118     #endif
119     
120     typedef void (*done_fct_t) (Scsi_Cmnd *);
121     
122     static volatile done_fct_t do_done[SCSI_DEBUG_MAILBOXES] =
123     {NULL,};
124     
125     struct Scsi_Host * SHpnt = NULL;
126     
127     static void scsi_debug_send_self_command(struct Scsi_Host * shpnt);
128     static void scsi_debug_intr_handle(unsigned long);
129     
130     static struct timer_list timeout[SCSI_DEBUG_MAILBOXES];
131     
132     Scsi_Cmnd *SCint[SCSI_DEBUG_MAILBOXES] =
133     {NULL,};
134     static char SCrst[SCSI_DEBUG_MAILBOXES] =
135     {0,};
136     
137     /*
138      * Semaphore used to simulate bus lockups.
139      */
140     static int scsi_debug_lockup = 0;
141     
142     static char sense_buffer[128] =
143     {0,};
144     
145     static void scsi_dump(Scsi_Cmnd * SCpnt, int flag)
146     {
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]);
161     		};
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]);
168     	};
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++);
174     	};
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++);
183     	};
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++);
191     	};
192     	printk("\n");
193     #endif
194     	printk("DMA free %d sectors.\n", scsi_dma_free_sectors);
195     }
196     
197     int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
198     {
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;
213     
214     #ifdef CONFIG_SMP
215             /*
216              * The io_request_lock *must* be held at this point.
217              */
218             if( io_request_lock.lock == 0 )
219             {
220                     printk("Warning - io_request_lock is not held in queuecommand\n");
221             }
222     #endif
223     
224     	/*
225     	 * If we are being notified of the mid-level reposessing a command due to timeout,
226     	 * just return.
227     	 */
228     	if (done == NULL) {
229     		return 0;
230     	}
231     	DEB(if (target >= NR_FAKE_DISKS) {
232     	    SCpnt->result = DID_TIME_OUT << 16; done(SCpnt); return 0;
233     	    }
234     	);
235     
236     	buff = (unsigned char *) SCpnt->request_buffer;
237     
238             /*
239              * If a command comes for the ID of the host itself, just print
240              * a silly message and return.
241              */
242             if( target == 7 ) {
243                     printk("How do you do!\n");
244                     SCpnt->result = 0;
245                     done(SCpnt);
246                     return 0;
247             }
248     
249     	if (target >= NR_FAKE_DISKS || SCpnt->lun != 0) {
250     		SCpnt->result = DID_NO_CONNECT << 16;
251     		done(SCpnt);
252     		return 0;
253     	}
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);
261     	}
262     	switch (*cmd) {
263     	case REQUEST_SENSE:
264     		SCSI_LOG_LLQUEUE(3, printk("Request sense...\n"));
265     #ifndef DEBUG
266     		{
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");
272     		};
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..."));
289     		}
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;
324     
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)
338     		{
339     			int delay = SCSI_SETUP_LATENCY;
340     
341     			delay += SCpnt->request.nr_sectors * SCSI_DATARATE;
342     			if (delay)
343     				usleep(delay);
344     		};
345     #endif
346     
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;
357     		};
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;
375     
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;
379     
380     					p->head = (i == 0 ? 1 : 0);
381     					p->sector = 1 | ((start_cyl >> 8) << 6);
382     					p->cyl = (start_cyl & 0xff);
383     
384     					p->end_head = N_HEAD - 1;
385     					p->end_sector = N_SECTOR | ((end_cyl >> 8) << 6);
386     					p->end_cyl = (end_cyl & 0xff);
387     
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++;
393     				};
394     				if (!npart)
395     					npart = i;
396     				scsi_debug_errsts = 0;
397     				break;
398     			};
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
404     
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;
413     
414     #ifdef DEBUG
415     				{
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");
421     				};
422     #endif
423     				scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
424     				break;
425     			}	/* End phony disk change code */
426     #endif
427     
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;
447     				};
448     			}
449     		} while (nbytes);
450     
451     		SCpnt->result = 0;
452     		(done) (SCpnt);
453     		return 0;
454     
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;
475     		};
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");
481     		};
482     #endif
483     		scsi_debug_errsts = 0;
484     		break;
485     	case MODE_SENSE:
486     		/*
487     		 * Used to detect write protected status.
488     		 */
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;
497     	};
498     
499     	save_flags(flags);
500     	cli();
501     	for (i = 0; i < SCSI_DEBUG_MAILBOXES; i++) {
502     		if (timeout[i].function == NULL)
503     			break;
504     	};
505     
506     	/*
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.
509     	 */
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;
514     	}
515     	SCSI_LOG_LLQUEUE(1, printk("Command accepted - slot %d\n", i));
516     
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 */
523     	}
524     	restore_flags(flags);
525     #else
526     
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;
533     
534     	restore_flags(flags);
535     	add_timer(&timeout[i]);
536     	if (!done)
537     		panic("scsi_debug_queuecommand: done can't be NULL\n");
538     
539     #if 0
540     	printk("Sending command (%d %x %d %d)...", i, done, timeout[i].expires, jiffies);
541     #endif
542     #endif
543     
544     	return 0;
545     }
546     
547     static void scsi_debug_send_self_command(struct Scsi_Host * shpnt)
548     {
549     	static unsigned char cmd[6] =
550     	{TEST_UNIT_READY, 0, 0, 0, 0, 0};
551     
552             Scsi_Request  * scp;
553             Scsi_Device   * sdev;
554             
555             printk("Allocating host dev\n");
556             sdev = scsi_get_host_dev(shpnt);
557             if(sdev==NULL)
558             {
559             	printk("Out of memory.\n");
560             	return;
561             }
562             
563             printk("Got %p. Allocating command block\n", sdev);
564             scp  = scsi_allocate_request(sdev);
565             printk("Got %p\n", scp);
566             
567             if(scp==NULL)
568             {
569             	printk("Out of memory.\n");
570             	goto bail;
571             }
572     
573             scp->sr_cmd_len = 6;
574             scp->sr_use_sg = 0;
575             
576             printk("Sending command\n");
577             scsi_wait_req (scp, (void *) cmd, (void *) NULL,
578                            0, 100, 3);
579             
580             printk("Releasing command\n");
581             scsi_release_request(scp);
582     bail:
583     	printk("Freeing device\n");
584             scsi_free_host_dev(sdev);
585     }
586     
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. */
589     
590     static void scsi_debug_intr_handle(unsigned long indx)
591     {
592     	Scsi_Cmnd *SCtmp;
593     	void (*my_done) (Scsi_Cmnd *);
594     #ifdef DEBUG
595     	int to;
596     #endif
597     
598     #if 0
599     	del_timer(&timeout[indx]);
600     #endif
601     
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;
607     
608     	if (!my_done) {
609     		printk("scsi_debug_intr_handle: Unexpected interrupt\n");
610     		return;
611     	}
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
617     
618     	my_done(SCtmp);
619     #ifdef DEBUG
620     	printk("Called done.\n");
621     #endif
622     }
623     
624     
625     int scsi_debug_detect(Scsi_Host_Template * tpnt)
626     {
627     	int i;
628     
629     	for (i = 0; i < NR_HOSTS_PRESENT; i++) {
630     		tpnt->proc_name = "scsi_debug";	/* Huh? In the loop??? */
631     		scsi_register(tpnt, 0);
632     	}
633     	return NR_HOSTS_PRESENT;
634     }
635     
636     int scsi_debug_abort(Scsi_Cmnd * SCpnt)
637     {
638     #if 0
639     	int j;
640     	void (*my_done) (Scsi_Cmnd *);
641     	unsigned long flags;
642     #endif
643     
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);
657     		};
658     	};
659     #endif
660     	return SCSI_ABORT_SNOOZE;
661     }
662     
663     int scsi_debug_biosparam(Disk * disk, kdev_t dev, int *info)
664     {
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;
672     }
673     
674     int scsi_debug_reset(Scsi_Cmnd * SCpnt, unsigned int why)
675     {
676     	int i;
677     	unsigned long flags;
678     
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);
695     	}
696     	return SCSI_RESET_SUCCESS;
697     }
698     
699     const char *scsi_debug_info(void)
700     {
701     	static char buffer[] = " ";	/* looks nicer without anything here */
702     	return buffer;
703     }
704     
705     /* scsi_debug_proc_info
706      * Used if the driver currently has no own support for /proc/scsi
707      */
708     int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
709     			 int length, int inode, int inout)
710     {
711     	int len, pos, begin;
712     	int orig_length;
713     
714     	orig_length = length;
715     
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;
721     
722     			if (buffer[length - 1] == '\n') {
723     				buffer[length - 1] = '\0';
724     				length--;
725     			}
726     			/*
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.
730     			 */
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;
735                             }
736     			if (length == 6 && strncmp(buffer, "lockup", length) == 0) {
737     				scsi_debug_lockup = 1;
738     				return orig_length;
739     			}
740     			if (length == 6 && strncmp(buffer, "unlock", length) == 0) {
741     				scsi_debug_lockup = 0;
742     				return orig_length;
743     			}
744     			printk("Unknown command:%s (%d)\n", buffer, length);
745     		} else
746     			printk("Wrong Signature:%10s\n", (char *) buffer);
747     
748     		return -EINVAL;
749     
750     	}
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;
759     	}
760     	*start = buffer + (offset - begin);	/* Start of wanted data */
761     	len -= (offset - begin);
762     	if (len > length)
763     		len = length;
764     
765     	return (len);
766     }
767     
768     #ifdef CONFIG_USER_DEBUG
769     /*
770      * This is a hack for the user space emulator.  It allows us to
771      * "insert" arbitrary numbers of additional drivers.
772      */
773     void *scsi_debug_get_handle(void)
774     {
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;
782     }
783     #endif
784     
785     /* Eventually this will go into an include file, but this will be later */
786     static Scsi_Host_Template driver_template = SCSI_DEBUG;
787     
788     #include "scsi_module.c"
789     
790     /*
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:
807      */
808