Beispiel #1
0
int
mps_pci_setup_interrupts(struct mps_softc *sc)
{
    device_t dev;
    int i, error, msgs;

    dev = sc->mps_dev;
    error = ENXIO;
    if ((sc->disable_msix == 0) &&
            ((msgs = pci_msix_count(dev)) >= MPS_MSI_COUNT))
        error = mps_alloc_msix(sc, MPS_MSI_COUNT);
    if ((error != 0) && (sc->disable_msi == 0) &&
            ((msgs = pci_msi_count(dev)) >= MPS_MSI_COUNT))
        error = mps_alloc_msi(sc, MPS_MSI_COUNT);

    if (error != 0) {
        sc->mps_flags |= MPS_FLAGS_INTX;
        sc->mps_irq_rid[0] = 0;
        sc->mps_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
                                                &sc->mps_irq_rid[0],  RF_SHAREABLE | RF_ACTIVE);
        if (sc->mps_irq[0] == NULL) {
            mps_printf(sc, "Cannot allocate INTx interrupt\n");
            return (ENXIO);
        }
        error = bus_setup_intr(dev, sc->mps_irq[0],
                               INTR_TYPE_BIO | INTR_MPSAFE, NULL, mps_intr, sc,
                               &sc->mps_intrhand[0]);
        if (error)
            mps_printf(sc, "Cannot setup INTx interrupt\n");
    } else {
        sc->mps_flags |= MPS_FLAGS_MSI;
        for (i = 0; i < MPS_MSI_COUNT; i++) {
            sc->mps_irq_rid[i] = i + 1;
            sc->mps_irq[i] = bus_alloc_resource_any(dev,
                                                    SYS_RES_IRQ, &sc->mps_irq_rid[i], RF_ACTIVE);
            if (sc->mps_irq[i] == NULL) {
                mps_printf(sc,
                           "Cannot allocate MSI interrupt\n");
                return (ENXIO);
            }
            error = bus_setup_intr(dev, sc->mps_irq[i],
                                   INTR_TYPE_BIO | INTR_MPSAFE, NULL, mps_intr_msi,
                                   sc, &sc->mps_intrhand[i]);
            if (error) {
                mps_printf(sc,
                           "Cannot setup MSI interrupt %d\n", i);
                break;
            }
        }
    }

    return (error);
}
Beispiel #2
0
static int
mps_pci_attach(device_t dev)
{
    struct mps_softc *sc;
    struct mps_ident *m;
    int error;

    sc = device_get_softc(dev);
    bzero(sc, sizeof(*sc));
    sc->mps_dev = dev;
    m = mps_find_ident(dev);
    sc->mps_flags = m->flags;

    /* Twiddle basic PCI config bits for a sanity check */
    pci_enable_busmaster(dev);

    /* Allocate the System Interface Register Set */
    sc->mps_regs_rid = PCIR_BAR(1);
    if ((sc->mps_regs_resource = bus_alloc_resource_any(dev,
                                 SYS_RES_MEMORY, &sc->mps_regs_rid, RF_ACTIVE)) == NULL) {
        mps_printf(sc, "Cannot allocate PCI registers\n");
        return (ENXIO);
    }
    sc->mps_btag = rman_get_bustag(sc->mps_regs_resource);
    sc->mps_bhandle = rman_get_bushandle(sc->mps_regs_resource);

    /* Allocate the parent DMA tag */
    if (bus_dma_tag_create( bus_get_dma_tag(dev),	/* parent */
                            1, 0,			/* algnmnt, boundary */
                            BUS_SPACE_MAXADDR,	/* lowaddr */
                            BUS_SPACE_MAXADDR,	/* highaddr */
                            NULL, NULL,		/* filter, filterarg */
                            BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
                            BUS_SPACE_UNRESTRICTED,	/* nsegments */
                            BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
                            0,			/* flags */
                            NULL, NULL,		/* lockfunc, lockarg */
                            &sc->mps_parent_dmat)) {
        mps_printf(sc, "Cannot allocate parent DMA tag\n");
        mps_pci_free(sc);
        return (ENOMEM);
    }

    if ((error = mps_attach(sc)) != 0)
        mps_pci_free(sc);

    return (error);
}
Beispiel #3
0
static int
mps_user_read_extcfg_page(struct mps_softc *sc,
    struct mps_ext_cfg_page_req *ext_page_req, void *buf)
{
	MPI2_CONFIG_EXTENDED_PAGE_HEADER *reqhdr, *hdr;
	struct mps_config_params params;
	int error;

	reqhdr = buf;
	hdr = &params.hdr.Ext;
	params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
	params.page_address = le32toh(ext_page_req->page_address);
	hdr->PageVersion = reqhdr->PageVersion;
	hdr->PageNumber = reqhdr->PageNumber;
	hdr->ExtPageType = reqhdr->ExtPageType;
	hdr->ExtPageLength = reqhdr->ExtPageLength;
	params.buffer = buf;
	params.length = le32toh(ext_page_req->len);
	params.callback = NULL;

	if ((error = mps_read_config_page(sc, &params)) != 0) {
		mps_printf(sc, "mps_user_read_extcfg_page timed out\n");
		return (ETIMEDOUT);
	}

	ext_page_req->ioc_status = htole16(params.status);
	return (0);
}
Beispiel #4
0
static int
mps_user_write_cfg_page(struct mps_softc *sc,
    struct mps_cfg_page_req *page_req, void *buf)
{
	MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
	struct mps_config_params params;
	u_int	      hdr_attr;
	int	      error;

	reqhdr = buf;
	hdr = &params.hdr.Struct;
	hdr_attr = reqhdr->PageType & MPI2_CONFIG_PAGEATTR_MASK;
	if (hdr_attr != MPI2_CONFIG_PAGEATTR_CHANGEABLE &&
	    hdr_attr != MPI2_CONFIG_PAGEATTR_PERSISTENT) {
		mps_printf(sc, "page type 0x%x not changeable\n",
			reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK);
		return (EINVAL);
	}

	/*
	 * There isn't any point in restoring stripped out attributes
	 * if you then mask them going down to issue the request.
	 */

	hdr->PageVersion = reqhdr->PageVersion;
	hdr->PageLength = reqhdr->PageLength;
	hdr->PageNumber = reqhdr->PageNumber;
	hdr->PageType = reqhdr->PageType;
	params.action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
	params.page_address = le32toh(page_req->page_address);
	params.buffer = buf;
	params.length = le32toh(page_req->len);
	params.callback = NULL;

	if ((error = mps_write_config_page(sc, &params)) != 0) {
		mps_printf(sc, "mps_write_cfg_page timed out\n");
		return (ETIMEDOUT);
	}

	page_req->ioc_status = htole16(params.status);
	return (0);
}
Beispiel #5
0
static int
mps_user_read_extcfg_header(struct mps_softc *sc,
    struct mps_ext_cfg_page_req *ext_page_req)
{
	MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
	struct mps_config_params params;
	int	    error;

	hdr = &params.hdr.Ext;
	params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
	hdr->PageVersion = ext_page_req->header.PageVersion;
	hdr->ExtPageLength = 0;
	hdr->PageNumber = ext_page_req->header.PageNumber;
	hdr->ExtPageType = ext_page_req->header.ExtPageType;
	params.page_address = le32toh(ext_page_req->page_address);
	if ((error = mps_read_config_page(sc, &params)) != 0) {
		/*
		 * Leave the request. Without resetting the chip, it's
		 * still owned by it and we'll just get into trouble
		 * freeing it now. Mark it as abandoned so that if it
		 * shows up later it can be freed.
		 */
		mps_printf(sc, "mps_user_read_extcfg_header timed out\n");
		return (ETIMEDOUT);
	}

	ext_page_req->ioc_status = htole16(params.status);
	if ((ext_page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
	    MPI2_IOCSTATUS_SUCCESS) {
		ext_page_req->header.PageVersion = hdr->PageVersion;
		ext_page_req->header.PageNumber = hdr->PageNumber;
		ext_page_req->header.PageType = hdr->PageType;
		ext_page_req->header.ExtPageLength = hdr->ExtPageLength;
		ext_page_req->header.ExtPageType = hdr->ExtPageType;
	}

	return (0);
}
Beispiel #6
0
static int
mps_user_read_cfg_header(struct mps_softc *sc,
    struct mps_cfg_page_req *page_req)
{
	MPI2_CONFIG_PAGE_HEADER *hdr;
	struct mps_config_params params;
	int	    error;

	hdr = &params.hdr.Struct;
	params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
	params.page_address = le32toh(page_req->page_address);
	hdr->PageVersion = 0;
	hdr->PageLength = 0;
	hdr->PageNumber = page_req->header.PageNumber;
	hdr->PageType = page_req->header.PageType;
	params.buffer = NULL;
	params.length = 0;
	params.callback = NULL;

	if ((error = mps_read_config_page(sc, &params)) != 0) {
		/*
		 * Leave the request. Without resetting the chip, it's
		 * still owned by it and we'll just get into trouble
		 * freeing it now. Mark it as abandoned so that if it
		 * shows up later it can be freed.
		 */
		mps_printf(sc, "read_cfg_header timed out\n");
		return (ETIMEDOUT);
	}

	page_req->ioc_status = htole16(params.status);
	if ((page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
	    MPI2_IOCSTATUS_SUCCESS) {
		bcopy(hdr, &page_req->header, sizeof(page_req->header));
	}

	return (0);
}
Beispiel #7
0
static int
mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
{
	MPI2_REQUEST_HEADER *hdr;
	MPI2_DEFAULT_REPLY *rpl;
	void *buf = NULL;
	struct mps_command *cm = NULL;
	int err = 0;
	int sz;

	mps_lock(sc);
	cm = mps_alloc_command(sc);

	if (cm == NULL) {
		mps_printf(sc, "mps_user_command: no mps requests\n");
		err = ENOMEM;
		goto Ret;
	}
	mps_unlock(sc);

	hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;

	mps_dprint(sc, MPS_INFO, "mps_user_command: req %p %d  rpl %p %d\n",
		    cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len );

	if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) {
		err = EINVAL;
		goto RetFreeUnlocked;
	}
	err = copyin(cmd->req, hdr, cmd->req_len);
	if (err != 0)
		goto RetFreeUnlocked;

	mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X  "
	    "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags );

	err = mps_user_setup_request(cm, cmd);
	if (err != 0) {
		mps_printf(sc, "mps_user_command: unsupported function 0x%X\n",
		    hdr->Function );
		goto RetFreeUnlocked;
	}

	if (cmd->len > 0) {
		buf = kmalloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
		cm->cm_data = buf;
		cm->cm_length = cmd->len;
	} else {
		cm->cm_data = NULL;
		cm->cm_length = 0;
	}

	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_WAKEUP;
	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;

	mps_lock(sc);
	err = mps_map_command(sc, cm);

	if (err != 0 && err != EINPROGRESS) {
		mps_printf(sc, "%s: invalid request: error %d\n",
		    __func__, err);
		goto Ret;
	}
	lksleep(cm, &sc->mps_lock, 0, "mpsuser", 0);

	rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
	sz = rpl->MsgLength * 4;

	if (sz > cmd->rpl_len) {
		mps_printf(sc,
		    "mps_user_command: reply buffer too small %d required %d\n",
		    cmd->rpl_len, sz );
		err = EINVAL;
		sz = cmd->rpl_len;
	}

	mps_unlock(sc);
	copyout(rpl, cmd->rpl, sz);
	if (buf != NULL)
		copyout(buf, cmd->buf, cmd->len);
	mps_dprint(sc, MPS_INFO, "mps_user_command: reply size %d\n", sz );

RetFreeUnlocked:
	mps_lock(sc);
	if (cm != NULL)
		mps_free_command(sc, cm);
Ret:
	mps_unlock(sc);
	if (buf != NULL)
		kfree(buf, M_MPSUSER);
	return (err);
}