Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ieee1394 Various small changes.



details:   https://anonhg.NetBSD.org/src/rev/f101d6c5cb7f
branches:  trunk
changeset: 509891:f101d6c5cb7f
user:      jmc <jmc%NetBSD.org@localhost>
date:      Tue May 15 06:52:30 2001 +0000

description:
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.

diffstat:

 sys/dev/ieee1394/fwohci.c      |  374 ++++++++++++++++++++++++++++------------
 sys/dev/ieee1394/fwohcivar.h   |   15 +-
 sys/dev/ieee1394/ieee1394var.h |    3 +-
 3 files changed, 271 insertions(+), 121 deletions(-)

diffs (truncated from 586 to 300 lines):

diff -r d5c74b356329 -r f101d6c5cb7f sys/dev/ieee1394/fwohci.c
--- a/sys/dev/ieee1394/fwohci.c Tue May 15 06:30:30 2001 +0000
+++ b/sys/dev/ieee1394/fwohci.c Tue May 15 06:52:30 2001 +0000
@@ -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 @@
     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 @@
                                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 @@
  * 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 @@
        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 @@
        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;
+       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;
-       rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt);
+       fcb->count = 1;
        return rv;
 }
 
@@ -2836,6 +2889,9 @@
        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 @@
                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 @@
 }
 
 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;
-
-               /* 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);
+               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--;
+
+               /*
+                * 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 @@
 
                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;
+                   fwohci_read_multi_resp, fcb);
+               if (rv) {
+                       (*ab->ab_cb)(ab, -1);
+                       goto cleanup;
+               }
+               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;
-               if (ab->ab_ackcb) {
-                       newpkt.fp_statusarg = ab;



Home | Main Index | Thread Index | Old Index