Last minute fixes to ahc and ahd:

ahd_pci.c:
	Retrieve the allow_memio hint from the resource manager to
	determine whether or not to try PCI MEMIO.

aic79xx_osm.h:
aic7xxx_osm.h:
	Don't wrongly abuse the callout_reset() interface when trying
	to abuse timeouts generated from the CAM layer.  This fixes the
	console freeze and lost timeout problem that many have reported,
	especially on SMP systems.

aic79xx_pci.c
aic7xxx_pci.c
	Rewrite the MEMIO test routine to prevent certain broken chipsets
	from trying to burst multiple DWORDs to the registers.  Also make
	the routine better detect byte merging by the host bridge and
	deal with it.

aic79xx.reg:
	Correct an incorrect register definition.

Approved by:	re (rwatson, jhb)
This commit is contained in:
Scott Long 2002-12-04 22:51:29 +00:00
parent e7cba1c7dd
commit 97cae63d7f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=107623
6 changed files with 95 additions and 48 deletions

View file

@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahd_pci.c#9 $ * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahd_pci.c#10 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
@ -150,14 +150,26 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
int regs_type; int regs_type;
int regs_id; int regs_id;
int regs_id2; int regs_id2;
int allow_memio;
command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1); command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
regs = NULL; regs = NULL;
regs2 = NULL; regs2 = NULL;
regs_type = 0; regs_type = 0;
regs_id = 0; regs_id = 0;
/* Retrieve the per-device 'allow_memio' hint */
if (resource_int_value(device_get_name(ahd->dev_softc),
device_get_unit(ahd->dev_softc),
"allow_memio", &allow_memio) != 0) {
if (bootverbose)
device_printf(ahd->dev_softc,
"Defaulting to MEMIO on\n");
}
if ((command & PCIM_CMD_MEMEN) != 0 if ((command & PCIM_CMD_MEMEN) != 0
&& (ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0) { && (ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0
&& allow_memio != 0) {
regs_type = SYS_RES_MEMORY; regs_type = SYS_RES_MEMORY;
regs_id = AHD_PCI_MEMADDR; regs_id = AHD_PCI_MEMADDR;

View file

@ -39,7 +39,7 @@
* *
* $FreeBSD$ * $FreeBSD$
*/ */
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#55 $" VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#56 $"
/* /*
* This file is processed by the aic7xxx_asm utility for use in assembling * This file is processed by the aic7xxx_asm utility for use in assembling
@ -190,6 +190,7 @@ register CLRINT {
field CLRHWERRINT 0x80 /* Rev B or greater */ field CLRHWERRINT 0x80 /* Rev B or greater */
field CLRBRKADRINT 0x40 field CLRBRKADRINT 0x40
field CLRSWTMINT 0x20 field CLRSWTMINT 0x20
field CLRPCIINT 0x10
field CLRSCSIINT 0x08 field CLRSCSIINT 0x08
field CLRSEQINT 0x04 field CLRSEQINT 0x04
field CLRCMDINT 0x02 field CLRCMDINT 0x02
@ -1168,7 +1169,7 @@ register MSIPCISTAT {
* PCI Status for Target * PCI Status for Target
*/ */
register TARGPCISTAT { register TARGPCISTAT {
address 0x0A6 address 0x0A7
access_mode RW access_mode RW
modes M_CFG modes M_CFG
field DPE 0x80 field DPE 0x80

View file

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.h#18 $ * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.h#19 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
@ -239,8 +239,9 @@ ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg)
static __inline void static __inline void
ahd_scb_timer_reset(struct scb *scb, u_int usec) ahd_scb_timer_reset(struct scb *scb, u_int usec)
{ {
callout_reset(scb->io_ctx->ccb_h.timeout_ch.callout, untimeout(ahd_timeout, (caddr_t)scb, scb->io_ctx->ccb_h.timeout_ch);
(usec * hz)/1000000, ahd_timeout, scb); scb->io_ctx->ccb_h.timeout_ch =
timeout(ahd_timeout, scb, (usec * hz)/1000000);
} }
/*************************** Device Access ************************************/ /*************************** Device Access ************************************/

View file

@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#54 $ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#60 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
@ -175,8 +175,8 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
}, },
/* Generic chip probes for devices we don't know 'exactly' */ /* Generic chip probes for devices we don't know 'exactly' */
{ {
ID_AIC7901A & ID_ALL_MASK, ID_AIC7901A & ID_DEV_VENDOR_MASK,
ID_ALL_MASK, ID_DEV_VENDOR_MASK,
"Adaptec AIC7901A Ultra320 SCSI adapter", "Adaptec AIC7901A Ultra320 SCSI adapter",
ahd_aic7901A_setup ahd_aic7901A_setup
}, },
@ -378,7 +378,16 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
int int
ahd_pci_test_register_access(struct ahd_softc *ahd) ahd_pci_test_register_access(struct ahd_softc *ahd)
{ {
int i; ahd_mode_state saved_modes;
int error;
uint8_t seqctl;
saved_modes = ahd_save_modes(ahd);
error = EIO;
/* Enable PCI error interrupt status */
seqctl = ahd_inb(ahd, SEQCTL0);
ahd_outb(ahd, SEQCTL0, seqctl & ~FAILDIS);
/* /*
* First a simple test to see if any * First a simple test to see if any
@ -389,7 +398,7 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
* use for this test. * use for this test.
*/ */
if (ahd_inb(ahd, HCNTRL) == 0xFF) if (ahd_inb(ahd, HCNTRL) == 0xFF)
return (EIO); goto fail;
/* /*
* Next create a situation where write combining * Next create a situation where write combining
@ -398,19 +407,26 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
* either, so look for data corruption and/or flaged * either, so look for data corruption and/or flaged
* PCI errors. * PCI errors.
*/ */
for (i = 0; i < 16; i++) ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);
ahd_outb(ahd, SRAM_BASE + i, i); if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)
goto fail;
for (i = 0; i < 16; i++)
if (ahd_inb(ahd, SRAM_BASE + i) != i)
return (EIO);
if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) { if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
ahd_mode_state saved_modes; u_int targpcistat;
u_int targpcistat;
u_int pci_status1; 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) {
u_int targpcistat;
u_int pci_status1;
saved_modes = ahd_save_modes(ahd);
ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
targpcistat = ahd_inb(ahd, TARGPCISTAT); targpcistat = ahd_inb(ahd, TARGPCISTAT);
@ -420,13 +436,12 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
PCIR_STATUS + 1, /*bytes*/1); PCIR_STATUS + 1, /*bytes*/1);
ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
pci_status1, /*bytes*/1); pci_status1, /*bytes*/1);
ahd_restore_modes(ahd, saved_modes); ahd_outb(ahd, CLRINT, CLRPCIINT);
if ((targpcistat & STA) != 0)
return (EIO);
} }
return (0); ahd_restore_modes(ahd, saved_modes);
ahd_outb(ahd, SEQCTL0, seqctl);
return (error);
} }
/* /*
@ -731,7 +746,7 @@ ahd_pci_intr(struct ahd_softc *ahd)
s = pci_status_strings[bit]; s = pci_status_strings[bit];
if (i == 7/*TARG*/ && bit == 3) if (i == 7/*TARG*/ && bit == 3)
s = "%s: Signal Target Abort\n"; s = "%s: Signaled Target Abort\n";
printf(s, ahd_name(ahd), pci_status_source[i]); printf(s, ahd_name(ahd), pci_status_source[i]);
} }
} }
@ -741,6 +756,7 @@ ahd_pci_intr(struct ahd_softc *ahd)
ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
pci_status1, /*bytes*/1); pci_status1, /*bytes*/1);
ahd_restore_modes(ahd, saved_modes); ahd_restore_modes(ahd, saved_modes);
ahd_outb(ahd, CLRINT, CLRPCIINT);
ahd_unpause(ahd); ahd_unpause(ahd);
} }
@ -810,6 +826,7 @@ ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
*/ */
ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS, ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS,
pcix_status, /*bytes*/2); pcix_status, /*bytes*/2);
ahd_outb(ahd, CLRINT, CLRSPLTINT);
ahd_restore_modes(ahd, saved_modes); ahd_restore_modes(ahd, saved_modes);
} }

View file

@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.h#13 $ * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.h#14 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
@ -251,8 +251,9 @@ ahc_timer_reset(ahc_timer_t *timer, u_int usec, ahc_callback_t *func, void *arg)
static __inline void static __inline void
ahc_scb_timer_reset(struct scb *scb, u_int usec) ahc_scb_timer_reset(struct scb *scb, u_int usec)
{ {
callout_reset(scb->io_ctx->ccb_h.timeout_ch.callout, untimeout(ahc_timeout, (caddr_t)scb, scb->io_ctx->ccb_h.timeout_ch);
(usec * hz)/1000000, ahc_timeout, scb); scb->io_ctx->ccb_h.timeout_ch =
timeout(ahc_timeout, scb, (usec * hz)/1000000);
} }
/*************************** Device Access ************************************/ /*************************** Device Access ************************************/

View file

@ -39,7 +39,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES. * POSSIBILITY OF SUCH DAMAGES.
* *
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#52 $ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#53 $
* *
* $FreeBSD$ * $FreeBSD$
*/ */
@ -1202,8 +1202,15 @@ ahc_probe_ext_scbram(struct ahc_softc *ahc)
int int
ahc_pci_test_register_access(struct ahc_softc *ahc) ahc_pci_test_register_access(struct ahc_softc *ahc)
{ {
int i; int error;
u_int status1; u_int status1;
uint8_t seqctl;
error = EIO;
/* Enable PCI error interrupt status */
seqctl = ahc_inb(ahc, SEQCTL);
ahc_outb(ahc, SEQCTL, seqctl & ~FAILDIS);
/* /*
* First a simple test to see if any * First a simple test to see if any
@ -1214,7 +1221,7 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
* use for this test. * use for this test.
*/ */
if (ahc_inb(ahc, HCNTRL) == 0xFF) if (ahc_inb(ahc, HCNTRL) == 0xFF)
return (EIO); goto fail;
/* /*
* Next create a situation where write combining * Next create a situation where write combining
@ -1223,25 +1230,33 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
* either, so look for data corruption and/or flagged * either, so look for data corruption and/or flagged
* PCI errors. * PCI errors.
*/ */
for (i = 0; i < 16; i++) ahc_outb(ahc, SRAM_BASE, 0xaa);
ahc_outb(ahc, SRAM_BASE + i, i); ahc_outb(ahc, SRAM_BASE + 1, 0x55);
ahc_outb(ahc, SRAM_BASE + 2, 0xa5);
ahc_outb(ahc, SRAM_BASE + 3, 0x5a);
for (i = 0; i < 16; i++) if ((ahc_inb(ahc, SRAM_BASE) != 0xaa)
if (ahc_inb(ahc, SRAM_BASE + i) != i) || (ahc_inb(ahc, SRAM_BASE + 1) != 0x55)
return (EIO); || (ahc_inb(ahc, SRAM_BASE + 2) != 0xa5)
|| (ahc_inb(ahc, SRAM_BASE + 3) != 0x5a))
goto fail;
status1 = ahc_pci_read_config(ahc->dev_softc, status1 = ahc_pci_read_config(ahc->dev_softc,
PCIR_STATUS + 1, /*bytes*/1); PCIR_STATUS + 1, /*bytes*/1);
if ((status1 & STA) != 0) { if ((status1 & STA) != 0)
goto fail;
/* Silently clear any latched errors. */ error = 0;
ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
status1, /*bytes*/1);
ahc_outb(ahc, CLRINT, CLRPARERR);
return (EIO);
}
return (0); fail:
/* Silently clear any latched errors. */
status1 = ahc_pci_read_config(ahc->dev_softc,
PCIR_STATUS + 1, /*bytes*/1);
ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
status1, /*bytes*/1);
ahc_outb(ahc, CLRINT, CLRPARERR);
ahc_outb(ahc, SEQCTL, seqctl);
return (error);
} }
/* /*