1 /* fd_mcs.c -- Future Domain MCS 600/700 (or IBM OEM) driver
3 * FutureDomain MCS-600/700 v0.2 03/11/1998 by ZP Gu (zpg@castle.net)
5 * This driver is cloned from fdomain.* to specifically support
6 * the Future Domain MCS 600/700 MCA SCSI adapters. Some PS/2s
7 * also equipped with IBM Fast SCSI Adapter/A which is an OEM
10 * This driver also supports Reply SB16/SCSI card (the SCSI part).
12 * What makes this driver different is that this driver is MCA only
13 * and it supports multiple adapters in the same system, IRQ
14 * sharing, some driver statistics, and maps highest SCSI id to sda.
15 * All cards are auto-detected.
17 * Assumptions: TMC-1800/18C50/18C30, BIOS >= 3.4
19 * LILO command-line options:
20 * fd_mcs=<FIFO_COUNT>[,<FIFO_SIZE>]
22 * ********************************************************
23 * Please see Copyrights/Comments in fdomain.* for credits.
24 * Following is from fdomain.c for acknowledgement:
26 * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu
27 * Revised: Wed Oct 2 11:10:55 1996 by r.faith@ieee.org
28 * Author: Rickard E. Faith, faith@cs.unc.edu
29 * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
31 * $Id: fdomain.c,v 5.45 1996/10/02 15:13:06 root Exp $
33 * This program is free software; you can redistribute it and/or modify it
34 * under the terms of the GNU General Public License as published by the
35 * Free Software Foundation; either version 2, or (at your option) any
38 * This program is distributed in the hope that it will be useful, but
39 * WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41 * General Public License for more details.
43 * You should have received a copy of the GNU General Public License along
44 * with this program; if not, write to the Free Software Foundation, Inc.,
45 * 675 Mass Ave, Cambridge, MA 02139, USA.
47 **************************************************************************
49 NOTES ON USER DEFINABLE OPTIONS:
51 DEBUG: This turns on the printing of various debug information.
53 ENABLE_PARITY: This turns on SCSI parity checking. With the current
54 driver, all attached devices must support SCSI parity. If none of your
55 devices support parity, then you can probably get the driver to work by
56 turning this option off. I have no way of testing this, however, and it
57 would appear that no one ever uses this option.
59 FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the
60 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by
61 the SCSI device, an interrupt will be raised. Therefore, this could be as
62 low as 0, or as high as 16. Note, however, that values which are too high
63 or too low seem to prevent any interrupts from occurring, and thereby lock
64 up the machine. I have found that 2 is a good number, but throughput may
65 be increased by changing this value to values which are close to 2.
66 Please let me know if you try any different values.
67 [*****Now a runtime option*****]
69 RESELECTION: This is no longer an option, since I gave up trying to
70 implement it in version 4.x of this driver. It did not improve
71 performance at all and made the driver unstable (because I never found one
72 of the two race conditions which were introduced by the multiple
73 outstanding command code). The instability seems a very high price to pay
74 just so that you don't have to wait for the tape to rewind. If you want
75 this feature implemented, send me patches. I'll be happy to send a copy
76 of my (broken) driver to anyone who would like to see a copy.
78 **************************************************************************/
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>
95 #include <asm/system.h>
98 #include <scsi/scsi_host.h>
100 #define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
102 /* START OF USER DEFINABLE OPTIONS */
104 #define DEBUG 0 /* Enable debugging output */
105 #define ENABLE_PARITY 1 /* Enable SCSI Parity */
107 /* END OF USER DEFINABLE OPTIONS */
110 #define EVERY_ACCESS 0 /* Write a line on every scsi access */
111 #define ERRORS_ONLY 1 /* Only write a line if there is an error */
112 #define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */
113 #define DEBUG_ABORT 1 /* Debug abort() routine */
114 #define DEBUG_RESET 1 /* Debug reset() routine */
115 #define DEBUG_RACE 1 /* Debug interrupt-driven race condition */
117 #define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
118 #define ERRORS_ONLY 0
119 #define DEBUG_MESSAGES 0
120 #define DEBUG_ABORT 0
121 #define DEBUG_RESET 0
125 /* Errors are reported on the line, so we don't need to report them again */
128 #define ERRORS_ONLY 0
132 #define PARITY_MASK 0x08
134 #define PARITY_MASK 0x00
145 in_arbitration = 0x02,
157 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */
158 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */
163 Interrupt_Status = 9,
165 Configuration2 = 11, /* tmc18c50/tmc18c30 only */
176 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */
178 IO_Control = 11, /* tmc18c30 only */
183 unsigned long _bios_base;
186 volatile int _in_command;
187 Scsi_Cmnd *_current_SC;
188 enum chip_type _chip;
190 int _fifo_count; /* Number of 512 byte blocks before INTR */
192 char _adapter_name[64];
194 volatile int _in_interrupt_flag;
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;
203 int _Read_SCSI_Data_port;
205 int _SCSI_Data_NoACK_port;
206 int _SCSI_Status_port;
208 int _TMC_Status_port;
209 int _Write_FIFO_port;
210 int _Write_SCSI_Data_port;
212 int _FIFO_Size; /* = 0x2000; 8k FIFO for
213 pre-tmc18c30 chips */
220 #define FD_MAX_HOSTS 3 /* enough? */
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)
233 #define in_interrupt_flag (HOSTDATA(shpnt)->_in_interrupt_flag)
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)
254 struct fd_mcs_adapters_struct {
257 enum chip_type fd_chip;
262 #define REPLY_ID 0x5137
264 static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
265 {"Future Domain SCSI Adapter MCS-700(18C50)",
270 {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
275 {"Reply Sound Blaster/SCSI Adapter",
282 #define FD_BRDS ARRAY_SIZE(fd_mcs_adapters)
284 static irqreturn_t fd_mcs_intr(int irq, void *dev_id);
286 static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
287 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
288 static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
290 /* host information */
291 static int found = 0;
292 static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL };
294 static int user_fifo_count = 0;
295 static int user_fifo_size = 0;
298 static int __init fd_mcs_setup(char *str)
300 static int done_setup = 0;
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");
309 user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
310 user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
314 __setup("fd_mcs=", fd_mcs_setup);
317 static void print_banner(struct Scsi_Host *shpnt)
319 printk("scsi%d <fd_mcs>: ", shpnt->host_no);
322 printk("BIOS at 0x%lX", bios_base);
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);
331 static void do_pause(unsigned amount)
332 { /* Pause for amount*10 milliseconds */
338 static void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt)
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); /* Clear forced intr. */
345 outb(0x01 | PARITY_MASK, TMC_Cntl_port);
348 static int fd_mcs_detect(struct scsi_host_template * tpnt)
351 struct Scsi_Host *shpnt;
353 /* get id, port, bios, irq */
355 u_char pos2, pos3, pos4;
359 /* if not MCA machine, return */
366 for (loop = 0; loop < FD_BRDS; loop++) {
368 while (MCA_NOTFOUND != (slot = mca_find_adapter(fd_mcs_adapters[loop].id, slot))) {
370 /* if we get this far, an adapter has been detected and is
373 printk(KERN_INFO "scsi <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1);
375 pos2 = mca_read_stored_pos(slot, 2);
376 pos3 = mca_read_stored_pos(slot, 3);
377 pos4 = mca_read_stored_pos(slot, 4);
379 /* ready for next probe */
382 if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */
383 static int reply_irq[] = { 10, 11, 14, 15 };
385 bios = 0; /* no bios */
388 port = ports[pos4 & 0x3];
392 /* can't really disable it, same as irq=10 */
393 irq = reply_irq[((pos4 >> 2) & 0x1) + 2 * ((pos4 >> 4) & 0x1)];
395 bios = addresses[pos2 >> 6];
396 port = ports[(pos2 >> 4) & 0x03];
397 irq = interrupts[(pos2 >> 1) & 0x07];
402 mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name);
404 /* check irq/region */
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");
410 /* request I/O region */
411 if (request_region(port, 0x10, "fd_mcs")) {
412 printk(KERN_ERR "fd_mcs: I/O region is already in use, skipping...\n");
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);
425 strcpy(adapter_name, fd_mcs_adapters[loop].name);
428 chip = fd_mcs_adapters[loop].fd_chip;
429 /* use boot time value if available */
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;
433 /* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */
435 /* *************************************************** */
436 /* Try to toggle 32-bit mode. This only
437 works on an 18c30 chip. (User reports
438 say this works, so we should switch to
439 it in the near future.) */
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) {
445 FIFO_Size = 0x800; /* 2k FIFO */
447 printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
451 /* That should have worked, but appears to
452 have problems. Let's assume it is an
453 18c30 if the RAM is disabled. */
455 if (inb(port + Configuration2) & 0x02) {
457 FIFO_Size = 0x800; /* 2k FIFO */
459 printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
461 /* *************************************************** */
464 /* IBM/ANSI scsi scan ordering */
465 /* Stick this back in when the scsi.c changes are there */
466 shpnt->reverse_ordering = 1;
470 hosts[found++] = shpnt;
474 shpnt->io_port = port;
475 shpnt->n_io_port = 0x10;
479 adapter_mask = (1 << id);
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;
505 outb(1, SCSI_Cntl_port);
507 outb(0, SCSI_Cntl_port);
509 outb(0, SCSI_Mode_Cntl_port);
510 outb(PARITY_MASK, TMC_Cntl_port);
515 if (found == FD_MAX_HOSTS) {
516 printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS);
524 static const char *fd_mcs_info(struct Scsi_Host *shpnt)
529 static int TOTAL_INTR = 0;
532 * inout : decides on the direction of the dataflow and the meaning of the
534 * buffer: If inout==FALSE data is being written to it else read from it
535 * *start: If inout==FALSE start of the valid data in the buffer
536 * offset: If inout==FALSE offset from the beginning of the imaginary file
537 * from which we start writing into the buffer
538 * length: If inout==FALSE max number of bytes to be written into the buffer
539 * else number of bytes in the buffer
541 static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
548 *start = buffer + offset;
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);
555 if ((len -= offset) <= 0)
562 static int fd_mcs_select(struct Scsi_Host *shpnt, int target)
565 unsigned long timeout;
567 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
568 outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port);
570 /* Stop arbitration and enable parity */
571 outb(PARITY_MASK, TMC_Cntl_port);
573 timeout = 350; /* 350mS -- because of timeouts
577 status = inb(SCSI_Status_port); /* Read adapter status */
578 if (status & 1) { /* Busy asserted */
579 /* Enable SCSI Bus (on error, should make bus idle with 0) */
580 outb(0x80, SCSI_Cntl_port);
583 udelay(1000); /* wait one msec */
587 fd_mcs_make_bus_idle(shpnt);
590 printk("Selection failed\n");
596 if (!flag) /* Skip first failure for all chips. */
599 printk("fd_mcs: Selection failed\n");
605 static void my_done(struct Scsi_Host *shpnt, int error)
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);
614 panic("fd_mcs: my_done() called outside of command\n");
617 in_interrupt_flag = 0;
621 /* only my_done needs to be protected */
622 static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
627 unsigned data_count, tmp_count;
630 struct Scsi_Host *shpnt;
634 /* search for one adapter-response on shared interrupt */
635 while ((shpnt = hosts[i++])) {
636 if ((inb(TMC_Status_port)) & 1)
640 /* return if some other device on this IRQ caused the interrupt */
647 outb(0x00, Interrupt_Cntl_port);
649 /* Abort calls my_done, so we do nothing here. */
650 if (current_SC->SCp.phase & aborted) {
652 printk("Interrupt after abort, ignoring\n");
654 /* return IRQ_HANDLED; */
660 if (current_SC->SCp.phase & in_arbitration) {
661 status = inb(TMC_Status_port); /* Read adapter status */
662 if (!(status & 0x02)) {
666 spin_lock_irqsave(shpnt->host_lock, flags);
667 my_done(shpnt, DID_BUS_BUSY << 16);
668 spin_unlock_irqrestore(shpnt->host_lock, flags);
671 current_SC->SCp.phase = in_selection;
673 outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port);
675 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
676 outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port);
678 /* Stop arbitration and enable parity */
679 outb(0x10 | PARITY_MASK, TMC_Cntl_port);
681 in_interrupt_flag = 0;
684 } else if (current_SC->SCp.phase & in_selection) {
685 status = inb(SCSI_Status_port);
686 if (!(status & 0x01)) {
687 /* Try again, for slow devices */
688 if (fd_mcs_select(shpnt, scmd_id(current_SC))) {
692 spin_lock_irqsave(shpnt->host_lock, flags);
693 my_done(shpnt, DID_NO_CONNECT << 16);
694 spin_unlock_irqrestore(shpnt->host_lock, flags);
700 /* Stop arbitration and enable parity */
701 outb(0x10 | PARITY_MASK, TMC_Cntl_port);
704 current_SC->SCp.phase = in_other;
705 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
706 outb(0x80, SCSI_Cntl_port);
708 in_interrupt_flag = 0;
713 /* current_SC->SCp.phase == in_other: this is the body of the routine */
715 status = inb(SCSI_Status_port);
717 if (status & 0x10) { /* REQ */
719 switch (status & 0x0e) {
721 case 0x08: /* COMMAND OUT */
722 outb(current_SC->cmnd[current_SC->SCp.sent_command++], Write_SCSI_Data_port);
724 printk("CMD = %x,", current_SC->cmnd[current_SC->SCp.sent_command - 1]);
727 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */
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);
733 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */
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);
739 case 0x0c: /* STATUS IN */
740 current_SC->SCp.Status = inb(Read_SCSI_Data_port);
742 printk("Status = %x, ", current_SC->SCp.Status);
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);
750 case 0x0a: /* MESSAGE OUT */
751 outb(MESSAGE_REJECT, Write_SCSI_Data_port); /* Reject */
753 case 0x0e: /* MESSAGE IN */
754 current_SC->SCp.Message = inb(Read_SCSI_Data_port);
756 printk("Message = %x, ", current_SC->SCp.Message);
758 if (!current_SC->SCp.Message)
760 #if DEBUG_MESSAGES || EVERY_ACCESS
761 if (current_SC->SCp.Message) {
762 printk("fd_mcs: message = %x\n", current_SC->SCp.Message);
769 if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
770 /* We have to get the FIFO direction
771 correct, so I've made a table based
772 on the SCSI Standard of which commands
773 appear to require a DATA OUT phase.
776 p. 94: Command for all device types
777 CHANGE DEFINITION 40 DATA OUT
780 COPY AND VERIFY 3a DATA OUT
782 LOG SELECT 4c DATA OUT
784 MODE SELECT (6) 15 DATA OUT
785 MODE SELECT (10) 55 DATA OUT
789 RECEIVE DIAGNOSTIC RESULTS 1c
791 SEND DIAGNOSTIC 1d DATA OUT
793 WRITE BUFFER 3b DATA OUT
795 p.178: Commands for direct-access devices (not listed on p. 94)
796 FORMAT UNIT 04 DATA OUT
799 PREVENT-ALLOW MEDIUM REMOVAL 1e
803 READ DEFECT DATA (10) 37
805 REASSIGN BLOCKS 07 DATA OUT
808 REZERO UNIT/REWIND 01
809 SEARCH DATA EQUAL (10) 31 DATA OUT
810 SEARCH DATA HIGH (10) 30 DATA OUT
811 SEARCH DATA LOW (10) 32 DATA OUT
818 WRITE (6)/PRINT/SEND 0a DATA OUT
819 WRITE (10)/SEND 2a DATA OUT
820 WRITE AND VERIFY (10) 2e DATA OUT
821 WRITE LONG 3f DATA OUT
822 WRITE SAME 41 DATA OUT ?
824 p. 261: Commands for sequential-access devices (not previously listed)
831 RECOVER BUFFERED DATA 14
835 p. 298: Commands for printer devices (not previously listed)
836 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
837 SLEW AND PRINT 0b DATA OUT -- same as seek
839 SYNCHRONIZE BUFFER 10
841 p. 315: Commands for processor devices (not previously listed)
843 p. 321: Commands for write-once devices (not previously listed)
846 SEARCH DATA EQUAL (12) b1 DATA OUT
847 SEARCH DATA HIGH (12) b0 DATA OUT
848 SEARCH DATA LOW (12) b2 DATA OUT
851 WRITE (12) aa DATA OUT
852 WRITE AND VERIFY (12) ae DATA OUT
854 p. 332: Commands for CD-ROM devices (not previously listed)
859 PLAY TRACK RELATIVE (10) 49
860 PLAY TRACK RELATIVE (12) a9
865 p. 370: Commands for scanner devices (not previously listed)
866 GET DATA BUFFER STATUS 34
870 SET WINDOW 24 DATA OUT
872 p. 391: Commands for optical memory devices (not listed)
875 MEDIUM SCAN 38 DATA OUT
876 READ DEFECT DATA (12) b7
878 READ UPDATED BLOCK 2d
879 UPDATE BLOCK 3d DATA OUT
881 p. 419: Commands for medium changer devices (not listed)
883 INITIALIZE ELEMENT STATUS 07
885 POSITION TO ELEMENT 2b
886 READ ELEMENT STATUS b8
887 REQUEST VOL. ELEMENT ADDRESS b5
888 SEND VOLUME TAG b6 DATA OUT
890 p. 454: Commands for communications devices (not listed previously)
896 switch (current_SC->cmnd[0]) {
897 case CHANGE_DEFINITION:
904 case SEND_DIAGNOSTIC:
908 case REASSIGN_BLOCKS:
932 case 0xea: /* alternate number for WRITE LONG */
934 current_SC->SCp.have_data_in = -1;
935 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
941 current_SC->SCp.have_data_in = 1;
942 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
947 if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
948 while ((data_count = FIFO_Size - inw(FIFO_Data_Count_port)) > 512) {
950 printk("DC=%d, ", data_count);
952 if (data_count > current_SC->SCp.this_residual)
953 data_count = current_SC->SCp.this_residual;
954 if (data_count > 0) {
956 printk("%d OUT, ", data_count);
958 if (data_count == 1) {
961 outb(*current_SC->SCp.ptr++, Write_FIFO_port);
962 --current_SC->SCp.this_residual;
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;
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;
982 } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
983 while ((data_count = inw(FIFO_Data_Count_port)) > 0) {
985 printk("DC=%d, ", data_count);
987 if (data_count > current_SC->SCp.this_residual)
988 data_count = current_SC->SCp.this_residual;
991 printk("%d IN, ", data_count);
993 if (data_count == 1) {
995 *current_SC->SCp.ptr++ = inb(Read_FIFO_port);
996 --current_SC->SCp.this_residual;
998 data_count >>= 1; /* Number of words */
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;
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;
1017 printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in);
1021 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1022 if ((unsigned char) (*((char *) current_SC->request_buffer + 2)) & 0x0f) {
1025 unsigned char qualifier;
1027 key = (unsigned char) (*((char *) current_SC->request_buffer + 2)) & 0x0f;
1028 code = (unsigned char) (*((char *) current_SC->request_buffer + 12));
1029 qualifier = (unsigned char) (*((char *) current_SC->request_buffer + 13));
1031 if (key != UNIT_ATTENTION && !(key == NOT_READY && code == 0x04 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1032 && !(key == ILLEGAL_REQUEST && (code == 0x25 || code == 0x24 || !code)))
1034 printk("fd_mcs: REQUEST SENSE " "Key = %x, Code = %x, Qualifier = %x\n", key, code, qualifier);
1039 printk("BEFORE MY_DONE. . .");
1041 spin_lock_irqsave(shpnt->host_lock, flags);
1042 my_done(shpnt, (current_SC->SCp.Status & 0xff)
1043 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
1044 spin_unlock_irqrestore(shpnt->host_lock, flags);
1046 printk("RETURNING.\n");
1050 if (current_SC->SCp.phase & disconnect) {
1051 outb(0xd0 | FIFO_COUNT, Interrupt_Cntl_port);
1052 outb(0x00, SCSI_Cntl_port);
1054 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
1058 in_interrupt_flag = 0;
1063 static int fd_mcs_release(struct Scsi_Host *shpnt)
1065 int i, this_host, irq_usage;
1067 release_region(shpnt->io_port, shpnt->n_io_port);
1071 for (i = 0; i < found; i++) {
1072 if (shpnt == hosts[i])
1074 if (shpnt->irq == hosts[i]->irq)
1078 /* only for the last one */
1080 free_irq(shpnt->irq, hosts);
1084 for (i = this_host; i < found; i++)
1085 hosts[i] = hosts[i + 1];
1087 hosts[found] = NULL;
1092 static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
1094 struct Scsi_Host *shpnt = SCpnt->device->host;
1097 panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
1100 printk("queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", SCpnt->target, *(unsigned char *) SCpnt->cmnd, SCpnt->use_sg, SCpnt->request_bufflen);
1103 fd_mcs_make_bus_idle(shpnt);
1105 SCpnt->scsi_done = done; /* Save this for the done function */
1108 /* Initialize static data */
1110 if (current_SC->use_sg) {
1111 current_SC->SCp.buffer = (struct scatterlist *) current_SC->request_buffer;
1112 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1113 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1114 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1116 current_SC->SCp.ptr = (char *) current_SC->request_buffer;
1117 current_SC->SCp.this_residual = current_SC->request_bufflen;
1118 current_SC->SCp.buffer = NULL;
1119 current_SC->SCp.buffers_residual = 0;
1123 current_SC->SCp.Status = 0;
1124 current_SC->SCp.Message = 0;
1125 current_SC->SCp.have_data_in = 0;
1126 current_SC->SCp.sent_command = 0;
1127 current_SC->SCp.phase = in_arbitration;
1129 /* Start arbitration */
1130 outb(0x00, Interrupt_Cntl_port);
1131 outb(0x00, SCSI_Cntl_port); /* Disable data drivers */
1132 outb(adapter_mask, SCSI_Data_NoACK_port); /* Set our id bit */
1134 outb(0x20, Interrupt_Cntl_port);
1135 outb(0x14 | PARITY_MASK, TMC_Cntl_port); /* Start arbitration */
1140 #if DEBUG_ABORT || DEBUG_RESET
1141 static void fd_mcs_print_info(Scsi_Cmnd * SCpnt)
1146 struct Scsi_Host *shpnt = SCpnt->host;
1148 if (!SCpnt || !SCpnt->host) {
1149 printk("fd_mcs: cannot provide detailed information\n");
1152 printk("%s\n", fd_mcs_info(SCpnt->host));
1153 print_banner(SCpnt->host);
1154 switch (SCpnt->SCp.phase) {
1155 case in_arbitration:
1156 printk("arbitration ");
1159 printk("selection ");
1169 printk("(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", SCpnt->SCp.phase, SCpnt->device->id, *(unsigned char *) SCpnt->cmnd, SCpnt->use_sg, SCpnt->request_bufflen);
1170 printk("sent_command = %d, have_data_in = %d, timeout = %d\n", SCpnt->SCp.sent_command, SCpnt->SCp.have_data_in, SCpnt->timeout);
1172 printk("in_interrupt_flag = %d\n", in_interrupt_flag);
1175 imr = (inb(0x0a1) << 8) + inb(0x21);
1177 irr = inb(0xa0) << 8;
1181 isr = inb(0xa0) << 8;
1185 /* Print out interesting information */
1186 printk("IMR = 0x%04x", imr);
1187 if (imr & (1 << shpnt->irq))
1188 printk(" (masked)");
1189 printk(", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr);
1191 printk("SCSI Status = 0x%02x\n", inb(SCSI_Status_port));
1192 printk("TMC Status = 0x%02x", inb(TMC_Status_port));
1193 if (inb(TMC_Status_port) & 1)
1194 printk(" (interrupt)");
1196 printk("Interrupt Status = 0x%02x", inb(Interrupt_Status_port));
1197 if (inb(Interrupt_Status_port) & 0x08)
1198 printk(" (enabled)");
1200 if (chip == tmc18c50 || chip == tmc18c30) {
1201 printk("FIFO Status = 0x%02x\n", inb(shpnt->io_port + FIFO_Status));
1202 printk("Int. Condition = 0x%02x\n", inb(shpnt->io_port + Interrupt_Cond));
1204 printk("Configuration 1 = 0x%02x\n", inb(shpnt->io_port + Configuration1));
1205 if (chip == tmc18c50 || chip == tmc18c30)
1206 printk("Configuration 2 = 0x%02x\n", inb(shpnt->io_port + Configuration2));
1210 static int fd_mcs_abort(Scsi_Cmnd * SCpnt)
1212 struct Scsi_Host *shpnt = SCpnt->device->host;
1214 unsigned long flags;
1215 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1216 printk("fd_mcs: abort ");
1219 spin_lock_irqsave(shpnt->host_lock, flags);
1221 #if EVERY_ACCESS || ERRORS_ONLY
1222 printk(" (not in command)\n");
1224 spin_unlock_irqrestore(shpnt->host_lock, flags);
1230 fd_mcs_print_info(SCpnt);
1233 fd_mcs_make_bus_idle(shpnt);
1235 current_SC->SCp.phase |= aborted;
1237 current_SC->result = DID_ABORT << 16;
1239 /* Aborts are not done well. . . */
1240 my_done(shpnt, DID_ABORT << 16);
1242 spin_unlock_irqrestore(shpnt->host_lock, flags);
1246 static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
1247 struct Scsi_Host *shpnt = SCpnt->device->host;
1248 unsigned long flags;
1251 static int called_once = 0;
1256 printk("fd_mcs: SCSI Bus Reset\n");
1261 fd_mcs_print_info(current_SC);
1265 spin_lock_irqsave(shpnt->host_lock, flags);
1267 outb(1, SCSI_Cntl_port);
1269 outb(0, SCSI_Cntl_port);
1271 outb(0, SCSI_Mode_Cntl_port);
1272 outb(PARITY_MASK, TMC_Cntl_port);
1274 spin_unlock_irqrestore(shpnt->host_lock, flags);
1276 /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1277 is probably hosed at this point. We will, however, try to keep
1278 things going by informing the high-level code that we need help. */
1282 #include <scsi/scsi_ioctl.h>
1284 static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
1285 sector_t capacity, int *info_array)
1287 unsigned char *p = scsi_bios_ptable(bdev);
1288 int size = capacity;
1290 /* BIOS >= 3.4 for MCA cards */
1291 /* This algorithm was provided by Future Domain (much thanks!). */
1293 if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */
1294 && p[4]) { /* Partition type */
1295 /* The partition table layout is as follows:
1298 Offset: 0 = partition status
1300 2 = starting sector and cylinder (word, encoded)
1303 6 = ending sector and cylinder (word, encoded)
1304 8 = starting absolute sector (double word)
1305 c = number of sectors (double word)
1306 Signature: 0x1fe = 0x55aa
1308 So, this algorithm assumes:
1309 1) the first partition table is in use,
1310 2) the data in the first entry is correct, and
1311 3) partitions never divide cylinders
1313 Note that (1) may be FALSE for NetBSD (and other BSD flavors),
1314 as well as for Linux. Note also, that Linux doesn't pay any
1315 attention to the fields that are used by this algorithm -- it
1316 only uses the absolute sector data. Recent versions of Linux's
1317 fdisk(1) will fill this data in correctly, and forthcoming
1318 versions will check for consistency.
1320 Checking for a non-zero partition type is not part of the
1321 Future Domain algorithm, but it seemed to be a reasonable thing
1322 to do, especially in the Linux and BSD worlds. */
1324 info_array[0] = p[5] + 1; /* heads */
1325 info_array[1] = p[6] & 0x3f; /* sectors */
1327 /* Note that this new method guarantees that there will always be
1328 less than 1024 cylinders on a platter. This is good for drives
1329 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
1330 if ((unsigned int) size >= 0x7e0000U)
1332 info_array[0] = 0xff; /* heads = 255 */
1333 info_array[1] = 0x3f; /* sectors = 63 */
1334 } else if ((unsigned int) size >= 0x200000U) {
1335 info_array[0] = 0x80; /* heads = 128 */
1336 info_array[1] = 0x3f; /* sectors = 63 */
1338 info_array[0] = 0x40; /* heads = 64 */
1339 info_array[1] = 0x20; /* sectors = 32 */
1342 /* For both methods, compute the cylinders */
1343 info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]);
1348 static struct scsi_host_template driver_template = {
1349 .proc_name = "fd_mcs",
1350 .proc_info = fd_mcs_proc_info,
1351 .detect = fd_mcs_detect,
1352 .release = fd_mcs_release,
1353 .info = fd_mcs_info,
1354 .queuecommand = fd_mcs_queue,
1355 .eh_abort_handler = fd_mcs_abort,
1356 .eh_bus_reset_handler = fd_mcs_bus_reset,
1357 .bios_param = fd_mcs_biosparam,
1362 .use_clustering = DISABLE_CLUSTERING,
1364 #include "scsi_module.c"
1366 MODULE_LICENSE("GPL");