tdfxfb: hardware cursor
[linux-2.6/zen-sources.git] / drivers / scsi / fd_mcs.c
blob668569e8856bdb635ad90d9aaa718abcedf0b754
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
8 * of MCS 700.
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
36 * later version.
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>
94 #include <asm/io.h>
95 #include <asm/system.h>
97 #include "scsi.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 */
109 #if DEBUG
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 */
116 #else
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
122 #define DEBUG_RACE 0
123 #endif
125 /* Errors are reported on the line, so we don't need to report them again */
126 #if EVERY_ACCESS
127 #undef ERRORS_ONLY
128 #define ERRORS_ONLY 0
129 #endif
131 #if ENABLE_PARITY
132 #define PARITY_MASK 0x08
133 #else
134 #define PARITY_MASK 0x00
135 #endif
137 enum chip_type {
138 unknown = 0x00,
139 tmc1800 = 0x01,
140 tmc18c50 = 0x02,
141 tmc18c30 = 0x03,
144 enum {
145 in_arbitration = 0x02,
146 in_selection = 0x04,
147 in_other = 0x08,
148 disconnect = 0x10,
149 aborted = 0x20,
150 sent_ident = 0x40,
153 enum in_port_type {
154 Read_SCSI_Data = 0,
155 SCSI_Status = 1,
156 TMC_Status = 2,
157 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */
158 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */
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, /* tmc18c50/tmc18c30 only */
166 Read_FIFO = 12,
167 FIFO_Data_Count = 14
170 enum 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, /* tmc18c50/tmc18c30 only */
177 Write_Loopback = 7,
178 IO_Control = 11, /* tmc18c30 only */
179 Write_FIFO = 12
182 struct 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; /* Number of 512 byte blocks before INTR */
192 char _adapter_name[64];
193 #if DEBUG_RACE
194 volatile int _in_interrupt_flag;
195 #endif
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;
212 int _FIFO_Size; /* = 0x2000; 8k FIFO for
213 pre-tmc18c30 chips */
214 /* simple stats */
215 int _Bytes_Read;
216 int _Bytes_Written;
217 int _INTR_Processed;
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)
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)
254 struct fd_mcs_adapters_struct {
255 char *name;
256 int id;
257 enum chip_type fd_chip;
258 int fifo_size;
259 int fifo_count;
262 #define REPLY_ID 0x5137
264 static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
265 {"Future Domain SCSI Adapter MCS-700(18C50)",
266 0x60e9,
267 tmc18c50,
268 0x2000,
270 {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
271 0x6127,
272 tmc1800,
273 0x2000,
275 {"Reply Sound Blaster/SCSI Adapter",
276 REPLY_ID,
277 tmc18c30,
278 0x800,
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 #ifndef MODULE
298 static int __init fd_mcs_setup(char *str)
300 static int done_setup = 0;
301 int ints[3];
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;
309 user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
310 user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
311 return 1;
314 __setup("fd_mcs=", fd_mcs_setup);
315 #endif /* !MODULE */
317 static void print_banner(struct Scsi_Host *shpnt)
319 printk("scsi%d <fd_mcs>: ", shpnt->host_no);
321 if (bios_base) {
322 printk("BIOS at 0x%lX", bios_base);
323 } else {
324 printk("No BIOS");
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 */
333 do {
334 mdelay(10);
335 } while (--amount);
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. */
344 else
345 outb(0x01 | PARITY_MASK, TMC_Cntl_port);
348 static int fd_mcs_detect(struct scsi_host_template * tpnt)
350 int loop;
351 struct Scsi_Host *shpnt;
353 /* get id, port, bios, irq */
354 int slot;
355 u_char pos2, pos3, pos4;
356 int id, port, irq;
357 unsigned long bios;
359 /* if not MCA machine, return */
360 if (!MCA_bus)
361 return 0;
363 /* changeable? */
364 id = 7;
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))) {
370 /* if we get this far, an adapter has been detected and is
371 enabled */
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 */
380 slot++;
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 */
387 if (pos2 & 0x2)
388 port = ports[pos4 & 0x3];
389 else
390 continue;
392 /* can't really disable it, same as irq=10 */
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];
400 if (irq) {
401 /* claim the slot */
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");
407 continue;
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");
413 continue;
415 /* register */
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;
424 /* save name */
425 strcpy(adapter_name, fd_mcs_adapters[loop].name);
427 /* chip/fifo */
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? */
434 #ifdef NOT_USED
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) {
444 chip = tmc18c30;
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) {
456 chip = tmc18c30;
457 FIFO_Size = 0x800; /* 2k FIFO */
459 printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
461 /* *************************************************** */
462 #endif
464 /* IBM/ANSI scsi scan ordering */
465 /* Stick this back in when the scsi.c changes are there */
466 shpnt->reverse_ordering = 1;
469 /* saving info */
470 hosts[found++] = shpnt;
472 shpnt->this_id = id;
473 shpnt->irq = irq;
474 shpnt->io_port = port;
475 shpnt->n_io_port = 0x10;
477 /* save */
478 bios_base = bios;
479 adapter_mask = (1 << id);
481 /* save more */
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;
497 Bytes_Read = 0;
498 Bytes_Written = 0;
499 INTR_Processed = 0;
501 /* say something */
502 print_banner(shpnt);
504 /* reset */
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 /* done reset */
515 if (found == FD_MAX_HOSTS) {
516 printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS);
517 break;
521 return found;
524 static const char *fd_mcs_info(struct Scsi_Host *shpnt)
526 return adapter_name;
529 static int TOTAL_INTR = 0;
532 * inout : decides on the direction of the dataflow and the meaning of the
533 * variables
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)
543 int len = 0;
545 if (inout)
546 return (-ENOSYS);
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)
556 return 0;
557 if (len > length)
558 len = length;
559 return len;
562 static int fd_mcs_select(struct Scsi_Host *shpnt, int target)
564 int status;
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
574 (was 250mS) */
576 do {
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);
581 return 0;
583 udelay(1000); /* wait one msec */
584 } while (--timeout);
586 /* Make bus idle */
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;
596 if (!flag) /* Skip first failure for all chips. */
597 ++flag;
598 else
599 printk("fd_mcs: Selection failed\n");
601 #endif
602 return 1;
605 static void my_done(struct Scsi_Host *shpnt, int error)
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");
616 #if DEBUG_RACE
617 in_interrupt_flag = 0;
618 #endif
621 /* only my_done needs to be protected */
622 static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
624 unsigned long flags;
625 int status;
626 int done = 0;
627 unsigned data_count, tmp_count;
629 int i = 0;
630 struct Scsi_Host *shpnt;
632 TOTAL_INTR++;
634 /* search for one adapter-response on shared interrupt */
635 while ((shpnt = hosts[i++])) {
636 if ((inb(TMC_Status_port)) & 1)
637 break;
640 /* return if some other device on this IRQ caused the interrupt */
641 if (!shpnt) {
642 return IRQ_NONE;
645 INTR_Processed++;
647 outb(0x00, Interrupt_Cntl_port);
649 /* Abort calls my_done, so we do nothing here. */
650 if (current_SC->SCp.phase & aborted) {
651 #if DEBUG_ABORT
652 printk("Interrupt after abort, ignoring\n");
653 #endif
654 /* return IRQ_HANDLED; */
656 #if DEBUG_RACE
657 ++in_interrupt_flag;
658 #endif
660 if (current_SC->SCp.phase & in_arbitration) {
661 status = inb(TMC_Status_port); /* Read adapter status */
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;
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);
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 /* Try again, for slow devices */
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 /* 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);
707 #if DEBUG_RACE
708 in_interrupt_flag = 0;
709 #endif
710 return IRQ_HANDLED;
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);
723 #if EVERY_ACCESS
724 printk("CMD = %x,", current_SC->cmnd[current_SC->SCp.sent_command - 1]);
725 #endif
726 break;
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);
732 break;
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);
738 break;
739 case 0x0c: /* STATUS IN */
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);
748 #endif
749 break;
750 case 0x0a: /* MESSAGE OUT */
751 outb(MESSAGE_REJECT, Write_SCSI_Data_port); /* Reject */
752 break;
753 case 0x0e: /* MESSAGE IN */
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);
764 #endif
765 break;
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
778 COMPARE 39 DATA OUT
779 COPY 18 DATA OUT
780 COPY AND VERIFY 3a DATA OUT
781 INQUIRY 12
782 LOG SELECT 4c DATA OUT
783 LOG SENSE 4d
784 MODE SELECT (6) 15 DATA OUT
785 MODE SELECT (10) 55 DATA OUT
786 MODE SENSE (6) 1a
787 MODE SENSE (10) 5a
788 READ BUFFER 3c
789 RECEIVE DIAGNOSTIC RESULTS 1c
790 REQUEST SENSE 03
791 SEND DIAGNOSTIC 1d DATA OUT
792 TEST UNIT READY 00
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
797 LOCK-UNLOCK CACHE 36
798 PRE-FETCH 34
799 PREVENT-ALLOW MEDIUM REMOVAL 1e
800 READ (6)/RECEIVE 08
801 READ (10) 3c
802 READ CAPACITY 25
803 READ DEFECT DATA (10) 37
804 READ LONG 3e
805 REASSIGN BLOCKS 07 DATA OUT
806 RELEASE 17
807 RESERVE 16 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
812 SEEK (6) 0b
813 SEEK (10) 2b
814 SET LIMITS (10) 33
815 START STOP UNIT 1b
816 SYNCHRONIZE CACHE 35
817 VERIFY (10) 2f
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)
825 ERASE 19
826 LOAD UNLOAD 1b
827 LOCATE 2b
828 READ BLOCK LIMITS 05
829 READ POSITION 34
830 READ REVERSE 0f
831 RECOVER BUFFERED DATA 14
832 SPACE 11
833 WRITE FILEMARKS 10 ?
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
838 STOP PRINT 1b
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)
844 MEDIUM SCAN 38
845 READ (12) a8
846 SEARCH DATA EQUAL (12) b1 DATA OUT
847 SEARCH DATA HIGH (12) b0 DATA OUT
848 SEARCH DATA LOW (12) b2 DATA OUT
849 SET LIMITS (12) b3
850 VERIFY (12) af
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)
855 PAUSE/RESUME 4b
856 PLAY AUDIO (10) 45
857 PLAY AUDIO (12) a5
858 PLAY AUDIO MSF 47
859 PLAY TRACK RELATIVE (10) 49
860 PLAY TRACK RELATIVE (12) a9
861 READ HEADER 44
862 READ SUB-CHANNEL 42
863 READ TOC 43
865 p. 370: Commands for scanner devices (not previously listed)
866 GET DATA BUFFER STATUS 34
867 GET WINDOW 25
868 OBJECT POSITION 31
869 SCAN 1b
870 SET WINDOW 24 DATA OUT
872 p. 391: Commands for optical memory devices (not listed)
873 ERASE (10) 2c
874 ERASE (12) ac
875 MEDIUM SCAN 38 DATA OUT
876 READ DEFECT DATA (12) b7
877 READ GENERATION 29
878 READ UPDATED BLOCK 2d
879 UPDATE BLOCK 3d DATA OUT
881 p. 419: Commands for medium changer devices (not listed)
882 EXCHANGE MEDIUM 46
883 INITIALIZE ELEMENT STATUS 07
884 MOVE MEDIUM a5
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)
891 GET MESSAGE (6) 08
892 GET MESSAGE (10) 28
893 GET MESSAGE (12) a8
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:
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:
919 case 0xb1:
920 case 0xb0:
921 case 0xb2:
922 case 0xaa:
923 case 0xae:
925 case 0x24:
927 case 0x38:
928 case 0x3d:
930 case 0xb6:
932 case 0xea: /* alternate number for WRITE LONG */
934 current_SC->SCp.have_data_in = -1;
935 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
936 break;
938 case 0x00:
939 default:
941 current_SC->SCp.have_data_in = 1;
942 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
943 break;
947 if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
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++;
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;
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 = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
977 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
978 } else
979 break;
982 } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
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; /* 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 = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
1010 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1015 if (done) {
1016 #if EVERY_ACCESS
1017 printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in);
1018 #endif
1020 #if ERRORS_ONLY
1021 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1022 if ((unsigned char) (*((char *) current_SC->request_buffer + 2)) & 0x0f) {
1023 unsigned char key;
1024 unsigned char code;
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);
1037 #endif
1038 #if EVERY_ACCESS
1039 printk("BEFORE MY_DONE. . .");
1040 #endif
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);
1045 #if EVERY_ACCESS
1046 printk("RETURNING.\n");
1047 #endif
1049 } else {
1050 if (current_SC->SCp.phase & disconnect) {
1051 outb(0xd0 | FIFO_COUNT, Interrupt_Cntl_port);
1052 outb(0x00, SCSI_Cntl_port);
1053 } else {
1054 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
1057 #if DEBUG_RACE
1058 in_interrupt_flag = 0;
1059 #endif
1060 return IRQ_HANDLED;
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);
1069 this_host = -1;
1070 irq_usage = 0;
1071 for (i = 0; i < found; i++) {
1072 if (shpnt == hosts[i])
1073 this_host = i;
1074 if (shpnt->irq == hosts[i]->irq)
1075 irq_usage++;
1078 /* only for the last one */
1079 if (1 == irq_usage)
1080 free_irq(shpnt->irq, hosts);
1082 found--;
1084 for (i = this_host; i < found; i++)
1085 hosts[i] = hosts[i + 1];
1087 hosts[found] = NULL;
1089 return 0;
1092 static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
1094 struct Scsi_Host *shpnt = SCpnt->device->host;
1096 if (in_command) {
1097 panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
1099 #if EVERY_ACCESS
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);
1101 #endif
1103 fd_mcs_make_bus_idle(shpnt);
1105 SCpnt->scsi_done = done; /* Save this for the done function */
1106 current_SC = SCpnt;
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 = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
1113 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1114 current_SC->SCp.buffers_residual = current_SC->use_sg - 1;
1115 } else {
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 */
1133 in_command = 1;
1134 outb(0x20, Interrupt_Cntl_port);
1135 outb(0x14 | PARITY_MASK, TMC_Cntl_port); /* Start arbitration */
1137 return 0;
1140 #if DEBUG_ABORT || DEBUG_RESET
1141 static void fd_mcs_print_info(Scsi_Cmnd * SCpnt)
1143 unsigned int imr;
1144 unsigned int irr;
1145 unsigned int isr;
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 ");
1157 break;
1158 case in_selection:
1159 printk("selection ");
1160 break;
1161 case in_other:
1162 printk("other ");
1163 break;
1164 default:
1165 printk("unknown ");
1166 break;
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);
1171 #if DEBUG_RACE
1172 printk("in_interrupt_flag = %d\n", in_interrupt_flag);
1173 #endif
1175 imr = (inb(0x0a1) << 8) + inb(0x21);
1176 outb(0x0a, 0xa0);
1177 irr = inb(0xa0) << 8;
1178 outb(0x0a, 0x20);
1179 irr += inb(0x20);
1180 outb(0x0b, 0xa0);
1181 isr = inb(0xa0) << 8;
1182 outb(0x0b, 0x20);
1183 isr += inb(0x20);
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)");
1195 printk("\n");
1196 printk("Interrupt Status = 0x%02x", inb(Interrupt_Status_port));
1197 if (inb(Interrupt_Status_port) & 0x08)
1198 printk(" (enabled)");
1199 printk("\n");
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));
1208 #endif
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 ");
1217 #endif
1219 spin_lock_irqsave(shpnt->host_lock, flags);
1220 if (!in_command) {
1221 #if EVERY_ACCESS || ERRORS_ONLY
1222 printk(" (not in command)\n");
1223 #endif
1224 spin_unlock_irqrestore(shpnt->host_lock, flags);
1225 return FAILED;
1226 } else
1227 printk("\n");
1229 #if DEBUG_ABORT
1230 fd_mcs_print_info(SCpnt);
1231 #endif
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);
1243 return SUCCESS;
1246 static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
1247 struct Scsi_Host *shpnt = SCpnt->device->host;
1248 unsigned long flags;
1250 #if DEBUG_RESET
1251 static int called_once = 0;
1252 #endif
1254 #if ERRORS_ONLY
1255 if (SCpnt)
1256 printk("fd_mcs: SCSI Bus Reset\n");
1257 #endif
1259 #if DEBUG_RESET
1260 if (called_once)
1261 fd_mcs_print_info(current_SC);
1262 called_once = 1;
1263 #endif
1265 spin_lock_irqsave(shpnt->host_lock, flags);
1267 outb(1, SCSI_Cntl_port);
1268 do_pause(2);
1269 outb(0, SCSI_Cntl_port);
1270 do_pause(115);
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. */
1279 return SUCCESS;
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:
1297 Start: 0x1b3h
1298 Offset: 0 = partition status
1299 1 = starting head
1300 2 = starting sector and cylinder (word, encoded)
1301 4 = partition type
1302 5 = ending head
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 */
1326 } else {
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 */
1337 } else {
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]);
1344 kfree(p);
1345 return 0;
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,
1358 .can_queue = 1,
1359 .this_id = 7,
1360 .sg_tablesize = 64,
1361 .cmd_per_lun = 1,
1362 .use_clustering = DISABLE_CLUSTERING,
1364 #include "scsi_module.c"
1366 MODULE_LICENSE("GPL");