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