Commit | Line | Data |
---|---|---|
09c434b8 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
1da177e4 LT |
2 | /* |
3 | * Generic Macintosh NCR5380 driver | |
4 | * | |
5 | * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov> | |
6 | * | |
78ff751f FT |
7 | * Copyright 2019 Finn Thain |
8 | * | |
1da177e4 LT |
9 | * derived in part from: |
10 | */ | |
11 | /* | |
12 | * Generic Generic NCR5380 driver | |
13 | * | |
14 | * Copyright 1995, Russell King | |
1da177e4 LT |
15 | */ |
16 | ||
78ff751f | 17 | #include <linux/delay.h> |
1da177e4 | 18 | #include <linux/types.h> |
1da177e4 | 19 | #include <linux/module.h> |
1da177e4 LT |
20 | #include <linux/ioport.h> |
21 | #include <linux/init.h> | |
22 | #include <linux/blkdev.h> | |
23 | #include <linux/interrupt.h> | |
cbad48de | 24 | #include <linux/platform_device.h> |
1da177e4 | 25 | |
cbad48de | 26 | #include <asm/hwtest.h> |
1da177e4 | 27 | #include <asm/io.h> |
8fb9a64e | 28 | #include <asm/macintosh.h> |
1da177e4 | 29 | #include <asm/macints.h> |
cbad48de | 30 | #include <asm/setup.h> |
1da177e4 | 31 | |
1da177e4 | 32 | #include <scsi/scsi_host.h> |
92de3831 FT |
33 | |
34 | /* Definitions for the core NCR5380 driver. */ | |
e744fdea | 35 | |
820682b1 | 36 | #define NCR5380_implementation_fields int pdma_residual |
92de3831 | 37 | |
61e1ce58 FT |
38 | #define NCR5380_read(reg) in_8(hostdata->io + ((reg) << 4)) |
39 | #define NCR5380_write(reg, value) out_8(hostdata->io + ((reg) << 4), value) | |
92de3831 | 40 | |
4a98f896 | 41 | #define NCR5380_dma_xfer_len macscsi_dma_xfer_len |
6c4b88ca FT |
42 | #define NCR5380_dma_recv_setup macscsi_pread |
43 | #define NCR5380_dma_send_setup macscsi_pwrite | |
4a98f896 | 44 | #define NCR5380_dma_residual macscsi_dma_residual |
92de3831 FT |
45 | |
46 | #define NCR5380_intr macscsi_intr | |
47 | #define NCR5380_queue_command macscsi_queue_command | |
48 | #define NCR5380_abort macscsi_abort | |
12e5fc66 | 49 | #define NCR5380_host_reset macscsi_host_reset |
92de3831 | 50 | #define NCR5380_info macscsi_info |
92de3831 | 51 | |
1da177e4 LT |
52 | #include "NCR5380.h" |
53 | ||
1da177e4 | 54 | static int setup_can_queue = -1; |
6e9ae6d5 | 55 | module_param(setup_can_queue, int, 0); |
1da177e4 | 56 | static int setup_cmd_per_lun = -1; |
6e9ae6d5 | 57 | module_param(setup_cmd_per_lun, int, 0); |
1da177e4 | 58 | static int setup_sg_tablesize = -1; |
6e9ae6d5 | 59 | module_param(setup_sg_tablesize, int, 0); |
7398cee4 | 60 | static int setup_use_pdma = 512; |
6e9ae6d5 | 61 | module_param(setup_use_pdma, int, 0); |
1da177e4 | 62 | static int setup_hostid = -1; |
6e9ae6d5 | 63 | module_param(setup_hostid, int, 0); |
9c3f0e2b FT |
64 | static int setup_toshiba_delay = -1; |
65 | module_param(setup_toshiba_delay, int, 0); | |
1da177e4 | 66 | |
6e9ae6d5 FT |
67 | #ifndef MODULE |
68 | static int __init mac_scsi_setup(char *str) | |
69 | { | |
9c3f0e2b | 70 | int ints[8]; |
6e9ae6d5 FT |
71 | |
72 | (void)get_options(str, ARRAY_SIZE(ints), ints); | |
73 | ||
9c3f0e2b FT |
74 | if (ints[0] < 1) { |
75 | pr_err("Usage: mac5380=<can_queue>[,<cmd_per_lun>[,<sg_tablesize>[,<hostid>[,<use_tags>[,<use_pdma>[,<toshiba_delay>]]]]]]\n"); | |
6e9ae6d5 | 76 | return 0; |
1da177e4 | 77 | } |
6e9ae6d5 FT |
78 | if (ints[0] >= 1) |
79 | setup_can_queue = ints[1]; | |
80 | if (ints[0] >= 2) | |
81 | setup_cmd_per_lun = ints[2]; | |
82 | if (ints[0] >= 3) | |
83 | setup_sg_tablesize = ints[3]; | |
84 | if (ints[0] >= 4) | |
85 | setup_hostid = ints[4]; | |
c4ec6f92 | 86 | /* ints[5] (use_tagged_queuing) is ignored */ |
6e9ae6d5 | 87 | if (ints[0] >= 6) |
1da177e4 | 88 | setup_use_pdma = ints[6]; |
9c3f0e2b FT |
89 | if (ints[0] >= 7) |
90 | setup_toshiba_delay = ints[7]; | |
1da177e4 LT |
91 | return 1; |
92 | } | |
93 | ||
94 | __setup("mac5380=", mac_scsi_setup); | |
6e9ae6d5 | 95 | #endif /* !MODULE */ |
1da177e4 | 96 | |
78ff751f FT |
97 | /* |
98 | * According to "Inside Macintosh: Devices", Mac OS requires disk drivers to | |
99 | * specify the number of bytes between the delays expected from a SCSI target. | |
100 | * This allows the operating system to "prevent bus errors when a target fails | |
101 | * to deliver the next byte within the processor bus error timeout period." | |
102 | * Linux SCSI drivers lack knowledge of the timing behaviour of SCSI targets | |
103 | * so bus errors are unavoidable. | |
104 | * | |
5551bc30 FT |
105 | * If a MOVE.B instruction faults during a receive operation, we assume the |
106 | * target sent nothing and try again. That assumption probably depends on | |
107 | * target firmware but it seems to hold up okay. If a fault happens during a | |
108 | * send operation, the target may or may not have seen /ACK and got the byte. | |
109 | * It's uncertain so the whole SCSI command gets retried. | |
110 | * | |
111 | * The NOP is needed for synchronization because the fault address in the | |
112 | * exception stack frame may or may not be the instruction that actually | |
113 | * caused the bus error. Post-increment addressing can't be used. | |
78ff751f FT |
114 | */ |
115 | ||
116 | #define MOVE_BYTE(operands) \ | |
117 | asm volatile ( \ | |
118 | "1: moveb " operands " \n" \ | |
119 | "11: nop \n" \ | |
120 | " addq #1,%0 \n" \ | |
121 | " subq #1,%1 \n" \ | |
122 | "40: \n" \ | |
123 | " \n" \ | |
124 | ".section .fixup,\"ax\" \n" \ | |
125 | ".even \n" \ | |
126 | "90: movel #1, %2 \n" \ | |
127 | " jra 40b \n" \ | |
128 | ".previous \n" \ | |
129 | " \n" \ | |
130 | ".section __ex_table,\"a\" \n" \ | |
131 | ".align 4 \n" \ | |
132 | ".long 1b,90b \n" \ | |
133 | ".long 11b,90b \n" \ | |
134 | ".previous \n" \ | |
135 | : "+a" (addr), "+r" (n), "+r" (result) : "a" (io)) | |
136 | ||
137 | /* | |
138 | * If a MOVE.W (or MOVE.L) instruction faults, it cannot be retried because | |
139 | * the residual byte count would be uncertain. In that situation the MOVE_WORD | |
140 | * macro clears n in the fixup section to abort the transfer. | |
141 | */ | |
142 | ||
143 | #define MOVE_WORD(operands) \ | |
144 | asm volatile ( \ | |
145 | "1: movew " operands " \n" \ | |
146 | "11: nop \n" \ | |
147 | " subq #2,%1 \n" \ | |
148 | "40: \n" \ | |
149 | " \n" \ | |
150 | ".section .fixup,\"ax\" \n" \ | |
151 | ".even \n" \ | |
152 | "90: movel #0, %1 \n" \ | |
153 | " movel #2, %2 \n" \ | |
154 | " jra 40b \n" \ | |
155 | ".previous \n" \ | |
156 | " \n" \ | |
157 | ".section __ex_table,\"a\" \n" \ | |
158 | ".align 4 \n" \ | |
159 | ".long 1b,90b \n" \ | |
160 | ".long 11b,90b \n" \ | |
161 | ".previous \n" \ | |
162 | : "+a" (addr), "+r" (n), "+r" (result) : "a" (io)) | |
163 | ||
164 | #define MOVE_16_WORDS(operands) \ | |
165 | asm volatile ( \ | |
166 | "1: movew " operands " \n" \ | |
167 | "2: movew " operands " \n" \ | |
168 | "3: movew " operands " \n" \ | |
169 | "4: movew " operands " \n" \ | |
170 | "5: movew " operands " \n" \ | |
171 | "6: movew " operands " \n" \ | |
172 | "7: movew " operands " \n" \ | |
173 | "8: movew " operands " \n" \ | |
174 | "9: movew " operands " \n" \ | |
175 | "10: movew " operands " \n" \ | |
176 | "11: movew " operands " \n" \ | |
177 | "12: movew " operands " \n" \ | |
178 | "13: movew " operands " \n" \ | |
179 | "14: movew " operands " \n" \ | |
180 | "15: movew " operands " \n" \ | |
181 | "16: movew " operands " \n" \ | |
182 | "17: nop \n" \ | |
183 | " subl #32,%1 \n" \ | |
184 | "40: \n" \ | |
185 | " \n" \ | |
186 | ".section .fixup,\"ax\" \n" \ | |
187 | ".even \n" \ | |
188 | "90: movel #0, %1 \n" \ | |
189 | " movel #2, %2 \n" \ | |
190 | " jra 40b \n" \ | |
191 | ".previous \n" \ | |
192 | " \n" \ | |
193 | ".section __ex_table,\"a\" \n" \ | |
194 | ".align 4 \n" \ | |
195 | ".long 1b,90b \n" \ | |
196 | ".long 2b,90b \n" \ | |
197 | ".long 3b,90b \n" \ | |
198 | ".long 4b,90b \n" \ | |
199 | ".long 5b,90b \n" \ | |
200 | ".long 6b,90b \n" \ | |
201 | ".long 7b,90b \n" \ | |
202 | ".long 8b,90b \n" \ | |
203 | ".long 9b,90b \n" \ | |
204 | ".long 10b,90b \n" \ | |
205 | ".long 11b,90b \n" \ | |
206 | ".long 12b,90b \n" \ | |
207 | ".long 13b,90b \n" \ | |
208 | ".long 14b,90b \n" \ | |
209 | ".long 15b,90b \n" \ | |
210 | ".long 16b,90b \n" \ | |
211 | ".long 17b,90b \n" \ | |
212 | ".previous \n" \ | |
213 | : "+a" (addr), "+r" (n), "+r" (result) : "a" (io)) | |
214 | ||
78ff751f FT |
215 | static inline int mac_pdma_recv(void __iomem *io, unsigned char *start, int n) |
216 | { | |
217 | unsigned char *addr = start; | |
218 | int result = 0; | |
219 | ||
220 | if (n >= 1) { | |
221 | MOVE_BYTE("%3@,%0@"); | |
222 | if (result) | |
223 | goto out; | |
224 | } | |
225 | if (n >= 1 && ((unsigned long)addr & 1)) { | |
226 | MOVE_BYTE("%3@,%0@"); | |
227 | if (result) | |
228 | goto out; | |
229 | } | |
230 | while (n >= 32) | |
231 | MOVE_16_WORDS("%3@,%0@+"); | |
232 | while (n >= 2) | |
233 | MOVE_WORD("%3@,%0@+"); | |
234 | if (result) | |
235 | return start - addr; /* Negated to indicate uncertain length */ | |
236 | if (n == 1) | |
237 | MOVE_BYTE("%3@,%0@"); | |
238 | out: | |
239 | return addr - start; | |
240 | } | |
241 | ||
242 | static inline int mac_pdma_send(unsigned char *start, void __iomem *io, int n) | |
243 | { | |
244 | unsigned char *addr = start; | |
245 | int result = 0; | |
246 | ||
247 | if (n >= 1) { | |
248 | MOVE_BYTE("%0@,%3@"); | |
249 | if (result) | |
5551bc30 | 250 | return -1; |
78ff751f FT |
251 | } |
252 | if (n >= 1 && ((unsigned long)addr & 1)) { | |
253 | MOVE_BYTE("%0@,%3@"); | |
254 | if (result) | |
5551bc30 | 255 | return -2; |
78ff751f FT |
256 | } |
257 | while (n >= 32) | |
258 | MOVE_16_WORDS("%0@+,%3@"); | |
259 | while (n >= 2) | |
260 | MOVE_WORD("%0@+,%3@"); | |
261 | if (result) | |
5551bc30 | 262 | return start - addr - 1; /* Negated to indicate uncertain length */ |
78ff751f FT |
263 | if (n == 1) |
264 | MOVE_BYTE("%0@,%3@"); | |
78ff751f FT |
265 | return addr - start; |
266 | } | |
1da177e4 | 267 | |
8fb9a64e FT |
268 | /* The "SCSI DMA" chip on the IIfx implements this register. */ |
269 | #define CTRL_REG 0x8 | |
270 | #define CTRL_INTERRUPTS_ENABLE BIT(1) | |
271 | #define CTRL_HANDSHAKE_MODE BIT(3) | |
272 | ||
273 | static inline void write_ctrl_reg(struct NCR5380_hostdata *hostdata, u32 value) | |
274 | { | |
275 | out_be32(hostdata->io + (CTRL_REG << 4), value); | |
276 | } | |
1da177e4 | 277 | |
5545c316 FT |
278 | static inline int macscsi_wait_for_drq(struct NCR5380_hostdata *hostdata) |
279 | { | |
280 | unsigned int n = 1; /* effectively multiplies NCR5380_REG_POLL_TIME */ | |
281 | unsigned char basr; | |
282 | ||
283 | again: | |
284 | basr = NCR5380_read(BUS_AND_STATUS_REG); | |
285 | ||
286 | if (!(basr & BASR_PHASE_MATCH)) | |
287 | return 1; | |
288 | ||
289 | if (basr & BASR_IRQ) | |
290 | return -1; | |
291 | ||
292 | if (basr & BASR_DRQ) | |
293 | return 0; | |
294 | ||
295 | if (n-- == 0) { | |
296 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); | |
297 | dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, | |
298 | "%s: DRQ timeout\n", __func__); | |
299 | return -1; | |
300 | } | |
301 | ||
302 | NCR5380_poll_politely2(hostdata, | |
303 | BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, | |
304 | BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0); | |
305 | goto again; | |
306 | } | |
307 | ||
4a98f896 FT |
308 | static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, |
309 | unsigned char *dst, int len) | |
1da177e4 | 310 | { |
4ab2a787 | 311 | u8 __iomem *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); |
3a0f64bf | 312 | unsigned char *d = dst; |
78ff751f FT |
313 | |
314 | hostdata->pdma_residual = len; | |
3a0f64bf | 315 | |
5545c316 | 316 | while (macscsi_wait_for_drq(hostdata) == 0) { |
5ec4f820 | 317 | int bytes, chunk_bytes; |
3a0f64bf | 318 | |
8fb9a64e FT |
319 | if (macintosh_config->ident == MAC_MODEL_IIFX) |
320 | write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | | |
321 | CTRL_INTERRUPTS_ENABLE); | |
3a0f64bf | 322 | |
5ec4f820 FT |
323 | chunk_bytes = min(hostdata->pdma_residual, 512); |
324 | bytes = mac_pdma_recv(s, d, chunk_bytes); | |
3a0f64bf | 325 | |
5545c316 FT |
326 | if (macintosh_config->ident == MAC_MODEL_IIFX) |
327 | write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); | |
328 | ||
78ff751f FT |
329 | if (bytes > 0) { |
330 | d += bytes; | |
331 | hostdata->pdma_residual -= bytes; | |
332 | } | |
333 | ||
334 | if (hostdata->pdma_residual == 0) | |
5545c316 | 335 | break; |
78ff751f | 336 | |
5ec4f820 | 337 | if (bytes > 0) |
78ff751f | 338 | continue; |
3a0f64bf | 339 | |
4a98f896 | 340 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
5ec4f820 FT |
341 | dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, |
342 | "%s: bus error [%d/%d] (%d/%d)\n", | |
343 | __func__, d - dst, len, bytes, chunk_bytes); | |
344 | ||
345 | if (bytes == 0) | |
346 | continue; | |
347 | ||
5551bc30 FT |
348 | if (macscsi_wait_for_drq(hostdata) <= 0) |
349 | set_host_byte(hostdata->connected, DID_ERROR); | |
5545c316 | 350 | break; |
ffdede67 FT |
351 | } |
352 | ||
5551bc30 | 353 | return 0; |
1da177e4 LT |
354 | } |
355 | ||
4a98f896 FT |
356 | static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, |
357 | unsigned char *src, int len) | |
1da177e4 | 358 | { |
3a0f64bf | 359 | unsigned char *s = src; |
4ab2a787 | 360 | u8 __iomem *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); |
78ff751f FT |
361 | |
362 | hostdata->pdma_residual = len; | |
3a0f64bf | 363 | |
5545c316 | 364 | while (macscsi_wait_for_drq(hostdata) == 0) { |
5ec4f820 | 365 | int bytes, chunk_bytes; |
3a0f64bf | 366 | |
8fb9a64e FT |
367 | if (macintosh_config->ident == MAC_MODEL_IIFX) |
368 | write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | | |
369 | CTRL_INTERRUPTS_ENABLE); | |
3a0f64bf | 370 | |
5ec4f820 FT |
371 | chunk_bytes = min(hostdata->pdma_residual, 512); |
372 | bytes = mac_pdma_send(s, d, chunk_bytes); | |
3a0f64bf | 373 | |
5545c316 FT |
374 | if (macintosh_config->ident == MAC_MODEL_IIFX) |
375 | write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); | |
376 | ||
78ff751f FT |
377 | if (bytes > 0) { |
378 | s += bytes; | |
379 | hostdata->pdma_residual -= bytes; | |
380 | } | |
3a0f64bf | 381 | |
5551bc30 | 382 | if (hostdata->pdma_residual == 0) |
5545c316 | 383 | break; |
3a0f64bf | 384 | |
5ec4f820 | 385 | if (bytes > 0) |
78ff751f FT |
386 | continue; |
387 | ||
4a98f896 | 388 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
5ec4f820 FT |
389 | dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, |
390 | "%s: bus error [%d/%d] (%d/%d)\n", | |
391 | __func__, s - src, len, bytes, chunk_bytes); | |
392 | ||
393 | if (bytes == 0) | |
394 | continue; | |
395 | ||
5551bc30 FT |
396 | if (macscsi_wait_for_drq(hostdata) <= 0) |
397 | set_host_byte(hostdata->connected, DID_ERROR); | |
5545c316 | 398 | break; |
ffdede67 FT |
399 | } |
400 | ||
5551bc30 | 401 | return 0; |
ffdede67 | 402 | } |
1da177e4 | 403 | |
4a98f896 | 404 | static int macscsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, |
7e9ec8d9 FT |
405 | struct scsi_cmnd *cmd) |
406 | { | |
ff1269cb FT |
407 | int resid = NCR5380_to_ncmd(cmd)->this_residual; |
408 | ||
409 | if (hostdata->flags & FLAG_NO_PSEUDO_DMA || resid < setup_use_pdma) | |
7e9ec8d9 FT |
410 | return 0; |
411 | ||
ff1269cb | 412 | return resid; |
7e9ec8d9 FT |
413 | } |
414 | ||
4a98f896 FT |
415 | static int macscsi_dma_residual(struct NCR5380_hostdata *hostdata) |
416 | { | |
417 | return hostdata->pdma_residual; | |
418 | } | |
419 | ||
1da177e4 LT |
420 | #include "NCR5380.c" |
421 | ||
cbad48de FT |
422 | #define DRV_MODULE_NAME "mac_scsi" |
423 | #define PFX DRV_MODULE_NAME ": " | |
424 | ||
425 | static struct scsi_host_template mac_scsi_template = { | |
aa2e2cb1 FT |
426 | .module = THIS_MODULE, |
427 | .proc_name = DRV_MODULE_NAME, | |
aa2e2cb1 FT |
428 | .name = "Macintosh NCR5380 SCSI", |
429 | .info = macscsi_info, | |
430 | .queuecommand = macscsi_queue_command, | |
431 | .eh_abort_handler = macscsi_abort, | |
12e5fc66 | 432 | .eh_host_reset_handler = macscsi_host_reset, |
aa2e2cb1 FT |
433 | .can_queue = 16, |
434 | .this_id = 7, | |
2ac6d297 | 435 | .sg_tablesize = SG_ALL, |
aa2e2cb1 | 436 | .cmd_per_lun = 2, |
4af14d11 | 437 | .dma_boundary = PAGE_SIZE - 1, |
cd614642 | 438 | .cmd_size = sizeof(struct NCR5380_cmd), |
0a4e3612 | 439 | .max_sectors = 128, |
1da177e4 LT |
440 | }; |
441 | ||
cbad48de FT |
442 | static int __init mac_scsi_probe(struct platform_device *pdev) |
443 | { | |
444 | struct Scsi_Host *instance; | |
820682b1 | 445 | struct NCR5380_hostdata *hostdata; |
cbad48de FT |
446 | int error; |
447 | int host_flags = 0; | |
448 | struct resource *irq, *pio_mem, *pdma_mem = NULL; | |
449 | ||
450 | pio_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
451 | if (!pio_mem) | |
452 | return -ENODEV; | |
453 | ||
cbad48de | 454 | pdma_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
cbad48de FT |
455 | |
456 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
457 | ||
458 | if (!hwreg_present((unsigned char *)pio_mem->start + | |
459 | (STATUS_REG << 4))) { | |
460 | pr_info(PFX "no device detected at %pap\n", &pio_mem->start); | |
461 | return -ENODEV; | |
462 | } | |
463 | ||
464 | if (setup_can_queue > 0) | |
465 | mac_scsi_template.can_queue = setup_can_queue; | |
466 | if (setup_cmd_per_lun > 0) | |
467 | mac_scsi_template.cmd_per_lun = setup_cmd_per_lun; | |
79172ab2 | 468 | if (setup_sg_tablesize > 0) |
cbad48de FT |
469 | mac_scsi_template.sg_tablesize = setup_sg_tablesize; |
470 | if (setup_hostid >= 0) | |
471 | mac_scsi_template.this_id = setup_hostid & 7; | |
cbad48de | 472 | |
2ac6d297 FT |
473 | if (macintosh_config->ident == MAC_MODEL_IIFX) |
474 | mac_scsi_template.sg_tablesize = 1; | |
475 | ||
cbad48de FT |
476 | instance = scsi_host_alloc(&mac_scsi_template, |
477 | sizeof(struct NCR5380_hostdata)); | |
478 | if (!instance) | |
479 | return -ENOMEM; | |
480 | ||
cbad48de FT |
481 | if (irq) |
482 | instance->irq = irq->start; | |
483 | else | |
484 | instance->irq = NO_IRQ; | |
485 | ||
820682b1 FT |
486 | hostdata = shost_priv(instance); |
487 | hostdata->base = pio_mem->start; | |
4ab2a787 | 488 | hostdata->io = (u8 __iomem *)pio_mem->start; |
cbad48de | 489 | |
820682b1 | 490 | if (pdma_mem && setup_use_pdma) |
4ab2a787 | 491 | hostdata->pdma_io = (u8 __iomem *)pdma_mem->start; |
820682b1 | 492 | else |
cbad48de FT |
493 | host_flags |= FLAG_NO_PSEUDO_DMA; |
494 | ||
9c3f0e2b | 495 | host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; |
ca513fc9 | 496 | |
2ac6d297 FT |
497 | if (instance->sg_tablesize > 1) |
498 | host_flags |= FLAG_DMA_FIXUP; | |
499 | ||
8053b0ee | 500 | error = NCR5380_init(instance, host_flags | FLAG_LATE_DMA_SETUP); |
0ad0eff9 FT |
501 | if (error) |
502 | goto fail_init; | |
cbad48de FT |
503 | |
504 | if (instance->irq != NO_IRQ) { | |
505 | error = request_irq(instance->irq, macscsi_intr, IRQF_SHARED, | |
506 | "NCR5380", instance); | |
507 | if (error) | |
508 | goto fail_irq; | |
509 | } | |
510 | ||
9c3f0e2b FT |
511 | NCR5380_maybe_reset_bus(instance); |
512 | ||
cbad48de FT |
513 | error = scsi_add_host(instance, NULL); |
514 | if (error) | |
515 | goto fail_host; | |
516 | ||
517 | platform_set_drvdata(pdev, instance); | |
518 | ||
519 | scsi_scan_host(instance); | |
520 | return 0; | |
521 | ||
522 | fail_host: | |
523 | if (instance->irq != NO_IRQ) | |
524 | free_irq(instance->irq, instance); | |
525 | fail_irq: | |
526 | NCR5380_exit(instance); | |
0ad0eff9 | 527 | fail_init: |
cbad48de FT |
528 | scsi_host_put(instance); |
529 | return error; | |
530 | } | |
531 | ||
69b43bf3 | 532 | static void __exit mac_scsi_remove(struct platform_device *pdev) |
cbad48de FT |
533 | { |
534 | struct Scsi_Host *instance = platform_get_drvdata(pdev); | |
535 | ||
536 | scsi_remove_host(instance); | |
537 | if (instance->irq != NO_IRQ) | |
538 | free_irq(instance->irq, instance); | |
539 | NCR5380_exit(instance); | |
540 | scsi_host_put(instance); | |
cbad48de FT |
541 | } |
542 | ||
4a0166d5 UKK |
543 | /* |
544 | * mac_scsi_remove() lives in .exit.text. For drivers registered via | |
545 | * module_platform_driver_probe() this is ok because they cannot get unbound at | |
546 | * runtime. So mark the driver struct with __refdata to prevent modpost | |
547 | * triggering a section mismatch warning. | |
548 | */ | |
549 | static struct platform_driver mac_scsi_driver __refdata = { | |
f8da4c1c | 550 | .remove = __exit_p(mac_scsi_remove), |
cbad48de FT |
551 | .driver = { |
552 | .name = DRV_MODULE_NAME, | |
cbad48de FT |
553 | }, |
554 | }; | |
1da177e4 | 555 | |
cbad48de | 556 | module_platform_driver_probe(mac_scsi_driver, mac_scsi_probe); |
6e9ae6d5 | 557 | |
cbad48de | 558 | MODULE_ALIAS("platform:" DRV_MODULE_NAME); |
95f8bf93 | 559 | MODULE_DESCRIPTION("Macintosh NCR5380 SCSI driver"); |
6e9ae6d5 | 560 | MODULE_LICENSE("GPL"); |