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