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