145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong/*
245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong *		Amiga MacroSystemUS WarpEngine SCSI controller.
445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong *		Amiga Technologies/DKB A4091 SCSI controller.
545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong *
645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong * plus modifications of the 53c7xx.c driver to support the Amiga.
845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong *
945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
1045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong */
1145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
1245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong#include <linux/module.h>
1345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong#include <linux/init.h>
1445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong#include <linux/interrupt.h>
1545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong#include <linux/zorro.h>
165a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
17e482179d547ff250cab487859b6fc91995bbdbb5Geert Uytterhoeven
18e482179d547ff250cab487859b6fc91995bbdbb5Geert Uytterhoeven#include <asm/amigahw.h>
1945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong#include <asm/amigaints.h>
20e482179d547ff250cab487859b6fc91995bbdbb5Geert Uytterhoeven
2145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong#include <scsi/scsi_host.h>
2245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong#include <scsi/scsi_transport_spi.h>
2345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
2445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong#include "53c700.h"
2545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
2645804fbb00eea27bdf4d62751681228a9e2844e9Kars de JongMODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
2745804fbb00eea27bdf4d62751681228a9e2844e9Kars de JongMODULE_DESCRIPTION("Amiga Zorro NCR53C710 driver");
2845804fbb00eea27bdf4d62751681228a9e2844e9Kars de JongMODULE_LICENSE("GPL");
2945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
3045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
3145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jongstatic struct scsi_host_template zorro7xx_scsi_driver_template = {
3245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	.proc_name	= "zorro7xx",
3345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	.this_id	= 7,
3445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	.module		= THIS_MODULE,
3545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong};
3645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
3745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jongstatic struct zorro_driver_data {
3845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	const char *name;
3945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	unsigned long offset;
4045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	int absolute;	/* offset is absolute address */
416f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartman} zorro7xx_driver_data[] = {
4245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{ .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 },
4345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{ .name = "WarpEngine 40xx", .offset = 0x40000 },
4445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{ .name = "A4091", .offset = 0x800000 },
4545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{ .name = "GForce 040/060", .offset = 0x40000 },
4645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{ 0 }
4745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong};
4845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
496f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic struct zorro_device_id zorro7xx_zorro_tbl[] = {
5045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{
5145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS,
5245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.driver_data = (unsigned long)&zorro7xx_driver_data[0],
5345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	},
5445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{
5545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx,
5645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.driver_data = (unsigned long)&zorro7xx_driver_data[1],
5745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	},
5845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{
5945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.id = ZORRO_PROD_CBM_A4091_1,
6045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.driver_data = (unsigned long)&zorro7xx_driver_data[2],
6145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	},
6245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{
6345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.id = ZORRO_PROD_CBM_A4091_2,
6445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.driver_data = (unsigned long)&zorro7xx_driver_data[2],
6545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	},
6645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{
6745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.id = ZORRO_PROD_GVP_GFORCE_040_060,
6845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		.driver_data = (unsigned long)&zorro7xx_driver_data[3],
6945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	},
7045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	{ 0 }
7145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong};
72bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert UytterhoevenMODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl);
7345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
746f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic int zorro7xx_init_one(struct zorro_dev *z,
756f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartman			     const struct zorro_device_id *ent)
7645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong{
77bbfbbbc1182f8b44c8cc4c99f4a3f3a512149022Mariusz Kozlowski	struct Scsi_Host *host;
7845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	struct NCR_700_Host_Parameters *hostdata;
7945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	struct zorro_driver_data *zdd;
8045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	unsigned long board, ioaddr;
8145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
8245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	board = zorro_resource_start(z);
8345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	zdd = (struct zorro_driver_data *)ent->driver_data;
8445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
8545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	if (zdd->absolute) {
8645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		ioaddr = zdd->offset;
8745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	} else {
8845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		ioaddr = board + zdd->offset;
8945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	}
9045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
9145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	if (!zorro_request_device(z, zdd->name)) {
9245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		printk(KERN_ERR "zorro7xx: cannot reserve region 0x%lx, abort\n",
9345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		       board);
9445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		return -EBUSY;
9545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	}
9645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
97bbfbbbc1182f8b44c8cc4c99f4a3f3a512149022Mariusz Kozlowski	hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
98bbfbbbc1182f8b44c8cc4c99f4a3f3a512149022Mariusz Kozlowski	if (!hostdata) {
9945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		printk(KERN_ERR "zorro7xx: Failed to allocate host data\n");
10045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		goto out_release;
10145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	}
10245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
10345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	/* Fill in the required pieces of hostdata */
10445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	if (ioaddr > 0x01000000)
10545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		hostdata->base = ioremap(ioaddr, zorro_resource_len(z));
10645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	else
1076112ea0862facaeaeab504ee01c0d04bcd22daafGeert Uytterhoeven		hostdata->base = ZTWO_VADDR(ioaddr);
10845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
10945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	hostdata->clock = 50;
11045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	hostdata->chip710 = 1;
11145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
11245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	/* Settings for at least WarpEngine 40xx */
11345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	hostdata->ctest7_extra = CTEST7_TT1;
11445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
11545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	zorro7xx_scsi_driver_template.name = zdd->name;
11645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
11745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	/* and register the chip */
11845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	host = NCR_700_detect(&zorro7xx_scsi_driver_template, hostdata,
11945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong			      &z->dev);
12045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	if (!host) {
12145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		printk(KERN_ERR "zorro7xx: No host detected; "
12245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong				"board configuration problem?\n");
12345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		goto out_free;
12445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	}
12545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
12645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	host->this_id = 7;
12745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	host->base = ioaddr;
12845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	host->irq = IRQ_AMIGA_PORTS;
12945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
13045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "zorro7xx-scsi",
13145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong			host)) {
13245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		printk(KERN_ERR "zorro7xx: request_irq failed\n");
13345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		goto out_put_host;
13445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	}
13545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
1363ac709c113daa19e375e8b0fef318fab1713f687Matthew Wilcox	zorro_set_drvdata(z, host);
13745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	scsi_scan_host(host);
13845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
13945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	return 0;
14045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
14145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong out_put_host:
14245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	scsi_host_put(host);
14345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong out_free:
14445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	if (ioaddr > 0x01000000)
14545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong		iounmap(hostdata->base);
14645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	kfree(hostdata);
14745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong out_release:
14845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	zorro_release_device(z);
14945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
15045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	return -ENODEV;
15145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong}
15245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
1536f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartmanstatic void zorro7xx_remove_one(struct zorro_dev *z)
15445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong{
1553ac709c113daa19e375e8b0fef318fab1713f687Matthew Wilcox	struct Scsi_Host *host = zorro_get_drvdata(z);
15645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
15745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
15845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	scsi_remove_host(host);
15945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
16045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	NCR_700_release(host);
16145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	kfree(hostdata);
16245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	free_irq(host->irq, host);
16345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	zorro_release_device(z);
16445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong}
16545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
16645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jongstatic struct zorro_driver zorro7xx_driver = {
16745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	.name	  = "zorro7xx-scsi",
16845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	.id_table = zorro7xx_zorro_tbl,
16945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	.probe	  = zorro7xx_init_one,
1706f039790510fd630ff348efe8c4802dbaa041fbaGreg Kroah-Hartman	.remove	  = zorro7xx_remove_one,
17145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong};
17245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
17345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jongstatic int __init zorro7xx_scsi_init(void)
17445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong{
17545804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	return zorro_register_driver(&zorro7xx_driver);
17645804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong}
17745804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
17845804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jongstatic void __exit zorro7xx_scsi_exit(void)
17945804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong{
18045804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong	zorro_unregister_driver(&zorro7xx_driver);
18145804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong}
18245804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jong
18345804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jongmodule_init(zorro7xx_scsi_init);
18445804fbb00eea27bdf4d62751681228a9e2844e9Kars de Jongmodule_exit(zorro7xx_scsi_exit);
185