1/* 2 * sym53c416.c 3 * Low-level SCSI driver for sym53c416 chip. 4 * Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com) 5 * 6 * Changes : 7 * 8 * Marcelo Tosatti <marcelo@conectiva.com.br> : Added io_request_lock locking 9 * Alan Cox <alan@redhat.com> : Cleaned up code formatting 10 * Fixed an irq locking bug 11 * Added ISAPnP support 12 * Bjoern A. Zeeb <bzeeb@zabbadoz.net> : Initial irq locking updates 13 * Added another card with ISAPnP support 14 * 15 * LILO command line usage: sym53c416=<PORTBASE>[,<IRQ>] 16 * 17 * This program is free software; you can redistribute it and/or modify it 18 * under the terms of the GNU General Public License as published by the 19 * Free Software Foundation; either version 2, or (at your option) any 20 * later version. 21 * 22 * This program is distributed in the hope that it will be useful, but 23 * WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 * General Public License for more details. 26 * 27 */ 28 29#include <linux/module.h> 30#include <linux/kernel.h> 31#include <linux/types.h> 32#include <linux/init.h> 33#include <linux/string.h> 34#include <linux/ioport.h> 35#include <linux/interrupt.h> 36#include <linux/delay.h> 37#include <linux/proc_fs.h> 38#include <linux/spinlock.h> 39#include <asm/dma.h> 40#include <asm/system.h> 41#include <asm/io.h> 42#include <linux/blkdev.h> 43#include <linux/isapnp.h> 44#include "scsi.h" 45#include <scsi/scsi_host.h> 46#include "sym53c416.h" 47 48#define VERSION_STRING "Version 1.0.0-ac" 49 50#define TC_LOW 0x00 /* Transfer counter low */ 51#define TC_MID 0x01 /* Transfer counter mid */ 52#define SCSI_FIFO 0x02 /* SCSI FIFO register */ 53#define COMMAND_REG 0x03 /* Command Register */ 54#define STATUS_REG 0x04 /* Status Register (READ) */ 55#define DEST_BUS_ID 0x04 /* Destination Bus ID (WRITE) */ 56#define INT_REG 0x05 /* Interrupt Register (READ) */ 57#define TOM 0x05 /* Time out multiplier (WRITE) */ 58#define STP 0x06 /* Synchronous Transfer period */ 59#define SYNC_OFFSET 0x07 /* Synchronous Offset */ 60#define CONF_REG_1 0x08 /* Configuration register 1 */ 61#define CONF_REG_2 0x0B /* Configuration register 2 */ 62#define CONF_REG_3 0x0C /* Configuration register 3 */ 63#define CONF_REG_4 0x0D /* Configuration register 4 */ 64#define TC_HIGH 0x0E /* Transfer counter high */ 65#define PIO_FIFO_1 0x10 /* PIO FIFO register 1 */ 66#define PIO_FIFO_2 0x11 /* PIO FIFO register 2 */ 67#define PIO_FIFO_3 0x12 /* PIO FIFO register 3 */ 68#define PIO_FIFO_4 0x13 /* PIO FIFO register 4 */ 69#define PIO_FIFO_CNT 0x14 /* PIO FIFO count */ 70#define PIO_INT_REG 0x15 /* PIO interrupt register */ 71#define CONF_REG_5 0x16 /* Configuration register 5 */ 72#define FEATURE_EN 0x1D /* Feature Enable register */ 73 74/* Configuration register 1 entries: */ 75/* Bits 2-0: SCSI ID of host adapter */ 76#define SCM 0x80 /* Slow Cable Mode */ 77#define SRID 0x40 /* SCSI Reset Interrupt Disable */ 78#define PTM 0x20 /* Parity Test Mode */ 79#define EPC 0x10 /* Enable Parity Checking */ 80#define CTME 0x08 /* Special Test Mode */ 81 82/* Configuration register 2 entries: */ 83#define FE 0x40 /* Features Enable */ 84#define SCSI2 0x08 /* SCSI 2 Enable */ 85#define TBPA 0x04 /* Target Bad Parity Abort */ 86 87/* Configuration register 3 entries: */ 88#define IDMRC 0x80 /* ID Message Reserved Check */ 89#define QTE 0x40 /* Queue Tag Enable */ 90#define CDB10 0x20 /* Command Descriptor Block 10 */ 91#define FSCSI 0x10 /* FastSCSI */ 92#define FCLK 0x08 /* FastClock */ 93 94/* Configuration register 4 entries: */ 95#define RBS 0x08 /* Register bank select */ 96#define EAN 0x04 /* Enable Active Negotiation */ 97 98/* Configuration register 5 entries: */ 99#define LPSR 0x80 /* Lower Power SCSI Reset */ 100#define IE 0x20 /* Interrupt Enable */ 101#define LPM 0x02 /* Low Power Mode */ 102#define WSE0 0x01 /* 0WS Enable */ 103 104/* Interrupt register entries: */ 105#define SRST 0x80 /* SCSI Reset */ 106#define ILCMD 0x40 /* Illegal Command */ 107#define DIS 0x20 /* Disconnect */ 108#define BS 0x10 /* Bus Service */ 109#define FC 0x08 /* Function Complete */ 110#define RESEL 0x04 /* Reselected */ 111#define SI 0x03 /* Selection Interrupt */ 112 113/* Status Register Entries: */ 114#define SCI 0x80 /* SCSI Core Int */ 115#define GE 0x40 /* Gross Error */ 116#define PE 0x20 /* Parity Error */ 117#define TC 0x10 /* Terminal Count */ 118#define VGC 0x08 /* Valid Group Code */ 119#define PHBITS 0x07 /* Phase bits */ 120 121/* PIO Interrupt Register Entries: */ 122#define SCI 0x80 /* SCSI Core Int */ 123#define PFI 0x40 /* PIO FIFO Interrupt */ 124#define FULL 0x20 /* PIO FIFO Full */ 125#define EMPTY 0x10 /* PIO FIFO Empty */ 126#define CE 0x08 /* Collision Error */ 127#define OUE 0x04 /* Overflow / Underflow error */ 128#define FIE 0x02 /* Full Interrupt Enable */ 129#define EIE 0x01 /* Empty Interrupt Enable */ 130 131/* SYM53C416 SCSI phases (lower 3 bits of SYM53C416_STATUS_REG) */ 132#define PHASE_DATA_OUT 0x00 133#define PHASE_DATA_IN 0x01 134#define PHASE_COMMAND 0x02 135#define PHASE_STATUS 0x03 136#define PHASE_RESERVED_1 0x04 137#define PHASE_RESERVED_2 0x05 138#define PHASE_MESSAGE_OUT 0x06 139#define PHASE_MESSAGE_IN 0x07 140 141/* SYM53C416 core commands */ 142#define NOOP 0x00 143#define FLUSH_FIFO 0x01 144#define RESET_CHIP 0x02 145#define RESET_SCSI_BUS 0x03 146#define DISABLE_SEL_RESEL 0x45 147#define RESEL_SEQ 0x40 148#define SEL_WITHOUT_ATN_SEQ 0x41 149#define SEL_WITH_ATN_SEQ 0x42 150#define SEL_WITH_ATN_AND_STOP_SEQ 0x43 151#define ENABLE_SEL_RESEL 0x44 152#define SEL_WITH_ATN3_SEQ 0x46 153#define RESEL3_SEQ 0x47 154#define SND_MSG 0x20 155#define SND_STAT 0x21 156#define SND_DATA 0x22 157#define DISCONNECT_SEQ 0x23 158#define TERMINATE_SEQ 0x24 159#define TARGET_COMM_COMPLETE_SEQ 0x25 160#define DISCONN 0x27 161#define RECV_MSG_SEQ 0x28 162#define RECV_CMD 0x29 163#define RECV_DATA 0x2A 164#define RECV_CMD_SEQ 0x2B 165#define TARGET_ABORT_PIO 0x04 166#define TRANSFER_INFORMATION 0x10 167#define INIT_COMM_COMPLETE_SEQ 0x11 168#define MSG_ACCEPTED 0x12 169#define TRANSFER_PAD 0x18 170#define SET_ATN 0x1A 171#define RESET_ATN 0x1B 172#define ILLEGAL 0xFF 173 174#define PIO_MODE 0x80 175 176#define IO_RANGE 0x20 /* 0x00 - 0x1F */ 177#define ID "sym53c416" /* Attention: copied to the sym53c416.h */ 178#define PIO_SIZE 128 /* Size of PIO fifo is 128 bytes */ 179 180#define READ_TIMEOUT 150 181#define WRITE_TIMEOUT 150 182 183#ifdef MODULE 184 185#define sym53c416_base sym53c416 186#define sym53c416_base_1 sym53c416_1 187#define sym53c416_base_2 sym53c416_2 188#define sym53c416_base_3 sym53c416_3 189 190static unsigned int sym53c416_base[2] = {0,0}; 191static unsigned int sym53c416_base_1[2] = {0,0}; 192static unsigned int sym53c416_base_2[2] = {0,0}; 193static unsigned int sym53c416_base_3[2] = {0,0}; 194 195#endif 196 197#define MAXHOSTS 4 198 199#define SG_ADDRESS(buffer) ((char *) (page_address((buffer)->page)+(buffer)->offset)) 200 201enum phases 202{ 203 idle, 204 data_out, 205 data_in, 206 command_ph, 207 status_ph, 208 message_out, 209 message_in 210}; 211 212typedef struct 213{ 214 int base; 215 int irq; 216 int scsi_id; 217} host; 218 219static host hosts[MAXHOSTS] = { 220 {0, 0, SYM53C416_SCSI_ID}, 221 {0, 0, SYM53C416_SCSI_ID}, 222 {0, 0, SYM53C416_SCSI_ID}, 223 {0, 0, SYM53C416_SCSI_ID} 224 }; 225 226static int host_index = 0; 227static char info[120]; 228static Scsi_Cmnd *current_command = NULL; 229static int fastpio = 1; 230 231static int probeaddrs[] = {0x200, 0x220, 0x240, 0}; 232 233static void sym53c416_set_transfer_counter(int base, unsigned int len) 234{ 235 /* Program Transfer Counter */ 236 outb(len & 0x0000FF, base + TC_LOW); 237 outb((len & 0x00FF00) >> 8, base + TC_MID); 238 outb((len & 0xFF0000) >> 16, base + TC_HIGH); 239} 240 241static DEFINE_SPINLOCK(sym53c416_lock); 242 243/* Returns the number of bytes read */ 244static __inline__ unsigned int sym53c416_read(int base, unsigned char *buffer, unsigned int len) 245{ 246 unsigned int orig_len = len; 247 unsigned long flags = 0; 248 unsigned int bytes_left; 249 unsigned long i; 250 int timeout = READ_TIMEOUT; 251 252 /* Do transfer */ 253 spin_lock_irqsave(&sym53c416_lock, flags); 254 while(len && timeout) 255 { 256 bytes_left = inb(base + PIO_FIFO_CNT); /* Number of bytes in the PIO FIFO */ 257 if(fastpio && bytes_left > 3) 258 { 259 insl(base + PIO_FIFO_1, buffer, bytes_left >> 2); 260 buffer += bytes_left & 0xFC; 261 len -= bytes_left & 0xFC; 262 } 263 else if(bytes_left > 0) 264 { 265 len -= bytes_left; 266 for(; bytes_left > 0; bytes_left--) 267 *(buffer++) = inb(base + PIO_FIFO_1); 268 } 269 else 270 { 271 i = jiffies + timeout; 272 spin_unlock_irqrestore(&sym53c416_lock, flags); 273 while(time_before(jiffies, i) && (inb(base + PIO_INT_REG) & EMPTY) && timeout) 274 if(inb(base + PIO_INT_REG) & SCI) 275 timeout = 0; 276 spin_lock_irqsave(&sym53c416_lock, flags); 277 if(inb(base + PIO_INT_REG) & EMPTY) 278 timeout = 0; 279 } 280 } 281 spin_unlock_irqrestore(&sym53c416_lock, flags); 282 return orig_len - len; 283} 284 285/* Returns the number of bytes written */ 286static __inline__ unsigned int sym53c416_write(int base, unsigned char *buffer, unsigned int len) 287{ 288 unsigned int orig_len = len; 289 unsigned long flags = 0; 290 unsigned int bufferfree; 291 unsigned long i; 292 unsigned int timeout = WRITE_TIMEOUT; 293 294 /* Do transfer */ 295 spin_lock_irqsave(&sym53c416_lock, flags); 296 while(len && timeout) 297 { 298 bufferfree = PIO_SIZE - inb(base + PIO_FIFO_CNT); 299 if(bufferfree > len) 300 bufferfree = len; 301 if(fastpio && bufferfree > 3) 302 { 303 outsl(base + PIO_FIFO_1, buffer, bufferfree >> 2); 304 buffer += bufferfree & 0xFC; 305 len -= bufferfree & 0xFC; 306 } 307 else if(bufferfree > 0) 308 { 309 len -= bufferfree; 310 for(; bufferfree > 0; bufferfree--) 311 outb(*(buffer++), base + PIO_FIFO_1); 312 } 313 else 314 { 315 i = jiffies + timeout; 316 spin_unlock_irqrestore(&sym53c416_lock, flags); 317 while(time_before(jiffies, i) && (inb(base + PIO_INT_REG) & FULL) && timeout) 318 ; 319 spin_lock_irqsave(&sym53c416_lock, flags); 320 if(inb(base + PIO_INT_REG) & FULL) 321 timeout = 0; 322 } 323 } 324 spin_unlock_irqrestore(&sym53c416_lock, flags); 325 return orig_len - len; 326} 327 328static irqreturn_t sym53c416_intr_handle(int irq, void *dev_id) 329{ 330 struct Scsi_Host *dev = dev_id; 331 int base = 0; 332 int i; 333 unsigned long flags = 0; 334 unsigned char status_reg, pio_int_reg, int_reg; 335 struct scatterlist *sglist; 336 unsigned int sgcount; 337 unsigned int tot_trans = 0; 338 339 /* We search the base address of the host adapter which caused the interrupt */ 340 for(i = 0; i < host_index && !base; i++) 341 if(irq == hosts[i].irq) 342 base = hosts[i].base; 343 /* If no adapter found, we cannot handle the interrupt. Leave a message */ 344 /* and continue. This should never happen... */ 345 if(!base) 346 { 347 printk(KERN_ERR "sym53c416: No host adapter defined for interrupt %d\n", irq); 348 return IRQ_NONE; 349 } 350 /* Now we have the base address and we can start handling the interrupt */ 351 352 spin_lock_irqsave(dev->host_lock,flags); 353 status_reg = inb(base + STATUS_REG); 354 pio_int_reg = inb(base + PIO_INT_REG); 355 int_reg = inb(base + INT_REG); 356 spin_unlock_irqrestore(dev->host_lock, flags); 357 358 /* First, we handle error conditions */ 359 if(int_reg & SCI) /* SCSI Reset */ 360 { 361 printk(KERN_DEBUG "sym53c416: Reset received\n"); 362 current_command->SCp.phase = idle; 363 current_command->result = DID_RESET << 16; 364 spin_lock_irqsave(dev->host_lock, flags); 365 current_command->scsi_done(current_command); 366 spin_unlock_irqrestore(dev->host_lock, flags); 367 goto out; 368 } 369 if(int_reg & ILCMD) /* Illegal Command */ 370 { 371 printk(KERN_WARNING "sym53c416: Illegal Command: 0x%02x.\n", inb(base + COMMAND_REG)); 372 current_command->SCp.phase = idle; 373 current_command->result = DID_ERROR << 16; 374 spin_lock_irqsave(dev->host_lock, flags); 375 current_command->scsi_done(current_command); 376 spin_unlock_irqrestore(dev->host_lock, flags); 377 goto out; 378 } 379 if(status_reg & GE) /* Gross Error */ 380 { 381 printk(KERN_WARNING "sym53c416: Controller reports gross error.\n"); 382 current_command->SCp.phase = idle; 383 current_command->result = DID_ERROR << 16; 384 spin_lock_irqsave(dev->host_lock, flags); 385 current_command->scsi_done(current_command); 386 spin_unlock_irqrestore(dev->host_lock, flags); 387 goto out; 388 } 389 if(status_reg & PE) /* Parity Error */ 390 { 391 printk(KERN_WARNING "sym53c416:SCSI parity error.\n"); 392 current_command->SCp.phase = idle; 393 current_command->result = DID_PARITY << 16; 394 spin_lock_irqsave(dev->host_lock, flags); 395 current_command->scsi_done(current_command); 396 spin_unlock_irqrestore(dev->host_lock, flags); 397 goto out; 398 } 399 if(pio_int_reg & (CE | OUE)) 400 { 401 printk(KERN_WARNING "sym53c416: PIO interrupt error.\n"); 402 current_command->SCp.phase = idle; 403 current_command->result = DID_ERROR << 16; 404 spin_lock_irqsave(dev->host_lock, flags); 405 current_command->scsi_done(current_command); 406 spin_unlock_irqrestore(dev->host_lock, flags); 407 goto out; 408 } 409 if(int_reg & DIS) /* Disconnect */ 410 { 411 if(current_command->SCp.phase != message_in) 412 current_command->result = DID_NO_CONNECT << 16; 413 else 414 current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16); 415 current_command->SCp.phase = idle; 416 spin_lock_irqsave(dev->host_lock, flags); 417 current_command->scsi_done(current_command); 418 spin_unlock_irqrestore(dev->host_lock, flags); 419 goto out; 420 } 421 /* Now we handle SCSI phases */ 422 423 switch(status_reg & PHBITS) /* Filter SCSI phase out of status reg */ 424 { 425 case PHASE_DATA_OUT: 426 { 427 if(int_reg & BS) 428 { 429 current_command->SCp.phase = data_out; 430 outb(FLUSH_FIFO, base + COMMAND_REG); 431 sym53c416_set_transfer_counter(base, current_command->request_bufflen); 432 outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); 433 if(!current_command->use_sg) 434 tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen); 435 else 436 { 437 sgcount = current_command->use_sg; 438 sglist = current_command->request_buffer; 439 while(sgcount--) 440 { 441 tot_trans += sym53c416_write(base, SG_ADDRESS(sglist), sglist->length); 442 sglist++; 443 } 444 } 445 if(tot_trans < current_command->underflow) 446 printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow); 447 } 448 break; 449 } 450 451 case PHASE_DATA_IN: 452 { 453 if(int_reg & BS) 454 { 455 current_command->SCp.phase = data_in; 456 outb(FLUSH_FIFO, base + COMMAND_REG); 457 sym53c416_set_transfer_counter(base, current_command->request_bufflen); 458 outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); 459 if(!current_command->use_sg) 460 tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen); 461 else 462 { 463 sgcount = current_command->use_sg; 464 sglist = current_command->request_buffer; 465 while(sgcount--) 466 { 467 tot_trans += sym53c416_read(base, SG_ADDRESS(sglist), sglist->length); 468 sglist++; 469 } 470 } 471 if(tot_trans < current_command->underflow) 472 printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow); 473 } 474 break; 475 } 476 477 case PHASE_COMMAND: 478 { 479 current_command->SCp.phase = command_ph; 480 printk(KERN_ERR "sym53c416: Unknown interrupt in command phase.\n"); 481 break; 482 } 483 484 case PHASE_STATUS: 485 { 486 current_command->SCp.phase = status_ph; 487 outb(FLUSH_FIFO, base + COMMAND_REG); 488 outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG); 489 break; 490 } 491 492 case PHASE_RESERVED_1: 493 case PHASE_RESERVED_2: 494 { 495 printk(KERN_ERR "sym53c416: Reserved phase occurred.\n"); 496 break; 497 } 498 499 case PHASE_MESSAGE_OUT: 500 { 501 current_command->SCp.phase = message_out; 502 outb(SET_ATN, base + COMMAND_REG); 503 outb(MSG_ACCEPTED, base + COMMAND_REG); 504 break; 505 } 506 507 case PHASE_MESSAGE_IN: 508 { 509 current_command->SCp.phase = message_in; 510 current_command->SCp.Status = inb(base + SCSI_FIFO); 511 current_command->SCp.Message = inb(base + SCSI_FIFO); 512 if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT) 513 outb(SET_ATN, base + COMMAND_REG); 514 outb(MSG_ACCEPTED, base + COMMAND_REG); 515 break; 516 } 517 } 518out: 519 return IRQ_HANDLED; 520} 521 522static void sym53c416_init(int base, int scsi_id) 523{ 524 outb(RESET_CHIP, base + COMMAND_REG); 525 outb(NOOP, base + COMMAND_REG); 526 outb(0x99, base + TOM); /* Time out of 250 ms */ 527 outb(0x05, base + STP); 528 outb(0x00, base + SYNC_OFFSET); 529 outb(EPC | scsi_id, base + CONF_REG_1); 530 outb(FE | SCSI2 | TBPA, base + CONF_REG_2); 531 outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3); 532 outb(0x83 | EAN, base + CONF_REG_4); 533 outb(IE | WSE0, base + CONF_REG_5); 534 outb(0, base + FEATURE_EN); 535} 536 537static int sym53c416_probeirq(int base, int scsi_id) 538{ 539 int irq, irqs; 540 unsigned long i; 541 542 /* Clear interrupt register */ 543 inb(base + INT_REG); 544 /* Start probing for irq's */ 545 irqs = probe_irq_on(); 546 /* Reinit chip */ 547 sym53c416_init(base, scsi_id); 548 /* Cause interrupt */ 549 outb(NOOP, base + COMMAND_REG); 550 outb(ILLEGAL, base + COMMAND_REG); 551 outb(0x07, base + DEST_BUS_ID); 552 outb(0x00, base + DEST_BUS_ID); 553 /* Wait for interrupt to occur */ 554 i = jiffies + 20; 555 while(time_before(jiffies, i) && !(inb(base + STATUS_REG) & SCI)) 556 barrier(); 557 if(time_before_eq(i, jiffies)) /* timed out */ 558 return 0; 559 /* Get occurred irq */ 560 irq = probe_irq_off(irqs); 561 sym53c416_init(base, scsi_id); 562 return irq; 563} 564 565/* Setup: sym53c416=base,irq */ 566void sym53c416_setup(char *str, int *ints) 567{ 568 int i; 569 570 if(host_index >= MAXHOSTS) 571 { 572 printk(KERN_WARNING "sym53c416: Too many hosts defined\n"); 573 return; 574 } 575 if(ints[0] < 1 || ints[0] > 2) 576 { 577 printk(KERN_ERR "sym53c416: Wrong number of parameters:\n"); 578 printk(KERN_ERR "sym53c416: usage: sym53c416=<base>[,<irq>]\n"); 579 return; 580 } 581 for(i = 0; i < host_index && i >= 0; i++) 582 if(hosts[i].base == ints[1]) 583 i = -2; 584 if(i >= 0) 585 { 586 hosts[host_index].base = ints[1]; 587 hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0; 588 host_index++; 589 } 590} 591 592static int sym53c416_test(int base) 593{ 594 outb(RESET_CHIP, base + COMMAND_REG); 595 outb(NOOP, base + COMMAND_REG); 596 if(inb(base + COMMAND_REG) != NOOP) 597 return 0; 598 if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF) 599 return 0; 600 if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY) 601 return 0; 602 return 1; 603} 604 605 606static struct isapnp_device_id id_table[] __devinitdata = { 607 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, 608 ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4161), 0 }, 609 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, 610 ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4163), 0 }, 611 { ISAPNP_DEVICE_SINGLE_END } 612}; 613 614MODULE_DEVICE_TABLE(isapnp, id_table); 615 616static void sym53c416_probe(void) 617{ 618 int *base = probeaddrs; 619 int ints[2]; 620 621 ints[0] = 1; 622 for(; *base; base++) { 623 if (request_region(*base, IO_RANGE, ID)) { 624 if (sym53c416_test(*base)) { 625 ints[1] = *base; 626 sym53c416_setup(NULL, ints); 627 } 628 release_region(*base, IO_RANGE); 629 } 630 } 631} 632 633int __init sym53c416_detect(struct scsi_host_template *tpnt) 634{ 635 unsigned long flags; 636 struct Scsi_Host * shpnt = NULL; 637 int i; 638 int count; 639 struct pnp_dev *idev = NULL; 640 641#ifdef MODULE 642 int ints[3]; 643 644 ints[0] = 2; 645 if(sym53c416_base) 646 { 647 ints[1] = sym53c416_base[0]; 648 ints[2] = sym53c416_base[1]; 649 sym53c416_setup(NULL, ints); 650 } 651 if(sym53c416_base_1) 652 { 653 ints[1] = sym53c416_base_1[0]; 654 ints[2] = sym53c416_base_1[1]; 655 sym53c416_setup(NULL, ints); 656 } 657 if(sym53c416_base_2) 658 { 659 ints[1] = sym53c416_base_2[0]; 660 ints[2] = sym53c416_base_2[1]; 661 sym53c416_setup(NULL, ints); 662 } 663 if(sym53c416_base_3) 664 { 665 ints[1] = sym53c416_base_3[0]; 666 ints[2] = sym53c416_base_3[1]; 667 sym53c416_setup(NULL, ints); 668 } 669#endif 670 printk(KERN_INFO "sym53c416.c: %s\n", VERSION_STRING); 671 672 for (i=0; id_table[i].vendor != 0; i++) { 673 while((idev=pnp_find_dev(NULL, id_table[i].vendor, 674 id_table[i].function, idev))!=NULL) 675 { 676 int i[3]; 677 678 if(pnp_device_attach(idev)<0) 679 { 680 printk(KERN_WARNING "sym53c416: unable to attach PnP device.\n"); 681 continue; 682 } 683 if(pnp_activate_dev(idev) < 0) 684 { 685 printk(KERN_WARNING "sym53c416: unable to activate PnP device.\n"); 686 pnp_device_detach(idev); 687 continue; 688 689 } 690 691 i[0] = 2; 692 i[1] = pnp_port_start(idev, 0); 693 i[2] = pnp_irq(idev, 0); 694 695 printk(KERN_INFO "sym53c416: ISAPnP card found and configured at 0x%X, IRQ %d.\n", 696 i[1], i[2]); 697 sym53c416_setup(NULL, i); 698 } 699 } 700 sym53c416_probe(); 701 702 /* Now we register and set up each host adapter found... */ 703 for(count = 0, i = 0; i < host_index; i++) { 704 if (!request_region(hosts[i].base, IO_RANGE, ID)) 705 continue; 706 if (!sym53c416_test(hosts[i].base)) { 707 printk(KERN_WARNING "No sym53c416 found at address 0x%03x\n", hosts[i].base); 708 goto fail_release_region; 709 } 710 711 /* We don't have an irq yet, so we should probe for one */ 712 if (!hosts[i].irq) 713 hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id); 714 if (!hosts[i].irq) 715 goto fail_release_region; 716 717 shpnt = scsi_register(tpnt, 0); 718 if (!shpnt) 719 goto fail_release_region; 720 /* Request for specified IRQ */ 721 if (request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, shpnt)) 722 goto fail_free_host; 723 724 spin_lock_irqsave(&sym53c416_lock, flags); 725 shpnt->unique_id = hosts[i].base; 726 shpnt->io_port = hosts[i].base; 727 shpnt->n_io_port = IO_RANGE; 728 shpnt->irq = hosts[i].irq; 729 shpnt->this_id = hosts[i].scsi_id; 730 sym53c416_init(hosts[i].base, hosts[i].scsi_id); 731 count++; 732 spin_unlock_irqrestore(&sym53c416_lock, flags); 733 continue; 734 735 fail_free_host: 736 scsi_unregister(shpnt); 737 fail_release_region: 738 release_region(hosts[i].base, IO_RANGE); 739 } 740 return count; 741} 742 743const char *sym53c416_info(struct Scsi_Host *SChost) 744{ 745 int i; 746 int base = SChost->io_port; 747 int irq = SChost->irq; 748 int scsi_id = 0; 749 int rev = inb(base + TC_HIGH); 750 751 for(i = 0; i < host_index; i++) 752 if(hosts[i].base == base) 753 scsi_id = hosts[i].scsi_id; 754 sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow"); 755 return info; 756} 757 758int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) 759{ 760 int base; 761 unsigned long flags = 0; 762 int i; 763 764 /* Store base register as we can have more than one controller in the system */ 765 base = SCpnt->device->host->io_port; 766 current_command = SCpnt; /* set current command */ 767 current_command->scsi_done = done; /* set ptr to done function */ 768 current_command->SCp.phase = command_ph; /* currect phase is the command phase */ 769 current_command->SCp.Status = 0; 770 current_command->SCp.Message = 0; 771 772 spin_lock_irqsave(&sym53c416_lock, flags); 773 outb(scmd_id(SCpnt), base + DEST_BUS_ID); /* Set scsi id target */ 774 outb(FLUSH_FIFO, base + COMMAND_REG); /* Flush SCSI and PIO FIFO's */ 775 /* Write SCSI command into the SCSI fifo */ 776 for(i = 0; i < SCpnt->cmd_len; i++) 777 outb(SCpnt->cmnd[i], base + SCSI_FIFO); 778 /* Start selection sequence */ 779 outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG); 780 /* Now an interrupt will be generated which we will catch in out interrupt routine */ 781 spin_unlock_irqrestore(&sym53c416_lock, flags); 782 return 0; 783} 784 785static int sym53c416_host_reset(Scsi_Cmnd *SCpnt) 786{ 787 int base; 788 int scsi_id = -1; 789 int i; 790 unsigned long flags; 791 792 spin_lock_irqsave(&sym53c416_lock, flags); 793 794 /* printk("sym53c416_reset\n"); */ 795 base = SCpnt->device->host->io_port; 796 for(i = 0; i < host_index && scsi_id == -1; i++) 797 if(hosts[i].base == base) 798 scsi_id = hosts[i].scsi_id; 799 outb(RESET_CHIP, base + COMMAND_REG); 800 outb(NOOP | PIO_MODE, base + COMMAND_REG); 801 outb(RESET_SCSI_BUS, base + COMMAND_REG); 802 sym53c416_init(base, scsi_id); 803 804 spin_unlock_irqrestore(&sym53c416_lock, flags); 805 return SUCCESS; 806} 807 808static int sym53c416_release(struct Scsi_Host *shost) 809{ 810 if (shost->irq) 811 free_irq(shost->irq, shost); 812 if (shost->io_port && shost->n_io_port) 813 release_region(shost->io_port, shost->n_io_port); 814 return 0; 815} 816 817static int sym53c416_bios_param(struct scsi_device *sdev, 818 struct block_device *dev, 819 sector_t capacity, int *ip) 820{ 821 int size; 822 823 size = capacity; 824 ip[0] = 64; /* heads */ 825 ip[1] = 32; /* sectors */ 826 if((ip[2] = size >> 11) > 1024) /* cylinders, test for big disk */ 827 { 828 ip[0] = 255; /* heads */ 829 ip[1] = 63; /* sectors */ 830 ip[2] = size / (255 * 63); /* cylinders */ 831 } 832 return 0; 833} 834 835/* Loadable module support */ 836#ifdef MODULE 837 838MODULE_AUTHOR("Lieven Willems"); 839MODULE_LICENSE("GPL"); 840 841module_param_array(sym53c416, uint, NULL, 0); 842module_param_array(sym53c416_1, uint, NULL, 0); 843module_param_array(sym53c416_2, uint, NULL, 0); 844module_param_array(sym53c416_3, uint, NULL, 0); 845 846#endif 847 848static struct scsi_host_template driver_template = { 849 .proc_name = "sym53c416", 850 .name = "Symbios Logic 53c416", 851 .detect = sym53c416_detect, 852 .info = sym53c416_info, 853 .queuecommand = sym53c416_queuecommand, 854 .eh_host_reset_handler =sym53c416_host_reset, 855 .release = sym53c416_release, 856 .bios_param = sym53c416_bios_param, 857 .can_queue = 1, 858 .this_id = SYM53C416_SCSI_ID, 859 .sg_tablesize = 32, 860 .cmd_per_lun = 1, 861 .unchecked_isa_dma = 1, 862 .use_clustering = ENABLE_CLUSTERING, 863}; 864#include "scsi_module.c" 865