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