22d5aa3a45
Commit1697c6a64c
("scsi: fdomain: Add register definitions") somehow missed the uses of CFG1_IRQ_MASK in the Futire Domain ISA driver, leaving the magic numbers intact. Fix this issue (with no change in the generated object file), removing an excess empty line, while at it... Fixes:1697c6a64c
("scsi: fdomain: Add register definitions") Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
222 lines
6.6 KiB
C
222 lines
6.6 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/io.h>
|
|
#include <linux/isa.h>
|
|
#include <scsi/scsi_host.h>
|
|
#include "fdomain.h"
|
|
|
|
#define MAXBOARDS_PARAM 4
|
|
static int io[MAXBOARDS_PARAM] = { 0, 0, 0, 0 };
|
|
module_param_hw_array(io, int, ioport, NULL, 0);
|
|
MODULE_PARM_DESC(io, "base I/O address of controller (0x140, 0x150, 0x160, 0x170)");
|
|
|
|
static int irq[MAXBOARDS_PARAM] = { 0, 0, 0, 0 };
|
|
module_param_hw_array(irq, int, irq, NULL, 0);
|
|
MODULE_PARM_DESC(irq, "IRQ of controller (0=auto [default])");
|
|
|
|
static int scsi_id[MAXBOARDS_PARAM] = { 0, 0, 0, 0 };
|
|
module_param_hw_array(scsi_id, int, other, NULL, 0);
|
|
MODULE_PARM_DESC(scsi_id, "SCSI ID of controller (default = 7)");
|
|
|
|
static unsigned long addresses[] = {
|
|
0xc8000,
|
|
0xca000,
|
|
0xce000,
|
|
0xde000,
|
|
};
|
|
#define ADDRESS_COUNT ARRAY_SIZE(addresses)
|
|
|
|
static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
|
|
#define PORT_COUNT ARRAY_SIZE(ports)
|
|
|
|
static unsigned short irqs[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
|
|
|
|
/* This driver works *ONLY* for Future Domain cards using the TMC-1800,
|
|
* TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670,
|
|
* and 1680. These are all 16-bit cards.
|
|
* BIOS versions prior to 3.2 assigned SCSI ID 6 to SCSI adapter.
|
|
*
|
|
* The following BIOS signature signatures are for boards which do *NOT*
|
|
* work with this driver (these TMC-8xx and TMC-9xx boards may work with the
|
|
* Seagate driver):
|
|
*
|
|
* FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88
|
|
* FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89
|
|
* FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89
|
|
* FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90
|
|
* FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90
|
|
* FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90
|
|
* FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92
|
|
*
|
|
* (The cards which do *NOT* work are all 8-bit cards -- although some of
|
|
* them have a 16-bit form-factor, the upper 8-bits are used only for IRQs
|
|
* and are *NOT* used for data. You can tell the difference by following
|
|
* the tracings on the circuit board -- if only the IRQ lines are involved,
|
|
* you have a "8-bit" card, and should *NOT* use this driver.)
|
|
*/
|
|
|
|
static struct signature {
|
|
const char *signature;
|
|
int offset;
|
|
int length;
|
|
int this_id;
|
|
int base_offset;
|
|
} signatures[] = {
|
|
/* 1 2 3 4 5 6 */
|
|
/* 123456789012345678901234567890123456789012345678901234567890 */
|
|
{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 6, 0x1fcc },
|
|
{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 6, 0x1fcc },
|
|
{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 6, 0x1fa2 },
|
|
{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 6, 0x1fa2 },
|
|
{ "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 6, 0x1fa3 },
|
|
{ "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 6, 0 },
|
|
{ "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 7, 0 },
|
|
{ "IBM F1 P2 BIOS v1.0011/09/92", 5, 28, 7, 0x1ff3 },
|
|
{ "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 7, 0 },
|
|
{ "Future Domain Corp. V1.0008/18/93", 5, 33, 7, 0 },
|
|
{ "Future Domain Corp. V2.0108/18/93", 5, 33, 7, 0 },
|
|
{ "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 7, 0 },
|
|
{ "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 7, 0 },
|
|
{ "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 7, 0 },
|
|
{ "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 7, 0 },
|
|
};
|
|
#define SIGNATURE_COUNT ARRAY_SIZE(signatures)
|
|
|
|
static int fdomain_isa_match(struct device *dev, unsigned int ndev)
|
|
{
|
|
struct Scsi_Host *sh;
|
|
int i, base = 0, irq = 0;
|
|
unsigned long bios_base = 0;
|
|
struct signature *sig = NULL;
|
|
void __iomem *p;
|
|
static struct signature *saved_sig;
|
|
int this_id = 7;
|
|
|
|
if (ndev < ADDRESS_COUNT) { /* scan supported ISA BIOS addresses */
|
|
p = ioremap(addresses[ndev], FDOMAIN_BIOS_SIZE);
|
|
if (!p)
|
|
return 0;
|
|
for (i = 0; i < SIGNATURE_COUNT; i++)
|
|
if (check_signature(p + signatures[i].offset,
|
|
signatures[i].signature,
|
|
signatures[i].length))
|
|
break;
|
|
if (i == SIGNATURE_COUNT) /* no signature found */
|
|
goto fail_unmap;
|
|
sig = &signatures[i];
|
|
bios_base = addresses[ndev];
|
|
/* read I/O base from BIOS area */
|
|
if (sig->base_offset)
|
|
base = readb(p + sig->base_offset) +
|
|
(readb(p + sig->base_offset + 1) << 8);
|
|
iounmap(p);
|
|
if (base)
|
|
dev_info(dev, "BIOS at 0x%lx specifies I/O base 0x%x\n",
|
|
bios_base, base);
|
|
else
|
|
dev_info(dev, "BIOS at 0x%lx\n", bios_base);
|
|
if (!base) { /* no I/O base in BIOS area */
|
|
/* save BIOS signature for later use in port probing */
|
|
saved_sig = sig;
|
|
return 0;
|
|
}
|
|
} else /* scan supported I/O ports */
|
|
base = ports[ndev - ADDRESS_COUNT];
|
|
|
|
/* use saved BIOS signature if present */
|
|
if (!sig && saved_sig)
|
|
sig = saved_sig;
|
|
|
|
if (!request_region(base, FDOMAIN_REGION_SIZE, "fdomain_isa"))
|
|
return 0;
|
|
|
|
irq = irqs[(inb(base + REG_CFG1) & CFG1_IRQ_MASK) >> 1];
|
|
|
|
if (sig)
|
|
this_id = sig->this_id;
|
|
|
|
sh = fdomain_create(base, irq, this_id, dev);
|
|
if (!sh) {
|
|
release_region(base, FDOMAIN_REGION_SIZE);
|
|
return 0;
|
|
}
|
|
|
|
dev_set_drvdata(dev, sh);
|
|
return 1;
|
|
fail_unmap:
|
|
iounmap(p);
|
|
return 0;
|
|
}
|
|
|
|
static int fdomain_isa_param_match(struct device *dev, unsigned int ndev)
|
|
{
|
|
struct Scsi_Host *sh;
|
|
int irq_ = irq[ndev];
|
|
|
|
if (!io[ndev])
|
|
return 0;
|
|
|
|
if (!request_region(io[ndev], FDOMAIN_REGION_SIZE, "fdomain_isa")) {
|
|
dev_err(dev, "base 0x%x already in use", io[ndev]);
|
|
return 0;
|
|
}
|
|
|
|
if (irq_ <= 0)
|
|
irq_ = irqs[(inb(io[ndev] + REG_CFG1) & CFG1_IRQ_MASK) >> 1];
|
|
|
|
sh = fdomain_create(io[ndev], irq_, scsi_id[ndev], dev);
|
|
if (!sh) {
|
|
dev_err(dev, "controller not found at base 0x%x", io[ndev]);
|
|
release_region(io[ndev], FDOMAIN_REGION_SIZE);
|
|
return 0;
|
|
}
|
|
|
|
dev_set_drvdata(dev, sh);
|
|
return 1;
|
|
}
|
|
|
|
static int fdomain_isa_remove(struct device *dev, unsigned int ndev)
|
|
{
|
|
struct Scsi_Host *sh = dev_get_drvdata(dev);
|
|
int base = sh->io_port;
|
|
|
|
fdomain_destroy(sh);
|
|
release_region(base, FDOMAIN_REGION_SIZE);
|
|
dev_set_drvdata(dev, NULL);
|
|
return 0;
|
|
}
|
|
|
|
static struct isa_driver fdomain_isa_driver = {
|
|
.match = fdomain_isa_match,
|
|
.remove = fdomain_isa_remove,
|
|
.driver = {
|
|
.name = "fdomain_isa",
|
|
.pm = FDOMAIN_PM_OPS,
|
|
},
|
|
};
|
|
|
|
static int __init fdomain_isa_init(void)
|
|
{
|
|
int isa_probe_count = ADDRESS_COUNT + PORT_COUNT;
|
|
|
|
if (io[0]) { /* use module parameters if present */
|
|
fdomain_isa_driver.match = fdomain_isa_param_match;
|
|
isa_probe_count = MAXBOARDS_PARAM;
|
|
}
|
|
|
|
return isa_register_driver(&fdomain_isa_driver, isa_probe_count);
|
|
}
|
|
|
|
static void __exit fdomain_isa_exit(void)
|
|
{
|
|
isa_unregister_driver(&fdomain_isa_driver);
|
|
}
|
|
|
|
module_init(fdomain_isa_init);
|
|
module_exit(fdomain_isa_exit);
|
|
|
|
MODULE_AUTHOR("Ondrej Zary, Rickard E. Faith");
|
|
MODULE_DESCRIPTION("Future Domain TMC-16x0 ISA SCSI driver");
|
|
MODULE_LICENSE("GPL");
|