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