/*
* Driver for Adaptec AHA-1542 SCSI host adapters
*
* Copyright (C) 1992 Tommy Thorn
* Copyright (C) 1993, 1994, 1995 Eric Youngdale
* Copyright (C) 2015 Ondrej Zary
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/isa.h>
#include <linux/pnp.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <asm/dma.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include "aha1542.h"
#define MAXBOARDS 4
static bool isapnp = 1;
module_param(isapnp, bool, 0);
MODULE_PARM_DESC(isapnp, "enable PnP support (default=1)");
static int io[MAXBOARDS] = { 0x330, 0x334, 0, 0 };
module_param_array(io, int, NULL, 0);
MODULE_PARM_DESC(io, "base IO address of controller (0x130,0x134,0x230,0x234,0x330,0x334, default=0x330,0x334)");
/* time AHA spends on the AT-bus during data transfer */
static int bus_on[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 11us */
module_param_array(bus_on, int, NULL, 0);
MODULE_PARM_DESC(bus_on, "bus on time [us] (2-15, default=-1 [HW default: 11])");
/* time AHA spends off the bus (not to monopolize it) during data transfer */
static int bus_off[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 4us */
module_param_array(bus_off, int, NULL, 0);
MODULE_PARM_DESC(bus_off, "bus off time [us] (1-64, default=-1 [HW default: 4])");
/* default is jumper selected (J1 on 1542A), factory default = 5 MB/s */
static int dma_speed[MAXBOARDS] = { -1, -1, -1, -1 };
module_param_array(dma_speed, int, NULL, 0);
MODULE_PARM_DESC(dma_speed, "DMA speed [MB/s] (5,6,7,8,10, default=-1 [by jumper])");
#define BIOS_TRANSLATION_6432 1 /* Default case these days */
#define BIOS_TRANSLATION_25563 2 /* Big disk case */
struct aha1542_hostdata {
/* This will effectively start both of them at the first mailbox */
int bios_translation; /* Mapping bios uses - for compatibility */
int aha1542_last_mbi_used;
int aha1542_last_mbo_used;
struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES];
struct mailbox mb[2 * AHA1542_MAILBOXES];
struct ccb ccb[AHA1542_MAILBOXES];
};
static inline void aha1542_intr_reset(u16 base)
{
outb(IRST, CONTROL(base));
}
static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout)
{
bool delayed = true;
if (timeout == 0) {
timeout = 3000000;
delayed = false;
}
while (1) {
u8 bits = inb(port) & mask;
if ((bits & allof) == allof && ((bits & noneof) == 0))
break;
if (delayed)
mdelay(1);
if (--timeout == 0)
return false;
}
return true;
}
static int aha1542_outb(unsigned int base, u8 val)
{
if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
return 1;
outb(val, DATA(base));
return 0;
}
static int aha1542_out(unsigned int base, u8 *buf, int len)
{
while (len--) {
if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
return 1;
outb(*buf++, DATA(base));
}
if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
return 1;
return 0;
}
/* Only used at boot time, so we do not need to worry about latency as much
here */
static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
{
while (len--) {
if (!wait_mask(STATUS(base), DF, DF, 0, timeout))
return 1;
*buf++ = inb(DATA(base));
}
return 0;
}
static int makecode(unsigned hosterr, unsigned scsierr)
{
switch (hosterr) {
case 0x0:
case 0xa: /* Linked command complete without error and linked normally */
case 0xb: /* Linked command complete without error, interrupt generated */
hosterr = 0;
break;
case 0x11: /* Selection time out-The initiator selection or target
reselection was not complete within the SCSI Time out period */
hosterr = DID_TIME_OUT;
break;
case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
than was allocated by the Data Length field or the sum of the
Scatter / Gather Data Length fields. */
case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
invalid. This usually indicates a software failure. */
case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
This usually indicates a software failure. */
case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
of linked CCB's does not specify the same logical unit number as
the first. */
case 0x18: /* Invalid Target Direction received from Host-The direction of a
Target Mode CCB was invalid. */
case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
received to service data transfer between the same target LUN
and initiator SCSI ID in the same direction. */
case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
length segment or invalid segment list boundaries was received.
A CCB parameter was invalid. */
#ifdef DEBUG
printk