A chunk of cleanup, both stylistic and substantive.

We now also read configuration information for the SCSI cards- this allows
us to try and say what the speed settings now are.

Start, but not yet complete, the process of reorgs && #defines so that we
can backport to RELENG_4 pretty soon.
This commit is contained in:
Matt Jacob 2002-08-20 23:04:08 +00:00
parent 71f9b42067
commit 7104aeef01
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=102199
6 changed files with 1018 additions and 327 deletions

View file

@ -31,7 +31,7 @@
*/
#include <dev/mpt/mpt_freebsd.h>
#include <dev/mpt/mpt.h>
#define MPT_MAX_TRYS 3
#define MPT_MAX_WAIT 300000
@ -39,24 +39,24 @@ static int maxwait_ack = 0;
static int maxwait_int = 0;
static int maxwait_state = 0;
static __inline u_int32_t mpt_rd_db(struct mpt_softc *mpt);
static __inline u_int32_t mpt_rd_intr(struct mpt_softc *mpt);
static __inline u_int32_t mpt_rd_db(mpt_softc_t *mpt);
static __inline u_int32_t mpt_rd_intr(mpt_softc_t *mpt);
static __inline u_int32_t
mpt_rd_db(struct mpt_softc *mpt)
mpt_rd_db(mpt_softc_t *mpt)
{
return mpt_read(mpt, MPT_OFFSET_DOORBELL);
}
static __inline u_int32_t
mpt_rd_intr(struct mpt_softc *mpt)
mpt_rd_intr(mpt_softc_t *mpt)
{
return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
}
/* Busy wait for a door bell to be read by IOC */
static int
mpt_wait_db_ack(struct mpt_softc *mpt)
mpt_wait_db_ack(mpt_softc_t *mpt)
{
int i;
for (i=0; i < MPT_MAX_WAIT; i++) {
@ -72,7 +72,7 @@ mpt_wait_db_ack(struct mpt_softc *mpt)
/* Busy wait for a door bell interrupt */
static int
mpt_wait_db_int(struct mpt_softc *mpt)
mpt_wait_db_int(mpt_softc_t *mpt)
{
int i;
for (i=0; i < MPT_MAX_WAIT; i++) {
@ -87,7 +87,7 @@ mpt_wait_db_int(struct mpt_softc *mpt)
/* Wait for IOC to transition to a give state */
void
mpt_check_doorbell(struct mpt_softc *mpt)
mpt_check_doorbell(mpt_softc_t *mpt)
{
u_int32_t db = mpt_rd_db(mpt);
if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
@ -98,7 +98,7 @@ mpt_check_doorbell(struct mpt_softc *mpt)
/* Wait for IOC to transition to a give state */
static int
mpt_wait_state(struct mpt_softc *mpt, enum DB_STATE_BITS state)
mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state)
{
int i;
@ -116,7 +116,7 @@ mpt_wait_state(struct mpt_softc *mpt, enum DB_STATE_BITS state)
/* Issue the reset COMMAND to the IOC */
int
mpt_soft_reset(struct mpt_softc *mpt)
mpt_soft_reset(mpt_softc_t *mpt)
{
if (mpt->verbose) {
device_printf(mpt->dev,"soft reset\n");
@ -160,7 +160,7 @@ mpt_soft_reset(struct mpt_softc *mpt)
* processors in the chip.
*/
void
mpt_hard_reset(struct mpt_softc *mpt)
mpt_hard_reset(mpt_softc_t *mpt)
{
/* This extra read comes for the Linux source
* released by LSI. It's function is undocumented!
@ -204,7 +204,7 @@ mpt_hard_reset(struct mpt_softc *mpt)
* fouls up the PCI configuration registers.
*/
int
mpt_reset(struct mpt_softc *mpt)
mpt_reset(mpt_softc_t *mpt)
{
int ret;
@ -225,7 +225,7 @@ mpt_reset(struct mpt_softc *mpt)
/* Return a command buffer to the free queue */
void
mpt_free_request(struct mpt_softc *mpt, request_t *req)
mpt_free_request(mpt_softc_t *mpt, request_t *req)
{
if (req == NULL || req != &mpt->requests[req->index]) {
panic("mpt_free_request bad req ptr\n");
@ -238,7 +238,7 @@ mpt_free_request(struct mpt_softc *mpt, request_t *req)
/* Get a command buffer from the free queue */
request_t *
mpt_get_request(struct mpt_softc *mpt)
mpt_get_request(mpt_softc_t *mpt)
{
request_t *req;
req = SLIST_FIRST(&mpt->request_free_list);
@ -257,7 +257,7 @@ mpt_get_request(struct mpt_softc *mpt)
/* Pass the command to the IOC */
void
mpt_send_cmd(struct mpt_softc *mpt, request_t *req)
mpt_send_cmd(mpt_softc_t *mpt, request_t *req)
{
req->sequence = mpt->sequence++;
if (mpt->verbose > 1) {
@ -285,14 +285,14 @@ mpt_send_cmd(struct mpt_softc *mpt, request_t *req)
* finished processing it.
*/
void
mpt_free_reply(struct mpt_softc *mpt, u_int32_t ptr)
mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr)
{
mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
}
/* Get a reply from the IOC */
u_int32_t
mpt_pop_reply_queue(struct mpt_softc *mpt)
mpt_pop_reply_queue(mpt_softc_t *mpt)
{
return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
}
@ -304,7 +304,7 @@ mpt_pop_reply_queue(struct mpt_softc *mpt)
* commands such as device/bus reset as specified by LSI.
*/
int
mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd)
mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd)
{
int i;
u_int32_t data, *data32;
@ -365,7 +365,7 @@ mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd)
/* Get the response from the handshake register */
int
mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply)
mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply)
{
int left, reply_left;
u_int16_t *data16;
@ -436,9 +436,8 @@ mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply)
return (0);
}
/* Get API statistics from the chip */
static int
mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp)
mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp)
{
MSG_IOC_FACTS f_req;
int error;
@ -453,6 +452,23 @@ mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp)
return (error);
}
static int
mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp)
{
MSG_PORT_FACTS f_req;
int error;
/* XXX: Only getting PORT FACTS for Port 0 */
bzero(&f_req, sizeof f_req);
f_req.Function = MPI_FUNCTION_PORT_FACTS;
f_req.MsgContext = 0x12071943;
error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
if (error)
return(error);
error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
return (error);
}
/*
* Send the initialization request. This is where we specify how many
* SCSI busses and how many devices per bus we wish to emulate.
@ -460,7 +476,7 @@ mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp)
* frames from the IOC that we will be allocating.
*/
static int
mpt_send_ioc_init(struct mpt_softc *mpt, u_int32_t who)
mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
{
int error = 0;
MSG_IOC_INIT init;
@ -486,9 +502,446 @@ mpt_send_ioc_init(struct mpt_softc *mpt, u_int32_t who)
return (error);
}
/* Send the port enable to allow the IOC to join the FC loop */
/*
* Utiltity routine to read configuration headers and pages
*/
static int
mpt_send_port_enable(struct mpt_softc *mpt, int port)
mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *);
static int
mpt_read_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *);
static int
mpt_write_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *);
static int
mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
int PageAddress, fCONFIG_PAGE_HEADER *rslt)
{
int count;
request_t *req;
MSG_CONFIG *cfgp;
MSG_CONFIG_REPLY *reply;
req = mpt_get_request(mpt);
cfgp = req->req_vbuf;
bzero(cfgp, sizeof *cfgp);
cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfgp->Function = MPI_FUNCTION_CONFIG;
cfgp->Header.PageNumber = (U8) PageNumber;
cfgp->Header.PageType = (U8) PageType;
cfgp->PageAddress = PageAddress;
MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
(MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
cfgp->MsgContext = req->index | 0x80000000;
mpt_check_doorbell(mpt);
mpt_send_cmd(mpt, req);
count = 0;
do {
DELAY(500);
mpt_intr(mpt);
if (++count == 1000) {
device_printf(mpt->dev, "read_cfg_header timed out\n");
return (-1);
}
} while (req->debug == REQ_ON_CHIP);
reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
device_printf(mpt->dev,
"mpt_read_cfg_header: Config Info Status %x\n",
reply->IOCStatus);
return (-1);
}
bcopy(&reply->Header, rslt, sizeof (fCONFIG_PAGE_HEADER));
mpt_free_reply(mpt, (req->sequence << 1));
mpt_free_request(mpt, req);
return (0);
}
#define CFG_DATA_OFF 40
static int
mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
{
int count;
request_t *req;
SGE_SIMPLE32 *se;
MSG_CONFIG *cfgp;
size_t amt;
MSG_CONFIG_REPLY *reply;
req = mpt_get_request(mpt);
cfgp = req->req_vbuf;
amt = (cfgp->Header.PageLength * sizeof (uint32_t));
bzero(cfgp, sizeof *cfgp);
cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
cfgp->Function = MPI_FUNCTION_CONFIG;
cfgp->Header = *hdr;
cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
cfgp->PageAddress = PageAddress;
se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
se->Address = req->req_pbuf + CFG_DATA_OFF;
MPI_pSGE_SET_LENGTH(se, amt);
MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
MPI_SGE_FLAGS_END_OF_LIST));
cfgp->MsgContext = req->index | 0x80000000;
mpt_check_doorbell(mpt);
mpt_send_cmd(mpt, req);
count = 0;
do {
DELAY(500);
mpt_intr(mpt);
if (++count == 1000) {
device_printf(mpt->dev, "read_cfg_page timed out\n");
return (-1);
}
} while (req->debug == REQ_ON_CHIP);
reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
device_printf(mpt->dev,
"mpt_read_cfg_page: Config Info Status %x\n",
reply->IOCStatus);
return (-1);
}
mpt_free_reply(mpt, (req->sequence << 1));
bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
BUS_DMASYNC_POSTREAD);
if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
cfgp->Header.PageNumber == 0) {
amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
cfgp->Header.PageNumber == 1) {
amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
cfgp->Header.PageNumber == 2) {
amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
cfgp->Header.PageNumber == 0) {
amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
cfgp->Header.PageNumber == 1) {
amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
}
bcopy(((caddr_t)req->req_vbuf)+CFG_DATA_OFF, hdr, amt);
mpt_free_request(mpt, req);
return (0);
}
static int
mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
{
int count, hdr_attr;
request_t *req;
SGE_SIMPLE32 *se;
MSG_CONFIG *cfgp;
size_t amt;
MSG_CONFIG_REPLY *reply;
req = mpt_get_request(mpt);
cfgp = req->req_vbuf;
bzero(cfgp, sizeof *cfgp);
hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
device_printf(mpt->dev, "page type 0x%x not changeable\n",
hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
return (-1);
}
hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
amt = (cfgp->Header.PageLength * sizeof (uint32_t));
cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfgp->Function = MPI_FUNCTION_CONFIG;
cfgp->Header = *hdr;
cfgp->PageAddress = PageAddress;
se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
se->Address = req->req_pbuf + CFG_DATA_OFF;
MPI_pSGE_SET_LENGTH(se, amt);
MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
cfgp->MsgContext = req->index | 0x80000000;
if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
cfgp->Header.PageNumber == 0) {
amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
cfgp->Header.PageNumber == 1) {
amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
cfgp->Header.PageNumber == 2) {
amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
cfgp->Header.PageNumber == 0) {
amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
cfgp->Header.PageNumber == 1) {
amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
}
bcopy(hdr, ((caddr_t)req->req_vbuf)+CFG_DATA_OFF, amt);
mpt_check_doorbell(mpt);
mpt_send_cmd(mpt, req);
count = 0;
do {
DELAY(500);
mpt_intr(mpt);
if (++count == 1000) {
hdr->PageType |= hdr_attr;
device_printf(mpt->dev,
"mpt_write_cfg_page timed out\n");
return (-1);
}
} while (req->debug == REQ_ON_CHIP);
reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
device_printf(mpt->dev,
"mpt_write_cfg_page: Config Info Status %x\n",
reply->IOCStatus);
return (-1);
}
mpt_free_reply(mpt, (req->sequence << 1));
/*
* Restore stripped out attributes
*/
hdr->PageType |= hdr_attr;
mpt_free_request(mpt, req);
return (0);
}
/*
* Read SCSI configuration information
*/
static int
mpt_read_config_info_spi(mpt_softc_t *mpt)
{
int rv, i;
rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
0, &mpt->mpt_port_page0.Header);
if (rv) {
return (-1);
}
if (mpt->verbose > 1) {
device_printf(mpt->dev, "SPI Port Page 0 Header: %x %x %x %x\n",
mpt->mpt_port_page0.Header.PageVersion,
mpt->mpt_port_page0.Header.PageLength,
mpt->mpt_port_page0.Header.PageNumber,
mpt->mpt_port_page0.Header.PageType);
}
rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
0, &mpt->mpt_port_page1.Header);
if (rv) {
return (-1);
}
if (mpt->verbose > 1) {
device_printf(mpt->dev, "SPI Port Page 1 Header: %x %x %x %x\n",
mpt->mpt_port_page1.Header.PageVersion,
mpt->mpt_port_page1.Header.PageLength,
mpt->mpt_port_page1.Header.PageNumber,
mpt->mpt_port_page1.Header.PageType);
}
rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
0, &mpt->mpt_port_page2.Header);
if (rv) {
return (-1);
}
if (mpt->verbose > 1) {
device_printf(mpt->dev, "SPI Port Page 2 Header: %x %x %x %x\n",
mpt->mpt_port_page1.Header.PageVersion,
mpt->mpt_port_page1.Header.PageLength,
mpt->mpt_port_page1.Header.PageNumber,
mpt->mpt_port_page1.Header.PageType);
}
for (i = 0; i < 16; i++) {
rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
0, i, &mpt->mpt_dev_page0[i].Header);
if (rv) {
return (-1);
}
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"SPI Target %d Device Page 0 Header: %x %x %x %x\n",
i, mpt->mpt_dev_page0[i].Header.PageVersion,
mpt->mpt_dev_page0[i].Header.PageLength,
mpt->mpt_dev_page0[i].Header.PageNumber,
mpt->mpt_dev_page0[i].Header.PageType);
}
rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
1, i, &mpt->mpt_dev_page1[i].Header);
if (rv) {
return (-1);
}
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"SPI Target %d Device Page 1 Header: %x %x %x %x\n",
i, mpt->mpt_dev_page1[i].Header.PageVersion,
mpt->mpt_dev_page1[i].Header.PageLength,
mpt->mpt_dev_page1[i].Header.PageNumber,
mpt->mpt_dev_page1[i].Header.PageType);
}
}
/*
* At this point, we don't *have* to fail. As long as we have
* valid config header information, we can (barely) lurch
* along.
*/
rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
if (rv) {
device_printf(mpt->dev, "failed to read SPI Port Page 0\n");
} else if (mpt->verbose > 1) {
device_printf(mpt->dev,
"SPI Port Page 0: Capabilities %x PhysicalInterface %x\n",
mpt->mpt_port_page0.Capabilities,
mpt->mpt_port_page0.PhysicalInterface);
}
rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
if (rv) {
device_printf(mpt->dev, "failed to read SPI Port Page 1\n");
} else if (mpt->verbose > 1) {
device_printf(mpt->dev,
"SPI Port Page 1: Configuration %x OnBusTimerValue %x\n",
mpt->mpt_port_page1.Configuration,
mpt->mpt_port_page1.OnBusTimerValue);
}
rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
if (rv) {
device_printf(mpt->dev, "failed to read SPI Port Page 2\n");
} else if (mpt->verbose > 1) {
device_printf(mpt->dev,
"SPI Port Page 2: Flags %x Settings %x\n",
mpt->mpt_port_page2.PortFlags,
mpt->mpt_port_page2.PortSettings);
for (i = 0; i < 16; i++) {
device_printf(mpt->dev,
"SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x\n",
i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
}
}
for (i = 0; i < 16; i++) {
rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
if (rv) {
device_printf(mpt->dev,
"cannot read SPI Tgt %d Device Page 0\n", i);
continue;
}
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"SPI Tgt %d Page 0: NParms %x Information %x\n",
i, mpt->mpt_dev_page0[i].NegotiatedParameters,
mpt->mpt_dev_page0[i].Information);
}
rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
if (rv) {
device_printf(mpt->dev,
"cannot read SPI Tgt %d Device Page 1\n", i);
continue;
}
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"SPI Tgt %d Page 1: RParms %x Configuration %x\n",
i, mpt->mpt_dev_page1[i].RequestedParameters,
mpt->mpt_dev_page1[i].Configuration);
}
}
return (0);
}
/*
* Validate SPI configuration information.
*
* In particular, validate SPI Port Page 1.
*/
static int
mpt_set_initial_config_spi(mpt_softc_t *mpt)
{
int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
if (mpt->mpt_port_page1.Configuration != pp1val) {
fCONFIG_PAGE_SCSI_PORT_1 tmp;
device_printf(mpt->dev,
"SPI Port Page 1 Config value bad (%x)- should be %x\n",
mpt->mpt_port_page1.Configuration, pp1val);
tmp = mpt->mpt_port_page1;
tmp.Configuration = pp1val;
if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
return (-1);
}
if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
return (-1);
}
if (tmp.Configuration != pp1val) {
device_printf(mpt->dev,
"failed to reset SPI Port Page 1 Config value\n");
return (-1);
}
mpt->mpt_port_page1 = tmp;
}
#if 1
i = i;
#else
for (i = 0; i < 16; i++) {
fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
tmp = mpt->mpt_dev_page1[i];
tmp.RequestedParameters = 0;
tmp.Configuration = 0;
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"Set Tgt %d SPI DevicePage 1 values to %x 0 %x\n",
i, tmp.RequestedParameters, tmp.Configuration);
}
if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
return (-1);
}
if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
return (-1);
}
mpt->mpt_dev_page1[i] = tmp;
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"SPI Tgt %d Page 1: RParm %x Configuration %x\n", i,
mpt->mpt_dev_page1[i].RequestedParameters,
mpt->mpt_dev_page1[i].Configuration);
}
}
#endif
return (0);
}
/*
* Enable IOC port
*/
static int
mpt_send_port_enable(mpt_softc_t *mpt, int port)
{
int count;
request_t *req;
@ -529,7 +982,7 @@ mpt_send_port_enable(struct mpt_softc *mpt, int port)
* instead of the handshake register.
*/
static int
mpt_send_event_request(struct mpt_softc *mpt, int onoff)
mpt_send_event_request(mpt_softc_t *mpt, int onoff)
{
request_t *req;
MSG_EVENT_NOTIFY *enable_req;
@ -557,7 +1010,7 @@ mpt_send_event_request(struct mpt_softc *mpt, int onoff)
* Un-mask the interupts on the chip.
*/
void
mpt_enable_ints(struct mpt_softc *mpt)
mpt_enable_ints(mpt_softc_t *mpt)
{
/* Unmask every thing except door bell int */
mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
@ -567,7 +1020,7 @@ mpt_enable_ints(struct mpt_softc *mpt)
* Mask the interupts on the chip.
*/
void
mpt_disable_ints(struct mpt_softc *mpt)
mpt_disable_ints(mpt_softc_t *mpt)
{
/* Mask all interrupts */
mpt_write(mpt, MPT_OFFSET_INTR_MASK,
@ -576,10 +1029,11 @@ mpt_disable_ints(struct mpt_softc *mpt)
/* (Re)Initialize the chip for use */
int
mpt_init(struct mpt_softc *mpt, u_int32_t who)
mpt_init(mpt_softc_t *mpt, u_int32_t who)
{
int try;
MSG_IOC_FACTS_REPLY facts;
MSG_PORT_FACTS_REPLY pfp;
u_int32_t pptr;
int val;
@ -629,20 +1083,51 @@ mpt_init(struct mpt_softc *mpt, u_int32_t who)
if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
device_printf(mpt->dev, "mpt_get_iocfacts failed\n");
continue;
} else if (mpt->verbose > 1) {
}
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"mpt_get_iocfacts: GlobalCredits=%d BlockSize=%u "
"Request Frame Size %u\n", facts.GlobalCredits,
facts.BlockSize, facts.RequestFrameSize);
}
mpt->mpt_global_credits = facts.GlobalCredits;
mpt->blk_size = facts.BlockSize;
mpt->request_frame_size = facts.RequestFrameSize;
if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
device_printf(mpt->dev, "mpt_get_portfacts failed\n");
continue;
}
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"mpt_get_portfacts: Type %x PFlags %x IID %d\n",
pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID);
}
if (pfp.PortType != MPI_PORTFACTS_PORTTYPE_SCSI &&
pfp.PortType != MPI_PORTFACTS_PORTTYPE_FC) {
device_printf(mpt->dev, "Unsupported Port Type (%x)\n",
pfp.PortType);
return (ENXIO);
}
if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
device_printf(mpt->dev, "initiator role unsupported\n");
return (ENXIO);
}
if (pfp.PortType == MPI_PORTFACTS_PORTTYPE_FC) {
mpt->is_fc = 1;
} else {
mpt->is_fc = 0;
}
mpt->mpt_ini_id = pfp.PortSCSIID;
if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
device_printf(mpt->dev, "mpt_send_ioc_init failed\n");
continue;
} else if (mpt->verbose > 1) {
}
if (mpt->verbose > 1) {
device_printf(mpt->dev, "mpt_send_ioc_init ok\n");
}
@ -650,7 +1135,8 @@ mpt_init(struct mpt_softc *mpt, u_int32_t who)
device_printf(mpt->dev,
"IOC failed to go to run state\n");
continue;
} else if (mpt->verbose > 1) {
}
if (mpt->verbose > 1) {
device_printf(mpt->dev, "IOC now at RUNSTATE\n");
}
@ -667,12 +1153,35 @@ mpt_init(struct mpt_softc *mpt, u_int32_t who)
break;
}
/*
* Enable asynchronous event reporting
*/
mpt_send_event_request(mpt, 1);
/*
* Read set up initial configuration information
* (SPI only for now)
*/
if (mpt->is_fc == 0) {
if (mpt_read_config_info_spi(mpt)) {
return (EIO);
}
if (mpt_set_initial_config_spi(mpt)) {
return (EIO);
}
}
/*
* Now enable the port
*/
if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
device_printf(mpt->dev, "failed to enable port 0\n");
continue;
} else if (mpt->verbose > 1) {
}
if (mpt->verbose > 1) {
device_printf(mpt->dev, "enabled port 0\n");
}

View file

@ -145,33 +145,24 @@ enum _MPT_DIAG_BITS {
#define MPT_CONTEXT_REPLY (0x80000000)
#define MPT_CONTEXT_MASK (~0xE0000000)
#include "dev/mpt/mpilib/mpi_type.h"
#include "dev/mpt/mpilib/mpi.h"
#include "dev/mpt/mpilib/mpi_cnfg.h"
#include "dev/mpt/mpilib/mpi_fc.h"
#include "dev/mpt/mpilib/mpi_init.h"
#include "dev/mpt/mpilib/mpi_ioc.h"
#include "dev/mpt/mpilib/mpi_lan.h"
#include "dev/mpt/mpilib/mpi_targ.h"
#ifdef _KERNEL
int mpt_soft_reset(struct mpt_softc *mpt);
void mpt_hard_reset(struct mpt_softc *mpt);
int mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply);
int mpt_soft_reset(mpt_softc_t *mpt);
void mpt_hard_reset(mpt_softc_t *mpt);
int mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply);
void mpt_send_cmd(struct mpt_softc *mpt, request_t *req);
void mpt_free_reply(struct mpt_softc *mpt, u_int32_t ptr);
void mpt_enable_ints(struct mpt_softc *mpt);
void mpt_disable_ints(struct mpt_softc *mpt);
u_int32_t mpt_pop_reply_queue(struct mpt_softc *mpt);
int mpt_init(struct mpt_softc *mpt, u_int32_t who);
int mpt_reset(struct mpt_softc *mpt);
int mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd);
request_t * mpt_get_request(struct mpt_softc *mpt);
void mpt_free_request(struct mpt_softc *mpt, request_t *req);
void mpt_send_cmd(mpt_softc_t *mpt, request_t *req);
void mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr);
void mpt_enable_ints(mpt_softc_t *mpt);
void mpt_disable_ints(mpt_softc_t *mpt);
u_int32_t mpt_pop_reply_queue(mpt_softc_t *mpt);
int mpt_init(mpt_softc_t *mpt, u_int32_t who);
int mpt_reset(mpt_softc_t *mpt);
int mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd);
request_t * mpt_get_request(mpt_softc_t *mpt);
void mpt_free_request(mpt_softc_t *mpt, request_t *req);
int mpt_intr(void *dummy);
void mpt_check_doorbell(struct mpt_softc* mpt);
void mpt_check_doorbell(mpt_softc_t * mpt);
/* mpt_debug.c functions */
void mpt_print_reply(void *vmsg);
@ -182,6 +173,5 @@ char *mpt_req_state(enum mpt_req_state state);
void mpt_print_scsi_io_request(MSG_SCSI_IO_REQUEST *msg);
void mpt_print_config_request(void *vmsg);
void mpt_print_request(void *vmsg);
#endif /* _KERNEL */
#endif
#endif /* _MPT_H_ */

View file

@ -30,7 +30,7 @@
* Additional Copyright (c) 2002 by Matthew Jacob under same license.
*/
#include <dev/mpt/mpt.h>
#include <dev/mpt/mpt_freebsd.h>
struct Error_Map {
int Error_Code;
@ -324,7 +324,7 @@ mpt_print_ioc_facts(MSG_IOC_FACTS_REPLY *msg)
printf("\tFlags %d\n", msg->Flags);
printf("\tReplyQueueDepth %d\n", msg->ReplyQueueDepth);
printf("\tReqFrameSize 0x%04x\n", msg->RequestFrameSize);
printf("\tFW Version 0x%04x\n", msg->FWVersion);
printf("\tFW Version 0x%08x\n", msg->FWVersion.Word);
printf("\tProduct ID 0x%04x\n", msg->ProductID);
printf("\tCredits 0x%04x\n", msg->GlobalCredits);
printf("\tPorts %d\n", msg->NumberOfPorts);

View file

@ -31,20 +31,13 @@
*/
#include <dev/mpt/mpt_freebsd.h>
#include <dev/mpt/mpt.h>
#include <machine/stdarg.h>
#include <sys/signal.h>
#if 0
static void mpt_cam_async(void *, u_int32_t, struct cam_path *, void *);
static void mpt_intr_enable(void *);
#endif
static void mpt_poll(struct cam_sim *);
static timeout_t mpttimeout;
static void mpt_action(struct cam_sim *, union ccb *);
void
mpt_cam_attach(struct mpt_softc *mpt)
mpt_cam_attach(mpt_softc_t *mpt)
{
struct cam_devq *devq;
struct cam_sim *sim;
@ -52,7 +45,7 @@ mpt_cam_attach(struct mpt_softc *mpt)
mpt->bus = 0;
maxq = (mpt->mpt_global_credits < MPT_MAX_REQUESTS)?
mpt->mpt_global_credits : MPT_MAX_REQUESTS;
mpt->mpt_global_credits : MPT_MAX_REQUESTS;
/*
@ -74,19 +67,10 @@ mpt_cam_attach(struct mpt_softc *mpt)
return;
}
#if 0
mpt->mpt_osinfo.ehook.ich_func = mpt_intr_enable;
mpt->mpt_osinfo.ehook.ich_arg = mpt;
if (config_intrhook_establish(&mpt->mpt_osinfo.ehook) != 0) {
device_printf(mpt->dev,
"could not establish interrupt enable hook\n");
cam_sim_free(sim, TRUE);
return;
}
#endif
/*
* Register exactly the bus.
*/
/* Register exactly one bus */
/* (Duals look like two cards to us) */
if (xpt_bus_register(sim, 0) != CAM_SUCCESS) {
cam_sim_free(sim, TRUE);
return;
@ -98,22 +82,11 @@ mpt_cam_attach(struct mpt_softc *mpt)
cam_sim_free(sim, TRUE);
return;
}
#if 0 /* GJA Don't think we care about lost devices */
struct ccb_setasync csa;
xpt_setup_ccb(&csa.ccb_h, mpt->path, 5);
csa.ccb_h.func_code = XPT_SASYNC_CB;
csa.event_enable = AC_LOST_DEVICE;
csa.callback = mpt_cam_async;
csa.callback_arg = sim;
xpt_action((union ccb *)&csa);
#endif
mpt->sim = sim;
}
void
mpt_cam_detach(struct mpt_softc *mpt)
mpt_cam_detach(mpt_softc_t *mpt)
{
if (mpt->sim != NULL) {
xpt_free_path(mpt->path);
@ -123,59 +96,16 @@ mpt_cam_detach(struct mpt_softc *mpt)
}
}
#if 0
/* Sample routine for processing async events from CAM */
static void
mpt_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
{
struct cam_sim *sim;
struct mpt_softc *mpt;
sim = (struct cam_sim *)cbarg;
mpt = (struct mpt_softc *) cam_sim_softc(sim);
switch (code) {
#if 0 /* GJA */
case AC_LOST_DEVICE:
if (IS_SCSI(mpt)) {
u_int16_t oflags, nflags;
sdparam *sdp = mpt->mpt_param;
int rvf, tgt;
tgt = xpt_path_target_id(path);
rvf = ISP_FW_REVX(mpt->mpt_fwrev);
ISP_LOCK(mpt);
sdp += cam_sim_bus(sim);
mpt->mpt_update |= (1 << cam_sim_bus(sim));
nflags = DPARM_SAFE_DFLT;
if (rvf >= ISP_FW_REV(7, 55, 0) ||
(ISP_FW_REV(4, 55, 0) <= rvf &&
(rvf < ISP_FW_REV(5, 0, 0)))) {
nflags |= DPARM_NARROW | DPARM_ASYNC;
}
oflags = sdp->mpt_devparam[tgt].dev_flags;
sdp->mpt_devparam[tgt].dev_flags = nflags;
sdp->mpt_devparam[tgt].dev_update = 1;
(void) mpt_control(mpt, ISPCTL_UPDATE_PARAMS, NULL);
sdp->mpt_devparam[tgt].dev_flags = oflags;
ISP_UNLOCK(mpt);
}
break;
#endif /* 0 GJA */
default:
device_printf(mpt->dev,
"mpt Async Code 0x%x\n", code);
break;
}
}
#endif
/* This routine is used after a system crash to dump core onto the
* swap device.
*/
static void
mpt_poll(struct cam_sim *sim)
{
mpt_intr((struct mpt_softc *) cam_sim_softc(sim));
mpt_softc_t *mpt = (mpt_softc_t *) cam_sim_softc(sim);
MPT_LOCK(mpt);
mpt_intr(mpt);
MPT_UNLOCK(mpt);
}
/*
@ -186,16 +116,17 @@ static void
mpttimeout(void *arg)
{
request_t *req;
union ccb *ccb = arg;
struct mpt_softc *mpt;
union ccb *ccb = arg;
mpt_softc_t *mpt;
mpt = ccb->ccb_h.ccb_mpt_ptr;
MPT_LOCK(mpt);
req = ccb->ccb_h.ccb_req_ptr;
mpt->timeouts++;
device_printf(mpt->dev, "time out on request index = 0x%02x sequence = 0x%08x\n",
req->index, req->sequence);
device_printf(mpt->dev,
"time out on request index = 0x%02x sequence = 0x%08x\n",
req->index, req->sequence);
mpt_check_doorbell(mpt);
device_printf(mpt->dev, "Status %08X; Mask %08X; Doorbell %08X\n",
mpt_read(mpt, MPT_OFFSET_INTR_STATUS),
@ -212,7 +143,9 @@ mpttimeout(void *arg)
req->ccb = NULL;
ccb->ccb_h.status = CAM_CMD_TIMEOUT;
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
MPTLOCK_2_CAMLOCK(mpt);
xpt_done(ccb);
CAMLOCK_2_MPTLOCK(mpt);
}
/*
@ -225,10 +158,9 @@ mpttimeout(void *arg)
static void
mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
{
int s;
request_t *req;
union ccb *ccb;
struct mpt_softc *mpt;
mpt_softc_t *mpt;
MSG_SCSI_IO_REQUEST *mpt_req;
SGE_SIMPLE32 *se;
@ -258,7 +190,9 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
xpt_done(ccb);
CAMLOCK_2_MPTLOCK(mpt);
mpt_free_request(mpt, req);
MPTLOCK_2_CAMLOCK(mpt);
return;
}
@ -389,18 +323,18 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
}
s = splcam();
/*
* Last time we need to check if this CCB needs to be aborted.
*/
if (ccb->ccb_h.status != CAM_REQ_INPROG) {
if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0)
bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
CAMLOCK_2_MPTLOCK(mpt);
mpt_free_request(mpt, req);
MPTLOCK_2_CAMLOCK(mpt);
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
xpt_done(ccb);
splx(s);
return;
}
@ -412,13 +346,11 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
} else {
callout_handle_init(&ccb->ccb_h.timeout_ch);
}
if (mpt->verbose > 1)
mpt_print_scsi_io_request(mpt_req);
CAMLOCK_2_MPTLOCK(mpt);
mpt_send_cmd(mpt, req);
splx(s);
MPTLOCK_2_CAMLOCK(mpt);
}
/* Convert a CAM SCSI I/O ccb into a MPT request to pass the FC Chip */
@ -436,9 +368,12 @@ mpt_start(union ccb *ccb)
mpt = ccb->ccb_h.ccb_mpt_ptr;
/* Get a request structure off the free list */
CAMLOCK_2_MPTLOCK(mpt);
if ((req = mpt_get_request(mpt)) == NULL) {
MPTLOCK_2_CAMLOCK(mpt);
return (CAM_REQUEUE_REQ);
}
MPTLOCK_2_CAMLOCK(mpt);
/* Link the ccb and the request structure so we can find */
/* the other knowing either the request or the ccb */
@ -580,7 +515,7 @@ mpt_bus_reset(union ccb *ccb)
{
int error;
request_t *req;
struct mpt_softc *mpt;
mpt_softc_t *mpt;
MSG_SCSI_TASK_MGMT *reset_req;
/* Get the pointer for the physical adapter */
@ -630,7 +565,7 @@ mpt_bus_reset(union ccb *ccb)
* Process an asynchronous event from the IOC.
*/
void
mpt_notify(struct mpt_softc *mpt, void *vmsg)
mpt_notify(mpt_softc_t *mpt, void *vmsg, u_int32_t reply)
{
MSG_DEFAULT_REPLY *dmsg = vmsg;
@ -759,6 +694,7 @@ mpt_notify(struct mpt_softc *mpt, void *vmsg)
default:
device_printf(mpt->dev, "Unknown event %X\n", msg->Event);
}
mpt_free_reply(mpt, (reply << 1));
} else if (dmsg->Function == MPI_FUNCTION_PORT_ENABLE) {
MSG_PORT_ENABLE_REPLY *msg = vmsg;
int index = msg->MsgContext & ~0x80000000;
@ -770,6 +706,17 @@ mpt_notify(struct mpt_softc *mpt, void *vmsg)
request_t *req = &mpt->requests[index];
req->debug = REQ_DONE;
}
mpt_free_reply(mpt, (reply << 1));
} else if (dmsg->Function == MPI_FUNCTION_CONFIG) {
MSG_CONFIG_REPLY *msg = vmsg;
int index = msg->MsgContext & ~0x80000000;
if (index >= 0 && index < MPT_MAX_REQUESTS) {
request_t *req = &mpt->requests[index];
req->debug = REQ_DONE;
req->sequence = reply;
} else {
mpt_free_reply(mpt, (reply << 1));
}
} else {
device_printf(mpt->dev, "unknown mpt_notify: %x\n",
dmsg->Function);
@ -777,7 +724,7 @@ mpt_notify(struct mpt_softc *mpt, void *vmsg)
}
void
mpt_done(struct mpt_softc *mpt, u_int32_t reply)
mpt_done(mpt_softc_t *mpt, u_int32_t reply)
{
int index;
request_t *req;
@ -817,8 +764,7 @@ mpt_done(struct mpt_softc *mpt, u_int32_t reply)
/* to process it then free it */
if ((index & 0x80000000) != 0) {
if (mpt_reply != NULL) {
mpt_notify(mpt, mpt_reply);
mpt_free_reply(mpt, (reply << 1));
mpt_notify(mpt, mpt_reply, reply);
} else {
device_printf(mpt->dev,
"mpt_done: index 0x%x, NULL reply\n", index);
@ -1016,7 +962,9 @@ mpt_done(struct mpt_softc *mpt, u_int32_t reply)
if ((mpt_reply->MsgFlags & 0x80) == 0)
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
MPTLOCK_2_CAMLOCK(mpt);
xpt_done(ccb);
CAMLOCK_2_MPTLOCK(mpt);
done:
/* If IOC done with this request free it up */
@ -1032,12 +980,12 @@ static void
mpt_action(struct cam_sim *sim, union ccb *ccb)
{
int tgt, error;
struct mpt_softc *mpt;
mpt_softc_t *mpt;
struct ccb_trans_settings *cts;
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n"));
mpt = (struct mpt_softc *)cam_sim_softc(sim);
mpt = (mpt_softc_t *)cam_sim_softc(sim);
ccb->ccb_h.ccb_mpt_ptr = mpt;
@ -1045,16 +993,15 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
case XPT_RESET_BUS:
if (mpt->verbose > 1)
device_printf(mpt->dev, "XPT_RESET_BUS\n");
CAMLOCK_2_MPTLOCK(mpt);
error = mpt_bus_reset(ccb);
MPTLOCK_2_CAMLOCK(mpt);
switch (error) {
case CAM_REQ_INPROG:
ccb->ccb_h.status |= CAM_SIM_QUEUED;
break;
case CAM_REQUEUE_REQ:
/* if (mpt->mpt_osinfo.simqfrozen == 0) */
{
xpt_freeze_simq(sim, 1);
}
xpt_freeze_simq(sim, 1);
ccb->ccb_h.status = CAM_REQUEUE_REQ;
xpt_done(ccb);
break;
@ -1090,20 +1037,14 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
}
ccb->csio.scsi_status = SCSI_STATUS_OK;
/* XXX GJA MPT_LOCK(mpt); */
error = mpt_start(ccb);
/* XXX GJA MPT_UNLOCK(mpt); */
switch (error) {
case CAM_REQ_INPROG:
ccb->ccb_h.status |= CAM_SIM_QUEUED;
break;
case CAM_REQUEUE_REQ:
/* if (mpt->mpt_osinfo.simqfrozen == 0) */
{
xpt_freeze_simq(sim, 1);
}
/* mpt->mpt_osinfo.simqfrozen |= SIMQFRZ_RESOURCE; */
xpt_freeze_simq(sim, 1);
ccb->ccb_h.status = CAM_REQUEUE_REQ;
xpt_done(ccb);
break;
@ -1114,21 +1055,36 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
break;
default:
device_printf(mpt->dev, "What's this? 0x%x at %d in file %s\n",
error, __LINE__, __FILE__);
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
xpt_done(ccb);
}
break;
case XPT_ABORT:
/* Probably ought to impliment this but no one actualy */
/* uses it for anything worthwile. XXX GJA */
/*
* XXX: Need to implement
*/
ccb->ccb_h.status = CAM_UA_ABORT;
xpt_done(ccb);
break;
#ifdef CAM_NEW_TRAN_CODE
#define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS)
#else
#define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS)
#endif
#define DP_DISC 0x1
#define DP_TQING 0x2
#define DP_WIDE 0x4
case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */
cts = &ccb->cts;
if (!IS_CURRENT_SETTINGS(cts)) {
ccb->ccb_h.status = CAM_REQ_INVALID;
xpt_done(ccb);
break;
}
/* XXX: need to implement */
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@ -1136,19 +1092,136 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
case XPT_GET_TRAN_SETTINGS:
cts = &ccb->cts;
tgt = cts->ccb_h.target_id;
/*
* a lot of normal SCSI things don't make sense.
*/
cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
/*
* How do you measure the width of a high
* speed serial bus? Well, in bytes.
*
* Offset and period make no sense, though, so we set
* (above) a 'base' transfer speed to be gigabit.
*/
cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
if (mpt->is_fc) {
#ifndef CAM_NEW_TRAN_CODE
/*
* a lot of normal SCSI things don't make sense.
*/
cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
/*
* How do you measure the width of a high
* speed serial bus? Well, in bytes.
*
* Offset and period make no sense, though, so we set
* (above) a 'base' transfer speed to be gigabit.
*/
cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
#else
struct ccb_trans_settings_fc *fc =
&cts->xport_specific.fc;
cts->protocol = PROTO_SCSI;
cts->protocol_version = SCSI_REV_2;
cts->transport = XPORT_FC;
cts->transport_version = 0;
fc->valid = CTS_FC_VALID_SPEED;
fc->bitrate = 100000; /* XXX: Need for 2Gb/s */
/* XXX: need a port database for each target */
#endif
} else {
#ifdef CAM_NEW_TRAN_CODE
struct ccb_trans_settings_scsi *scsi =
&cts->proto_specific.scsi;
struct ccb_trans_settings_spi *spi =
&cts->xport_specific.spi;
#endif
u_int8_t dval, pval, oval;
if (IS_CURRENT_SETTINGS(cts)) {
dval = 0;
if (mpt->mpt_dev_page0[tgt].
NegotiatedParameters &
MPI_SCSIDEVPAGE0_NP_WIDE)
dval |= DP_WIDE;
if (mpt->mpt_port_page2.DeviceSettings[tgt].
DeviceFlags &
MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE)
dval |= DP_DISC;
if (mpt->mpt_port_page2.DeviceSettings[tgt].
DeviceFlags &
MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE)
dval |= DP_TQING;
oval = (mpt->mpt_dev_page0[tgt].
NegotiatedParameters >> 16);
pval = (mpt->mpt_dev_page0[tgt].
NegotiatedParameters >> 8);
} else {
/*
* XXX: Fix wrt NVRAM someday. Attempts
* XXX: to read port page2 device data
* XXX: just returns zero in these areas.
*/
dval = DP_WIDE|DP_DISC|DP_TQING;
oval = (mpt->mpt_port_page0.Capabilities >> 16);
pval = (mpt->mpt_port_page0.Capabilities >> 8);
}
#ifndef CAM_NEW_TRAN_CODE
cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
if (dval & DP_DISC) {
cts->flags |= CCB_TRANS_DISC_ENB;
}
if (dval & DP_TQING) {
cts->flags |= CCB_TRANS_TAG_ENB;
}
if (dval & DP_WIDE) {
cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
} else {
cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
}
cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
if (oval) {
cts->sync_period = pval;
cts->sync_offset = oval;
cts->valid |=
CCB_TRANS_SYNC_RATE_VALID |
CCB_TRANS_SYNC_OFFSET_VALID;
}
#else
cts->protocol = PROTO_SCSI;
cts->protocol_version = SCSI_REV_2;
cts->transport = XPORT_SPI;
cts->transport_version = 2;
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
if (dval & DP_DISC) {
spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
}
if (dval & DP_TQING) {
scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
}
if (oval && pval) {
spi->sync_offset = oval;
spi->sync_period = pval;
spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
spi->valid |= CTS_SPI_VALID_SYNC_RATE;
}
spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
if (dval & DP_WIDE) {
spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
} else {
spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
}
if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
scsi->valid = CTS_SCSI_VALID_TQ;
spi->valid |= CTS_SPI_VALID_DISC;
} else {
scsi->valid = 0;
}
#endif
if (mpt->verbose > 1) {
device_printf(mpt->dev,
"GET %s targ %d flags %x off %x per %x\n",
IS_CURRENT_SETTINGS(cts)? "ACTIVE" :
"NVRAM", tgt, dval, oval, pval);
}
}
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@ -1161,10 +1234,6 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
ccg = &ccb->ccg;
if (ccg->block_size == 0) {
device_printf(mpt->dev, "%d.%d XPT_CALC_GEOMETRY block size 0?\n",
ccg->ccb_h.target_id,
ccg->ccb_h.target_lun);
ccb->ccb_h.status = CAM_REQ_INVALID;
xpt_done(ccb);
break;
@ -1200,7 +1269,7 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
cpi->base_transfer_speed = 100000;
cpi->hba_inquiry = PI_TAG_ABLE;
} else {
cpi->initiator_id = 7; /* XXX */
cpi->initiator_id = mpt->mpt_ini_id;
cpi->base_transfer_speed = 3300;
cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
cpi->hba_misc = 0;

View file

@ -31,15 +31,22 @@
#ifndef _MPT_FREEBSD_H_
#define _MPT_FREEBSD_H_
#include <sys/ioccom.h>
#ifdef _KERNEL
/* #define RELENG_4 1 */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/endian.h>
#include <sys/kernel.h>
#include <sys/queue.h>
#ifdef RELENG_4
#include <sys/malloc.h>
#else
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#endif
#include <sys/proc.h>
#include <sys/bus.h>
@ -58,9 +65,50 @@
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
#include "opt_ddb.h"
#include "dev/mpt/mpilib/mpi_type.h"
#include "dev/mpt/mpilib/mpi.h"
#include "dev/mpt/mpilib/mpi_cnfg.h"
#include "dev/mpt/mpilib/mpi_fc.h"
#include "dev/mpt/mpilib/mpi_init.h"
#include "dev/mpt/mpilib/mpi_ioc.h"
#include "dev/mpt/mpilib/mpi_lan.h"
#include "dev/mpt/mpilib/mpi_targ.h"
#define INLINE __inline
#ifdef RELENG_4
#define MPT_IFLAGS INTR_TYPE_CAM
#define MPT_LOCK(mpt) mpt_lockspl(mpt)
#define MPT_UNLOCK(mpt) mpt_unlockspl(mpt)
#define MPTLOCK_2_CAMLOCK MPT_UNLOCK
#define CAMLOCK_2_MPTLOCK(mpt) MPT_LOCK
#define MPT_LOCK_SETUP(mpt)
#define MPT_LOCK_DESTROY(mpt)
#else
#define MPT_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE
#define MPT_LOCK_SETUP(mpt) \
mtx_init(&mpt->mpt_lock, "mpt", NULL, MTX_DEF); \
mpt->mpt_locksetup = 1
#define MPT_LOCK_DESTROY(mpt) \
if (mpt->mpt_locksetup) { \
mtx_destroy(&mpt->mpt_lock); \
mpt->mpt_locksetup = 0; \
}
#define MPT_LOCK(mpt) mtx_lock(&(mpt)->mpt_lock)
#define MPT_UNLOCK(mpt) mtx_unlock(&(mpt)->mpt_lock)
#define MPTLOCK_2_CAMLOCK(mpt) \
mtx_unlock(&(mpt)->mpt_lock); mtx_lock(&Giant)
#define CAMLOCK_2_MPTLOCK(mpt) \
mtx_unlock(&Giant); mtx_lock(&(mpt)->mpt_lock)
#endif
/* Max MPT Reply we are willing to accept (must be power of 2) */
#define MPT_REPLY_SIZE 128
@ -112,17 +160,16 @@ enum mpt_req_state {
REQ_FREE, REQ_IN_PROGRESS, REQ_TIMEOUT, REQ_ON_CHIP, REQ_DONE
};
typedef struct req_entry {
u_int16_t index; /* Index of this entry */
union ccb *ccb; /* Request that generated this command */
void *req_vbuf; /* Virtual Address of Entry */
void *sense_vbuf; /* Virtual Address of sense data */
u_int32_t req_pbuf; /* Physical Address of Entry */
u_int32_t sense_pbuf; /* Physical Address of sense data */
bus_dmamap_t dmap; /* DMA map for data buffer */
SLIST_ENTRY(req_entry) link; /* Pointer to next in list */
enum mpt_req_state debug; /* Debuging */
u_int32_t sequence; /* Sequence Number */
u_int16_t index; /* Index of this entry */
union ccb *ccb; /* CAM request */
void *req_vbuf; /* Virtual Address of Entry */
void *sense_vbuf; /* Virtual Address of sense data */
u_int32_t req_pbuf; /* Physical Address of Entry */
u_int32_t sense_pbuf; /* Physical Address of sense data */
bus_dmamap_t dmap; /* DMA map for data buffer */
SLIST_ENTRY(req_entry) link; /* Pointer to next in list */
enum mpt_req_state debug; /* Debugging */
u_int32_t sequence; /* Sequence Number */
} request_t;
@ -138,98 +185,162 @@ struct mpt_pci_cfg {
u_int32_t PMCSR;
};
struct mpt_softc {
device_t dev;
int unit;
struct mtx lock;
/* Operational flags, set during initialization */
int verbose; /* print debug messages */
struct resource *pci_irq; /* Interrupt map for chip */
void *ih; /* Interupt handle */
/* First Memory Region (Device MEM) */
struct resource *pci_reg; /* Register map for chip */
int pci_reg_id; /* Resource ID */
bus_space_tag_t pci_st; /* Bus tag for registers */
bus_space_handle_t pci_sh; /* Bus handle for registers */
vm_offset_t pci_pa; /* Physical Address */
/* Second Memory Region (Diagnostic memory window) */
/* (only used for diagnostic purposes) */
struct resource *pci_mem; /* Register map for chip */
int pci_mem_id; /* Resource ID */
bus_space_tag_t pci_mst; /* Bus tag for registers */
bus_space_handle_t pci_msh; /* Bus handle for registers */
/* DMA Memory for IOCTLs */
void *ioctl_mem_va; /* Virtual Addr */
u_int32_t ioctl_mem_pa; /* Physical Addr */
bus_dmamap_t ioctl_mem_map; /* DMA map for buffer */
bus_dma_tag_t ioctl_mem_tag; /* DMA tag for memory alloc */
int open; /* only allow one open at a time */
bus_dma_tag_t parent_dmat; /* DMA tag for parent PCI bus */
bus_dma_tag_t reply_dmat; /* DMA tag for reply memory */
bus_dmamap_t reply_dmap; /* DMA map for reply memory */
char *reply; /* Virtual address of reply memory */
u_int32_t reply_phys; /* Physical address of reply memory */
u_int32_t
: 29,
typedef struct mpt_softc {
device_t dev;
#ifdef RELENG_4
int mpt_splsaved;
u_int32_t mpt_islocked;
#else
struct mtx mpt_lock;
#endif
u_int32_t : 16,
unit : 8,
verbose : 3,
: 1,
mpt_locksetup : 1,
disabled : 1,
is_fc : 1,
bus : 1; /* FC929/1030 have two busses */
u_int32_t blk_size; /* Block size transfers to IOC */
u_int16_t mpt_global_credits;
u_int16_t request_frame_size;
/*
* IOC Facts
*/
u_int16_t mpt_global_credits;
u_int16_t request_frame_size;
u_int8_t mpt_max_devices;
u_int8_t mpt_max_buses;
bus_dma_tag_t buffer_dmat; /* DMA tag for mapping data buffers */
/*
* Port Facts
*/
u_int16_t mpt_ini_id;
bus_dma_tag_t request_dmat; /* DMA tag for request memroy */
bus_dmamap_t request_dmap; /* DMA map for request memroy */
char *request; /* Virtual address of Request memory */
u_int32_t request_phys; /* Physical address of Request memory */
request_t requests[MPT_MAX_REQUESTS];
/*
* Device Configuration Information
*/
union {
struct mpt_spi_cfg {
fCONFIG_PAGE_SCSI_PORT_0 _port_page0;
fCONFIG_PAGE_SCSI_PORT_1 _port_page1;
fCONFIG_PAGE_SCSI_PORT_2 _port_page2;
fCONFIG_PAGE_SCSI_DEVICE_0 _dev_page0[16];
fCONFIG_PAGE_SCSI_DEVICE_1 _dev_page1[16];
uint16_t _tagmask;
uint16_t _update_params0;
uint16_t _update_params1;
} spi;
#define mpt_port_page0 cfg.spi._port_page0
#define mpt_port_page1 cfg.spi._port_page1
#define mpt_port_page2 cfg.spi._port_page2
#define mpt_dev_page0 cfg.spi._dev_page0
#define mpt_dev_page1 cfg.spi._dev_page1
#define mpt_tagmask cfg.spi._tagmask
#define mpt_update_params0 cfg.spi._update_params0
#define mpt_update_params1 cfg.spi._update_params1
struct mpi_fc_cfg {
u_int8_t nada;
} fc;
} cfg;
/*
* PCI Hardware info
*/
struct resource * pci_irq; /* Interrupt map for chip */
void * ih; /* Interupt handle */
struct mpt_pci_cfg pci_cfg; /* saved PCI conf registers */
/*
* DMA Mapping Stuff
*/
struct resource * pci_reg; /* Register map for chip */
int pci_reg_id; /* Resource ID */
bus_space_tag_t pci_st; /* Bus tag for registers */
bus_space_handle_t pci_sh; /* Bus handle for registers */
vm_offset_t pci_pa; /* Physical Address */
bus_dma_tag_t parent_dmat; /* DMA tag for parent PCI bus */
bus_dma_tag_t reply_dmat; /* DMA tag for reply memory */
bus_dmamap_t reply_dmap; /* DMA map for reply memory */
char * reply; /* KVA of reply memory */
u_int32_t reply_phys; /* BusAddr of reply memory (XXX Wrong) */
bus_dma_tag_t buffer_dmat; /* DMA tag for buffers */
bus_dma_tag_t request_dmat; /* DMA tag for request memroy */
bus_dmamap_t request_dmap; /* DMA map for request memroy */
char * request; /* KVA of Request memory */
u_int32_t request_phys; /* BusADdr of request memory (XXX WRONG) */
/*
* CAM && Software Management
*/
request_t requests[MPT_MAX_REQUESTS];
SLIST_HEAD(req_queue, req_entry) request_free_list;
struct cam_sim *sim;
struct cam_path *path;
struct cam_sim * sim;
struct cam_path * path;
u_int32_t sequence; /* Sequence Number */
u_int32_t timeouts; /* timeout count */
u_int32_t success; /* timeout successes afer timeout */
u_int32_t sequence; /* Sequence Number */
u_int32_t timeouts; /* timeout count */
u_int32_t success; /* successes afer timeout */
/* Opposing port in a 929, or NULL */
struct mpt_softc *mpt2;
/* Opposing port in a 929 or 1030, or NULL */
struct mpt_softc * mpt2;
/* Saved values for the PCI configuration registers */
struct mpt_pci_cfg pci_cfg;
};
} mpt_softc_t;
#include <dev/mpt/mpt.h>
static INLINE void mpt_write(mpt_softc_t *, size_t, u_int32_t);
static INLINE u_int32_t mpt_read(mpt_softc_t *, int);
static INLINE void
mpt_write(struct mpt_softc *mpt, size_t offset, u_int32_t val)
mpt_write(mpt_softc_t *mpt, size_t offset, u_int32_t val)
{
bus_space_write_4(mpt->pci_st, mpt->pci_sh, offset, val);
}
static INLINE u_int32_t
mpt_read(struct mpt_softc *mpt, int offset)
mpt_read(mpt_softc_t *mpt, int offset)
{
return bus_space_read_4(mpt->pci_st, mpt->pci_sh, offset);
return (bus_space_read_4(mpt->pci_st, mpt->pci_sh, offset));
}
void mpt_cam_attach(struct mpt_softc *mpt);
void mpt_cam_detach(struct mpt_softc *mpt);
void mpt_done(struct mpt_softc *mpt, u_int32_t reply);
void mpt_notify(struct mpt_softc *mpt, void *vmsg);
void mpt_cam_attach(mpt_softc_t *);
void mpt_cam_detach(mpt_softc_t *);
void mpt_done(mpt_softc_t *, u_int32_t);
void mpt_notify(mpt_softc_t *, void *, u_int32_t);
void mpt_set_config_regs(mpt_softc_t *);
/* mpt_pci.c declarations */
void mpt_set_config_regs(struct mpt_softc *mpt);
#ifdef RELENG_4
static INLINE void mpt_lockspl(mpt_softc_t *);
static INLINE void mpt_unlockspl(mpt_softc_t *);
static INLINE void
mpt_lockspl(mpt_softc_t *mpt)
{
int s = splcam();
if (mpt->mpt_islocked++ == 0) {
mpt->mpt_splsaved = s;
} else {
splx(s);
}
}
static INLINE void
mpt_unlockspl(mpt_softc_t *mpt)
{
if (mpt->mpt_islocked) {
if (--mpt->mpt_islocked == 0) {
splx(mpt->mpt_splsaved);
}
}
}
#endif
#endif /*_KERNEL */
#endif /* _MPT_FREEBSD_H */

View file

@ -34,11 +34,9 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
@ -47,8 +45,8 @@
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <dev/mpt/mpt.h>
#include <dev/mpt/mpt_freebsd.h>
#ifndef PCI_VENDOR_LSI
@ -74,12 +72,13 @@
static int mpt_probe(device_t);
static int mpt_attach(device_t);
static void mpt_free_bus_resources(struct mpt_softc *mpt);
static void mpt_free_bus_resources(mpt_softc_t *mpt);
static int mpt_detach(device_t);
static int mpt_shutdown(device_t);
static int mpt_dma_mem_alloc(struct mpt_softc *mpt);
static void mpt_dma_mem_free(struct mpt_softc *mpt);
static void mpt_read_config_regs(struct mpt_softc *mpt);
static int mpt_dma_mem_alloc(mpt_softc_t *mpt);
static void mpt_dma_mem_free(mpt_softc_t *mpt);
static void mpt_read_config_regs(mpt_softc_t *mpt);
static void mpt_pci_intr(void *);
static device_method_t mpt_methods[] = {
/* Device interface */
@ -91,7 +90,7 @@ static device_method_t mpt_methods[] = {
};
static driver_t mpt_driver = {
"mpt", mpt_methods, sizeof (struct mpt_softc)
"mpt", mpt_methods, sizeof (mpt_softc_t)
};
static devclass_t mpt_devclass;
DRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, 0, 0);
@ -101,7 +100,7 @@ int
mpt_intr(void *dummy)
{
u_int32_t reply;
struct mpt_softc *mpt = (struct mpt_softc *)dummy;
mpt_softc_t *mpt = (mpt_softc_t *)dummy;
reply = mpt_pop_reply_queue(mpt);
while (reply != MPT_REPLY_EMPTY) {
@ -149,7 +148,7 @@ mpt_probe(device_t dev)
#ifdef RELENG_4
static void
mpt_set_options(struct mpt_softc *mpt)
mpt_set_options(mpt_softc_t *mpt)
{
int bitmap;
@ -171,7 +170,7 @@ mpt_set_options(struct mpt_softc *mpt)
}
#else
static void
mpt_set_options(struct mpt_softc *mpt)
mpt_set_options(mpt_softc_t *mpt)
{
int tval;
@ -194,15 +193,15 @@ mpt_attach(device_t dev)
{
int iqd;
u_int32_t data, cmd;
struct mpt_softc *mpt;
mpt_softc_t *mpt;
/* Allocate the softc structure */
mpt = (struct mpt_softc*) device_get_softc(dev);
mpt = (mpt_softc_t*) device_get_softc(dev);
if (mpt == NULL) {
device_printf(dev, "cannot allocate softc\n");
return (ENOMEM);
}
bzero(mpt, sizeof (struct mpt_softc));
bzero(mpt, sizeof (mpt_softc_t));
switch ((pci_get_device(dev) & ~1)) {
case PCI_PRODUCT_LSI_FC909:
case PCI_PRODUCT_LSI_FC929:
@ -243,7 +242,7 @@ mpt_attach(device_t dev)
if ((pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC929) {
/* Yes; is the previous device the counterpart? */
if (mpt->unit) {
mpt->mpt2 = (struct mpt_softc *)
mpt->mpt2 = (mpt_softc_t *)
devclass_get_softc(mpt_devclass, mpt->unit-1);
if ((mpt->mpt2->mpt2 == NULL)
@ -285,13 +284,14 @@ mpt_attach(device_t dev)
}
/* Register the interrupt handler */
if (bus_setup_intr(dev, mpt->pci_irq,
INTR_TYPE_CAM, (void (*)(void *))mpt_intr,
if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, mpt_pci_intr,
mpt, &mpt->ih)) {
device_printf(dev, "could not setup interrupt\n");
goto bad;
}
MPT_LOCK_SETUP(mpt);
/* Disable interrupts at the part */
mpt_disable_ints(mpt);
@ -301,27 +301,35 @@ mpt_attach(device_t dev)
goto bad;
}
/* Initialize character device */
/* currently closed */
mpt->open = 0;
/*
* Save the PCI config register values
*
* Hard resets are known to screw up the BAR for diagnostic
* memory accesses (Mem1).
*
* Using Mem1 is known to make the chip stop responding to
* configuration space transfers, so we need to save it now
*/
/* Save the PCI config register values */
/* Hard resets are known to screw up the BAR for diagnostic
memory accesses (Mem1). */
/* Using Mem1 is known to make the chip stop responding to
configuration space transfers, so we need to save it now */
mpt_read_config_regs(mpt);
/* Initialize the hardware */
if (mpt->disabled == 0) {
if (mpt_init(mpt, MPT_DB_INIT_HOST) != 0)
MPT_LOCK(mpt);
if (mpt_init(mpt, MPT_DB_INIT_HOST) != 0) {
MPT_UNLOCK(mpt);
goto bad;
}
/* Attach to CAM */
/*
* Attach to CAM
*/
MPTLOCK_2_CAMLOCK(mpt);
mpt_cam_attach(mpt);
CAMLOCK_2_MPTLOCK(mpt);
MPT_UNLOCK(mpt);
}
/* Done */
return (0);
bad:
@ -334,11 +342,11 @@ mpt_attach(device_t dev)
return (0);
}
/******************************************************************************
/*
* Free bus resources
*/
static void
mpt_free_bus_resources(struct mpt_softc *mpt)
mpt_free_bus_resources(mpt_softc_t *mpt)
{
if (mpt->ih) {
bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih);
@ -355,23 +363,18 @@ mpt_free_bus_resources(struct mpt_softc *mpt)
mpt->pci_reg);
mpt->pci_reg = 0;
}
if (mpt->pci_mem) {
bus_release_resource(mpt->dev, SYS_RES_MEMORY, mpt->pci_mem_id,
mpt->pci_mem);
mpt->pci_mem = 0;
}
MPT_LOCK_DESTROY(mpt);
}
/******************************************************************************
/*
* Disconnect ourselves from the system.
*/
static int
mpt_detach(device_t dev)
{
struct mpt_softc *mpt;
mpt = (struct mpt_softc*) device_get_softc(dev);
mpt_softc_t *mpt;
mpt = (mpt_softc_t*) device_get_softc(dev);
device_printf(mpt->dev,"mpt_detach!\n");
@ -386,14 +389,14 @@ mpt_detach(device_t dev)
}
/******************************************************************************
/*
* Disable the hardware
*/
static int
mpt_shutdown(device_t dev)
{
struct mpt_softc *mpt;
mpt = (struct mpt_softc*) device_get_softc(dev);
mpt_softc_t *mpt;
mpt = (mpt_softc_t*) device_get_softc(dev);
if (mpt) {
mpt_reset(mpt);
@ -403,7 +406,7 @@ mpt_shutdown(device_t dev)
struct imush {
struct mpt_softc *mpt;
mpt_softc_t *mpt;
int error;
u_int32_t phys;
};
@ -418,7 +421,7 @@ mpt_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error)
static int
mpt_dma_mem_alloc(struct mpt_softc *mpt)
mpt_dma_mem_alloc(mpt_softc_t *mpt)
{
int i, error;
u_char *vptr;
@ -551,7 +554,7 @@ mpt_dma_mem_alloc(struct mpt_softc *mpt)
/* Deallocate memory that was allocated by mpt_dma_mem_alloc
*/
static void
mpt_dma_mem_free(struct mpt_softc *mpt)
mpt_dma_mem_free(mpt_softc_t *mpt)
{
int i;
@ -581,7 +584,7 @@ mpt_dma_mem_free(struct mpt_softc *mpt)
/* Reads modifiable (via PCI transactions) config registers */
static void
mpt_read_config_regs(struct mpt_softc *mpt)
mpt_read_config_regs(mpt_softc_t *mpt)
{
mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2);
mpt->pci_cfg.LatencyTimer_LineSize =
@ -598,7 +601,7 @@ mpt_read_config_regs(struct mpt_softc *mpt)
/* Sets modifiable config registers */
void
mpt_set_config_regs(struct mpt_softc *mpt)
mpt_set_config_regs(mpt_softc_t *mpt)
{
u_int32_t val;
@ -636,3 +639,12 @@ mpt_set_config_regs(struct mpt_softc *mpt)
pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1);
pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4);
}
static void
mpt_pci_intr(void *arg)
{
mpt_softc_t *mpt = arg;
MPT_LOCK(mpt);
mpt_intr(mpt);
MPT_UNLOCK(mpt);
}