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 | * | |
105 | * If a MOVE.B instruction faults, we assume that zero bytes were transferred | |
106 | * and simply retry. That assumption probably depends on target behaviour but | |
107 | * seems to hold up okay. The NOP provides synchronization: without it the | |
108 | * fault can sometimes occur after the program counter has moved past the | |
109 | * offending instruction. Post-increment addressing can't be used. | |
110 | */ | |
111 | ||
112 | #define MOVE_BYTE(operands) \ | |
113 | asm volatile ( \ | |
114 | "1: moveb " operands " \n" \ | |
115 | "11: nop \n" \ | |
116 | " addq #1,%0 \n" \ | |
117 | " subq #1,%1 \n" \ | |
118 | "40: \n" \ | |
119 | " \n" \ | |
120 | ".section .fixup,\"ax\" \n" \ | |
121 | ".even \n" \ | |
122 | "90: movel #1, %2 \n" \ | |
123 | " jra 40b \n" \ | |
124 | ".previous \n" \ | |
125 | " \n" \ | |
126 | ".section __ex_table,\"a\" \n" \ | |
127 | ".align 4 \n" \ | |
128 | ".long 1b,90b \n" \ | |
129 | ".long 11b,90b \n" \ | |
130 | ".previous \n" \ | |
131 | : "+a" (addr), "+r" (n), "+r" (result) : "a" (io)) | |
132 | ||
133 | /* | |
134 | * If a MOVE.W (or MOVE.L) instruction faults, it cannot be retried because | |
135 | * the residual byte count would be uncertain. In that situation the MOVE_WORD | |
136 | * macro clears n in the fixup section to abort the transfer. | |
137 | */ | |
138 | ||
139 | #define MOVE_WORD(operands) \ | |
140 | asm volatile ( \ | |
141 | "1: movew " operands " \n" \ | |
142 | "11: nop \n" \ | |
143 | " subq #2,%1 \n" \ | |
144 | "40: \n" \ | |
145 | " \n" \ | |
146 | ".section .fixup,\"ax\" \n" \ | |
147 | ".even \n" \ | |
148 | "90: movel #0, %1 \n" \ | |
149 | " movel #2, %2 \n" \ | |
150 | " jra 40b \n" \ | |
151 | ".previous \n" \ | |
152 | " \n" \ | |
153 | ".section __ex_table,\"a\" \n" \ | |
154 | ".align 4 \n" \ | |
155 | ".long 1b,90b \n" \ | |
156 | ".long 11b,90b \n" \ | |
157 | ".previous \n" \ | |
158 | : "+a" (addr), "+r" (n), "+r" (result) : "a" (io)) | |
159 | ||
160 | #define MOVE_16_WORDS(operands) \ | |
161 | asm volatile ( \ | |
162 | "1: movew " operands " \n" \ | |
163 | "2: movew " operands " \n" \ | |
164 | "3: movew " operands " \n" \ | |
165 | "4: movew " operands " \n" \ | |
166 | "5: movew " operands " \n" \ | |
167 | "6: movew " operands " \n" \ | |
168 | "7: movew " operands " \n" \ | |
169 | "8: movew " operands " \n" \ | |
170 | "9: movew " operands " \n" \ | |
171 | "10: movew " operands " \n" \ | |
172 | "11: movew " operands " \n" \ | |
173 | "12: movew " operands " \n" \ | |
174 | "13: movew " operands " \n" \ | |
175 | "14: movew " operands " \n" \ | |
176 | "15: movew " operands " \n" \ | |
177 | "16: movew " operands " \n" \ | |
178 | "17: nop \n" \ | |
179 | " subl #32,%1 \n" \ | |
180 | "40: \n" \ | |
181 | " \n" \ | |
182 | ".section .fixup,\"ax\" \n" \ | |
183 | ".even \n" \ | |
184 | "90: movel #0, %1 \n" \ | |
185 | " movel #2, %2 \n" \ | |
186 | " jra 40b \n" \ | |
187 | ".previous \n" \ | |
188 | " \n" \ | |
189 | ".section __ex_table,\"a\" \n" \ | |
190 | ".align 4 \n" \ | |
191 | ".long 1b,90b \n" \ | |
192 | ".long 2b,90b \n" \ | |
193 | ".long 3b,90b \n" \ | |
194 | ".long 4b,90b \n" \ | |
195 | ".long 5b,90b \n" \ | |
196 | ".long 6b,90b \n" \ | |
197 | ".long 7b,90b \n" \ | |
198 | ".long 8b,90b \n" \ | |
199 | ".long 9b,90b \n" \ | |
200 | ".long 10b,90b \n" \ | |
201 | ".long 11b,90b \n" \ | |
202 | ".long 12b,90b \n" \ | |
203 | ".long 13b,90b \n" \ | |
204 | ".long 14b,90b \n" \ | |
205 | ".long 15b,90b \n" \ | |
206 | ".long 16b,90b \n" \ | |
207 | ".long 17b,90b \n" \ | |
208 | ".previous \n" \ | |
209 | : "+a" (addr), "+r" (n), "+r" (result) : "a" (io)) | |
210 | ||
211 | #define MAC_PDMA_DELAY 32 | |
212 | ||
213 | static inline int mac_pdma_recv(void __iomem *io, unsigned char *start, int n) | |
214 | { | |
215 | unsigned char *addr = start; | |
216 | int result = 0; | |
217 | ||
218 | if (n >= 1) { | |
219 | MOVE_BYTE("%3@,%0@"); | |
220 | if (result) | |
221 | goto out; | |
222 | } | |
223 | if (n >= 1 && ((unsigned long)addr & 1)) { | |
224 | MOVE_BYTE("%3@,%0@"); | |
225 | if (result) | |
226 | goto out; | |
227 | } | |
228 | while (n >= 32) | |
229 | MOVE_16_WORDS("%3@,%0@+"); | |
230 | while (n >= 2) | |
231 | MOVE_WORD("%3@,%0@+"); | |
232 | if (result) | |
233 | return start - addr; /* Negated to indicate uncertain length */ | |
234 | if (n == 1) | |
235 | MOVE_BYTE("%3@,%0@"); | |
236 | out: | |
237 | return addr - start; | |
238 | } | |
239 | ||
240 | static inline int mac_pdma_send(unsigned char *start, void __iomem *io, int n) | |
241 | { | |
242 | unsigned char *addr = start; | |
243 | int result = 0; | |
244 | ||
245 | if (n >= 1) { | |
246 | MOVE_BYTE("%0@,%3@"); | |
247 | if (result) | |
248 | goto out; | |
249 | } | |
250 | if (n >= 1 && ((unsigned long)addr & 1)) { | |
251 | MOVE_BYTE("%0@,%3@"); | |
252 | if (result) | |
253 | goto out; | |
254 | } | |
255 | while (n >= 32) | |
256 | MOVE_16_WORDS("%0@+,%3@"); | |
257 | while (n >= 2) | |
258 | MOVE_WORD("%0@+,%3@"); | |
259 | if (result) | |
260 | return start - addr; /* Negated to indicate uncertain length */ | |
261 | if (n == 1) | |
262 | MOVE_BYTE("%0@,%3@"); | |
263 | out: | |
264 | return addr - start; | |
265 | } | |
1da177e4 | 266 | |
8fb9a64e FT |
267 | /* The "SCSI DMA" chip on the IIfx implements this register. */ |
268 | #define CTRL_REG 0x8 | |
269 | #define CTRL_INTERRUPTS_ENABLE BIT(1) | |
270 | #define CTRL_HANDSHAKE_MODE BIT(3) | |
271 | ||
272 | static inline void write_ctrl_reg(struct NCR5380_hostdata *hostdata, u32 value) | |
273 | { | |
274 | out_be32(hostdata->io + (CTRL_REG << 4), value); | |
275 | } | |
1da177e4 | 276 | |
4a98f896 FT |
277 | static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, |
278 | unsigned char *dst, int len) | |
1da177e4 | 279 | { |
4ab2a787 | 280 | u8 __iomem *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); |
3a0f64bf | 281 | unsigned char *d = dst; |
8fb9a64e | 282 | int result = 0; |
78ff751f FT |
283 | |
284 | hostdata->pdma_residual = len; | |
3a0f64bf | 285 | |
d5d37a0a | 286 | while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, |
3a0f64bf | 287 | BASR_DRQ | BASR_PHASE_MATCH, |
e7734ef1 | 288 | BASR_DRQ | BASR_PHASE_MATCH, 0)) { |
78ff751f | 289 | int bytes; |
3a0f64bf | 290 | |
8fb9a64e FT |
291 | if (macintosh_config->ident == MAC_MODEL_IIFX) |
292 | write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | | |
293 | CTRL_INTERRUPTS_ENABLE); | |
3a0f64bf | 294 | |
78ff751f | 295 | bytes = mac_pdma_recv(s, d, min(hostdata->pdma_residual, 512)); |
3a0f64bf | 296 | |
78ff751f FT |
297 | if (bytes > 0) { |
298 | d += bytes; | |
299 | hostdata->pdma_residual -= bytes; | |
300 | } | |
301 | ||
302 | if (hostdata->pdma_residual == 0) | |
8fb9a64e | 303 | goto out; |
3a0f64bf | 304 | |
d5d37a0a | 305 | if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, |
78ff751f | 306 | BUS_AND_STATUS_REG, BASR_ACK, |
e7734ef1 | 307 | BASR_ACK, 0) < 0) |
78ff751f | 308 | scmd_printk(KERN_DEBUG, hostdata->connected, |
3a0f64bf FT |
309 | "%s: !REQ and !ACK\n", __func__); |
310 | if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) | |
8fb9a64e | 311 | goto out; |
3a0f64bf | 312 | |
78ff751f FT |
313 | if (bytes == 0) |
314 | udelay(MAC_PDMA_DELAY); | |
315 | ||
316 | if (bytes >= 0) | |
317 | continue; | |
3a0f64bf | 318 | |
4a98f896 | 319 | dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, |
78ff751f | 320 | "%s: bus error (%d/%d)\n", __func__, d - dst, len); |
4a98f896 | 321 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
8fb9a64e FT |
322 | result = -1; |
323 | goto out; | |
ffdede67 FT |
324 | } |
325 | ||
3a0f64bf FT |
326 | scmd_printk(KERN_ERR, hostdata->connected, |
327 | "%s: phase mismatch or !DRQ\n", __func__); | |
4a98f896 | 328 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
8fb9a64e FT |
329 | result = -1; |
330 | out: | |
331 | if (macintosh_config->ident == MAC_MODEL_IIFX) | |
332 | write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); | |
333 | return result; | |
1da177e4 LT |
334 | } |
335 | ||
4a98f896 FT |
336 | static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, |
337 | unsigned char *src, int len) | |
1da177e4 | 338 | { |
3a0f64bf | 339 | unsigned char *s = src; |
4ab2a787 | 340 | u8 __iomem *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); |
8fb9a64e | 341 | int result = 0; |
78ff751f FT |
342 | |
343 | hostdata->pdma_residual = len; | |
3a0f64bf | 344 | |
d5d37a0a | 345 | while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, |
3a0f64bf | 346 | BASR_DRQ | BASR_PHASE_MATCH, |
e7734ef1 | 347 | BASR_DRQ | BASR_PHASE_MATCH, 0)) { |
78ff751f | 348 | int bytes; |
3a0f64bf | 349 | |
8fb9a64e FT |
350 | if (macintosh_config->ident == MAC_MODEL_IIFX) |
351 | write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | | |
352 | CTRL_INTERRUPTS_ENABLE); | |
3a0f64bf | 353 | |
78ff751f | 354 | bytes = mac_pdma_send(s, d, min(hostdata->pdma_residual, 512)); |
3a0f64bf | 355 | |
78ff751f FT |
356 | if (bytes > 0) { |
357 | s += bytes; | |
358 | hostdata->pdma_residual -= bytes; | |
359 | } | |
3a0f64bf | 360 | |
78ff751f | 361 | if (hostdata->pdma_residual == 0) { |
d5d37a0a | 362 | if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG, |
3a0f64bf | 363 | TCR_LAST_BYTE_SENT, |
7c1f3e34 | 364 | TCR_LAST_BYTE_SENT, |
e7734ef1 | 365 | 0) < 0) { |
3a0f64bf FT |
366 | scmd_printk(KERN_ERR, hostdata->connected, |
367 | "%s: Last Byte Sent timeout\n", __func__); | |
7c1f3e34 FT |
368 | result = -1; |
369 | } | |
8fb9a64e | 370 | goto out; |
3a0f64bf FT |
371 | } |
372 | ||
78ff751f FT |
373 | if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, |
374 | BUS_AND_STATUS_REG, BASR_ACK, | |
e7734ef1 | 375 | BASR_ACK, 0) < 0) |
78ff751f FT |
376 | scmd_printk(KERN_DEBUG, hostdata->connected, |
377 | "%s: !REQ and !ACK\n", __func__); | |
378 | if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) | |
8fb9a64e | 379 | goto out; |
78ff751f FT |
380 | |
381 | if (bytes == 0) | |
382 | udelay(MAC_PDMA_DELAY); | |
383 | ||
384 | if (bytes >= 0) | |
385 | continue; | |
386 | ||
4a98f896 | 387 | dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, |
78ff751f | 388 | "%s: bus error (%d/%d)\n", __func__, s - src, len); |
4a98f896 | 389 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
8fb9a64e FT |
390 | result = -1; |
391 | goto out; | |
ffdede67 FT |
392 | } |
393 | ||
3a0f64bf FT |
394 | scmd_printk(KERN_ERR, hostdata->connected, |
395 | "%s: phase mismatch or !DRQ\n", __func__); | |
4a98f896 | 396 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
8fb9a64e FT |
397 | result = -1; |
398 | out: | |
399 | if (macintosh_config->ident == MAC_MODEL_IIFX) | |
400 | write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); | |
401 | return result; | |
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, | |
3a0f64bf | 435 | .sg_tablesize = 1, |
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 FT |
472 | |
473 | instance = scsi_host_alloc(&mac_scsi_template, | |
474 | sizeof(struct NCR5380_hostdata)); | |
475 | if (!instance) | |
476 | return -ENOMEM; | |
477 | ||
cbad48de FT |
478 | if (irq) |
479 | instance->irq = irq->start; | |
480 | else | |
481 | instance->irq = NO_IRQ; | |
482 | ||
820682b1 FT |
483 | hostdata = shost_priv(instance); |
484 | hostdata->base = pio_mem->start; | |
4ab2a787 | 485 | hostdata->io = (u8 __iomem *)pio_mem->start; |
cbad48de | 486 | |
820682b1 | 487 | if (pdma_mem && setup_use_pdma) |
4ab2a787 | 488 | hostdata->pdma_io = (u8 __iomem *)pdma_mem->start; |
820682b1 | 489 | else |
cbad48de FT |
490 | host_flags |= FLAG_NO_PSEUDO_DMA; |
491 | ||
9c3f0e2b | 492 | host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; |
ca513fc9 | 493 | |
8053b0ee | 494 | error = NCR5380_init(instance, host_flags | FLAG_LATE_DMA_SETUP); |
0ad0eff9 FT |
495 | if (error) |
496 | goto fail_init; | |
cbad48de FT |
497 | |
498 | if (instance->irq != NO_IRQ) { | |
499 | error = request_irq(instance->irq, macscsi_intr, IRQF_SHARED, | |
500 | "NCR5380", instance); | |
501 | if (error) | |
502 | goto fail_irq; | |
503 | } | |
504 | ||
9c3f0e2b FT |
505 | NCR5380_maybe_reset_bus(instance); |
506 | ||
cbad48de FT |
507 | error = scsi_add_host(instance, NULL); |
508 | if (error) | |
509 | goto fail_host; | |
510 | ||
511 | platform_set_drvdata(pdev, instance); | |
512 | ||
513 | scsi_scan_host(instance); | |
514 | return 0; | |
515 | ||
516 | fail_host: | |
517 | if (instance->irq != NO_IRQ) | |
518 | free_irq(instance->irq, instance); | |
519 | fail_irq: | |
520 | NCR5380_exit(instance); | |
0ad0eff9 | 521 | fail_init: |
cbad48de FT |
522 | scsi_host_put(instance); |
523 | return error; | |
524 | } | |
525 | ||
526 | static int __exit mac_scsi_remove(struct platform_device *pdev) | |
527 | { | |
528 | struct Scsi_Host *instance = platform_get_drvdata(pdev); | |
529 | ||
530 | scsi_remove_host(instance); | |
531 | if (instance->irq != NO_IRQ) | |
532 | free_irq(instance->irq, instance); | |
533 | NCR5380_exit(instance); | |
534 | scsi_host_put(instance); | |
535 | return 0; | |
536 | } | |
537 | ||
538 | static struct platform_driver mac_scsi_driver = { | |
539 | .remove = __exit_p(mac_scsi_remove), | |
540 | .driver = { | |
541 | .name = DRV_MODULE_NAME, | |
cbad48de FT |
542 | }, |
543 | }; | |
1da177e4 | 544 | |
cbad48de | 545 | module_platform_driver_probe(mac_scsi_driver, mac_scsi_probe); |
6e9ae6d5 | 546 | |
cbad48de | 547 | MODULE_ALIAS("platform:" DRV_MODULE_NAME); |
6e9ae6d5 | 548 | MODULE_LICENSE("GPL"); |