This source file includes following definitions.
- scsi_dump
- scsi_debug_queuecommand
- internal_done
- scsi_debug_command
- scsi_debug_intr_handle
- scsi_debug_detect
- scsi_debug_abort
- scsi_debug_biosparam
- scsi_debug_reset
- scsi_debug_info
- scsi_debug_proc_info
1
2
3
4
5
6
7
8
9
10 #include <linux/module.h>
11
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/errno.h>
15 #include <linux/timer.h>
16 #include <linux/head.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 #ifdef MODULE
27 #include <linux/module.h>
28 #endif
29
30 #include <linux/blk.h>
31 #include "scsi.h"
32 #include "hosts.h"
33
34 #include "sd.h"
35
36 #include<linux/stat.h>
37
38 struct proc_dir_entry proc_scsi_scsi_debug = {
39 PROC_SCSI_SCSI_DEBUG, 10, "scsi_debug",
40 S_IFDIR | S_IRUGO | S_IXUGO, 2
41 };
42
43
44
45
46
47
48 #define IMMEDIATE
49
50
51 #define SPEEDY
52
53
54 static int NR_REAL=-1;
55
56 #define NR_BLK_DEV 12
57 #ifndef MAJOR_NR
58 #define MAJOR_NR 8
59 #endif
60 #define START_PARTITION 4
61 #define SCSI_DEBUG_TIMER 20
62
63 #define DISK_SPEED 10
64 #define CAPACITY (0x80000)
65
66 static int starts[] = {4, 1000, 50000, CAPACITY, 0};
67 static int npart = 0;
68
69 #include "scsi_debug.h"
70 #ifdef DEBUG
71 #define DEB(x) x
72 #else
73 #define DEB(x)
74 #endif
75
76 #ifdef SPEEDY
77 #define VERIFY1_DEBUG(RW) 1
78 #define VERIFY_DEBUG(RW) 1
79 #else
80
81 #define VERIFY1_DEBUG(RW) \
82 if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");}; \
83 start = 0; \
84 if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \
85 if (bh){ \
86 if (bh->b_size != 1024) panic ("Wrong bh size"); \
87 if ((bh->b_blocknr << 1) + start != block) \
88 { printk("Wrong bh block# %d %d ",bh->b_blocknr, block); \
89 panic ("Wrong bh block#"); \
90 }; \
91 if (bh->b_dev != SCpnt->request.rq_dev) \
92 panic ("Bad bh target"); \
93 };
94
95 #define VERIFY_DEBUG(RW) \
96 if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");}; \
97 start = 0; \
98 if ((MINOR(SCpnt->request.rq_dev) & 0xf) > npart) panic ("Bad partition"); \
99 if ((MINOR(SCpnt->request.rq_dev) & 0xf) != 0) start = starts[(MINOR(SCpnt->request.rq_dev) & 0xf) - 1]; \
100 if (SCpnt->request.cmd != RW) panic ("Wrong operation"); \
101 if (SCpnt->request.sector + start != block) panic("Wrong block."); \
102 if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks"); \
103 if (SCpnt->request.bh){ \
104 if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size"); \
105 if ((SCpnt->request.bh->b_blocknr << 1) + start != block) \
106 { printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block); \
107 panic ("Wrong bh block#"); \
108 }; \
109 if (SCpnt->request.bh->b_dev != SCpnt->request.rq_dev) \
110 panic ("Bad bh target");\
111 };
112 #endif
113
114 static volatile void (*do_done[SCSI_DEBUG_MAILBOXES])(Scsi_Cmnd *) = {NULL, };
115 extern void scsi_debug_interrupt();
116
117 volatile Scsi_Cmnd * SCint[SCSI_DEBUG_MAILBOXES] = {NULL,};
118 static char SCrst[SCSI_DEBUG_MAILBOXES] = {0,};
119 static volatile unsigned int timeout[8] ={0,};
120
121
122
123
124 static int scsi_debug_lockup = 0;
125
126 static char sense_buffer[128] = {0,};
127
128 static void scsi_dump(Scsi_Cmnd * SCpnt, int flag){
129 int i;
130 #if 0
131 unsigned char * pnt;
132 #endif
133 unsigned int * lpnt;
134 struct scatterlist * sgpnt = NULL;
135 printk("use_sg: %d",SCpnt->use_sg);
136 if (SCpnt->use_sg){
137 sgpnt = (struct scatterlist *) SCpnt->buffer;
138 for(i=0; i<SCpnt->use_sg; i++) {
139 lpnt = (int *) sgpnt[i].alt_address;
140 printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
141 if (lpnt) printk(" (Alt %x) ",lpnt[15]);
142 };
143 } else {
144 printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
145 SCpnt->bufflen);
146 lpnt = (int *) SCpnt->request.buffer;
147 if (lpnt) printk(" (Alt %x) ",lpnt[15]);
148 };
149 lpnt = (unsigned int *) SCpnt;
150 for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
151 if ((i & 7) == 0) printk("\n");
152 printk("%x ",*lpnt++);
153 };
154 printk("\n");
155 if (flag == 0) return;
156 lpnt = (unsigned int *) sgpnt[0].alt_address;
157 for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
158 if ((i & 7) == 0) printk("\n");
159 printk("%x ",*lpnt++);
160 };
161 #if 0
162 printk("\n");
163 lpnt = (unsigned int *) sgpnt[0].address;
164 for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
165 if ((i & 7) == 0) printk("\n");
166 printk("%x ",*lpnt++);
167 };
168 printk("\n");
169 #endif
170 printk("DMA free %d sectors.\n", dma_free_sectors);
171 }
172
173 int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
174 {
175 unchar *cmd = (unchar *) SCpnt->cmnd;
176 struct partition * p;
177 int block, start;
178 struct buffer_head * bh = NULL;
179 unsigned char * buff;
180 int nbytes, sgcount;
181 int scsi_debug_errsts;
182 struct scatterlist * sgpnt;
183 int target = SCpnt->target;
184 int bufflen = SCpnt->request_bufflen;
185 unsigned long flags;
186 int i;
187 sgcount = 0;
188 sgpnt = NULL;
189
190 DEB(if (target > 1) { SCpnt->result = DID_TIME_OUT << 16;done(SCpnt);return 0;});
191
192 buff = (unsigned char *) SCpnt->request_buffer;
193
194 if(target>=1 || SCpnt->lun != 0) {
195 SCpnt->result = DID_NO_CONNECT << 16;
196 done(SCpnt);
197 return 0;
198 };
199
200 if( SCrst[target] != 0 && !scsi_debug_lockup )
201 {
202 SCrst[target] = 0;
203 memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
204 SCpnt->sense_buffer[0] = 0x70;
205 SCpnt->sense_buffer[2] = UNIT_ATTENTION;
206 SCpnt->result = (CHECK_CONDITION << 1);
207 done(SCpnt);
208 }
209 switch(*cmd){
210 case REQUEST_SENSE:
211 printk("Request sense...\n");
212 #ifndef DEBUG
213 {
214 int i;
215 printk("scsi_debug: Requesting sense buffer (%x %x %x %d):", SCpnt, buff, done, bufflen);
216 for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
217 printk("\n");
218 };
219 #endif
220 memset(buff, 0, bufflen);
221 memcpy(buff, sense_buffer, bufflen);
222 memset(sense_buffer, 0, sizeof(sense_buffer));
223 SCpnt->result = 0;
224 done(SCpnt);
225 return 0;
226 case ALLOW_MEDIUM_REMOVAL:
227 if(cmd[4]) printk("Medium removal inhibited...");
228 else printk("Medium removal enabled...");
229 scsi_debug_errsts = 0;
230 break;
231 case INQUIRY:
232 printk("Inquiry...(%x %d)\n", buff, bufflen);
233 memset(buff, 0, bufflen);
234 buff[0] = TYPE_DISK;
235 buff[1] = 0x80;
236 buff[2] = 1;
237 buff[4] = 33 - 5;
238 memcpy(&buff[8],"Foo Inc",7);
239 memcpy(&buff[16],"XYZZY",5);
240 memcpy(&buff[32],"1",1);
241 scsi_debug_errsts = 0;
242 break;
243 case TEST_UNIT_READY:
244 printk("Test unit ready(%x %d)\n", buff, bufflen);
245 if (buff)
246 memset(buff, 0, bufflen);
247 scsi_debug_errsts = 0;
248 break;
249 case READ_CAPACITY:
250 printk("Read Capacity\n");
251 if(NR_REAL < 0) NR_REAL = (MINOR(SCpnt->request.rq_dev) >> 4) & 0x0f;
252 memset(buff, 0, bufflen);
253 buff[0] = (CAPACITY >> 24);
254 buff[1] = (CAPACITY >> 16) & 0xff;
255 buff[2] = (CAPACITY >> 8) & 0xff;
256 buff[3] = CAPACITY & 0xff;
257 buff[6] = 2;
258 scsi_debug_errsts = 0;
259 break;
260 case READ_10:
261 case READ_6:
262 #ifdef DEBUG
263 printk("Read...");
264 #endif
265 if ((*cmd) == READ_10)
266 block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
267 else
268 block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
269 VERIFY_DEBUG(READ);
270 #if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
271 {
272 int delay = SCSI_SETUP_LATENCY;
273 double usec;
274
275 usec = 0.0;
276 usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE;
277 delay += usec;
278 if(delay) usleep(delay);
279 };
280 #endif
281
282 #ifdef DEBUG
283 printk("(r%d)",SCpnt->request.nr_sectors);
284 #endif
285 nbytes = bufflen;
286 if(SCpnt->use_sg){
287 sgcount = 0;
288 sgpnt = (struct scatterlist *) buff;
289 buff = sgpnt[sgcount].address;
290 bufflen = sgpnt[sgcount].length;
291 bh = SCpnt->request.bh;
292 };
293 scsi_debug_errsts = 0;
294 do{
295 VERIFY1_DEBUG(READ);
296
297 #ifndef SPEEDY
298 memset(buff, 0, bufflen);
299 #endif
300
301
302 if(block == 0 && target == 0) {
303 memset(buff, 0, bufflen);
304 *((unsigned short *) (buff+510)) = 0xAA55;
305 p = (struct partition* ) (buff + 0x1be);
306 npart = 0;
307 while(starts[npart+1]){
308 p->start_sect = starts[npart];
309 p->nr_sects = starts[npart+1] - starts [npart];
310 p->sys_ind = 0x81;
311 p++;
312 npart++;
313 };
314 scsi_debug_errsts = 0;
315 break;
316 };
317 #ifdef DEBUG
318 if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors,
319 SCpnt->request.current_nr_sectors);
320 #endif
321
322 #if 0
323
324 if(block == 0xfff0) {
325 sense_buffer[0] = 0x70;
326 sense_buffer[2] = UNIT_ATTENTION;
327 starts[0] += 10;
328 starts[1] += 10;
329 starts[2] += 10;
330
331 #ifdef DEBUG
332 {
333 int i;
334 printk("scsi_debug: Filling sense buffer:");
335 for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
336 printk("\n");
337 };
338 #endif
339 scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
340 break;
341 }
342 #endif
343
344 #ifndef SPEEDY
345 memcpy(buff, &target, sizeof(target));
346 memcpy(buff+sizeof(target), cmd, 24);
347 memcpy(buff+60, &block, sizeof(block));
348 memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd));
349 #endif
350 nbytes -= bufflen;
351 if(SCpnt->use_sg){
352 #ifndef SPEEDY
353 memcpy(buff+128, bh, sizeof(struct buffer_head));
354 #endif
355 block += bufflen >> 9;
356 bh = bh->b_reqnext;
357 sgcount++;
358 if (nbytes) {
359 if(!bh) panic("Too few blocks for linked request.");
360 buff = sgpnt[sgcount].address;
361 bufflen = sgpnt[sgcount].length;
362 };
363 }
364 } while(nbytes);
365
366 SCpnt->result = 0;
367 (done)(SCpnt);
368 return;
369
370 if (SCpnt->use_sg && !scsi_debug_errsts)
371 if(bh) scsi_dump(SCpnt, 0);
372 break;
373 case WRITE_10:
374 case WRITE_6:
375 #ifdef DEBUG
376 printk("Write\n");
377 #endif
378 if ((*cmd) == WRITE_10)
379 block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
380 else
381 block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
382 VERIFY_DEBUG(WRITE);
383
384 if (SCpnt->use_sg){
385 if ((bufflen >> 9) != SCpnt->request.nr_sectors)
386 panic ("Trying to write wrong number of blocks\n");
387 sgpnt = (struct scatterlist *) buff;
388 buff = sgpnt[sgcount].address;
389 };
390 #if 0
391 if (block != *((unsigned long *) (buff+60))) {
392 printk("%x %x :",block, *((unsigned long *) (buff+60)));
393 scsi_dump(SCpnt,1);
394 panic("Bad block written.\n");
395 };
396 #endif
397 scsi_debug_errsts = 0;
398 break;
399 default:
400 printk("Unknown command %d\n",*cmd);
401 SCpnt->result = DID_NO_CONNECT << 16;
402 done(SCpnt);
403 return 0;
404 };
405
406 save_flags(flags);
407 cli();
408 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++){
409 if (SCint[i] == 0) break;
410 };
411
412 if (i >= SCSI_DEBUG_MAILBOXES || SCint[i] != 0)
413 panic("Unable to find empty SCSI_DEBUG command slot.\n");
414
415 SCint[i] = SCpnt;
416
417 if (done) {
418 DEB(printk("scsi_debug_queuecommand: now waiting for interrupt "););
419 if (do_done[i])
420 printk("scsi_debug_queuecommand: Two concurrent queuecommand?\n");
421 else
422 do_done[i] = done;
423 }
424 else
425 printk("scsi_debug_queuecommand: done cant be NULL\n");
426
427 #ifdef IMMEDIATE
428 if( !scsi_debug_lockup )
429 {
430 SCpnt->result = scsi_debug_errsts;
431 scsi_debug_intr_handle();
432 }
433 restore_flags(flags);
434 #else
435 timeout[i] = jiffies+DISK_SPEED;
436
437
438 if ((timer_active & (1 << SCSI_DEBUG_TIMER)) == 0) {
439 timer_table[SCSI_DEBUG_TIMER].expires = timeout[i];
440 timer_active |= 1 << SCSI_DEBUG_TIMER;
441 };
442
443 SCpnt->result = scsi_debug_errsts;
444 restore_flags(flags);
445
446 #if 0
447 printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
448 #endif
449 #endif
450
451 return 0;
452 }
453
454 volatile static int internal_done_flag = 0;
455 volatile static int internal_done_errcode = 0;
456 static void internal_done(Scsi_Cmnd * SCpnt)
457 {
458 internal_done_errcode = SCpnt->result;
459 ++internal_done_flag;
460 }
461
462 int scsi_debug_command(Scsi_Cmnd * SCpnt)
463 {
464 DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n"));
465 scsi_debug_queuecommand(SCpnt, internal_done);
466
467 while (!internal_done_flag);
468 internal_done_flag = 0;
469 return internal_done_errcode;
470 }
471
472
473
474
475 static void scsi_debug_intr_handle(void)
476 {
477 Scsi_Cmnd * SCtmp;
478 int i, pending;
479 void (*my_done)(Scsi_Cmnd *);
480 unsigned long flags;
481 int to;
482
483 #ifndef IMMEDIATE
484 timer_table[SCSI_DEBUG_TIMER].expires = 0;
485 timer_active &= ~(1 << SCSI_DEBUG_TIMER);
486 #endif
487
488 repeat:
489 save_flags(flags);
490 cli();
491 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
492 if (SCint[i] == 0) continue;
493 #ifndef IMMEDIATE
494 if (timeout[i] == 0) continue;
495 if (timeout[i] <= jiffies) break;
496 #else
497 break;
498 #endif
499 };
500
501 if(i == SCSI_DEBUG_MAILBOXES){
502 #ifndef IMMEDIATE
503 pending = INT_MAX;
504 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
505 if (SCint[i] == 0) continue;
506 if (timeout[i] == 0) continue;
507 if (timeout[i] <= jiffies) {restore_flags(flags); goto repeat;};
508 if (timeout[i] > jiffies) {
509 if (pending > timeout[i]) pending = timeout[i];
510 continue;
511 };
512 };
513 if (pending && pending != INT_MAX) {
514 timer_table[SCSI_DEBUG_TIMER].expires =
515 (pending <= jiffies ? jiffies+1 : pending);
516 timer_active |= 1 << SCSI_DEBUG_TIMER;
517 };
518 restore_flags(flags);
519 #endif
520 return;
521 };
522
523 if(i < SCSI_DEBUG_MAILBOXES){
524 timeout[i] = 0;
525 my_done = do_done[i];
526 do_done[i] = NULL;
527 to = timeout[i];
528 timeout[i] = 0;
529 SCtmp = (Scsi_Cmnd *) SCint[i];
530 SCint[i] = NULL;
531 restore_flags(flags);
532
533 if (!my_done) {
534 printk("scsi_debug_intr_handle: Unexpected interrupt\n");
535 return;
536 }
537
538 #ifdef DEBUG
539 printk("In intr_handle...");
540 printk("...done %d %x %d %d\n",i , my_done, to, jiffies);
541 printk("In intr_handle: %d %x %x\n",i, SCtmp, my_done);
542 #endif
543
544 my_done(SCtmp);
545 #ifdef DEBUG
546 printk("Called done.\n");
547 #endif
548 };
549 goto repeat;
550 }
551
552
553 int scsi_debug_detect(Scsi_Host_Template * tpnt)
554 {
555 tpnt->proc_dir = &proc_scsi_scsi_debug;
556 #ifndef IMMEDIATE
557 timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle;
558 timer_table[SCSI_DEBUG_TIMER].expires = 0;
559 #endif
560 return 1;
561 }
562
563 int scsi_debug_abort(Scsi_Cmnd * SCpnt)
564 {
565 int j;
566 void (*my_done)(Scsi_Cmnd *);
567 unsigned long flags;
568
569 DEB(printk("scsi_debug_abort\n"));
570 #if 0
571 SCpnt->result = SCpnt->abort_reason << 16;
572 for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) {
573 if(SCpnt == SCint[j]) {
574 my_done = do_done[j];
575 my_done(SCpnt);
576 save_flags(flags);
577 cli();
578 timeout[j] = 0;
579 SCint[j] = NULL;
580 do_done[j] = NULL;
581 restore_flags(flags);
582 };
583 };
584 #endif
585 return SCSI_ABORT_SNOOZE;
586 }
587
588 int scsi_debug_biosparam(Disk * disk, kdev_t dev, int* info){
589 int size = disk->capacity;
590 info[0] = 32;
591 info[1] = 64;
592 info[2] = (size + 2047) >> 11;
593 if (info[2] >= 1024) info[2] = 1024;
594 return 0;
595 }
596
597 int scsi_debug_reset(Scsi_Cmnd * SCpnt)
598 {
599 int i;
600 unsigned long flags;
601
602 void (*my_done)(Scsi_Cmnd *);
603 printk("Bus unlocked by reset(%d)\n", SCpnt->host->suggest_bus_reset);
604 scsi_debug_lockup = 0;
605 DEB(printk("scsi_debug_reset called\n"));
606 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
607 if (SCint[i] == NULL) continue;
608 SCint[i]->result = DID_RESET << 16;
609 my_done = do_done[i];
610 my_done(SCint[i]);
611 save_flags(flags);
612 cli();
613 SCint[i] = NULL;
614 do_done[i] = NULL;
615 timeout[i] = 0;
616 restore_flags(flags);
617 }
618 return SCSI_RESET_SUCCESS;
619 }
620
621 const char *scsi_debug_info(void)
622 {
623 static char buffer[] = " ";
624 return buffer;
625 }
626
627
628
629
630 int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
631 int length, int inode, int inout)
632 {
633 int len, pos, begin;
634 int orig_length;
635
636 if(inout == 1)
637 {
638
639 if (length >= 10 && strncmp(buffer, "scsi_debug", 10) == 0) {
640 buffer += 11;
641 length -= 11;
642
643
644
645
646
647 if( length == 6 && strncmp(buffer, "lockup", length) == 0 )
648 {
649 scsi_debug_lockup = 1;
650 return length;
651 }
652
653 if( length == 6 && strncmp(buffer, "unlock", length) == 0 )
654 {
655 scsi_debug_lockup = 0;
656 return length;
657 }
658
659 printk("Unknown command:%s\n", buffer);
660 } else
661 printk("Wrong Signature:%10s\n", (char *) ((ulong)buffer-11));
662
663 return -EINVAL;
664
665 }
666
667 begin = 0;
668 pos = len = sprintf(buffer,
669 "This driver is not a real scsi driver, but it plays one on TV.\n"
670 "It is very handy for debugging specific problems because you\n"
671 "can simulate a variety of error conditions\n");
672 if(pos < offset)
673 {
674 len = 0;
675 begin = pos;
676 }
677
678 *start = buffer + (offset - begin);
679 len -= (offset - begin);
680 if(len > length)
681 len = length;
682
683 return(len);
684 }
685
686 #ifdef MODULE
687
688 Scsi_Host_Template driver_template = SCSI_DEBUG;
689
690 #include "scsi_module.c"
691 #endif
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710