diff options
Diffstat (limited to 'drivers/scsi/dtc.c')
-rw-r--r-- | drivers/scsi/dtc.c | 85 |
1 files changed, 30 insertions, 55 deletions
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 0a667fe05006..4c74c7ba2dff 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c | |||
@@ -1,5 +1,4 @@ | |||
1 | 1 | ||
2 | #define AUTOSENSE | ||
3 | #define PSEUDO_DMA | 2 | #define PSEUDO_DMA |
4 | #define DONT_USE_INTR | 3 | #define DONT_USE_INTR |
5 | #define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */ | 4 | #define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */ |
@@ -18,29 +17,9 @@ | |||
18 | * (Unix and Linux consulting and custom programming) | 17 | * (Unix and Linux consulting and custom programming) |
19 | * drew@colorado.edu | 18 | * drew@colorado.edu |
20 | * +1 (303) 440-4894 | 19 | * +1 (303) 440-4894 |
21 | * | 20 | */ |
22 | * DISTRIBUTION RELEASE 1. | ||
23 | * | ||
24 | * For more information, please consult | ||
25 | * | ||
26 | * NCR 5380 Family | ||
27 | * SCSI Protocol Controller | ||
28 | * Databook | ||
29 | */ | ||
30 | 21 | ||
31 | /* | 22 | /* |
32 | * Options : | ||
33 | * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically | ||
34 | * for commands that return with a CHECK CONDITION status. | ||
35 | * | ||
36 | * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance | ||
37 | * increase compared to polled I/O. | ||
38 | * | ||
39 | * PARITY - enable parity checking. Not supported. | ||
40 | * | ||
41 | * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. | ||
42 | * You probably want this. | ||
43 | * | ||
44 | * The card is detected and initialized in one of several ways : | 23 | * The card is detected and initialized in one of several ways : |
45 | * 1. Autoprobe (default) - since the board is memory mapped, | 24 | * 1. Autoprobe (default) - since the board is memory mapped, |
46 | * a BIOS signature is scanned for to locate the registers. | 25 | * a BIOS signature is scanned for to locate the registers. |
@@ -79,15 +58,11 @@ | |||
79 | #include <linux/init.h> | 58 | #include <linux/init.h> |
80 | #include <linux/interrupt.h> | 59 | #include <linux/interrupt.h> |
81 | #include <linux/io.h> | 60 | #include <linux/io.h> |
82 | #include "scsi.h" | ||
83 | #include <scsi/scsi_host.h> | 61 | #include <scsi/scsi_host.h> |
84 | #include "dtc.h" | 62 | #include "dtc.h" |
85 | #define AUTOPROBE_IRQ | 63 | #define AUTOPROBE_IRQ |
86 | #include "NCR5380.h" | 64 | #include "NCR5380.h" |
87 | 65 | ||
88 | |||
89 | #define DTC_PUBLIC_RELEASE 2 | ||
90 | |||
91 | /* | 66 | /* |
92 | * The DTC3180 & 3280 boards are memory mapped. | 67 | * The DTC3180 & 3280 boards are memory mapped. |
93 | * | 68 | * |
@@ -173,10 +148,13 @@ static const struct signature { | |||
173 | * | 148 | * |
174 | */ | 149 | */ |
175 | 150 | ||
176 | static void __init dtc_setup(char *str, int *ints) | 151 | static int __init dtc_setup(char *str) |
177 | { | 152 | { |
178 | static int commandline_current = 0; | 153 | static int commandline_current = 0; |
179 | int i; | 154 | int i; |
155 | int ints[10]; | ||
156 | |||
157 | get_options(str, ARRAY_SIZE(ints), ints); | ||
180 | if (ints[0] != 2) | 158 | if (ints[0] != 2) |
181 | printk("dtc_setup: usage dtc=address,irq\n"); | 159 | printk("dtc_setup: usage dtc=address,irq\n"); |
182 | else if (commandline_current < NO_OVERRIDES) { | 160 | else if (commandline_current < NO_OVERRIDES) { |
@@ -189,7 +167,10 @@ static void __init dtc_setup(char *str, int *ints) | |||
189 | } | 167 | } |
190 | ++commandline_current; | 168 | ++commandline_current; |
191 | } | 169 | } |
170 | return 1; | ||
192 | } | 171 | } |
172 | |||
173 | __setup("dtc=", dtc_setup); | ||
193 | #endif | 174 | #endif |
194 | 175 | ||
195 | /* | 176 | /* |
@@ -213,10 +194,6 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) | |||
213 | void __iomem *base; | 194 | void __iomem *base; |
214 | int sig, count; | 195 | int sig, count; |
215 | 196 | ||
216 | tpnt->proc_name = "dtc3x80"; | ||
217 | tpnt->show_info = dtc_show_info; | ||
218 | tpnt->write_info = dtc_write_info; | ||
219 | |||
220 | for (count = 0; current_override < NO_OVERRIDES; ++current_override) { | 197 | for (count = 0; current_override < NO_OVERRIDES; ++current_override) { |
221 | addr = 0; | 198 | addr = 0; |
222 | base = NULL; | 199 | base = NULL; |
@@ -271,38 +248,33 @@ found: | |||
271 | else | 248 | else |
272 | instance->irq = NCR5380_probe_irq(instance, DTC_IRQS); | 249 | instance->irq = NCR5380_probe_irq(instance, DTC_IRQS); |
273 | 250 | ||
251 | /* Compatibility with documented NCR5380 kernel parameters */ | ||
252 | if (instance->irq == 255) | ||
253 | instance->irq = NO_IRQ; | ||
254 | |||
274 | #ifndef DONT_USE_INTR | 255 | #ifndef DONT_USE_INTR |
275 | /* With interrupts enabled, it will sometimes hang when doing heavy | 256 | /* With interrupts enabled, it will sometimes hang when doing heavy |
276 | * reads. So better not enable them until I finger it out. */ | 257 | * reads. So better not enable them until I finger it out. */ |
277 | if (instance->irq != SCSI_IRQ_NONE) | 258 | if (instance->irq != NO_IRQ) |
278 | if (request_irq(instance->irq, dtc_intr, 0, | 259 | if (request_irq(instance->irq, dtc_intr, 0, |
279 | "dtc", instance)) { | 260 | "dtc", instance)) { |
280 | printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); | 261 | printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); |
281 | instance->irq = SCSI_IRQ_NONE; | 262 | instance->irq = NO_IRQ; |
282 | } | 263 | } |
283 | 264 | ||
284 | if (instance->irq == SCSI_IRQ_NONE) { | 265 | if (instance->irq == NO_IRQ) { |
285 | printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); | 266 | printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); |
286 | printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); | 267 | printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); |
287 | } | 268 | } |
288 | #else | 269 | #else |
289 | if (instance->irq != SCSI_IRQ_NONE) | 270 | if (instance->irq != NO_IRQ) |
290 | printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no); | 271 | printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no); |
291 | instance->irq = SCSI_IRQ_NONE; | 272 | instance->irq = NO_IRQ; |
292 | #endif | 273 | #endif |
293 | #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) | 274 | #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) |
294 | printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); | 275 | printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); |
295 | #endif | 276 | #endif |
296 | 277 | ||
297 | printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base); | ||
298 | if (instance->irq == SCSI_IRQ_NONE) | ||
299 | printk(" interrupts disabled"); | ||
300 | else | ||
301 | printk(" irq %d", instance->irq); | ||
302 | printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE); | ||
303 | NCR5380_print_options(instance); | ||
304 | printk("\n"); | ||
305 | |||
306 | ++current_override; | 278 | ++current_override; |
307 | ++count; | 279 | ++count; |
308 | } | 280 | } |
@@ -354,20 +326,18 @@ static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev, | |||
354 | * timeout. | 326 | * timeout. |
355 | */ | 327 | */ |
356 | 328 | ||
357 | static int dtc_maxi = 0; | ||
358 | static int dtc_wmaxi = 0; | ||
359 | |||
360 | static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) | 329 | static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) |
361 | { | 330 | { |
362 | unsigned char *d = dst; | 331 | unsigned char *d = dst; |
363 | int i; /* For counting time spent in the poll-loop */ | 332 | int i; /* For counting time spent in the poll-loop */ |
333 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | ||
364 | NCR5380_local_declare(); | 334 | NCR5380_local_declare(); |
365 | NCR5380_setup(instance); | 335 | NCR5380_setup(instance); |
366 | 336 | ||
367 | i = 0; | 337 | i = 0; |
368 | NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 338 | NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
369 | NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); | 339 | NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); |
370 | if (instance->irq == SCSI_IRQ_NONE) | 340 | if (instance->irq == NO_IRQ) |
371 | NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ); | 341 | NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ); |
372 | else | 342 | else |
373 | NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE); | 343 | NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE); |
@@ -391,8 +361,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, | |||
391 | NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ | 361 | NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ |
392 | rtrc(0); | 362 | rtrc(0); |
393 | NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 363 | NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
394 | if (i > dtc_maxi) | 364 | if (i > hostdata->spin_max_r) |
395 | dtc_maxi = i; | 365 | hostdata->spin_max_r = i; |
396 | return (0); | 366 | return (0); |
397 | } | 367 | } |
398 | 368 | ||
@@ -412,13 +382,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, | |||
412 | static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) | 382 | static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) |
413 | { | 383 | { |
414 | int i; | 384 | int i; |
385 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | ||
415 | NCR5380_local_declare(); | 386 | NCR5380_local_declare(); |
416 | NCR5380_setup(instance); | 387 | NCR5380_setup(instance); |
417 | 388 | ||
418 | NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 389 | NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
419 | NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); | 390 | NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); |
420 | /* set direction (write) */ | 391 | /* set direction (write) */ |
421 | if (instance->irq == SCSI_IRQ_NONE) | 392 | if (instance->irq == NO_IRQ) |
422 | NCR5380_write(DTC_CONTROL_REG, 0); | 393 | NCR5380_write(DTC_CONTROL_REG, 0); |
423 | else | 394 | else |
424 | NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); | 395 | NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); |
@@ -444,8 +415,8 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, | |||
444 | /* Check for parity error here. fixme. */ | 415 | /* Check for parity error here. fixme. */ |
445 | NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ | 416 | NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ |
446 | rtrc(0); | 417 | rtrc(0); |
447 | if (i > dtc_wmaxi) | 418 | if (i > hostdata->spin_max_w) |
448 | dtc_wmaxi = i; | 419 | hostdata->spin_max_w = i; |
449 | return (0); | 420 | return (0); |
450 | } | 421 | } |
451 | 422 | ||
@@ -457,7 +428,7 @@ static int dtc_release(struct Scsi_Host *shost) | |||
457 | { | 428 | { |
458 | NCR5380_local_declare(); | 429 | NCR5380_local_declare(); |
459 | NCR5380_setup(shost); | 430 | NCR5380_setup(shost); |
460 | if (shost->irq) | 431 | if (shost->irq != NO_IRQ) |
461 | free_irq(shost->irq, shost); | 432 | free_irq(shost->irq, shost); |
462 | NCR5380_exit(shost); | 433 | NCR5380_exit(shost); |
463 | if (shost->io_port && shost->n_io_port) | 434 | if (shost->io_port && shost->n_io_port) |
@@ -471,6 +442,10 @@ static struct scsi_host_template driver_template = { | |||
471 | .name = "DTC 3180/3280 ", | 442 | .name = "DTC 3180/3280 ", |
472 | .detect = dtc_detect, | 443 | .detect = dtc_detect, |
473 | .release = dtc_release, | 444 | .release = dtc_release, |
445 | .proc_name = "dtc3x80", | ||
446 | .show_info = dtc_show_info, | ||
447 | .write_info = dtc_write_info, | ||
448 | .info = dtc_info, | ||
474 | .queuecommand = dtc_queue_command, | 449 | .queuecommand = dtc_queue_command, |
475 | .eh_abort_handler = dtc_abort, | 450 | .eh_abort_handler = dtc_abort, |
476 | .eh_bus_reset_handler = dtc_bus_reset, | 451 | .eh_bus_reset_handler = dtc_bus_reset, |