aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx/aic79xx_osm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_osm.c')
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c181
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
196static struct ahd_linux_iocell_opts aic79xx_iocell_info[] = 196static 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);
369static int ahd_linux_unit; 369static int ahd_linux_unit;
370 370
371 371
372/************************** OS Utility Wrappers *******************************/
373void ahd_delay(long);
374void
375ahd_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 **********************************/
390uint8_t ahd_inb(struct ahd_softc * ahd, long port);
391void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
392void ahd_outw_atomic(struct ahd_softc * ahd,
393 long port, uint16_t val);
394void ahd_outsb(struct ahd_softc * ahd, long port,
395 uint8_t *, int count);
396void ahd_insb(struct ahd_softc * ahd, long port,
397 uint8_t *, int count);
398
399uint8_t
400ahd_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 */
414static uint16_t
415ahd_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
429void
430ahd_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
440void
441ahd_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
451void
452ahd_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
465void
466ahd_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 *********************************/
480uint32_t
481ahd_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
510void
511ahd_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 ***************************************/
373static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); 530static void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
374 531
375static __inline void 532static void
376ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) 533ahd_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
435static inline struct scsi_target ** 590static struct scsi_target **
436ahd_linux_target_in_softc(struct scsi_target *starget) 591ahd_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;