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;
297 static int __init fd_mcs_setup(char *str)
299 static int done_setup = 0;
302 get_options(str, 3, ints);
303 if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) {
304 printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n");
308 user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
309 user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
313 __setup("fd_mcs=", fd_mcs_setup);
315 static void print_banner(struct Scsi_Host *shpnt)
317 printk("scsi%d <fd_mcs>: ", shpnt->host_no);
320 printk("BIOS at 0x%lX", bios_base);
325 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 static void do_pause(unsigned amount)
330 { /* Pause for amount*10 milliseconds */
336 static void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt)
338 outb(0, SCSI_Cntl_port);
339 outb(0, SCSI_Mode_Cntl_port);
340 if (chip == tmc18c50 || chip == tmc18c30)
341 outb(0x21 | PARITY_MASK, TMC_Cntl_port); /* Clear forced intr. */
343 outb(0x01 | PARITY_MASK, TMC_Cntl_port);
346 static int fd_mcs_detect(struct scsi_host_template * tpnt)
349 struct Scsi_Host *shpnt;
351 /* get id, port, bios, irq */
353 u_char pos2, pos3, pos4;
357 /* if not MCA machine, return */
364 for (loop = 0; loop < FD_BRDS; loop++) {
366 while (MCA_NOTFOUND != (slot = mca_find_adapter(fd_mcs_adapters[loop].id, slot))) {
368 /* if we get this far, an adapter has been detected and is
371 printk(KERN_INFO "scsi <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1);
373 pos2 = mca_read_stored_pos(slot, 2);
374 pos3 = mca_read_stored_pos(slot, 3);
375 pos4 = mca_read_stored_pos(slot, 4);
377 /* ready for next probe */
380 if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */
381 static int reply_irq[] = { 10, 11, 14, 15 };
383 bios = 0; /* no bios */
386 port = ports[pos4 & 0x3];
390 /* can't really disable it, same as irq=10 */
391 irq = reply_irq[((pos4 >> 2) & 0x1) + 2 * ((pos4 >> 4) & 0x1)];
393 bios = addresses[pos2 >> 6];
394 port = ports[(pos2 >> 4) & 0x03];
395 irq = interrupts[(pos2 >> 1) & 0x07];
400 mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name);
402 /* check irq/region */
403 if (request_irq(irq, fd_mcs_intr, IRQF_SHARED, "fd_mcs", hosts)) {
404 printk(KERN_ERR "fd_mcs: interrupt is not available, skipping...\n");
408 /* request I/O region */
409 if (request_region(port, 0x10, "fd_mcs")) {
410 printk(KERN_ERR "fd_mcs: I/O region is already in use, skipping...\n");
414 if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) {
415 printk(KERN_ERR "fd_mcs: scsi_register() failed\n");
416 release_region(port, 0x10);
417 free_irq(irq, hosts);
423 strcpy(adapter_name, fd_mcs_adapters[loop].name);
426 chip = fd_mcs_adapters[loop].fd_chip;
427 /* use boot time value if available */
428 FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count;
429 FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size;
431 /* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */
433 /* *************************************************** */
434 /* Try to toggle 32-bit mode. This only
435 works on an 18c30 chip. (User reports
436 say this works, so we should switch to
437 it in the near future.) */
438 outb(0x80, port + IO_Control);
439 if ((inb(port + Configuration2) & 0x80) == 0x80) {
440 outb(0x00, port + IO_Control);
441 if ((inb(port + Configuration2) & 0x80) == 0x00) {
443 FIFO_Size = 0x800; /* 2k FIFO */
445 printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
449 /* That should have worked, but appears to
450 have problems. Let's assume it is an
451 18c30 if the RAM is disabled. */
453 if (inb(port + Configuration2) & 0x02) {
455 FIFO_Size = 0x800; /* 2k FIFO */
457 printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
459 /* *************************************************** */
462 /* IBM/ANSI scsi scan ordering */
463 /* Stick this back in when the scsi.c changes are there */
464 shpnt->reverse_ordering = 1;
468 hosts[found++] = shpnt;
472 shpnt->io_port = port;
473 shpnt->n_io_port = 0x10;
477 adapter_mask = (1 << id);
480 SCSI_Mode_Cntl_port = port + SCSI_Mode_Cntl;
481 FIFO_Data_Count_port = port + FIFO_Data_Count;
482 Interrupt_Cntl_port = port + Interrupt_Cntl;
483 Interrupt_Status_port = port + Interrupt_Status;
484 Interrupt_Cond_port = port + Interrupt_Cond;
485 Read_FIFO_port = port + Read_FIFO;
486 Read_SCSI_Data_port = port + Read_SCSI_Data;
487 SCSI_Cntl_port = port + SCSI_Cntl;
488 SCSI_Data_NoACK_port = port + SCSI_Data_NoACK;
489 SCSI_Status_port = port + SCSI_Status;
490 TMC_Cntl_port = port + TMC_Cntl;
491 TMC_Status_port = port + TMC_Status;
492 Write_FIFO_port = port + Write_FIFO;
493 Write_SCSI_Data_port = port + Write_SCSI_Data;
503 outb(1, SCSI_Cntl_port);
505 outb(0, SCSI_Cntl_port);
507 outb(0, SCSI_Mode_Cntl_port);
508 outb(PARITY_MASK, TMC_Cntl_port);
513 if (found == FD_MAX_HOSTS) {
514 printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS);
522 static const char *fd_mcs_info(struct Scsi_Host *shpnt)
527 static int TOTAL_INTR = 0;
530 * inout : decides on the direction of the dataflow and the meaning of the
532 * buffer: If inout==FALSE data is being written to it else read from it
533 * *start: If inout==FALSE start of the valid data in the buffer
534 * offset: If inout==FALSE offset from the beginning of the imaginary file
535 * from which we start writing into the buffer
536 * length: If inout==FALSE max number of bytes to be written into the buffer
537 * else number of bytes in the buffer
539 static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
546 *start = buffer + offset;
548 len += sprintf(buffer + len, "Future Domain MCS-600/700 Driver %s\n", DRIVER_VERSION);
549 len += sprintf(buffer + len, "HOST #%d: %s\n", shpnt->host_no, adapter_name);
550 len += sprintf(buffer + len, "FIFO Size=0x%x, FIFO Count=%d\n", FIFO_Size, FIFO_COUNT);
551 len += sprintf(buffer + len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n", TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written);
553 if ((len -= offset) <= 0)
560 static int fd_mcs_select(struct Scsi_Host *shpnt, int target)
563 unsigned long timeout;
565 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
566 outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port);
568 /* Stop arbitration and enable parity */
569 outb(PARITY_MASK, TMC_Cntl_port);
571 timeout = 350; /* 350mS -- because of timeouts
575 status = inb(SCSI_Status_port); /* Read adapter status */
576 if (status & 1) { /* Busy asserted */
577 /* Enable SCSI Bus (on error, should make bus idle with 0) */
578 outb(0x80, SCSI_Cntl_port);
581 udelay(1000); /* wait one msec */
585 fd_mcs_make_bus_idle(shpnt);
588 printk("Selection failed\n");
594 if (!flag) /* Skip first failure for all chips. */
597 printk("fd_mcs: Selection failed\n");
603 static void my_done(struct Scsi_Host *shpnt, int error)
607 outb(0x00, Interrupt_Cntl_port);
608 fd_mcs_make_bus_idle(shpnt);
609 current_SC->result = error;
610 current_SC->scsi_done(current_SC);
612 panic("fd_mcs: my_done() called outside of command\n");
615 in_interrupt_flag = 0;
619 /* only my_done needs to be protected */
620 static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
625 unsigned data_count, tmp_count;
628 struct Scsi_Host *shpnt;
632 /* search for one adapter-response on shared interrupt */
633 while ((shpnt = hosts[i++])) {
634 if ((inb(TMC_Status_port)) & 1)
638 /* return if some other device on this IRQ caused the interrupt */
645 outb(0x00, Interrupt_Cntl_port);
647 /* Abort calls my_done, so we do nothing here. */
648 if (current_SC->SCp.phase & aborted) {
650 printk("Interrupt after abort, ignoring\n");
652 /* return IRQ_HANDLED; */
658 if (current_SC->SCp.phase & in_arbitration) {
659 status = inb(TMC_Status_port); /* Read adapter status */
660 if (!(status & 0x02)) {
664 spin_lock_irqsave(shpnt->host_lock, flags);
665 my_done(shpnt, DID_BUS_BUSY << 16);
666 spin_unlock_irqrestore(shpnt->host_lock, flags);
669 current_SC->SCp.phase = in_selection;
671 outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port);
673 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
674 outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port);
676 /* Stop arbitration and enable parity */
677 outb(0x10 | PARITY_MASK, TMC_Cntl_port);
679 in_interrupt_flag = 0;
682 } else if (current_SC->SCp.phase & in_selection) {
683 status = inb(SCSI_Status_port);
684 if (!(status & 0x01)) {
685 /* Try again, for slow devices */
686 if (fd_mcs_select(shpnt, scmd_id(current_SC))) {
690 spin_lock_irqsave(shpnt->host_lock, flags);
691 my_done(shpnt, DID_NO_CONNECT << 16);
692 spin_unlock_irqrestore(shpnt->host_lock, flags);
698 /* Stop arbitration and enable parity */
699 outb(0x10 | PARITY_MASK, TMC_Cntl_port);
702 current_SC->SCp.phase = in_other;
703 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
704 outb(0x80, SCSI_Cntl_port);
706 in_interrupt_flag = 0;
711 /* current_SC->SCp.phase == in_other: this is the body of the routine */
713 status = inb(SCSI_Status_port);
715 if (status & 0x10) { /* REQ */
717 switch (status & 0x0e) {
719 case 0x08: /* COMMAND OUT */
720 outb(current_SC->cmnd[current_SC->SCp.sent_command++], Write_SCSI_Data_port);
722 printk("CMD = %x,", current_SC->cmnd[current_SC->SCp.sent_command - 1]);
725 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */
726 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
727 current_SC->SCp.have_data_in = -1;
728 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
731 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */
732 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
733 current_SC->SCp.have_data_in = 1;
734 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
737 case 0x0c: /* STATUS IN */
738 current_SC->SCp.Status = inb(Read_SCSI_Data_port);
740 printk("Status = %x, ", current_SC->SCp.Status);
743 if (current_SC->SCp.Status && current_SC->SCp.Status != 2 && current_SC->SCp.Status != 8) {
744 printk("ERROR fd_mcs: target = %d, command = %x, status = %x\n", current_SC->device->id, current_SC->cmnd[0], current_SC->SCp.Status);
748 case 0x0a: /* MESSAGE OUT */
749 outb(MESSAGE_REJECT, Write_SCSI_Data_port); /* Reject */
751 case 0x0e: /* MESSAGE IN */
752 current_SC->SCp.Message = inb(Read_SCSI_Data_port);
754 printk("Message = %x, ", current_SC->SCp.Message);
756 if (!current_SC->SCp.Message)
758 #if DEBUG_MESSAGES || EVERY_ACCESS
759 if (current_SC->SCp.Message) {
760 printk("fd_mcs: message = %x\n", current_SC->SCp.Message);
767 if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
768 /* We have to get the FIFO direction
769 correct, so I've made a table based
770 on the SCSI Standard of which commands
771 appear to require a DATA OUT phase.
774 p. 94: Command for all device types
775 CHANGE DEFINITION 40 DATA OUT
778 COPY AND VERIFY 3a DATA OUT
780 LOG SELECT 4c DATA OUT
782 MODE SELECT (6) 15 DATA OUT
783 MODE SELECT (10) 55 DATA OUT
787 RECEIVE DIAGNOSTIC RESULTS 1c
789 SEND DIAGNOSTIC 1d DATA OUT
791 WRITE BUFFER 3b DATA OUT
793 p.178: Commands for direct-access devices (not listed on p. 94)
794 FORMAT UNIT 04 DATA OUT
797 PREVENT-ALLOW MEDIUM REMOVAL 1e
801 READ DEFECT DATA (10) 37
803 REASSIGN BLOCKS 07 DATA OUT
806 REZERO UNIT/REWIND 01
807 SEARCH DATA EQUAL (10) 31 DATA OUT
808 SEARCH DATA HIGH (10) 30 DATA OUT
809 SEARCH DATA LOW (10) 32 DATA OUT
816 WRITE (6)/PRINT/SEND 0a DATA OUT
817 WRITE (10)/SEND 2a DATA OUT
818 WRITE AND VERIFY (10) 2e DATA OUT
819 WRITE LONG 3f DATA OUT
820 WRITE SAME 41 DATA OUT ?
822 p. 261: Commands for sequential-access devices (not previously listed)
829 RECOVER BUFFERED DATA 14
833 p. 298: Commands for printer devices (not previously listed)
834 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
835 SLEW AND PRINT 0b DATA OUT -- same as seek
837 SYNCHRONIZE BUFFER 10
839 p. 315: Commands for processor devices (not previously listed)
841 p. 321: Commands for write-once devices (not previously listed)
844 SEARCH DATA EQUAL (12) b1 DATA OUT
845 SEARCH DATA HIGH (12) b0 DATA OUT
846 SEARCH DATA LOW (12) b2 DATA OUT
849 WRITE (12) aa DATA OUT
850 WRITE AND VERIFY (12) ae DATA OUT
852 p. 332: Commands for CD-ROM devices (not previously listed)
857 PLAY TRACK RELATIVE (10) 49
858 PLAY TRACK RELATIVE (12) a9
863 p. 370: Commands for scanner devices (not previously listed)
864 GET DATA BUFFER STATUS 34
868 SET WINDOW 24 DATA OUT
870 p. 391: Commands for optical memory devices (not listed)
873 MEDIUM SCAN 38 DATA OUT
874 READ DEFECT DATA (12) b7
876 READ UPDATED BLOCK 2d
877 UPDATE BLOCK 3d DATA OUT
879 p. 419: Commands for medium changer devices (not listed)
881 INITIALIZE ELEMENT STATUS 07
883 POSITION TO ELEMENT 2b
884 READ ELEMENT STATUS b8
885 REQUEST VOL. ELEMENT ADDRESS b5
886 SEND VOLUME TAG b6 DATA OUT
888 p. 454: Commands for communications devices (not listed previously)
894 switch (current_SC->cmnd[0]) {
895 case CHANGE_DEFINITION:
902 case SEND_DIAGNOSTIC:
906 case REASSIGN_BLOCKS:
930 case 0xea: /* alternate number for WRITE LONG */
932 current_SC->SCp.have_data_in = -1;
933 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
939 current_SC->SCp.have_data_in = 1;
940 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
945 if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
946 while ((data_count = FIFO_Size - inw(FIFO_Data_Count_port)) > 512) {
948 printk("DC=%d, ", data_count);
950 if (data_count > current_SC->SCp.this_residual)
951 data_count = current_SC->SCp.this_residual;
952 if (data_count > 0) {
954 printk("%d OUT, ", data_count);
956 if (data_count == 1) {
959 outb(*current_SC->SCp.ptr++, Write_FIFO_port);
960 --current_SC->SCp.this_residual;
963 tmp_count = data_count << 1;
964 outsw(Write_FIFO_port, current_SC->SCp.ptr, data_count);
965 current_SC->SCp.ptr += tmp_count;
966 Bytes_Written += tmp_count;
967 current_SC->SCp.this_residual -= tmp_count;
970 if (!current_SC->SCp.this_residual) {
971 if (current_SC->SCp.buffers_residual) {
972 --current_SC->SCp.buffers_residual;
973 ++current_SC->SCp.buffer;
974 current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
975 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
980 } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
981 while ((data_count = inw(FIFO_Data_Count_port)) > 0) {
983 printk("DC=%d, ", data_count);
985 if (data_count > current_SC->SCp.this_residual)
986 data_count = current_SC->SCp.this_residual;
989 printk("%d IN, ", data_count);
991 if (data_count == 1) {
993 *current_SC->SCp.ptr++ = inb(Read_FIFO_port);
994 --current_SC->SCp.this_residual;
996 data_count >>= 1; /* Number of words */
997 tmp_count = data_count << 1;
998 insw(Read_FIFO_port, current_SC->SCp.ptr, data_count);
999 current_SC->SCp.ptr += tmp_count;
1000 Bytes_Read += tmp_count;
1001 current_SC->SCp.this_residual -= tmp_count;
1004 if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
1005 --current_SC->SCp.buffers_residual;
1006 ++current_SC->SCp.buffer;
1007 current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
1008 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1015 printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in);
1019 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1020 if ((unsigned char) (*((char *) current_SC->request_buffer + 2)) & 0x0f) {
1023 unsigned char qualifier;
1025 key = (unsigned char) (*((char *) current_SC->request_buffer + 2)) & 0x0f;
1026 code = (unsigned char) (*((char *) current_SC->request_buffer + 12));
1027 qualifier = (unsigned char) (*((char *) current_SC->request_buffer + 13));
1029 if (key != UNIT_ATTENTION && !(key == NOT_READY && code == 0x04 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1030 && !(key == ILLEGAL_REQUEST && (code == 0x25 || code == 0x24 || !code)))
1032 printk("fd_mcs: REQUEST SENSE " "Key = %x, Code = %x, Qualifier = %x\n", key, code, qualifier);
1037 printk("BEFORE MY_DONE. . .");
1039 spin_lock_irqsave(shpnt->host_lock, flags);
1040 my_done(shpnt, (current_SC->SCp.Status & 0xff)
1041 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
1042 spin_unlock_irqrestore(shpnt->host_lock, flags);
1044 printk("RETURNING.\n");
1048 if (current_SC->SCp.phase & disconnect) {
1049 outb(0xd0 | FIFO_COUNT, Interrupt_Cntl_port);
1050 outb(0x00, SCSI_Cntl_port);
1052 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
1056 in_interrupt_flag = 0;
1061 static int fd_mcs_release(struct Scsi_Host *shpnt)
1063 int i, this_host, irq_usage;
1065 release_region(shpnt->io_port, shpnt->n_io_port);
1069 for (i = 0; i < found; i++) {
1070 if (shpnt == hosts[i])
1072 if (shpnt->irq == hosts[i]->irq)
1076 /* only for the last one */
1078 free_irq(shpnt->irq, hosts);
1082 for (i = this_host; i < found; i++)
1083 hosts[i] = hosts[i + 1];
1085 hosts[found] = NULL;
1090 static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
1092 struct Scsi_Host *shpnt = SCpnt->device->host;
1095 panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
1098 printk("queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", SCpnt->target, *(unsigned char *) SCpnt->cmnd, SCpnt->use_sg, SCpnt->request_bufflen);
1101 fd_mcs_make_bus_idle(shpnt);
1103 SCpnt->scsi_done = done; /* Save this for the done function */
1106 /* Initialize static data */
1108 if (current_SC->use_sg) {
1109 current_SC->SCp.buffer = (struct scatterlist *) current_SC->request_buffer;
1110 current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
1111 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1112 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1114 current_SC->SCp.ptr = (char *) current_SC->request_buffer;
1115 current_SC->SCp.this_residual = current_SC->request_bufflen;
1116 current_SC->SCp.buffer = NULL;
1117 current_SC->SCp.buffers_residual = 0;
1121 current_SC->SCp.Status = 0;
1122 current_SC->SCp.Message = 0;
1123 current_SC->SCp.have_data_in = 0;
1124 current_SC->SCp.sent_command = 0;
1125 current_SC->SCp.phase = in_arbitration;
1127 /* Start arbitration */
1128 outb(0x00, Interrupt_Cntl_port);
1129 outb(0x00, SCSI_Cntl_port); /* Disable data drivers */
1130 outb(adapter_mask, SCSI_Data_NoACK_port); /* Set our id bit */
1132 outb(0x20, Interrupt_Cntl_port);
1133 outb(0x14 | PARITY_MASK, TMC_Cntl_port); /* Start arbitration */
1138 #if DEBUG_ABORT || DEBUG_RESET
1139 static void fd_mcs_print_info(Scsi_Cmnd * SCpnt)
1144 struct Scsi_Host *shpnt = SCpnt->host;
1146 if (!SCpnt || !SCpnt->host) {
1147 printk("fd_mcs: cannot provide detailed information\n");
1150 printk("%s\n", fd_mcs_info(SCpnt->host));
1151 print_banner(SCpnt->host);
1152 switch (SCpnt->SCp.phase) {
1153 case in_arbitration:
1154 printk("arbitration ");
1157 printk("selection ");
1167 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);
1168 printk("sent_command = %d, have_data_in = %d, timeout = %d\n", SCpnt->SCp.sent_command, SCpnt->SCp.have_data_in, SCpnt->timeout);
1170 printk("in_interrupt_flag = %d\n", in_interrupt_flag);
1173 imr = (inb(0x0a1) << 8) + inb(0x21);
1175 irr = inb(0xa0) << 8;
1179 isr = inb(0xa0) << 8;
1183 /* Print out interesting information */
1184 printk("IMR = 0x%04x", imr);
1185 if (imr & (1 << shpnt->irq))
1186 printk(" (masked)");
1187 printk(", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr);
1189 printk("SCSI Status = 0x%02x\n", inb(SCSI_Status_port));
1190 printk("TMC Status = 0x%02x", inb(TMC_Status_port));
1191 if (inb(TMC_Status_port) & 1)
1192 printk(" (interrupt)");
1194 printk("Interrupt Status = 0x%02x", inb(Interrupt_Status_port));
1195 if (inb(Interrupt_Status_port) & 0x08)
1196 printk(" (enabled)");
1198 if (chip == tmc18c50 || chip == tmc18c30) {
1199 printk("FIFO Status = 0x%02x\n", inb(shpnt->io_port + FIFO_Status));
1200 printk("Int. Condition = 0x%02x\n", inb(shpnt->io_port + Interrupt_Cond));
1202 printk("Configuration 1 = 0x%02x\n", inb(shpnt->io_port + Configuration1));
1203 if (chip == tmc18c50 || chip == tmc18c30)
1204 printk("Configuration 2 = 0x%02x\n", inb(shpnt->io_port + Configuration2));
1208 static int fd_mcs_abort(Scsi_Cmnd * SCpnt)
1210 struct Scsi_Host *shpnt = SCpnt->device->host;
1212 unsigned long flags;
1213 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1214 printk("fd_mcs: abort ");
1217 spin_lock_irqsave(shpnt->host_lock, flags);
1219 #if EVERY_ACCESS || ERRORS_ONLY
1220 printk(" (not in command)\n");
1222 spin_unlock_irqrestore(shpnt->host_lock, flags);
1228 fd_mcs_print_info(SCpnt);
1231 fd_mcs_make_bus_idle(shpnt);
1233 current_SC->SCp.phase |= aborted;
1235 current_SC->result = DID_ABORT << 16;
1237 /* Aborts are not done well. . . */
1238 my_done(shpnt, DID_ABORT << 16);
1240 spin_unlock_irqrestore(shpnt->host_lock, flags);
1244 static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
1245 struct Scsi_Host *shpnt = SCpnt->device->host;
1246 unsigned long flags;
1249 static int called_once = 0;
1254 printk("fd_mcs: SCSI Bus Reset\n");
1259 fd_mcs_print_info(current_SC);
1263 spin_lock_irqsave(shpnt->host_lock, flags);
1265 outb(1, SCSI_Cntl_port);
1267 outb(0, SCSI_Cntl_port);
1269 outb(0, SCSI_Mode_Cntl_port);
1270 outb(PARITY_MASK, TMC_Cntl_port);
1272 spin_unlock_irqrestore(shpnt->host_lock, flags);
1274 /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1275 is probably hosed at this point. We will, however, try to keep
1276 things going by informing the high-level code that we need help. */
1280 #include <scsi/scsi_ioctl.h>
1282 static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
1283 sector_t capacity, int *info_array)
1285 unsigned char *p = scsi_bios_ptable(bdev);
1286 int size = capacity;
1288 /* BIOS >= 3.4 for MCA cards */
1289 /* This algorithm was provided by Future Domain (much thanks!). */
1291 if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */
1292 && p[4]) { /* Partition type */
1293 /* The partition table layout is as follows:
1296 Offset: 0 = partition status
1298 2 = starting sector and cylinder (word, encoded)
1301 6 = ending sector and cylinder (word, encoded)
1302 8 = starting absolute sector (double word)
1303 c = number of sectors (double word)
1304 Signature: 0x1fe = 0x55aa
1306 So, this algorithm assumes:
1307 1) the first partition table is in use,
1308 2) the data in the first entry is correct, and
1309 3) partitions never divide cylinders
1311 Note that (1) may be FALSE for NetBSD (and other BSD flavors),
1312 as well as for Linux. Note also, that Linux doesn't pay any
1313 attention to the fields that are used by this algorithm -- it
1314 only uses the absolute sector data. Recent versions of Linux's
1315 fdisk(1) will fill this data in correctly, and forthcoming
1316 versions will check for consistency.
1318 Checking for a non-zero partition type is not part of the
1319 Future Domain algorithm, but it seemed to be a reasonable thing
1320 to do, especially in the Linux and BSD worlds. */
1322 info_array[0] = p[5] + 1; /* heads */
1323 info_array[1] = p[6] & 0x3f; /* sectors */
1325 /* Note that this new method guarantees that there will always be
1326 less than 1024 cylinders on a platter. This is good for drives
1327 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
1328 if ((unsigned int) size >= 0x7e0000U)
1330 info_array[0] = 0xff; /* heads = 255 */
1331 info_array[1] = 0x3f; /* sectors = 63 */
1332 } else if ((unsigned int) size >= 0x200000U) {
1333 info_array[0] = 0x80; /* heads = 128 */
1334 info_array[1] = 0x3f; /* sectors = 63 */
1336 info_array[0] = 0x40; /* heads = 64 */
1337 info_array[1] = 0x20; /* sectors = 32 */
1340 /* For both methods, compute the cylinders */
1341 info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]);
1346 static struct scsi_host_template driver_template = {
1347 .proc_name = "fd_mcs",
1348 .proc_info = fd_mcs_proc_info,
1349 .detect = fd_mcs_detect,
1350 .release = fd_mcs_release,
1351 .info = fd_mcs_info,
1352 .queuecommand = fd_mcs_queue,
1353 .eh_abort_handler = fd_mcs_abort,
1354 .eh_bus_reset_handler = fd_mcs_bus_reset,
1355 .bios_param = fd_mcs_biosparam,
1360 .use_clustering = DISABLE_CLUSTERING,
1362 #include "scsi_module.c"
1364 MODULE_LICENSE("GPL");