/* * RQ buffer constructor function * * rqbd - pointer to rq buffer descriptor * rq - pointer to RQ structure * size - size of the buffer * flags - KM_SLEEP OR KM_NOSLEEP * * return DDI_SUCCESS => success, DDI_FAILURE otherwise */ static int oce_rqb_ctor(oce_rq_bdesc_t *rqbd, struct oce_rq *rq, size_t size, int flags) { struct oce_dev *dev; oce_dma_buf_t *dbuf; dev = rq->parent; dbuf = oce_alloc_dma_buffer(dev, size, &oce_rx_buf_attr, flags); if (dbuf == NULL) { return (DDI_FAILURE); } /* Set the call back function parameters */ rqbd->fr_rtn.free_func = (void (*)())oce_rx_pool_free; rqbd->fr_rtn.free_arg = (caddr_t)(void *)rqbd; rqbd->mp = desballoc((uchar_t *)(dbuf->base), dbuf->size, 0, &rqbd->fr_rtn); if (rqbd->mp == NULL) { oce_free_dma_buffer(dev, dbuf); return (DDI_FAILURE); } rqbd->rqb = dbuf; rqbd->rq = rq; rqbd->frag_addr.dw.addr_lo = ADDR_LO(dbuf->addr + OCE_RQE_BUF_HEADROOM); rqbd->frag_addr.dw.addr_hi = ADDR_HI(dbuf->addr + OCE_RQE_BUF_HEADROOM); rqbd->mp->b_rptr = (uchar_t *)rqbd->rqb->base + OCE_RQE_BUF_HEADROOM; return (DDI_SUCCESS); } /* oce_rqb_ctor */
static void dcons_crom_expose_idt(struct dcons_crom_softc *sc) { static off_t idt_paddr; /* XXX */ idt_paddr = (char *)idt - (char *)KERNBASE; crom_add_entry(&sc->unit, DCONS_CSR_KEY_RESET_HI, ADDR_HI(idt_paddr)); crom_add_entry(&sc->unit, DCONS_CSR_KEY_RESET_LO, ADDR_LO(idt_paddr)); }
static void dcons_crom_expose_idt(struct dcons_crom_softc *sc) { static off_t idt_paddr; /* XXX */ #ifdef __amd64__ idt_paddr = (char *)idt - (char *)KERNBASE; #else /* __i386__ */ idt_paddr = (off_t)pmap_kextract((vm_offset_t)idt); #endif crom_add_entry(&sc->unit, DCONS_CSR_KEY_RESET_HI, ADDR_HI(idt_paddr)); crom_add_entry(&sc->unit, DCONS_CSR_KEY_RESET_LO, ADDR_LO(idt_paddr)); }
/* * WQ buffer constructor * * wqbd - pointer to WQ buffer descriptor * wq - pointer to WQ structure * size - size of the buffer * flags - KM_SLEEP or KM_NOSLEEP * * return DDI_SUCCESS=>success, DDI_FAILURE=>error */ static int oce_wqb_ctor(oce_wq_bdesc_t *wqbd, struct oce_wq *wq, size_t size, int flags) { struct oce_dev *dev; dev = wq->parent; wqbd->wqb = oce_alloc_dma_buffer(dev, size, &oce_tx_dma_buf_attr, flags); if (wqbd->wqb == NULL) { return (DDI_FAILURE); } wqbd->frag_addr.dw.addr_lo = ADDR_LO(wqbd->wqb->addr); wqbd->frag_addr.dw.addr_hi = ADDR_HI(wqbd->wqb->addr); return (DDI_SUCCESS); }
/* * function to copy the packet or dma map on the fly depending on size * * wq - pointer to WQ * wqed - Pointer to WQE descriptor * mp - Pointer to packet chain * * return DDI_SUCCESS=>success, DDI_FAILURE=>error */ static int oce_map_wqe(struct oce_wq *wq, oce_wqe_desc_t *wqed, mblk_t *mp, uint32_t pkt_len) { ddi_dma_cookie_t cookie; oce_wq_mdesc_t *wqmd; uint32_t ncookies; int ret; struct oce_dev *dev = wq->parent; wqmd = oce_wqm_alloc(wq); if (wqmd == NULL) { oce_log(dev, CE_WARN, MOD_TX, "%s", "wqm pool empty"); return (ENOMEM); } ret = ddi_dma_addr_bind_handle(wqmd->dma_handle, (struct as *)0, (caddr_t)mp->b_rptr, pkt_len, DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL, &cookie, &ncookies); if (ret != DDI_DMA_MAPPED) { oce_log(dev, CE_WARN, MOD_TX, "MAP FAILED %d", ret); /* free the last one */ oce_wqm_free(wq, wqmd); return (ENOMEM); } do { wqed->frag[wqed->frag_idx].u0.s.frag_pa_hi = ADDR_HI(cookie.dmac_laddress); wqed->frag[wqed->frag_idx].u0.s.frag_pa_lo = ADDR_LO(cookie.dmac_laddress); wqed->frag[wqed->frag_idx].u0.s.frag_len = (uint32_t)cookie.dmac_size; wqed->frag_cnt++; wqed->frag_idx++; if (--ncookies > 0) ddi_dma_nextcookie(wqmd->dma_handle, &cookie); else break; } while (ncookies > 0); wqed->hdesc[wqed->nhdl].hdl = (void *)wqmd; wqed->hdesc[wqed->nhdl].type = MAPPED_WQE; wqed->nhdl++; return (0); } /* oce_map_wqe */
/** * @brief Map ring buffer * @param arg dma map phyical address table pointer * @param segs dma memory segments * @param nseg number of dma memory segments * @param error maps only if error is 0 */ static void oce_dma_map_ring(void *arg, bus_dma_segment_t * segs, int nseg, int error) { int i; struct _oce_dmamap_paddr_table *dpt = (struct _oce_dmamap_paddr_table *)arg; if (error == 0) { if (nseg <= dpt->max_entries) { for (i = 0; i < nseg; i++) { dpt->paddrs[i].lo = ADDR_LO(segs[i].ds_addr); dpt->paddrs[i].hi = ADDR_HI(segs[i].ds_addr); } dpt->num_entries = nseg; } } }
/* * function to breakup a block of memory into pages and return the address * in an array * * dbuf - pointer to structure describing DMA-able memory * pa_list - [OUT] pointer to an array to return the PA of pages * list_size - number of entries in pa_list */ void oce_page_list(oce_dma_buf_t *dbuf, struct phys_addr *pa_list, int list_size) { int i = 0; uint64_t paddr = 0; ASSERT(dbuf != NULL); ASSERT(pa_list != NULL); paddr = DBUF_PA(dbuf); for (i = 0; i < list_size; i++) { pa_list[i].lo = ADDR_LO(paddr); pa_list[i].hi = ADDR_HI(paddr); paddr += PAGE_4K; } } /* oce_page_list */
static void dcons_crom(struct fwohci_softc *sc) { struct crom_src_buf *buf; struct crom_src *src; struct crom_chunk *root; buf = sc->crom_src_buf; src = sc->crom_src; root = sc->crom_root; bzero(&buf->unit, sizeof(struct crom_chunk)); crom_add_chunk(src, root, &buf->unit, CROM_UDIR); crom_add_entry(&buf->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE); crom_add_simple_text(src, &buf->unit, &buf->spec, "FreeBSD"); crom_add_entry(&buf->unit, CSRKEY_VER, DCONS_CSR_VAL_VER); crom_add_simple_text(src, &buf->unit, &buf->ver, "dcons"); crom_add_entry(&buf->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr)); crom_add_entry(&buf->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr)); }
static void dcons_crom_post_busreset(void *arg) { struct dcons_crom_softc *sc; struct crom_src *src; struct crom_chunk *root; sc = (struct dcons_crom_softc *) arg; src = sc->fd.fc->crom_src; root = sc->fd.fc->crom_root; bzero(&sc->unit, sizeof(struct crom_chunk)); crom_add_chunk(src, root, &sc->unit, CROM_UDIR); crom_add_entry(&sc->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE); crom_add_simple_text(src, &sc->unit, &sc->spec, "FreeBSD"); crom_add_entry(&sc->unit, CSRKEY_VER, DCONS_CSR_VAL_VER); crom_add_simple_text(src, &sc->unit, &sc->ver, "dcons"); crom_add_entry(&sc->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr)); crom_add_entry(&sc->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr)); }
static void dcons_crom_post_busreset(void *arg) { struct dcons_crom_softc *sc; struct crom_src *src; struct crom_chunk *root; sc = (struct dcons_crom_softc *) arg; src = sc->fd.fc->crom_src; root = sc->fd.fc->crom_root; bzero(&sc->unit, sizeof(struct crom_chunk)); crom_add_chunk(src, root, &sc->unit, CROM_UDIR); crom_add_entry(&sc->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE); crom_add_simple_text(src, &sc->unit, &sc->spec, "FreeBSD"); crom_add_entry(&sc->unit, CSRKEY_VER, DCONS_CSR_VAL_VER); crom_add_simple_text(src, &sc->unit, &sc->ver, "dcons"); crom_add_entry(&sc->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr)); crom_add_entry(&sc->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr)); #if (defined(__i386__) || defined(__amd64__)) && defined(EXPOSE_IDT_ADDR) dcons_crom_expose_idt(sc); #endif }