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