Various small changes.
Clean up one bug in a DPRINTF in arrs_input which could panic on some packets. Gut the ack/response functionality and clean it up so all packets get checked correctly and the abuf struct isn't used once the ab_cb has happened (there still could be ack packets waiting to be processed at that time). Finally, add some documentation explaining read/write/inreg and their purpose/argument calling.
This commit is contained in:
parent
d91da495a9
commit
c3967bca55
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fwohci.c,v 1.30 2001/05/13 05:01:42 jmc Exp $ */
|
||||
/* $NetBSD: fwohci.c,v 1.31 2001/05/15 06:52:30 jmc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -147,9 +147,9 @@ static int fwohci_if_output(struct device *, struct mbuf *,
|
|||
void (*)(struct device *, struct mbuf *));
|
||||
static int fwohci_read(struct ieee1394_abuf *);
|
||||
static int fwohci_write(struct ieee1394_abuf *);
|
||||
static int fwohci_extract_resp(struct fwohci_softc *, void *,
|
||||
struct fwohci_pkt *);
|
||||
static int fwohci_multi_resp(struct fwohci_softc *, void *,
|
||||
static int fwohci_read_resp(struct fwohci_softc *, void *, struct fwohci_pkt *);
|
||||
static int fwohci_write_ack(struct fwohci_softc *, void *, struct fwohci_pkt *);
|
||||
static int fwohci_read_multi_resp(struct fwohci_softc *, void *,
|
||||
struct fwohci_pkt *);
|
||||
static int fwohci_inreg(struct ieee1394_abuf *, int);
|
||||
static int fwohci_parse_input(struct fwohci_softc *, void *,
|
||||
|
@ -1550,15 +1550,8 @@ fwohci_arrs_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#ifdef FW_DEBUG
|
||||
if (fh == NULL) {
|
||||
if (fh == NULL)
|
||||
DPRINTFN(1, ("fwohci_arrs_input: no listner\n"));
|
||||
DPRINTFN(1, ("src: %d, rcode: %d, tlabel: %d, tcode: "
|
||||
"%d hdr[3]: 0x%08x, data: 0x%08lx\n", srcid, rcode,
|
||||
tlabel, pkt.fp_tcode, pkt.fp_hdr[3],
|
||||
(unsigned long)(*((int *)pkt.fp_iov[0].iov_base))));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
fwohci_buf_next(sc, fc);
|
||||
OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
|
||||
|
@ -2771,6 +2764,52 @@ fwohci_if_output(struct device *self, struct mbuf *m0,
|
|||
* send/receive data.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These break down into 4 routines as follows:
|
||||
*
|
||||
* int fwohci_read(struct ieee1394_abuf *)
|
||||
*
|
||||
* This routine will attempt to read a region from the requested node.
|
||||
* A callback must be provided which will be called when either the completed
|
||||
* read is done or an unrecoverable error occurs. This is mainly a convenience
|
||||
* routine since it will encapsulate retrying a region as quadlet vs. block reads
|
||||
* and recombining all the returned data. This could also be done with a series
|
||||
* of write/inreg's for each packet sent.
|
||||
*
|
||||
* int fwohci_write(struct ieee1394_abuf *)
|
||||
*
|
||||
* The work horse main entry point for putting packets on the bus. This is the
|
||||
* generalized interface for fwnode/etc code to put packets out onto the bus.
|
||||
* It accepts all standard ieee1394 tcodes (XXX: only a few today) and optionally
|
||||
* will callback via a func pointer to the calling code with the resulting ACK
|
||||
* code from the packet. If the ACK code is to be ignored (i.e. no cb) then the
|
||||
* write routine will take care of free'ing the abuf since the fwnode/etc code
|
||||
* won't have any knowledge of when to do this. This allows for simple one-off
|
||||
* packets to be sent from the upper-level code without worrying about a callback
|
||||
* for cleanup.
|
||||
*
|
||||
* int fwohci_inreg(struct ieee1394_abuf *, int)
|
||||
*
|
||||
* This is very simple. It evals the abuf passed in and registers an internal
|
||||
* handler as the callback for packets received for that operation.
|
||||
* The integer argument specifies whether on a block read/write operation to
|
||||
* allow sub-regions to be read/written (in block form) as well.
|
||||
*
|
||||
* XXX: This whole structure needs to be redone as a list of regions and
|
||||
* operations allowed on those regions.
|
||||
*
|
||||
* int fwohci_unreg(struct ieee1394_abuf *, int)
|
||||
*
|
||||
* XXX: TBD. For now passing in a NULL ab_cb to inreg will unregister. This
|
||||
* routine will simply verify ab_cb is NULL and call inreg.
|
||||
*
|
||||
* This simply unregisters the respective callback done via inreg for items
|
||||
* which only need to register an area for a one-time operation (like a status
|
||||
* buffer a remote node will write to when the current operation is done). The
|
||||
* int argument specifies the same behavior as inreg, except in reverse (i.e.
|
||||
* it unregisters).
|
||||
*/
|
||||
|
||||
static int
|
||||
fwohci_read(struct ieee1394_abuf *ab)
|
||||
{
|
||||
|
@ -2778,9 +2817,19 @@ fwohci_read(struct ieee1394_abuf *ab)
|
|||
struct ieee1394_softc *sc = ab->ab_req;
|
||||
struct fwohci_softc *psc =
|
||||
(struct fwohci_softc *)sc->sc1394_dev.dv_parent;
|
||||
struct fwohci_cb *fcb;
|
||||
u_int32_t high, lo;
|
||||
int rv, tcode;
|
||||
|
||||
/* Have to have a callback when reading. */
|
||||
if (ab->ab_cb == NULL)
|
||||
return -1;
|
||||
|
||||
fcb = malloc(sizeof(struct fwohci_cb), M_DEVBUF, M_WAITOK);
|
||||
fcb->ab = ab;
|
||||
fcb->count = 0;
|
||||
fcb->abuf_valid = 1;
|
||||
|
||||
high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
|
||||
lo = (ab->ab_csr & 0x00000000ffffffff);
|
||||
|
||||
|
@ -2802,15 +2851,19 @@ fwohci_read(struct ieee1394_abuf *ab)
|
|||
pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) |
|
||||
(psc->sc_tlabel << 10) | (pkt.fp_tcode << 4);
|
||||
|
||||
pkt.fp_statusarg = ab;
|
||||
pkt.fp_statuscb = fwohci_extract_resp;
|
||||
pkt.fp_statusarg = fcb;
|
||||
pkt.fp_statuscb = fwohci_read_resp;
|
||||
|
||||
rv = fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
|
||||
psc->sc_tlabel, fwohci_extract_resp, ab);
|
||||
psc->sc_tlabel, fwohci_read_resp, fcb);
|
||||
if (rv)
|
||||
return rv;
|
||||
psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f;
|
||||
rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
|
||||
if (rv)
|
||||
fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id,
|
||||
psc->sc_tlabel, NULL, NULL);
|
||||
psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f;
|
||||
fcb->count = 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -2836,6 +2889,9 @@ fwohci_write(struct ieee1394_abuf *ab)
|
|||
pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
|
||||
pkt.fp_uio.uio_rw = UIO_WRITE;
|
||||
|
||||
pkt.fp_statusarg = ab;
|
||||
pkt.fp_statuscb = fwohci_write_ack;
|
||||
|
||||
switch (ab->ab_tcode) {
|
||||
case IEEE1394_TCODE_WRITE_RESP:
|
||||
pkt.fp_hlen = 12;
|
||||
|
@ -2880,12 +2936,6 @@ fwohci_write(struct ieee1394_abuf *ab)
|
|||
rv = fwohci_at_output(psc, psc->sc_ctx_atrs, &pkt);
|
||||
break;
|
||||
default:
|
||||
rv = fwohci_handler_set(psc, IEEE1394_TCODE_WRITE_RESP,
|
||||
ab->ab_req->sc1394_node_id, psc->sc_tlabel,
|
||||
fwohci_extract_resp, ab);
|
||||
if (rv)
|
||||
return rv;
|
||||
psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f;
|
||||
rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
|
||||
break;
|
||||
}
|
||||
|
@ -2893,76 +2943,70 @@ fwohci_write(struct ieee1394_abuf *ab)
|
|||
}
|
||||
|
||||
static int
|
||||
fwohci_extract_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
|
||||
fwohci_read_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
|
||||
{
|
||||
struct ieee1394_abuf *ab = (struct ieee1394_abuf *)arg;
|
||||
struct fwohci_cb *fcb = arg;
|
||||
struct ieee1394_abuf *ab = fcb->ab;
|
||||
struct fwohci_pkt newpkt;
|
||||
u_int16_t status;
|
||||
u_int32_t *cur, high, lo;
|
||||
int i, rcode, rv;
|
||||
|
||||
status = 0;
|
||||
int i, tcode, rcode, status, rv;
|
||||
|
||||
/*
|
||||
* No callback just means we want to have something clean up the abuf.
|
||||
* Both the ACK handling and normal response callbacks are handled here.
|
||||
* The main reason for this is the various error conditions that can
|
||||
* occur trying to block read some areas and the ways that gets reported
|
||||
* back to calling station. This is a variety of ACK codes, responses,
|
||||
* etc which makes it much more difficult to process if both aren't
|
||||
* handled here.
|
||||
*/
|
||||
|
||||
if (ab->ab_cb == NULL) {
|
||||
if (ab->ab_data)
|
||||
free(ab->ab_data, M_1394DATA);
|
||||
if (ab)
|
||||
free(ab, M_1394DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check for status packet. */
|
||||
|
||||
if (pkt->fp_tcode == -1) {
|
||||
status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
|
||||
pkt->fp_tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
|
||||
rcode = -1;
|
||||
tcode = (pkt->fp_hdr[0] >> 4) & 0xf;
|
||||
if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
|
||||
(status != OHCI_CTXCTL_EVENT_ACK_PENDING))
|
||||
DPRINTF(("Got status packet: 0x%02x\n",
|
||||
(unsigned int)status));
|
||||
fcb->count--;
|
||||
|
||||
/* See below for this exception that's trapped internally. */
|
||||
if (ab->ab_ackcb &&
|
||||
!((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) &&
|
||||
(pkt->fp_tcode == IEEE1394_TCODE_READ_REQ_BLOCK))) {
|
||||
|
||||
/*
|
||||
* XXX: Deal with this better. Trap OHCI code and
|
||||
* translate/deal with the results.
|
||||
*/
|
||||
|
||||
if (status >= OHCI_CTXCTL_EVENT_RESERVED16)
|
||||
status = status & 0xf;
|
||||
else
|
||||
status = 0;
|
||||
ab->ab_ackcb(ab, status);
|
||||
/*
|
||||
* Got all the ack's back and the buffer is invalid (i.e. the
|
||||
* callback has been called. Clean up.
|
||||
*/
|
||||
|
||||
if (fcb->abuf_valid == 0) {
|
||||
if (fcb->count == 0)
|
||||
free(fcb, M_DEVBUF);
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
}
|
||||
if (!((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) &&
|
||||
(pkt->fp_tcode == IEEE1394_TCODE_READ_REQ_BLOCK)))
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
|
||||
} else
|
||||
} else {
|
||||
status = -1;
|
||||
tcode = pkt->fp_tcode;
|
||||
rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some area's (like the config rom want to be read as quadlets only.
|
||||
*
|
||||
* The current ideas to try are:
|
||||
*
|
||||
* Got an ACK_TYPE_ERROR on a block read
|
||||
* Got an ACK_TYPE_ERROR on a block read.
|
||||
*
|
||||
* Got either RCODE_TYPE or RCODE_ADDRESS errors in a read block response
|
||||
* Got either RCODE_TYPE or RCODE_ADDRESS errors in a block read
|
||||
* response.
|
||||
*
|
||||
* If all cases construct a new packet for a quadlet read and let
|
||||
* In all cases construct a new packet for a quadlet read and let
|
||||
* mutli_resp handle the iteration over the space.
|
||||
*/
|
||||
|
||||
if (((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) &&
|
||||
(pkt->fp_tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) ||
|
||||
(tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) ||
|
||||
(((rcode == IEEE1394_RCODE_TYPE_ERROR) ||
|
||||
(rcode == IEEE1394_RCODE_ADDRESS_ERROR)) &&
|
||||
(pkt->fp_tcode == IEEE1394_TCODE_READ_RESP_BLOCK))) {
|
||||
(rcode == IEEE1394_RCODE_ADDRESS_ERROR)) &&
|
||||
(tcode == IEEE1394_TCODE_READ_RESP_BLOCK))) {
|
||||
|
||||
/* Read the area in quadlet chunks (internally track this). */
|
||||
|
||||
|
@ -2982,49 +3026,80 @@ fwohci_extract_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
|
|||
|
||||
rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
|
||||
ab->ab_req->sc1394_node_id, sc->sc_tlabel,
|
||||
fwohci_multi_resp, ab);
|
||||
if (rv)
|
||||
return rv;
|
||||
sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
|
||||
if (ab->ab_ackcb) {
|
||||
newpkt.fp_statusarg = ab;
|
||||
newpkt.fp_statuscb = fwohci_extract_resp;
|
||||
fwohci_read_multi_resp, fcb);
|
||||
if (rv) {
|
||||
(*ab->ab_cb)(ab, -1);
|
||||
goto cleanup;
|
||||
}
|
||||
fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
|
||||
} else {
|
||||
newpkt.fp_statusarg = fcb;
|
||||
newpkt.fp_statuscb = fwohci_read_resp;
|
||||
rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
|
||||
if (rv) {
|
||||
fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
|
||||
ab->ab_req->sc1394_node_id, sc->sc_tlabel, NULL,
|
||||
NULL);
|
||||
(*ab->ab_cb)(ab, -1);
|
||||
goto cleanup;
|
||||
}
|
||||
fcb->count++;
|
||||
sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
} else if ((rcode != -1) || ((status != -1) &&
|
||||
(status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
|
||||
(status != OHCI_CTXCTL_EVENT_ACK_PENDING))) {
|
||||
|
||||
/*
|
||||
* Recombine all the iov data into 1 chunk for higher
|
||||
* level code.
|
||||
*/
|
||||
|
||||
cur = ab->ab_data;
|
||||
for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
|
||||
/*
|
||||
* Make sure and don't exceed the buffer
|
||||
* allocated for return.
|
||||
*/
|
||||
if ((ab->ab_retlen + pkt->fp_iov[i].iov_len) >
|
||||
ab->ab_length) {
|
||||
if (rcode != -1) {
|
||||
cur = ab->ab_data;
|
||||
for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) {
|
||||
/*
|
||||
* Make sure and don't exceed the buffer
|
||||
* allocated for return.
|
||||
*/
|
||||
if ((ab->ab_retlen + pkt->fp_iov[i].iov_len) >
|
||||
ab->ab_length) {
|
||||
memcpy(cur, pkt->fp_iov[i].iov_base,
|
||||
(ab->ab_length - ab->ab_retlen));
|
||||
ab->ab_retlen = ab->ab_length;
|
||||
break;
|
||||
}
|
||||
memcpy(cur, pkt->fp_iov[i].iov_base,
|
||||
(ab->ab_length - ab->ab_retlen));
|
||||
ab->ab_retlen = ab->ab_length;
|
||||
break;
|
||||
pkt->fp_iov[i].iov_len);
|
||||
cur += pkt->fp_iov[i].iov_len;
|
||||
ab->ab_retlen += pkt->fp_iov[i].iov_len;
|
||||
}
|
||||
memcpy(cur, pkt->fp_iov[i].iov_base,
|
||||
pkt->fp_iov[i].iov_len);
|
||||
cur += pkt->fp_iov[i].iov_len;
|
||||
ab->ab_retlen += pkt->fp_iov[i].iov_len;
|
||||
}
|
||||
if (status != -1)
|
||||
/* XXX: Need a complete tlabel interface. */
|
||||
for (i = 0; i < 64; i++)
|
||||
fwohci_handler_set(sc,
|
||||
IEEE1394_TCODE_READ_RESP_QUAD,
|
||||
ab->ab_req->sc1394_node_id, i, NULL, NULL);
|
||||
(*ab->ab_cb)(ab, rcode);
|
||||
}
|
||||
goto cleanup;
|
||||
} else
|
||||
/* Good ack packet. */
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
|
||||
/* Can't get here unless ab->ab_cb has been called. */
|
||||
|
||||
cleanup:
|
||||
fcb->abuf_valid = 0;
|
||||
if (fcb->count == 0)
|
||||
free(fcb, M_DEVBUF);
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
}
|
||||
|
||||
static int
|
||||
fwohci_multi_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
|
||||
fwohci_read_multi_resp(struct fwohci_softc *sc, void *arg,
|
||||
struct fwohci_pkt *pkt)
|
||||
{
|
||||
struct ieee1394_abuf *ab = (struct ieee1394_abuf *)arg;
|
||||
struct fwohci_cb *fcb = arg;
|
||||
struct ieee1394_abuf *ab = fcb->ab;
|
||||
struct fwohci_pkt newpkt;
|
||||
u_int32_t high, lo;
|
||||
int rcode, rv;
|
||||
|
@ -3034,11 +3109,15 @@ fwohci_multi_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
|
|||
* buf.
|
||||
*/
|
||||
|
||||
/* Make sure a response packet didn't arrive after a bad ACK. */
|
||||
if (fcb->abuf_valid == 0)
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
|
||||
rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12;
|
||||
|
||||
if (rcode) {
|
||||
(*ab->ab_cb)(ab, rcode);
|
||||
return rcode;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((ab->ab_retlen + pkt->fp_iov[0].iov_len) > ab->ab_length) {
|
||||
|
@ -3066,25 +3145,64 @@ fwohci_multi_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
|
|||
newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
|
||||
(newpkt.fp_tcode << 4);
|
||||
|
||||
newpkt.fp_statusarg = fcb;
|
||||
newpkt.fp_statuscb = fwohci_read_resp;
|
||||
|
||||
/*
|
||||
* Bad return code. Just give up and return what's
|
||||
* come in now.
|
||||
*/
|
||||
rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD,
|
||||
ab->ab_req->sc1394_node_id, sc->sc_tlabel,
|
||||
fwohci_multi_resp, ab);
|
||||
if (rv) {
|
||||
(*ab->ab_cb)(ab, rcode);
|
||||
return IEEE1394_RCODE_DATA_ERROR;
|
||||
fwohci_read_multi_resp, fcb);
|
||||
if (rv)
|
||||
(*ab->ab_cb)(ab, -1);
|
||||
else {
|
||||
rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
|
||||
if (rv) {
|
||||
fwohci_handler_set(sc,
|
||||
IEEE1394_TCODE_READ_RESP_QUAD,
|
||||
ab->ab_req->sc1394_node_id, sc->sc_tlabel,
|
||||
NULL, NULL);
|
||||
(*ab->ab_cb)(ab, -1);
|
||||
} else {
|
||||
sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
|
||||
fcb->count++;
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
}
|
||||
}
|
||||
sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
|
||||
rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt);
|
||||
if (rv) {
|
||||
(*ab->ab_cb)(ab, rcode);
|
||||
return IEEE1394_RCODE_DATA_ERROR;
|
||||
}
|
||||
} else
|
||||
(*ab->ab_cb)(ab, rcode);
|
||||
} else
|
||||
(*ab->ab_cb)(ab, IEEE1394_RCODE_COMPLETE);
|
||||
|
||||
cleanup:
|
||||
/* Can't get here unless ab_cb has been called. */
|
||||
fcb->abuf_valid = 0;
|
||||
if (fcb->count == 0)
|
||||
free(fcb, M_DEVBUF);
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
}
|
||||
|
||||
static int
|
||||
fwohci_write_ack(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
|
||||
{
|
||||
struct ieee1394_abuf *ab = arg;
|
||||
u_int16_t status;
|
||||
|
||||
|
||||
status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK;
|
||||
if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) &&
|
||||
(status != OHCI_CTXCTL_EVENT_ACK_PENDING))
|
||||
DPRINTF(("Got status packet: 0x%02x\n",
|
||||
(unsigned int)status));
|
||||
|
||||
/* No callback means this level should free the buffers. */
|
||||
if (ab->ab_cb)
|
||||
(*ab->ab_cb)(ab, status);
|
||||
else {
|
||||
if (ab->ab_data)
|
||||
free(ab->ab_data, M_1394DATA);
|
||||
free(ab, M_1394DATA);
|
||||
}
|
||||
return IEEE1394_RCODE_COMPLETE;
|
||||
}
|
||||
|
||||
|
@ -3095,31 +3213,51 @@ fwohci_inreg(struct ieee1394_abuf *ab, int allow)
|
|||
struct fwohci_softc *psc =
|
||||
(struct fwohci_softc *)sc->sc1394_dev.dv_parent;
|
||||
u_int32_t high, lo;
|
||||
int i, rv;
|
||||
int i, j, rv;
|
||||
|
||||
high = ((ab->ab_csr & 0x0000ffff00000000) >> 32);
|
||||
lo = (ab->ab_csr & 0x00000000ffffffff);
|
||||
|
||||
rv = 0;
|
||||
switch (ab->ab_tcode) {
|
||||
case IEEE1394_TCODE_READ_REQ_QUAD:
|
||||
case IEEE1394_TCODE_WRITE_REQ_QUAD:
|
||||
rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo,
|
||||
fwohci_parse_input, ab);
|
||||
if (ab->ab_cb)
|
||||
rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo,
|
||||
fwohci_parse_input, ab);
|
||||
else
|
||||
fwohci_handler_set(psc, ab->ab_tcode, high, lo, NULL,
|
||||
NULL);
|
||||
break;
|
||||
case IEEE1394_TCODE_READ_REQ_BLOCK:
|
||||
case IEEE1394_TCODE_WRITE_REQ_BLOCK:
|
||||
if (allow) {
|
||||
for (i = 0; i < (ab->ab_length / 4); i++) {
|
||||
rv = fwohci_handler_set(psc, ab->ab_tcode,
|
||||
high, lo + (i * 4),
|
||||
fwohci_parse_input, ab);
|
||||
if (rv)
|
||||
return rv;
|
||||
if (ab->ab_cb) {
|
||||
rv = fwohci_handler_set(psc,
|
||||
ab->ab_tcode, high, lo + (i * 4),
|
||||
fwohci_parse_input, ab);
|
||||
if (rv)
|
||||
break;
|
||||
} else
|
||||
fwohci_handler_set(psc, ab->ab_tcode,
|
||||
high, lo + (i * 4), NULL, NULL);
|
||||
}
|
||||
ab->ab_data = (void *)1;
|
||||
} else
|
||||
rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo,
|
||||
fwohci_parse_input, ab);
|
||||
if (i != (ab->ab_length / 4)) {
|
||||
j = i + 1;
|
||||
for (i = 0; i < j; i++)
|
||||
fwohci_handler_set(psc, ab->ab_tcode,
|
||||
high, lo + (i * 4), NULL, NULL);
|
||||
} else
|
||||
ab->ab_data = (void *)1;
|
||||
} else {
|
||||
if (ab->ab_cb)
|
||||
rv = fwohci_handler_set(psc, ab->ab_tcode, high,
|
||||
lo, fwohci_parse_input, ab);
|
||||
else
|
||||
fwohci_handler_set(psc, ab->ab_tcode, high, lo,
|
||||
NULL, NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DPRINTF(("Invalid registration tcode: %d\n", ab->ab_tcode));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fwohcivar.h,v 1.13 2001/05/13 05:01:43 jmc Exp $ */
|
||||
/* $NetBSD: fwohcivar.h,v 1.14 2001/05/15 06:52:31 jmc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -115,6 +115,19 @@ struct fwohci_uidtbl {
|
|||
u_int8_t fu_uid[8];
|
||||
};
|
||||
|
||||
/*
|
||||
* Needed to keep track of outstanding packets during a read op. Since the
|
||||
* packet stream is asynch it's possible to parse a response packet before the
|
||||
* ack bits are processed. In this case something needs to track whether the
|
||||
* abuf is still valid before possibly attempting to use items from within it.
|
||||
*/
|
||||
|
||||
struct fwohci_cb {
|
||||
struct ieee1394_abuf *ab;
|
||||
int count;
|
||||
int abuf_valid;
|
||||
};
|
||||
|
||||
struct fwohci_softc {
|
||||
struct ieee1394_softc sc_sc1394;
|
||||
struct evcnt sc_intrcnt;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ieee1394var.h,v 1.11 2001/05/15 06:30:30 jmc Exp $ */
|
||||
/* $NetBSD: ieee1394var.h,v 1.12 2001/05/15 06:52:30 jmc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
|
@ -57,7 +57,6 @@ struct ieee1394_abuf {
|
|||
u_int16_t ab_retlen; /* length returned from read. */
|
||||
u_int32_t ab_retries;
|
||||
void (*ab_cb)(struct ieee1394_abuf *, int);
|
||||
void (*ab_ackcb)(struct ieee1394_abuf *, int);
|
||||
void *ab_cbarg;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue