This source file includes following definitions.
- generic_NCR5380_setup
- generic_NCR53C400_setup
- generic_NCR5380_detect
- generic_NCR5380_info
- generic_NCR5380_release_resources
- generic_NCR5380_biosparam
- NCR5380_pread
- NCR5380_pwrite
- sprint_opcode
- sprint_command
- sprint_Scsi_Cmnd
- generic_NCR5380_proc_info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 #define AUTOPROBE_IRQ
60 #define AUTOSENSE
61
62 #include <linux/config.h>
63
64 #ifdef CONFIG_SCSI_GENERIC_NCR53C400
65 #define NCR53C400_PSEUDO_DMA 1
66 #define PSEUDO_DMA
67 #define NCR53C400
68 #define NCR5380_STATS
69 #undef NCR5380_STAT_LIMIT
70 #endif
71 #if defined(CONFIG_SCSI_G_NCR5380_PORT) && defined(CONFIG_SCSI_G_NCR5380_MEM)
72 #error You can not configure the Generic NCR 5380 SCSI Driver for memory mapped I/O and port mapped I/O at the same time (yet)
73 #endif
74 #if !defined(CONFIG_SCSI_G_NCR5380_PORT) && !defined(CONFIG_SCSI_G_NCR5380_MEM)
75 #error You must configure the Generic NCR 5380 SCSI Driver for one of memory mapped I/O and port mapped I/O.
76 #endif
77
78 #include <asm/system.h>
79 #include <asm/io.h>
80 #include <linux/signal.h>
81 #include <linux/sched.h>
82 #include <linux/blk.h>
83 #include "scsi.h"
84 #include "hosts.h"
85 #include "g_NCR5380.h"
86 #include "NCR5380.h"
87 #include "constants.h"
88 #include "sd.h"
89 #include<linux/stat.h>
90
91 struct proc_dir_entry proc_scsi_g_ncr5380 = {
92 PROC_SCSI_GENERIC_NCR5380, 9, "g_NCR5380",
93 S_IFDIR | S_IRUGO | S_IXUGO, 2
94 };
95
96 static struct override {
97 NCR5380_implementation_fields;
98 int irq;
99 int dma;
100 int board;
101 } overrides
102 #ifdef GENERIC_NCR5380_OVERRIDE
103 [] = GENERIC_NCR5380_OVERRIDE
104 #else
105 [1] = {{0,},};
106 #endif
107
108 #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
109
110
111
112
113
114
115
116
117
118
119
120
121 static void internal_setup(int board, char *str, int *ints) {
122 static int commandline_current = 0;
123 switch (board) {
124 case BOARD_NCR5380:
125 if (ints[0] != 2 && ints[0] != 3) {
126 printk("generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n");
127 return;
128 }
129 case BOARD_NCR53C400:
130 if (ints[0] != 2) {
131 printk("generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n");
132 return;
133 }
134 }
135
136 if (commandline_current < NO_OVERRIDES) {
137 overrides[commandline_current].NCR5380_map_name = (NCR5380_map_type)ints[1];
138 overrides[commandline_current].irq = ints[2];
139 if (ints[0] == 3)
140 overrides[commandline_current].dma = ints[3];
141 else
142 overrides[commandline_current].dma = DMA_NONE;
143 overrides[commandline_current].board = board;
144 ++commandline_current;
145 }
146 }
147
148
149
150
151
152
153
154
155
156
157 void generic_NCR5380_setup (char *str, int *ints) {
158 internal_setup (BOARD_NCR5380, str, ints);
159 }
160
161
162
163
164
165
166
167
168
169
170 void generic_NCR53C400_setup (char *str, int *ints) {
171 internal_setup (BOARD_NCR53C400, str, ints);
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186 int generic_NCR5380_detect(Scsi_Host_Template * tpnt) {
187 static int current_override = 0;
188 int count;
189 int flags = 0;
190 struct Scsi_Host *instance;
191
192 tpnt->proc_dir = &proc_scsi_g_ncr5380;
193
194 for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
195 if (!(overrides[current_override].NCR5380_map_name))
196 continue;
197
198 switch (overrides[current_override].board) {
199 case BOARD_NCR5380:
200 flags = FLAG_NO_PSEUDO_DMA;
201 break;
202 case BOARD_NCR53C400:
203 flags = FLAG_NCR53C400;
204 break;
205 }
206
207 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
208 instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name;
209
210 NCR5380_init(instance, flags);
211
212 if (overrides[current_override].irq != IRQ_AUTO)
213 instance->irq = overrides[current_override].irq;
214 else
215 instance->irq = NCR5380_probe_irq(instance, 0xffff);
216
217 if (instance->irq != IRQ_NONE)
218 if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) {
219 printk("scsi%d : IRQ%d not free, interrupts disabled\n",
220 instance->host_no, instance->irq);
221 instance->irq = IRQ_NONE;
222 }
223
224 if (instance->irq == IRQ_NONE) {
225 printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
226 printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
227 }
228
229 printk("scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int)instance->NCR5380_instance_name);
230 if (instance->irq == IRQ_NONE)
231 printk (" interrupts disabled");
232 else
233 printk (" irq %d", instance->irq);
234 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
235 CAN_QUEUE, CMD_PER_LUN, GENERIC_NCR5380_PUBLIC_RELEASE);
236 NCR5380_print_options(instance);
237 printk("\n");
238
239 ++current_override;
240 ++count;
241 }
242 return count;
243 }
244
245 const char * generic_NCR5380_info (struct Scsi_Host* host) {
246 static const char string[]="Generic NCR5380/53C400 Driver";
247 return string;
248 }
249
250 int generic_NCR5380_release_resources(struct Scsi_Host * instance)
251 {
252 NCR5380_local_declare();
253
254 NCR5380_setup(instance);
255
256 free_irq(instance->irq, NULL);
257
258 return 0;
259 }
260
261 #ifdef BIOSPARAM
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282 int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip)
283 {
284 int size = disk->capacity;
285 ip[0] = 64;
286 ip[1] = 32;
287 ip[2] = size >> 11;
288 return 0;
289 }
290 #endif
291
292 #if NCR53C400_PSEUDO_DMA
293 static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, int len)
294 {
295 int blocks = len / 128;
296 int start = 0;
297 int i;
298 int bl;
299 NCR5380_local_declare();
300
301 NCR5380_setup(instance);
302
303 #if (NDEBUG & NDEBUG_C400_PREAD)
304 printk("53C400r: About to read %d blocks for %d bytes\n", blocks, len);
305 #endif
306
307 NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
308 NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
309 while (1) {
310
311 #if (NDEBUG & NDEBUG_C400_PREAD)
312 printk("53C400r: %d blocks left\n", blocks);
313 #endif
314
315 if ((bl=NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
316 #if (NDEBUG & NDEBUG_C400_PREAD)
317 if (blocks)
318 printk("53C400r: blocks still == %d\n", blocks);
319 else
320 printk("53C400r: Exiting loop\n");
321 #endif
322 break;
323 }
324
325 #if 1
326 if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
327 printk("53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
328 return -1;
329 }
330 #endif
331
332 #if (NDEBUG & NDEBUG_C400_PREAD)
333 printk("53C400r: Waiting for buffer, bl=%d\n", bl);
334 #endif
335
336 while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
337 ;
338 #if (NDEBUG & NDEBUG_C400_PREAD)
339 printk("53C400r: Transferring 128 bytes\n");
340 #endif
341
342 #ifdef CONFIG_SCSI_G_NCR5380_PORT
343 for (i=0; i<128; i++)
344 dst[start+i] = NCR5380_read(C400_HOST_BUFFER);
345 #else
346
347 memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
348 #endif
349 start+=128;
350 blocks--;
351 }
352
353 #if (NDEBUG & NDEBUG_C400_PREAD)
354 printk("53C400r: EXTRA: Waiting for buffer\n");
355 #endif
356 while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
357 ;
358
359 #if (NDEBUG & NDEBUG_C400_PREAD)
360 printk("53C400r: Transferring EXTRA 128 bytes\n");
361 #endif
362 #ifdef CONFIG_SCSI_G_NCR5380_PORT
363 for (i=0; i<128; i++)
364 dst[start+i] = NCR5380_read(C400_HOST_BUFFER);
365 #else
366
367 memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
368 #endif
369 start+=128;
370 blocks--;
371
372 #if (NDEBUG & NDEBUG_C400_PREAD)
373 printk("53C400r: Final values: blocks=%d start=%d\n", blocks, start);
374 #endif
375
376 if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
377 printk("53C400r: no 53C80 gated irq after transfer");
378 #if (NDEBUG & NDEBUG_C400_PREAD)
379 else
380 printk("53C400r: Got 53C80 interrupt and tried to clear it\n");
381 #endif
382
383
384
385
386
387
388
389 if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
390 printk("53C400r: no end dma signal\n");
391 #if (NDEBUG & NDEBUG_C400_PREAD)
392 else
393 printk("53C400r: end dma as expected\n");
394 #endif
395
396 NCR5380_write(MODE_REG, MR_BASE);
397 NCR5380_read(RESET_PARITY_INTERRUPT_REG);
398 return 0;
399 }
400
401 static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, int len)
402 {
403 int blocks = len / 128;
404 int start = 0;
405 int i;
406 int bl;
407 NCR5380_local_declare();
408
409 NCR5380_setup(instance);
410
411 #if (NDEBUG & NDEBUG_C400_PWRITE)
412 printk("53C400w: About to write %d blocks for %d bytes\n", blocks, len);
413 #endif
414
415 NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
416 NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
417 while (1) {
418 if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
419 printk("53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
420 return -1;
421 }
422
423 if ((bl=NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
424 #if (NDEBUG & NDEBUG_C400_PWRITE)
425 if (blocks)
426 printk("53C400w: exiting loop, blocks still == %d\n", blocks);
427 else
428 printk("53C400w: exiting loop\n");
429 #endif
430 break;
431 }
432
433 #if (NDEBUG & NDEBUG_C400_PWRITE)
434 printk("53C400w: %d blocks left\n", blocks);
435
436 printk("53C400w: waiting for buffer, bl=%d\n", bl);
437 #endif
438 while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
439 ;
440
441 #if (NDEBUG & NDEBUG_C400_PWRITE)
442 printk("53C400w: transferring 128 bytes\n");
443 #endif
444 #ifdef CONFIG_SCSI_G_NCR5380_PORT
445 for (i=0; i<128; i++)
446 NCR5380_write(C400_HOST_BUFFER, src[start+i]);
447 #else
448
449 memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128);
450 #endif
451 start+=128;
452 blocks--;
453 }
454 if (blocks) {
455 #if (NDEBUG & NDEBUG_C400_PWRITE)
456 printk("53C400w: EXTRA waiting for buffer\n");
457 #endif
458 while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
459 ;
460
461 #if (NDEBUG & NDEBUG_C400_PWRITE)
462 printk("53C400w: transferring EXTRA 128 bytes\n");
463 #endif
464 #ifdef CONFIG_SCSI_G_NCR5380_PORT
465 for (i=0; i<128; i++)
466 NCR5380_write(C400_HOST_BUFFER, src[start+i]);
467 #else
468
469 memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128);
470 #endif
471 start+=128;
472 blocks--;
473 }
474 #if (NDEBUG & NDEBUG_C400_PWRITE)
475 else
476 printk("53C400w: No EXTRA required\n");
477 #endif
478
479 #if (NDEBUG & NDEBUG_C400_PWRITE)
480 printk("53C400w: Final values: blocks=%d start=%d\n", blocks, start);
481 #endif
482
483 #if 0
484 printk("53C400w: waiting for registers to be available\n");
485 THEY NEVER DO!
486 while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
487 ;
488 printk("53C400w: Got em\n");
489 #endif
490
491
492
493
494
495 while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
496 ;
497
498
499
500
501
502 if (i) {
503 #if (NDEBUG & NDEBUG_C400_PWRITE)
504 printk("53C400w: got 53C80 gated irq (last block)\n");
505 #endif
506 if (!((i=NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER))
507 printk("53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n",i);
508 #if (NDEBUG & NDEBUG_C400_PWRITE)
509 else
510 printk("53C400w: Got END OF DMA\n");
511 #endif
512 }
513 else
514 printk("53C400w: no 53C80 gated irq after transfer (last block)\n");
515
516 #if 0
517 if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
518 printk("53C400w: no end dma signal\n");
519 }
520 #endif
521
522 #if (NDEBUG & NDEBUG_C400_PWRITE)
523 printk("53C400w: waiting for last byte...\n");
524 #endif
525 while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
526 ;
527
528 #if (NDEBUG & NDEBUG_C400_PWRITE)
529 printk("53C400w: got last byte.\n");
530 printk("53C400w: pwrite exiting with status 0, whoopee!\n");
531 #endif
532 return 0;
533 }
534 #endif
535
536 #include "NCR5380.c"
537
538 #define PRINTP(x) len += sprintf(buffer+len, x)
539 #define ANDP ,
540
541 static int sprint_opcode(char* buffer, int len, int opcode) {
542 int start = len;
543 PRINTP("0x%02x " ANDP opcode);
544 return len-start;
545 }
546
547 static int sprint_command (char* buffer, int len, unsigned char *command) {
548 int i,s,start=len;
549 len += sprint_opcode(buffer, len, command[0]);
550 for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
551 PRINTP("%02x " ANDP command[i]);
552 PRINTP("\n");
553 return len-start;
554 }
555
556 static int sprint_Scsi_Cmnd (char* buffer, int len, Scsi_Cmnd *cmd) {
557 int start = len;
558 PRINTP("host number %d destination target %d, lun %d\n" ANDP
559 cmd->host->host_no ANDP
560 cmd->target ANDP
561 cmd->lun);
562 PRINTP(" command = ");
563 len += sprint_command (buffer, len, cmd->cmnd);
564 return len-start;
565 }
566
567 const char *const private_scsi_device_types[] =
568 {
569 "Direct-Access ",
570 "Sequential-Access",
571 "Printer ",
572 "Processor ",
573 "WORM ",
574 "CD-ROM ",
575 "Scanner ",
576 "Optical Device ",
577 "Medium Changer ",
578 "Communications "
579 };
580 #define MAX_SCSI_DEVICE_CODE sizeof(private_scsi_device_types)/sizeof(char*)
581
582 int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout)
583 {
584 int len = 0;
585 NCR5380_local_declare();
586 unsigned char status;
587 int i;
588 struct Scsi_Host *scsi_ptr;
589 Scsi_Device *dev;
590 Scsi_Cmnd *ptr;
591 struct NCR5380_hostdata *hostdata;
592
593 cli();
594
595 for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next)
596 if (scsi_ptr->host_no == hostno)
597 break;
598 NCR5380_setup(scsi_ptr);
599 hostdata = (struct NCR5380_hostdata *)scsi_ptr->hostdata;
600
601 PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
602 PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
603 PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
604 #ifdef NCR53C400
605 PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE);
606 PRINTP("NCR53C400 card%s detected\n" ANDP (((struct NCR5380_hostdata *)scsi_ptr->hostdata)->flags & FLAG_NCR53C400)?"":" not");
607 # if NCR53C400_PSEUDO_DMA
608 PRINTP("NCR53C400 pseudo DMA used\n");
609 # endif
610 #else
611 PRINTP("NO NCR53C400 driver extensions\n");
612 #endif
613 PRINTP("Using %s mapping at %s 0x%x, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name);
614 if (scsi_ptr->irq == IRQ_NONE)
615 PRINTP("no interrupt\n");
616 else
617 PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq);
618
619 #ifdef NCR5380_STATS
620 if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue)
621 PRINTP("There are commands pending, transfer rates may be crud\n");
622 if (hostdata->pendingr)
623 PRINTP(" %d pending reads" ANDP hostdata->pendingr);
624 if (hostdata->pendingw)
625 PRINTP(" %d pending writes" ANDP hostdata->pendingw);
626 if (hostdata->pendingr || hostdata->pendingw)
627 PRINTP("\n");
628 for (dev = scsi_devices; dev; dev=dev->next) {
629 if (dev->host == scsi_ptr) {
630 unsigned long br = hostdata->bytes_read[dev->id];
631 unsigned long bw = hostdata->bytes_write[dev->id];
632 long tr = hostdata->time_read[dev->id] / HZ;
633 long tw = hostdata->time_write[dev->id] / HZ;
634
635 PRINTP(" T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? private_scsi_device_types[(int)dev->type] : "Unknown");
636 for (i=0; i<8; i++)
637 if (dev->vendor[i] >= 0x20)
638 *(buffer+(len++)) = dev->vendor[i];
639 *(buffer+(len++)) = ' ';
640 for (i=0; i<16; i++)
641 if (dev->model[i] >= 0x20)
642 *(buffer+(len++)) = dev->model[i];
643 *(buffer+(len++)) = ' ';
644 for (i=0; i<4; i++)
645 if (dev->rev[i] >= 0x20)
646 *(buffer+(len++)) = dev->rev[i];
647 *(buffer+(len++)) = ' ';
648
649 PRINTP("\n%10ld kb read in %5ld secs" ANDP br/1024 ANDP tr);
650 if (tr)
651 PRINTP(" @ %5ld bps" ANDP br / tr);
652
653 PRINTP("\n%10ld kb written in %5ld secs" ANDP bw/1024 ANDP tw);
654 if (tw)
655 PRINTP(" @ %5ld bps" ANDP bw / tw);
656 PRINTP("\n");
657 }
658 }
659 #endif
660
661 status = NCR5380_read(STATUS_REG);
662 if (!(status & SR_REQ))
663 PRINTP("REQ not asserted, phase unknown.\n");
664 else {
665 for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
666 (phases[i].value != (status & PHASE_MASK)); ++i)
667 ;
668 PRINTP("Phase %s\n" ANDP phases[i].name);
669 }
670
671 if (!hostdata->connected) {
672 PRINTP("No currently connected command\n");
673 } else {
674 len += sprint_Scsi_Cmnd (buffer, len, (Scsi_Cmnd *) hostdata->connected);
675 }
676
677 PRINTP("issue_queue\n");
678
679 for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr;
680 ptr = (Scsi_Cmnd *) ptr->host_scribble)
681 len += sprint_Scsi_Cmnd (buffer, len, ptr);
682
683 PRINTP("disconnected_queue\n");
684
685 for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
686 ptr = (Scsi_Cmnd *) ptr->host_scribble)
687 len += sprint_Scsi_Cmnd (buffer, len, ptr);
688
689 *start = buffer + offset;
690 len -= offset;
691 if (len > length)
692 len = length;
693 sti();
694 return len;
695 }
696
697 #undef PRINTP
698 #undef ANDP
699
700 #ifdef MODULE
701
702 Scsi_Host_Template driver_template = GENERIC_NCR5380;
703
704 #include <linux/module.h>
705 #include "scsi_module.c"
706 #endif