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