Add support for newer SAS and similar devices to mpt(4). Tested with

the LSI SAS1064 in a Sun x4200 server.

These enhancements were developed by Garrett D'Amore and contributed
to NetBSD by the TELES AG.
This commit is contained in:
tron 2007-07-27 13:06:51 +00:00
parent 294ea334f7
commit 14ce5c0a98
6 changed files with 192 additions and 263 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpt.c,v 1.8 2007/03/04 06:01:58 christos Exp $ */
/* $NetBSD: mpt.c,v 1.9 2007/07/27 13:06:51 tron Exp $ */
/*
* Copyright (c) 2000, 2001 by Greg Ansley
@ -28,6 +28,7 @@
* Additional Copyright (c) 2002 by Matthew Jacob under same license.
*/
/*
* mpt.c:
*
@ -35,10 +36,12 @@
*
* Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
* Wasabi Systems, Inc.
*
* Additional contributions by Garrett D'Amore on behalf of TELES AG.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.8 2007/03/04 06:01:58 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.9 2007/07/27 13:06:51 tron Exp $");
#include <dev/ic/mpt.h>
@ -167,13 +170,10 @@ mpt_soft_reset(mpt_softc_t *mpt)
void
mpt_hard_reset(mpt_softc_t *mpt)
{
/* This extra read comes for the Linux source
* released by LSI. It's function is undocumented!
*/
if (mpt->verbose) {
mpt_prt(mpt, "hard reset");
}
mpt_read(mpt, MPT_OFFSET_FUBAR);
mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xff);
/* Enable diagnostic registers */
mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1);
@ -189,17 +189,6 @@ mpt_hard_reset(mpt_softc_t *mpt)
/* Disable Diagnostic Register */
mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF);
/* Restore the config register values */
/* Hard resets are known to screw up the BAR for diagnostic
memory accesses (Mem1). */
mpt_set_config_regs(mpt);
if (mpt->mpt2 != NULL) {
mpt_set_config_regs(mpt->mpt2);
}
/* Note that if there is no valid firmware to run, the doorbell will
remain in the reset state (0x00000000) */
}
/*
@ -487,11 +476,7 @@ mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
bzero(&init, sizeof init);
init.WhoInit = who;
init.Function = MPI_FUNCTION_IOC_INIT;
if (mpt->is_fc) {
init.MaxDevices = 255;
} else {
init.MaxDevices = 16;
}
init.MaxDevices = mpt->mpt_max_devices;
init.MaxBuses = 1;
init.ReplyFrameSize = MPT_REPLY_SIZE;
init.MsgContext = 0x12071941;
@ -1021,6 +1006,40 @@ mpt_disable_ints(mpt_softc_t *mpt)
}
/* (Re)Initialize the chip for use */
int
mpt_hw_init(mpt_softc_t *mpt)
{
u_int32_t db;
int try;
/*
* Start by making sure we're not at FAULT or RESET state
*/
for (try = 0; try < MPT_MAX_TRYS; try++) {
db = mpt_rd_db(mpt);
switch (MPT_STATE(db)) {
case MPT_DB_STATE_READY:
return (0);
default:
/* if peer has already reset us, don't do it again! */
if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER)
return (0);
/*FALLTHRU*/
case MPT_DB_STATE_RESET:
case MPT_DB_STATE_FAULT:
if (mpt_reset(mpt) != MPT_OK) {
DELAY(10000);
continue;
}
break;
}
}
return (EIO);
}
int
mpt_init(mpt_softc_t *mpt, u_int32_t who)
{
@ -1044,33 +1063,13 @@ mpt_init(mpt_softc_t *mpt, u_int32_t who)
/*
* Start by making sure we're not at FAULT or RESET state
*/
switch (mpt_rd_db(mpt) & MPT_DB_STATE_MASK) {
case MPT_DB_STATE_RESET:
case MPT_DB_STATE_FAULT:
if (mpt_reset(mpt) != MPT_OK) {
return (EIO);
}
default:
break;
}
if (mpt_hw_init(mpt) != 0)
return (EIO);
for (try = 0; try < MPT_MAX_TRYS; try++) {
/*
* No need to reset if the IOC is already in the READY state.
*
* Force reset if initialization failed previously.
* Note that a hard_reset of the second channel of a '929
* will stop operation of the first channel. Hopefully, if the
* first channel is ok, the second will not require a hard
* reset.
*/
if ((mpt_rd_db(mpt) & MPT_DB_STATE_MASK) !=
MPT_DB_STATE_READY) {
if (mpt_reset(mpt) != MPT_OK) {
DELAY(10000);
continue;
}
}
if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
mpt_prt(mpt, "mpt_get_iocfacts failed");
@ -1083,6 +1082,7 @@ mpt_init(mpt_softc_t *mpt, u_int32_t who)
"Request Frame Size %u\n", facts.GlobalCredits,
facts.BlockSize, facts.RequestFrameSize);
}
mpt->mpt_max_devices = facts.MaxDevices;
mpt->mpt_global_credits = facts.GlobalCredits;
mpt->request_frame_size = facts.RequestFrameSize;
@ -1098,21 +1098,29 @@ mpt_init(mpt_softc_t *mpt, u_int32_t who)
pfp.MaxDevices);
}
if (pfp.PortType != MPI_PORTFACTS_PORTTYPE_SCSI &&
pfp.PortType != MPI_PORTFACTS_PORTTYPE_FC) {
mpt_prt(mpt, "Unsupported Port Type (%x)",
pfp.PortType);
return (ENXIO);
}
if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
mpt_prt(mpt, "initiator role unsupported");
return (ENXIO);
}
if (pfp.PortType == MPI_PORTFACTS_PORTTYPE_FC) {
switch (pfp.PortType) {
case MPI_PORTFACTS_PORTTYPE_FC:
mpt->is_fc = 1;
} else {
mpt->is_fc = 0;
break;
case MPI_PORTFACTS_PORTTYPE_SCSI:
mpt->is_scsi = 1;
/* some SPI controllers (VMWare, Sun) lie */
mpt->mpt_max_devices = 16;
break;
case MPI_PORTFACTS_PORTTYPE_SAS:
mpt->is_sas = 1;
break;
default:
mpt_prt(mpt, "Unsupported Port Type (%x)",
pfp.PortType);
return (ENXIO);
}
mpt->mpt_ini_id = pfp.PortSCSIID;
if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
@ -1156,7 +1164,7 @@ mpt_init(mpt_softc_t *mpt, u_int32_t who)
* (SPI only for now)
*/
if (mpt->is_fc == 0) {
if (mpt->is_scsi) {
if (mpt_read_config_info_spi(mpt)) {
return (EIO);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpt.h,v 1.5 2005/12/11 12:21:27 christos Exp $ */
/* $NetBSD: mpt.h,v 1.6 2007/07/27 13:06:51 tron Exp $ */
/*
* Copyright (c) 2000, 2001 by Greg Ansley
@ -164,6 +164,7 @@ void mpt_free_reply(mpt_softc_t *, u_int32_t);
void mpt_enable_ints(mpt_softc_t *);
void mpt_disable_ints(mpt_softc_t *);
u_int32_t mpt_pop_reply_queue(mpt_softc_t *);
int mpt_hw_init(mpt_softc_t *);
int mpt_init(mpt_softc_t *, u_int32_t);
int mpt_reset(mpt_softc_t *);
int mpt_send_handshake_cmd(mpt_softc_t *, size_t, void *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpt_mpilib.h,v 1.2 2003/04/16 23:24:01 thorpej Exp $ */
/* $NetBSD: mpt_mpilib.h,v 1.3 2007/07/27 13:06:51 tron Exp $ */
/*
* Copyright (c) 2000, 2001 by LSI Logic Corporation
@ -3152,6 +3152,8 @@ typedef struct _MSG_PORT_FACTS_REPLY
#define MPI_PORTFACTS_PORTTYPE_INACTIVE (0x00)
#define MPI_PORTFACTS_PORTTYPE_SCSI (0x01)
#define MPI_PORTFACTS_PORTTYPE_FC (0x10)
#define MPI_PORTFACTS_PORTTYPE_ISCSI (0x20)
#define MPI_PORTFACTS_PORTTYPE_SAS (0x30)
/* ProtocolFlags values */
@ -3285,6 +3287,15 @@ typedef struct _MSG_EVENT_ACK_REPLY
#define MPI_EVENT_INTEGRATED_RAID (0x0000000B)
#define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE (0x0000000C)
#define MPI_EVENT_ON_BUS_TIMER_EXPIRED (0x0000000D)
#define MPI_EVENT_QUEUE_FULL (0x0000000E)
#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0000000F)
#define MPI_EVENT_SAS_SES (0x00000010)
#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014)
#define MPI_EVENT_IR2 (0x00000015)
#define MPI_EVENT_SAS_DISCOVERY (0x00000016)
/* AckRequired field values */
@ -3406,6 +3417,28 @@ typedef struct _EVENT_DATA_RAID
#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
/* MPI SAS Phy Link Event data */
typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
{
U8 PhyNum; /* 00h */
U8 LinkRates; /* 01h */
U16 DevHandle; /* 02h */
U64 SASAddress; /* 04h */
} EVENT_DATA_SAS_PHY_LINK_STATUS,
MPI_POINTER PTR_EVENT_DATA_SAS_PHY_LINK_STATUS,
EventDataSASPhyLinkStatus_t, MPI_POINTER pEventDataSASPhyLinkStatus_t;
#define MPI_EVENT_SAS_PLS_LR_CURRENT_MASK (0xF0)
#define MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT (4)
#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_MASK (0x0F)
#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_SHIFT (0)
#define MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN (0x00)
#define MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED (0x01)
#define MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEG (0x02)
#define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE (0x03)
#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08)
#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09)
/*****************************************************************************
*

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpt_netbsd.c,v 1.11 2007/03/04 06:01:59 christos Exp $ */
/* $NetBSD: mpt_netbsd.c,v 1.12 2007/07/27 13:06:51 tron Exp $ */
/*
* Copyright (c) 2003 Wasabi Systems, Inc.
@ -72,10 +72,12 @@
*
* Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
* Wasabi Systems, Inc.
*
* Additional contributions by Garrett D'Amore on behalf of TELES AG.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mpt_netbsd.c,v 1.11 2007/03/04 06:01:59 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: mpt_netbsd.c,v 1.12 2007/07/27 13:06:51 tron Exp $");
#include <dev/ic/mpt.h> /* pulls in all headers */
@ -122,13 +124,8 @@ mpt_scsipi_attach(mpt_softc_t *mpt)
chan->chan_channel = 0;
chan->chan_flags = 0;
chan->chan_nluns = 8;
if (mpt->is_fc) {
chan->chan_ntargets = 256;
chan->chan_id = 256;
} else {
chan->chan_ntargets = 16;
chan->chan_id = mpt->mpt_ini_id;
}
chan->chan_ntargets = mpt->mpt_max_devices;
chan->chan_id = mpt->mpt_ini_id;
(void) config_found(&mpt->sc_dev, &mpt->sc_channel, scsiprint);
}
@ -702,7 +699,7 @@ mpt_run_xfer(mpt_softc_t *mpt, struct scsipi_xfer *xs)
mpt_req->Control = MPI_SCSIIO_CONTROL_NODATATRANSFER;
/* Set the queue behavior. */
if (__predict_true(mpt->is_fc ||
if (__predict_true((!mpt->is_scsi) ||
(mpt->mpt_tag_enable &
(1 << periph->periph_target)))) {
switch (XS_CTL_TAGTYPE(xs)) {
@ -725,16 +722,16 @@ mpt_run_xfer(mpt_softc_t *mpt, struct scsipi_xfer *xs)
break;
default:
if (mpt->is_fc)
mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
else
if (mpt->is_scsi)
mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED;
else
mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
break;
}
} else
mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED;
if (__predict_false(mpt->is_fc == 0 &&
if (__predict_false(mpt->is_scsi &&
(mpt->mpt_disc_enable &
(1 << periph->periph_target)) == 0))
mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT;
@ -937,7 +934,7 @@ mpt_set_xfer_mode(mpt_softc_t *mpt, struct scsipi_xfer_mode *xm)
{
fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
if (mpt->is_fc) {
if (!mpt->is_scsi) {
/*
* SCSI transport settings don't make any sense for
* Fibre Channel; silently ignore the request.
@ -1254,6 +1251,44 @@ mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *msg)
*/
break;
case MPI_EVENT_SAS_PHY_LINK_STATUS:
switch((msg->Data[0] >> 12) & 0x0f) {
case 0x00:
mpt_prt(mpt, "Phy %d: Link Status Unknown",
msg->Data[0] & 0xff);
break;
case 0x01:
mpt_prt(mpt, "Phy %d: Link Disabled",
msg->Data[0] & 0xff);
break;
case 0x02:
mpt_prt(mpt, "Phy %d: Failed Speed Negotiation",
msg->Data[0] & 0xff);
break;
case 0x03:
mpt_prt(mpt, "Phy %d: SATA OOB Complete",
msg->Data[0] & 0xff);
break;
case 0x08:
mpt_prt(mpt, "Phy %d: Link Rate 1.5 Gbps",
msg->Data[0] & 0xff);
break;
case 0x09:
mpt_prt(mpt, "Phy %d: Link Rate 3.0 Gbps",
msg->Data[0] & 0xff);
break;
default:
mpt_prt(mpt, "Phy %d: SAS Phy Link Status Event: "
"Unknown event (%0x)",
msg->Data[0] & 0xff, (msg->Data[0] >> 8) & 0xff);
}
break;
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
case MPI_EVENT_SAS_DISCOVERY:
/* ignore these events for now */
break;
default:
mpt_prt(mpt, "Unknown async event: 0x%x", msg->Event);
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpt_netbsd.h,v 1.5 2006/12/25 18:39:48 wiz Exp $ */
/* $NetBSD: mpt_netbsd.h,v 1.6 2007/07/27 13:06:51 tron Exp $ */
/*
* Copyright (c) 2003 Wasabi Systems, Inc.
@ -70,6 +70,8 @@
*
* Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
* Wasabi Systems, Inc.
*
* Additional contributions by Garrett D'Amore on behalf of TELES AG.
*/
#ifndef _DEV_IC_MPT_NETBSD_H_
@ -168,8 +170,10 @@ typedef struct mpt_softc {
int verbose : 3,
mpt_locksetup : 1,
is_fc : 1,
is_scsi : 1,
is_sas : 1,
bus : 1,
: 26;
: 23;
/* IOC facts */
uint16_t mpt_global_credits;
@ -235,9 +239,6 @@ typedef struct mpt_softc {
uint32_t timeouts; /* timeout count */
uint32_t success; /* success after timeout */
/* Companion part in a 929 or 1030, or NULL. */
struct mpt_softc *mpt2;
/* To restore configuration after hard reset. */
void (*sc_set_config_regs)(struct mpt_softc *);
} mpt_softc_t;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mpt_pci.c,v 1.10 2006/11/16 01:33:09 christos Exp $ */
/* $NetBSD: mpt_pci.c,v 1.11 2007/07/27 13:06:51 tron Exp $ */
/*
* Copyright (c) 2003 Wasabi Systems, Inc.
@ -35,6 +35,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Additional contributions by Garrett D'Amore on behalf of TELES AG.
*/
/*
* mpt_pci.c:
*
@ -42,7 +46,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mpt_pci.c,v 1.10 2006/11/16 01:33:09 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: mpt_pci.c,v 1.11 2007/07/27 13:06:51 tron Exp $");
#include <dev/ic/mpt.h> /* pulls in all headers */
@ -71,74 +75,47 @@ struct mpt_pci_softc {
pcireg_t sc_pci_pmcsr;
};
static void mpt_pci_link_peer(mpt_softc_t *);
static void mpt_pci_read_config_regs(mpt_softc_t *);
static void mpt_pci_set_config_regs(mpt_softc_t *);
#define MPP_F_FC 0x01 /* Fibre Channel adapter */
#define MPP_F_DUAL 0x02 /* Dual port adapter */
static const struct mpt_pci_product {
pci_vendor_id_t mpp_vendor;
pci_product_id_t mpp_product;
int mpp_flags;
const char *mpp_name;
} mpt_pci_products[] = {
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_1030,
MPP_F_DUAL,
"LSI Logic 53c1030 Ultra320 SCSI" },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC909,
MPP_F_FC,
"LSI Logic FC909 FC Adapter" },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC909A,
MPP_F_FC,
"LSI Logic FC909A FC Adapter" },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929,
MPP_F_FC | MPP_F_DUAL,
"LSI Logic FC929 FC Adapter" },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929_1,
MPP_F_FC | MPP_F_DUAL,
"LSI Logic FC929 FC Adapter" },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919,
MPP_F_FC,
"LSI Logic FC919 FC Adapter" },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919_1,
MPP_F_FC,
"LSI Logic FC919 FC Adapter" },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929X,
MPP_F_FC | MPP_F_DUAL,
"LSI Logic FC929X FC Adapter" },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919X,
MPP_F_FC,
"LSI Logic FC919X FC Adapter" },
{ 0, 0,
0,
NULL },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_1030 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC909 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC909A },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929_1 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919_1},
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929X },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919X },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929X },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC939X },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC949X },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1064 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1064A },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1064E },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1066 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1066E },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1068 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1068E },
{ 0, 0 }
};
static const struct mpt_pci_product *
mpt_pci_lookup(const struct pci_attach_args *pa)
{
const struct mpt_pci_product *mpp;
for (mpp = mpt_pci_products; mpp->mpp_name != NULL; mpp++) {
if (PCI_VENDOR(pa->pa_id) == mpp->mpp_vendor &&
PCI_PRODUCT(pa->pa_id) == mpp->mpp_product)
return (mpp);
}
return (NULL);
}
static int
mpt_pci_match(struct device *parent, struct cfdata *cf,
void *aux)
mpt_pci_match(struct device *parent, struct cfdata *cf, void *aux)
{
struct pci_attach_args *pa = aux;
const struct mpt_pci_product *mpp;
if (mpt_pci_lookup(pa) != NULL)
return (1);
for (mpp = mpt_pci_products; mpp->mpp_vendor != 0; mpp++) {
if (PCI_VENDOR(pa->pa_id) == mpp->mpp_vendor &&
PCI_PRODUCT(pa->pa_id) == mpp->mpp_product)
return (1);
}
return (0);
}
@ -149,32 +126,23 @@ mpt_pci_attach(struct device *parent, struct device *self, void *aux)
struct mpt_pci_softc *psc = (void *) self;
mpt_softc_t *mpt = &psc->sc_mpt;
struct pci_attach_args *pa = aux;
const struct mpt_pci_product *mpp;
pci_intr_handle_t ih;
const char *intrstr;
pcireg_t reg, memtype;
bus_space_tag_t memt;
bus_space_handle_t memh;
int memh_valid;
char devinfo[200];
mpp = mpt_pci_lookup(pa);
if (mpp == NULL) {
printf("\n");
panic("mpt_pci_attach");
}
pci_devinfo(pa->pa_id, 0, 0, devinfo, sizeof (devinfo));
if (mpp->mpp_flags & MPP_F_FC) {
mpt->is_fc = 1;
aprint_naive(": Fibre Channel controller\n");
} else
aprint_naive(": SCSI controller\n");
aprint_normal(": %s\n", mpp->mpp_name);
aprint_naive("\n");
aprint_normal(": %s\n", devinfo);
psc->sc_pc = pa->pa_pc;
psc->sc_tag = pa->pa_tag;
mpt->sc_dmat = pa->pa_dmat;
mpt->sc_set_config_regs = mpt_pci_set_config_regs;
/*
* Map the device.
@ -248,24 +216,6 @@ mpt_pci_attach(struct device *parent, struct device *self, void *aux)
return;
}
/*
* Save the PCI config register values.
*
* Hard resets are known to screw up the BAR for diagnostic
* memory accesses (Mem1).
*
* Using Mem1 is know to make the chip stop responding to
* configuration cycles, so we need to save it now.
*/
mpt_pci_read_config_regs(mpt);
/*
* If we're a dual-port adapter, try to find our peer. We
* need to fix his PCI config registers, too.
*/
if (mpp->mpp_flags & MPP_F_DUAL)
mpt_pci_link_peer(mpt);
/* Initialize the hardware. */
if (mpt_init(mpt, MPT_DB_INIT_HOST) != 0) {
/* Error message already printed. */
@ -279,102 +229,3 @@ mpt_pci_attach(struct device *parent, struct device *self, void *aux)
CFATTACH_DECL(mpt_pci, sizeof(struct mpt_pci_softc),
mpt_pci_match, mpt_pci_attach, NULL, NULL);
/*
* Find and remember our peer PCI function on a dual-port device.
*/
static void
mpt_pci_link_peer(mpt_softc_t *mpt)
{
extern struct cfdriver mpt_cd;
struct mpt_pci_softc *peer_psc, *psc = (void *) mpt;
struct device *dev;
int unit, b, d, f, peer_b, peer_d, peer_f;
pci_decompose_tag(psc->sc_pc, psc->sc_tag, &b, &d, &f);
for (unit = 0; unit < mpt_cd.cd_ndevs; unit++) {
if (unit == device_unit(&mpt->sc_dev))
continue;
dev = device_lookup(&mpt_cd, unit);
if (dev == NULL)
continue;
if (device_parent(&mpt->sc_dev) != device_parent(dev))
continue;
/*
* If we have the same parent, we know the other one
* is attached with mpt_pci.
*/
peer_psc = (void *) dev;
if (peer_psc->sc_pc != psc->sc_pc)
continue;
pci_decompose_tag(peer_psc->sc_pc, peer_psc->sc_tag,
&peer_b, &peer_d, &peer_f);
if (peer_b == b && peer_d == d) {
if (mpt->verbose)
mpt_prt(mpt, "linking with peer: %s",
peer_psc->sc_mpt.sc_dev.dv_xname);
mpt->mpt2 = (mpt_softc_t *) peer_psc;
peer_psc->sc_mpt.mpt2 = mpt;
return;
}
}
}
/*
* Save the volatile PCI configuration registers.
*/
static void
mpt_pci_read_config_regs(mpt_softc_t *mpt)
{
struct mpt_pci_softc *psc = (void *) mpt;
psc->sc_pci_csr = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_COMMAND_STATUS_REG);
psc->sc_pci_bhlc = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_BHLC_REG);
psc->sc_pci_io_bar = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_MAPREG_START);
psc->sc_pci_mem0_bar[0] = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_MAPREG_START+0x04);
psc->sc_pci_mem0_bar[1] = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_MAPREG_START+0x08);
psc->sc_pci_mem1_bar[0] = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_MAPREG_START+0x0c);
psc->sc_pci_mem1_bar[1] = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_MAPREG_START+0x10);
psc->sc_pci_rom_bar = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_MAPREG_ROM);
psc->sc_pci_int = pci_conf_read(psc->sc_pc, psc->sc_tag,
PCI_INTERRUPT_REG);
psc->sc_pci_pmcsr = pci_conf_read(psc->sc_pc, psc->sc_tag, 0x44);
}
/*
* Restore the volatile PCI configuration registers.
*/
static void
mpt_pci_set_config_regs(mpt_softc_t *mpt)
{
struct mpt_pci_softc *psc = (void *) mpt;
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_COMMAND_STATUS_REG,
psc->sc_pci_csr);
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_BHLC_REG,
psc->sc_pci_bhlc);
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_MAPREG_START,
psc->sc_pci_io_bar);
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_MAPREG_START+0x04,
psc->sc_pci_mem0_bar[0]);
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_MAPREG_START+0x08,
psc->sc_pci_mem0_bar[1]);
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_MAPREG_START+0x0c,
psc->sc_pci_mem1_bar[0]);
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_MAPREG_START+0x10,
psc->sc_pci_mem1_bar[1]);
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_MAPREG_ROM,
psc->sc_pci_rom_bar);
pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_INTERRUPT_REG,
psc->sc_pci_int);
pci_conf_write(psc->sc_pc, psc->sc_tag, 0x44, psc->sc_pci_pmcsr);
}