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