1a16efc1cSKars de Jong /* 2a16efc1cSKars de Jong * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux. 3a16efc1cSKars de Jong * Amiga Technologies A4000T SCSI controller. 4a16efc1cSKars de Jong * 5a16efc1cSKars de Jong * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk> 6a16efc1cSKars de Jong * plus modifications of the 53c7xx.c driver to support the Amiga. 7a16efc1cSKars de Jong * 8a16efc1cSKars de Jong * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org> 9a16efc1cSKars de Jong */ 10a16efc1cSKars de Jong 11a16efc1cSKars de Jong #include <linux/module.h> 12a16efc1cSKars de Jong #include <linux/platform_device.h> 13a16efc1cSKars de Jong #include <linux/init.h> 14a16efc1cSKars de Jong #include <linux/interrupt.h> 15*96249cf9SGeert Uytterhoeven #include <asm/amigahw.h> 16a16efc1cSKars de Jong #include <asm/amigaints.h> 17a16efc1cSKars de Jong #include <scsi/scsi_host.h> 18a16efc1cSKars de Jong #include <scsi/scsi_transport_spi.h> 19a16efc1cSKars de Jong 20a16efc1cSKars de Jong #include "53c700.h" 21a16efc1cSKars de Jong 22a16efc1cSKars de Jong MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>"); 23a16efc1cSKars de Jong MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); 24a16efc1cSKars de Jong MODULE_LICENSE("GPL"); 25a16efc1cSKars de Jong 26a16efc1cSKars de Jong 27a16efc1cSKars de Jong static struct scsi_host_template a4000t_scsi_driver_template = { 28a16efc1cSKars de Jong .name = "A4000T builtin SCSI", 29a16efc1cSKars de Jong .proc_name = "A4000t", 30a16efc1cSKars de Jong .this_id = 7, 31a16efc1cSKars de Jong .module = THIS_MODULE, 32a16efc1cSKars de Jong }; 33a16efc1cSKars de Jong 34a16efc1cSKars de Jong static struct platform_device *a4000t_scsi_device; 35a16efc1cSKars de Jong 36a16efc1cSKars de Jong #define A4000T_SCSI_ADDR 0xdd0040 37a16efc1cSKars de Jong 38a16efc1cSKars de Jong static int __devinit a4000t_probe(struct device *dev) 39a16efc1cSKars de Jong { 40a16efc1cSKars de Jong struct Scsi_Host * host = NULL; 41a16efc1cSKars de Jong struct NCR_700_Host_Parameters *hostdata; 42a16efc1cSKars de Jong 43a16efc1cSKars de Jong if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) 44a16efc1cSKars de Jong goto out; 45a16efc1cSKars de Jong 46a16efc1cSKars de Jong if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000, 47a16efc1cSKars de Jong "A4000T builtin SCSI")) 48a16efc1cSKars de Jong goto out; 49a16efc1cSKars de Jong 50a16efc1cSKars de Jong hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); 51a16efc1cSKars de Jong if (hostdata == NULL) { 52a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n"); 53a16efc1cSKars de Jong goto out_release; 54a16efc1cSKars de Jong } 55a16efc1cSKars de Jong memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); 56a16efc1cSKars de Jong 57a16efc1cSKars de Jong /* Fill in the required pieces of hostdata */ 58a16efc1cSKars de Jong hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR); 59a16efc1cSKars de Jong hostdata->clock = 50; 60a16efc1cSKars de Jong hostdata->chip710 = 1; 61a16efc1cSKars de Jong hostdata->dmode_extra = DMODE_FC2; 62a16efc1cSKars de Jong hostdata->dcntl_extra = EA_710; 63a16efc1cSKars de Jong 64a16efc1cSKars de Jong /* and register the chip */ 65a16efc1cSKars de Jong host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev); 66a16efc1cSKars de Jong if (!host) { 67a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: No host detected; " 68a16efc1cSKars de Jong "board configuration problem?\n"); 69a16efc1cSKars de Jong goto out_free; 70a16efc1cSKars de Jong } 71a16efc1cSKars de Jong 72a16efc1cSKars de Jong host->this_id = 7; 73a16efc1cSKars de Jong host->base = A4000T_SCSI_ADDR; 74a16efc1cSKars de Jong host->irq = IRQ_AMIGA_PORTS; 75a16efc1cSKars de Jong 76a16efc1cSKars de Jong if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", 77a16efc1cSKars de Jong host)) { 78a16efc1cSKars de Jong printk(KERN_ERR "a4000t-scsi: request_irq failed\n"); 79a16efc1cSKars de Jong goto out_put_host; 80a16efc1cSKars de Jong } 81a16efc1cSKars de Jong 82a16efc1cSKars de Jong scsi_scan_host(host); 83a16efc1cSKars de Jong 84a16efc1cSKars de Jong return 0; 85a16efc1cSKars de Jong 86a16efc1cSKars de Jong out_put_host: 87a16efc1cSKars de Jong scsi_host_put(host); 88a16efc1cSKars de Jong out_free: 89a16efc1cSKars de Jong kfree(hostdata); 90a16efc1cSKars de Jong out_release: 91a16efc1cSKars de Jong release_mem_region(A4000T_SCSI_ADDR, 0x1000); 92a16efc1cSKars de Jong out: 93a16efc1cSKars de Jong return -ENODEV; 94a16efc1cSKars de Jong } 95a16efc1cSKars de Jong 96a16efc1cSKars de Jong static __devexit int a4000t_device_remove(struct device *dev) 97a16efc1cSKars de Jong { 98a16efc1cSKars de Jong struct Scsi_Host *host = dev_to_shost(dev); 99a16efc1cSKars de Jong struct NCR_700_Host_Parameters *hostdata = shost_priv(host); 100a16efc1cSKars de Jong 101a16efc1cSKars de Jong scsi_remove_host(host); 102a16efc1cSKars de Jong 103a16efc1cSKars de Jong NCR_700_release(host); 104a16efc1cSKars de Jong kfree(hostdata); 105a16efc1cSKars de Jong free_irq(host->irq, host); 106a16efc1cSKars de Jong release_mem_region(A4000T_SCSI_ADDR, 0x1000); 107a16efc1cSKars de Jong 108a16efc1cSKars de Jong return 0; 109a16efc1cSKars de Jong } 110a16efc1cSKars de Jong 111a16efc1cSKars de Jong static struct device_driver a4000t_scsi_driver = { 112a16efc1cSKars de Jong .name = "a4000t-scsi", 113a16efc1cSKars de Jong .bus = &platform_bus_type, 114a16efc1cSKars de Jong .probe = a4000t_probe, 115a16efc1cSKars de Jong .remove = __devexit_p(a4000t_device_remove), 116a16efc1cSKars de Jong }; 117a16efc1cSKars de Jong 118a16efc1cSKars de Jong static int __init a4000t_scsi_init(void) 119a16efc1cSKars de Jong { 120a16efc1cSKars de Jong int err; 121a16efc1cSKars de Jong 122a16efc1cSKars de Jong err = driver_register(&a4000t_scsi_driver); 123a16efc1cSKars de Jong if (err) 124a16efc1cSKars de Jong return err; 125a16efc1cSKars de Jong 126a16efc1cSKars de Jong a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", 127a16efc1cSKars de Jong -1, NULL, 0); 128a16efc1cSKars de Jong if (IS_ERR(a4000t_scsi_device)) { 129a16efc1cSKars de Jong driver_unregister(&a4000t_scsi_driver); 130a16efc1cSKars de Jong return PTR_ERR(a4000t_scsi_device); 131a16efc1cSKars de Jong } 132a16efc1cSKars de Jong 133a16efc1cSKars de Jong return err; 134a16efc1cSKars de Jong } 135a16efc1cSKars de Jong 136a16efc1cSKars de Jong static void __exit a4000t_scsi_exit(void) 137a16efc1cSKars de Jong { 138a16efc1cSKars de Jong platform_device_unregister(a4000t_scsi_device); 139a16efc1cSKars de Jong driver_unregister(&a4000t_scsi_driver); 140a16efc1cSKars de Jong } 141a16efc1cSKars de Jong 142a16efc1cSKars de Jong module_init(a4000t_scsi_init); 143a16efc1cSKars de Jong module_exit(a4000t_scsi_exit); 144