diff --git a/sys/dev/ieee1394/fwohci.c b/sys/dev/ieee1394/fwohci.c index 3de32c0c6667..f0fa16108e0b 100644 --- a/sys/dev/ieee1394/fwohci.c +++ b/sys/dev/ieee1394/fwohci.c @@ -1,5 +1,7 @@ -/* $NetBSD: fwohci.c,v 1.39 2001/07/02 11:12:09 onoe Exp $ */ +/* $NetBSD: fwohci.c,v 1.40 2001/07/17 11:01:03 haya Exp $ */ +#define DOUBLEBUF 1 +#define NO_THREAD 1 /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. @@ -43,6 +45,11 @@ * Atsushi Onoe . */ +/* + * The first version to support isochronous acquisition part is wrtten + * by HAYAKAWA Koichi . + */ + #include "opt_inet.h" #include @@ -90,7 +97,7 @@ static struct fwohci_desc *fwohci_desc_get(struct fwohci_softc *, int); static void fwohci_desc_put(struct fwohci_softc *, struct fwohci_desc *, int); static int fwohci_ctx_alloc(struct fwohci_softc *, struct fwohci_ctx **, - int, int); + int, int, int); static void fwohci_ctx_free(struct fwohci_softc *, struct fwohci_ctx *); static void fwohci_ctx_init(struct fwohci_softc *, struct fwohci_ctx *); @@ -147,8 +154,11 @@ static void fwohci_check_nodes(struct fwohci_softc *); static int fwohci_if_inreg(struct device *, u_int32_t, u_int32_t, void (*)(struct device *, struct mbuf *)); static int fwohci_if_input(struct fwohci_softc *, void *, struct fwohci_pkt *); +static int fwohci_if_input_iso(struct fwohci_softc *, void *, struct fwohci_pkt *); static int fwohci_if_output(struct device *, struct mbuf *, void (*)(struct device *, struct mbuf *)); +static int fwohci_if_setiso(struct device *, int, int, int, + void (*)(struct device *, struct mbuf *)); static int fwohci_read(struct ieee1394_abuf *); static int fwohci_write(struct ieee1394_abuf *); static int fwohci_read_resp(struct fwohci_softc *, void *, struct fwohci_pkt *); @@ -186,6 +196,11 @@ fwohci_init(struct fwohci_softc *sc, const struct evcnt *ev) evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ev, sc->sc_sc1394.sc1394_dev.dv_xname, "intr"); + evcnt_attach_dynamic(&sc->sc_isocnt, EVCNT_TYPE_MISC, ev, + sc->sc_sc1394.sc1394_dev.dv_xname, "iso"); + evcnt_attach_dynamic(&sc->sc_isopktcnt, EVCNT_TYPE_MISC, ev, + sc->sc_sc1394.sc1394_dev.dv_xname, "isopackets"); + /* * Wait for reset completion */ @@ -263,6 +278,34 @@ fwohci_init(struct fwohci_softc *sc, const struct evcnt *ev) return 0; } +static int +fwohci_if_setiso(struct device *self, int channel, int tag, int direction, + void (*handler)(struct device *, struct mbuf *)) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)self; + int retval; + int s; + + if (direction == 1) { + return EIO; + } + + s = splnet(); + retval = fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA, + channel, tag, fwohci_if_input_iso, handler); + splx(s); + + if (!retval) { + printf("%s: dummy iso handler set\n", + sc->sc_sc1394.sc1394_dev.dv_xname); + } else { + printf("%s: dummy iso handler cannot set\n", + sc->sc_sc1394.sc1394_dev.dv_xname); + } + + return retval; +} + int fwohci_intr(void *arg) { @@ -318,9 +361,38 @@ fwohci_intr(void *arg) OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntEventClear, iso); } if (intmask & OHCI_Int_IsochRx) { +#if NO_THREAD + int i; + int asyncstream = 0; +#endif + iso = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear); OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, iso); +#if NO_THREAD + for (i = 0; i < sc->sc_isoctx; i++) { + if ((iso & (1<sc_ctx_ir[i] != NULL) { + if (sc->sc_ctx_ir[i]->fc_type == FWOHCI_CTX_ISO_SINGLE) { + asyncstream |= (1 << i); + continue; + } + bus_dmamap_sync(sc->sc_dmat, + sc->sc_ddmamap, + 0, sizeof(struct fwohci_desc) * sc->sc_descsize, + BUS_DMASYNC_PREREAD); + sc->sc_isocnt.ev_count++; + + fwohci_ir_input(sc, sc->sc_ctx_ir[i]); + } + } + if (asyncstream != 0) { + sc->sc_iso |= asyncstream; + } else { + /* all iso intr is pure isochronous */ + sc->sc_intmask &= ~OHCI_Int_IsochRx; + } +#else sc->sc_iso |= iso; +#endif /* NO_THREAD */ } if (!progress) { @@ -368,11 +440,13 @@ fwohci_thread_init(void *arg) * Allocate DMA Context */ fwohci_ctx_alloc(sc, &sc->sc_ctx_arrq, OHCI_BUF_ARRQ_CNT, - OHCI_CTX_ASYNC_RX_REQUEST); + OHCI_CTX_ASYNC_RX_REQUEST, FWOHCI_CTX_ASYNC); fwohci_ctx_alloc(sc, &sc->sc_ctx_arrs, OHCI_BUF_ARRS_CNT, - OHCI_CTX_ASYNC_RX_RESPONSE); - fwohci_ctx_alloc(sc, &sc->sc_ctx_atrq, 0, OHCI_CTX_ASYNC_TX_REQUEST); - fwohci_ctx_alloc(sc, &sc->sc_ctx_atrs, 0, OHCI_CTX_ASYNC_TX_RESPONSE); + OHCI_CTX_ASYNC_RX_RESPONSE, FWOHCI_CTX_ASYNC); + fwohci_ctx_alloc(sc, &sc->sc_ctx_atrq, 0, OHCI_CTX_ASYNC_TX_REQUEST, + FWOHCI_CTX_ASYNC); + fwohci_ctx_alloc(sc, &sc->sc_ctx_atrs, 0, OHCI_CTX_ASYNC_TX_RESPONSE, + FWOHCI_CTX_ASYNC); sc->sc_ctx_ir = malloc(sizeof(sc->sc_ctx_ir[0]) * sc->sc_isoctx, M_DEVBUF, M_WAITOK); for (i = 0; i < sc->sc_isoctx; i++) @@ -388,6 +462,7 @@ fwohci_thread_init(void *arg) sc->sc_sc1394.sc1394_ifinreg = fwohci_if_inreg; sc->sc_sc1394.sc1394_ifoutput = fwohci_if_output; + sc->sc_sc1394.sc1394_ifsetiso = fwohci_if_setiso; /* * establish hooks for shutdown and suspend/resume @@ -476,8 +551,10 @@ fwohci_event_thread(struct fwohci_softc *sc) splx(s); for (i = 0; i < sc->sc_isoctx; i++) { if ((iso & (1 << i)) && - sc->sc_ctx_ir[i] != NULL) + sc->sc_ctx_ir[i] != NULL) { fwohci_ir_input(sc, sc->sc_ctx_ir[i]); + sc->sc_isocnt.ev_count++; + } } } } @@ -855,12 +932,13 @@ fwohci_desc_put(struct fwohci_softc *sc, struct fwohci_desc *fd, int ndesc) */ static int fwohci_ctx_alloc(struct fwohci_softc *sc, struct fwohci_ctx **fcp, - int bufcnt, int ctx) + int bufcnt, int ctx, int ctxtype) { int i, error; struct fwohci_ctx *fc; struct fwohci_buf *fb; struct fwohci_desc *fd; + int buf2cnt; fc = malloc(sizeof(*fc) + sizeof(*fb) * bufcnt, M_DEVBUF, M_WAITOK); memset(fc, 0, sizeof(*fc) + sizeof(*fb) * bufcnt); @@ -869,6 +947,16 @@ fwohci_ctx_alloc(struct fwohci_softc *sc, struct fwohci_ctx **fcp, fc->fc_ctx = ctx; fc->fc_bufcnt = bufcnt; fb = (struct fwohci_buf *)&fc[1]; +#if DOUBLEBUF + TAILQ_INIT(&fc->fc_buf2); /* for isochronous */ + if (ctxtype == FWOHCI_CTX_ISO_MULTI) { + buf2cnt = bufcnt/2; + bufcnt -= buf2cnt; + if (buf2cnt == 0) { + panic("cannot allocate iso buffer"); + } + } +#endif for (i = 0; i < bufcnt; i++, fb++) { if ((error = fwohci_buf_alloc(sc, fb)) != 0) goto fail; @@ -885,6 +973,33 @@ fwohci_ctx_alloc(struct fwohci_softc *sc, struct fwohci_ctx **fcp, fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr; TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list); } +#if DOUBLEBUF + if (ctxtype == FWOHCI_CTX_ISO_MULTI) { + for (i = bufcnt; i < bufcnt + buf2cnt; i++, fb++) { + if ((error = fwohci_buf_alloc(sc, fb)) != 0) + goto fail; + if ((fd = fwohci_desc_get(sc, 1)) == NULL) { + error = ENOBUFS; + goto fail; + } + fb->fb_desc = fd; + fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr + + ((caddr_t)fd - (caddr_t)sc->sc_desc); + bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap, + (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc), + BUS_DMASYNC_PREWRITE); + fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_STATUS | + OHCI_DESC_INTR_ALWAYS | OHCI_DESC_BRANCH; + fd->fd_reqcount = fb->fb_dmamap->dm_segs[0].ds_len; + fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr; + TAILQ_INSERT_TAIL(&fc->fc_buf2, fb, fb_list); + bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap, + (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc), + BUS_DMASYNC_POSTWRITE); + } + } +#endif /* DOUBLEBUF */ + fc->fc_type = ctxtype; *fcp = fc; return 0; @@ -914,6 +1029,14 @@ fwohci_ctx_free(struct fwohci_softc *sc, struct fwohci_ctx *fc) fwohci_desc_put(sc, fb->fb_desc, 1); fwohci_buf_free(sc, fb); } +#if DOUBLEBUF + while ((fb = TAILQ_FIRST(&fc->fc_buf2)) != NULL) { + TAILQ_REMOVE(&fc->fc_buf2, fb, fb_list); + if (fb->fb_desc) + fwohci_desc_put(sc, fb->fb_desc, 1); + fwohci_buf_free(sc, fb); + } +#endif /* DOUBLEBUF */ free(fc, M_DEVBUF); } @@ -933,9 +1056,25 @@ fwohci_ctx_init(struct fwohci_softc *sc, struct fwohci_ctx *fc) fd->fd_rescount = fd->fd_reqcount; } +#if DOUBLEBUF + for (fb = TAILQ_FIRST(&fc->fc_buf2); fb != NULL; fb = nfb) { + bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap, + (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc), + BUS_DMASYNC_PREWRITE); + nfb = TAILQ_NEXT(fb, fb_list); + fb->fb_off = 0; + fd = fb->fb_desc; + fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0; + fd->fd_rescount = fd->fd_reqcount; + bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap, + (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc), + BUS_DMASYNC_POSTWRITE); + } +#endif /* DOUBLEBUF */ + n = fc->fc_ctx; fb = TAILQ_FIRST(&fc->fc_buf); - if (fc->fc_isoch) { + if (fc->fc_type != FWOHCI_CTX_ASYNC) { OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr, fb->fb_daddr | 1); OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear, @@ -945,6 +1084,11 @@ fwohci_ctx_init(struct fwohci_softc *sc, struct fwohci_ctx *fc) OHCI_CTXCTL_RX_DUAL_BUFFER_MODE); OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RX_ISOCH_HEADER); + if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) { + OHCI_SYNC_RX_DMA_WRITE(sc, n, + OHCI_SUBREG_ContextControlSet, + OHCI_CTXCTL_RX_BUFFER_FILL); + } fh = LIST_FIRST(&fc->fc_handler); OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextMatch, (OHCI_CTXMATCH_TAG0 << fh->fh_key2) | fh->fh_key1); @@ -1102,23 +1246,43 @@ fwohci_buf_next(struct fwohci_softc *sc, struct fwohci_ctx *fc) { struct fwohci_buf *fb, *tfb; - while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) { - if (fc->fc_isoch) { - if (fb->fb_off == 0) - break; - } else { - if (fb->fb_off != fb->fb_desc->fd_reqcount || - fb->fb_desc->fd_rescount != 0) - break; +#if DOUBLEBUF + if (fc->fc_type != FWOHCI_CTX_ISO_MULTI) { +#endif + while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) { + if (fc->fc_type) { + if (fb->fb_off == 0) + break; + } else { + if (fb->fb_off != fb->fb_desc->fd_reqcount || + fb->fb_desc->fd_rescount != 0) + break; + } + TAILQ_REMOVE(&fc->fc_buf, fb, fb_list); + fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount; + fb->fb_off = 0; + fb->fb_desc->fd_branch = 0; + tfb = TAILQ_LAST(&fc->fc_buf, fwohci_buf_s); + tfb->fb_desc->fd_branch = fb->fb_daddr | 1; + TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list); } - TAILQ_REMOVE(&fc->fc_buf, fb, fb_list); - fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount; - fb->fb_off = 0; - fb->fb_desc->fd_branch = 0; - tfb = TAILQ_LAST(&fc->fc_buf, fwohci_buf_s); - tfb->fb_desc->fd_branch = fb->fb_daddr | 1; - TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list); +#if DOUBLEBUF + } else { + struct fwohci_buf_s fctmp; + + /* cleaning buffer */ + for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL; + fb = TAILQ_NEXT(fb, fb_list)) { + fb->fb_off = 0; + fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount; + } + + /* rotating buffer */ + fctmp = fc->fc_buf; + fc->fc_buf = fc->fc_buf2; + fc->fc_buf2 = fctmp; } +#endif } static int @@ -1138,6 +1302,9 @@ fwohci_buf_pktget(struct fwohci_softc *sc, struct fwohci_buf **fbp, caddr_t *pp, fd->fd_reqcount - fd->fd_rescount - fb->fb_off)); bufend = fd->fd_reqcount - fd->fd_rescount; if (fb->fb_off >= bufend) { + DPRINTFN(5, ("buf %x finish req %d res %d off %d ", + fb->fb_desc->fd_data, fd->fd_reqcount, fd->fd_rescount, + fb->fb_off)); if (fd->fd_rescount == 0) { *fbp = fb = TAILQ_NEXT(fb, fb_list); if (fb != NULL) @@ -1194,10 +1361,21 @@ fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc, case IEEE1394_TCODE_LOCK_RESP: pkt->fp_hlen = 16; break; -#ifdef DIAGNOSTIC case IEEE1394_TCODE_STREAM_DATA: - printf("fwohci_buf_input: bad tcode: STREAM_DATA\n"); - return 0; +#ifdef DIAGNOSTIC + if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) +#endif + { + pkt->fp_hlen = 4; + pkt->fp_dlen = pkt->fp_hdr[0] >> 16; + DPRINTFN(5, ("[%d]", pkt->fp_dlen)); + break; + } +#ifdef DIAGNOSTIC + else { + printf("fwohci_buf_input: bad tcode: STREAM_DATA\n"); + return 0; + } #endif default: pkt->fp_hlen = 12; @@ -1260,6 +1438,10 @@ fwohci_buf_input_ppb(struct fwohci_softc *sc, struct fwohci_ctx *fc, struct fwohci_buf *fb; struct fwohci_desc *fd; + if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) { + return fwohci_buf_input(sc, fc, pkt); + } + memset(pkt, 0, sizeof(*pkt)); pkt->fp_uio.uio_iov = pkt->fp_iov; pkt->fp_uio.uio_rw = UIO_WRITE; @@ -1329,6 +1511,9 @@ fwohci_handler_set(struct fwohci_softc *sc, int i, j; if (tcode == IEEE1394_TCODE_STREAM_DATA) { + int isasync = key1 & OHCI_ASYNC_STREAM; + + key1 &= IEEE1394_ISOCH_MASK; j = sc->sc_isoctx; fh = NULL; for (i = 0; i < sc->sc_isoctx; i++) { @@ -1352,8 +1537,9 @@ fwohci_handler_set(struct fwohci_softc *sc, return ENOMEM; } if ((fc = sc->sc_ctx_ir[j]) == NULL) { - fwohci_ctx_alloc(sc, &fc, OHCI_BUF_IR_CNT, j); - fc->fc_isoch = 1; + fwohci_ctx_alloc(sc, &fc, OHCI_BUF_IR_CNT, j, + isasync ? FWOHCI_CTX_ISO_SINGLE : + FWOHCI_CTX_ISO_MULTI); sc->sc_ctx_ir[j] = fc; } } @@ -1519,6 +1705,43 @@ fwohci_ir_input(struct fwohci_softc *sc, struct fwohci_ctx *fc) struct fwohci_handler *fh; struct fwohci_pkt pkt; +#if DOUBLEBUF + if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) { + struct fwohci_buf *fb; + int i; + u_int32_t reg; + + /* stop dma engine before read buffer */ + reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, + OHCI_SUBREG_ContextControlClear); + DPRINTFN(5, ("ir_input %08x =>", reg)); + if (reg & OHCI_CTXCTL_RUN) { + OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, + OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); + } + DPRINTFN(5, (" %08x\n", OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlClear))); + + i = 0; + while ((reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlSet)) & OHCI_CTXCTL_ACTIVE) { + delay(10); + if (++i > 10000) { + printf("cannot stop dma engine 0x08x\n", reg); + return; + } + } + + /* rotate dma buffer */ + fb = TAILQ_FIRST(&fc->fc_buf2); + OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_CommandPtr, + fb->fb_daddr | 1); + /* start dma engine */ + OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, + OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN); + OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, + (1 << fc->fc_ctx)); + } +#endif + while (fwohci_buf_input_ppb(sc, fc, &pkt)) { chan = (pkt.fp_hdr[0] & 0x00003f00) >> 8; tag = (pkt.fp_hdr[0] & 0x0000c000) >> 14; @@ -1541,6 +1764,7 @@ fwohci_ir_input(struct fwohci_softc *sc, struct fwohci_ctx *fc) pkt.fp_hlen += 8; pkt.fp_dlen -= 8; } + sc->sc_isopktcnt.ev_count++; for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL; fh = LIST_NEXT(fh, fh_list)) { if (pkt.fp_tcode == fh->fh_tcode && @@ -1559,8 +1783,12 @@ fwohci_ir_input(struct fwohci_softc *sc, struct fwohci_ctx *fc) #endif } fwohci_buf_next(sc, fc); - OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlSet, - OHCI_CTXCTL_WAKE); + + if (fc->fc_type == FWOHCI_CTX_ISO_SINGLE) { + OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, + OHCI_SUBREG_ContextControlSet, + OHCI_CTXCTL_WAKE); + } } /* @@ -2514,7 +2742,7 @@ fwohci_if_inreg(struct device *self, u_int32_t offhi, u_int32_t offlo, fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_BLOCK, offhi, offlo, handler ? fwohci_if_input : NULL, handler); fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA, - sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & OHCI_NodeId_NodeNumber, + (sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & IEEE1394_ISOCH_MASK) | OHCI_ASYNC_STREAM, IEEE1394_TAG_GASP, handler ? fwohci_if_input : NULL, handler); return 0; } @@ -2606,6 +2834,107 @@ fwohci_if_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) return IEEE1394_RCODE_COMPLETE; } +static int +fwohci_if_input_iso(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) +{ + int n, len; + int chan, tag; + struct mbuf *m; + struct iovec *iov; + void (*handler)(struct device *, struct mbuf *) = arg; + + chan = (pkt->fp_hdr[0] & 0x00003f00) >> 8; + tag = (pkt->fp_hdr[0] & 0x0000c000) >> 14; +#ifdef FW_DEBUG + if (fw_verbose) { + int i; + printf("fwohci_if_input_iso: tcode=0x%x, chan=%d, tag=%x, dlen=%d", + pkt->fp_tcode, chan, tag, pkt->fp_dlen); + if (fw_dump) { + for (i = 0; i < pkt->fp_hlen/4; i++) + printf("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i]); + printf("$"); + for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){ + iov = &pkt->fp_iov[n]; + for (i = 0; i < iov->iov_len; i++) + printf("%s%02x", + (i%32)?((i%4)?"":" "):"\n\t", + ((u_int8_t *)iov->iov_base)[i]); + printf("$"); + } + } + printf("\n"); + } +#endif /* FW_DEBUG */ + len = pkt->fp_dlen; + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) + return IEEE1394_RCODE_COMPLETE; + m->m_len = 16; + if (m->m_len + len > MHLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + return IEEE1394_RCODE_COMPLETE; + } + } + + m->m_flags |= M_BCAST; + + if (tag == IEEE1394_TAG_GASP) { + n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber; + if (sc->sc_uidtbl == NULL || n > sc->sc_rootid || + sc->sc_uidtbl[n].fu_valid != 0x3) { + printf("%s: packet from unknown node: phy id %d\n", + sc->sc_sc1394.sc1394_dev.dv_xname, n); + m_freem(m); + return IEEE1394_RCODE_COMPLETE; + } + memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8); + mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]); + mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]); + mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */ + mtod(m, u_int8_t *)[9] = + (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) & + ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1); + } else { + m->m_flags |= M_LINK0; + } + mtod(m, u_int8_t *)[14] = chan; + mtod(m, u_int8_t *)[15] = tag; + + + m->m_pkthdr.rcvif = NULL; /* set in child */ + m->m_pkthdr.len = len + m->m_len; + /* + * We may use receive buffer by external mbuf instead of copy here. + * But asynchronous receive buffer must be operate in buffer fill + * mode, so that each receive buffer will shared by multiple mbufs. + * If upper layer doesn't free mbuf soon, e.g. application program + * is suspended, buffer must be reallocated. + * Isochronous buffer must be operate in packet buffer mode, and + * it is easy to map receive buffer to external mbuf. But it is + * used for broadcast/multicast only, and is expected not so + * performance sensitive for now. + * XXX: The performance may be important for multicast case, + * so we should revisit here later. + * -- onoe + */ + n = 0; + iov = pkt->fp_uio.uio_iov; + while (len > 0) { + memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base, + iov->iov_len); + m->m_len += iov->iov_len; + len -= iov->iov_len; + iov++; + } + (*handler)(sc->sc_sc1394.sc1394_if, m); + return IEEE1394_RCODE_COMPLETE; +} + + + static int fwohci_if_output(struct device *self, struct mbuf *m0, void (*callback)(struct device *, struct mbuf *)) diff --git a/sys/dev/ieee1394/fwohcivar.h b/sys/dev/ieee1394/fwohcivar.h index 3f07f79ad458..6f2de444ba52 100644 --- a/sys/dev/ieee1394/fwohcivar.h +++ b/sys/dev/ieee1394/fwohcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: fwohcivar.h,v 1.14 2001/05/15 06:52:31 jmc Exp $ */ +/* $NetBSD: fwohcivar.h,v 1.15 2001/07/17 11:01:04 haya Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -50,13 +50,14 @@ #define OHCI_BUF_ARRS_CNT 8 #define OHCI_BUF_ATRQ_CNT (8*8) #define OHCI_BUF_ATRS_CNT (8*8) -#define OHCI_BUF_IR_CNT 16 +#define OHCI_BUF_IR_CNT 8 #define OHCI_BUF_CNT \ (OHCI_BUF_ARRQ_CNT + OHCI_BUF_ARRS_CNT + OHCI_BUF_ATRQ_CNT + \ OHCI_BUF_ATRS_CNT + OHCI_BUF_IR_CNT + 1 + 1) #define OHCI_LOOP 1000 #define OHCI_SELFID_TIMEOUT (hz * 3) +#define OHCI_ASYNC_STREAM 0x40 struct fwohci_softc; struct fwohci_pkt; @@ -65,10 +66,10 @@ struct fwohci_buf { TAILQ_ENTRY(fwohci_buf) fb_list; bus_dma_segment_t fb_seg; int fb_nseg; - bus_dmamap_t fb_dmamap; - caddr_t fb_buf; - struct fwohci_desc *fb_desc; - bus_addr_t fb_daddr; + bus_dmamap_t fb_dmamap; /* DMA map of the buffer */ + caddr_t fb_buf; /* kernel virtual addr of the buffer */ + struct fwohci_desc *fb_desc; /* kernel virtual addr of descriptor */ + bus_addr_t fb_daddr; /* physical addr of the descriptor */ int fb_off; struct mbuf *fb_m; void *fb_statusarg; @@ -103,10 +104,11 @@ struct fwohci_handler { struct fwohci_ctx { int fc_ctx; - int fc_isoch; + int fc_type; /* FWOHCI_CTX_(ASYNC|ISO_SINGLE|ISO_MULTI) */ int fc_bufcnt; u_int32_t *fc_branch; TAILQ_HEAD(fwohci_buf_s, fwohci_buf) fc_buf; + struct fwohci_buf_s fc_buf2; /* for iso */ LIST_HEAD(, fwohci_handler) fc_handler; }; @@ -131,6 +133,8 @@ struct fwohci_cb { struct fwohci_softc { struct ieee1394_softc sc_sc1394; struct evcnt sc_intrcnt; + struct evcnt sc_isocnt; + struct evcnt sc_isopktcnt; bus_space_tag_t sc_memt; bus_space_handle_t sc_memh; @@ -195,6 +199,10 @@ int fwohci_print (void *, const char *); #define OHCI_CSR_READ(sc, reg) \ le32toh(bus_space_read_4((sc)->sc_memt, (sc)->sc_memh, reg)) +#define FWOHCI_CTX_ASYNC 0 +#define FWOHCI_CTX_ISO_SINGLE 1 /* for async stream */ +#define FWOHCI_CTX_ISO_MULTI 2 /* for isochronous */ + /* Locators. */ #include "locators.h" diff --git a/sys/dev/ieee1394/ieee1394reg.h b/sys/dev/ieee1394/ieee1394reg.h index ed039d03e7a1..e59d6dd89ccb 100644 --- a/sys/dev/ieee1394/ieee1394reg.h +++ b/sys/dev/ieee1394/ieee1394reg.h @@ -1,4 +1,4 @@ -/* $NetBSD: ieee1394reg.h,v 1.8 2001/05/01 06:15:43 enami Exp $ */ +/* $NetBSD: ieee1394reg.h,v 1.9 2001/07/17 11:01:04 haya Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -134,6 +134,7 @@ struct ieee1394_async_nodata { #endif #define IEEE1394_BCAST_PHY_ID 0x3f +#define IEEE1394_ISOCH_MASK 0x3f /* * Transaction code