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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80#include <linux/module.h>
81#include <linux/init.h>
82#include <linux/interrupt.h>
83#include <linux/blkdev.h>
84#include <linux/errno.h>
85#include <linux/string.h>
86#include <linux/ioport.h>
87#include <linux/proc_fs.h>
88#include <linux/delay.h>
89#include <linux/mca.h>
90#include <linux/spinlock.h>
91#include <linux/slab.h>
92#include <scsi/scsicam.h>
93#include <linux/mca-legacy.h>
94
95#include <asm/io.h>
96#include <asm/system.h>
97
98#include "scsi.h"
99#include <scsi/scsi_host.h>
100
101#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
102
103
104
105#define DEBUG 0
106#define ENABLE_PARITY 1
107
108
109
110#if DEBUG
111#define EVERY_ACCESS 0
112#define ERRORS_ONLY 1
113#define DEBUG_MESSAGES 1
114#define DEBUG_ABORT 1
115#define DEBUG_RESET 1
116#define DEBUG_RACE 1
117#else
118#define EVERY_ACCESS 0
119#define ERRORS_ONLY 0
120#define DEBUG_MESSAGES 0
121#define DEBUG_ABORT 0
122#define DEBUG_RESET 0
123#define DEBUG_RACE 0
124#endif
125
126
127#if EVERY_ACCESS
128#undef ERRORS_ONLY
129#define ERRORS_ONLY 0
130#endif
131
132#if ENABLE_PARITY
133#define PARITY_MASK 0x08
134#else
135#define PARITY_MASK 0x00
136#endif
137
138enum chip_type {
139 unknown = 0x00,
140 tmc1800 = 0x01,
141 tmc18c50 = 0x02,
142 tmc18c30 = 0x03,
143};
144
145enum {
146 in_arbitration = 0x02,
147 in_selection = 0x04,
148 in_other = 0x08,
149 disconnect = 0x10,
150 aborted = 0x20,
151 sent_ident = 0x40,
152};
153
154enum in_port_type {
155 Read_SCSI_Data = 0,
156 SCSI_Status = 1,
157 TMC_Status = 2,
158 FIFO_Status = 3,
159 Interrupt_Cond = 4,
160 LSB_ID_Code = 5,
161 MSB_ID_Code = 6,
162 Read_Loopback = 7,
163 SCSI_Data_NoACK = 8,
164 Interrupt_Status = 9,
165 Configuration1 = 10,
166 Configuration2 = 11,
167 Read_FIFO = 12,
168 FIFO_Data_Count = 14
169};
170
171enum out_port_type {
172 Write_SCSI_Data = 0,
173 SCSI_Cntl = 1,
174 Interrupt_Cntl = 2,
175 SCSI_Mode_Cntl = 3,
176 TMC_Cntl = 4,
177 Memory_Cntl = 5,
178 Write_Loopback = 7,
179 IO_Control = 11,
180 Write_FIFO = 12
181};
182
183struct fd_hostdata {
184 unsigned long _bios_base;
185 int _bios_major;
186 int _bios_minor;
187 volatile int _in_command;
188 Scsi_Cmnd *_current_SC;
189 enum chip_type _chip;
190 int _adapter_mask;
191 int _fifo_count;
192
193 char _adapter_name[64];
194#if DEBUG_RACE
195 volatile int _in_interrupt_flag;
196#endif
197
198 int _SCSI_Mode_Cntl_port;
199 int _FIFO_Data_Count_port;
200 int _Interrupt_Cntl_port;
201 int _Interrupt_Status_port;
202 int _Interrupt_Cond_port;
203 int _Read_FIFO_port;
204 int _Read_SCSI_Data_port;
205 int _SCSI_Cntl_port;
206 int _SCSI_Data_NoACK_port;
207 int _SCSI_Status_port;
208 int _TMC_Cntl_port;
209 int _TMC_Status_port;
210 int _Write_FIFO_port;
211 int _Write_SCSI_Data_port;
212
213 int _FIFO_Size;
214
215
216 int _Bytes_Read;
217 int _Bytes_Written;
218 int _INTR_Processed;
219};
220
221#define FD_MAX_HOSTS 3
222
223#define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata)
224#define bios_base (HOSTDATA(shpnt)->_bios_base)
225#define bios_major (HOSTDATA(shpnt)->_bios_major)
226#define bios_minor (HOSTDATA(shpnt)->_bios_minor)
227#define in_command (HOSTDATA(shpnt)->_in_command)
228#define current_SC (HOSTDATA(shpnt)->_current_SC)
229#define chip (HOSTDATA(shpnt)->_chip)
230#define adapter_mask (HOSTDATA(shpnt)->_adapter_mask)
231#define FIFO_COUNT (HOSTDATA(shpnt)->_fifo_count)
232#define adapter_name (HOSTDATA(shpnt)->_adapter_name)
233#if DEBUG_RACE
234#define in_interrupt_flag (HOSTDATA(shpnt)->_in_interrupt_flag)
235#endif
236#define SCSI_Mode_Cntl_port (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port)
237#define FIFO_Data_Count_port (HOSTDATA(shpnt)->_FIFO_Data_Count_port)
238#define Interrupt_Cntl_port (HOSTDATA(shpnt)->_Interrupt_Cntl_port)
239#define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port)
240#define Interrupt_Cond_port (HOSTDATA(shpnt)->_Interrupt_Cond_port)
241#define Read_FIFO_port (HOSTDATA(shpnt)->_Read_FIFO_port)
242#define Read_SCSI_Data_port (HOSTDATA(shpnt)->_Read_SCSI_Data_port)
243#define SCSI_Cntl_port (HOSTDATA(shpnt)->_SCSI_Cntl_port)
244#define SCSI_Data_NoACK_port (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port)
245#define SCSI_Status_port (HOSTDATA(shpnt)->_SCSI_Status_port)
246#define TMC_Cntl_port (HOSTDATA(shpnt)->_TMC_Cntl_port)
247#define TMC_Status_port (HOSTDATA(shpnt)->_TMC_Status_port)
248#define Write_FIFO_port (HOSTDATA(shpnt)->_Write_FIFO_port)
249#define Write_SCSI_Data_port (HOSTDATA(shpnt)->_Write_SCSI_Data_port)
250#define FIFO_Size (HOSTDATA(shpnt)->_FIFO_Size)
251#define Bytes_Read (HOSTDATA(shpnt)->_Bytes_Read)
252#define Bytes_Written (HOSTDATA(shpnt)->_Bytes_Written)
253#define INTR_Processed (HOSTDATA(shpnt)->_INTR_Processed)
254
255struct fd_mcs_adapters_struct {
256 char *name;
257 int id;
258 enum chip_type fd_chip;
259 int fifo_size;
260 int fifo_count;
261};
262
263#define REPLY_ID 0x5137
264
265static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
266 {"Future Domain SCSI Adapter MCS-700(18C50)",
267 0x60e9,
268 tmc18c50,
269 0x2000,
270 4},
271 {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
272 0x6127,
273 tmc1800,
274 0x2000,
275 4},
276 {"Reply Sound Blaster/SCSI Adapter",
277 REPLY_ID,
278 tmc18c30,
279 0x800,
280 2},
281};
282
283#define FD_BRDS ARRAY_SIZE(fd_mcs_adapters)
284
285static irqreturn_t fd_mcs_intr(int irq, void *dev_id);
286
287static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
288static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
289static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
290
291
292static int found = 0;
293static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL };
294
295static int user_fifo_count = 0;
296static int user_fifo_size = 0;
297
298#ifndef MODULE
299static int __init fd_mcs_setup(char *str)
300{
301 static int done_setup = 0;
302 int ints[3];
303
304 get_options(str, 3, ints);
305 if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) {
306 printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n");
307 return 0;
308 }
309
310 user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
311 user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
312 return 1;
313}
314
315__setup("fd_mcs=", fd_mcs_setup);
316#endif
317
318static void print_banner(struct Scsi_Host *shpnt)
319{
320 printk("scsi%d <fd_mcs>: ", shpnt->host_no);
321
322 if (bios_base) {
323 printk("BIOS at 0x%lX", bios_base);
324 } else {
325 printk("No BIOS");
326 }
327
328 printk(", HostID %d, %s Chip, IRQ %d, IO 0x%lX\n", shpnt->this_id, chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? "TMC-18C30" : (chip == tmc1800 ? "TMC-1800" : "Unknown")), shpnt->irq, shpnt->io_port);
329}
330
331
332static void do_pause(unsigned amount)
333{
334 do {
335 mdelay(10);
336 } while (--amount);
337}
338
339static void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt)
340{
341 outb(0, SCSI_Cntl_port);
342 outb(0, SCSI_Mode_Cntl_port);
343 if (chip == tmc18c50 || chip == tmc18c30)
344 outb(0x21 | PARITY_MASK, TMC_Cntl_port);
345 else
346 outb(0x01 | PARITY_MASK, TMC_Cntl_port);
347}
348
349static int fd_mcs_detect(struct scsi_host_template * tpnt)
350{
351 int loop;
352 struct Scsi_Host *shpnt;
353
354
355 int slot;
356 u_char pos2, pos3, pos4;
357 int id, port, irq;
358 unsigned long bios;
359
360
361 if (!MCA_bus)
362 return 0;
363
364
365 id = 7;
366
367 for (loop = 0; loop < FD_BRDS; loop++) {
368 slot = 0;
369 while (MCA_NOTFOUND != (slot = mca_find_adapter(fd_mcs_adapters[loop].id, slot))) {
370
371
372
373
374 printk(KERN_INFO "scsi <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1);
375
376 pos2 = mca_read_stored_pos(slot, 2);
377 pos3 = mca_read_stored_pos(slot, 3);
378 pos4 = mca_read_stored_pos(slot, 4);
379
380
381 slot++;
382
383 if (fd_mcs_adapters[loop].id == REPLY_ID) {
384 static int reply_irq[] = { 10, 11, 14, 15 };
385
386 bios = 0;
387
388 if (pos2 & 0x2)
389 port = ports[pos4 & 0x3];
390 else
391 continue;
392
393
394 irq = reply_irq[((pos4 >> 2) & 0x1) + 2 * ((pos4 >> 4) & 0x1)];
395 } else {
396 bios = addresses[pos2 >> 6];
397 port = ports[(pos2 >> 4) & 0x03];
398 irq = interrupts[(pos2 >> 1) & 0x07];
399 }
400
401 if (irq) {
402
403 mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name);
404
405
406 if (request_irq(irq, fd_mcs_intr, IRQF_SHARED, "fd_mcs", hosts)) {
407 printk(KERN_ERR "fd_mcs: interrupt is not available, skipping...\n");
408 continue;
409 }
410
411
412 if (request_region(port, 0x10, "fd_mcs")) {
413 printk(KERN_ERR "fd_mcs: I/O region is already in use, skipping...\n");
414 continue;
415 }
416
417 if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) {
418 printk(KERN_ERR "fd_mcs: scsi_register() failed\n");
419 release_region(port, 0x10);
420 free_irq(irq, hosts);
421 continue;
422 }
423
424
425
426 strcpy(adapter_name, fd_mcs_adapters[loop].name);
427
428
429 chip = fd_mcs_adapters[loop].fd_chip;
430
431 FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count;
432 FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size;
433
434
435#ifdef NOT_USED
436
437
438
439
440
441 outb(0x80, port + IO_Control);
442 if ((inb(port + Configuration2) & 0x80) == 0x80) {
443 outb(0x00, port + IO_Control);
444 if ((inb(port + Configuration2) & 0x80) == 0x00) {
445 chip = tmc18c30;
446 FIFO_Size = 0x800;
447
448 printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
449 }
450 }
451
452
453
454
455
456 if (inb(port + Configuration2) & 0x02) {
457 chip = tmc18c30;
458 FIFO_Size = 0x800;
459
460 printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
461 }
462
463#endif
464
465
466
467 shpnt->reverse_ordering = 1;
468
469
470
471 hosts[found++] = shpnt;
472
473 shpnt->this_id = id;
474 shpnt->irq = irq;
475 shpnt->io_port = port;
476 shpnt->n_io_port = 0x10;
477
478
479 bios_base = bios;
480 adapter_mask = (1 << id);
481
482
483 SCSI_Mode_Cntl_port = port + SCSI_Mode_Cntl;
484 FIFO_Data_Count_port = port + FIFO_Data_Count;
485 Interrupt_Cntl_port = port + Interrupt_Cntl;
486 Interrupt_Status_port = port + Interrupt_Status;
487 Interrupt_Cond_port = port + Interrupt_Cond;
488 Read_FIFO_port = port + Read_FIFO;
489 Read_SCSI_Data_port = port + Read_SCSI_Data;
490 SCSI_Cntl_port = port + SCSI_Cntl;
491 SCSI_Data_NoACK_port = port + SCSI_Data_NoACK;
492 SCSI_Status_port = port + SCSI_Status;
493 TMC_Cntl_port = port + TMC_Cntl;
494 TMC_Status_port = port + TMC_Status;
495 Write_FIFO_port = port + Write_FIFO;
496 Write_SCSI_Data_port = port + Write_SCSI_Data;
497
498 Bytes_Read = 0;
499 Bytes_Written = 0;
500 INTR_Processed = 0;
501
502
503 print_banner(shpnt);
504
505
506 outb(1, SCSI_Cntl_port);
507 do_pause(2);
508 outb(0, SCSI_Cntl_port);
509 do_pause(115);
510 outb(0, SCSI_Mode_Cntl_port);
511 outb(PARITY_MASK, TMC_Cntl_port);
512
513 }
514 }
515
516 if (found == FD_MAX_HOSTS) {
517 printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS);
518 break;
519 }
520 }
521
522 return found;
523}
524
525static const char *fd_mcs_info(struct Scsi_Host *shpnt)
526{
527 return adapter_name;
528}
529
530static int TOTAL_INTR = 0;
531
532
533
534
535
536
537
538
539
540
541
542static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
543{
544 int len = 0;
545
546 if (inout)
547 return (-ENOSYS);
548
549 *start = buffer + offset;
550
551 len += sprintf(buffer + len, "Future Domain MCS-600/700 Driver %s\n", DRIVER_VERSION);
552 len += sprintf(buffer + len, "HOST #%d: %s\n", shpnt->host_no, adapter_name);
553 len += sprintf(buffer + len, "FIFO Size=0x%x, FIFO Count=%d\n", FIFO_Size, FIFO_COUNT);
554 len += sprintf(buffer + len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n", TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written);
555
556 if ((len -= offset) <= 0)
557 return 0;
558 if (len > length)
559 len = length;
560 return len;
561}
562
563static int fd_mcs_select(struct Scsi_Host *shpnt, int target)
564{
565 int status;
566 unsigned long timeout;
567
568 outb(0x82, SCSI_Cntl_port);
569 outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port);
570
571
572 outb(PARITY_MASK, TMC_Cntl_port);
573
574 timeout = 350;
575
576
577 do {
578 status = inb(SCSI_Status_port);
579 if (status & 1) {
580
581 outb(0x80, SCSI_Cntl_port);
582 return 0;
583 }
584 udelay(1000);
585 } while (--timeout);
586
587
588 fd_mcs_make_bus_idle(shpnt);
589#if EVERY_ACCESS
590 if (!target)
591 printk("Selection failed\n");
592#endif
593#if ERRORS_ONLY
594 if (!target) {
595 static int flag = 0;
596
597 if (!flag)
598 ++flag;
599 else
600 printk("fd_mcs: Selection failed\n");
601 }
602#endif
603 return 1;
604}
605
606static void my_done(struct Scsi_Host *shpnt, int error)
607{
608 if (in_command) {
609 in_command = 0;
610 outb(0x00, Interrupt_Cntl_port);
611 fd_mcs_make_bus_idle(shpnt);
612 current_SC->result = error;
613 current_SC->scsi_done(current_SC);
614 } else {
615 panic("fd_mcs: my_done() called outside of command\n");
616 }
617#if DEBUG_RACE
618 in_interrupt_flag = 0;
619#endif
620}
621
622
623static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
624{
625 unsigned long flags;
626 int status;
627 int done = 0;
628 unsigned data_count, tmp_count;
629
630 int i = 0;
631 struct Scsi_Host *shpnt;
632
633 TOTAL_INTR++;
634
635
636 while ((shpnt = hosts[i++])) {
637 if ((inb(TMC_Status_port)) & 1)
638 break;
639 }
640
641
642 if (!shpnt) {
643 return IRQ_NONE;
644 }
645
646 INTR_Processed++;
647
648 outb(0x00, Interrupt_Cntl_port);
649
650
651 if (current_SC->SCp.phase & aborted) {
652#if DEBUG_ABORT
653 printk("Interrupt after abort, ignoring\n");
654#endif
655
656 }
657#if DEBUG_RACE
658 ++in_interrupt_flag;
659#endif
660
661 if (current_SC->SCp.phase & in_arbitration) {
662 status = inb(TMC_Status_port);
663 if (!(status & 0x02)) {
664#if EVERY_ACCESS
665 printk(" AFAIL ");
666#endif
667 spin_lock_irqsave(shpnt->host_lock, flags);
668 my_done(shpnt, DID_BUS_BUSY << 16);
669 spin_unlock_irqrestore(shpnt->host_lock, flags);
670 return IRQ_HANDLED;
671 }
672 current_SC->SCp.phase = in_selection;
673
674 outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port);
675
676 outb(0x82, SCSI_Cntl_port);
677 outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port);
678
679
680 outb(0x10 | PARITY_MASK, TMC_Cntl_port);
681#if DEBUG_RACE
682 in_interrupt_flag = 0;
683#endif
684 return IRQ_HANDLED;
685 } else if (current_SC->SCp.phase & in_selection) {
686 status = inb(SCSI_Status_port);
687 if (!(status & 0x01)) {
688
689 if (fd_mcs_select(shpnt, scmd_id(current_SC))) {
690#if EVERY_ACCESS
691 printk(" SFAIL ");
692#endif
693 spin_lock_irqsave(shpnt->host_lock, flags);
694 my_done(shpnt, DID_NO_CONNECT << 16);
695 spin_unlock_irqrestore(shpnt->host_lock, flags);
696 return IRQ_HANDLED;
697 } else {
698#if EVERY_ACCESS
699 printk(" AltSel ");
700#endif
701
702 outb(0x10 | PARITY_MASK, TMC_Cntl_port);
703 }
704 }
705 current_SC->SCp.phase = in_other;
706 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
707 outb(0x80, SCSI_Cntl_port);
708#if DEBUG_RACE
709 in_interrupt_flag = 0;
710#endif
711 return IRQ_HANDLED;
712 }
713
714
715
716 status = inb(SCSI_Status_port);
717
718 if (status & 0x10) {
719
720 switch (status & 0x0e) {
721
722 case 0x08:
723 outb(current_SC->cmnd[current_SC->SCp.sent_command++], Write_SCSI_Data_port);
724#if EVERY_ACCESS
725 printk("CMD = %x,", current_SC->cmnd[current_SC->SCp.sent_command - 1]);
726#endif
727 break;
728 case 0x00:
729 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
730 current_SC->SCp.have_data_in = -1;
731 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
732 }
733 break;
734 case 0x04:
735 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
736 current_SC->SCp.have_data_in = 1;
737 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
738 }
739 break;
740 case 0x0c:
741 current_SC->SCp.Status = inb(Read_SCSI_Data_port);
742#if EVERY_ACCESS
743 printk("Status = %x, ", current_SC->SCp.Status);
744#endif
745#if ERRORS_ONLY
746 if (current_SC->SCp.Status && current_SC->SCp.Status != 2 && current_SC->SCp.Status != 8) {
747 printk("ERROR fd_mcs: target = %d, command = %x, status = %x\n", current_SC->device->id, current_SC->cmnd[0], current_SC->SCp.Status);
748 }
749#endif
750 break;
751 case 0x0a:
752 outb(MESSAGE_REJECT, Write_SCSI_Data_port);
753 break;
754 case 0x0e:
755 current_SC->SCp.Message = inb(Read_SCSI_Data_port);
756#if EVERY_ACCESS
757 printk("Message = %x, ", current_SC->SCp.Message);
758#endif
759 if (!current_SC->SCp.Message)
760 ++done;
761#if DEBUG_MESSAGES || EVERY_ACCESS
762 if (current_SC->SCp.Message) {
763 printk("fd_mcs: message = %x\n", current_SC->SCp.Message);
764 }
765#endif
766 break;
767 }
768 }
769
770 if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897 switch (current_SC->cmnd[0]) {
898 case CHANGE_DEFINITION:
899 case COMPARE:
900 case COPY:
901 case COPY_VERIFY:
902 case LOG_SELECT:
903 case MODE_SELECT:
904 case MODE_SELECT_10:
905 case SEND_DIAGNOSTIC:
906 case WRITE_BUFFER:
907
908 case FORMAT_UNIT:
909 case REASSIGN_BLOCKS:
910 case RESERVE:
911 case SEARCH_EQUAL:
912 case SEARCH_HIGH:
913 case SEARCH_LOW:
914 case WRITE_6:
915 case WRITE_10:
916 case WRITE_VERIFY:
917 case 0x3f:
918 case 0x41:
919
920 case 0xb1:
921 case 0xb0:
922 case 0xb2:
923 case 0xaa:
924 case 0xae:
925
926 case 0x24:
927
928 case 0x38:
929 case 0x3d:
930
931 case 0xb6:
932
933 case 0xea:
934
935 current_SC->SCp.have_data_in = -1;
936 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
937 break;
938
939 case 0x00:
940 default:
941
942 current_SC->SCp.have_data_in = 1;
943 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
944 break;
945 }
946 }
947
948 if (current_SC->SCp.have_data_in == -1) {
949 while ((data_count = FIFO_Size - inw(FIFO_Data_Count_port)) > 512) {
950#if EVERY_ACCESS
951 printk("DC=%d, ", data_count);
952#endif
953 if (data_count > current_SC->SCp.this_residual)
954 data_count = current_SC->SCp.this_residual;
955 if (data_count > 0) {
956#if EVERY_ACCESS
957 printk("%d OUT, ", data_count);
958#endif
959 if (data_count == 1) {
960 Bytes_Written++;
961
962 outb(*current_SC->SCp.ptr++, Write_FIFO_port);
963 --current_SC->SCp.this_residual;
964 } else {
965 data_count >>= 1;
966 tmp_count = data_count << 1;
967 outsw(Write_FIFO_port, current_SC->SCp.ptr, data_count);
968 current_SC->SCp.ptr += tmp_count;
969 Bytes_Written += tmp_count;
970 current_SC->SCp.this_residual -= tmp_count;
971 }
972 }
973 if (!current_SC->SCp.this_residual) {
974 if (current_SC->SCp.buffers_residual) {
975 --current_SC->SCp.buffers_residual;
976 ++current_SC->SCp.buffer;
977 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
978 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
979 } else
980 break;
981 }
982 }
983 } else if (current_SC->SCp.have_data_in == 1) {
984 while ((data_count = inw(FIFO_Data_Count_port)) > 0) {
985#if EVERY_ACCESS
986 printk("DC=%d, ", data_count);
987#endif
988 if (data_count > current_SC->SCp.this_residual)
989 data_count = current_SC->SCp.this_residual;
990 if (data_count) {
991#if EVERY_ACCESS
992 printk("%d IN, ", data_count);
993#endif
994 if (data_count == 1) {
995 Bytes_Read++;
996 *current_SC->SCp.ptr++ = inb(Read_FIFO_port);
997 --current_SC->SCp.this_residual;
998 } else {
999 data_count >>= 1;
1000 tmp_count = data_count << 1;
1001 insw(Read_FIFO_port, current_SC->SCp.ptr, data_count);
1002 current_SC->SCp.ptr += tmp_count;
1003 Bytes_Read += tmp_count;
1004 current_SC->SCp.this_residual -= tmp_count;
1005 }
1006 }
1007 if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
1008 --current_SC->SCp.buffers_residual;
1009 ++current_SC->SCp.buffer;
1010 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1011 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1012 }
1013 }
1014 }
1015
1016 if (done) {
1017#if EVERY_ACCESS
1018 printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in);
1019#endif
1020
1021#if EVERY_ACCESS
1022 printk("BEFORE MY_DONE. . .");
1023#endif
1024 spin_lock_irqsave(shpnt->host_lock, flags);
1025 my_done(shpnt, (current_SC->SCp.Status & 0xff)
1026 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
1027 spin_unlock_irqrestore(shpnt->host_lock, flags);
1028#if EVERY_ACCESS
1029 printk("RETURNING.\n");
1030#endif
1031
1032 } else {
1033 if (current_SC->SCp.phase & disconnect) {
1034 outb(0xd0 | FIFO_COUNT, Interrupt_Cntl_port);
1035 outb(0x00, SCSI_Cntl_port);
1036 } else {
1037 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
1038 }
1039 }
1040#if DEBUG_RACE
1041 in_interrupt_flag = 0;
1042#endif
1043 return IRQ_HANDLED;
1044}
1045
1046static int fd_mcs_release(struct Scsi_Host *shpnt)
1047{
1048 int i, this_host, irq_usage;
1049
1050 release_region(shpnt->io_port, shpnt->n_io_port);
1051
1052 this_host = -1;
1053 irq_usage = 0;
1054 for (i = 0; i < found; i++) {
1055 if (shpnt == hosts[i])
1056 this_host = i;
1057 if (shpnt->irq == hosts[i]->irq)
1058 irq_usage++;
1059 }
1060
1061
1062 if (1 == irq_usage)
1063 free_irq(shpnt->irq, hosts);
1064
1065 found--;
1066
1067 for (i = this_host; i < found; i++)
1068 hosts[i] = hosts[i + 1];
1069
1070 hosts[found] = NULL;
1071
1072 return 0;
1073}
1074
1075static int fd_mcs_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
1076{
1077 struct Scsi_Host *shpnt = SCpnt->device->host;
1078
1079 if (in_command) {
1080 panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
1081 }
1082#if EVERY_ACCESS
1083 printk("queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1084 SCpnt->target, *(unsigned char *) SCpnt->cmnd,
1085 scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
1086#endif
1087
1088 fd_mcs_make_bus_idle(shpnt);
1089
1090 SCpnt->scsi_done = done;
1091 current_SC = SCpnt;
1092
1093
1094
1095 if (scsi_bufflen(current_SC)) {
1096 current_SC->SCp.buffer = scsi_sglist(current_SC);
1097 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1098 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1099 current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
1100 } else {
1101 current_SC->SCp.ptr = NULL;
1102 current_SC->SCp.this_residual = 0;
1103 current_SC->SCp.buffer = NULL;
1104 current_SC->SCp.buffers_residual = 0;
1105 }
1106
1107
1108 current_SC->SCp.Status = 0;
1109 current_SC->SCp.Message = 0;
1110 current_SC->SCp.have_data_in = 0;
1111 current_SC->SCp.sent_command = 0;
1112 current_SC->SCp.phase = in_arbitration;
1113
1114
1115 outb(0x00, Interrupt_Cntl_port);
1116 outb(0x00, SCSI_Cntl_port);
1117 outb(adapter_mask, SCSI_Data_NoACK_port);
1118 in_command = 1;
1119 outb(0x20, Interrupt_Cntl_port);
1120 outb(0x14 | PARITY_MASK, TMC_Cntl_port);
1121
1122 return 0;
1123}
1124
1125static DEF_SCSI_QCMD(fd_mcs_queue)
1126
1127#if DEBUG_ABORT || DEBUG_RESET
1128static void fd_mcs_print_info(Scsi_Cmnd * SCpnt)
1129{
1130 unsigned int imr;
1131 unsigned int irr;
1132 unsigned int isr;
1133 struct Scsi_Host *shpnt = SCpnt->host;
1134
1135 if (!SCpnt || !SCpnt->host) {
1136 printk("fd_mcs: cannot provide detailed information\n");
1137 }
1138
1139 printk("%s\n", fd_mcs_info(SCpnt->host));
1140 print_banner(SCpnt->host);
1141 switch (SCpnt->SCp.phase) {
1142 case in_arbitration:
1143 printk("arbitration ");
1144 break;
1145 case in_selection:
1146 printk("selection ");
1147 break;
1148 case in_other:
1149 printk("other ");
1150 break;
1151 default:
1152 printk("unknown ");
1153 break;
1154 }
1155
1156 printk("(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1157 SCpnt->SCp.phase, SCpnt->device->id, *(unsigned char *) SCpnt->cmnd,
1158 scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
1159 printk("sent_command = %d, have_data_in = %d, timeout = %d\n", SCpnt->SCp.sent_command, SCpnt->SCp.have_data_in, SCpnt->timeout);
1160#if DEBUG_RACE
1161 printk("in_interrupt_flag = %d\n", in_interrupt_flag);
1162#endif
1163
1164 imr = (inb(0x0a1) << 8) + inb(0x21);
1165 outb(0x0a, 0xa0);
1166 irr = inb(0xa0) << 8;
1167 outb(0x0a, 0x20);
1168 irr += inb(0x20);
1169 outb(0x0b, 0xa0);
1170 isr = inb(0xa0) << 8;
1171 outb(0x0b, 0x20);
1172 isr += inb(0x20);
1173
1174
1175 printk("IMR = 0x%04x", imr);
1176 if (imr & (1 << shpnt->irq))
1177 printk(" (masked)");
1178 printk(", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr);
1179
1180 printk("SCSI Status = 0x%02x\n", inb(SCSI_Status_port));
1181 printk("TMC Status = 0x%02x", inb(TMC_Status_port));
1182 if (inb(TMC_Status_port) & 1)
1183 printk(" (interrupt)");
1184 printk("\n");
1185 printk("Interrupt Status = 0x%02x", inb(Interrupt_Status_port));
1186 if (inb(Interrupt_Status_port) & 0x08)
1187 printk(" (enabled)");
1188 printk("\n");
1189 if (chip == tmc18c50 || chip == tmc18c30) {
1190 printk("FIFO Status = 0x%02x\n", inb(shpnt->io_port + FIFO_Status));
1191 printk("Int. Condition = 0x%02x\n", inb(shpnt->io_port + Interrupt_Cond));
1192 }
1193 printk("Configuration 1 = 0x%02x\n", inb(shpnt->io_port + Configuration1));
1194 if (chip == tmc18c50 || chip == tmc18c30)
1195 printk("Configuration 2 = 0x%02x\n", inb(shpnt->io_port + Configuration2));
1196}
1197#endif
1198
1199static int fd_mcs_abort(Scsi_Cmnd * SCpnt)
1200{
1201 struct Scsi_Host *shpnt = SCpnt->device->host;
1202
1203 unsigned long flags;
1204#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1205 printk("fd_mcs: abort ");
1206#endif
1207
1208 spin_lock_irqsave(shpnt->host_lock, flags);
1209 if (!in_command) {
1210#if EVERY_ACCESS || ERRORS_ONLY
1211 printk(" (not in command)\n");
1212#endif
1213 spin_unlock_irqrestore(shpnt->host_lock, flags);
1214 return FAILED;
1215 } else
1216 printk("\n");
1217
1218#if DEBUG_ABORT
1219 fd_mcs_print_info(SCpnt);
1220#endif
1221
1222 fd_mcs_make_bus_idle(shpnt);
1223
1224 current_SC->SCp.phase |= aborted;
1225
1226 current_SC->result = DID_ABORT << 16;
1227
1228
1229 my_done(shpnt, DID_ABORT << 16);
1230
1231 spin_unlock_irqrestore(shpnt->host_lock, flags);
1232 return SUCCESS;
1233}
1234
1235static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
1236 struct Scsi_Host *shpnt = SCpnt->device->host;
1237 unsigned long flags;
1238
1239#if DEBUG_RESET
1240 static int called_once = 0;
1241#endif
1242
1243#if ERRORS_ONLY
1244 if (SCpnt)
1245 printk("fd_mcs: SCSI Bus Reset\n");
1246#endif
1247
1248#if DEBUG_RESET
1249 if (called_once)
1250 fd_mcs_print_info(current_SC);
1251 called_once = 1;
1252#endif
1253
1254 spin_lock_irqsave(shpnt->host_lock, flags);
1255
1256 outb(1, SCSI_Cntl_port);
1257 do_pause(2);
1258 outb(0, SCSI_Cntl_port);
1259 do_pause(115);
1260 outb(0, SCSI_Mode_Cntl_port);
1261 outb(PARITY_MASK, TMC_Cntl_port);
1262
1263 spin_unlock_irqrestore(shpnt->host_lock, flags);
1264
1265
1266
1267
1268 return SUCCESS;
1269}
1270
1271#include <scsi/scsi_ioctl.h>
1272
1273static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
1274 sector_t capacity, int *info_array)
1275{
1276 unsigned char *p = scsi_bios_ptable(bdev);
1277 int size = capacity;
1278
1279
1280
1281
1282 if (p && p[65] == 0xaa && p[64] == 0x55
1283 && p[4]) {
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 info_array[0] = p[5] + 1;
1314 info_array[1] = p[6] & 0x3f;
1315 } else {
1316
1317
1318
1319 if ((unsigned int) size >= 0x7e0000U)
1320 {
1321 info_array[0] = 0xff;
1322 info_array[1] = 0x3f;
1323 } else if ((unsigned int) size >= 0x200000U) {
1324 info_array[0] = 0x80;
1325 info_array[1] = 0x3f;
1326 } else {
1327 info_array[0] = 0x40;
1328 info_array[1] = 0x20;
1329 }
1330 }
1331
1332 info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]);
1333 kfree(p);
1334 return 0;
1335}
1336
1337static struct scsi_host_template driver_template = {
1338 .proc_name = "fd_mcs",
1339 .proc_info = fd_mcs_proc_info,
1340 .detect = fd_mcs_detect,
1341 .release = fd_mcs_release,
1342 .info = fd_mcs_info,
1343 .queuecommand = fd_mcs_queue,
1344 .eh_abort_handler = fd_mcs_abort,
1345 .eh_bus_reset_handler = fd_mcs_bus_reset,
1346 .bios_param = fd_mcs_biosparam,
1347 .can_queue = 1,
1348 .this_id = 7,
1349 .sg_tablesize = 64,
1350 .cmd_per_lun = 1,
1351 .use_clustering = DISABLE_CLUSTERING,
1352};
1353#include "scsi_module.c"
1354
1355MODULE_LICENSE("GPL");
1356