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