Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.38-rc2 1355 lines 40 kB view raw
1/* 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 <linux/slab.h> 92#include <scsi/scsicam.h> 93#include <linux/mca-legacy.h> 94 95#include <asm/io.h> 96#include <asm/system.h> 97 98#include "scsi.h" 99#include <scsi/scsi_host.h> 100 101#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>" 102 103/* START OF USER DEFINABLE OPTIONS */ 104 105#define DEBUG 0 /* Enable debugging output */ 106#define ENABLE_PARITY 1 /* Enable SCSI Parity */ 107 108/* END OF USER DEFINABLE OPTIONS */ 109 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 125 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 131 132#if ENABLE_PARITY 133#define PARITY_MASK 0x08 134#else 135#define PARITY_MASK 0x00 136#endif 137 138enum chip_type { 139 unknown = 0x00, 140 tmc1800 = 0x01, 141 tmc18c50 = 0x02, 142 tmc18c30 = 0x03, 143}; 144 145enum { 146 in_arbitration = 0x02, 147 in_selection = 0x04, 148 in_other = 0x08, 149 disconnect = 0x10, 150 aborted = 0x20, 151 sent_ident = 0x40, 152}; 153 154enum 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 169}; 170 171enum 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 181}; 182 183struct 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 */ 192 193 char _adapter_name[64]; 194#if DEBUG_RACE 195 volatile int _in_interrupt_flag; 196#endif 197 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; 212 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; 219}; 220 221#define FD_MAX_HOSTS 3 /* enough? */ 222 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) 254 255struct fd_mcs_adapters_struct { 256 char *name; 257 int id; 258 enum chip_type fd_chip; 259 int fifo_size; 260 int fifo_count; 261}; 262 263#define REPLY_ID 0x5137 264 265static struct fd_mcs_adapters_struct fd_mcs_adapters[] = { 266 {"Future Domain SCSI Adapter MCS-700(18C50)", 267 0x60e9, 268 tmc18c50, 269 0x2000, 270 4}, 271 {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)", 272 0x6127, 273 tmc1800, 274 0x2000, 275 4}, 276 {"Reply Sound Blaster/SCSI Adapter", 277 REPLY_ID, 278 tmc18c30, 279 0x800, 280 2}, 281}; 282 283#define FD_BRDS ARRAY_SIZE(fd_mcs_adapters) 284 285static irqreturn_t fd_mcs_intr(int irq, void *dev_id); 286 287static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 }; 288static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; 289static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; 290 291/* host information */ 292static int found = 0; 293static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL }; 294 295static int user_fifo_count = 0; 296static int user_fifo_size = 0; 297 298#ifndef MODULE 299static int __init fd_mcs_setup(char *str) 300{ 301 static int done_setup = 0; 302 int ints[3]; 303 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; 308 } 309 310 user_fifo_count = ints[0] >= 1 ? ints[1] : 0; 311 user_fifo_size = ints[0] >= 2 ? ints[2] : 0; 312 return 1; 313} 314 315__setup("fd_mcs=", fd_mcs_setup); 316#endif /* !MODULE */ 317 318static void print_banner(struct Scsi_Host *shpnt) 319{ 320 printk("scsi%d <fd_mcs>: ", shpnt->host_no); 321 322 if (bios_base) { 323 printk("BIOS at 0x%lX", bios_base); 324 } else { 325 printk("No BIOS"); 326 } 327 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); 329} 330 331 332static void do_pause(unsigned amount) 333{ /* Pause for amount*10 milliseconds */ 334 do { 335 mdelay(10); 336 } while (--amount); 337} 338 339static void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt) 340{ 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); 347} 348 349static int fd_mcs_detect(struct scsi_host_template * tpnt) 350{ 351 int loop; 352 struct Scsi_Host *shpnt; 353 354 /* get id, port, bios, irq */ 355 int slot; 356 u_char pos2, pos3, pos4; 357 int id, port, irq; 358 unsigned long bios; 359 360 /* if not MCA machine, return */ 361 if (!MCA_bus) 362 return 0; 363 364 /* changeable? */ 365 id = 7; 366 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))) { 370 371 /* if we get this far, an adapter has been detected and is 372 enabled */ 373 374 printk(KERN_INFO "scsi <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1); 375 376 pos2 = mca_read_stored_pos(slot, 2); 377 pos3 = mca_read_stored_pos(slot, 3); 378 pos4 = mca_read_stored_pos(slot, 4); 379 380 /* ready for next probe */ 381 slot++; 382 383 if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */ 384 static int reply_irq[] = { 10, 11, 14, 15 }; 385 386 bios = 0; /* no bios */ 387 388 if (pos2 & 0x2) 389 port = ports[pos4 & 0x3]; 390 else 391 continue; 392 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]; 399 } 400 401 if (irq) { 402 /* claim the slot */ 403 mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name); 404 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; 409 } 410 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; 415 } 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; 422 } 423 424 425 /* save name */ 426 strcpy(adapter_name, fd_mcs_adapters[loop].name); 427 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; 433 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 */ 447 448 printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size); 449 } 450 } 451 452 /* That should have worked, but appears to 453 have problems. Let's assume it is an 454 18c30 if the RAM is disabled. */ 455 456 if (inb(port + Configuration2) & 0x02) { 457 chip = tmc18c30; 458 FIFO_Size = 0x800; /* 2k FIFO */ 459 460 printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size); 461 } 462 /* *************************************************** */ 463#endif 464 465 /* IBM/ANSI scsi scan ordering */ 466 /* Stick this back in when the scsi.c changes are there */ 467 shpnt->reverse_ordering = 1; 468 469 470 /* saving info */ 471 hosts[found++] = shpnt; 472 473 shpnt->this_id = id; 474 shpnt->irq = irq; 475 shpnt->io_port = port; 476 shpnt->n_io_port = 0x10; 477 478 /* save */ 479 bios_base = bios; 480 adapter_mask = (1 << id); 481 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; 497 498 Bytes_Read = 0; 499 Bytes_Written = 0; 500 INTR_Processed = 0; 501 502 /* say something */ 503 print_banner(shpnt); 504 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 */ 513 } 514 } 515 516 if (found == FD_MAX_HOSTS) { 517 printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS); 518 break; 519 } 520 } 521 522 return found; 523} 524 525static const char *fd_mcs_info(struct Scsi_Host *shpnt) 526{ 527 return adapter_name; 528} 529 530static int TOTAL_INTR = 0; 531 532/* 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 541 */ 542static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout) 543{ 544 int len = 0; 545 546 if (inout) 547 return (-ENOSYS); 548 549 *start = buffer + offset; 550 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); 555 556 if ((len -= offset) <= 0) 557 return 0; 558 if (len > length) 559 len = length; 560 return len; 561} 562 563static int fd_mcs_select(struct Scsi_Host *shpnt, int target) 564{ 565 int status; 566 unsigned long timeout; 567 568 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */ 569 outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port); 570 571 /* Stop arbitration and enable parity */ 572 outb(PARITY_MASK, TMC_Cntl_port); 573 574 timeout = 350; /* 350mS -- because of timeouts 575 (was 250mS) */ 576 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; 583 } 584 udelay(1000); /* wait one msec */ 585 } while (--timeout); 586 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; 596 597 if (!flag) /* Skip first failure for all chips. */ 598 ++flag; 599 else 600 printk("fd_mcs: Selection failed\n"); 601 } 602#endif 603 return 1; 604} 605 606static void my_done(struct Scsi_Host *shpnt, int error) 607{ 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"); 616 } 617#if DEBUG_RACE 618 in_interrupt_flag = 0; 619#endif 620} 621 622/* only my_done needs to be protected */ 623static irqreturn_t fd_mcs_intr(int irq, void *dev_id) 624{ 625 unsigned long flags; 626 int status; 627 int done = 0; 628 unsigned data_count, tmp_count; 629 630 int i = 0; 631 struct Scsi_Host *shpnt; 632 633 TOTAL_INTR++; 634 635 /* search for one adapter-response on shared interrupt */ 636 while ((shpnt = hosts[i++])) { 637 if ((inb(TMC_Status_port)) & 1) 638 break; 639 } 640 641 /* return if some other device on this IRQ caused the interrupt */ 642 if (!shpnt) { 643 return IRQ_NONE; 644 } 645 646 INTR_Processed++; 647 648 outb(0x00, Interrupt_Cntl_port); 649 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; */ 656 } 657#if DEBUG_RACE 658 ++in_interrupt_flag; 659#endif 660 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; 671 } 672 current_SC->SCp.phase = in_selection; 673 674 outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port); 675 676 outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */ 677 outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port); 678 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); 703 } 704 } 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; 712 } 713 714 /* current_SC->SCp.phase == in_other: this is the body of the routine */ 715 716 status = inb(SCSI_Status_port); 717 718 if (status & 0x10) { /* REQ */ 719 720 switch (status & 0x0e) { 721 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); 732 } 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); 738 } 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); 748 } 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); 764 } 765#endif 766 break; 767 } 768 } 769 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. 775 */ 776 /* 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 795 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 ? 824 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 ? 835 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 841 842 p. 315: Commands for processor devices (not previously listed) 843 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 854 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 865 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 872 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 881 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 890 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 895 */ 896 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: 907 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: 919 920 case 0xb1: 921 case 0xb0: 922 case 0xb2: 923 case 0xaa: 924 case 0xae: 925 926 case 0x24: 927 928 case 0x38: 929 case 0x3d: 930 931 case 0xb6: 932 933 case 0xea: /* alternate number for WRITE LONG */ 934 935 current_SC->SCp.have_data_in = -1; 936 outb(0xd0 | PARITY_MASK, TMC_Cntl_port); 937 break; 938 939 case 0x00: 940 default: 941 942 current_SC->SCp.have_data_in = 1; 943 outb(0x90 | PARITY_MASK, TMC_Cntl_port); 944 break; 945 } 946 } 947 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++; 961 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; 971 } 972 } 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; 981 } 982 } 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; 1005 } 1006 } 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; 1012 } 1013 } 1014 } 1015 1016 if (done) { 1017#if EVERY_ACCESS 1018 printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in); 1019#endif 1020 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 1031 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); 1038 } 1039 } 1040#if DEBUG_RACE 1041 in_interrupt_flag = 0; 1042#endif 1043 return IRQ_HANDLED; 1044} 1045 1046static int fd_mcs_release(struct Scsi_Host *shpnt) 1047{ 1048 int i, this_host, irq_usage; 1049 1050 release_region(shpnt->io_port, shpnt->n_io_port); 1051 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++; 1059 } 1060 1061 /* only for the last one */ 1062 if (1 == irq_usage) 1063 free_irq(shpnt->irq, hosts); 1064 1065 found--; 1066 1067 for (i = this_host; i < found; i++) 1068 hosts[i] = hosts[i + 1]; 1069 1070 hosts[found] = NULL; 1071 1072 return 0; 1073} 1074 1075static int fd_mcs_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) 1076{ 1077 struct Scsi_Host *shpnt = SCpnt->device->host; 1078 1079 if (in_command) { 1080 panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n"); 1081 } 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 1087 1088 fd_mcs_make_bus_idle(shpnt); 1089 1090 SCpnt->scsi_done = done; /* Save this for the done function */ 1091 current_SC = SCpnt; 1092 1093 /* Initialize static data */ 1094 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; 1105 } 1106 1107 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; 1113 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 */ 1121 1122 return 0; 1123} 1124 1125static DEF_SCSI_QCMD(fd_mcs_queue) 1126 1127#if DEBUG_ABORT || DEBUG_RESET 1128static void fd_mcs_print_info(Scsi_Cmnd * SCpnt) 1129{ 1130 unsigned int imr; 1131 unsigned int irr; 1132 unsigned int isr; 1133 struct Scsi_Host *shpnt = SCpnt->host; 1134 1135 if (!SCpnt || !SCpnt->host) { 1136 printk("fd_mcs: cannot provide detailed information\n"); 1137 } 1138 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; 1154 } 1155 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 1163 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); 1173 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); 1179 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)); 1192 } 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)); 1196} 1197#endif 1198 1199static int fd_mcs_abort(Scsi_Cmnd * SCpnt) 1200{ 1201 struct Scsi_Host *shpnt = SCpnt->device->host; 1202 1203 unsigned long flags; 1204#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT 1205 printk("fd_mcs: abort "); 1206#endif 1207 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"); 1217 1218#if DEBUG_ABORT 1219 fd_mcs_print_info(SCpnt); 1220#endif 1221 1222 fd_mcs_make_bus_idle(shpnt); 1223 1224 current_SC->SCp.phase |= aborted; 1225 1226 current_SC->result = DID_ABORT << 16; 1227 1228 /* Aborts are not done well. . . */ 1229 my_done(shpnt, DID_ABORT << 16); 1230 1231 spin_unlock_irqrestore(shpnt->host_lock, flags); 1232 return SUCCESS; 1233} 1234 1235static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) { 1236 struct Scsi_Host *shpnt = SCpnt->device->host; 1237 unsigned long flags; 1238 1239#if DEBUG_RESET 1240 static int called_once = 0; 1241#endif 1242 1243#if ERRORS_ONLY 1244 if (SCpnt) 1245 printk("fd_mcs: SCSI Bus Reset\n"); 1246#endif 1247 1248#if DEBUG_RESET 1249 if (called_once) 1250 fd_mcs_print_info(current_SC); 1251 called_once = 1; 1252#endif 1253 1254 spin_lock_irqsave(shpnt->host_lock, flags); 1255 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); 1262 1263 spin_unlock_irqrestore(shpnt->host_lock, flags); 1264 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; 1269} 1270 1271#include <scsi/scsi_ioctl.h> 1272 1273static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev, 1274 sector_t capacity, int *info_array) 1275{ 1276 unsigned char *p = scsi_bios_ptable(bdev); 1277 int size = capacity; 1278 1279 /* BIOS >= 3.4 for MCA cards */ 1280 /* This algorithm was provided by Future Domain (much thanks!). */ 1281 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: 1285 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 1296 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 1301 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. 1308 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. */ 1312 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) 1320 { 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 */ 1329 } 1330 } 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; 1335} 1336 1337static 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, 1352}; 1353#include "scsi_module.c" 1354 1355MODULE_LICENSE("GPL");