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