#include <linux/pci.h>
#include <linux/stat.h>
#include <linux/delay.h>
+#include <scsi/scsicam.h>
#include <asm/io.h>
#include <asm/system.h>
-#include "scsi.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_ioctl.h>
+#include "fdomain.h"
MODULE_AUTHOR("Rickard E. Faith");
MODULE_DESCRIPTION("Future domain SCSI driver");
/* .bss will zero all the static variables below */
static int port_base;
static unsigned long bios_base;
+static void __iomem * bios_mem;
static int bios_major;
static int bios_minor;
static int PCI_bus;
static int Quantum; /* Quantum board variant */
static int interrupt_level;
static volatile int in_command;
-static Scsi_Cmnd *current_SC;
+static struct scsi_cmnd *current_SC;
static enum chip_type chip = unknown;
static int adapter_mask;
static int this_id;
static volatile int in_interrupt_flag;
#endif
-static int SCSI_Mode_Cntl_port;
-static int FIFO_Data_Count_port;
-static int Interrupt_Cntl_port;
-static int Interrupt_Status_port;
-static int Read_FIFO_port;
-static int Read_SCSI_Data_port;
-static int SCSI_Cntl_port;
-static int SCSI_Data_NoACK_port;
-static int SCSI_Status_port;
-static int TMC_Cntl_port;
-static int TMC_Status_port;
-static int Write_FIFO_port;
-static int Write_SCSI_Data_port;
-
static int FIFO_Size = 0x2000; /* 8k FIFO for
pre-tmc18c30 chips */
static irqreturn_t do_fdomain_16x0_intr( int irq, void *dev_id,
struct pt_regs * regs );
-int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
-
/* Allow insmod parameters to be like LILO parameters. For example:
insmod fdomain fdomain=0x140,11 */
static char * fdomain = NULL;
-MODULE_PARM(fdomain, "s");
+module_param(fdomain, charp, 0);
static unsigned long addresses[] = {
0xc8000,
*/
-struct signature {
+static struct signature {
const char *signature;
int sig_offset;
int sig_length;
printk( "\n" );
}
-int __init fdomain_setup(char *str)
+int fdomain_setup(char *str)
{
int ints[4];
mdelay(10*amount);
}
-inline static void fdomain_make_bus_idle( void )
+static inline void fdomain_make_bus_idle( void )
{
- outb( 0, SCSI_Cntl_port );
- outb( 0, SCSI_Mode_Cntl_port );
+ outb(0, port_base + SCSI_Cntl);
+ outb(0, port_base + SCSI_Mode_Cntl);
if (chip == tmc18c50 || chip == tmc18c30)
- outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */
+ outb(0x21 | PARITY_MASK, port_base + TMC_Cntl); /* Clear forced intr. */
else
- outb( 0x01 | PARITY_MASK, TMC_Cntl_port );
+ outb(0x01 | PARITY_MASK, port_base + TMC_Cntl);
}
static int fdomain_is_valid_port( int port )
static int fdomain_isa_detect( int *irq, int *iobase )
{
+#ifndef PCMCIA
int i, j;
int base = 0xdeadbeef;
int flag = 0;
printk( "scsi: <fdomain> fdomain_isa_detect:" );
#endif
- for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
+ for (i = 0; i < ADDRESS_COUNT; i++) {
+ void __iomem *p = ioremap(addresses[i], 0x2000);
+ if (!p)
+ continue;
#if DEBUG_DETECT
printk( " %lx(%lx),", addresses[i], bios_base );
#endif
- for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
- if (isa_check_signature(addresses[i] + signatures[j].sig_offset,
+ for (j = 0; j < SIGNATURE_COUNT; j++) {
+ if (check_signature(p + signatures[j].sig_offset,
signatures[j].signature,
signatures[j].sig_length )) {
bios_major = signatures[j].major_bios_version;
PCI_bus = (signatures[j].flag == 1);
Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
bios_base = addresses[i];
+ bios_mem = p;
+ goto found;
}
}
+ iounmap(p);
}
-
+
+found:
if (bios_major == 2) {
/* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
Assuming the ROM is enabled (otherwise we wouldn't have been
switch (Quantum) {
case 2: /* ISA_200S */
case 3: /* ISA_250MG */
- base = isa_readb(bios_base + 0x1fa2) + (isa_readb(bios_base + 0x1fa3) << 8);
+ base = readb(bios_mem + 0x1fa2) + (readb(bios_mem + 0x1fa3) << 8);
break;
case 4: /* ISA_200S (another one) */
- base = isa_readb(bios_base + 0x1fa3) + (isa_readb(bios_base + 0x1fa4) << 8);
+ base = readb(bios_mem + 0x1fa3) + (readb(bios_mem + 0x1fa4) << 8);
break;
default:
- base = isa_readb(bios_base + 0x1fcc) + (isa_readb(bios_base + 0x1fcd) << 8);
+ base = readb(bios_mem + 0x1fcc) + (readb(bios_mem + 0x1fcd) << 8);
break;
}
printk( " %x,", base );
#endif
- for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
- if (base == ports[i])
- ++flag;
+ for (i = 0; i < PORT_COUNT; i++) {
+ if (base == ports[i]) {
+ if (!request_region(base, 0x10, "fdomain"))
+ break;
+ if (!fdomain_is_valid_port(base)) {
+ release_region(base, 0x10);
+ break;
+ }
+ *irq = fdomain_get_irq( base );
+ *iobase = base;
+ return 1;
+ }
}
- if (flag && fdomain_is_valid_port( base )) {
- *irq = fdomain_get_irq( base );
- *iobase = base;
- return 1;
- }
-
/* This is a bad sign. It usually means that someone patched the
BIOS signature list (the signatures variable) to contain a BIOS
signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */
for (i = 0; i < PORT_COUNT; i++) {
base = ports[i];
- if (check_region( base, 0x10 )) {
+ if (!request_region(base, 0x10, "fdomain")) {
#if DEBUG_DETECT
printk( " (%x inuse),", base );
#endif
#if DEBUG_DETECT
printk( " %x,", base );
#endif
- if ((flag = fdomain_is_valid_port( base ))) break;
+ flag = fdomain_is_valid_port(base);
+ if (flag)
+ break;
+ release_region(base, 0x10);
}
#if DEBUG_DETECT
*iobase = base;
return 1; /* success */
+#else
+ return 0;
+#endif
}
/* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
pci_base = pci_resource_start(pdev, 0);
pci_irq = pdev->irq;
+ if (!request_region( pci_base, 0x10, "fdomain" ))
+ return 0;
+
/* Now we have the I/O base address and interrupt from the PCI
configuration registers. */
" IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
#endif
- if (!fdomain_is_valid_port( *iobase )) {
+ if (!fdomain_is_valid_port(pci_base)) {
printk(KERN_ERR "scsi: <fdomain> PCI card detected, but driver not loaded (invalid port)\n" );
+ release_region(pci_base, 0x10);
return 0;
}
}
#endif
-struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
{
int retcode;
struct Scsi_Host *shpnt;
printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
port_base, interrupt_level );
#endif
+ if (!request_region(port_base, 0x10, "fdomain")) {
+ printk( "scsi: <fdomain> port 0x%x is busy\n", port_base );
+ printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
+ return NULL;
+ }
if (!fdomain_is_valid_port( port_base )) {
printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
port_base );
printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
+ release_region(port_base, 0x10);
return NULL;
}
} else {
}
}
- SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl;
- FIFO_Data_Count_port = port_base + FIFO_Data_Count;
- Interrupt_Cntl_port = port_base + Interrupt_Cntl;
- Interrupt_Status_port = port_base + Interrupt_Status;
- Read_FIFO_port = port_base + Read_FIFO;
- Read_SCSI_Data_port = port_base + Read_SCSI_Data;
- SCSI_Cntl_port = port_base + SCSI_Cntl;
- SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK;
- SCSI_Status_port = port_base + SCSI_Status;
- TMC_Cntl_port = port_base + TMC_Cntl;
- TMC_Status_port = port_base + TMC_Status;
- Write_FIFO_port = port_base + Write_FIFO;
- Write_SCSI_Data_port = port_base + Write_SCSI_Data;
-
- fdomain_16x0_bus_reset( NULL);
+ fdomain_16x0_bus_reset(NULL);
if (fdomain_test_loopback()) {
printk(KERN_ERR "scsi: <fdomain> Detection failed (loopback test failed at port base 0x%x)\n", port_base);
if (setup_called) {
printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
}
+ release_region(port_base, 0x10);
return NULL;
}
get resources. */
shpnt = scsi_register( tpnt, 0 );
- if(shpnt == NULL)
+ if(shpnt == NULL) {
+ release_region(port_base, 0x10);
return NULL;
+ }
shpnt->irq = interrupt_level;
shpnt->io_port = port_base;
- scsi_set_device(shpnt, &pdev->dev);
shpnt->n_io_port = 0x10;
print_banner( shpnt );
/* Log IRQ with kernel */
if (!interrupt_level) {
printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
+ release_region(port_base, 0x10);
return NULL;
} else {
/* Register the IRQ with the kernel */
printk(KERN_ERR " Send mail to faith@acm.org\n" );
}
printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
+ release_region(port_base, 0x10);
return NULL;
}
}
-
- /* Log I/O ports with kernel */
- request_region( port_base, 0x10, "fdomain" );
-
return shpnt;
}
-static int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+static int fdomain_16x0_detect(struct scsi_host_template *tpnt)
{
if (fdomain)
fdomain_setup(fdomain);
printk( "fdomain_arbitrate()\n" );
#endif
- outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */
- outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */
- outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
+ outb(0x00, port_base + SCSI_Cntl); /* Disable data drivers */
+ outb(adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */
+ outb(0x04 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */
timeout = 500;
do {
- status = inb( TMC_Status_port ); /* Read adapter status */
+ status = inb(port_base + TMC_Status); /* Read adapter status */
if (status & 0x02) /* Arbitration complete */
return 0;
mdelay(1); /* Wait one millisecond */
static int flag = 0;
#endif
- outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
- outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
+ outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */
+ outb(adapter_mask | (1 << target), port_base + SCSI_Data_NoACK);
/* Stop arbitration and enable parity */
- outb( PARITY_MASK, TMC_Cntl_port );
+ outb(PARITY_MASK, port_base + TMC_Cntl);
timeout = 350; /* 350 msec */
do {
- status = inb( SCSI_Status_port ); /* Read adapter status */
+ status = inb(port_base + SCSI_Status); /* Read adapter status */
if (status & 1) { /* Busy asserted */
/* Enable SCSI Bus (on error, should make bus idle with 0) */
- outb( 0x80, SCSI_Cntl_port );
+ outb(0x80, port_base + SCSI_Cntl);
return 0;
}
mdelay(1); /* wait one msec */
{
if (in_command) {
in_command = 0;
- outb( 0x00, Interrupt_Cntl_port );
+ outb(0x00, port_base + Interrupt_Cntl);
fdomain_make_bus_idle();
current_SC->result = error;
if (current_SC->scsi_done)
running. */
/* Check for other IRQ sources */
- if((inb(TMC_Status_port)&0x01)==0)
+ if ((inb(port_base + TMC_Status) & 0x01) == 0)
return IRQ_NONE;
/* It is our IRQ */
- outb( 0x00, Interrupt_Cntl_port );
+ outb(0x00, port_base + Interrupt_Cntl);
/* We usually have one spurious interrupt after each command. Ignore it. */
if (!in_command || !current_SC) { /* Spurious interrupt */
#endif
if (current_SC->SCp.phase & in_arbitration) {
- status = inb( TMC_Status_port ); /* Read adapter status */
+ status = inb(port_base + TMC_Status); /* Read adapter status */
if (!(status & 0x02)) {
#if EVERY_ACCESS
printk( " AFAIL " );
}
current_SC->SCp.phase = in_selection;
- outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
+ outb(0x40 | FIFO_COUNT, port_base + Interrupt_Cntl);
- outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
- outb( adapter_mask | (1 << current_SC->device->id), SCSI_Data_NoACK_port );
+ outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */
+ outb(adapter_mask | (1 << scmd_id(current_SC)), port_base + SCSI_Data_NoACK);
/* Stop arbitration and enable parity */
- outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
+ outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
#if DEBUG_RACE
in_interrupt_flag = 0;
#endif
return IRQ_HANDLED;
} else if (current_SC->SCp.phase & in_selection) {
- status = inb( SCSI_Status_port );
+ status = inb(port_base + SCSI_Status);
if (!(status & 0x01)) {
/* Try again, for slow devices */
- if (fdomain_select( current_SC->device->id )) {
+ if (fdomain_select( scmd_id(current_SC) )) {
#if EVERY_ACCESS
printk( " SFAIL " );
#endif
printk( " AltSel " );
#endif
/* Stop arbitration and enable parity */
- outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
+ outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
}
}
current_SC->SCp.phase = in_other;
- outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
- outb( 0x80, SCSI_Cntl_port );
+ outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl);
+ outb(0x80, port_base + SCSI_Cntl);
#if DEBUG_RACE
in_interrupt_flag = 0;
#endif
/* current_SC->SCp.phase == in_other: this is the body of the routine */
- status = inb( SCSI_Status_port );
+ status = inb(port_base + SCSI_Status);
if (status & 0x10) { /* REQ */
switch (status & 0x0e) {
case 0x08: /* COMMAND OUT */
- outb( current_SC->cmnd[current_SC->SCp.sent_command++],
- Write_SCSI_Data_port );
+ outb(current_SC->cmnd[current_SC->SCp.sent_command++],
+ port_base + Write_SCSI_Data);
#if EVERY_ACCESS
printk( "CMD = %x,",
current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */
if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
current_SC->SCp.have_data_in = -1;
- outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
+ outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl);
}
break;
case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */
if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
current_SC->SCp.have_data_in = 1;
- outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
+ outb(0x90 | PARITY_MASK, port_base + TMC_Cntl);
}
break;
case 0x0c: /* STATUS IN */
- current_SC->SCp.Status = inb( Read_SCSI_Data_port );
+ current_SC->SCp.Status = inb(port_base + Read_SCSI_Data);
#if EVERY_ACCESS
printk( "Status = %x, ", current_SC->SCp.Status );
#endif
#endif
break;
case 0x0a: /* MESSAGE OUT */
- outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
+ outb(MESSAGE_REJECT, port_base + Write_SCSI_Data); /* Reject */
break;
case 0x0e: /* MESSAGE IN */
- current_SC->SCp.Message = inb( Read_SCSI_Data_port );
+ current_SC->SCp.Message = inb(port_base + Read_SCSI_Data);
#if EVERY_ACCESS
printk( "Message = %x, ", current_SC->SCp.Message );
#endif
if (chip == tmc1800 && !current_SC->SCp.have_data_in
&& (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
- if(scsi_to_pci_dma_dir(current_SC->sc_data_direction) == PCI_DMA_TODEVICE)
+ if(current_SC->sc_data_direction == DMA_TO_DEVICE)
{
current_SC->SCp.have_data_in = -1;
- outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
+ outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl);
}
else
{
current_SC->SCp.have_data_in = 1;
- outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
+ outb(0x90 | PARITY_MASK, port_base + TMC_Cntl);
}
}
if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
- while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) {
+ while ((data_count = FIFO_Size - inw(port_base + FIFO_Data_Count)) > 512) {
#if EVERY_ACCESS
printk( "DC=%d, ", data_count ) ;
#endif
printk( "%d OUT, ", data_count );
#endif
if (data_count == 1) {
- outb( *current_SC->SCp.ptr++, Write_FIFO_port );
+ outb(*current_SC->SCp.ptr++, port_base + Write_FIFO);
--current_SC->SCp.this_residual;
} else {
data_count >>= 1;
- outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
+ outsw(port_base + Write_FIFO, current_SC->SCp.ptr, data_count);
current_SC->SCp.ptr += 2 * data_count;
current_SC->SCp.this_residual -= 2 * data_count;
}
}
if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
- while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
+ while ((data_count = inw(port_base + FIFO_Data_Count)) > 0) {
#if EVERY_ACCESS
printk( "DC=%d, ", data_count );
#endif
printk( "%d IN, ", data_count );
#endif
if (data_count == 1) {
- *current_SC->SCp.ptr++ = inb( Read_FIFO_port );
+ *current_SC->SCp.ptr++ = inb(port_base + Read_FIFO);
--current_SC->SCp.this_residual;
} else {
data_count >>= 1; /* Number of words */
- insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );
+ insw(port_base + Read_FIFO, current_SC->SCp.ptr, data_count);
current_SC->SCp.ptr += 2 * data_count;
current_SC->SCp.this_residual -= 2 * data_count;
}
} else {
if (current_SC->SCp.phase & disconnect) {
- outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );
- outb( 0x00, SCSI_Cntl_port );
+ outb(0xd0 | FIFO_COUNT, port_base + Interrupt_Cntl);
+ outb(0x00, port_base + SCSI_Cntl);
} else {
- outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
+ outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl);
}
}
#if DEBUG_RACE
return IRQ_HANDLED;
}
-static int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *))
{
if (in_command) {
panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
current_SC->SCp.phase = in_arbitration;
/* Start arbitration */
- outb( 0x00, Interrupt_Cntl_port );
- outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */
- outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */
+ outb(0x00, port_base + Interrupt_Cntl);
+ outb(0x00, port_base + SCSI_Cntl); /* Disable data drivers */
+ outb(adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */
++in_command;
- outb( 0x20, Interrupt_Cntl_port );
- outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */
+ outb(0x20, port_base + Interrupt_Cntl);
+ outb(0x14 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */
return 0;
}
#if DEBUG_ABORT
-static void print_info(Scsi_Cmnd *SCpnt)
+static void print_info(struct scsi_cmnd *SCpnt)
{
unsigned int imr;
unsigned int irr;
printk( " (masked)" );
printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
- printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) );
- printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) );
- if (inb( TMC_Status_port & 1))
+ printk( "SCSI Status = 0x%02x\n", inb(port_base + SCSI_Status));
+ printk( "TMC Status = 0x%02x", inb(port_base + TMC_Status));
+ if (inb((port_base + TMC_Status) & 1))
printk( " (interrupt)" );
printk( "\n" );
- printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );
- if (inb( Interrupt_Status_port ) & 0x08)
+ printk("Interrupt Status = 0x%02x", inb(port_base + Interrupt_Status));
+ if (inb(port_base + Interrupt_Status) & 0x08)
printk( " (enabled)" );
printk( "\n" );
if (chip == tmc18c50 || chip == tmc18c30) {
- printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) );
+ printk("FIFO Status = 0x%02x\n", inb(port_base + FIFO_Status));
printk( "Int. Condition = 0x%02x\n",
inb( port_base + Interrupt_Cond ) );
}
}
#endif
-static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
+static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt)
{
#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
printk( "scsi: <fdomain> abort " );
return SUCCESS;
}
-int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
+int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt)
{
- outb( 1, SCSI_Cntl_port );
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ outb(1, port_base + SCSI_Cntl);
do_pause( 2 );
- outb( 0, SCSI_Cntl_port );
+ outb(0, port_base + SCSI_Cntl);
do_pause( 115 );
- outb( 0, SCSI_Mode_Cntl_port );
- outb( PARITY_MASK, TMC_Cntl_port );
- return SUCCESS;
-}
+ outb(0, port_base + SCSI_Mode_Cntl);
+ outb(PARITY_MASK, port_base + TMC_Cntl);
-static int fdomain_16x0_host_reset(Scsi_Cmnd *SCpnt)
-{
- return FAILED;
-}
-
-static int fdomain_16x0_device_reset(Scsi_Cmnd *SCpnt)
-{
- return FAILED;
+ local_irq_restore(flags);
+ return SUCCESS;
}
-#include <scsi/scsi_ioctl.h>
-
static int fdomain_16x0_biosparam(struct scsi_device *sdev,
struct block_device *bdev,
sector_t capacity, int *info_array)
{
int drive;
- unsigned char buf[512 + sizeof (Scsi_Ioctl_Command)];
- Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
int size = capacity;
- unsigned char *data = sic->data;
- unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 };
- int retcode;
unsigned long offset;
struct drive_info {
unsigned short cylinders;
case 2: /* ISA_200S */
/* The value of 25 has never been verified.
It should probably be 15. */
- offset = bios_base + 0x1f33 + drive * 25;
+ offset = 0x1f33 + drive * 25;
break;
case 3: /* ISA_250MG */
- offset = bios_base + 0x1f36 + drive * 15;
+ offset = 0x1f36 + drive * 15;
break;
case 4: /* ISA_200S (another one) */
- offset = bios_base + 0x1f34 + drive * 15;
+ offset = 0x1f34 + drive * 15;
break;
default:
- offset = bios_base + 0x1f31 + drive * 25;
+ offset = 0x1f31 + drive * 25;
break;
}
- isa_memcpy_fromio( &i, offset, sizeof( struct drive_info ) );
+ memcpy_fromio( &i, bios_mem + offset, sizeof( struct drive_info ) );
info_array[0] = i.heads;
info_array[1] = i.sectors;
info_array[2] = i.cylinders;
} else if (bios_major == 3
&& bios_minor >= 0
&& bios_minor < 4) { /* 3.0 and 3.2 BIOS */
- memcpy_fromio( &i, bios_base + 0x1f71 + drive * 10,
+ memcpy_fromio( &i, bios_mem + 0x1f71 + drive * 10,
sizeof( struct drive_info ) );
info_array[0] = i.heads + 1;
info_array[1] = i.sectors;
info_array[2] = i.cylinders;
} else { /* 3.4 BIOS (and up?) */
/* This algorithm was provided by Future Domain (much thanks!). */
+ unsigned char *p = scsi_bios_ptable(bdev);
- sic->inlen = 0; /* zero bytes out */
- sic->outlen = 512; /* one sector in */
- memcpy( data, do_read, sizeof( do_read ) );
- retcode = kernel_scsi_ioctl( sdev,
- SCSI_IOCTL_SEND_COMMAND,
- sic );
- if (!retcode /* SCSI command ok */
- && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
- && data[0x1c2]) { /* Partition type */
+ if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */
+ && p[4]) { /* Partition type */
/* The partition table layout is as follows:
Future Domain algorithm, but it seemed to be a reasonable thing
to do, especially in the Linux and BSD worlds. */
- info_array[0] = data[0x1c3] + 1; /* heads */
- info_array[1] = data[0x1c4] & 0x3f; /* sectors */
+ info_array[0] = p[5] + 1; /* heads */
+ info_array[1] = p[6] & 0x3f; /* sectors */
} else {
/* Note that this new method guarantees that there will always be
}
/* For both methods, compute the cylinders */
info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
+ kfree(p);
}
return 0;
return 0;
}
-Scsi_Host_Template fdomain_driver_template = {
+struct scsi_host_template fdomain_driver_template = {
.module = THIS_MODULE,
.name = "fdomain",
.proc_name = "fdomain",
.queuecommand = fdomain_16x0_queue,
.eh_abort_handler = fdomain_16x0_abort,
.eh_bus_reset_handler = fdomain_16x0_bus_reset,
- .eh_device_reset_handler = fdomain_16x0_device_reset,
- .eh_host_reset_handler = fdomain_16x0_host_reset,
.bios_param = fdomain_16x0_biosparam,
.release = fdomain_16x0_release,
.can_queue = 1,