diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_osm.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.c | 181 |
1 files changed, 168 insertions, 13 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 0081aa357c8b..0f829b3b8ab7 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -193,7 +193,7 @@ struct ahd_linux_iocell_opts | |||
193 | #define AIC79XX_PRECOMP_INDEX 0 | 193 | #define AIC79XX_PRECOMP_INDEX 0 |
194 | #define AIC79XX_SLEWRATE_INDEX 1 | 194 | #define AIC79XX_SLEWRATE_INDEX 1 |
195 | #define AIC79XX_AMPLITUDE_INDEX 2 | 195 | #define AIC79XX_AMPLITUDE_INDEX 2 |
196 | static struct ahd_linux_iocell_opts aic79xx_iocell_info[] = | 196 | static const struct ahd_linux_iocell_opts aic79xx_iocell_info[] = |
197 | { | 197 | { |
198 | AIC79XX_DEFAULT_IOOPTS, | 198 | AIC79XX_DEFAULT_IOOPTS, |
199 | AIC79XX_DEFAULT_IOOPTS, | 199 | AIC79XX_DEFAULT_IOOPTS, |
@@ -369,10 +369,167 @@ static void ahd_release_simq(struct ahd_softc *ahd); | |||
369 | static int ahd_linux_unit; | 369 | static int ahd_linux_unit; |
370 | 370 | ||
371 | 371 | ||
372 | /************************** OS Utility Wrappers *******************************/ | ||
373 | void ahd_delay(long); | ||
374 | void | ||
375 | ahd_delay(long usec) | ||
376 | { | ||
377 | /* | ||
378 | * udelay on Linux can have problems for | ||
379 | * multi-millisecond waits. Wait at most | ||
380 | * 1024us per call. | ||
381 | */ | ||
382 | while (usec > 0) { | ||
383 | udelay(usec % 1024); | ||
384 | usec -= 1024; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | |||
389 | /***************************** Low Level I/O **********************************/ | ||
390 | uint8_t ahd_inb(struct ahd_softc * ahd, long port); | ||
391 | void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val); | ||
392 | void ahd_outw_atomic(struct ahd_softc * ahd, | ||
393 | long port, uint16_t val); | ||
394 | void ahd_outsb(struct ahd_softc * ahd, long port, | ||
395 | uint8_t *, int count); | ||
396 | void ahd_insb(struct ahd_softc * ahd, long port, | ||
397 | uint8_t *, int count); | ||
398 | |||
399 | uint8_t | ||
400 | ahd_inb(struct ahd_softc * ahd, long port) | ||
401 | { | ||
402 | uint8_t x; | ||
403 | |||
404 | if (ahd->tags[0] == BUS_SPACE_MEMIO) { | ||
405 | x = readb(ahd->bshs[0].maddr + port); | ||
406 | } else { | ||
407 | x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); | ||
408 | } | ||
409 | mb(); | ||
410 | return (x); | ||
411 | } | ||
412 | |||
413 | #if 0 /* unused */ | ||
414 | static uint16_t | ||
415 | ahd_inw_atomic(struct ahd_softc * ahd, long port) | ||
416 | { | ||
417 | uint8_t x; | ||
418 | |||
419 | if (ahd->tags[0] == BUS_SPACE_MEMIO) { | ||
420 | x = readw(ahd->bshs[0].maddr + port); | ||
421 | } else { | ||
422 | x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); | ||
423 | } | ||
424 | mb(); | ||
425 | return (x); | ||
426 | } | ||
427 | #endif | ||
428 | |||
429 | void | ||
430 | ahd_outb(struct ahd_softc * ahd, long port, uint8_t val) | ||
431 | { | ||
432 | if (ahd->tags[0] == BUS_SPACE_MEMIO) { | ||
433 | writeb(val, ahd->bshs[0].maddr + port); | ||
434 | } else { | ||
435 | outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); | ||
436 | } | ||
437 | mb(); | ||
438 | } | ||
439 | |||
440 | void | ||
441 | ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val) | ||
442 | { | ||
443 | if (ahd->tags[0] == BUS_SPACE_MEMIO) { | ||
444 | writew(val, ahd->bshs[0].maddr + port); | ||
445 | } else { | ||
446 | outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); | ||
447 | } | ||
448 | mb(); | ||
449 | } | ||
450 | |||
451 | void | ||
452 | ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count) | ||
453 | { | ||
454 | int i; | ||
455 | |||
456 | /* | ||
457 | * There is probably a more efficient way to do this on Linux | ||
458 | * but we don't use this for anything speed critical and this | ||
459 | * should work. | ||
460 | */ | ||
461 | for (i = 0; i < count; i++) | ||
462 | ahd_outb(ahd, port, *array++); | ||
463 | } | ||
464 | |||
465 | void | ||
466 | ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count) | ||
467 | { | ||
468 | int i; | ||
469 | |||
470 | /* | ||
471 | * There is probably a more efficient way to do this on Linux | ||
472 | * but we don't use this for anything speed critical and this | ||
473 | * should work. | ||
474 | */ | ||
475 | for (i = 0; i < count; i++) | ||
476 | *array++ = ahd_inb(ahd, port); | ||
477 | } | ||
478 | |||
479 | /******************************* PCI Routines *********************************/ | ||
480 | uint32_t | ||
481 | ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width) | ||
482 | { | ||
483 | switch (width) { | ||
484 | case 1: | ||
485 | { | ||
486 | uint8_t retval; | ||
487 | |||
488 | pci_read_config_byte(pci, reg, &retval); | ||
489 | return (retval); | ||
490 | } | ||
491 | case 2: | ||
492 | { | ||
493 | uint16_t retval; | ||
494 | pci_read_config_word(pci, reg, &retval); | ||
495 | return (retval); | ||
496 | } | ||
497 | case 4: | ||
498 | { | ||
499 | uint32_t retval; | ||
500 | pci_read_config_dword(pci, reg, &retval); | ||
501 | return (retval); | ||
502 | } | ||
503 | default: | ||
504 | panic("ahd_pci_read_config: Read size too big"); | ||
505 | /* NOTREACHED */ | ||
506 | return (0); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | void | ||
511 | ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width) | ||
512 | { | ||
513 | switch (width) { | ||
514 | case 1: | ||
515 | pci_write_config_byte(pci, reg, value); | ||
516 | break; | ||
517 | case 2: | ||
518 | pci_write_config_word(pci, reg, value); | ||
519 | break; | ||
520 | case 4: | ||
521 | pci_write_config_dword(pci, reg, value); | ||
522 | break; | ||
523 | default: | ||
524 | panic("ahd_pci_write_config: Write size too big"); | ||
525 | /* NOTREACHED */ | ||
526 | } | ||
527 | } | ||
528 | |||
372 | /****************************** Inlines ***************************************/ | 529 | /****************************** Inlines ***************************************/ |
373 | static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); | 530 | static void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); |
374 | 531 | ||
375 | static __inline void | 532 | static void |
376 | ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) | 533 | ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) |
377 | { | 534 | { |
378 | struct scsi_cmnd *cmd; | 535 | struct scsi_cmnd *cmd; |
@@ -400,13 +557,11 @@ ahd_linux_info(struct Scsi_Host *host) | |||
400 | bp = &buffer[0]; | 557 | bp = &buffer[0]; |
401 | ahd = *(struct ahd_softc **)host->hostdata; | 558 | ahd = *(struct ahd_softc **)host->hostdata; |
402 | memset(bp, 0, sizeof(buffer)); | 559 | memset(bp, 0, sizeof(buffer)); |
403 | strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev "); | 560 | strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev " AIC79XX_DRIVER_VERSION "\n" |
404 | strcat(bp, AIC79XX_DRIVER_VERSION); | 561 | " <"); |
405 | strcat(bp, "\n"); | ||
406 | strcat(bp, " <"); | ||
407 | strcat(bp, ahd->description); | 562 | strcat(bp, ahd->description); |
408 | strcat(bp, ">\n"); | 563 | strcat(bp, ">\n" |
409 | strcat(bp, " "); | 564 | " "); |
410 | ahd_controller_info(ahd, ahd_info); | 565 | ahd_controller_info(ahd, ahd_info); |
411 | strcat(bp, ahd_info); | 566 | strcat(bp, ahd_info); |
412 | 567 | ||
@@ -432,7 +587,7 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)) | |||
432 | return rtn; | 587 | return rtn; |
433 | } | 588 | } |
434 | 589 | ||
435 | static inline struct scsi_target ** | 590 | static struct scsi_target ** |
436 | ahd_linux_target_in_softc(struct scsi_target *starget) | 591 | ahd_linux_target_in_softc(struct scsi_target *starget) |
437 | { | 592 | { |
438 | struct ahd_softc *ahd = | 593 | struct ahd_softc *ahd = |
@@ -991,7 +1146,7 @@ aic79xx_setup(char *s) | |||
991 | char *p; | 1146 | char *p; |
992 | char *end; | 1147 | char *end; |
993 | 1148 | ||
994 | static struct { | 1149 | static const struct { |
995 | const char *name; | 1150 | const char *name; |
996 | uint32_t *flag; | 1151 | uint32_t *flag; |
997 | } options[] = { | 1152 | } options[] = { |
@@ -1223,7 +1378,7 @@ ahd_platform_init(struct ahd_softc *ahd) | |||
1223 | * Lookup and commit any modified IO Cell options. | 1378 | * Lookup and commit any modified IO Cell options. |
1224 | */ | 1379 | */ |
1225 | if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { | 1380 | if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { |
1226 | struct ahd_linux_iocell_opts *iocell_opts; | 1381 | const struct ahd_linux_iocell_opts *iocell_opts; |
1227 | 1382 | ||
1228 | iocell_opts = &aic79xx_iocell_info[ahd->unit]; | 1383 | iocell_opts = &aic79xx_iocell_info[ahd->unit]; |
1229 | if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP) | 1384 | if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP) |
@@ -2613,7 +2768,7 @@ static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp) | |||
2613 | uint8_t precomp; | 2768 | uint8_t precomp; |
2614 | 2769 | ||
2615 | if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { | 2770 | if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { |
2616 | struct ahd_linux_iocell_opts *iocell_opts; | 2771 | const struct ahd_linux_iocell_opts *iocell_opts; |
2617 | 2772 | ||
2618 | iocell_opts = &aic79xx_iocell_info[ahd->unit]; | 2773 | iocell_opts = &aic79xx_iocell_info[ahd->unit]; |
2619 | precomp = iocell_opts->precomp; | 2774 | precomp = iocell_opts->precomp; |