MIPS: Yosemite, Emma: Fix off-by-two in arcs_cmdline buffer size check
[linux-2.6/linux-mips.git] / drivers / scsi / fd_mcs.c
bloba2c6135d337edab43838a94ee9c9ffc1061b216a
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 <linux/slab.h>
92 #include <scsi/scsicam.h>
93 #include <linux/mca-legacy.h>
95 #include <asm/io.h>
96 #include <asm/system.h>
98 #include "scsi.h"
99 #include <scsi/scsi_host.h>
101 #define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
103 /* START OF USER DEFINABLE OPTIONS */
105 #define DEBUG 0 /* Enable debugging output */
106 #define ENABLE_PARITY 1 /* Enable SCSI Parity */
108 /* END OF USER DEFINABLE OPTIONS */
110 #if DEBUG
111 #define EVERY_ACCESS 0 /* Write a line on every scsi access */
112 #define ERRORS_ONLY 1 /* Only write a line if there is an error */
113 #define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */
114 #define DEBUG_ABORT 1 /* Debug abort() routine */
115 #define DEBUG_RESET 1 /* Debug reset() routine */
116 #define DEBUG_RACE 1 /* Debug interrupt-driven race condition */
117 #else
118 #define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
119 #define ERRORS_ONLY 0
120 #define DEBUG_MESSAGES 0
121 #define DEBUG_ABORT 0
122 #define DEBUG_RESET 0
123 #define DEBUG_RACE 0
124 #endif
126 /* Errors are reported on the line, so we don't need to report them again */
127 #if EVERY_ACCESS
128 #undef ERRORS_ONLY
129 #define ERRORS_ONLY 0
130 #endif
132 #if ENABLE_PARITY
133 #define PARITY_MASK 0x08
134 #else
135 #define PARITY_MASK 0x00
136 #endif
138 enum chip_type {
139 unknown = 0x00,
140 tmc1800 = 0x01,
141 tmc18c50 = 0x02,
142 tmc18c30 = 0x03,
145 enum {
146 in_arbitration = 0x02,
147 in_selection = 0x04,
148 in_other = 0x08,
149 disconnect = 0x10,
150 aborted = 0x20,
151 sent_ident = 0x40,
154 enum in_port_type {
155 Read_SCSI_Data = 0,
156 SCSI_Status = 1,
157 TMC_Status = 2,
158 FIFO_Status = 3, /* tmc18c50/tmc18c30 only */
159 Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */
160 LSB_ID_Code = 5,
161 MSB_ID_Code = 6,
162 Read_Loopback = 7,
163 SCSI_Data_NoACK = 8,
164 Interrupt_Status = 9,
165 Configuration1 = 10,
166 Configuration2 = 11, /* tmc18c50/tmc18c30 only */
167 Read_FIFO = 12,
168 FIFO_Data_Count = 14
171 enum out_port_type {
172 Write_SCSI_Data = 0,
173 SCSI_Cntl = 1,
174 Interrupt_Cntl = 2,
175 SCSI_Mode_Cntl = 3,
176 TMC_Cntl = 4,
177 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */
178 Write_Loopback = 7,
179 IO_Control = 11, /* tmc18c30 only */
180 Write_FIFO = 12
183 struct fd_hostdata {
184 unsigned long _bios_base;
185 int _bios_major;
186 int _bios_minor;
187 volatile int _in_command;
188 Scsi_Cmnd *_current_SC;
189 enum chip_type _chip;
190 int _adapter_mask;
191 int _fifo_count; /* Number of 512 byte blocks before INTR */
193 char _adapter_name[64];
194 #if DEBUG_RACE
195 volatile int _in_interrupt_flag;
196 #endif
198 int _SCSI_Mode_Cntl_port;
199 int _FIFO_Data_Count_port;
200 int _Interrupt_Cntl_port;
201 int _Interrupt_Status_port;
202 int _Interrupt_Cond_port;
203 int _Read_FIFO_port;
204 int _Read_SCSI_Data_port;
205 int _SCSI_Cntl_port;
206 int _SCSI_Data_NoACK_port;
207 int _SCSI_Status_port;
208 int _TMC_Cntl_port;
209 int _TMC_Status_port;
210 int _Write_FIFO_port;
211 int _Write_SCSI_Data_port;
213 int _FIFO_Size; /* = 0x2000; 8k FIFO for
214 pre-tmc18c30 chips */
215 /* simple stats */
216 int _Bytes_Read;
217 int _Bytes_Written;
218 int _INTR_Processed;
221 #define FD_MAX_HOSTS 3 /* enough? */
223 #define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata)
224 #define bios_base (HOSTDATA(shpnt)->_bios_base)
225 #define bios_major (HOSTDATA(shpnt)->_bios_major)
226 #define bios_minor (HOSTDATA(shpnt)->_bios_minor)
227 #define in_command (HOSTDATA(shpnt)->_in_command)
228 #define current_SC (HOSTDATA(shpnt)->_current_SC)
229 #define chip (HOSTDATA(shpnt)->_chip)
230 #define adapter_mask (HOSTDATA(shpnt)->_adapter_mask)
231 #define FIFO_COUNT (HOSTDATA(shpnt)->_fifo_count)
232 #define adapter_name (HOSTDATA(shpnt)->_adapter_name)
233 #if DEBUG_RACE
234 #define in_interrupt_flag (HOSTDATA(shpnt)->_in_interrupt_flag)
235 #endif
236 #define SCSI_Mode_Cntl_port (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port)
237 #define FIFO_Data_Count_port (HOSTDATA(shpnt)->_FIFO_Data_Count_port)
238 #define Interrupt_Cntl_port (HOSTDATA(shpnt)->_Interrupt_Cntl_port)
239 #define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port)
240 #define Interrupt_Cond_port (HOSTDATA(shpnt)->_Interrupt_Cond_port)
241 #define Read_FIFO_port (HOSTDATA(shpnt)->_Read_FIFO_port)
242 #define Read_SCSI_Data_port (HOSTDATA(shpnt)->_Read_SCSI_Data_port)
243 #define SCSI_Cntl_port (HOSTDATA(shpnt)->_SCSI_Cntl_port)
244 #define SCSI_Data_NoACK_port (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port)
245 #define SCSI_Status_port (HOSTDATA(shpnt)->_SCSI_Status_port)
246 #define TMC_Cntl_port (HOSTDATA(shpnt)->_TMC_Cntl_port)
247 #define TMC_Status_port (HOSTDATA(shpnt)->_TMC_Status_port)
248 #define Write_FIFO_port (HOSTDATA(shpnt)->_Write_FIFO_port)
249 #define Write_SCSI_Data_port (HOSTDATA(shpnt)->_Write_SCSI_Data_port)
250 #define FIFO_Size (HOSTDATA(shpnt)->_FIFO_Size)
251 #define Bytes_Read (HOSTDATA(shpnt)->_Bytes_Read)
252 #define Bytes_Written (HOSTDATA(shpnt)->_Bytes_Written)
253 #define INTR_Processed (HOSTDATA(shpnt)->_INTR_Processed)
255 struct fd_mcs_adapters_struct {
256 char *name;
257 int id;
258 enum chip_type fd_chip;
259 int fifo_size;
260 int fifo_count;
263 #define REPLY_ID 0x5137
265 static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
266 {"Future Domain SCSI Adapter MCS-700(18C50)",
267 0x60e9,
268 tmc18c50,
269 0x2000,
271 {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
272 0x6127,
273 tmc1800,
274 0x2000,
276 {"Reply Sound Blaster/SCSI Adapter",
277 REPLY_ID,
278 tmc18c30,
279 0x800,
283 #define FD_BRDS ARRAY_SIZE(fd_mcs_adapters)
285 static irqreturn_t fd_mcs_intr(int irq, void *dev_id);
287 static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
288 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
289 static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
291 /* host information */
292 static int found = 0;
293 static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL };
295 static int user_fifo_count = 0;
296 static int user_fifo_size = 0;
298 #ifndef MODULE
299 static int __init fd_mcs_setup(char *str)
301 static int done_setup = 0;
302 int ints[3];
304 get_options(str, 3, ints);
305 if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) {
306 printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n");
307 return 0;
310 user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
311 user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
312 return 1;
315 __setup("fd_mcs=", fd_mcs_setup);
316 #endif /* !MODULE */
318 static void print_banner(struct Scsi_Host *shpnt)
320 printk("scsi%d <fd_mcs>: ", shpnt->host_no);
322 if (bios_base) {
323 printk("BIOS at 0x%lX", bios_base);
324 } else {
325 printk("No BIOS");
328 printk(", HostID %d, %s Chip, IRQ %d, IO 0x%lX\n", shpnt->this_id, chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? "TMC-18C30" : (chip == tmc1800 ? "TMC-1800" : "Unknown")), shpnt->irq, shpnt->io_port);
332 static void do_pause(unsigned amount)
333 { /* Pause for amount*10 milliseconds */
334 do {
335 mdelay(10);
336 } while (--amount);
339 static void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt)
341 outb(0, SCSI_Cntl_port);
342 outb(0, SCSI_Mode_Cntl_port);
343 if (chip == tmc18c50 || chip == tmc18c30)
344 outb(0x21 | PARITY_MASK, TMC_Cntl_port); /* Clear forced intr. */
345 else
346 outb(0x01 | PARITY_MASK, TMC_Cntl_port);
349 static int fd_mcs_detect(struct scsi_host_template * tpnt)
351 int loop;
352 struct Scsi_Host *shpnt;
354 /* get id, port, bios, irq */
355 int slot;
356 u_char pos2, pos3, pos4;
357 int id, port, irq;
358 unsigned long bios;
360 /* if not MCA machine, return */
361 if (!MCA_bus)
362 return 0;
364 /* changeable? */
365 id = 7;
367 for (loop = 0; loop < FD_BRDS; loop++) {
368 slot = 0;
369 while (MCA_NOTFOUND != (slot = mca_find_adapter(fd_mcs_adapters[loop].id, slot))) {
371 /* if we get this far, an adapter has been detected and is
372 enabled */
374 printk(KERN_INFO "scsi <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1);
376 pos2 = mca_read_stored_pos(slot, 2);
377 pos3 = mca_read_stored_pos(slot, 3);
378 pos4 = mca_read_stored_pos(slot, 4);
380 /* ready for next probe */
381 slot++;
383 if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */
384 static int reply_irq[] = { 10, 11, 14, 15 };
386 bios = 0; /* no bios */
388 if (pos2 & 0x2)
389 port = ports[pos4 & 0x3];
390 else
391 continue;
393 /* can't really disable it, same as irq=10 */
394 irq = reply_irq[((pos4 >> 2) & 0x1) + 2 * ((pos4 >> 4) & 0x1)];
395 } else {
396 bios = addresses[pos2 >> 6];
397 port = ports[(pos2 >> 4) & 0x03];
398 irq = interrupts[(pos2 >> 1) & 0x07];
401 if (irq) {
402 /* claim the slot */
403 mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name);
405 /* check irq/region */
406 if (request_irq(irq, fd_mcs_intr, IRQF_SHARED, "fd_mcs", hosts)) {
407 printk(KERN_ERR "fd_mcs: interrupt is not available, skipping...\n");
408 continue;
411 /* request I/O region */
412 if (request_region(port, 0x10, "fd_mcs")) {
413 printk(KERN_ERR "fd_mcs: I/O region is already in use, skipping...\n");
414 continue;
416 /* register */
417 if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) {
418 printk(KERN_ERR "fd_mcs: scsi_register() failed\n");
419 release_region(port, 0x10);
420 free_irq(irq, hosts);
421 continue;
425 /* save name */
426 strcpy(adapter_name, fd_mcs_adapters[loop].name);
428 /* chip/fifo */
429 chip = fd_mcs_adapters[loop].fd_chip;
430 /* use boot time value if available */
431 FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count;
432 FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size;
434 /* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */
435 #ifdef NOT_USED
436 /* *************************************************** */
437 /* Try to toggle 32-bit mode. This only
438 works on an 18c30 chip. (User reports
439 say this works, so we should switch to
440 it in the near future.) */
441 outb(0x80, port + IO_Control);
442 if ((inb(port + Configuration2) & 0x80) == 0x80) {
443 outb(0x00, port + IO_Control);
444 if ((inb(port + Configuration2) & 0x80) == 0x00) {
445 chip = tmc18c30;
446 FIFO_Size = 0x800; /* 2k FIFO */
448 printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
452 /* That should have worked, but appears to
453 have problems. Let's assume it is an
454 18c30 if the RAM is disabled. */
456 if (inb(port + Configuration2) & 0x02) {
457 chip = tmc18c30;
458 FIFO_Size = 0x800; /* 2k FIFO */
460 printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
462 /* *************************************************** */
463 #endif
465 /* IBM/ANSI scsi scan ordering */
466 /* Stick this back in when the scsi.c changes are there */
467 shpnt->reverse_ordering = 1;
470 /* saving info */
471 hosts[found++] = shpnt;
473 shpnt->this_id = id;
474 shpnt->irq = irq;
475 shpnt->io_port = port;
476 shpnt->n_io_port = 0x10;
478 /* save */
479 bios_base = bios;
480 adapter_mask = (1 << id);
482 /* save more */
483 SCSI_Mode_Cntl_port = port + SCSI_Mode_Cntl;
484 FIFO_Data_Count_port = port + FIFO_Data_Count;
485 Interrupt_Cntl_port = port + Interrupt_Cntl;
486 Interrupt_Status_port = port + Interrupt_Status;
487 Interrupt_Cond_port = port + Interrupt_Cond;
488 Read_FIFO_port = port + Read_FIFO;
489 Read_SCSI_Data_port = port + Read_SCSI_Data;
490 SCSI_Cntl_port = port + SCSI_Cntl;
491 SCSI_Data_NoACK_port = port + SCSI_Data_NoACK;
492 SCSI_Status_port = port + SCSI_Status;
493 TMC_Cntl_port = port + TMC_Cntl;
494 TMC_Status_port = port + TMC_Status;
495 Write_FIFO_port = port + Write_FIFO;
496 Write_SCSI_Data_port = port + Write_SCSI_Data;
498 Bytes_Read = 0;
499 Bytes_Written = 0;
500 INTR_Processed = 0;
502 /* say something */
503 print_banner(shpnt);
505 /* reset */
506 outb(1, SCSI_Cntl_port);
507 do_pause(2);
508 outb(0, SCSI_Cntl_port);
509 do_pause(115);
510 outb(0, SCSI_Mode_Cntl_port);
511 outb(PARITY_MASK, TMC_Cntl_port);
512 /* done reset */
516 if (found == FD_MAX_HOSTS) {
517 printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS);
518 break;
522 return found;
525 static const char *fd_mcs_info(struct Scsi_Host *shpnt)
527 return adapter_name;
530 static int TOTAL_INTR = 0;
533 * inout : decides on the direction of the dataflow and the meaning of the
534 * variables
535 * buffer: If inout==FALSE data is being written to it else read from it
536 * *start: If inout==FALSE start of the valid data in the buffer
537 * offset: If inout==FALSE offset from the beginning of the imaginary file
538 * from which we start writing into the buffer
539 * length: If inout==FALSE max number of bytes to be written into the buffer
540 * else number of bytes in the buffer
542 static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
544 int len = 0;
546 if (inout)
547 return (-ENOSYS);
549 *start = buffer + offset;
551 len += sprintf(buffer + len, "Future Domain MCS-600/700 Driver %s\n", DRIVER_VERSION);
552 len += sprintf(buffer + len, "HOST #%d: %s\n", shpnt->host_no, adapter_name);
553 len += sprintf(buffer + len, "FIFO Size=0x%x, FIFO Count=%d\n", FIFO_Size, FIFO_COUNT);
554 len += sprintf(buffer + len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n", TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written);
556 if ((len -= offset) <= 0)
557 return 0;
558 if (len > length)
559 len = length;
560 return len;
563 static int fd_mcs_select(struct Scsi_Host *shpnt, int target)
565 int status;
566 unsigned long timeout;
568 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
569 outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port);
571 /* Stop arbitration and enable parity */
572 outb(PARITY_MASK, TMC_Cntl_port);
574 timeout = 350; /* 350mS -- because of timeouts
575 (was 250mS) */
577 do {
578 status = inb(SCSI_Status_port); /* Read adapter status */
579 if (status & 1) { /* Busy asserted */
580 /* Enable SCSI Bus (on error, should make bus idle with 0) */
581 outb(0x80, SCSI_Cntl_port);
582 return 0;
584 udelay(1000); /* wait one msec */
585 } while (--timeout);
587 /* Make bus idle */
588 fd_mcs_make_bus_idle(shpnt);
589 #if EVERY_ACCESS
590 if (!target)
591 printk("Selection failed\n");
592 #endif
593 #if ERRORS_ONLY
594 if (!target) {
595 static int flag = 0;
597 if (!flag) /* Skip first failure for all chips. */
598 ++flag;
599 else
600 printk("fd_mcs: Selection failed\n");
602 #endif
603 return 1;
606 static void my_done(struct Scsi_Host *shpnt, int error)
608 if (in_command) {
609 in_command = 0;
610 outb(0x00, Interrupt_Cntl_port);
611 fd_mcs_make_bus_idle(shpnt);
612 current_SC->result = error;
613 current_SC->scsi_done(current_SC);
614 } else {
615 panic("fd_mcs: my_done() called outside of command\n");
617 #if DEBUG_RACE
618 in_interrupt_flag = 0;
619 #endif
622 /* only my_done needs to be protected */
623 static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
625 unsigned long flags;
626 int status;
627 int done = 0;
628 unsigned data_count, tmp_count;
630 int i = 0;
631 struct Scsi_Host *shpnt;
633 TOTAL_INTR++;
635 /* search for one adapter-response on shared interrupt */
636 while ((shpnt = hosts[i++])) {
637 if ((inb(TMC_Status_port)) & 1)
638 break;
641 /* return if some other device on this IRQ caused the interrupt */
642 if (!shpnt) {
643 return IRQ_NONE;
646 INTR_Processed++;
648 outb(0x00, Interrupt_Cntl_port);
650 /* Abort calls my_done, so we do nothing here. */
651 if (current_SC->SCp.phase & aborted) {
652 #if DEBUG_ABORT
653 printk("Interrupt after abort, ignoring\n");
654 #endif
655 /* return IRQ_HANDLED; */
657 #if DEBUG_RACE
658 ++in_interrupt_flag;
659 #endif
661 if (current_SC->SCp.phase & in_arbitration) {
662 status = inb(TMC_Status_port); /* Read adapter status */
663 if (!(status & 0x02)) {
664 #if EVERY_ACCESS
665 printk(" AFAIL ");
666 #endif
667 spin_lock_irqsave(shpnt->host_lock, flags);
668 my_done(shpnt, DID_BUS_BUSY << 16);
669 spin_unlock_irqrestore(shpnt->host_lock, flags);
670 return IRQ_HANDLED;
672 current_SC->SCp.phase = in_selection;
674 outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port);
676 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
677 outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port);
679 /* Stop arbitration and enable parity */
680 outb(0x10 | PARITY_MASK, TMC_Cntl_port);
681 #if DEBUG_RACE
682 in_interrupt_flag = 0;
683 #endif
684 return IRQ_HANDLED;
685 } else if (current_SC->SCp.phase & in_selection) {
686 status = inb(SCSI_Status_port);
687 if (!(status & 0x01)) {
688 /* Try again, for slow devices */
689 if (fd_mcs_select(shpnt, scmd_id(current_SC))) {
690 #if EVERY_ACCESS
691 printk(" SFAIL ");
692 #endif
693 spin_lock_irqsave(shpnt->host_lock, flags);
694 my_done(shpnt, DID_NO_CONNECT << 16);
695 spin_unlock_irqrestore(shpnt->host_lock, flags);
696 return IRQ_HANDLED;
697 } else {
698 #if EVERY_ACCESS
699 printk(" AltSel ");
700 #endif
701 /* Stop arbitration and enable parity */
702 outb(0x10 | PARITY_MASK, TMC_Cntl_port);
705 current_SC->SCp.phase = in_other;
706 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
707 outb(0x80, SCSI_Cntl_port);
708 #if DEBUG_RACE
709 in_interrupt_flag = 0;
710 #endif
711 return IRQ_HANDLED;
714 /* current_SC->SCp.phase == in_other: this is the body of the routine */
716 status = inb(SCSI_Status_port);
718 if (status & 0x10) { /* REQ */
720 switch (status & 0x0e) {
722 case 0x08: /* COMMAND OUT */
723 outb(current_SC->cmnd[current_SC->SCp.sent_command++], Write_SCSI_Data_port);
724 #if EVERY_ACCESS
725 printk("CMD = %x,", current_SC->cmnd[current_SC->SCp.sent_command - 1]);
726 #endif
727 break;
728 case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */
729 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
730 current_SC->SCp.have_data_in = -1;
731 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
733 break;
734 case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */
735 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
736 current_SC->SCp.have_data_in = 1;
737 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
739 break;
740 case 0x0c: /* STATUS IN */
741 current_SC->SCp.Status = inb(Read_SCSI_Data_port);
742 #if EVERY_ACCESS
743 printk("Status = %x, ", current_SC->SCp.Status);
744 #endif
745 #if ERRORS_ONLY
746 if (current_SC->SCp.Status && current_SC->SCp.Status != 2 && current_SC->SCp.Status != 8) {
747 printk("ERROR fd_mcs: target = %d, command = %x, status = %x\n", current_SC->device->id, current_SC->cmnd[0], current_SC->SCp.Status);
749 #endif
750 break;
751 case 0x0a: /* MESSAGE OUT */
752 outb(MESSAGE_REJECT, Write_SCSI_Data_port); /* Reject */
753 break;
754 case 0x0e: /* MESSAGE IN */
755 current_SC->SCp.Message = inb(Read_SCSI_Data_port);
756 #if EVERY_ACCESS
757 printk("Message = %x, ", current_SC->SCp.Message);
758 #endif
759 if (!current_SC->SCp.Message)
760 ++done;
761 #if DEBUG_MESSAGES || EVERY_ACCESS
762 if (current_SC->SCp.Message) {
763 printk("fd_mcs: message = %x\n", current_SC->SCp.Message);
765 #endif
766 break;
770 if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
771 /* We have to get the FIFO direction
772 correct, so I've made a table based
773 on the SCSI Standard of which commands
774 appear to require a DATA OUT phase.
777 p. 94: Command for all device types
778 CHANGE DEFINITION 40 DATA OUT
779 COMPARE 39 DATA OUT
780 COPY 18 DATA OUT
781 COPY AND VERIFY 3a DATA OUT
782 INQUIRY 12
783 LOG SELECT 4c DATA OUT
784 LOG SENSE 4d
785 MODE SELECT (6) 15 DATA OUT
786 MODE SELECT (10) 55 DATA OUT
787 MODE SENSE (6) 1a
788 MODE SENSE (10) 5a
789 READ BUFFER 3c
790 RECEIVE DIAGNOSTIC RESULTS 1c
791 REQUEST SENSE 03
792 SEND DIAGNOSTIC 1d DATA OUT
793 TEST UNIT READY 00
794 WRITE BUFFER 3b DATA OUT
796 p.178: Commands for direct-access devices (not listed on p. 94)
797 FORMAT UNIT 04 DATA OUT
798 LOCK-UNLOCK CACHE 36
799 PRE-FETCH 34
800 PREVENT-ALLOW MEDIUM REMOVAL 1e
801 READ (6)/RECEIVE 08
802 READ (10) 3c
803 READ CAPACITY 25
804 READ DEFECT DATA (10) 37
805 READ LONG 3e
806 REASSIGN BLOCKS 07 DATA OUT
807 RELEASE 17
808 RESERVE 16 DATA OUT
809 REZERO UNIT/REWIND 01
810 SEARCH DATA EQUAL (10) 31 DATA OUT
811 SEARCH DATA HIGH (10) 30 DATA OUT
812 SEARCH DATA LOW (10) 32 DATA OUT
813 SEEK (6) 0b
814 SEEK (10) 2b
815 SET LIMITS (10) 33
816 START STOP UNIT 1b
817 SYNCHRONIZE CACHE 35
818 VERIFY (10) 2f
819 WRITE (6)/PRINT/SEND 0a DATA OUT
820 WRITE (10)/SEND 2a DATA OUT
821 WRITE AND VERIFY (10) 2e DATA OUT
822 WRITE LONG 3f DATA OUT
823 WRITE SAME 41 DATA OUT ?
825 p. 261: Commands for sequential-access devices (not previously listed)
826 ERASE 19
827 LOAD UNLOAD 1b
828 LOCATE 2b
829 READ BLOCK LIMITS 05
830 READ POSITION 34
831 READ REVERSE 0f
832 RECOVER BUFFERED DATA 14
833 SPACE 11
834 WRITE FILEMARKS 10 ?
836 p. 298: Commands for printer devices (not previously listed)
837 ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
838 SLEW AND PRINT 0b DATA OUT -- same as seek
839 STOP PRINT 1b
840 SYNCHRONIZE BUFFER 10
842 p. 315: Commands for processor devices (not previously listed)
844 p. 321: Commands for write-once devices (not previously listed)
845 MEDIUM SCAN 38
846 READ (12) a8
847 SEARCH DATA EQUAL (12) b1 DATA OUT
848 SEARCH DATA HIGH (12) b0 DATA OUT
849 SEARCH DATA LOW (12) b2 DATA OUT
850 SET LIMITS (12) b3
851 VERIFY (12) af
852 WRITE (12) aa DATA OUT
853 WRITE AND VERIFY (12) ae DATA OUT
855 p. 332: Commands for CD-ROM devices (not previously listed)
856 PAUSE/RESUME 4b
857 PLAY AUDIO (10) 45
858 PLAY AUDIO (12) a5
859 PLAY AUDIO MSF 47
860 PLAY TRACK RELATIVE (10) 49
861 PLAY TRACK RELATIVE (12) a9
862 READ HEADER 44
863 READ SUB-CHANNEL 42
864 READ TOC 43
866 p. 370: Commands for scanner devices (not previously listed)
867 GET DATA BUFFER STATUS 34
868 GET WINDOW 25
869 OBJECT POSITION 31
870 SCAN 1b
871 SET WINDOW 24 DATA OUT
873 p. 391: Commands for optical memory devices (not listed)
874 ERASE (10) 2c
875 ERASE (12) ac
876 MEDIUM SCAN 38 DATA OUT
877 READ DEFECT DATA (12) b7
878 READ GENERATION 29
879 READ UPDATED BLOCK 2d
880 UPDATE BLOCK 3d DATA OUT
882 p. 419: Commands for medium changer devices (not listed)
883 EXCHANGE MEDIUM 46
884 INITIALIZE ELEMENT STATUS 07
885 MOVE MEDIUM a5
886 POSITION TO ELEMENT 2b
887 READ ELEMENT STATUS b8
888 REQUEST VOL. ELEMENT ADDRESS b5
889 SEND VOLUME TAG b6 DATA OUT
891 p. 454: Commands for communications devices (not listed previously)
892 GET MESSAGE (6) 08
893 GET MESSAGE (10) 28
894 GET MESSAGE (12) a8
897 switch (current_SC->cmnd[0]) {
898 case CHANGE_DEFINITION:
899 case COMPARE:
900 case COPY:
901 case COPY_VERIFY:
902 case LOG_SELECT:
903 case MODE_SELECT:
904 case MODE_SELECT_10:
905 case SEND_DIAGNOSTIC:
906 case WRITE_BUFFER:
908 case FORMAT_UNIT:
909 case REASSIGN_BLOCKS:
910 case RESERVE:
911 case SEARCH_EQUAL:
912 case SEARCH_HIGH:
913 case SEARCH_LOW:
914 case WRITE_6:
915 case WRITE_10:
916 case WRITE_VERIFY:
917 case 0x3f:
918 case 0x41:
920 case 0xb1:
921 case 0xb0:
922 case 0xb2:
923 case 0xaa:
924 case 0xae:
926 case 0x24:
928 case 0x38:
929 case 0x3d:
931 case 0xb6:
933 case 0xea: /* alternate number for WRITE LONG */
935 current_SC->SCp.have_data_in = -1;
936 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
937 break;
939 case 0x00:
940 default:
942 current_SC->SCp.have_data_in = 1;
943 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
944 break;
948 if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
949 while ((data_count = FIFO_Size - inw(FIFO_Data_Count_port)) > 512) {
950 #if EVERY_ACCESS
951 printk("DC=%d, ", data_count);
952 #endif
953 if (data_count > current_SC->SCp.this_residual)
954 data_count = current_SC->SCp.this_residual;
955 if (data_count > 0) {
956 #if EVERY_ACCESS
957 printk("%d OUT, ", data_count);
958 #endif
959 if (data_count == 1) {
960 Bytes_Written++;
962 outb(*current_SC->SCp.ptr++, Write_FIFO_port);
963 --current_SC->SCp.this_residual;
964 } else {
965 data_count >>= 1;
966 tmp_count = data_count << 1;
967 outsw(Write_FIFO_port, current_SC->SCp.ptr, data_count);
968 current_SC->SCp.ptr += tmp_count;
969 Bytes_Written += tmp_count;
970 current_SC->SCp.this_residual -= tmp_count;
973 if (!current_SC->SCp.this_residual) {
974 if (current_SC->SCp.buffers_residual) {
975 --current_SC->SCp.buffers_residual;
976 ++current_SC->SCp.buffer;
977 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
978 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
979 } else
980 break;
983 } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
984 while ((data_count = inw(FIFO_Data_Count_port)) > 0) {
985 #if EVERY_ACCESS
986 printk("DC=%d, ", data_count);
987 #endif
988 if (data_count > current_SC->SCp.this_residual)
989 data_count = current_SC->SCp.this_residual;
990 if (data_count) {
991 #if EVERY_ACCESS
992 printk("%d IN, ", data_count);
993 #endif
994 if (data_count == 1) {
995 Bytes_Read++;
996 *current_SC->SCp.ptr++ = inb(Read_FIFO_port);
997 --current_SC->SCp.this_residual;
998 } else {
999 data_count >>= 1; /* Number of words */
1000 tmp_count = data_count << 1;
1001 insw(Read_FIFO_port, current_SC->SCp.ptr, data_count);
1002 current_SC->SCp.ptr += tmp_count;
1003 Bytes_Read += tmp_count;
1004 current_SC->SCp.this_residual -= tmp_count;
1007 if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
1008 --current_SC->SCp.buffers_residual;
1009 ++current_SC->SCp.buffer;
1010 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1011 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1016 if (done) {
1017 #if EVERY_ACCESS
1018 printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in);
1019 #endif
1021 #if EVERY_ACCESS
1022 printk("BEFORE MY_DONE. . .");
1023 #endif
1024 spin_lock_irqsave(shpnt->host_lock, flags);
1025 my_done(shpnt, (current_SC->SCp.Status & 0xff)
1026 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
1027 spin_unlock_irqrestore(shpnt->host_lock, flags);
1028 #if EVERY_ACCESS
1029 printk("RETURNING.\n");
1030 #endif
1032 } else {
1033 if (current_SC->SCp.phase & disconnect) {
1034 outb(0xd0 | FIFO_COUNT, Interrupt_Cntl_port);
1035 outb(0x00, SCSI_Cntl_port);
1036 } else {
1037 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
1040 #if DEBUG_RACE
1041 in_interrupt_flag = 0;
1042 #endif
1043 return IRQ_HANDLED;
1046 static int fd_mcs_release(struct Scsi_Host *shpnt)
1048 int i, this_host, irq_usage;
1050 release_region(shpnt->io_port, shpnt->n_io_port);
1052 this_host = -1;
1053 irq_usage = 0;
1054 for (i = 0; i < found; i++) {
1055 if (shpnt == hosts[i])
1056 this_host = i;
1057 if (shpnt->irq == hosts[i]->irq)
1058 irq_usage++;
1061 /* only for the last one */
1062 if (1 == irq_usage)
1063 free_irq(shpnt->irq, hosts);
1065 found--;
1067 for (i = this_host; i < found; i++)
1068 hosts[i] = hosts[i + 1];
1070 hosts[found] = NULL;
1072 return 0;
1075 static int fd_mcs_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
1077 struct Scsi_Host *shpnt = SCpnt->device->host;
1079 if (in_command) {
1080 panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
1082 #if EVERY_ACCESS
1083 printk("queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1084 SCpnt->target, *(unsigned char *) SCpnt->cmnd,
1085 scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
1086 #endif
1088 fd_mcs_make_bus_idle(shpnt);
1090 SCpnt->scsi_done = done; /* Save this for the done function */
1091 current_SC = SCpnt;
1093 /* Initialize static data */
1095 if (scsi_bufflen(current_SC)) {
1096 current_SC->SCp.buffer = scsi_sglist(current_SC);
1097 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1098 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1099 current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
1100 } else {
1101 current_SC->SCp.ptr = NULL;
1102 current_SC->SCp.this_residual = 0;
1103 current_SC->SCp.buffer = NULL;
1104 current_SC->SCp.buffers_residual = 0;
1108 current_SC->SCp.Status = 0;
1109 current_SC->SCp.Message = 0;
1110 current_SC->SCp.have_data_in = 0;
1111 current_SC->SCp.sent_command = 0;
1112 current_SC->SCp.phase = in_arbitration;
1114 /* Start arbitration */
1115 outb(0x00, Interrupt_Cntl_port);
1116 outb(0x00, SCSI_Cntl_port); /* Disable data drivers */
1117 outb(adapter_mask, SCSI_Data_NoACK_port); /* Set our id bit */
1118 in_command = 1;
1119 outb(0x20, Interrupt_Cntl_port);
1120 outb(0x14 | PARITY_MASK, TMC_Cntl_port); /* Start arbitration */
1122 return 0;
1125 static DEF_SCSI_QCMD(fd_mcs_queue)
1127 #if DEBUG_ABORT || DEBUG_RESET
1128 static void fd_mcs_print_info(Scsi_Cmnd * SCpnt)
1130 unsigned int imr;
1131 unsigned int irr;
1132 unsigned int isr;
1133 struct Scsi_Host *shpnt = SCpnt->host;
1135 if (!SCpnt || !SCpnt->host) {
1136 printk("fd_mcs: cannot provide detailed information\n");
1139 printk("%s\n", fd_mcs_info(SCpnt->host));
1140 print_banner(SCpnt->host);
1141 switch (SCpnt->SCp.phase) {
1142 case in_arbitration:
1143 printk("arbitration ");
1144 break;
1145 case in_selection:
1146 printk("selection ");
1147 break;
1148 case in_other:
1149 printk("other ");
1150 break;
1151 default:
1152 printk("unknown ");
1153 break;
1156 printk("(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1157 SCpnt->SCp.phase, SCpnt->device->id, *(unsigned char *) SCpnt->cmnd,
1158 scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
1159 printk("sent_command = %d, have_data_in = %d, timeout = %d\n", SCpnt->SCp.sent_command, SCpnt->SCp.have_data_in, SCpnt->timeout);
1160 #if DEBUG_RACE
1161 printk("in_interrupt_flag = %d\n", in_interrupt_flag);
1162 #endif
1164 imr = (inb(0x0a1) << 8) + inb(0x21);
1165 outb(0x0a, 0xa0);
1166 irr = inb(0xa0) << 8;
1167 outb(0x0a, 0x20);
1168 irr += inb(0x20);
1169 outb(0x0b, 0xa0);
1170 isr = inb(0xa0) << 8;
1171 outb(0x0b, 0x20);
1172 isr += inb(0x20);
1174 /* Print out interesting information */
1175 printk("IMR = 0x%04x", imr);
1176 if (imr & (1 << shpnt->irq))
1177 printk(" (masked)");
1178 printk(", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr);
1180 printk("SCSI Status = 0x%02x\n", inb(SCSI_Status_port));
1181 printk("TMC Status = 0x%02x", inb(TMC_Status_port));
1182 if (inb(TMC_Status_port) & 1)
1183 printk(" (interrupt)");
1184 printk("\n");
1185 printk("Interrupt Status = 0x%02x", inb(Interrupt_Status_port));
1186 if (inb(Interrupt_Status_port) & 0x08)
1187 printk(" (enabled)");
1188 printk("\n");
1189 if (chip == tmc18c50 || chip == tmc18c30) {
1190 printk("FIFO Status = 0x%02x\n", inb(shpnt->io_port + FIFO_Status));
1191 printk("Int. Condition = 0x%02x\n", inb(shpnt->io_port + Interrupt_Cond));
1193 printk("Configuration 1 = 0x%02x\n", inb(shpnt->io_port + Configuration1));
1194 if (chip == tmc18c50 || chip == tmc18c30)
1195 printk("Configuration 2 = 0x%02x\n", inb(shpnt->io_port + Configuration2));
1197 #endif
1199 static int fd_mcs_abort(Scsi_Cmnd * SCpnt)
1201 struct Scsi_Host *shpnt = SCpnt->device->host;
1203 unsigned long flags;
1204 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1205 printk("fd_mcs: abort ");
1206 #endif
1208 spin_lock_irqsave(shpnt->host_lock, flags);
1209 if (!in_command) {
1210 #if EVERY_ACCESS || ERRORS_ONLY
1211 printk(" (not in command)\n");
1212 #endif
1213 spin_unlock_irqrestore(shpnt->host_lock, flags);
1214 return FAILED;
1215 } else
1216 printk("\n");
1218 #if DEBUG_ABORT
1219 fd_mcs_print_info(SCpnt);
1220 #endif
1222 fd_mcs_make_bus_idle(shpnt);
1224 current_SC->SCp.phase |= aborted;
1226 current_SC->result = DID_ABORT << 16;
1228 /* Aborts are not done well. . . */
1229 my_done(shpnt, DID_ABORT << 16);
1231 spin_unlock_irqrestore(shpnt->host_lock, flags);
1232 return SUCCESS;
1235 static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
1236 struct Scsi_Host *shpnt = SCpnt->device->host;
1237 unsigned long flags;
1239 #if DEBUG_RESET
1240 static int called_once = 0;
1241 #endif
1243 #if ERRORS_ONLY
1244 if (SCpnt)
1245 printk("fd_mcs: SCSI Bus Reset\n");
1246 #endif
1248 #if DEBUG_RESET
1249 if (called_once)
1250 fd_mcs_print_info(current_SC);
1251 called_once = 1;
1252 #endif
1254 spin_lock_irqsave(shpnt->host_lock, flags);
1256 outb(1, SCSI_Cntl_port);
1257 do_pause(2);
1258 outb(0, SCSI_Cntl_port);
1259 do_pause(115);
1260 outb(0, SCSI_Mode_Cntl_port);
1261 outb(PARITY_MASK, TMC_Cntl_port);
1263 spin_unlock_irqrestore(shpnt->host_lock, flags);
1265 /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1266 is probably hosed at this point. We will, however, try to keep
1267 things going by informing the high-level code that we need help. */
1268 return SUCCESS;
1271 #include <scsi/scsi_ioctl.h>
1273 static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
1274 sector_t capacity, int *info_array)
1276 unsigned char *p = scsi_bios_ptable(bdev);
1277 int size = capacity;
1279 /* BIOS >= 3.4 for MCA cards */
1280 /* This algorithm was provided by Future Domain (much thanks!). */
1282 if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */
1283 && p[4]) { /* Partition type */
1284 /* The partition table layout is as follows:
1286 Start: 0x1b3h
1287 Offset: 0 = partition status
1288 1 = starting head
1289 2 = starting sector and cylinder (word, encoded)
1290 4 = partition type
1291 5 = ending head
1292 6 = ending sector and cylinder (word, encoded)
1293 8 = starting absolute sector (double word)
1294 c = number of sectors (double word)
1295 Signature: 0x1fe = 0x55aa
1297 So, this algorithm assumes:
1298 1) the first partition table is in use,
1299 2) the data in the first entry is correct, and
1300 3) partitions never divide cylinders
1302 Note that (1) may be FALSE for NetBSD (and other BSD flavors),
1303 as well as for Linux. Note also, that Linux doesn't pay any
1304 attention to the fields that are used by this algorithm -- it
1305 only uses the absolute sector data. Recent versions of Linux's
1306 fdisk(1) will fill this data in correctly, and forthcoming
1307 versions will check for consistency.
1309 Checking for a non-zero partition type is not part of the
1310 Future Domain algorithm, but it seemed to be a reasonable thing
1311 to do, especially in the Linux and BSD worlds. */
1313 info_array[0] = p[5] + 1; /* heads */
1314 info_array[1] = p[6] & 0x3f; /* sectors */
1315 } else {
1316 /* Note that this new method guarantees that there will always be
1317 less than 1024 cylinders on a platter. This is good for drives
1318 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
1319 if ((unsigned int) size >= 0x7e0000U)
1321 info_array[0] = 0xff; /* heads = 255 */
1322 info_array[1] = 0x3f; /* sectors = 63 */
1323 } else if ((unsigned int) size >= 0x200000U) {
1324 info_array[0] = 0x80; /* heads = 128 */
1325 info_array[1] = 0x3f; /* sectors = 63 */
1326 } else {
1327 info_array[0] = 0x40; /* heads = 64 */
1328 info_array[1] = 0x20; /* sectors = 32 */
1331 /* For both methods, compute the cylinders */
1332 info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]);
1333 kfree(p);
1334 return 0;
1337 static struct scsi_host_template driver_template = {
1338 .proc_name = "fd_mcs",
1339 .proc_info = fd_mcs_proc_info,
1340 .detect = fd_mcs_detect,
1341 .release = fd_mcs_release,
1342 .info = fd_mcs_info,
1343 .queuecommand = fd_mcs_queue,
1344 .eh_abort_handler = fd_mcs_abort,
1345 .eh_bus_reset_handler = fd_mcs_bus_reset,
1346 .bios_param = fd_mcs_biosparam,
1347 .can_queue = 1,
1348 .this_id = 7,
1349 .sg_tablesize = 64,
1350 .cmd_per_lun = 1,
1351 .use_clustering = DISABLE_CLUSTERING,
1353 #include "scsi_module.c"
1355 MODULE_LICENSE("GPL");