New Feature: Add isochronous stream input routine. This feature has

been tested on i386.  It does not have any interface for useland to
get isochoronous stream.  The isochoronous acquisition interface
should be determined.
This commit is contained in:
haya 2001-07-17 11:01:03 +00:00
parent d699caad5a
commit 8a1cc19a9f
3 changed files with 378 additions and 40 deletions

View File

@ -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 <onoe@netbsd.org>.
*/
/*
* The first version to support isochronous acquisition part is wrtten
* by HAYAKAWA Koichi <haya@netbsd.org>.
*/
#include "opt_inet.h"
#include <sys/param.h>
@ -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<<i)) && sc->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 *))

View File

@ -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"

View File

@ -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