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 int i;
168 sgcount = 0;
169 sgpnt = NULL;
170
171 DEB(if (target > 1) { SCpnt->result = DID_TIME_OUT << 16;done(SCpnt);return 0;});
172
173 buff = (unsigned char *) SCpnt->request_buffer;
174
175 if(target>=1 || SCpnt->lun != 0) {
176 SCpnt->result = DID_NO_CONNECT << 16;
177 done(SCpnt);
178 return 0;
179 };
180
181 switch(*cmd){
182 case REQUEST_SENSE:
183 printk("Request sense...\n");
184 #ifndef DEBUG
185 { int i;
186 printk("scsi_debug: Requesting sense buffer (%x %x %x %d):", SCpnt, buff, done, bufflen);
187 for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
188 printk("\n");
189 };
190 #endif
191 memset(buff, 0, bufflen);
192 memcpy(buff, sense_buffer, bufflen);
193 memset(sense_buffer, 0, sizeof(sense_buffer));
194 SCpnt->result = 0;
195 done(SCpnt);
196 return 0;
197 case ALLOW_MEDIUM_REMOVAL:
198 if(cmd[4]) printk("Medium removal inhibited...");
199 else printk("Medium removal enabled...");
200 scsi_debug_errsts = 0;
201 break;
202 case INQUIRY:
203 printk("Inquiry...(%x %d)\n", buff, bufflen);
204 memset(buff, 0, bufflen);
205 buff[0] = TYPE_DISK;
206 buff[1] = 0x80;
207 buff[2] = 1;
208 buff[4] = 33 - 5;
209 memcpy(&buff[8],"Foo Inc",7);
210 memcpy(&buff[16],"XYZZY",5);
211 memcpy(&buff[32],"1",1);
212 scsi_debug_errsts = 0;
213 break;
214 case TEST_UNIT_READY:
215 printk("Test unit ready.\n");
216 if (buff)
217 memset(buff, 0, bufflen);
218 scsi_debug_errsts = 0;
219 break;
220 case READ_CAPACITY:
221 printk("Read Capacity\n");
222 if(NR_REAL < 0) NR_REAL = (SCpnt->request.dev >> 4) & 0x0f;
223 memset(buff, 0, bufflen);
224 buff[0] = (CAPACITY >> 24);
225 buff[1] = (CAPACITY >> 16) & 0xff;
226 buff[2] = (CAPACITY >> 8) & 0xff;
227 buff[3] = CAPACITY & 0xff;
228 buff[6] = 2;
229 scsi_debug_errsts = 0;
230 break;
231 case READ_10:
232 case READ_6:
233 #ifdef DEBUG
234 printk("Read...");
235 #endif
236 if ((*cmd) == READ_10)
237 block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
238 else
239 block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
240 VERIFY_DEBUG(READ);
241 #if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
242 {
243 int delay = SCSI_SETUP_LATENCY;
244 double usec;
245
246 usec = 0.0;
247 usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE;
248 delay += usec;
249 if(delay) usleep(delay);
250 };
251 #endif
252
253 #ifdef DEBUG
254 printk("(r%d)",SCpnt->request.nr_sectors);
255 #endif
256 nbytes = bufflen;
257 if(SCpnt->use_sg){
258 sgcount = 0;
259 sgpnt = (struct scatterlist *) buff;
260 buff = sgpnt[sgcount].address;
261 bufflen = sgpnt[sgcount].length;
262 bh = SCpnt->request.bh;
263 };
264 scsi_debug_errsts = 0;
265 do{
266 VERIFY1_DEBUG(READ);
267
268 #ifndef SPEEDY
269 memset(buff, 0, bufflen);
270 #endif
271
272
273 if(block == 0 && target == 0) {
274 *((unsigned short *) (buff+510)) = 0xAA55;
275 p = (struct partition* ) (buff + 0x1be);
276 npart = 0;
277 while(starts[npart+1]){
278 p->start_sect = starts[npart];
279 p->nr_sects = starts[npart+1] - starts [npart];
280 p->sys_ind = 0x81;
281 p++;
282 npart++;
283 };
284 scsi_debug_errsts = 0;
285 break;
286 };
287 #ifdef DEBUG
288 if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors,
289 SCpnt->request.current_nr_sectors);
290 #endif
291
292 #if 0
293
294 if(block == 0xfff0) {
295 sense_buffer[0] = 0x70;
296 sense_buffer[2] = UNIT_ATTENTION;
297 starts[0] += 10;
298 starts[1] += 10;
299 starts[2] += 10;
300
301 #ifdef DEBUG
302 { int i;
303 printk("scsi_debug: Filling sense buffer:");
304 for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
305 printk("\n");
306 };
307 #endif
308 scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
309 break;
310 }
311 #endif
312
313 #ifndef SPEEDY
314 memcpy(buff, &target, sizeof(target));
315 memcpy(buff+sizeof(target), cmd, 24);
316 memcpy(buff+60, &block, sizeof(block));
317 memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd));
318 #endif
319 nbytes -= bufflen;
320 if(SCpnt->use_sg){
321 #ifndef SPEEDY
322 memcpy(buff+128, bh, sizeof(struct buffer_head));
323 #endif
324 block += bufflen >> 9;
325 bh = bh->b_reqnext;
326 sgcount++;
327 if (nbytes) {
328 if(!bh) panic("Too few blocks for linked request.");
329 buff = sgpnt[sgcount].address;
330 bufflen = sgpnt[sgcount].length;
331 };
332 }
333 } while(nbytes);
334
335 SCpnt->result = 0;
336 (done)(SCpnt);
337 return;
338
339 if (SCpnt->use_sg && !scsi_debug_errsts)
340 if(bh) scsi_dump(SCpnt, 0);
341 break;
342 case WRITE_10:
343 case WRITE_6:
344 #ifdef DEBUG
345 printk("Write\n");
346 #endif
347 if ((*cmd) == WRITE_10)
348 block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
349 else
350 block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
351 VERIFY_DEBUG(WRITE);
352
353 if (SCpnt->use_sg){
354 if ((bufflen >> 9) != SCpnt->request.nr_sectors)
355 panic ("Trying to write wrong number of blocks\n");
356 sgpnt = (struct scatterlist *) buff;
357 buff = sgpnt[sgcount].address;
358 };
359 #if 0
360 if (block != *((unsigned long *) (buff+60))) {
361 printk("%x %x :",block, *((unsigned long *) (buff+60)));
362 scsi_dump(SCpnt,1);
363 panic("Bad block written.\n");
364 };
365 #endif
366 scsi_debug_errsts = 0;
367 break;
368 default:
369 printk("Unknown command %d\n",*cmd);
370 SCpnt->result = DID_NO_CONNECT << 16;
371 done(SCpnt);
372 return 0;
373 };
374
375 cli();
376 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++){
377 if (SCint[i] == 0) break;
378 };
379
380 if (i >= SCSI_DEBUG_MAILBOXES || SCint[i] != 0)
381 panic("Unable to find empty SCSI_DEBUG command slot.\n");
382
383 SCint[i] = SCpnt;
384
385 if (done) {
386 DEB(printk("scsi_debug_queuecommand: now waiting for interrupt "););
387 if (do_done[i])
388 printk("scsi_debug_queuecommand: Two concurrent queuecommand?\n");
389 else
390 do_done[i] = done;
391 }
392 else
393 printk("scsi_debug_queuecommand: done cant be NULL\n");
394
395 #ifdef IMMEDIATE
396 SCpnt->result = scsi_debug_errsts;
397 scsi_debug_intr_handle();
398 #else
399 timeout[i] = jiffies+DISK_SPEED;
400
401
402 if ((timer_active & (1 << SCSI_DEBUG_TIMER)) == 0) {
403 timer_table[SCSI_DEBUG_TIMER].expires = timeout[i];
404 timer_active |= 1 << SCSI_DEBUG_TIMER;
405 };
406
407 SCpnt->result = scsi_debug_errsts;
408 sti();
409
410 #if 0
411 printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
412 #endif
413 #endif
414
415 return 0;
416 }
417
418 volatile static int internal_done_flag = 0;
419 volatile static int internal_done_errcode = 0;
420 static void internal_done(Scsi_Cmnd * SCpnt)
421 {
422 internal_done_errcode = SCpnt->result;
423 ++internal_done_flag;
424 }
425
426 int scsi_debug_command(Scsi_Cmnd * SCpnt)
427 {
428 DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n"));
429 scsi_debug_queuecommand(SCpnt, internal_done);
430
431 while (!internal_done_flag);
432 internal_done_flag = 0;
433 return internal_done_errcode;
434 }
435
436
437
438
439 static void scsi_debug_intr_handle(void)
440 {
441 Scsi_Cmnd * SCtmp;
442 int i, pending;
443 void (*my_done)(Scsi_Cmnd *);
444 int to;
445
446 #ifndef IMMEDIATE
447 timer_table[SCSI_DEBUG_TIMER].expires = 0;
448 timer_active &= ~(1 << SCSI_DEBUG_TIMER);
449 #endif
450
451 repeat:
452 cli();
453 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
454 if (SCint[i] == 0) continue;
455 #ifndef IMMEDIATE
456 if (timeout[i] == 0) continue;
457 if (timeout[i] <= jiffies) break;
458 #else
459 break;
460 #endif
461 };
462
463 if(i == SCSI_DEBUG_MAILBOXES){
464 #ifndef IMMEDIATE
465 pending = INT_MAX;
466 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
467 if (SCint[i] == 0) continue;
468 if (timeout[i] == 0) continue;
469 if (timeout[i] <= jiffies) {sti(); goto repeat;};
470 if (timeout[i] > jiffies) {
471 if (pending > timeout[i]) pending = timeout[i];
472 continue;
473 };
474 };
475 if (pending && pending != INT_MAX) {
476 timer_table[SCSI_DEBUG_TIMER].expires =
477 (pending <= jiffies ? jiffies+1 : pending);
478 timer_active |= 1 << SCSI_DEBUG_TIMER;
479 };
480 sti();
481 #endif
482 return;
483 };
484
485 if(i < SCSI_DEBUG_MAILBOXES){
486 timeout[i] = 0;
487 my_done = do_done[i];
488 do_done[i] = NULL;
489 to = timeout[i];
490 timeout[i] = 0;
491 SCtmp = (Scsi_Cmnd *) SCint[i];
492 SCint[i] = NULL;
493 sti();
494
495 if (!my_done) {
496 printk("scsi_debug_intr_handle: Unexpected interrupt\n");
497 return;
498 }
499
500 #ifdef DEBUG
501 printk("In intr_handle...");
502 printk("...done %d %x %d %d\n",i , my_done, to, jiffies);
503 printk("In intr_handle: %d %x %x\n",i, SCtmp, my_done);
504 #endif
505
506 my_done(SCtmp);
507 #ifdef DEBUG
508 printk("Called done.\n");
509 #endif
510 };
511 goto repeat;
512 }
513
514
515 int scsi_debug_detect(Scsi_Host_Template * tpnt)
516 {
517 #ifndef IMMEDIATE
518 timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle;
519 timer_table[SCSI_DEBUG_TIMER].expires = 0;
520 #endif
521 return 1;
522 }
523
524 int scsi_debug_abort(Scsi_Cmnd * SCpnt)
525 {
526 int j;
527 void (*my_done)(Scsi_Cmnd *);
528 DEB(printk("scsi_debug_abort\n"));
529 SCpnt->result = SCpnt->abort_reason << 16;
530 for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) {
531 if(SCpnt == SCint[j]) {
532 my_done = do_done[j];
533 my_done(SCpnt);
534 cli();
535 timeout[j] = 0;
536 SCint[j] = NULL;
537 do_done[j] = NULL;
538 sti();
539 };
540 };
541 return 0;
542 }
543
544 int scsi_debug_biosparam(Disk * disk, int dev, int* info){
545 int size = disk->capacity;
546 info[0] = 32;
547 info[1] = 64;
548 info[2] = (size + 2047) >> 11;
549 if (info[2] >= 1024) info[2] = 1024;
550 return 0;
551 }
552
553 int scsi_debug_reset(Scsi_Cmnd * SCpnt)
554 {
555 int i;
556 void (*my_done)(Scsi_Cmnd *);
557 DEB(printk("scsi_debug_reset called\n"));
558 for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
559 if (SCint[i] == NULL) continue;
560 SCint[i]->result = DID_ABORT << 16;
561 my_done = do_done[i];
562 my_done(SCint[i]);
563 cli();
564 SCint[i] = NULL;
565 do_done[i] = NULL;
566 timeout[i] = 0;
567 sti();
568 };
569 return 0;
570 }
571
572 const char *scsi_debug_info(void)
573 {
574 static char buffer[] = " ";
575 return buffer;
576 }
577
578