Set some termination defaults correctly. Test register access like

in the original FreeBSD driver.
This commit is contained in:
fvdl 2003-10-10 12:58:38 +00:00
parent 00cb14ef50
commit 7bff47db67
1 changed files with 98 additions and 2 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ahd_pci.c,v 1.9 2003/10/10 05:57:26 thorpej Exp $ */ /* $NetBSD: ahd_pci.c,v 1.10 2003/10/10 12:58:38 fvdl Exp $ */
/* /*
* Product specific probe and attach routines for: * Product specific probe and attach routines for:
@ -49,7 +49,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ahd_pci.c,v 1.9 2003/10/10 05:57:26 thorpej Exp $"); __KERNEL_RCSID(0, "$NetBSD: ahd_pci.c,v 1.10 2003/10/10 12:58:38 fvdl Exp $");
#define AHD_PCI_IOADDR PCI_MAPREG_START /* I/O Address */ #define AHD_PCI_IOADDR PCI_MAPREG_START /* I/O Address */
#define AHD_PCI_MEMADDR (PCI_MAPREG_START + 4) /* Mem I/O Address */ #define AHD_PCI_MEMADDR (PCI_MAPREG_START + 4) /* Mem I/O Address */
@ -380,6 +380,8 @@ ahd_pci_attach(parent, self, aux)
LIST_INIT(&ahd->pending_scbs); LIST_INIT(&ahd->pending_scbs);
ahd_timer_init(&ahd->reset_timer); ahd_timer_init(&ahd->reset_timer);
ahd_timer_init(&ahd->stat_timer); ahd_timer_init(&ahd->stat_timer);
ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A
| AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A;
ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT; ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT;
ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT; ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT;
ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT; ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT;
@ -443,6 +445,8 @@ ahd_pci_attach(parent, self, aux)
/*offset*/0x100, /*offset*/0x100,
/*size*/0x100, /*size*/0x100,
&ahd->bshs[1]); &ahd->bshs[1]);
if (ahd_pci_test_register_access(ahd) != 0)
memh_valid = 0;
} }
break; break;
default: default:
@ -590,6 +594,98 @@ ahd_pci_attach(parent, self, aux)
ahd_attach(ahd); ahd_attach(ahd);
} }
/*
* Perform some simple tests that should catch situations where
* our registers are invalidly mapped.
*/
int
ahd_pci_test_register_access(struct ahd_softc *ahd)
{
uint32_t cmd;
struct ahd_pci_busdata *bd = ahd->bus_data;
u_int targpcistat;
uint32_t pci_status1;
int error;
uint8_t hcntrl;
error = EIO;
/*
* Enable PCI error interrupt status, but suppress NMIs
* generated by SERR raised due to target aborts.
*/
cmd = pci_conf_read(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG);
pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG,
cmd & ~PCI_COMMAND_SERR_ENABLE);
/*
* First a simple test to see if any
* registers can be read. Reading
* HCNTRL has no side effects and has
* at least one bit that is guaranteed to
* be zero so it is a good register to
* use for this test.
*/
hcntrl = ahd_inb(ahd, HCNTRL);
if (hcntrl == 0xFF)
goto fail;
/*
* Next create a situation where write combining
* or read prefetching could be initiated by the
* CPU or host bridge. Our device does not support
* either, so look for data corruption and/or flaged
* PCI errors. First pause without causing another
* chip reset.
*/
hcntrl &= ~CHIPRST;
ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
while (ahd_is_paused(ahd) == 0)
;
/* Clear any PCI errors that occurred before our driver attached. */
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
targpcistat = ahd_inb(ahd, TARGPCISTAT);
ahd_outb(ahd, TARGPCISTAT, targpcistat);
pci_status1 = pci_conf_read(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG);
pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG, pci_status1);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_outb(ahd, CLRINT, CLRPCIINT);
ahd_outb(ahd, SEQCTL0, PERRORDIS);
ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);
if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)
goto fail;
if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
u_int targpcistat;
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
targpcistat = ahd_inb(ahd, TARGPCISTAT);
if ((targpcistat & STA) != 0)
goto fail;
}
error = 0;
fail:
if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
targpcistat = ahd_inb(ahd, TARGPCISTAT);
/* Silently clear any latched errors. */
ahd_outb(ahd, TARGPCISTAT, targpcistat);
pci_status1 = pci_conf_read(bd->pc, bd->tag,
PCI_COMMAND_STATUS_REG);
pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG,
pci_status1);
ahd_outb(ahd, CLRINT, CLRPCIINT);
}
ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);
pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG, cmd);
return (error);
}
/* /*
* Check the external port logic for a serial eeprom * Check the external port logic for a serial eeprom