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