Fixes to make if_fw work:
- fwohci_arrq_input: Do not return if next packet is in the buffer, or the next packet cannot be received until the next receive interrupt. - fwohci_uid_collect: XXX change M_WAITOK to M_NOWAIT for now, since there is no lock but only one instance must be allowed here. split fwohci_uid_req() and retry to get uid. XXX need timer to wait some moment between retries... - Add DELAY(10) for wait loop. - split fwohci_buf_stop() into _stop_tx() and _stop_rx() because receiver should not be stopped at bus-reset. - split fwohci_buf_input() into _input() and _input_ppb() to improve performance slightly.
This commit is contained in:
parent
d136cfe99e
commit
3fc5f5722d
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fwohci.c,v 1.35 2001/06/28 14:41:28 onoe Exp $ */
|
||||
/* $NetBSD: fwohci.c,v 1.36 2001/06/29 14:57:24 onoe Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
@ -96,14 +96,17 @@ static void fwohci_ctx_init(struct fwohci_softc *, struct fwohci_ctx *);
|
||||
|
||||
static int fwohci_buf_alloc(struct fwohci_softc *, struct fwohci_buf *);
|
||||
static void fwohci_buf_free(struct fwohci_softc *, struct fwohci_buf *);
|
||||
static void fwohci_buf_init(struct fwohci_softc *);
|
||||
static void fwohci_buf_start(struct fwohci_softc *);
|
||||
static void fwohci_buf_stop(struct fwohci_softc *);
|
||||
static void fwohci_buf_init_rx(struct fwohci_softc *);
|
||||
static void fwohci_buf_start_rx(struct fwohci_softc *);
|
||||
static void fwohci_buf_stop_tx(struct fwohci_softc *);
|
||||
static void fwohci_buf_stop_rx(struct fwohci_softc *);
|
||||
static void fwohci_buf_next(struct fwohci_softc *, struct fwohci_ctx *);
|
||||
static int fwohci_buf_pktget(struct fwohci_softc *, struct fwohci_ctx *,
|
||||
caddr_t *, int);
|
||||
static int fwohci_buf_input(struct fwohci_softc *, struct fwohci_ctx *,
|
||||
struct fwohci_pkt *);
|
||||
static int fwohci_buf_input_ppb(struct fwohci_softc *, struct fwohci_ctx *,
|
||||
struct fwohci_pkt *);
|
||||
|
||||
static u_int8_t fwohci_phy_read(struct fwohci_softc *, u_int8_t);
|
||||
static void fwohci_phy_write(struct fwohci_softc *, u_int8_t, u_int8_t);
|
||||
@ -135,6 +138,7 @@ static int fwohci_csr_input(struct fwohci_softc *, void *,
|
||||
struct fwohci_pkt *);
|
||||
|
||||
static void fwohci_uid_collect(struct fwohci_softc *);
|
||||
static void fwohci_uid_req(struct fwohci_softc *, int);
|
||||
static int fwohci_uid_input(struct fwohci_softc *, void *,
|
||||
struct fwohci_pkt *);
|
||||
static int fwohci_uid_lookup(struct fwohci_softc *, const u_int8_t *);
|
||||
@ -189,6 +193,7 @@ fwohci_init(struct fwohci_softc *sc, const struct evcnt *ev)
|
||||
val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear);
|
||||
if ((val & OHCI_HCControl_SoftReset) == 0)
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
|
||||
/* What dialect of OHCI is this device?
|
||||
@ -252,6 +257,7 @@ fwohci_init(struct fwohci_softc *sc, const struct evcnt *ev)
|
||||
#endif
|
||||
|
||||
sc->sc_dying = 0;
|
||||
sc->sc_nodeid = 0xffff; /* invalid */
|
||||
|
||||
kthread_create(fwohci_create_event_thread, sc);
|
||||
return 0;
|
||||
@ -415,14 +421,13 @@ fwohci_event_thread(struct fwohci_softc *sc)
|
||||
|
||||
/* Initial Bus Reset */
|
||||
fwohci_phy_busreset(sc);
|
||||
tsleep(fwohci_event_thread, PZERO, "fwohci_event", 0);
|
||||
splx(s);
|
||||
|
||||
while (!sc->sc_dying) {
|
||||
s = splbio();
|
||||
intmask = sc->sc_intmask;
|
||||
if (intmask == 0) {
|
||||
tsleep(fwohci_event_thread, PZERO, "fwohci_event", 0);
|
||||
tsleep(fwohci_event_thread, PZERO, "fwohciev", 0);
|
||||
splx(s);
|
||||
continue;
|
||||
}
|
||||
@ -430,8 +435,7 @@ fwohci_event_thread(struct fwohci_softc *sc)
|
||||
splx(s);
|
||||
|
||||
if (intmask & OHCI_Int_BusReset) {
|
||||
fwohci_buf_stop(sc);
|
||||
fwohci_buf_init(sc);
|
||||
fwohci_buf_stop_tx(sc);
|
||||
if (sc->sc_uidtbl != NULL) {
|
||||
free(sc->sc_uidtbl, M_DEVBUF);
|
||||
sc->sc_uidtbl = NULL;
|
||||
@ -453,7 +457,7 @@ fwohci_event_thread(struct fwohci_softc *sc)
|
||||
splx(s);
|
||||
callout_stop(&sc->sc_selfid_callout);
|
||||
if (fwohci_selfid_input(sc) == 0) {
|
||||
fwohci_buf_start(sc);
|
||||
fwohci_buf_start_rx(sc);
|
||||
fwohci_uid_collect(sc);
|
||||
}
|
||||
}
|
||||
@ -545,6 +549,7 @@ fwohci_hw_init(struct fwohci_softc *sc)
|
||||
val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear);
|
||||
if ((val & OHCI_HCControl_SoftReset) == 0)
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
|
||||
OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS);
|
||||
@ -568,7 +573,7 @@ fwohci_hw_init(struct fwohci_softc *sc)
|
||||
|
||||
fwohci_configrom_init(sc);
|
||||
fwohci_selfid_init(sc);
|
||||
fwohci_buf_init(sc);
|
||||
fwohci_buf_init_rx(sc);
|
||||
fwohci_csr_init(sc);
|
||||
|
||||
/*
|
||||
@ -609,7 +614,7 @@ fwohci_hw_init(struct fwohci_softc *sc)
|
||||
/*
|
||||
* Start the receivers
|
||||
*/
|
||||
fwohci_buf_start(sc);
|
||||
fwohci_buf_start_rx(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -645,12 +650,14 @@ fwohci_shutdown(void *arg)
|
||||
callout_stop(&sc->sc_selfid_callout);
|
||||
/* disable all interrupt */
|
||||
OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, OHCI_Int_MasterEnable);
|
||||
fwohci_buf_stop(sc);
|
||||
fwohci_buf_stop_tx(sc);
|
||||
fwohci_buf_stop_rx(sc);
|
||||
val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
|
||||
val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_ISC |
|
||||
OHCI_BusOptions_CMC | OHCI_BusOptions_IRMC);
|
||||
OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val);
|
||||
fwohci_phy_busreset(sc);
|
||||
OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LinkEnable);
|
||||
OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LPS);
|
||||
OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset);
|
||||
}
|
||||
@ -674,6 +681,7 @@ fwohci_phy_read(struct fwohci_softc *sc, u_int8_t reg)
|
||||
if (OHCI_CSR_READ(sc, OHCI_REG_PhyControl) &
|
||||
OHCI_PhyControl_RdDone)
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
val = OHCI_CSR_READ(sc, OHCI_REG_PhyControl);
|
||||
return (val & OHCI_PhyControl_RdData) >> OHCI_PhyControl_RdData_BITPOS;
|
||||
@ -694,6 +702,7 @@ fwohci_phy_write(struct fwohci_softc *sc, u_int8_t reg, u_int8_t val)
|
||||
if (!(OHCI_CSR_READ(sc, OHCI_REG_PhyControl) &
|
||||
OHCI_PhyControl_WrReg))
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1001,16 +1010,10 @@ fwohci_buf_free(struct fwohci_softc *sc, struct fwohci_buf *fb)
|
||||
}
|
||||
|
||||
static void
|
||||
fwohci_buf_init(struct fwohci_softc *sc)
|
||||
fwohci_buf_init_rx(struct fwohci_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialize for Asynchronous Transmit Queue.
|
||||
*/
|
||||
fwohci_at_done(sc, sc->sc_ctx_atrq, 1);
|
||||
fwohci_at_done(sc, sc->sc_ctx_atrs, 1);
|
||||
|
||||
/*
|
||||
* Initialize for Asynchronous Receive Queue.
|
||||
*/
|
||||
@ -1027,7 +1030,7 @@ fwohci_buf_init(struct fwohci_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
fwohci_buf_start(struct fwohci_softc *sc)
|
||||
fwohci_buf_start_rx(struct fwohci_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1036,36 +1039,27 @@ fwohci_buf_start(struct fwohci_softc *sc)
|
||||
OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
|
||||
OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
|
||||
for (i = 0; i < sc->sc_isoctx; i++) {
|
||||
if (sc->sc_ctx_ir[i] != NULL &&
|
||||
LIST_FIRST(&sc->sc_ctx_ir[i]->fc_handler) != NULL) {
|
||||
if (sc->sc_ctx_ir[i] != NULL)
|
||||
OHCI_SYNC_RX_DMA_WRITE(sc, i,
|
||||
OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fwohci_buf_stop(struct fwohci_softc *sc)
|
||||
fwohci_buf_stop_tx(struct fwohci_softc *sc)
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_REQUEST,
|
||||
OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
|
||||
OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
|
||||
OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
|
||||
OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
|
||||
OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
|
||||
OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
|
||||
OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
|
||||
for (i = 0; i < sc->sc_isoctx; i++) {
|
||||
OHCI_SYNC_RX_DMA_WRITE(sc, i,
|
||||
OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the transmitter is stopped.
|
||||
*/
|
||||
for (j = 0; j < OHCI_LOOP; j++) {
|
||||
for (i = 0; i < OHCI_LOOP; i++) {
|
||||
DELAY(10);
|
||||
if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
|
||||
OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
|
||||
continue;
|
||||
@ -1074,6 +1068,27 @@ fwohci_buf_stop(struct fwohci_softc *sc)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize for Asynchronous Transmit Queue.
|
||||
*/
|
||||
fwohci_at_done(sc, sc->sc_ctx_atrq, 1);
|
||||
fwohci_at_done(sc, sc->sc_ctx_atrs, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
fwohci_buf_stop_rx(struct fwohci_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
|
||||
OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
|
||||
OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
|
||||
OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
|
||||
for (i = 0; i < sc->sc_isoctx; i++) {
|
||||
OHCI_SYNC_RX_DMA_WRITE(sc, i,
|
||||
OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1082,9 +1097,14 @@ 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 (fb->fb_off != fb->fb_desc->fd_reqcount ||
|
||||
fb->fb_desc->fd_rescount != 0)
|
||||
break;
|
||||
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;
|
||||
}
|
||||
TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
|
||||
fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount;
|
||||
fb->fb_off = 0;
|
||||
@ -1112,10 +1132,6 @@ fwohci_buf_pktget(struct fwohci_softc *sc, struct fwohci_ctx *fc, caddr_t *pp,
|
||||
fd->fd_reqcount - fd->fd_rescount - fb->fb_off));
|
||||
bufend = fd->fd_reqcount - fd->fd_rescount;
|
||||
if (fb->fb_off >= bufend) {
|
||||
if (fc->fc_isoch && fb->fb_off > 0) {
|
||||
fb->fb_off = fd->fd_reqcount;
|
||||
fd->fd_rescount = 0;
|
||||
}
|
||||
if (fd->fd_rescount == 0) {
|
||||
if ((fb = TAILQ_NEXT(fb, fb_list)) != NULL)
|
||||
goto again;
|
||||
@ -1145,21 +1161,6 @@ fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
|
||||
|
||||
/* get first quadlet */
|
||||
count = 4;
|
||||
if (fc->fc_isoch) {
|
||||
/*
|
||||
* get trailer first, may be bogus data unless status update
|
||||
* in descriptor is set.
|
||||
*/
|
||||
len = fwohci_buf_pktget(sc, fc, (caddr_t *)&pkt->fp_trail,
|
||||
sizeof(*pkt->fp_trail));
|
||||
if (len <= 0) {
|
||||
DPRINTFN(1, ("fwohci_buf_input: no input for is#%d\n",
|
||||
fc->fc_ctx));
|
||||
return 0;
|
||||
}
|
||||
*pkt->fp_trail = (*pkt->fp_trail & 0xffff) |
|
||||
(TAILQ_FIRST(&fc->fc_buf)->fb_desc->fd_status << 16);
|
||||
}
|
||||
len = fwohci_buf_pktget(sc, fc, &p, count);
|
||||
if (len <= 0) {
|
||||
DPRINTFN(1, ("fwohci_buf_input: no input for %d\n",
|
||||
@ -1184,10 +1185,11 @@ fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
|
||||
case IEEE1394_TCODE_LOCK_RESP:
|
||||
pkt->fp_hlen = 16;
|
||||
break;
|
||||
#ifdef DIAGNOSTICS
|
||||
case IEEE1394_TCODE_STREAM_DATA:
|
||||
pkt->fp_hlen = 4;
|
||||
pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
|
||||
break;
|
||||
printf("fwohci_buf_input: bad tcode: STREAM_DATA\n");
|
||||
return 0;
|
||||
#endif
|
||||
default:
|
||||
pkt->fp_hlen = 12;
|
||||
pkt->fp_dlen = 0;
|
||||
@ -1205,7 +1207,7 @@ fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
|
||||
memcpy((caddr_t)pkt->fp_hdr + count, p, len);
|
||||
count += len;
|
||||
}
|
||||
if ((pkt->fp_hlen == 16) &&
|
||||
if (pkt->fp_hlen == 16 &&
|
||||
pkt->fp_tcode != IEEE1394_TCODE_READ_REQ_BLOCK)
|
||||
pkt->fp_dlen = pkt->fp_hdr[3] >> 16;
|
||||
DPRINTFN(1, ("fwohci_buf_input: tcode=0x%x, hlen=%d, dlen=%d\n",
|
||||
@ -1220,7 +1222,7 @@ fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
|
||||
pkt->fp_dlen - count);
|
||||
if (len == 0) {
|
||||
printf("fwohci_buf_input: malformed input 2: %d\n",
|
||||
pkt->fp_hlen - count);
|
||||
pkt->fp_dlen - count);
|
||||
return 0;
|
||||
}
|
||||
pkt->fp_iov[i++].iov_len = len;
|
||||
@ -1229,19 +1231,84 @@ fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
|
||||
pkt->fp_uio.uio_iovcnt = i;
|
||||
pkt->fp_uio.uio_resid = count;
|
||||
|
||||
if (!fc->fc_isoch) {
|
||||
/* get trailer */
|
||||
len = fwohci_buf_pktget(sc, fc, (caddr_t *)&pkt->fp_trail,
|
||||
sizeof(*pkt->fp_trail));
|
||||
if (len <= 0) {
|
||||
printf("fwohci_buf_input: malformed input 3: %d\n",
|
||||
pkt->fp_hlen - count);
|
||||
return 0;
|
||||
}
|
||||
/* get trailer */
|
||||
len = fwohci_buf_pktget(sc, fc, (caddr_t *)&pkt->fp_trail,
|
||||
sizeof(*pkt->fp_trail));
|
||||
if (len <= 0) {
|
||||
printf("fwohci_buf_input: malformed input 3: %d\n",
|
||||
pkt->fp_hlen - count);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
fwohci_buf_input_ppb(struct fwohci_softc *sc, struct fwohci_ctx *fc,
|
||||
struct fwohci_pkt *pkt)
|
||||
{
|
||||
caddr_t p;
|
||||
int len;
|
||||
struct fwohci_buf *fb;
|
||||
struct fwohci_desc *fd;
|
||||
|
||||
memset(pkt, 0, sizeof(*pkt));
|
||||
pkt->fp_uio.uio_iov = pkt->fp_iov;
|
||||
pkt->fp_uio.uio_rw = UIO_WRITE;
|
||||
pkt->fp_uio.uio_segflg = UIO_SYSSPACE;
|
||||
|
||||
for (fb = TAILQ_FIRST(&fc->fc_buf); ; fb = TAILQ_NEXT(fb, fb_list)) {
|
||||
if (fb == NULL)
|
||||
return 0;
|
||||
if (fb->fb_off == 0)
|
||||
break;
|
||||
}
|
||||
fd = fb->fb_desc;
|
||||
len = fd->fd_reqcount - fd->fd_rescount;
|
||||
if (len == 0)
|
||||
return 0;
|
||||
bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len,
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
|
||||
p = fb->fb_buf;
|
||||
fb->fb_off += roundup(len, 4);
|
||||
if (len < 8) {
|
||||
printf("fwohci_buf_input_ppb: malformed input 1: %d\n", len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get trailer first, may be bogus data unless status update
|
||||
* in descriptor is set.
|
||||
*/
|
||||
pkt->fp_trail = (u_int32_t *)p;
|
||||
*pkt->fp_trail = (*pkt->fp_trail & 0xffff) | (fd->fd_status << 16);
|
||||
pkt->fp_hdr[0] = ((u_int32_t *)p)[1];
|
||||
pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4;
|
||||
#ifdef DIAGNOSTICS
|
||||
if (pkt->fp_tcode != IEEE1394_TCODE_STREAM_DATA) {
|
||||
printf("fwohci_buf_input_ppb: bad tcode: 0x%x\n",
|
||||
pkt->fp_tcode);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
pkt->fp_hlen = 4;
|
||||
pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
|
||||
p += 8;
|
||||
len -= 8;
|
||||
if (pkt->fp_dlen != len) {
|
||||
printf("fwohci_buf_input_ppb: malformed input 2: %d != %d\n",
|
||||
pkt->fp_dlen, len);
|
||||
return 0;
|
||||
}
|
||||
DPRINTFN(1, ("fwohci_buf_input_ppb: tcode=0x%x, hlen=%d, dlen=%d\n",
|
||||
pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen));
|
||||
pkt->fp_iov[0].iov_base = p;
|
||||
pkt->fp_iov[0].iov_len = len;
|
||||
pkt->fp_uio.uio_iovcnt = 0;
|
||||
pkt->fp_uio.uio_resid = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
fwohci_handler_set(struct fwohci_softc *sc,
|
||||
int tcode, u_int32_t key1, u_int32_t key2,
|
||||
@ -1262,10 +1329,6 @@ fwohci_handler_set(struct fwohci_softc *sc,
|
||||
continue;
|
||||
}
|
||||
fh = LIST_FIRST(&fc->fc_handler);
|
||||
if (fh == NULL) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
if (fh->fh_tcode == tcode &&
|
||||
fh->fh_key1 == key1 && fh->fh_key2 == key2)
|
||||
break;
|
||||
@ -1354,10 +1417,14 @@ fwohci_arrq_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
|
||||
struct fwohci_handler *fh;
|
||||
struct fwohci_pkt pkt, res;
|
||||
|
||||
/*
|
||||
* Do not return if next packet is in the buffer, or the next
|
||||
* packet cannot be received until the next receive interrupt.
|
||||
*/
|
||||
while (fwohci_buf_input(sc, fc, &pkt)) {
|
||||
if (pkt.fp_tcode == OHCI_TCODE_PHY) {
|
||||
fwohci_phy_input(sc, &pkt);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
key1 = pkt.fp_hdr[1] & 0xffff;
|
||||
key2 = pkt.fp_hdr[2];
|
||||
@ -1382,7 +1449,7 @@ fwohci_arrq_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
|
||||
}
|
||||
if (((*pkt.fp_trail & 0x001f0000) >> 16) !=
|
||||
OHCI_CTXCTL_EVENT_ACK_PENDING)
|
||||
return;
|
||||
continue;
|
||||
if (rcode != -1)
|
||||
fwohci_atrs_output(sc, rcode, &pkt, &res);
|
||||
}
|
||||
@ -1441,7 +1508,7 @@ fwohci_ir_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
|
||||
struct fwohci_handler *fh;
|
||||
struct fwohci_pkt pkt;
|
||||
|
||||
while (fwohci_buf_input(sc, fc, &pkt)) {
|
||||
while (fwohci_buf_input_ppb(sc, fc, &pkt)) {
|
||||
chan = (pkt.fp_hdr[0] & 0x00003f00) >> 8;
|
||||
tag = (pkt.fp_hdr[0] & 0x0000c000) >> 14;
|
||||
DPRINTFN(1, ("fwohci_ir_input: hdr 0x%08x, tcode %d, hlen %d, "
|
||||
@ -1501,7 +1568,7 @@ fwohci_at_output(struct fwohci_softc *sc, struct fwohci_ctx *fc,
|
||||
struct iovec *iov;
|
||||
#endif
|
||||
|
||||
if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) > sc->sc_rootid)
|
||||
if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == IEEE1394_BCAST_PHY_ID)
|
||||
/* We can't send anything during selfid duration */
|
||||
return EAGAIN;
|
||||
|
||||
@ -1695,6 +1762,7 @@ fwohci_at_done(struct fwohci_softc *sc, struct fwohci_ctx *fc, int force)
|
||||
OHCI_SUBREG_ContextControlClear) &
|
||||
OHCI_CTXCTL_ACTIVE))
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1802,6 +1870,7 @@ fwohci_guidrom_init(struct fwohci_softc *sc)
|
||||
val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
|
||||
if (!(val1 & OHCI_Guid_AddrReset))
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
off = OHCI_BITVAL(val1, OHCI_Guid_MiniROM) + 4;
|
||||
val2 = 0;
|
||||
@ -1812,6 +1881,7 @@ fwohci_guidrom_init(struct fwohci_softc *sc)
|
||||
val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
|
||||
if (!(val1 & OHCI_Guid_RdStart))
|
||||
break;
|
||||
DELAY(10);
|
||||
}
|
||||
if (n < off)
|
||||
continue;
|
||||
@ -2228,7 +2298,6 @@ fwohci_uid_collect(struct fwohci_softc *sc)
|
||||
{
|
||||
int i;
|
||||
struct fwohci_uidtbl *fu;
|
||||
struct fwohci_pkt pkt;
|
||||
struct ieee1394_softc *iea;
|
||||
|
||||
LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node)
|
||||
@ -2237,10 +2306,11 @@ fwohci_uid_collect(struct fwohci_softc *sc)
|
||||
if (sc->sc_uidtbl != NULL)
|
||||
free(sc->sc_uidtbl, M_DEVBUF);
|
||||
sc->sc_uidtbl = malloc(sizeof(*fu) * (sc->sc_rootid + 1), M_DEVBUF,
|
||||
M_WAITOK);
|
||||
M_NOWAIT); /* XXX M_WAITOK requires locks */
|
||||
if (sc->sc_uidtbl == NULL)
|
||||
return;
|
||||
memset(sc->sc_uidtbl, 0, sizeof(*fu) * (sc->sc_rootid + 1));
|
||||
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
for (i = 0, fu = sc->sc_uidtbl; i <= sc->sc_rootid; i++, fu++) {
|
||||
if (i == (sc->sc_nodeid & OHCI_NodeId_NodeNumber)) {
|
||||
memcpy(fu->fu_uid, sc->sc_sc1394.sc1394_guid, 8);
|
||||
@ -2253,34 +2323,42 @@ fwohci_uid_collect(struct fwohci_softc *sc)
|
||||
iea->sc1394_dev.dv_xname,
|
||||
iea->sc1394_node_id));
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
fu->fu_valid = 0;
|
||||
fwohci_uid_req(sc, i);
|
||||
}
|
||||
fu->fu_valid = 0;
|
||||
pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
|
||||
pkt.fp_hlen = 12;
|
||||
pkt.fp_dlen = 0;
|
||||
pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
|
||||
(pkt.fp_tcode << 4);
|
||||
pkt.fp_hdr[1] = ((0xffc0 | i) << 16) | CSR_BASE_HI;
|
||||
pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 12;
|
||||
fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, i,
|
||||
sc->sc_tlabel, fwohci_uid_input, (void *)0);
|
||||
sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
|
||||
fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
|
||||
|
||||
pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
|
||||
(pkt.fp_tcode << 4);
|
||||
pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 16;
|
||||
fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, i,
|
||||
sc->sc_tlabel, fwohci_uid_input, (void *)1);
|
||||
sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
|
||||
fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
|
||||
|
||||
}
|
||||
if (sc->sc_rootid == 0)
|
||||
fwohci_check_nodes(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
fwohci_uid_req(struct fwohci_softc *sc, int phyid)
|
||||
{
|
||||
struct fwohci_pkt pkt;
|
||||
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
|
||||
pkt.fp_hlen = 12;
|
||||
pkt.fp_dlen = 0;
|
||||
pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
|
||||
(pkt.fp_tcode << 4);
|
||||
pkt.fp_hdr[1] = ((0xffc0 | phyid) << 16) | CSR_BASE_HI;
|
||||
pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 12;
|
||||
fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid,
|
||||
sc->sc_tlabel, fwohci_uid_input, (void *)0);
|
||||
sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
|
||||
fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
|
||||
|
||||
pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
|
||||
(pkt.fp_tcode << 4);
|
||||
pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 16;
|
||||
fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid,
|
||||
sc->sc_tlabel, fwohci_uid_input, (void *)1);
|
||||
sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
|
||||
fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
|
||||
}
|
||||
|
||||
static int
|
||||
fwohci_uid_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *res)
|
||||
{
|
||||
@ -2391,19 +2469,26 @@ fwohci_uid_lookup(struct fwohci_softc *sc, const u_int8_t *uid)
|
||||
|
||||
fu = sc->sc_uidtbl;
|
||||
if (fu == NULL) {
|
||||
notfound:
|
||||
if (memcmp(uid, bcast, sizeof(bcast)) == 0)
|
||||
return IEEE1394_BCAST_PHY_ID;
|
||||
fwohci_uid_collect(sc); /* try to get */
|
||||
return -1;
|
||||
}
|
||||
for (n = 0; ; n++, fu++) {
|
||||
if (n > sc->sc_rootid)
|
||||
goto notfound;
|
||||
for (n = 0; n <= sc->sc_rootid; n++, fu++) {
|
||||
if (fu->fu_valid == 0x3 && memcmp(fu->fu_uid, uid, 8) == 0)
|
||||
break;
|
||||
return n;
|
||||
}
|
||||
return n;
|
||||
if (memcmp(uid, bcast, sizeof(bcast)) == 0)
|
||||
return IEEE1394_BCAST_PHY_ID;
|
||||
for (n = 0, fu = sc->sc_uidtbl; n <= sc->sc_rootid; n++, fu++) {
|
||||
if (fu->fu_valid != 0x3) {
|
||||
/*
|
||||
* XXX: need timer before retransmission
|
||||
*/
|
||||
fwohci_uid_req(sc, n);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2465,6 +2550,7 @@ fwohci_if_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
|
||||
printf("%s: packet from unknown node: phy id %d\n",
|
||||
sc->sc_sc1394.sc1394_dev.dv_xname, n);
|
||||
m_freem(m);
|
||||
fwohci_uid_req(sc, n);
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
}
|
||||
memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
|
||||
|
Loading…
Reference in New Issue
Block a user