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
40
41
42
43 #define IMMEDIATE
44
45
46 #define SPEEDY
47
48
49 static int NR_REAL=-1;
50
51 #define NR_BLK_DEV 12
52 #ifndef MAJOR_NR
53 #define MAJOR_NR 8
54 #endif
55 #define START_PARTITION 4
56 #define SCSI_DEBUG_TIMER 20
57
58 #define DISK_SPEED 10
59 #define CAPACITY (0x80000)
60
61 static int starts[] = {4, 1000, 50000, CAPACITY, 0};
62 static int npart = 0;
63
64 #include "scsi_debug.h"
65 #ifdef DEBUG
66 #define DEB(x) x
67 #else
68 #define DEB(x)
69 #endif
70
71 #ifdef SPEEDY
72 #define VERIFY1_DEBUG(RW) 1
73 #define VERIFY_DEBUG(RW) 1
74 #else
75
76 #define VERIFY1_DEBUG(RW) \
77 if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");}; \
78 start = 0; \
79 if ((SCpnt->request.dev & 0xf) != 0) start = starts[(SCpnt->request.dev & 0xf) - 1]; \
80 if (bh){ \
81 if (bh->b_size != 1024) panic ("Wrong bh size"); \
82 if ((bh->b_blocknr << 1) + start != block) \
83 { printk("Wrong bh block# %d %d ",bh->b_blocknr, block); \
84 panic ("Wrong bh block#"); \
85 }; \
86 if (bh->b_dev != SCpnt->request.dev) panic ("Bad bh target");\
87 };
88
89 #if 0
90
91
92 if ((SCpnt->request.dev & 0xfff0) != ((target + NR_REAL) << 4) +(MAJOR_NR << 8)){ \
93 printk("Dev #s %x %x ",SCpnt->request.dev, target); \
94 panic ("Bad target");\
95 }; \
96
97 #endif
98
99 #define VERIFY_DEBUG(RW) \
100 if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");}; \
101 start = 0; \
102 if ((SCpnt->request.dev & 0xf) > npart) panic ("Bad partition"); \
103 if ((SCpnt->request.dev & 0xf) != 0) start = starts[(SCpnt->request.dev & 0xf) - 1]; \
104 if (SCpnt->request.cmd != RW) panic ("Wrong operation"); \
105 if (SCpnt->request.sector + start != block) panic("Wrong block."); \
106 if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks"); \
107 if (SCpnt->request.bh){ \
108 if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size"); \
109 if ((SCpnt->request.bh->b_blocknr << 1) + start != block) \
110 { printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block); \
111 panic ("Wrong bh block#"); \
112 }; \
113 if (SCpnt->request.bh->b_dev != SCpnt->request.dev) 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 = (SCpnt->request.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 #ifndef IMMEDIATE
559 timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle;
560 timer_table[SCSI_DEBUG_TIMER].expires = 0;
561 #endif
562 return 1;
563 }
564
565 int scsi_debug_abort(Scsi_Cmnd * SCpnt)
566 {
567 int j;
568 void (*my_done)(Scsi_Cmnd *);
569 unsigned long flags;
570
571 DEB(printk("scsi_debug_abort\n"));
572 #if 0
573 SCpnt->result = SCpnt->abort_reason << 16;
574 for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) {
575 if(SCpnt == SCint[j]) {
576 my_done = do_done[j];
577 my_done(SCpnt);
578 save_flags(flags);
579 cli();
580 timeout[j] = 0;
581 SCint[j] = NULL;
582 do_done[j] = NULL;
583 restore_flags(flags);
584 };
585 };
586 #endif
587 return SCSI_ABORT_SNOOZE;
588 }
589
590 int scsi_debug_biosparam(Disk * disk, int dev, int* info){
591 int size = disk->capacity;
592 info[0] = 32;
593 info[1] = 64;
594 info[2] = (size + 2047) >> 11;
595 if (info[2] >= 1024) info[2] = 1024;
596 return 0;
597 }
598
599 int scsi_debug_reset(Scsi_Cmnd * SCpnt)
600 {
601 int i;
602 unsigned long flags;
603
604 void (*my_done)(Scsi_Cmnd *);
605 printk("Bus unlocked by reset(%d)\n", SCpnt->host->suggest_bus_reset);
606 scsi_debug_lockup = 0;
607 DEB(printk("scsi_debug_reset called\n"));
608 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
609 if (SCint[i] == NULL) continue;
610 SCint[i]->result = DID_RESET << 16;
611 my_done = do_done[i];
612 my_done(SCint[i]);
613 save_flags(flags);
614 cli();
615 SCint[i] = NULL;
616 do_done[i] = NULL;
617 timeout[i] = 0;
618 restore_flags(flags);
619 }
620 return SCSI_RESET_SUCCESS;
621 }
622
623 const char *scsi_debug_info(void)
624 {
625 static char buffer[] = " ";
626 return buffer;
627 }
628
629
630
631
632 int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
633 int length, int inode, int inout)
634 {
635 int len, pos, begin;
636 int orig_length;
637
638 if(inout == 1)
639 {
640
641 if (length >= 10 && strncmp(buffer, "scsi_debug", 10) == 0) {
642 buffer += 11;
643 length -= 11;
644
645
646
647
648
649 if( length == 6 && strncmp(buffer, "lockup", length) == 0 )
650 {
651 scsi_debug_lockup = 1;
652 return length;
653 }
654
655 if( length == 6 && strncmp(buffer, "unlock", length) == 0 )
656 {
657 scsi_debug_lockup = 0;
658 return length;
659 }
660
661 printk("Unknown command:%s\n", buffer);
662 } else
663 printk("Wrong Signature:%10s\n", (char *) ((ulong)buffer-11));
664
665 return -EINVAL;
666
667 }
668
669 begin = 0;
670 pos = len = sprintf(buffer,
671 "This driver is not a real scsi driver, but it plays one on TV.\n"
672 "It is very handy for debugging specific problems because you\n"
673 "can simulate a variety of error conditions\n");
674 if(pos < offset)
675 {
676 len = 0;
677 begin = pos;
678 }
679
680 *start = buffer + (offset - begin);
681 len -= (offset - begin);
682 if(len > length)
683 len = length;
684
685 return(len);
686 }
687
688 #ifdef MODULE
689
690 Scsi_Host_Template driver_template = SCSI_DEBUG;
691
692 #include "scsi_module.c"
693 #endif
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712