blob: 668569e8856bdb635ad90d9aaa718abcedf0b754 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* fd_mcs.c -- Future Domain MCS 600/700 (or IBM OEM) driver
2 *
3 * FutureDomain MCS-600/700 v0.2 03/11/1998 by ZP Gu (zpg@castle.net)
4 *
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.
9 *
10 * This driver also supports Reply SB16/SCSI card (the SCSI part).
11 *
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.
16 *
17 * Assumptions: TMC-1800/18C50/18C30, BIOS >= 3.4
18 *
19 * LILO command-line options:
20 * fd_mcs=<FIFO_COUNT>[,<FIFO_SIZE>]
21 *
22 * ********************************************************
23 * Please see Copyrights/Comments in fdomain.* for credits.
24 * Following is from fdomain.c for acknowledgement:
25 *
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
30 *
31 * $Id: fdomain.c,v 5.45 1996/10/02 15:13:06 root Exp $
32
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.
37
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.
42
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.
46
47 **************************************************************************
48
49 NOTES ON USER DEFINABLE OPTIONS:
50
51 DEBUG: This turns on the printing of various debug information.
52
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.
58
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*****]
68
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.
77
78 **************************************************************************/
79
80#include <linux/module.h>
81#include <linux/init.h>
82#include <linux/interrupt.h>
83#include <linux/blkdev.h>
84#include <linux/errno.h>
85#include <linux/string.h>
86#include <linux/ioport.h>
87#include <linux/proc_fs.h>
88#include <linux/delay.h>
89#include <linux/mca.h>
90#include <linux/spinlock.h>
91#include <scsi/scsicam.h>
92#include <linux/mca-legacy.h>
93
94#include <asm/io.h>
95#include <asm/system.h>
96
97#include "scsi.h"
98#include <scsi/scsi_host.h>
99
100#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
101
102/* START OF USER DEFINABLE OPTIONS */
103
104#define DEBUG 0 /* Enable debugging output */
105#define ENABLE_PARITY 1 /* Enable SCSI Parity */
106
107/* END OF USER DEFINABLE OPTIONS */
108
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
124
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
130
131#if ENABLE_PARITY
132#define PARITY_MASK 0x08
133#else
134#define PARITY_MASK 0x00
135#endif
136
137enum chip_type {
138 unknown = 0x00,
139 tmc1800 = 0x01,
140 tmc18c50 = 0x02,
141 tmc18c30 = 0x03,
142};
143
144enum {
145 in_arbitration = 0x02,
146 in_selection = 0x04,
147 in_other = 0x08,
148 disconnect = 0x10,
149 aborted = 0x20,
150 sent_ident = 0x40,
151};
152
153enum in_port_type {
154 Read_SCSI_Data = 0,
155 SCSI_Status = 1,
156 TMC_Status = 2,
157 FIFO_Status = 3, /* 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
168};
169
170enum out_port_type {
171 Write_SCSI_Data = 0,
172 SCSI_Cntl = 1,
173 Interrupt_Cntl = 2,
174 SCSI_Mode_Cntl = 3,
175 TMC_Cntl = 4,
176 Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */
177 Write_Loopback = 7,
178 IO_Control = 11, /* tmc18c30 only */
179 Write_FIFO = 12
180};
181
182struct fd_hostdata {
183 unsigned long _bios_base;
184 int _bios_major;
185 int _bios_minor;
186 volatile int _in_command;
187 Scsi_Cmnd *_current_SC;
188 enum chip_type _chip;
189 int _adapter_mask;
190 int _fifo_count; /* Number of 512 byte blocks before INTR */
191
192 char _adapter_name[64];
193#if DEBUG_RACE
194 volatile int _in_interrupt_flag;
195#endif
196
197 int _SCSI_Mode_Cntl_port;
198 int _FIFO_Data_Count_port;
199 int _Interrupt_Cntl_port;
200 int _Interrupt_Status_port;
201 int _Interrupt_Cond_port;
202 int _Read_FIFO_port;
203 int _Read_SCSI_Data_port;
204 int _SCSI_Cntl_port;
205 int _SCSI_Data_NoACK_port;
206 int _SCSI_Status_port;
207 int _TMC_Cntl_port;
208 int _TMC_Status_port;
209 int _Write_FIFO_port;
210 int _Write_SCSI_Data_port;
211
212 int _FIFO_Size; /* = 0x2000; 8k FIFO for
213 pre-tmc18c30 chips */
214 /* simple stats */
215 int _Bytes_Read;
216 int _Bytes_Written;
217 int _INTR_Processed;
218};
219
220#define FD_MAX_HOSTS 3 /* enough? */
221
222#define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata)
223#define bios_base (HOSTDATA(shpnt)->_bios_base)
224#define bios_major (HOSTDATA(shpnt)->_bios_major)
225#define bios_minor (HOSTDATA(shpnt)->_bios_minor)
226#define in_command (HOSTDATA(shpnt)->_in_command)
227#define current_SC (HOSTDATA(shpnt)->_current_SC)
228#define chip (HOSTDATA(shpnt)->_chip)
229#define adapter_mask (HOSTDATA(shpnt)->_adapter_mask)
230#define FIFO_COUNT (HOSTDATA(shpnt)->_fifo_count)
231#define adapter_name (HOSTDATA(shpnt)->_adapter_name)
232#if DEBUG_RACE
233#define in_interrupt_flag (HOSTDATA(shpnt)->_in_interrupt_flag)
234#endif
235#define SCSI_Mode_Cntl_port (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port)
236#define FIFO_Data_Count_port (HOSTDATA(shpnt)->_FIFO_Data_Count_port)
237#define Interrupt_Cntl_port (HOSTDATA(shpnt)->_Interrupt_Cntl_port)
238#define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port)
239#define Interrupt_Cond_port (HOSTDATA(shpnt)->_Interrupt_Cond_port)
240#define Read_FIFO_port (HOSTDATA(shpnt)->_Read_FIFO_port)
241#define Read_SCSI_Data_port (HOSTDATA(shpnt)->_Read_SCSI_Data_port)
242#define SCSI_Cntl_port (HOSTDATA(shpnt)->_SCSI_Cntl_port)
243#define SCSI_Data_NoACK_port (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port)
244#define SCSI_Status_port (HOSTDATA(shpnt)->_SCSI_Status_port)
245#define TMC_Cntl_port (HOSTDATA(shpnt)->_TMC_Cntl_port)
246#define TMC_Status_port (HOSTDATA(shpnt)->_TMC_Status_port)
247#define Write_FIFO_port (HOSTDATA(shpnt)->_Write_FIFO_port)
248#define Write_SCSI_Data_port (HOSTDATA(shpnt)->_Write_SCSI_Data_port)
249#define FIFO_Size (HOSTDATA(shpnt)->_FIFO_Size)
250#define Bytes_Read (HOSTDATA(shpnt)->_Bytes_Read)
251#define Bytes_Written (HOSTDATA(shpnt)->_Bytes_Written)
252#define INTR_Processed (HOSTDATA(shpnt)->_INTR_Processed)
253
254struct fd_mcs_adapters_struct {
255 char *name;
256 int id;
257 enum chip_type fd_chip;
258 int fifo_size;
259 int fifo_count;
260};
261
262#define REPLY_ID 0x5137
263
264static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
265 {"Future Domain SCSI Adapter MCS-700(18C50)",
266 0x60e9,
267 tmc18c50,
268 0x2000,
269 4},
270 {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
271 0x6127,
272 tmc1800,
273 0x2000,
274 4},
275 {"Reply Sound Blaster/SCSI Adapter",
276 REPLY_ID,
277 tmc18c30,
278 0x800,
279 2},
280};
281
Tobias Klauser6391a112006-06-08 22:23:48 -0700282#define FD_BRDS ARRAY_SIZE(fd_mcs_adapters)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
David Howells7d12e782006-10-05 14:55:46 +0100284static irqreturn_t fd_mcs_intr(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
287static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
288static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
289
290/* host information */
291static int found = 0;
292static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL };
293
294static int user_fifo_count = 0;
295static int user_fifo_size = 0;
296
Jeff Garzikdb3a8812006-11-08 19:56:20 -0800297#ifndef MODULE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298static int __init fd_mcs_setup(char *str)
299{
300 static int done_setup = 0;
301 int ints[3];
302
303 get_options(str, 3, ints);
304 if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) {
305 printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n");
306 return 0;
307 }
308
309 user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
310 user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
311 return 1;
312}
313
314__setup("fd_mcs=", fd_mcs_setup);
Jeff Garzikdb3a8812006-11-08 19:56:20 -0800315#endif /* !MODULE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
317static void print_banner(struct Scsi_Host *shpnt)
318{
319 printk("scsi%d <fd_mcs>: ", shpnt->host_no);
320
321 if (bios_base) {
322 printk("BIOS at 0x%lX", bios_base);
323 } else {
324 printk("No BIOS");
325 }
326
327 printk(", HostID %d, %s Chip, IRQ %d, IO 0x%lX\n", shpnt->this_id, chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? "TMC-18C30" : (chip == tmc1800 ? "TMC-1800" : "Unknown")), shpnt->irq, shpnt->io_port);
328}
329
330
331static void do_pause(unsigned amount)
332{ /* Pause for amount*10 milliseconds */
333 do {
334 mdelay(10);
335 } while (--amount);
336}
337
338static void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt)
339{
340 outb(0, SCSI_Cntl_port);
341 outb(0, SCSI_Mode_Cntl_port);
342 if (chip == tmc18c50 || chip == tmc18c30)
343 outb(0x21 | PARITY_MASK, TMC_Cntl_port); /* Clear forced intr. */
344 else
345 outb(0x01 | PARITY_MASK, TMC_Cntl_port);
346}
347
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100348static int fd_mcs_detect(struct scsi_host_template * tpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349{
350 int loop;
351 struct Scsi_Host *shpnt;
352
353 /* get id, port, bios, irq */
354 int slot;
355 u_char pos2, pos3, pos4;
356 int id, port, irq;
357 unsigned long bios;
358
359 /* if not MCA machine, return */
360 if (!MCA_bus)
361 return 0;
362
363 /* changeable? */
364 id = 7;
365
366 for (loop = 0; loop < FD_BRDS; loop++) {
367 slot = 0;
368 while (MCA_NOTFOUND != (slot = mca_find_adapter(fd_mcs_adapters[loop].id, slot))) {
369
370 /* if we get this far, an adapter has been detected and is
371 enabled */
372
373 printk(KERN_INFO "scsi <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1);
374
375 pos2 = mca_read_stored_pos(slot, 2);
376 pos3 = mca_read_stored_pos(slot, 3);
377 pos4 = mca_read_stored_pos(slot, 4);
378
379 /* ready for next probe */
380 slot++;
381
382 if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */
383 static int reply_irq[] = { 10, 11, 14, 15 };
384
385 bios = 0; /* no bios */
386
387 if (pos2 & 0x2)
388 port = ports[pos4 & 0x3];
389 else
390 continue;
391
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];
398 }
399
400 if (irq) {
401 /* claim the slot */
402 mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name);
403
404 /* check irq/region */
Thomas Gleixner1d6f3592006-07-01 19:29:42 -0700405 if (request_irq(irq, fd_mcs_intr, IRQF_SHARED, "fd_mcs", hosts)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 printk(KERN_ERR "fd_mcs: interrupt is not available, skipping...\n");
407 continue;
408 }
409
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;
414 }
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;
421 }
422
423
424 /* save name */
425 strcpy(adapter_name, fd_mcs_adapters[loop].name);
426
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;
432
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 */
446
447 printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
448 }
449 }
450
451 /* That should have worked, but appears to
452 have problems. Let's assume it is an
453 18c30 if the RAM is disabled. */
454
455 if (inb(port + Configuration2) & 0x02) {
456 chip = tmc18c30;
457 FIFO_Size = 0x800; /* 2k FIFO */
458
459 printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
460 }
461 /* *************************************************** */
462#endif
463
464 /* IBM/ANSI scsi scan ordering */
465 /* Stick this back in when the scsi.c changes are there */
466 shpnt->reverse_ordering = 1;
467
468
469 /* saving info */
470 hosts[found++] = shpnt;
471
472 shpnt->this_id = id;
473 shpnt->irq = irq;
474 shpnt->io_port = port;
475 shpnt->n_io_port = 0x10;
476
477 /* save */
478 bios_base = bios;
479 adapter_mask = (1 << id);
480
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;
496
497 Bytes_Read = 0;
498 Bytes_Written = 0;
499 INTR_Processed = 0;
500
501 /* say something */
502 print_banner(shpnt);
503
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 */
512 }
513 }
514
515 if (found == FD_MAX_HOSTS) {
516 printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS);
517 break;
518 }
519 }
520
521 return found;
522}
523
524static const char *fd_mcs_info(struct Scsi_Host *shpnt)
525{
526 return adapter_name;
527}
528
529static int TOTAL_INTR = 0;
530
531/*
532 * 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
540 */
541static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
542{
543 int len = 0;
544
545 if (inout)
546 return (-ENOSYS);
547
548 *start = buffer + offset;
549
550 len += sprintf(buffer + len, "Future Domain MCS-600/700 Driver %s\n", DRIVER_VERSION);
551 len += sprintf(buffer + len, "HOST #%d: %s\n", shpnt->host_no, adapter_name);
552 len += sprintf(buffer + len, "FIFO Size=0x%x, FIFO Count=%d\n", FIFO_Size, FIFO_COUNT);
553 len += sprintf(buffer + len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n", TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written);
554
555 if ((len -= offset) <= 0)
556 return 0;
557 if (len > length)
558 len = length;
559 return len;
560}
561
562static int fd_mcs_select(struct Scsi_Host *shpnt, int target)
563{
564 int status;
565 unsigned long timeout;
566
567 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
568 outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port);
569
570 /* Stop arbitration and enable parity */
571 outb(PARITY_MASK, TMC_Cntl_port);
572
573 timeout = 350; /* 350mS -- because of timeouts
574 (was 250mS) */
575
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;
582 }
583 udelay(1000); /* wait one msec */
584 } while (--timeout);
585
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;
595
596 if (!flag) /* Skip first failure for all chips. */
597 ++flag;
598 else
599 printk("fd_mcs: Selection failed\n");
600 }
601#endif
602 return 1;
603}
604
605static void my_done(struct Scsi_Host *shpnt, int error)
606{
607 if (in_command) {
608 in_command = 0;
609 outb(0x00, Interrupt_Cntl_port);
610 fd_mcs_make_bus_idle(shpnt);
611 current_SC->result = error;
612 current_SC->scsi_done(current_SC);
613 } else {
614 panic("fd_mcs: my_done() called outside of command\n");
615 }
616#if DEBUG_RACE
617 in_interrupt_flag = 0;
618#endif
619}
620
621/* only my_done needs to be protected */
David Howells7d12e782006-10-05 14:55:46 +0100622static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
624 unsigned long flags;
625 int status;
626 int done = 0;
627 unsigned data_count, tmp_count;
628
629 int i = 0;
630 struct Scsi_Host *shpnt;
631
632 TOTAL_INTR++;
633
634 /* search for one adapter-response on shared interrupt */
635 while ((shpnt = hosts[i++])) {
636 if ((inb(TMC_Status_port)) & 1)
637 break;
638 }
639
640 /* return if some other device on this IRQ caused the interrupt */
641 if (!shpnt) {
642 return IRQ_NONE;
643 }
644
645 INTR_Processed++;
646
647 outb(0x00, Interrupt_Cntl_port);
648
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; */
655 }
656#if DEBUG_RACE
657 ++in_interrupt_flag;
658#endif
659
660 if (current_SC->SCp.phase & in_arbitration) {
661 status = inb(TMC_Status_port); /* 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;
670 }
671 current_SC->SCp.phase = in_selection;
672
673 outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port);
674
675 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
Jeff Garzik422c0d62005-10-24 18:05:09 -0400676 outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
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 */
Jeff Garzik422c0d62005-10-24 18:05:09 -0400688 if (fd_mcs_select(shpnt, scmd_id(current_SC))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689#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);
702 }
703 }
704 current_SC->SCp.phase = in_other;
705 outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
706 outb(0x80, SCSI_Cntl_port);
707#if DEBUG_RACE
708 in_interrupt_flag = 0;
709#endif
710 return IRQ_HANDLED;
711 }
712
713 /* current_SC->SCp.phase == in_other: this is the body of the routine */
714
715 status = inb(SCSI_Status_port);
716
717 if (status & 0x10) { /* REQ */
718
719 switch (status & 0x0e) {
720
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);
731 }
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);
737 }
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);
747 }
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);
763 }
764#endif
765 break;
766 }
767 }
768
769 if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
770 /* 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.
774 */
775 /*
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
794
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 ?
823
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 ?
834
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
840
841 p. 315: Commands for processor devices (not previously listed)
842
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
853
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
864
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
871
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
880
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
889
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
894 */
895
896 switch (current_SC->cmnd[0]) {
897 case CHANGE_DEFINITION:
898 case COMPARE:
899 case COPY:
900 case COPY_VERIFY:
901 case LOG_SELECT:
902 case MODE_SELECT:
903 case MODE_SELECT_10:
904 case SEND_DIAGNOSTIC:
905 case WRITE_BUFFER:
906
907 case FORMAT_UNIT:
908 case REASSIGN_BLOCKS:
909 case RESERVE:
910 case SEARCH_EQUAL:
911 case SEARCH_HIGH:
912 case SEARCH_LOW:
913 case WRITE_6:
914 case WRITE_10:
915 case WRITE_VERIFY:
916 case 0x3f:
917 case 0x41:
918
919 case 0xb1:
920 case 0xb0:
921 case 0xb2:
922 case 0xaa:
923 case 0xae:
924
925 case 0x24:
926
927 case 0x38:
928 case 0x3d:
929
930 case 0xb6:
931
932 case 0xea: /* alternate number for WRITE LONG */
933
934 current_SC->SCp.have_data_in = -1;
935 outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
936 break;
937
938 case 0x00:
939 default:
940
941 current_SC->SCp.have_data_in = 1;
942 outb(0x90 | PARITY_MASK, TMC_Cntl_port);
943 break;
944 }
945 }
946
947 if (current_SC->SCp.have_data_in == -1) { /* 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++;
960
961 outb(*current_SC->SCp.ptr++, Write_FIFO_port);
962 --current_SC->SCp.this_residual;
963 } else {
964 data_count >>= 1;
965 tmp_count = data_count << 1;
966 outsw(Write_FIFO_port, current_SC->SCp.ptr, data_count);
967 current_SC->SCp.ptr += tmp_count;
968 Bytes_Written += tmp_count;
969 current_SC->SCp.this_residual -= tmp_count;
970 }
971 }
972 if (!current_SC->SCp.this_residual) {
973 if (current_SC->SCp.buffers_residual) {
974 --current_SC->SCp.buffers_residual;
975 ++current_SC->SCp.buffer;
976 current_SC->SCp.ptr = 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;
980 }
981 }
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;
1004 }
1005 }
1006 if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
1007 --current_SC->SCp.buffers_residual;
1008 ++current_SC->SCp.buffer;
1009 current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset;
1010 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1011 }
1012 }
1013 }
1014
1015 if (done) {
1016#if EVERY_ACCESS
1017 printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in);
1018#endif
1019
1020#if 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;
1026
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));
1030
1031 if (key != UNIT_ATTENTION && !(key == NOT_READY && code == 0x04 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1032 && !(key == ILLEGAL_REQUEST && (code == 0x25 || code == 0x24 || !code)))
1033
1034 printk("fd_mcs: REQUEST SENSE " "Key = %x, Code = %x, Qualifier = %x\n", key, code, qualifier);
1035 }
1036 }
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
1048
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);
1055 }
1056 }
1057#if DEBUG_RACE
1058 in_interrupt_flag = 0;
1059#endif
1060 return IRQ_HANDLED;
1061}
1062
1063static int fd_mcs_release(struct Scsi_Host *shpnt)
1064{
1065 int i, this_host, irq_usage;
1066
1067 release_region(shpnt->io_port, shpnt->n_io_port);
1068
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++;
1076 }
1077
1078 /* only for the last one */
1079 if (1 == irq_usage)
1080 free_irq(shpnt->irq, hosts);
1081
1082 found--;
1083
1084 for (i = this_host; i < found; i++)
1085 hosts[i] = hosts[i + 1];
1086
1087 hosts[found] = NULL;
1088
1089 return 0;
1090}
1091
1092static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
1093{
1094 struct Scsi_Host *shpnt = SCpnt->device->host;
1095
1096 if (in_command) {
1097 panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
1098 }
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
1102
1103 fd_mcs_make_bus_idle(shpnt);
1104
1105 SCpnt->scsi_done = done; /* Save this for the done function */
1106 current_SC = SCpnt;
1107
1108 /* Initialize static data */
1109
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;
1120 }
1121
1122
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;
1128
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 */
1136
1137 return 0;
1138}
1139
1140#if DEBUG_ABORT || DEBUG_RESET
1141static void fd_mcs_print_info(Scsi_Cmnd * SCpnt)
1142{
1143 unsigned int imr;
1144 unsigned int irr;
1145 unsigned int isr;
1146 struct Scsi_Host *shpnt = SCpnt->host;
1147
1148 if (!SCpnt || !SCpnt->host) {
1149 printk("fd_mcs: cannot provide detailed information\n");
1150 }
1151
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;
1167 }
1168
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
1174
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);
1184
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);
1190
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));
1203 }
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));
1207}
1208#endif
1209
1210static int fd_mcs_abort(Scsi_Cmnd * SCpnt)
1211{
1212 struct Scsi_Host *shpnt = SCpnt->device->host;
1213
1214 unsigned long flags;
1215#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1216 printk("fd_mcs: abort ");
1217#endif
1218
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");
1228
1229#if DEBUG_ABORT
1230 fd_mcs_print_info(SCpnt);
1231#endif
1232
1233 fd_mcs_make_bus_idle(shpnt);
1234
1235 current_SC->SCp.phase |= aborted;
1236
1237 current_SC->result = DID_ABORT << 16;
1238
1239 /* Aborts are not done well. . . */
1240 my_done(shpnt, DID_ABORT << 16);
1241
1242 spin_unlock_irqrestore(shpnt->host_lock, flags);
1243 return SUCCESS;
1244}
1245
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
1247 struct Scsi_Host *shpnt = SCpnt->device->host;
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001248 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
1250#if DEBUG_RESET
1251 static int called_once = 0;
1252#endif
1253
1254#if ERRORS_ONLY
1255 if (SCpnt)
1256 printk("fd_mcs: SCSI Bus Reset\n");
1257#endif
1258
1259#if DEBUG_RESET
1260 if (called_once)
1261 fd_mcs_print_info(current_SC);
1262 called_once = 1;
1263#endif
1264
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001265 spin_lock_irqsave(shpnt->host_lock, flags);
1266
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 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);
1273
Jeff Garzik 68b3aa72005-05-28 07:56:31 -04001274 spin_unlock_irqrestore(shpnt->host_lock, flags);
1275
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 /* 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;
1280}
1281
1282#include <scsi/scsi_ioctl.h>
1283
1284static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
1285 sector_t capacity, int *info_array)
1286{
1287 unsigned char *p = scsi_bios_ptable(bdev);
1288 int size = capacity;
1289
1290 /* BIOS >= 3.4 for MCA cards */
1291 /* This algorithm was provided by Future Domain (much thanks!). */
1292
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:
1296
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
1307
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
1312
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.
1319
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. */
1323
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)
1331 {
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 */
1340 }
1341 }
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;
1346}
1347
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +01001348static struct scsi_host_template driver_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 .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,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 .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,
1363};
1364#include "scsi_module.c"
Randy.Dunlapd39a9422005-09-13 21:43:56 -07001365
1366MODULE_LICENSE("GPL");