1/* 2 * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux. 3 * Amiga MacroSystemUS WarpEngine SCSI controller. 4 * Amiga Technologies/DKB A4091 SCSI controller. 5 * 6 * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk> 7 * plus modifications of the 53c7xx.c driver to support the Amiga. 8 * 9 * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org> 10 */ 11 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/interrupt.h> 15#include <linux/zorro.h> 16#include <linux/slab.h> 17 18#include <asm/amigahw.h> 19#include <asm/amigaints.h> 20 21#include <scsi/scsi_host.h> 22#include <scsi/scsi_transport_spi.h> 23 24#include "53c700.h" 25 26MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>"); 27MODULE_DESCRIPTION("Amiga Zorro NCR53C710 driver"); 28MODULE_LICENSE("GPL"); 29 30 31static struct scsi_host_template zorro7xx_scsi_driver_template = { 32 .proc_name = "zorro7xx", 33 .this_id = 7, 34 .module = THIS_MODULE, 35}; 36 37static struct zorro_driver_data { 38 const char *name; 39 unsigned long offset; 40 int absolute; /* offset is absolute address */ 41} zorro7xx_driver_data[] = { 42 { .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 }, 43 { .name = "WarpEngine 40xx", .offset = 0x40000 }, 44 { .name = "A4091", .offset = 0x800000 }, 45 { .name = "GForce 040/060", .offset = 0x40000 }, 46 { 0 } 47}; 48 49static struct zorro_device_id zorro7xx_zorro_tbl[] = { 50 { 51 .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, 52 .driver_data = (unsigned long)&zorro7xx_driver_data[0], 53 }, 54 { 55 .id = ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, 56 .driver_data = (unsigned long)&zorro7xx_driver_data[1], 57 }, 58 { 59 .id = ZORRO_PROD_CBM_A4091_1, 60 .driver_data = (unsigned long)&zorro7xx_driver_data[2], 61 }, 62 { 63 .id = ZORRO_PROD_CBM_A4091_2, 64 .driver_data = (unsigned long)&zorro7xx_driver_data[2], 65 }, 66 { 67 .id = ZORRO_PROD_GVP_GFORCE_040_060, 68 .driver_data = (unsigned long)&zorro7xx_driver_data[3], 69 }, 70 { 0 } 71}; 72MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl); 73 74static int zorro7xx_init_one(struct zorro_dev *z, 75 const struct zorro_device_id *ent) 76{ 77 struct Scsi_Host *host; 78 struct NCR_700_Host_Parameters *hostdata; 79 struct zorro_driver_data *zdd; 80 unsigned long board, ioaddr; 81 82 board = zorro_resource_start(z); 83 zdd = (struct zorro_driver_data *)ent->driver_data; 84 85 if (zdd->absolute) { 86 ioaddr = zdd->offset; 87 } else { 88 ioaddr = board + zdd->offset; 89 } 90 91 if (!zorro_request_device(z, zdd->name)) { 92 printk(KERN_ERR "zorro7xx: cannot reserve region 0x%lx, abort\n", 93 board); 94 return -EBUSY; 95 } 96 97 hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); 98 if (!hostdata) { 99 printk(KERN_ERR "zorro7xx: Failed to allocate host data\n"); 100 goto out_release; 101 } 102 103 /* Fill in the required pieces of hostdata */ 104 if (ioaddr > 0x01000000) 105 hostdata->base = ioremap(ioaddr, zorro_resource_len(z)); 106 else 107 hostdata->base = ZTWO_VADDR(ioaddr); 108 109 hostdata->clock = 50; 110 hostdata->chip710 = 1; 111 112 /* Settings for at least WarpEngine 40xx */ 113 hostdata->ctest7_extra = CTEST7_TT1; 114 115 zorro7xx_scsi_driver_template.name = zdd->name; 116 117 /* and register the chip */ 118 host = NCR_700_detect(&zorro7xx_scsi_driver_template, hostdata, 119 &z->dev); 120 if (!host) { 121 printk(KERN_ERR "zorro7xx: No host detected; " 122 "board configuration problem?\n"); 123 goto out_free; 124 } 125 126 host->this_id = 7; 127 host->base = ioaddr; 128 host->irq = IRQ_AMIGA_PORTS; 129 130 if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "zorro7xx-scsi", 131 host)) { 132 printk(KERN_ERR "zorro7xx: request_irq failed\n"); 133 goto out_put_host; 134 } 135 136 zorro_set_drvdata(z, host); 137 scsi_scan_host(host); 138 139 return 0; 140 141 out_put_host: 142 scsi_host_put(host); 143 out_free: 144 if (ioaddr > 0x01000000) 145 iounmap(hostdata->base); 146 kfree(hostdata); 147 out_release: 148 zorro_release_device(z); 149 150 return -ENODEV; 151} 152 153static void zorro7xx_remove_one(struct zorro_dev *z) 154{ 155 struct Scsi_Host *host = zorro_get_drvdata(z); 156 struct NCR_700_Host_Parameters *hostdata = shost_priv(host); 157 158 scsi_remove_host(host); 159 160 NCR_700_release(host); 161 kfree(hostdata); 162 free_irq(host->irq, host); 163 zorro_release_device(z); 164} 165 166static struct zorro_driver zorro7xx_driver = { 167 .name = "zorro7xx-scsi", 168 .id_table = zorro7xx_zorro_tbl, 169 .probe = zorro7xx_init_one, 170 .remove = zorro7xx_remove_one, 171}; 172 173static int __init zorro7xx_scsi_init(void) 174{ 175 return zorro_register_driver(&zorro7xx_driver); 176} 177 178static void __exit zorro7xx_scsi_exit(void) 179{ 180 zorro_unregister_driver(&zorro7xx_driver); 181} 182 183module_init(zorro7xx_scsi_init); 184module_exit(zorro7xx_scsi_exit); 185