1 /* $NetBSD: fwohci.c,v 1.64 2002/12/06 02:17:30 jmc Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * IEEE1394 Open Host Controller Interface 41 * based on OHCI Specification 1.1 (January 6, 2000) 42 * The first version to support network interface part is wrtten by 43 * Atsushi Onoe <onoe@netbsd.org>. 44 */ 45 46 /* 47 * The first version to support isochronous acquisition part is wrtten 48 * by HAYAKAWA Koichi <haya@netbsd.org>. 49 */ 50 51 #include <sys/cdefs.h> 52 __KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.64 2002/12/06 02:17:30 jmc Exp $"); 53 54 #define FWOHCI_WAIT_DEBUG 1 55 56 #define FWOHCI_IT_BUFNUM 4 57 58 #include "opt_inet.h" 59 #include "fwiso.h" 60 61 #include <sys/param.h> 62 #include <sys/systm.h> 63 #include <sys/kthread.h> 64 #include <sys/socket.h> 65 #include <sys/callout.h> 66 #include <sys/device.h> 67 #include <sys/kernel.h> 68 #include <sys/malloc.h> 69 #include <sys/mbuf.h> 70 #include <sys/poll.h> 71 #include <sys/select.h> 72 73 #if __NetBSD_Version__ >= 105010000 74 #include <uvm/uvm_extern.h> 75 #else 76 #include <vm/vm.h> 77 #endif 78 79 #include <machine/bus.h> 80 #include <machine/intr.h> 81 82 #include <dev/ieee1394/ieee1394reg.h> 83 #include <dev/ieee1394/fwohcireg.h> 84 85 #include <dev/ieee1394/ieee1394var.h> 86 #include <dev/ieee1394/fwohcivar.h> 87 #include <dev/ieee1394/fwisovar.h> 88 89 static const char * const ieee1394_speeds[] = { IEEE1394_SPD_STRINGS }; 90 91 #if 0 92 static int fwohci_dnamem_alloc(struct fwohci_softc *sc, int size, 93 int alignment, bus_dmamap_t *mapp, caddr_t *kvap, int flags); 94 #endif 95 static void fwohci_create_event_thread(void *); 96 static void fwohci_thread_init(void *); 97 98 static void fwohci_event_thread(struct fwohci_softc *); 99 static void fwohci_hw_init(struct fwohci_softc *); 100 static void fwohci_power(int, void *); 101 static void fwohci_shutdown(void *); 102 103 static int fwohci_desc_alloc(struct fwohci_softc *); 104 static struct fwohci_desc *fwohci_desc_get(struct fwohci_softc *, int); 105 static void fwohci_desc_put(struct fwohci_softc *, struct fwohci_desc *, int); 106 107 static int fwohci_ctx_alloc(struct fwohci_softc *, struct fwohci_ctx **, 108 int, int, int); 109 static void fwohci_ctx_free(struct fwohci_softc *, struct fwohci_ctx *); 110 static void fwohci_ctx_init(struct fwohci_softc *, struct fwohci_ctx *); 111 112 static int fwohci_misc_dmabuf_alloc(bus_dma_tag_t, int, int, 113 bus_dma_segment_t *, bus_dmamap_t *, void **, const char *); 114 static void fwohci_misc_dmabuf_free(bus_dma_tag_t, int, int, 115 bus_dma_segment_t *, bus_dmamap_t *, caddr_t); 116 117 static struct fwohci_ir_ctx *fwohci_ir_ctx_construct(struct fwohci_softc *, 118 int, int, int, int, int, int); 119 static void fwohci_ir_ctx_destruct(struct fwohci_ir_ctx *); 120 121 static int fwohci_ir_buf_setup(struct fwohci_ir_ctx *); 122 static int fwohci_ir_init(struct fwohci_ir_ctx *); 123 static int fwohci_ir_start(struct fwohci_ir_ctx *); 124 static void fwohci_ir_intr(struct fwohci_softc *, struct fwohci_ir_ctx *); 125 static int fwohci_ir_stop(struct fwohci_ir_ctx *); 126 static int fwohci_ir_ctx_packetnum(struct fwohci_ir_ctx *); 127 #ifdef USEDRAIN 128 static int fwohci_ir_ctx_drain(struct fwohci_ir_ctx *); 129 #endif /* USEDRAIN */ 130 131 static int fwohci_it_desc_alloc(struct fwohci_it_ctx *); 132 static void fwohci_it_desc_free(struct fwohci_it_ctx *itc); 133 struct fwohci_it_ctx *fwohci_it_ctx_construct(struct fwohci_softc *, 134 int, int, int, int); 135 void fwohci_it_ctx_destruct(struct fwohci_it_ctx *); 136 int fwohci_it_ctx_writedata(ieee1394_it_tag_t, int, 137 struct ieee1394_it_datalist *, int); 138 static void fwohci_it_ctx_run(struct fwohci_it_ctx *); 139 int fwohci_it_ctx_flush(ieee1394_it_tag_t); 140 static void fwohci_it_intr(struct fwohci_softc *, struct fwohci_it_ctx *); 141 142 int fwohci_itd_construct(struct fwohci_it_ctx *, struct fwohci_it_dmabuf *, 143 int, struct fwohci_desc *, bus_addr_t, int, int, paddr_t); 144 void fwohci_itd_destruct(struct fwohci_it_dmabuf *); 145 static int fwohci_itd_dmabuf_alloc(struct fwohci_it_dmabuf *); 146 static void fwohci_itd_dmabuf_free(struct fwohci_it_dmabuf *); 147 int fwohci_itd_link(struct fwohci_it_dmabuf *, struct fwohci_it_dmabuf *); 148 int fwohci_itd_unlink(struct fwohci_it_dmabuf *); 149 int fwohci_itd_writedata(struct fwohci_it_dmabuf *, int, 150 struct ieee1394_it_datalist *); 151 int fwohci_itd_isfilled(struct fwohci_it_dmabuf *); 152 153 static int fwohci_buf_alloc(struct fwohci_softc *, struct fwohci_buf *); 154 static void fwohci_buf_free(struct fwohci_softc *, struct fwohci_buf *); 155 static void fwohci_buf_init_rx(struct fwohci_softc *); 156 static void fwohci_buf_start_rx(struct fwohci_softc *); 157 static void fwohci_buf_stop_tx(struct fwohci_softc *); 158 static void fwohci_buf_stop_rx(struct fwohci_softc *); 159 static void fwohci_buf_next(struct fwohci_softc *, struct fwohci_ctx *); 160 static int fwohci_buf_pktget(struct fwohci_softc *, struct fwohci_buf **, 161 caddr_t *, int); 162 static int fwohci_buf_input(struct fwohci_softc *, struct fwohci_ctx *, 163 struct fwohci_pkt *); 164 static int fwohci_buf_input_ppb(struct fwohci_softc *, struct fwohci_ctx *, 165 struct fwohci_pkt *); 166 167 static u_int8_t fwohci_phy_read(struct fwohci_softc *, u_int8_t); 168 static void fwohci_phy_write(struct fwohci_softc *, u_int8_t, u_int8_t); 169 static void fwohci_phy_busreset(struct fwohci_softc *); 170 static void fwohci_phy_input(struct fwohci_softc *, struct fwohci_pkt *); 171 172 static int fwohci_handler_set(struct fwohci_softc *, int, u_int32_t, u_int32_t, 173 int (*)(struct fwohci_softc *, void *, struct fwohci_pkt *), void *); 174 175 ieee1394_ir_tag_t fwohci_ir_ctx_set(struct device *, int, int, int, int, int); 176 int fwohci_ir_ctx_clear(struct device *, ieee1394_ir_tag_t); 177 int fwohci_ir_read(struct device *, ieee1394_ir_tag_t, struct uio *, 178 int, int); 179 int fwohci_ir_wait(struct device *, ieee1394_ir_tag_t, void *, char *name); 180 int fwohci_ir_select(struct device *, ieee1394_ir_tag_t, struct proc *); 181 182 183 184 ieee1394_it_tag_t fwohci_it_set(struct ieee1394_softc *, int, int); 185 static ieee1394_it_tag_t fwohci_it_ctx_set(struct fwohci_softc *, int, int, int); 186 int fwohci_it_ctx_clear(ieee1394_it_tag_t *); 187 188 static void fwohci_arrq_input(struct fwohci_softc *, struct fwohci_ctx *); 189 static void fwohci_arrs_input(struct fwohci_softc *, struct fwohci_ctx *); 190 static void fwohci_as_input(struct fwohci_softc *, struct fwohci_ctx *); 191 192 static int fwohci_at_output(struct fwohci_softc *, struct fwohci_ctx *, 193 struct fwohci_pkt *); 194 static void fwohci_at_done(struct fwohci_softc *, struct fwohci_ctx *, int); 195 static void fwohci_atrs_output(struct fwohci_softc *, int, struct fwohci_pkt *, 196 struct fwohci_pkt *); 197 198 static int fwohci_guidrom_init(struct fwohci_softc *); 199 static void fwohci_configrom_init(struct fwohci_softc *); 200 static int fwohci_configrom_input(struct fwohci_softc *, void *, 201 struct fwohci_pkt *); 202 static void fwohci_selfid_init(struct fwohci_softc *); 203 static int fwohci_selfid_input(struct fwohci_softc *); 204 205 static void fwohci_csr_init(struct fwohci_softc *); 206 static int fwohci_csr_input(struct fwohci_softc *, void *, 207 struct fwohci_pkt *); 208 209 static void fwohci_uid_collect(struct fwohci_softc *); 210 static void fwohci_uid_req(struct fwohci_softc *, int); 211 static int fwohci_uid_input(struct fwohci_softc *, void *, 212 struct fwohci_pkt *); 213 static int fwohci_uid_lookup(struct fwohci_softc *, const u_int8_t *); 214 static void fwohci_check_nodes(struct fwohci_softc *); 215 216 static int fwohci_if_inreg(struct device *, u_int32_t, u_int32_t, 217 void (*)(struct device *, struct mbuf *)); 218 static int fwohci_if_input(struct fwohci_softc *, void *, struct fwohci_pkt *); 219 static int fwohci_if_input_iso(struct fwohci_softc *, void *, struct fwohci_pkt *); 220 221 static int fwohci_if_output(struct device *, struct mbuf *, 222 void (*)(struct device *, struct mbuf *)); 223 static int fwohci_if_setiso(struct device *, u_int32_t, u_int32_t, u_int32_t, 224 void (*)(struct device *, struct mbuf *)); 225 static int fwohci_read(struct ieee1394_abuf *); 226 static int fwohci_write(struct ieee1394_abuf *); 227 static int fwohci_read_resp(struct fwohci_softc *, void *, struct fwohci_pkt *); 228 static int fwohci_write_ack(struct fwohci_softc *, void *, struct fwohci_pkt *); 229 static int fwohci_read_multi_resp(struct fwohci_softc *, void *, 230 struct fwohci_pkt *); 231 static int fwohci_inreg(struct ieee1394_abuf *, int); 232 static int fwohci_unreg(struct ieee1394_abuf *, int); 233 static int fwohci_parse_input(struct fwohci_softc *, void *, 234 struct fwohci_pkt *); 235 static int fwohci_submatch(struct device *, struct cfdata *, void *); 236 237 /* XXX */ 238 u_int16_t fwohci_cycletimer(struct fwohci_softc *); 239 u_int16_t fwohci_it_cycletimer(ieee1394_it_tag_t); 240 241 #ifdef FW_DEBUG 242 static void fwohci_show_intr(struct fwohci_softc *, u_int32_t); 243 static void fwohci_show_phypkt(struct fwohci_softc *, u_int32_t); 244 245 /* 1 is normal debug, 2 is verbose debug, 3 is complete (packet dumps). */ 246 247 #define DPRINTF(x) if (fwdebug) printf x 248 #define DPRINTFN(n,x) if (fwdebug>(n)) printf x 249 int fwdebug = 1; 250 #else 251 #define DPRINTF(x) 252 #define DPRINTFN(n,x) 253 #endif 254 255 #define OHCI_ITHEADER_SPD_MASK 0x00070000 256 #define OHCI_ITHEADER_SPD_BITPOS 16 257 #define OHCI_ITHEADER_TAG_MASK 0x0000c000 258 #define OHCI_ITHEADER_TAG_BITPOS 14 259 #define OHCI_ITHEADER_CHAN_MASK 0x00003f00 260 #define OHCI_ITHEADER_CHAN_BITPOS 8 261 #define OHCI_ITHEADER_TCODE_MASK 0x000000f0 262 #define OHCI_ITHEADER_TCODE_BITPOS 4 263 #define OHCI_ITHEADER_SY_MASK 0x0000000f 264 #define OHCI_ITHEADER_SY_BITPOS 0 265 266 #define OHCI_ITHEADER_VAL(fld, val) \ 267 (OHCI_ITHEADER_##fld##_MASK & ((val) << OHCI_ITHEADER_##fld##_BITPOS)) 268 269 int 270 fwohci_init(struct fwohci_softc *sc, const struct evcnt *ev) 271 { 272 int i; 273 u_int32_t val; 274 #if 0 275 int error; 276 #endif 277 278 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ev, 279 sc->sc_sc1394.sc1394_dev.dv_xname, "intr"); 280 281 evcnt_attach_dynamic(&sc->sc_isocnt, EVCNT_TYPE_MISC, ev, 282 sc->sc_sc1394.sc1394_dev.dv_xname, "isorcvs"); 283 evcnt_attach_dynamic(&sc->sc_ascnt, EVCNT_TYPE_MISC, ev, 284 sc->sc_sc1394.sc1394_dev.dv_xname, "asrcvs"); 285 evcnt_attach_dynamic(&sc->sc_itintrcnt, EVCNT_TYPE_INTR, ev, 286 sc->sc_sc1394.sc1394_dev.dv_xname, "itintr"); 287 288 /* 289 * Wait for reset completion 290 */ 291 for (i = 0; i < OHCI_LOOP; i++) { 292 val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear); 293 if ((val & OHCI_HCControl_SoftReset) == 0) 294 break; 295 DELAY(10); 296 } 297 298 /* What dialect of OHCI is this device? 299 */ 300 val = OHCI_CSR_READ(sc, OHCI_REG_Version); 301 printf("%s: OHCI %u.%u", sc->sc_sc1394.sc1394_dev.dv_xname, 302 OHCI_Version_GET_Version(val), OHCI_Version_GET_Revision(val)); 303 304 LIST_INIT(&sc->sc_nodelist); 305 306 if (fwohci_guidrom_init(sc) != 0) { 307 printf("\n%s: fatal: no global UID ROM\n", 308 sc->sc_sc1394.sc1394_dev.dv_xname); 309 return -1; 310 } 311 312 printf(", %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 313 sc->sc_sc1394.sc1394_guid[0], sc->sc_sc1394.sc1394_guid[1], 314 sc->sc_sc1394.sc1394_guid[2], sc->sc_sc1394.sc1394_guid[3], 315 sc->sc_sc1394.sc1394_guid[4], sc->sc_sc1394.sc1394_guid[5], 316 sc->sc_sc1394.sc1394_guid[6], sc->sc_sc1394.sc1394_guid[7]); 317 318 /* Get the maximum link speed and receive size 319 */ 320 val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions); 321 sc->sc_sc1394.sc1394_link_speed = 322 OHCI_BITVAL(val, OHCI_BusOptions_LinkSpd); 323 if (sc->sc_sc1394.sc1394_link_speed < IEEE1394_SPD_MAX) { 324 printf(", %s", 325 ieee1394_speeds[sc->sc_sc1394.sc1394_link_speed]); 326 } else { 327 printf(", unknown speed %u", sc->sc_sc1394.sc1394_link_speed); 328 } 329 330 /* MaxRec is encoded as log2(max_rec_octets)-1 331 */ 332 sc->sc_sc1394.sc1394_max_receive = 333 1 << (OHCI_BITVAL(val, OHCI_BusOptions_MaxRec) + 1); 334 printf(", %u max_rec", sc->sc_sc1394.sc1394_max_receive); 335 336 /* 337 * Count how many isochronous receive ctx we have. 338 */ 339 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskSet, ~0); 340 val = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntMaskClear); 341 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskClear, ~0); 342 for (i = 0; val != 0; val >>= 1) { 343 if (val & 0x1) 344 i++; 345 } 346 sc->sc_isoctx = i; 347 printf(", %d ir_ctx", sc->sc_isoctx); 348 349 /* 350 * Count how many isochronous transmit ctx we have. 351 */ 352 OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntMaskSet, ~0); 353 val = OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntMaskClear); 354 OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntMaskClear, ~0); 355 for (i = 0; val != 0; val >>= 1) { 356 if (val & 0x1) { 357 i++; 358 OHCI_SYNC_TX_DMA_WRITE(sc, i,OHCI_SUBREG_CommandPtr,0); 359 } 360 } 361 sc->sc_itctx = i; 362 363 printf(", %d it_ctx", sc->sc_itctx); 364 365 printf("\n"); 366 367 #if 0 368 error = fwohci_dnamem_alloc(sc, OHCI_CONFIG_SIZE, 369 OHCI_CONFIG_ALIGNMENT, &sc->sc_configrom_map, 370 (caddr_t *) &sc->sc_configrom, BUS_DMA_WAITOK|BUS_DMA_COHERENT); 371 return error; 372 #endif 373 374 sc->sc_dying = 0; 375 sc->sc_nodeid = 0xffff; /* invalid */ 376 377 sc->sc_sc1394.sc1394_callback.sc1394_read = fwohci_read; 378 sc->sc_sc1394.sc1394_callback.sc1394_write = fwohci_write; 379 sc->sc_sc1394.sc1394_callback.sc1394_inreg = fwohci_inreg; 380 sc->sc_sc1394.sc1394_callback.sc1394_unreg = fwohci_unreg; 381 382 kthread_create(fwohci_create_event_thread, sc); 383 return 0; 384 } 385 386 static int 387 fwohci_if_setiso(struct device *self, u_int32_t channel, u_int32_t tag, 388 u_int32_t direction, void (*handler)(struct device *, struct mbuf *)) 389 { 390 struct fwohci_softc *sc = (struct fwohci_softc *)self; 391 int retval; 392 int s; 393 394 if (direction == 1) { 395 return EIO; 396 } 397 398 s = splnet(); 399 retval = fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA, 400 channel, 1 << tag, fwohci_if_input_iso, handler); 401 splx(s); 402 403 if (!retval) { 404 printf("%s: dummy iso handler set\n", 405 sc->sc_sc1394.sc1394_dev.dv_xname); 406 } else { 407 printf("%s: dummy iso handler cannot set\n", 408 sc->sc_sc1394.sc1394_dev.dv_xname); 409 } 410 411 return retval; 412 } 413 414 int 415 fwohci_intr(void *arg) 416 { 417 struct fwohci_softc * const sc = arg; 418 int progress = 0; 419 u_int32_t intmask, iso; 420 421 for (;;) { 422 intmask = OHCI_CSR_READ(sc, OHCI_REG_IntEventClear); 423 424 /* 425 * On a bus reset, everything except bus reset gets 426 * cleared. That can't get cleared until the selfid 427 * phase completes (which happens outside the 428 * interrupt routines). So if just a bus reset is left 429 * in the mask and it's already in the sc_intmask, 430 * just return. 431 */ 432 433 if ((intmask == 0) || 434 (progress && (intmask == OHCI_Int_BusReset) && 435 (sc->sc_intmask & OHCI_Int_BusReset))) { 436 if (progress) 437 wakeup(fwohci_event_thread); 438 return progress; 439 } 440 OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear, 441 intmask & ~OHCI_Int_BusReset); 442 #ifdef FW_DEBUG 443 if (fwdebug > 1) 444 fwohci_show_intr(sc, intmask); 445 #endif 446 447 if (intmask & OHCI_Int_BusReset) { 448 /* 449 * According to OHCI spec 6.1.1 "busReset", 450 * All asynchronous transmit must be stopped before 451 * clearing BusReset. Moreover, the BusReset 452 * interrupt bit should not be cleared during the 453 * SelfID phase. Thus we turned off interrupt mask 454 * bit of BusReset instead until SelfID completion 455 * or SelfID timeout. 456 */ 457 intmask &= OHCI_Int_SelfIDComplete; 458 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, 459 OHCI_Int_BusReset); 460 sc->sc_intmask = OHCI_Int_BusReset; 461 } 462 sc->sc_intmask |= intmask; 463 464 if (intmask & OHCI_Int_IsochTx) { 465 int i; 466 467 iso = OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear); 468 OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntEventClear, iso); 469 470 sc->sc_itintrcnt.ev_count++; 471 for (i = 0; i < sc->sc_itctx; ++i) { 472 if ((iso & (1<<i)) == 0 || 473 sc->sc_ctx_it[i] == NULL) { 474 continue; 475 } 476 477 fwohci_it_intr(sc, sc->sc_ctx_it[i]); 478 } 479 } 480 if (intmask & OHCI_Int_IsochRx) { 481 int i; 482 483 iso = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear); 484 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, iso); 485 486 for (i = 0; i < sc->sc_isoctx; i++) { 487 if ((iso & (1 << i)) 488 && sc->sc_ctx_ir[i] != NULL) { 489 iso &= ~(1 << i); 490 fwohci_ir_intr(sc, sc->sc_ctx_ir[i]); 491 } 492 } 493 494 if (iso == 0) { 495 sc->sc_intmask &= ~OHCI_Int_IsochRx; 496 } 497 sc->sc_iso |= iso; 498 } 499 500 if (!progress) { 501 sc->sc_intrcnt.ev_count++; 502 progress = 1; 503 } 504 } 505 } 506 507 static void 508 fwohci_create_event_thread(void *arg) 509 { 510 struct fwohci_softc *sc = arg; 511 512 if (kthread_create1(fwohci_thread_init, sc, &sc->sc_event_thread, "%s", 513 sc->sc_sc1394.sc1394_dev.dv_xname)) { 514 printf("%s: unable to create event thread\n", 515 sc->sc_sc1394.sc1394_dev.dv_xname); 516 panic("fwohci_create_event_thread"); 517 } 518 } 519 520 static void 521 fwohci_thread_init(void *arg) 522 { 523 struct fwohci_softc *sc = arg; 524 int i; 525 526 /* 527 * Allocate descriptors 528 */ 529 if (fwohci_desc_alloc(sc)) { 530 printf("%s: not enabling interrupts\n", 531 sc->sc_sc1394.sc1394_dev.dv_xname); 532 kthread_exit(1); 533 } 534 535 /* 536 * Enable Link Power 537 */ 538 539 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS); 540 541 /* 542 * Allocate DMA Context 543 */ 544 fwohci_ctx_alloc(sc, &sc->sc_ctx_arrq, OHCI_BUF_ARRQ_CNT, 545 OHCI_CTX_ASYNC_RX_REQUEST, FWOHCI_CTX_ASYNC); 546 fwohci_ctx_alloc(sc, &sc->sc_ctx_arrs, OHCI_BUF_ARRS_CNT, 547 OHCI_CTX_ASYNC_RX_RESPONSE, FWOHCI_CTX_ASYNC); 548 fwohci_ctx_alloc(sc, &sc->sc_ctx_atrq, 0, OHCI_CTX_ASYNC_TX_REQUEST, 549 FWOHCI_CTX_ASYNC); 550 fwohci_ctx_alloc(sc, &sc->sc_ctx_atrs, 0, OHCI_CTX_ASYNC_TX_RESPONSE, 551 FWOHCI_CTX_ASYNC); 552 sc->sc_ctx_as = malloc(sizeof(sc->sc_ctx_as[0]) * sc->sc_isoctx, 553 M_DEVBUF, M_WAITOK); 554 if (sc->sc_ctx_as == NULL) { 555 printf("no asynchronous stream\n"); 556 } else { 557 for (i = 0; i < sc->sc_isoctx; i++) 558 sc->sc_ctx_as[i] = NULL; 559 } 560 sc->sc_ctx_ir = malloc(sizeof(sc->sc_ctx_ir[0]) * sc->sc_isoctx, 561 M_DEVBUF, M_WAITOK|M_ZERO); 562 sc->sc_ctx_it = malloc(sizeof(sc->sc_ctx_it[0]) * sc->sc_itctx, 563 M_DEVBUF, M_WAITOK|M_ZERO); 564 565 /* 566 * Allocate buffer for configuration ROM and SelfID buffer 567 */ 568 fwohci_buf_alloc(sc, &sc->sc_buf_cnfrom); 569 fwohci_buf_alloc(sc, &sc->sc_buf_selfid); 570 571 callout_init(&sc->sc_selfid_callout); 572 573 sc->sc_sc1394.sc1394_ifinreg = fwohci_if_inreg; 574 sc->sc_sc1394.sc1394_ifoutput = fwohci_if_output; 575 sc->sc_sc1394.sc1394_ifsetiso = fwohci_if_setiso; 576 577 sc->sc_sc1394.sc1394_ir_open = fwohci_ir_ctx_set; 578 sc->sc_sc1394.sc1394_ir_close = fwohci_ir_ctx_clear; 579 sc->sc_sc1394.sc1394_ir_read = fwohci_ir_read; 580 sc->sc_sc1394.sc1394_ir_wait = fwohci_ir_wait; 581 sc->sc_sc1394.sc1394_ir_select = fwohci_ir_select; 582 583 #if 0 584 sc->sc_sc1394.sc1394_it_open = fwohci_it_open; 585 sc->sc_sc1394.sc1394_it_write = fwohci_it_write; 586 sc->sc_sc1394.sc1394_it_close = fwohci_it_close; 587 /* XXX: need fwohci_it_flush? */ 588 #endif 589 590 /* 591 * establish hooks for shutdown and suspend/resume 592 */ 593 sc->sc_shutdownhook = shutdownhook_establish(fwohci_shutdown, sc); 594 sc->sc_powerhook = powerhook_establish(fwohci_power, sc); 595 596 sc->sc_sc1394.sc1394_if = config_found(&sc->sc_sc1394.sc1394_dev, "fw", 597 fwohci_print); 598 599 #if NFWISO > 0 600 fwiso_register_if(&sc->sc_sc1394); 601 #endif 602 603 /* Main loop. It's not coming back normally. */ 604 605 fwohci_event_thread(sc); 606 607 kthread_exit(0); 608 } 609 610 static void 611 fwohci_event_thread(struct fwohci_softc *sc) 612 { 613 int i, s; 614 u_int32_t intmask, iso; 615 616 s = splbio(); 617 618 /* 619 * Initialize hardware registers. 620 */ 621 622 fwohci_hw_init(sc); 623 624 /* Initial Bus Reset */ 625 fwohci_phy_busreset(sc); 626 splx(s); 627 628 while (!sc->sc_dying) { 629 s = splbio(); 630 intmask = sc->sc_intmask; 631 if (intmask == 0) { 632 tsleep(fwohci_event_thread, PZERO, "fwohciev", 0); 633 splx(s); 634 continue; 635 } 636 sc->sc_intmask = 0; 637 splx(s); 638 639 if (intmask & OHCI_Int_BusReset) { 640 fwohci_buf_stop_tx(sc); 641 if (sc->sc_uidtbl != NULL) { 642 free(sc->sc_uidtbl, M_DEVBUF); 643 sc->sc_uidtbl = NULL; 644 } 645 646 callout_reset(&sc->sc_selfid_callout, 647 OHCI_SELFID_TIMEOUT, 648 (void (*)(void *))fwohci_phy_busreset, sc); 649 sc->sc_nodeid = 0xffff; /* indicate invalid */ 650 sc->sc_rootid = 0; 651 sc->sc_irmid = IEEE1394_BCAST_PHY_ID; 652 } 653 if (intmask & OHCI_Int_SelfIDComplete) { 654 s = splbio(); 655 OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear, 656 OHCI_Int_BusReset); 657 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, 658 OHCI_Int_BusReset); 659 splx(s); 660 callout_stop(&sc->sc_selfid_callout); 661 if (fwohci_selfid_input(sc) == 0) { 662 fwohci_buf_start_rx(sc); 663 fwohci_uid_collect(sc); 664 } 665 } 666 if (intmask & OHCI_Int_ReqTxComplete) 667 fwohci_at_done(sc, sc->sc_ctx_atrq, 0); 668 if (intmask & OHCI_Int_RespTxComplete) 669 fwohci_at_done(sc, sc->sc_ctx_atrs, 0); 670 if (intmask & OHCI_Int_RQPkt) 671 fwohci_arrq_input(sc, sc->sc_ctx_arrq); 672 if (intmask & OHCI_Int_RSPkt) 673 fwohci_arrs_input(sc, sc->sc_ctx_arrs); 674 if (intmask & OHCI_Int_IsochRx) { 675 if (sc->sc_ctx_as == NULL) { 676 continue; 677 } 678 s = splbio(); 679 iso = sc->sc_iso; 680 sc->sc_iso = 0; 681 splx(s); 682 for (i = 0; i < sc->sc_isoctx; i++) { 683 if ((iso & (1 << i)) && 684 sc->sc_ctx_as[i] != NULL) { 685 fwohci_as_input(sc, sc->sc_ctx_as[i]); 686 sc->sc_ascnt.ev_count++; 687 } 688 } 689 } 690 } 691 } 692 693 #if 0 694 static int 695 fwohci_dnamem_alloc(struct fwohci_softc *sc, int size, int alignment, 696 bus_dmamap_t *mapp, caddr_t *kvap, int flags) 697 { 698 bus_dma_segment_t segs[1]; 699 int error, nsegs, steps; 700 701 steps = 0; 702 error = bus_dmamem_alloc(sc->sc_dmat, size, alignment, alignment, 703 segs, 1, &nsegs, flags); 704 if (error) 705 goto cleanup; 706 707 steps = 1; 708 error = bus_dmamem_map(sc->sc_dmat, segs, nsegs, segs[0].ds_len, 709 kvap, flags); 710 if (error) 711 goto cleanup; 712 713 if (error == 0) 714 error = bus_dmamap_create(sc->sc_dmat, size, 1, alignment, 715 size, flags, mapp); 716 if (error) 717 goto cleanup; 718 if (error == 0) 719 error = bus_dmamap_load(sc->sc_dmat, *mapp, *kvap, size, NULL, 720 flags); 721 if (error) 722 goto cleanup; 723 724 cleanup: 725 switch (steps) { 726 case 1: 727 bus_dmamem_free(sc->sc_dmat, segs, nsegs); 728 } 729 730 return error; 731 } 732 #endif 733 734 int 735 fwohci_print(void *aux, const char *pnp) 736 { 737 char *name = aux; 738 739 if (pnp) 740 printf("%s at %s", name, pnp); 741 742 return UNCONF; 743 } 744 745 static void 746 fwohci_hw_init(struct fwohci_softc *sc) 747 { 748 int i; 749 u_int32_t val; 750 751 /* 752 * Software Reset. 753 */ 754 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset); 755 for (i = 0; i < OHCI_LOOP; i++) { 756 val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear); 757 if ((val & OHCI_HCControl_SoftReset) == 0) 758 break; 759 DELAY(10); 760 } 761 762 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS); 763 764 /* 765 * First, initilize CSRs with undefined value to default settings. 766 */ 767 val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions); 768 val |= OHCI_BusOptions_ISC | OHCI_BusOptions_CMC; 769 #if 0 770 val |= OHCI_BusOptions_BMC | OHCI_BusOptions_IRMC; 771 #else 772 val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_IRMC); 773 #endif 774 OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val); 775 for (i = 0; i < sc->sc_isoctx; i++) { 776 OHCI_SYNC_RX_DMA_WRITE(sc, i, OHCI_SUBREG_ContextControlClear, 777 ~0); 778 } 779 for (i = 0; i < sc->sc_itctx; i++) { 780 OHCI_SYNC_TX_DMA_WRITE(sc, i, OHCI_SUBREG_ContextControlClear, 781 ~0); 782 } 783 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear, ~0); 784 785 fwohci_configrom_init(sc); 786 fwohci_selfid_init(sc); 787 fwohci_buf_init_rx(sc); 788 fwohci_csr_init(sc); 789 790 /* 791 * Final CSR settings. 792 */ 793 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet, 794 OHCI_LinkControl_CycleTimerEnable | 795 OHCI_LinkControl_RcvSelfID | OHCI_LinkControl_RcvPhyPkt); 796 797 OHCI_CSR_WRITE(sc, OHCI_REG_ATRetries, 0x00000888); /*XXX*/ 798 799 /* clear receive filter */ 800 OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskHiClear, ~0); 801 OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskLoClear, ~0); 802 OHCI_CSR_WRITE(sc, OHCI_REG_AsynchronousRequestFilterHiSet, 0x80000000); 803 804 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, 805 OHCI_HCControl_NoByteSwapData | OHCI_HCControl_APhyEnhanceEnable); 806 #if BYTE_ORDER == BIG_ENDIAN 807 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, 808 OHCI_HCControl_NoByteSwapData); 809 #endif 810 811 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, ~0); 812 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_BusReset | 813 OHCI_Int_SelfIDComplete | OHCI_Int_IsochRx | OHCI_Int_IsochTx | 814 OHCI_Int_RSPkt | OHCI_Int_RQPkt | OHCI_Int_ARRS | OHCI_Int_ARRQ | 815 OHCI_Int_RespTxComplete | OHCI_Int_ReqTxComplete); 816 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_CycleTooLong | 817 OHCI_Int_UnrecoverableError | OHCI_Int_CycleInconsistent | 818 OHCI_Int_LockRespErr | OHCI_Int_PostedWriteErr); 819 OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntMaskSet, ~0); 820 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskSet, ~0); 821 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_MasterEnable); 822 823 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LinkEnable); 824 825 /* 826 * Start the receivers 827 */ 828 fwohci_buf_start_rx(sc); 829 } 830 831 static void 832 fwohci_power(int why, void *arg) 833 { 834 struct fwohci_softc *sc = arg; 835 int s; 836 837 s = splbio(); 838 switch (why) { 839 case PWR_SUSPEND: 840 case PWR_STANDBY: 841 fwohci_shutdown(sc); 842 break; 843 case PWR_RESUME: 844 fwohci_hw_init(sc); 845 fwohci_phy_busreset(sc); 846 break; 847 case PWR_SOFTSUSPEND: 848 case PWR_SOFTSTANDBY: 849 case PWR_SOFTRESUME: 850 break; 851 } 852 splx(s); 853 } 854 855 static void 856 fwohci_shutdown(void *arg) 857 { 858 struct fwohci_softc *sc = arg; 859 u_int32_t val; 860 861 callout_stop(&sc->sc_selfid_callout); 862 /* disable all interrupt */ 863 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, OHCI_Int_MasterEnable); 864 fwohci_buf_stop_tx(sc); 865 fwohci_buf_stop_rx(sc); 866 val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions); 867 val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_ISC | 868 OHCI_BusOptions_CMC | OHCI_BusOptions_IRMC); 869 OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val); 870 fwohci_phy_busreset(sc); 871 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LinkEnable); 872 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LPS); 873 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset); 874 } 875 876 /* 877 * COMMON FUNCTIONS 878 */ 879 880 /* 881 * read the PHY Register. 882 */ 883 static u_int8_t 884 fwohci_phy_read(struct fwohci_softc *sc, u_int8_t reg) 885 { 886 int i; 887 u_int32_t val; 888 889 OHCI_CSR_WRITE(sc, OHCI_REG_PhyControl, 890 OHCI_PhyControl_RdReg | (reg << OHCI_PhyControl_RegAddr_BITPOS)); 891 for (i = 0; i < OHCI_LOOP; i++) { 892 if (OHCI_CSR_READ(sc, OHCI_REG_PhyControl) & 893 OHCI_PhyControl_RdDone) 894 break; 895 DELAY(10); 896 } 897 val = OHCI_CSR_READ(sc, OHCI_REG_PhyControl); 898 return (val & OHCI_PhyControl_RdData) >> OHCI_PhyControl_RdData_BITPOS; 899 } 900 901 /* 902 * write the PHY Register. 903 */ 904 static void 905 fwohci_phy_write(struct fwohci_softc *sc, u_int8_t reg, u_int8_t val) 906 { 907 int i; 908 909 OHCI_CSR_WRITE(sc, OHCI_REG_PhyControl, OHCI_PhyControl_WrReg | 910 (reg << OHCI_PhyControl_RegAddr_BITPOS) | 911 (val << OHCI_PhyControl_WrData_BITPOS)); 912 for (i = 0; i < OHCI_LOOP; i++) { 913 if (!(OHCI_CSR_READ(sc, OHCI_REG_PhyControl) & 914 OHCI_PhyControl_WrReg)) 915 break; 916 DELAY(10); 917 } 918 } 919 920 /* 921 * Initiate Bus Reset 922 */ 923 static void 924 fwohci_phy_busreset(struct fwohci_softc *sc) 925 { 926 int s; 927 u_int8_t val; 928 929 s = splbio(); 930 OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear, 931 OHCI_Int_BusReset | OHCI_Int_SelfIDComplete); 932 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_BusReset); 933 callout_stop(&sc->sc_selfid_callout); 934 val = fwohci_phy_read(sc, 1); 935 val = (val & 0x80) | /* preserve RHB (force root) */ 936 0x40 | /* Initiate Bus Reset */ 937 0x3f; /* default GAP count */ 938 fwohci_phy_write(sc, 1, val); 939 splx(s); 940 } 941 942 /* 943 * PHY Packet 944 */ 945 static void 946 fwohci_phy_input(struct fwohci_softc *sc, struct fwohci_pkt *pkt) 947 { 948 u_int32_t val; 949 950 val = pkt->fp_hdr[1]; 951 if (val != ~pkt->fp_hdr[2]) { 952 if (val == 0 && ((*pkt->fp_trail & 0x001f0000) >> 16) == 953 OHCI_CTXCTL_EVENT_BUS_RESET) { 954 DPRINTFN(1, ("fwohci_phy_input: BusReset: 0x%08x\n", 955 pkt->fp_hdr[2])); 956 } else { 957 printf("%s: phy packet corrupted (0x%08x, 0x%08x)\n", 958 sc->sc_sc1394.sc1394_dev.dv_xname, val, 959 pkt->fp_hdr[2]); 960 } 961 return; 962 } 963 #ifdef FW_DEBUG 964 if (fwdebug > 1) 965 fwohci_show_phypkt(sc, val); 966 #endif 967 } 968 969 /* 970 * Descriptor for context DMA. 971 */ 972 static int 973 fwohci_desc_alloc(struct fwohci_softc *sc) 974 { 975 int error, mapsize, dsize; 976 977 /* 978 * allocate descriptor buffer 979 */ 980 981 sc->sc_descsize = OHCI_BUF_ARRQ_CNT + OHCI_BUF_ARRS_CNT + 982 OHCI_BUF_ATRQ_CNT + OHCI_BUF_ATRS_CNT + 983 OHCI_BUF_IR_CNT * sc->sc_isoctx + 2; 984 dsize = sizeof(struct fwohci_desc) * sc->sc_descsize; 985 mapsize = howmany(sc->sc_descsize, NBBY); 986 sc->sc_descmap = malloc(mapsize, M_DEVBUF, M_WAITOK|M_ZERO); 987 988 if (sc->sc_descmap == NULL) { 989 printf("fwohci_desc_alloc: cannot get memory\n"); 990 return -1; 991 } 992 993 if ((error = bus_dmamem_alloc(sc->sc_dmat, dsize, PAGE_SIZE, 0, 994 &sc->sc_dseg, 1, &sc->sc_dnseg, 0)) != 0) { 995 printf("%s: unable to allocate descriptor buffer, error = %d\n", 996 sc->sc_sc1394.sc1394_dev.dv_xname, error); 997 goto fail_0; 998 } 999 1000 if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg, 1001 dsize, (caddr_t *)&sc->sc_desc, BUS_DMA_COHERENT | BUS_DMA_WAITOK)) 1002 != 0) { 1003 printf("%s: unable to map descriptor buffer, error = %d\n", 1004 sc->sc_sc1394.sc1394_dev.dv_xname, error); 1005 goto fail_1; 1006 } 1007 1008 if ((error = bus_dmamap_create(sc->sc_dmat, dsize, sc->sc_dnseg, 1009 dsize, 0, BUS_DMA_WAITOK, &sc->sc_ddmamap)) != 0) { 1010 printf("%s: unable to create descriptor buffer DMA map, " 1011 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error); 1012 goto fail_2; 1013 } 1014 1015 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_ddmamap, sc->sc_desc, 1016 dsize, NULL, BUS_DMA_WAITOK)) != 0) { 1017 printf("%s: unable to load descriptor buffer DMA map, " 1018 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error); 1019 goto fail_3; 1020 } 1021 1022 return 0; 1023 1024 fail_3: 1025 bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap); 1026 fail_2: 1027 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_desc, dsize); 1028 fail_1: 1029 bus_dmamem_free(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg); 1030 fail_0: 1031 return error; 1032 } 1033 1034 static struct fwohci_desc * 1035 fwohci_desc_get(struct fwohci_softc *sc, int ndesc) 1036 { 1037 int i, n; 1038 1039 for (n = 0; n <= sc->sc_descsize - ndesc; n++) { 1040 for (i = 0; ; i++) { 1041 if (i == ndesc) { 1042 for (i = 0; i < ndesc; i++) 1043 setbit(sc->sc_descmap, n + i); 1044 return sc->sc_desc + n; 1045 } 1046 if (isset(sc->sc_descmap, n + i)) 1047 break; 1048 } 1049 } 1050 return NULL; 1051 } 1052 1053 static void 1054 fwohci_desc_put(struct fwohci_softc *sc, struct fwohci_desc *fd, int ndesc) 1055 { 1056 int i, n; 1057 1058 n = fd - sc->sc_desc; 1059 for (i = 0; i < ndesc; i++, n++) { 1060 #ifdef DIAGNOSTIC 1061 if (isclr(sc->sc_descmap, n)) 1062 panic("fwohci_desc_put: duplicated free"); 1063 #endif 1064 clrbit(sc->sc_descmap, n); 1065 } 1066 } 1067 1068 /* 1069 * Asyncronous/Isochronous Transmit/Receive Context 1070 */ 1071 static int 1072 fwohci_ctx_alloc(struct fwohci_softc *sc, struct fwohci_ctx **fcp, 1073 int bufcnt, int ctx, int ctxtype) 1074 { 1075 int i, error; 1076 struct fwohci_ctx *fc; 1077 struct fwohci_buf *fb; 1078 struct fwohci_desc *fd; 1079 #if DOUBLEBUF 1080 int buf2cnt; 1081 #endif 1082 1083 fc = malloc(sizeof(*fc), M_DEVBUF, M_WAITOK|M_ZERO); 1084 LIST_INIT(&fc->fc_handler); 1085 TAILQ_INIT(&fc->fc_buf); 1086 fc->fc_ctx = ctx; 1087 fc->fc_buffers = fb = malloc(sizeof(*fb) * bufcnt, M_DEVBUF, M_WAITOK|M_ZERO); 1088 fc->fc_bufcnt = bufcnt; 1089 #if DOUBLEBUF 1090 TAILQ_INIT(&fc->fc_buf2); /* for isochronous */ 1091 if (ctxtype == FWOHCI_CTX_ISO_MULTI) { 1092 buf2cnt = bufcnt/2; 1093 bufcnt -= buf2cnt; 1094 if (buf2cnt == 0) { 1095 panic("cannot allocate iso buffer"); 1096 } 1097 } 1098 #endif 1099 for (i = 0; i < bufcnt; i++, fb++) { 1100 if ((error = fwohci_buf_alloc(sc, fb)) != 0) 1101 goto fail; 1102 if ((fd = fwohci_desc_get(sc, 1)) == NULL) { 1103 error = ENOBUFS; 1104 goto fail; 1105 } 1106 fb->fb_desc = fd; 1107 fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr + 1108 ((caddr_t)fd - (caddr_t)sc->sc_desc); 1109 fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_STATUS | 1110 OHCI_DESC_INTR_ALWAYS | OHCI_DESC_BRANCH; 1111 fd->fd_reqcount = fb->fb_dmamap->dm_segs[0].ds_len; 1112 fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr; 1113 TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list); 1114 } 1115 #if DOUBLEBUF 1116 if (ctxtype == FWOHCI_CTX_ISO_MULTI) { 1117 for (i = bufcnt; i < bufcnt + buf2cnt; i++, fb++) { 1118 if ((error = fwohci_buf_alloc(sc, fb)) != 0) 1119 goto fail; 1120 if ((fd = fwohci_desc_get(sc, 1)) == NULL) { 1121 error = ENOBUFS; 1122 goto fail; 1123 } 1124 fb->fb_desc = fd; 1125 fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr + 1126 ((caddr_t)fd - (caddr_t)sc->sc_desc); 1127 bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap, 1128 (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc), 1129 BUS_DMASYNC_PREWRITE); 1130 fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_STATUS | 1131 OHCI_DESC_INTR_ALWAYS | OHCI_DESC_BRANCH; 1132 fd->fd_reqcount = fb->fb_dmamap->dm_segs[0].ds_len; 1133 fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr; 1134 TAILQ_INSERT_TAIL(&fc->fc_buf2, fb, fb_list); 1135 bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap, 1136 (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc), 1137 BUS_DMASYNC_POSTWRITE); 1138 } 1139 } 1140 #endif /* DOUBLEBUF */ 1141 fc->fc_type = ctxtype; 1142 *fcp = fc; 1143 return 0; 1144 1145 fail: 1146 while (i-- > 0) { 1147 fb--; 1148 if (fb->fb_desc) 1149 fwohci_desc_put(sc, fb->fb_desc, 1); 1150 fwohci_buf_free(sc, fb); 1151 } 1152 free(fc, M_DEVBUF); 1153 return error; 1154 } 1155 1156 static void 1157 fwohci_ctx_free(struct fwohci_softc *sc, struct fwohci_ctx *fc) 1158 { 1159 struct fwohci_buf *fb; 1160 struct fwohci_handler *fh; 1161 1162 #if DOUBLEBUF 1163 if ((fc->fc_type == FWOHCI_CTX_ISO_MULTI) && 1164 (TAILQ_FIRST(&fc->fc_buf) > TAILQ_FIRST(&fc->fc_buf2))) { 1165 struct fwohci_buf_s fctmp; 1166 1167 fctmp = fc->fc_buf; 1168 fc->fc_buf = fc->fc_buf2; 1169 fc->fc_buf2 = fctmp; 1170 } 1171 #endif 1172 while ((fh = LIST_FIRST(&fc->fc_handler)) != NULL) 1173 fwohci_handler_set(sc, fh->fh_tcode, fh->fh_key1, fh->fh_key2, 1174 NULL, NULL); 1175 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) { 1176 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list); 1177 if (fb->fb_desc) 1178 fwohci_desc_put(sc, fb->fb_desc, 1); 1179 fwohci_buf_free(sc, fb); 1180 } 1181 #if DOUBLEBUF 1182 while ((fb = TAILQ_FIRST(&fc->fc_buf2)) != NULL) { 1183 TAILQ_REMOVE(&fc->fc_buf2, fb, fb_list); 1184 if (fb->fb_desc) 1185 fwohci_desc_put(sc, fb->fb_desc, 1); 1186 fwohci_buf_free(sc, fb); 1187 } 1188 #endif /* DOUBLEBUF */ 1189 free(fc->fc_buffers, M_DEVBUF); 1190 free(fc, M_DEVBUF); 1191 } 1192 1193 static void 1194 fwohci_ctx_init(struct fwohci_softc *sc, struct fwohci_ctx *fc) 1195 { 1196 struct fwohci_buf *fb, *nfb; 1197 struct fwohci_desc *fd; 1198 struct fwohci_handler *fh; 1199 int n; 1200 1201 for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL; fb = nfb) { 1202 nfb = TAILQ_NEXT(fb, fb_list); 1203 fb->fb_off = 0; 1204 fd = fb->fb_desc; 1205 fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0; 1206 fd->fd_rescount = fd->fd_reqcount; 1207 } 1208 1209 #if DOUBLEBUF 1210 for (fb = TAILQ_FIRST(&fc->fc_buf2); fb != NULL; fb = nfb) { 1211 bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap, 1212 (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc), 1213 BUS_DMASYNC_PREWRITE); 1214 nfb = TAILQ_NEXT(fb, fb_list); 1215 fb->fb_off = 0; 1216 fd = fb->fb_desc; 1217 fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0; 1218 fd->fd_rescount = fd->fd_reqcount; 1219 bus_dmamap_sync(sc->sc_dmat, sc->sc_ddmamap, 1220 (caddr_t)fd - (caddr_t)sc->sc_desc, sizeof(struct fwohci_desc), 1221 BUS_DMASYNC_POSTWRITE); 1222 } 1223 #endif /* DOUBLEBUF */ 1224 1225 n = fc->fc_ctx; 1226 fb = TAILQ_FIRST(&fc->fc_buf); 1227 if (fc->fc_type != FWOHCI_CTX_ASYNC) { 1228 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr, 1229 fb->fb_daddr | 1); 1230 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear, 1231 OHCI_CTXCTL_RX_BUFFER_FILL | 1232 OHCI_CTXCTL_RX_CYCLE_MATCH_ENABLE | 1233 OHCI_CTXCTL_RX_MULTI_CHAN_MODE | 1234 OHCI_CTXCTL_RX_DUAL_BUFFER_MODE); 1235 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet, 1236 OHCI_CTXCTL_RX_ISOCH_HEADER); 1237 if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) { 1238 OHCI_SYNC_RX_DMA_WRITE(sc, n, 1239 OHCI_SUBREG_ContextControlSet, 1240 OHCI_CTXCTL_RX_BUFFER_FILL); 1241 } 1242 fh = LIST_FIRST(&fc->fc_handler); 1243 1244 if (fh->fh_key1 == IEEE1394_ISO_CHANNEL_ANY) { 1245 OHCI_SYNC_RX_DMA_WRITE(sc, n, 1246 OHCI_SUBREG_ContextControlSet, 1247 OHCI_CTXCTL_RX_MULTI_CHAN_MODE); 1248 1249 /* Receive all the isochronous channels */ 1250 OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskHiSet, 1251 0xffffffff); 1252 OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskLoSet, 1253 0xffffffff); 1254 DPRINTF(("%s: CTXCTL 0x%08x\n", 1255 sc->sc_sc1394.sc1394_dev.dv_xname, 1256 OHCI_SYNC_RX_DMA_READ(sc, n, 1257 OHCI_SUBREG_ContextControlSet))); 1258 } 1259 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextMatch, 1260 (fh->fh_key2 << OHCI_CTXMATCH_TAG_BITPOS) | 1261 (fh->fh_key1 & IEEE1394_ISO_CHANNEL_MASK)); 1262 } else { 1263 OHCI_ASYNC_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr, 1264 fb->fb_daddr | 1); 1265 } 1266 } 1267 1268 /* 1269 * DMA data buffer 1270 */ 1271 static int 1272 fwohci_buf_alloc(struct fwohci_softc *sc, struct fwohci_buf *fb) 1273 { 1274 int error; 1275 1276 if ((error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 1277 PAGE_SIZE, &fb->fb_seg, 1, &fb->fb_nseg, BUS_DMA_WAITOK)) != 0) { 1278 printf("%s: unable to allocate buffer, error = %d\n", 1279 sc->sc_sc1394.sc1394_dev.dv_xname, error); 1280 goto fail_0; 1281 } 1282 1283 if ((error = bus_dmamem_map(sc->sc_dmat, &fb->fb_seg, 1284 fb->fb_nseg, PAGE_SIZE, &fb->fb_buf, BUS_DMA_WAITOK)) != 0) { 1285 printf("%s: unable to map buffer, error = %d\n", 1286 sc->sc_sc1394.sc1394_dev.dv_xname, error); 1287 goto fail_1; 1288 } 1289 1290 if ((error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, fb->fb_nseg, 1291 PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) { 1292 printf("%s: unable to create buffer DMA map, " 1293 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, 1294 error); 1295 goto fail_2; 1296 } 1297 1298 if ((error = bus_dmamap_load(sc->sc_dmat, fb->fb_dmamap, 1299 fb->fb_buf, PAGE_SIZE, NULL, BUS_DMA_WAITOK)) != 0) { 1300 printf("%s: unable to load buffer DMA map, " 1301 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, 1302 error); 1303 goto fail_3; 1304 } 1305 1306 return 0; 1307 1308 bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap); 1309 fail_3: 1310 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap); 1311 fail_2: 1312 bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE); 1313 fail_1: 1314 bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg); 1315 fail_0: 1316 return error; 1317 } 1318 1319 static void 1320 fwohci_buf_free(struct fwohci_softc *sc, struct fwohci_buf *fb) 1321 { 1322 1323 bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap); 1324 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap); 1325 bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE); 1326 bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg); 1327 } 1328 1329 static void 1330 fwohci_buf_init_rx(struct fwohci_softc *sc) 1331 { 1332 int i; 1333 1334 /* 1335 * Initialize for Asynchronous Receive Queue. 1336 */ 1337 fwohci_ctx_init(sc, sc->sc_ctx_arrq); 1338 fwohci_ctx_init(sc, sc->sc_ctx_arrs); 1339 1340 /* 1341 * Initialize for Isochronous Receive Queue. 1342 */ 1343 if (sc->sc_ctx_as != NULL) { 1344 for (i = 0; i < sc->sc_isoctx; i++) { 1345 if (sc->sc_ctx_as[i] != NULL) 1346 fwohci_ctx_init(sc, sc->sc_ctx_as[i]); 1347 } 1348 } 1349 } 1350 1351 static void 1352 fwohci_buf_start_rx(struct fwohci_softc *sc) 1353 { 1354 int i; 1355 1356 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST, 1357 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN); 1358 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE, 1359 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN); 1360 if (sc->sc_ctx_as != NULL) { 1361 for (i = 0; i < sc->sc_isoctx; i++) { 1362 if (sc->sc_ctx_as[i] != NULL) 1363 OHCI_SYNC_RX_DMA_WRITE(sc, i, 1364 OHCI_SUBREG_ContextControlSet, 1365 OHCI_CTXCTL_RUN); 1366 } 1367 } 1368 } 1369 1370 static void 1371 fwohci_buf_stop_tx(struct fwohci_softc *sc) 1372 { 1373 int i; 1374 1375 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_REQUEST, 1376 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 1377 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_RESPONSE, 1378 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 1379 1380 /* 1381 * Make sure the transmitter is stopped. 1382 */ 1383 for (i = 0; i < OHCI_LOOP; i++) { 1384 DELAY(10); 1385 if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST, 1386 OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE) 1387 continue; 1388 if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE, 1389 OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE) 1390 continue; 1391 break; 1392 } 1393 1394 /* 1395 * Initialize for Asynchronous Transmit Queue. 1396 */ 1397 fwohci_at_done(sc, sc->sc_ctx_atrq, 1); 1398 fwohci_at_done(sc, sc->sc_ctx_atrs, 1); 1399 } 1400 1401 static void 1402 fwohci_buf_stop_rx(struct fwohci_softc *sc) 1403 { 1404 int i; 1405 1406 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST, 1407 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 1408 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE, 1409 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 1410 for (i = 0; i < sc->sc_isoctx; i++) { 1411 OHCI_SYNC_RX_DMA_WRITE(sc, i, 1412 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 1413 } 1414 } 1415 1416 static void 1417 fwohci_buf_next(struct fwohci_softc *sc, struct fwohci_ctx *fc) 1418 { 1419 struct fwohci_buf *fb, *tfb; 1420 1421 #if DOUBLEBUF 1422 if (fc->fc_type != FWOHCI_CTX_ISO_MULTI) { 1423 #endif 1424 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) { 1425 if (fc->fc_type) { 1426 if (fb->fb_off == 0) 1427 break; 1428 } else { 1429 if (fb->fb_off != fb->fb_desc->fd_reqcount || 1430 fb->fb_desc->fd_rescount != 0) 1431 break; 1432 } 1433 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list); 1434 fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount; 1435 fb->fb_off = 0; 1436 fb->fb_desc->fd_branch = 0; 1437 tfb = TAILQ_LAST(&fc->fc_buf, fwohci_buf_s); 1438 tfb->fb_desc->fd_branch = fb->fb_daddr | 1; 1439 TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list); 1440 } 1441 #if DOUBLEBUF 1442 } else { 1443 struct fwohci_buf_s fctmp; 1444 1445 /* cleaning buffer */ 1446 for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL; 1447 fb = TAILQ_NEXT(fb, fb_list)) { 1448 fb->fb_off = 0; 1449 fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount; 1450 } 1451 1452 /* rotating buffer */ 1453 fctmp = fc->fc_buf; 1454 fc->fc_buf = fc->fc_buf2; 1455 fc->fc_buf2 = fctmp; 1456 } 1457 #endif 1458 } 1459 1460 static int 1461 fwohci_buf_pktget(struct fwohci_softc *sc, struct fwohci_buf **fbp, caddr_t *pp, 1462 int len) 1463 { 1464 struct fwohci_buf *fb; 1465 struct fwohci_desc *fd; 1466 int bufend; 1467 1468 fb = *fbp; 1469 again: 1470 fd = fb->fb_desc; 1471 DPRINTFN(1, ("fwohci_buf_pktget: desc %ld, off %d, req %d, res %d," 1472 " len %d, avail %d\n", (long)(fd - sc->sc_desc), fb->fb_off, 1473 fd->fd_reqcount, fd->fd_rescount, len, 1474 fd->fd_reqcount - fd->fd_rescount - fb->fb_off)); 1475 bufend = fd->fd_reqcount - fd->fd_rescount; 1476 if (fb->fb_off >= bufend) { 1477 DPRINTFN(5, ("buf %x finish req %d res %d off %d ", 1478 fb->fb_desc->fd_data, fd->fd_reqcount, fd->fd_rescount, 1479 fb->fb_off)); 1480 if (fd->fd_rescount == 0) { 1481 *fbp = fb = TAILQ_NEXT(fb, fb_list); 1482 if (fb != NULL) 1483 goto again; 1484 } 1485 return 0; 1486 } 1487 if (fb->fb_off + len > bufend) 1488 len = bufend - fb->fb_off; 1489 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len, 1490 BUS_DMASYNC_POSTREAD); 1491 *pp = fb->fb_buf + fb->fb_off; 1492 fb->fb_off += roundup(len, 4); 1493 return len; 1494 } 1495 1496 static int 1497 fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc, 1498 struct fwohci_pkt *pkt) 1499 { 1500 caddr_t p; 1501 struct fwohci_buf *fb; 1502 int len, count, i; 1503 #ifdef FW_DEBUG 1504 int tlabel; 1505 #endif 1506 1507 memset(pkt, 0, sizeof(*pkt)); 1508 pkt->fp_uio.uio_iov = pkt->fp_iov; 1509 pkt->fp_uio.uio_rw = UIO_WRITE; 1510 pkt->fp_uio.uio_segflg = UIO_SYSSPACE; 1511 1512 /* get first quadlet */ 1513 fb = TAILQ_FIRST(&fc->fc_buf); 1514 count = 4; 1515 len = fwohci_buf_pktget(sc, &fb, &p, count); 1516 if (len <= 0) { 1517 DPRINTFN(1, ("fwohci_buf_input: no input for %d\n", 1518 fc->fc_ctx)); 1519 return 0; 1520 } 1521 pkt->fp_hdr[0] = *(u_int32_t *)p; 1522 pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4; 1523 switch (pkt->fp_tcode) { 1524 case IEEE1394_TCODE_WRITE_REQ_QUAD: 1525 case IEEE1394_TCODE_READ_RESP_QUAD: 1526 pkt->fp_hlen = 12; 1527 pkt->fp_dlen = 4; 1528 break; 1529 case IEEE1394_TCODE_READ_REQ_BLOCK: 1530 pkt->fp_hlen = 16; 1531 pkt->fp_dlen = 0; 1532 break; 1533 case IEEE1394_TCODE_WRITE_REQ_BLOCK: 1534 case IEEE1394_TCODE_READ_RESP_BLOCK: 1535 case IEEE1394_TCODE_LOCK_REQ: 1536 case IEEE1394_TCODE_LOCK_RESP: 1537 pkt->fp_hlen = 16; 1538 break; 1539 case IEEE1394_TCODE_STREAM_DATA: 1540 #ifdef DIAGNOSTIC 1541 if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) 1542 #endif 1543 { 1544 pkt->fp_hlen = 4; 1545 pkt->fp_dlen = pkt->fp_hdr[0] >> 16; 1546 DPRINTFN(5, ("[%d]", pkt->fp_dlen)); 1547 break; 1548 } 1549 #ifdef DIAGNOSTIC 1550 else { 1551 printf("fwohci_buf_input: bad tcode: STREAM_DATA\n"); 1552 return 0; 1553 } 1554 #endif 1555 default: 1556 pkt->fp_hlen = 12; 1557 pkt->fp_dlen = 0; 1558 break; 1559 } 1560 1561 /* get header */ 1562 while (count < pkt->fp_hlen) { 1563 len = fwohci_buf_pktget(sc, &fb, &p, pkt->fp_hlen - count); 1564 if (len == 0) { 1565 printf("fwohci_buf_input: malformed input 1: %d\n", 1566 pkt->fp_hlen - count); 1567 return 0; 1568 } 1569 memcpy((caddr_t)pkt->fp_hdr + count, p, len); 1570 count += len; 1571 } 1572 if (pkt->fp_hlen == 16 && 1573 pkt->fp_tcode != IEEE1394_TCODE_READ_REQ_BLOCK) 1574 pkt->fp_dlen = pkt->fp_hdr[3] >> 16; 1575 #ifdef FW_DEBUG 1576 tlabel = (pkt->fp_hdr[0] & 0x0000fc00) >> 10; 1577 #endif 1578 DPRINTFN(1, ("fwohci_buf_input: tcode=0x%x, tlabel=0x%x, hlen=%d, " 1579 "dlen=%d\n", pkt->fp_tcode, tlabel, pkt->fp_hlen, pkt->fp_dlen)); 1580 1581 /* get data */ 1582 count = 0; 1583 i = 0; 1584 while (count < pkt->fp_dlen) { 1585 len = fwohci_buf_pktget(sc, &fb, 1586 (caddr_t *)&pkt->fp_iov[i].iov_base, 1587 pkt->fp_dlen - count); 1588 if (len == 0) { 1589 printf("fwohci_buf_input: malformed input 2: %d\n", 1590 pkt->fp_dlen - count); 1591 return 0; 1592 } 1593 pkt->fp_iov[i++].iov_len = len; 1594 count += len; 1595 } 1596 pkt->fp_uio.uio_iovcnt = i; 1597 pkt->fp_uio.uio_resid = count; 1598 1599 /* get trailer */ 1600 len = fwohci_buf_pktget(sc, &fb, (caddr_t *)&pkt->fp_trail, 1601 sizeof(*pkt->fp_trail)); 1602 if (len <= 0) { 1603 printf("fwohci_buf_input: malformed input 3: %d\n", 1604 pkt->fp_hlen - count); 1605 return 0; 1606 } 1607 return 1; 1608 } 1609 1610 static int 1611 fwohci_buf_input_ppb(struct fwohci_softc *sc, struct fwohci_ctx *fc, 1612 struct fwohci_pkt *pkt) 1613 { 1614 caddr_t p; 1615 int len; 1616 struct fwohci_buf *fb; 1617 struct fwohci_desc *fd; 1618 1619 if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) { 1620 return fwohci_buf_input(sc, fc, pkt); 1621 } 1622 1623 memset(pkt, 0, sizeof(*pkt)); 1624 pkt->fp_uio.uio_iov = pkt->fp_iov; 1625 pkt->fp_uio.uio_rw = UIO_WRITE; 1626 pkt->fp_uio.uio_segflg = UIO_SYSSPACE; 1627 1628 for (fb = TAILQ_FIRST(&fc->fc_buf); ; fb = TAILQ_NEXT(fb, fb_list)) { 1629 if (fb == NULL) 1630 return 0; 1631 if (fb->fb_off == 0) 1632 break; 1633 } 1634 fd = fb->fb_desc; 1635 len = fd->fd_reqcount - fd->fd_rescount; 1636 if (len == 0) 1637 return 0; 1638 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len, 1639 BUS_DMASYNC_POSTREAD); 1640 1641 p = fb->fb_buf; 1642 fb->fb_off += roundup(len, 4); 1643 if (len < 8) { 1644 printf("fwohci_buf_input_ppb: malformed input 1: %d\n", len); 1645 return 0; 1646 } 1647 1648 /* 1649 * get trailer first, may be bogus data unless status update 1650 * in descriptor is set. 1651 */ 1652 pkt->fp_trail = (u_int32_t *)p; 1653 *pkt->fp_trail = (*pkt->fp_trail & 0xffff) | (fd->fd_status << 16); 1654 pkt->fp_hdr[0] = ((u_int32_t *)p)[1]; 1655 pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4; 1656 #ifdef DIAGNOSTIC 1657 if (pkt->fp_tcode != IEEE1394_TCODE_STREAM_DATA) { 1658 printf("fwohci_buf_input_ppb: bad tcode: 0x%x\n", 1659 pkt->fp_tcode); 1660 return 0; 1661 } 1662 #endif 1663 pkt->fp_hlen = 4; 1664 pkt->fp_dlen = pkt->fp_hdr[0] >> 16; 1665 p += 8; 1666 len -= 8; 1667 if (pkt->fp_dlen != len) { 1668 printf("fwohci_buf_input_ppb: malformed input 2: %d != %d\n", 1669 pkt->fp_dlen, len); 1670 return 0; 1671 } 1672 DPRINTFN(1, ("fwohci_buf_input_ppb: tcode=0x%x, hlen=%d, dlen=%d\n", 1673 pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen)); 1674 pkt->fp_iov[0].iov_base = p; 1675 pkt->fp_iov[0].iov_len = len; 1676 pkt->fp_uio.uio_iovcnt = 0; 1677 pkt->fp_uio.uio_resid = len; 1678 return 1; 1679 } 1680 1681 static int 1682 fwohci_handler_set(struct fwohci_softc *sc, 1683 int tcode, u_int32_t key1, u_int32_t key2, 1684 int (*handler)(struct fwohci_softc *, void *, struct fwohci_pkt *), 1685 void *arg) 1686 { 1687 struct fwohci_ctx *fc; 1688 struct fwohci_handler *fh; 1689 int i, j; 1690 1691 if (tcode == IEEE1394_TCODE_STREAM_DATA && 1692 (((key1 & OHCI_ASYNC_STREAM) && sc->sc_ctx_as != NULL) 1693 || (key1 & OHCI_ASYNC_STREAM) == 0)) { 1694 int isasync = key1 & OHCI_ASYNC_STREAM; 1695 1696 key1 = key1 & IEEE1394_ISO_CHANNEL_ANY ? 1697 IEEE1394_ISO_CHANNEL_ANY : (key1 & IEEE1394_ISOCH_MASK); 1698 if (key1 & IEEE1394_ISO_CHANNEL_ANY) { 1699 printf("%s: key changed to %x\n", 1700 sc->sc_sc1394.sc1394_dev.dv_xname, key1); 1701 } 1702 j = sc->sc_isoctx; 1703 fh = NULL; 1704 1705 for (i = 0; i < sc->sc_isoctx; i++) { 1706 if ((fc = sc->sc_ctx_as[i]) == NULL) { 1707 if (j == sc->sc_isoctx) 1708 j = i; 1709 continue; 1710 } 1711 fh = LIST_FIRST(&fc->fc_handler); 1712 if (fh->fh_tcode == tcode && 1713 fh->fh_key1 == key1 && fh->fh_key2 == key2) 1714 break; 1715 fh = NULL; 1716 } 1717 if (fh == NULL) { 1718 if (handler == NULL) 1719 return 0; 1720 if (j == sc->sc_isoctx) { 1721 DPRINTF(("fwohci_handler_set: no more free " 1722 "context\n")); 1723 return ENOMEM; 1724 } 1725 if ((fc = sc->sc_ctx_as[j]) == NULL) { 1726 fwohci_ctx_alloc(sc, &fc, OHCI_BUF_IR_CNT, j, 1727 isasync ? FWOHCI_CTX_ISO_SINGLE : 1728 FWOHCI_CTX_ISO_MULTI); 1729 sc->sc_ctx_as[j] = fc; 1730 } 1731 } 1732 #ifdef FW_DEBUG 1733 if (fh == NULL && handler != NULL) { 1734 printf("use ir context %d\n", j); 1735 } else if (fh != NULL && handler == NULL) { 1736 printf("remove ir context %d\n", i); 1737 } 1738 #endif 1739 } else { 1740 switch (tcode) { 1741 case IEEE1394_TCODE_WRITE_REQ_QUAD: 1742 case IEEE1394_TCODE_WRITE_REQ_BLOCK: 1743 case IEEE1394_TCODE_READ_REQ_QUAD: 1744 case IEEE1394_TCODE_READ_REQ_BLOCK: 1745 case IEEE1394_TCODE_LOCK_REQ: 1746 fc = sc->sc_ctx_arrq; 1747 break; 1748 case IEEE1394_TCODE_WRITE_RESP: 1749 case IEEE1394_TCODE_READ_RESP_QUAD: 1750 case IEEE1394_TCODE_READ_RESP_BLOCK: 1751 case IEEE1394_TCODE_LOCK_RESP: 1752 fc = sc->sc_ctx_arrs; 1753 break; 1754 default: 1755 return EIO; 1756 } 1757 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL; 1758 fh = LIST_NEXT(fh, fh_list)) { 1759 if (fh->fh_tcode == tcode && 1760 fh->fh_key1 == key1 && fh->fh_key2 == key2) 1761 break; 1762 } 1763 } 1764 if (handler == NULL) { 1765 if (fh != NULL) { 1766 LIST_REMOVE(fh, fh_list); 1767 free(fh, M_DEVBUF); 1768 } 1769 if (tcode == IEEE1394_TCODE_STREAM_DATA) { 1770 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, 1771 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 1772 sc->sc_ctx_as[fc->fc_ctx] = NULL; 1773 fwohci_ctx_free(sc, fc); 1774 } 1775 return 0; 1776 } 1777 if (fh == NULL) { 1778 fh = malloc(sizeof(*fh), M_DEVBUF, M_WAITOK); 1779 LIST_INSERT_HEAD(&fc->fc_handler, fh, fh_list); 1780 } 1781 fh->fh_tcode = tcode; 1782 fh->fh_key1 = key1; 1783 fh->fh_key2 = key2; 1784 fh->fh_handler = handler; 1785 fh->fh_handarg = arg; 1786 DPRINTFN(1, ("fwohci_handler_set: ctx %d, tcode %x, key 0x%x, 0x%x\n", 1787 fc->fc_ctx, tcode, key1, key2)); 1788 1789 if (tcode == IEEE1394_TCODE_STREAM_DATA) { 1790 fwohci_ctx_init(sc, fc); 1791 DPRINTFN(1, ("fwohci_handler_set: SYNC desc %ld\n", 1792 (long)(TAILQ_FIRST(&fc->fc_buf)->fb_desc - sc->sc_desc))); 1793 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, 1794 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN); 1795 } 1796 return 0; 1797 } 1798 1799 1800 1801 1802 1803 /* 1804 * static ieee1394_ir_tag_t 1805 * fwohci_ir_ctx_set(struct device *dev, int channel, int tagbm, 1806 * int bufnum, int maxsize, int flags) 1807 * 1808 * This function will return non-negative value if it succeeds. 1809 * This return value is pointer to the context of isochronous 1810 * transmission. This function will return NULL value if it 1811 * fails. 1812 */ 1813 ieee1394_ir_tag_t 1814 fwohci_ir_ctx_set(struct device *dev, int channel, int tagbm, 1815 int bufnum, int maxsize, int flags) 1816 { 1817 int i, openctx; 1818 struct fwohci_ir_ctx *irc; 1819 struct fwohci_softc *sc = (struct fwohci_softc *)dev; 1820 const char *xname = sc->sc_sc1394.sc1394_dev.dv_xname; 1821 1822 printf("%s: ir_ctx_set channel %d tagbm 0x%x maxsize %d bufnum %d\n", 1823 xname, channel, tagbm, maxsize, bufnum); 1824 /* 1825 * This loop will find the smallest vacant context and check 1826 * whether other channel uses the same channel. 1827 */ 1828 openctx = sc->sc_isoctx; 1829 for (i = 0; i < sc->sc_isoctx; ++i) { 1830 if (sc->sc_ctx_ir[i] == NULL) { 1831 /* 1832 * Find a vacant contet. If this has the 1833 * smallest context number, register it. 1834 */ 1835 if (openctx == sc->sc_isoctx) { 1836 openctx = i; 1837 } 1838 } else { 1839 /* 1840 * This context is used. Check whether this 1841 * context uses the same channel as ours. 1842 */ 1843 if (sc->sc_ctx_ir[i]->irc_channel == channel) { 1844 /* Using same channel. */ 1845 printf("%s: channel %d occupied by ctx%d\n", 1846 xname, channel, i); 1847 return NULL; 1848 } 1849 } 1850 } 1851 1852 /* 1853 * If there is a vacant context, allocate isochronous transmit 1854 * context for it. 1855 */ 1856 if (openctx != sc->sc_isoctx) { 1857 printf("%s using ctx %d for iso receive\n", xname, openctx); 1858 if ((irc = fwohci_ir_ctx_construct(sc, openctx, channel, 1859 tagbm, bufnum, maxsize, flags)) == NULL) { 1860 return NULL; 1861 } 1862 #ifndef IR_CTX_OPENTEST 1863 sc->sc_ctx_ir[openctx] = irc; 1864 #else 1865 fwohci_ir_ctx_destruct(irc); 1866 irc = NULL; 1867 #endif 1868 } else { 1869 printf("%s: cannot find any vacant contexts\n", xname); 1870 irc = NULL; 1871 } 1872 1873 return (ieee1394_ir_tag_t)irc; 1874 } 1875 1876 1877 /* 1878 * int fwohci_ir_ctx_clear(struct device *dev, ieee1394_ir_tag_t *ir) 1879 * 1880 * This function will return 0 if it succeed. Otherwise return 1881 * negative value. 1882 */ 1883 int 1884 fwohci_ir_ctx_clear(struct device *dev, ieee1394_ir_tag_t ir) 1885 { 1886 struct fwohci_ir_ctx *irc = (struct fwohci_ir_ctx *)ir; 1887 struct fwohci_softc *sc = irc->irc_sc; 1888 int i; 1889 1890 if (sc->sc_ctx_ir[irc->irc_num] != irc) { 1891 printf("fwohci_ir_ctx_clear: irc differs %p %p\n", 1892 sc->sc_ctx_ir[irc->irc_num], irc); 1893 return -1; 1894 } 1895 1896 i = 0; 1897 while (irc->irc_status & IRC_STATUS_RUN) { 1898 tsleep((void *)irc, PWAIT|PCATCH, "IEEE1394 iso receive", 100); 1899 if (irc->irc_status & IRC_STATUS_RUN) { 1900 if (fwohci_ir_stop(irc) == 0) { 1901 irc->irc_status &= ~IRC_STATUS_RUN; 1902 } 1903 1904 } 1905 if (++i > 20) { 1906 u_int32_t reg 1907 = OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, 1908 OHCI_SUBREG_ContextControlSet); 1909 1910 printf("fwochi_ir_ctx_clear: " 1911 "Cannot stop iso receive engine\n"); 1912 printf("%s: intr IR_CommandPtr 0x%08x " 1913 "ContextCtrl 0x%08x%s%s%s%s\n", 1914 sc->sc_sc1394.sc1394_dev.dv_xname, 1915 OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, 1916 OHCI_SUBREG_CommandPtr), 1917 reg, 1918 reg & OHCI_CTXCTL_RUN ? " run" : "", 1919 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 1920 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 1921 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 1922 1923 return EBUSY; 1924 } 1925 } 1926 1927 printf("fwohci_ir_ctx_clear: DMA engine is stopped. get %d frames max queuelen %d pos %d\n", 1928 irc->irc_pktcount, irc->irc_maxqueuelen, irc->irc_maxqueuepos); 1929 1930 fwohci_ir_ctx_destruct(irc); 1931 1932 sc->sc_ctx_ir[irc->irc_num] = NULL; 1933 1934 return 0; 1935 } 1936 1937 1938 1939 1940 1941 1942 1943 1944 ieee1394_it_tag_t 1945 fwohci_it_set(struct ieee1394_softc *isc, int channel, int tagbm) 1946 { 1947 ieee1394_it_tag_t rv; 1948 int tag; 1949 1950 for (tag = 0; tagbm != 0 && (tagbm & 0x01) == 0; tagbm >>= 1, ++tag); 1951 1952 rv = fwohci_it_ctx_set((struct fwohci_softc *)isc, channel, tag, 488); 1953 1954 return rv; 1955 } 1956 1957 /* 1958 * static ieee1394_it_tag_t 1959 * fwohci_it_ctx_set(struct fwohci_softc *sc, 1960 * u_int32_t key1 (channel), u_int32_t key2 (tag), int maxsize) 1961 * 1962 * This function will return non-negative value if it succeeds. 1963 * This return value is pointer to the context of isochronous 1964 * transmission. This function will return NULL value if it 1965 * fails. 1966 */ 1967 static ieee1394_it_tag_t 1968 fwohci_it_ctx_set(struct fwohci_softc *sc, int channel, int tag, int maxsize) 1969 { 1970 int i, openctx; 1971 struct fwohci_it_ctx *itc; 1972 const char *xname = sc->sc_sc1394.sc1394_dev.dv_xname; 1973 #ifdef TEST_CHAIN 1974 extern int fwohci_test_chain(struct fwohci_it_ctx *); 1975 #endif /* TEST_CHAIN */ 1976 #ifdef TEST_WRITE 1977 extern void fwohci_test_write(struct fwohci_it_ctx *itc); 1978 #endif /* TEST_WRITE */ 1979 1980 printf("%s: it_ctx_set channel %d tag %d maxsize %d\n", 1981 xname, channel, tag, maxsize); 1982 1983 /* 1984 * This loop will find the smallest vacant context and check 1985 * whether other channel uses the same channel. 1986 */ 1987 openctx = sc->sc_itctx; 1988 for (i = 0; i < sc->sc_itctx; ++i) { 1989 if (sc->sc_ctx_it[i] == NULL) { 1990 /* 1991 * Find a vacant contet. If this has the 1992 * smallest context number, register it. 1993 */ 1994 if (openctx == sc->sc_itctx) { 1995 openctx = i; 1996 } 1997 } else { 1998 /* 1999 * This context is used. Check whether this 2000 * context uses the same channel as ours. 2001 */ 2002 if (sc->sc_ctx_it[i]->itc_channel == channel) { 2003 /* Using same channel. */ 2004 printf("%s: channel %d occupied by ctx%d\n", 2005 xname, channel, i); 2006 return NULL; 2007 } 2008 } 2009 } 2010 2011 /* 2012 * If there is a vacant context, allocate isochronous transmit 2013 * context for it. 2014 */ 2015 if (openctx != sc->sc_itctx) { 2016 printf("%s using ctx %d for iso trasmit\n", xname, openctx); 2017 if ((itc = fwohci_it_ctx_construct(sc, openctx, channel, 2018 tag, maxsize)) == NULL) { 2019 return NULL; 2020 } 2021 sc->sc_ctx_it[openctx] = itc; 2022 2023 #ifdef TEST_CHAIN 2024 fwohci_test_chain(itc); 2025 #endif /* TEST_CHAIN */ 2026 #ifdef TEST_WRITE 2027 fwohci_test_write(itc); 2028 itc = NULL; 2029 #endif /* TEST_WRITE */ 2030 2031 } else { 2032 printf("%s: cannot find any vacant contexts\n", xname); 2033 itc = NULL; 2034 } 2035 2036 return (ieee1394_it_tag_t)itc; 2037 } 2038 2039 2040 /* 2041 * int fwohci_it_ctx_clear(ieee1394_it_tag_t *it) 2042 * 2043 * This function will return 0 if it succeed. Otherwise return 2044 * negative value. 2045 */ 2046 int 2047 fwohci_it_ctx_clear(ieee1394_it_tag_t *it) 2048 { 2049 struct fwohci_it_ctx *itc = (struct fwohci_it_ctx *)it; 2050 struct fwohci_softc *sc = itc->itc_sc; 2051 int i; 2052 2053 if (sc->sc_ctx_it[itc->itc_num] != itc) { 2054 printf("fwohci_it_ctx_clear: itc differs %p %p\n", 2055 sc->sc_ctx_it[itc->itc_num], itc); 2056 return -1; 2057 } 2058 2059 fwohci_it_ctx_flush(it); 2060 2061 i = 0; 2062 while (itc->itc_flags & ITC_FLAGS_RUN) { 2063 tsleep((void *)itc, PWAIT|PCATCH, "IEEE1394 iso transmit", 100); 2064 if (itc->itc_flags & ITC_FLAGS_RUN) { 2065 u_int32_t reg; 2066 2067 reg = OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, 2068 OHCI_SUBREG_ContextControlSet); 2069 2070 if ((reg & OHCI_CTXCTL_WAKE) == 0) { 2071 itc->itc_flags &= ~ITC_FLAGS_RUN; 2072 printf("fwochi_it_ctx_clear: " 2073 "DMA engine stopped without intr\n"); 2074 } 2075 printf("%s: %d intr IT_CommandPtr 0x%08x " 2076 "ContextCtrl 0x%08x%s%s%s%s\n", 2077 sc->sc_sc1394.sc1394_dev.dv_xname, i, 2078 OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, 2079 OHCI_SUBREG_CommandPtr), 2080 reg, 2081 reg & OHCI_CTXCTL_RUN ? " run" : "", 2082 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 2083 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 2084 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 2085 2086 2087 } 2088 if (++i > 20) { 2089 u_int32_t reg 2090 = OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, 2091 OHCI_SUBREG_ContextControlSet); 2092 2093 printf("fwochi_it_ctx_clear: " 2094 "Cannot stop iso transmit engine\n"); 2095 printf("%s: intr IT_CommandPtr 0x%08x " 2096 "ContextCtrl 0x%08x%s%s%s%s\n", 2097 sc->sc_sc1394.sc1394_dev.dv_xname, 2098 OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, 2099 OHCI_SUBREG_CommandPtr), 2100 reg, 2101 reg & OHCI_CTXCTL_RUN ? " run" : "", 2102 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 2103 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 2104 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 2105 2106 return EBUSY; 2107 } 2108 } 2109 2110 printf("fwohci_it_ctx_clear: DMA engine is stopped.\n"); 2111 2112 fwohci_it_ctx_destruct(itc); 2113 2114 sc->sc_ctx_it[itc->itc_num] = NULL; 2115 2116 2117 return 0; 2118 } 2119 2120 2121 2122 2123 2124 2125 /* 2126 * Asyncronous Receive Requests input frontend. 2127 */ 2128 static void 2129 fwohci_arrq_input(struct fwohci_softc *sc, struct fwohci_ctx *fc) 2130 { 2131 int rcode; 2132 u_int32_t key1, key2; 2133 struct fwohci_handler *fh; 2134 struct fwohci_pkt pkt, res; 2135 2136 /* 2137 * Do not return if next packet is in the buffer, or the next 2138 * packet cannot be received until the next receive interrupt. 2139 */ 2140 while (fwohci_buf_input(sc, fc, &pkt)) { 2141 if (pkt.fp_tcode == OHCI_TCODE_PHY) { 2142 fwohci_phy_input(sc, &pkt); 2143 continue; 2144 } 2145 key1 = pkt.fp_hdr[1] & 0xffff; 2146 key2 = pkt.fp_hdr[2]; 2147 memset(&res, 0, sizeof(res)); 2148 res.fp_uio.uio_rw = UIO_WRITE; 2149 res.fp_uio.uio_segflg = UIO_SYSSPACE; 2150 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL; 2151 fh = LIST_NEXT(fh, fh_list)) { 2152 if (pkt.fp_tcode == fh->fh_tcode && 2153 key1 == fh->fh_key1 && 2154 key2 == fh->fh_key2) { 2155 rcode = (*fh->fh_handler)(sc, fh->fh_handarg, 2156 &pkt); 2157 break; 2158 } 2159 } 2160 if (fh == NULL) { 2161 rcode = IEEE1394_RCODE_ADDRESS_ERROR; 2162 DPRINTFN(1, ("fwohci_arrq_input: no listener: tcode " 2163 "0x%x, addr=0x%04x %08x\n", pkt.fp_tcode, key1, 2164 key2)); 2165 } 2166 if (((*pkt.fp_trail & 0x001f0000) >> 16) != 2167 OHCI_CTXCTL_EVENT_ACK_PENDING) 2168 continue; 2169 if (rcode != -1) 2170 fwohci_atrs_output(sc, rcode, &pkt, &res); 2171 } 2172 fwohci_buf_next(sc, fc); 2173 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx, 2174 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE); 2175 } 2176 2177 2178 /* 2179 * Asynchronous Receive Response input frontend. 2180 */ 2181 static void 2182 fwohci_arrs_input(struct fwohci_softc *sc, struct fwohci_ctx *fc) 2183 { 2184 struct fwohci_pkt pkt; 2185 struct fwohci_handler *fh; 2186 u_int16_t srcid; 2187 int rcode, tlabel; 2188 2189 while (fwohci_buf_input(sc, fc, &pkt)) { 2190 srcid = pkt.fp_hdr[1] >> 16; 2191 rcode = (pkt.fp_hdr[1] & 0x0000f000) >> 12; 2192 tlabel = (pkt.fp_hdr[0] & 0x0000fc00) >> 10; 2193 DPRINTFN(1, ("fwohci_arrs_input: tcode 0x%x, from 0x%04x," 2194 " tlabel 0x%x, rcode 0x%x, hlen %d, dlen %d\n", 2195 pkt.fp_tcode, srcid, tlabel, rcode, pkt.fp_hlen, 2196 pkt.fp_dlen)); 2197 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL; 2198 fh = LIST_NEXT(fh, fh_list)) { 2199 if (pkt.fp_tcode == fh->fh_tcode && 2200 (srcid & OHCI_NodeId_NodeNumber) == fh->fh_key1 && 2201 tlabel == fh->fh_key2) { 2202 (*fh->fh_handler)(sc, fh->fh_handarg, &pkt); 2203 LIST_REMOVE(fh, fh_list); 2204 free(fh, M_DEVBUF); 2205 break; 2206 } 2207 } 2208 if (fh == NULL) 2209 DPRINTFN(1, ("fwohci_arrs_input: no listner\n")); 2210 } 2211 fwohci_buf_next(sc, fc); 2212 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx, 2213 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE); 2214 } 2215 2216 /* 2217 * Isochronous Receive input frontend. 2218 */ 2219 static void 2220 fwohci_as_input(struct fwohci_softc *sc, struct fwohci_ctx *fc) 2221 { 2222 int rcode, chan, tag; 2223 struct iovec *iov; 2224 struct fwohci_handler *fh; 2225 struct fwohci_pkt pkt; 2226 2227 #if DOUBLEBUF 2228 if (fc->fc_type == FWOHCI_CTX_ISO_MULTI) { 2229 struct fwohci_buf *fb; 2230 int i; 2231 u_int32_t reg; 2232 2233 /* stop dma engine before read buffer */ 2234 reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, 2235 OHCI_SUBREG_ContextControlClear); 2236 DPRINTFN(5, ("ir_input %08x =>", reg)); 2237 if (reg & OHCI_CTXCTL_RUN) { 2238 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, 2239 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 2240 } 2241 DPRINTFN(5, (" %08x\n", OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlClear))); 2242 2243 i = 0; 2244 while ((reg = OHCI_SYNC_RX_DMA_READ(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlSet)) & OHCI_CTXCTL_ACTIVE) { 2245 delay(10); 2246 if (++i > 10000) { 2247 printf("cannot stop dma engine 0x%08x\n", reg); 2248 return; 2249 } 2250 } 2251 2252 /* rotate dma buffer */ 2253 fb = TAILQ_FIRST(&fc->fc_buf2); 2254 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_CommandPtr, 2255 fb->fb_daddr | 1); 2256 /* start dma engine */ 2257 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, 2258 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN); 2259 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, 2260 (1 << fc->fc_ctx)); 2261 } 2262 #endif 2263 2264 while (fwohci_buf_input_ppb(sc, fc, &pkt)) { 2265 chan = (pkt.fp_hdr[0] & 0x00003f00) >> 8; 2266 tag = (pkt.fp_hdr[0] & 0x0000c000) >> 14; 2267 DPRINTFN(1, ("fwohci_as_input: hdr 0x%08x, tcode 0x%0x, hlen %d" 2268 ", dlen %d\n", pkt.fp_hdr[0], pkt.fp_tcode, pkt.fp_hlen, 2269 pkt.fp_dlen)); 2270 if (tag == IEEE1394_TAG_GASP && 2271 fc->fc_type == FWOHCI_CTX_ISO_SINGLE) { 2272 /* 2273 * The pkt with tag=3 is GASP format. 2274 * Move GASP header to header part. 2275 */ 2276 if (pkt.fp_dlen < 8) 2277 continue; 2278 iov = pkt.fp_iov; 2279 /* assuming pkt per buffer mode */ 2280 pkt.fp_hdr[1] = ntohl(((u_int32_t *)iov->iov_base)[0]); 2281 pkt.fp_hdr[2] = ntohl(((u_int32_t *)iov->iov_base)[1]); 2282 iov->iov_base = (caddr_t)iov->iov_base + 8; 2283 iov->iov_len -= 8; 2284 pkt.fp_hlen += 8; 2285 pkt.fp_dlen -= 8; 2286 } 2287 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL; 2288 fh = LIST_NEXT(fh, fh_list)) { 2289 if (pkt.fp_tcode == fh->fh_tcode && 2290 (chan == fh->fh_key1 || 2291 fh->fh_key1 == IEEE1394_ISO_CHANNEL_ANY) && 2292 ((1 << tag) & fh->fh_key2) != 0) { 2293 rcode = (*fh->fh_handler)(sc, fh->fh_handarg, 2294 &pkt); 2295 break; 2296 } 2297 } 2298 #ifdef FW_DEBUG 2299 if (fh == NULL) { 2300 DPRINTFN(1, ("fwohci_as_input: no handler\n")); 2301 } else { 2302 DPRINTFN(1, ("fwohci_as_input: rcode %d\n", rcode)); 2303 } 2304 #endif 2305 } 2306 fwohci_buf_next(sc, fc); 2307 2308 if (fc->fc_type == FWOHCI_CTX_ISO_SINGLE) { 2309 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, 2310 OHCI_SUBREG_ContextControlSet, 2311 OHCI_CTXCTL_WAKE); 2312 } 2313 } 2314 2315 /* 2316 * Asynchronous Transmit common routine. 2317 */ 2318 static int 2319 fwohci_at_output(struct fwohci_softc *sc, struct fwohci_ctx *fc, 2320 struct fwohci_pkt *pkt) 2321 { 2322 struct fwohci_buf *fb; 2323 struct fwohci_desc *fd; 2324 struct mbuf *m, *m0; 2325 int i, ndesc, error, off, len; 2326 u_int32_t val; 2327 #ifdef FW_DEBUG 2328 struct iovec *iov; 2329 int tlabel = (pkt->fp_hdr[0] & 0x0000fc00) >> 10; 2330 #endif 2331 2332 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == IEEE1394_BCAST_PHY_ID) 2333 /* We can't send anything during selfid duration */ 2334 return EAGAIN; 2335 2336 #ifdef FW_DEBUG 2337 DPRINTFN(1, ("fwohci_at_output: tcode 0x%x, tlabel 0x%x hlen %d, " 2338 "dlen %d", pkt->fp_tcode, tlabel, pkt->fp_hlen, pkt->fp_dlen)); 2339 for (i = 0; i < pkt->fp_hlen/4; i++) 2340 DPRINTFN(2, ("%s%08x", i?" ":"\n ", pkt->fp_hdr[i])); 2341 DPRINTFN(2, ("$")); 2342 for (ndesc = 0, iov = pkt->fp_iov; 2343 ndesc < pkt->fp_uio.uio_iovcnt; ndesc++, iov++) { 2344 for (i = 0; i < iov->iov_len; i++) 2345 DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n ", 2346 ((u_int8_t *)iov->iov_base)[i])); 2347 DPRINTFN(2, ("$")); 2348 } 2349 DPRINTFN(1, ("\n")); 2350 #endif 2351 2352 if ((m = pkt->fp_m) != NULL) { 2353 for (ndesc = 2; m != NULL; m = m->m_next) 2354 ndesc++; 2355 if (ndesc > OHCI_DESC_MAX) { 2356 m0 = NULL; 2357 ndesc = 2; 2358 for (off = 0; off < pkt->fp_dlen; off += len) { 2359 if (m0 == NULL) { 2360 MGETHDR(m0, M_DONTWAIT, MT_DATA); 2361 if (m0 != NULL) 2362 M_COPY_PKTHDR(m0, pkt->fp_m); 2363 m = m0; 2364 } else { 2365 MGET(m->m_next, M_DONTWAIT, MT_DATA); 2366 m = m->m_next; 2367 } 2368 if (m != NULL) 2369 MCLGET(m, M_DONTWAIT); 2370 if (m == NULL || (m->m_flags & M_EXT) == 0) { 2371 m_freem(m0); 2372 return ENOMEM; 2373 } 2374 len = pkt->fp_dlen - off; 2375 if (len > m->m_ext.ext_size) 2376 len = m->m_ext.ext_size; 2377 m_copydata(pkt->fp_m, off, len, 2378 mtod(m, caddr_t)); 2379 m->m_len = len; 2380 ndesc++; 2381 } 2382 m_freem(pkt->fp_m); 2383 pkt->fp_m = m0; 2384 } 2385 } else 2386 ndesc = 2 + pkt->fp_uio.uio_iovcnt; 2387 2388 if (ndesc > OHCI_DESC_MAX) 2389 return ENOBUFS; 2390 2391 if (fc->fc_bufcnt > 50) /*XXX*/ 2392 return ENOBUFS; 2393 fb = malloc(sizeof(*fb), M_DEVBUF, M_WAITOK); 2394 fb->fb_nseg = ndesc; 2395 fb->fb_desc = fwohci_desc_get(sc, ndesc); 2396 if (fb->fb_desc == NULL) { 2397 free(fb, M_DEVBUF); 2398 return ENOBUFS; 2399 } 2400 fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr + 2401 ((caddr_t)fb->fb_desc - (caddr_t)sc->sc_desc); 2402 fb->fb_m = pkt->fp_m; 2403 fb->fb_callback = pkt->fp_callback; 2404 fb->fb_statuscb = pkt->fp_statuscb; 2405 fb->fb_statusarg = pkt->fp_statusarg; 2406 2407 if (ndesc > 2) { 2408 if ((error = bus_dmamap_create(sc->sc_dmat, pkt->fp_dlen, ndesc, 2409 PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) { 2410 fwohci_desc_put(sc, fb->fb_desc, ndesc); 2411 free(fb, M_DEVBUF); 2412 return error; 2413 } 2414 2415 if (pkt->fp_m != NULL) 2416 error = bus_dmamap_load_mbuf(sc->sc_dmat, fb->fb_dmamap, 2417 pkt->fp_m, BUS_DMA_WAITOK); 2418 else 2419 error = bus_dmamap_load_uio(sc->sc_dmat, fb->fb_dmamap, 2420 &pkt->fp_uio, BUS_DMA_WAITOK); 2421 if (error != 0) { 2422 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap); 2423 fwohci_desc_put(sc, fb->fb_desc, ndesc); 2424 free(fb, M_DEVBUF); 2425 return error; 2426 } 2427 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, pkt->fp_dlen, 2428 BUS_DMASYNC_PREWRITE); 2429 } 2430 2431 fd = fb->fb_desc; 2432 fd->fd_flags = OHCI_DESC_IMMED; 2433 fd->fd_reqcount = pkt->fp_hlen; 2434 fd->fd_data = 0; 2435 fd->fd_branch = 0; 2436 fd->fd_status = 0; 2437 if (fc->fc_ctx == OHCI_CTX_ASYNC_TX_RESPONSE) { 2438 i = 3; /* XXX: 3 sec */ 2439 val = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer); 2440 fd->fd_timestamp = ((val >> 12) & 0x1fff) | 2441 ((((val >> 25) + i) & 0x7) << 13); 2442 } else 2443 fd->fd_timestamp = 0; 2444 memcpy(fd + 1, pkt->fp_hdr, pkt->fp_hlen); 2445 for (i = 0; i < ndesc - 2; i++) { 2446 fd = fb->fb_desc + 2 + i; 2447 fd->fd_flags = 0; 2448 fd->fd_reqcount = fb->fb_dmamap->dm_segs[i].ds_len; 2449 fd->fd_data = fb->fb_dmamap->dm_segs[i].ds_addr; 2450 fd->fd_branch = 0; 2451 fd->fd_status = 0; 2452 fd->fd_timestamp = 0; 2453 } 2454 fd->fd_flags |= OHCI_DESC_LAST | OHCI_DESC_BRANCH; 2455 fd->fd_flags |= OHCI_DESC_INTR_ALWAYS; 2456 2457 #ifdef FW_DEBUG 2458 DPRINTFN(1, ("fwohci_at_output: desc %ld", 2459 (long)(fb->fb_desc - sc->sc_desc))); 2460 for (i = 0; i < ndesc * 4; i++) 2461 DPRINTFN(2, ("%s%08x", i&7?" ":"\n ", 2462 ((u_int32_t *)fb->fb_desc)[i])); 2463 DPRINTFN(1, ("\n")); 2464 #endif 2465 2466 val = OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx, 2467 OHCI_SUBREG_ContextControlClear); 2468 2469 if (val & OHCI_CTXCTL_RUN) { 2470 if (fc->fc_branch == NULL) { 2471 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx, 2472 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 2473 goto run; 2474 } 2475 *fc->fc_branch = fb->fb_daddr | ndesc; 2476 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx, 2477 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE); 2478 } else { 2479 run: 2480 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx, 2481 OHCI_SUBREG_CommandPtr, fb->fb_daddr | ndesc); 2482 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx, 2483 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN); 2484 } 2485 fc->fc_branch = &fd->fd_branch; 2486 2487 fc->fc_bufcnt++; 2488 TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list); 2489 pkt->fp_m = NULL; 2490 return 0; 2491 } 2492 2493 static void 2494 fwohci_at_done(struct fwohci_softc *sc, struct fwohci_ctx *fc, int force) 2495 { 2496 struct fwohci_buf *fb; 2497 struct fwohci_desc *fd; 2498 struct fwohci_pkt pkt; 2499 int i; 2500 2501 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) { 2502 fd = fb->fb_desc; 2503 #ifdef FW_DEBUG 2504 DPRINTFN(1, ("fwohci_at_done: %sdesc %ld (%d)", 2505 force ? "force " : "", (long)(fd - sc->sc_desc), 2506 fb->fb_nseg)); 2507 for (i = 0; i < fb->fb_nseg * 4; i++) 2508 DPRINTFN(2, ("%s%08x", i&7?" ":"\n ", 2509 ((u_int32_t *)fd)[i])); 2510 DPRINTFN(1, ("\n")); 2511 #endif 2512 if (fb->fb_nseg > 2) 2513 fd += fb->fb_nseg - 1; 2514 if (!force && !(fd->fd_status & OHCI_CTXCTL_ACTIVE)) 2515 break; 2516 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list); 2517 if (fc->fc_branch == &fd->fd_branch) { 2518 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx, 2519 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); 2520 fc->fc_branch = NULL; 2521 for (i = 0; i < OHCI_LOOP; i++) { 2522 if (!(OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx, 2523 OHCI_SUBREG_ContextControlClear) & 2524 OHCI_CTXCTL_ACTIVE)) 2525 break; 2526 DELAY(10); 2527 } 2528 } 2529 2530 if (fb->fb_statuscb) { 2531 memset(&pkt, 0, sizeof(pkt)); 2532 pkt.fp_status = fd->fd_status; 2533 memcpy(pkt.fp_hdr, fd + 1, sizeof(pkt.fp_hdr[0])); 2534 2535 /* Indicate this is just returning the status bits. */ 2536 pkt.fp_tcode = -1; 2537 (*fb->fb_statuscb)(sc, fb->fb_statusarg, &pkt); 2538 fb->fb_statuscb = NULL; 2539 fb->fb_statusarg = NULL; 2540 } 2541 fwohci_desc_put(sc, fb->fb_desc, fb->fb_nseg); 2542 if (fb->fb_nseg > 2) 2543 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap); 2544 fc->fc_bufcnt--; 2545 if (fb->fb_callback) { 2546 (*fb->fb_callback)(sc->sc_sc1394.sc1394_if, fb->fb_m); 2547 fb->fb_callback = NULL; 2548 } else if (fb->fb_m != NULL) 2549 m_freem(fb->fb_m); 2550 free(fb, M_DEVBUF); 2551 } 2552 } 2553 2554 /* 2555 * Asynchronous Transmit Reponse -- in response of request packet. 2556 */ 2557 static void 2558 fwohci_atrs_output(struct fwohci_softc *sc, int rcode, struct fwohci_pkt *req, 2559 struct fwohci_pkt *res) 2560 { 2561 2562 if (((*req->fp_trail & 0x001f0000) >> 16) != 2563 OHCI_CTXCTL_EVENT_ACK_PENDING) 2564 return; 2565 2566 res->fp_hdr[0] = (req->fp_hdr[0] & 0x0000fc00) | 0x00000100; 2567 res->fp_hdr[1] = (req->fp_hdr[1] & 0xffff0000) | (rcode << 12); 2568 switch (req->fp_tcode) { 2569 case IEEE1394_TCODE_WRITE_REQ_QUAD: 2570 case IEEE1394_TCODE_WRITE_REQ_BLOCK: 2571 res->fp_tcode = IEEE1394_TCODE_WRITE_RESP; 2572 res->fp_hlen = 12; 2573 break; 2574 case IEEE1394_TCODE_READ_REQ_QUAD: 2575 res->fp_tcode = IEEE1394_TCODE_READ_RESP_QUAD; 2576 res->fp_hlen = 16; 2577 res->fp_dlen = 0; 2578 if (res->fp_uio.uio_iovcnt == 1 && res->fp_iov[0].iov_len == 4) 2579 res->fp_hdr[3] = 2580 *(u_int32_t *)res->fp_iov[0].iov_base; 2581 res->fp_uio.uio_iovcnt = 0; 2582 break; 2583 case IEEE1394_TCODE_READ_REQ_BLOCK: 2584 case IEEE1394_TCODE_LOCK_REQ: 2585 if (req->fp_tcode == IEEE1394_TCODE_LOCK_REQ) 2586 res->fp_tcode = IEEE1394_TCODE_LOCK_RESP; 2587 else 2588 res->fp_tcode = IEEE1394_TCODE_READ_RESP_BLOCK; 2589 res->fp_hlen = 16; 2590 res->fp_dlen = res->fp_uio.uio_resid; 2591 res->fp_hdr[3] = res->fp_dlen << 16; 2592 break; 2593 } 2594 res->fp_hdr[0] |= (res->fp_tcode << 4); 2595 fwohci_at_output(sc, sc->sc_ctx_atrs, res); 2596 } 2597 2598 /* 2599 * APPLICATION LAYER SERVICES 2600 */ 2601 2602 /* 2603 * Retrieve Global UID from GUID ROM 2604 */ 2605 static int 2606 fwohci_guidrom_init(struct fwohci_softc *sc) 2607 { 2608 int i, n, off; 2609 u_int32_t val1, val2; 2610 2611 /* Extract the Global UID 2612 */ 2613 val1 = OHCI_CSR_READ(sc, OHCI_REG_GUIDHi); 2614 val2 = OHCI_CSR_READ(sc, OHCI_REG_GUIDLo); 2615 2616 if (val1 != 0 || val2 != 0) { 2617 sc->sc_sc1394.sc1394_guid[0] = (val1 >> 24) & 0xff; 2618 sc->sc_sc1394.sc1394_guid[1] = (val1 >> 16) & 0xff; 2619 sc->sc_sc1394.sc1394_guid[2] = (val1 >> 8) & 0xff; 2620 sc->sc_sc1394.sc1394_guid[3] = (val1 >> 0) & 0xff; 2621 sc->sc_sc1394.sc1394_guid[4] = (val2 >> 24) & 0xff; 2622 sc->sc_sc1394.sc1394_guid[5] = (val2 >> 16) & 0xff; 2623 sc->sc_sc1394.sc1394_guid[6] = (val2 >> 8) & 0xff; 2624 sc->sc_sc1394.sc1394_guid[7] = (val2 >> 0) & 0xff; 2625 } else { 2626 val1 = OHCI_CSR_READ(sc, OHCI_REG_Version); 2627 if ((val1 & OHCI_Version_GUID_ROM) == 0) 2628 return -1; 2629 OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom, OHCI_Guid_AddrReset); 2630 for (i = 0; i < OHCI_LOOP; i++) { 2631 val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom); 2632 if (!(val1 & OHCI_Guid_AddrReset)) 2633 break; 2634 DELAY(10); 2635 } 2636 off = OHCI_BITVAL(val1, OHCI_Guid_MiniROM) + 4; 2637 val2 = 0; 2638 for (n = 0; n < off + sizeof(sc->sc_sc1394.sc1394_guid); n++) { 2639 OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom, 2640 OHCI_Guid_RdStart); 2641 for (i = 0; i < OHCI_LOOP; i++) { 2642 val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom); 2643 if (!(val1 & OHCI_Guid_RdStart)) 2644 break; 2645 DELAY(10); 2646 } 2647 if (n < off) 2648 continue; 2649 val1 = OHCI_BITVAL(val1, OHCI_Guid_RdData); 2650 sc->sc_sc1394.sc1394_guid[n - off] = val1; 2651 val2 |= val1; 2652 } 2653 if (val2 == 0) 2654 return -1; 2655 } 2656 return 0; 2657 } 2658 2659 /* 2660 * Initialization for Configuration ROM (no DMA context) 2661 */ 2662 2663 #define CFR_MAXUNIT 20 2664 2665 struct configromctx { 2666 u_int32_t *ptr; 2667 int curunit; 2668 struct { 2669 u_int32_t *start; 2670 int length; 2671 u_int32_t *refer; 2672 int refunit; 2673 } unit[CFR_MAXUNIT]; 2674 }; 2675 2676 #define CFR_PUT_DATA4(cfr, d1, d2, d3, d4) \ 2677 (*(cfr)->ptr++ = (((d1)<<24) | ((d2)<<16) | ((d3)<<8) | (d4))) 2678 2679 #define CFR_PUT_DATA1(cfr, d) (*(cfr)->ptr++ = (d)) 2680 2681 #define CFR_PUT_VALUE(cfr, key, d) (*(cfr)->ptr++ = ((key)<<24) | (d)) 2682 2683 #define CFR_PUT_CRC(cfr, n) \ 2684 (*(cfr)->unit[n].start = ((cfr)->unit[n].length << 16) | \ 2685 fwohci_crc16((cfr)->unit[n].start + 1, (cfr)->unit[n].length)) 2686 2687 #define CFR_START_UNIT(cfr, n) \ 2688 do { \ 2689 if ((cfr)->unit[n].refer != NULL) { \ 2690 *(cfr)->unit[n].refer |= \ 2691 (cfr)->ptr - (cfr)->unit[n].refer; \ 2692 CFR_PUT_CRC(cfr, (cfr)->unit[n].refunit); \ 2693 } \ 2694 (cfr)->curunit = (n); \ 2695 (cfr)->unit[n].start = (cfr)->ptr++; \ 2696 } while (0 /* CONSTCOND */) 2697 2698 #define CFR_PUT_REFER(cfr, key, n) \ 2699 do { \ 2700 (cfr)->unit[n].refer = (cfr)->ptr; \ 2701 (cfr)->unit[n].refunit = (cfr)->curunit; \ 2702 *(cfr)->ptr++ = (key) << 24; \ 2703 } while (0 /* CONSTCOND */) 2704 2705 #define CFR_END_UNIT(cfr) \ 2706 do { \ 2707 (cfr)->unit[(cfr)->curunit].length = (cfr)->ptr - \ 2708 ((cfr)->unit[(cfr)->curunit].start + 1); \ 2709 CFR_PUT_CRC(cfr, (cfr)->curunit); \ 2710 } while (0 /* CONSTCOND */) 2711 2712 static u_int16_t 2713 fwohci_crc16(u_int32_t *ptr, int len) 2714 { 2715 int shift; 2716 u_int32_t crc, sum, data; 2717 2718 crc = 0; 2719 while (len-- > 0) { 2720 data = *ptr++; 2721 for (shift = 28; shift >= 0; shift -= 4) { 2722 sum = ((crc >> 12) ^ (data >> shift)) & 0x000f; 2723 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; 2724 } 2725 crc &= 0xffff; 2726 } 2727 return crc; 2728 } 2729 2730 static void 2731 fwohci_configrom_init(struct fwohci_softc *sc) 2732 { 2733 int i, val; 2734 struct fwohci_buf *fb; 2735 u_int32_t *hdr; 2736 struct configromctx cfr; 2737 2738 fb = &sc->sc_buf_cnfrom; 2739 memset(&cfr, 0, sizeof(cfr)); 2740 cfr.ptr = hdr = (u_int32_t *)fb->fb_buf; 2741 2742 /* headers */ 2743 CFR_START_UNIT(&cfr, 0); 2744 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusId)); 2745 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusOptions)); 2746 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDHi)); 2747 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDLo)); 2748 CFR_END_UNIT(&cfr); 2749 /* copy info_length from crc_length */ 2750 *hdr |= (*hdr & 0x00ff0000) << 8; 2751 OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMhdr, *hdr); 2752 2753 /* root directory */ 2754 CFR_START_UNIT(&cfr, 1); 2755 CFR_PUT_VALUE(&cfr, 0x03, 0x00005e); /* vendor id */ 2756 CFR_PUT_REFER(&cfr, 0x81, 2); /* textual descriptor offset */ 2757 CFR_PUT_VALUE(&cfr, 0x0c, 0x0083c0); /* node capability */ 2758 /* spt,64,fix,lst,drq */ 2759 #ifdef INET 2760 CFR_PUT_REFER(&cfr, 0xd1, 3); /* IPv4 unit directory */ 2761 #endif /* INET */ 2762 #ifdef INET6 2763 CFR_PUT_REFER(&cfr, 0xd1, 4); /* IPv6 unit directory */ 2764 #endif /* INET6 */ 2765 CFR_END_UNIT(&cfr); 2766 2767 CFR_START_UNIT(&cfr, 2); 2768 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2769 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */ 2770 CFR_PUT_DATA4(&cfr, 'N', 'e', 't', 'B'); 2771 CFR_PUT_DATA4(&cfr, 'S', 'D', 0x00, 0x00); 2772 CFR_END_UNIT(&cfr); 2773 2774 #ifdef INET 2775 /* IPv4 unit directory */ 2776 CFR_START_UNIT(&cfr, 3); 2777 CFR_PUT_VALUE(&cfr, 0x12, 0x00005e); /* unit spec id */ 2778 CFR_PUT_REFER(&cfr, 0x81, 6); /* textual descriptor offset */ 2779 CFR_PUT_VALUE(&cfr, 0x13, 0x000001); /* unit sw version */ 2780 CFR_PUT_REFER(&cfr, 0x81, 7); /* textual descriptor offset */ 2781 CFR_PUT_REFER(&cfr, 0x95, 8); /* Unit location */ 2782 CFR_END_UNIT(&cfr); 2783 2784 CFR_START_UNIT(&cfr, 6); 2785 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2786 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */ 2787 CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A'); 2788 CFR_END_UNIT(&cfr); 2789 2790 CFR_START_UNIT(&cfr, 7); 2791 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2792 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */ 2793 CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '4'); 2794 CFR_END_UNIT(&cfr); 2795 2796 CFR_START_UNIT(&cfr, 8); /* Spec's valid addr range. */ 2797 CFR_PUT_DATA1(&cfr, FW_FIFO_HI); 2798 CFR_PUT_DATA1(&cfr, (FW_FIFO_LO | 0x1)); 2799 CFR_PUT_DATA1(&cfr, FW_FIFO_HI); 2800 CFR_PUT_DATA1(&cfr, FW_FIFO_LO); 2801 CFR_END_UNIT(&cfr); 2802 2803 #endif /* INET */ 2804 2805 #ifdef INET6 2806 /* IPv6 unit directory */ 2807 CFR_START_UNIT(&cfr, 4); 2808 CFR_PUT_VALUE(&cfr, 0x12, 0x00005e); /* unit spec id */ 2809 CFR_PUT_REFER(&cfr, 0x81, 9); /* textual descriptor offset */ 2810 CFR_PUT_VALUE(&cfr, 0x13, 0x000002); /* unit sw version */ 2811 /* XXX: TBA by IANA */ 2812 CFR_PUT_REFER(&cfr, 0x81, 10); /* textual descriptor offset */ 2813 CFR_PUT_REFER(&cfr, 0x95, 11); /* Unit location */ 2814 CFR_END_UNIT(&cfr); 2815 2816 CFR_START_UNIT(&cfr, 9); 2817 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2818 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */ 2819 CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A'); 2820 CFR_END_UNIT(&cfr); 2821 2822 CFR_START_UNIT(&cfr, 10); 2823 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */ 2824 CFR_PUT_DATA1(&cfr, 0); 2825 CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '6'); 2826 CFR_END_UNIT(&cfr); 2827 2828 CFR_START_UNIT(&cfr, 11); /* Spec's valid addr range. */ 2829 CFR_PUT_DATA1(&cfr, FW_FIFO_HI); 2830 CFR_PUT_DATA1(&cfr, (FW_FIFO_LO | 0x1)); 2831 CFR_PUT_DATA1(&cfr, FW_FIFO_HI); 2832 CFR_PUT_DATA1(&cfr, FW_FIFO_LO); 2833 CFR_END_UNIT(&cfr); 2834 2835 #endif /* INET6 */ 2836 2837 fb->fb_off = cfr.ptr - hdr; 2838 #ifdef FW_DEBUG 2839 DPRINTF(("%s: Config ROM:", sc->sc_sc1394.sc1394_dev.dv_xname)); 2840 for (i = 0; i < fb->fb_off; i++) 2841 DPRINTF(("%s%08x", i&7?" ":"\n ", hdr[i])); 2842 DPRINTF(("\n")); 2843 #endif /* FW_DEBUG */ 2844 2845 /* 2846 * Make network byte order for DMA 2847 */ 2848 for (i = 0; i < fb->fb_off; i++) 2849 HTONL(hdr[i]); 2850 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, 2851 (caddr_t)cfr.ptr - fb->fb_buf, BUS_DMASYNC_PREWRITE); 2852 2853 OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMmap, 2854 fb->fb_dmamap->dm_segs[0].ds_addr); 2855 2856 /* This register is only valid on OHCI 1.1. */ 2857 val = OHCI_CSR_READ(sc, OHCI_REG_Version); 2858 if ((OHCI_Version_GET_Version(val) == 1) && 2859 (OHCI_Version_GET_Revision(val) == 1)) 2860 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, 2861 OHCI_HCControl_BIBImageValid); 2862 2863 /* Just allow quad reads of the rom. */ 2864 for (i = 0; i < fb->fb_off; i++) 2865 fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD, 2866 CSR_BASE_HI, CSR_BASE_LO + CSR_CONFIG_ROM + (i * 4), 2867 fwohci_configrom_input, NULL); 2868 } 2869 2870 static int 2871 fwohci_configrom_input(struct fwohci_softc *sc, void *arg, 2872 struct fwohci_pkt *pkt) 2873 { 2874 struct fwohci_pkt res; 2875 u_int32_t loc, *rom; 2876 2877 /* This will be used as an array index so size accordingly. */ 2878 loc = pkt->fp_hdr[2] - (CSR_BASE_LO + CSR_CONFIG_ROM); 2879 if ((loc & 0x03) != 0) { 2880 /* alignment error */ 2881 return IEEE1394_RCODE_ADDRESS_ERROR; 2882 } 2883 else 2884 loc /= 4; 2885 rom = (u_int32_t *)sc->sc_buf_cnfrom.fb_buf; 2886 2887 DPRINTFN(1, ("fwohci_configrom_input: ConfigRom[0x%04x]: 0x%08x\n", loc, 2888 ntohl(rom[loc]))); 2889 2890 memset(&res, 0, sizeof(res)); 2891 res.fp_hdr[3] = rom[loc]; 2892 fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res); 2893 return -1; 2894 } 2895 2896 /* 2897 * SelfID buffer (no DMA context) 2898 */ 2899 static void 2900 fwohci_selfid_init(struct fwohci_softc *sc) 2901 { 2902 struct fwohci_buf *fb; 2903 2904 fb = &sc->sc_buf_selfid; 2905 #ifdef DIAGNOSTIC 2906 if ((fb->fb_dmamap->dm_segs[0].ds_addr & 0x7ff) != 0) 2907 panic("fwohci_selfid_init: not aligned: %ld (%ld) %p", 2908 (unsigned long)fb->fb_dmamap->dm_segs[0].ds_addr, 2909 (unsigned long)fb->fb_dmamap->dm_segs[0].ds_len, fb->fb_buf); 2910 #endif 2911 memset(fb->fb_buf, 0, fb->fb_dmamap->dm_segs[0].ds_len); 2912 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, 2913 fb->fb_dmamap->dm_segs[0].ds_len, BUS_DMASYNC_PREREAD); 2914 2915 OHCI_CSR_WRITE(sc, OHCI_REG_SelfIDBuffer, 2916 fb->fb_dmamap->dm_segs[0].ds_addr); 2917 } 2918 2919 static int 2920 fwohci_selfid_input(struct fwohci_softc *sc) 2921 { 2922 int i; 2923 u_int32_t count, val, gen; 2924 u_int32_t *buf; 2925 2926 buf = (u_int32_t *)sc->sc_buf_selfid.fb_buf; 2927 val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount); 2928 again: 2929 if (val & OHCI_SelfID_Error) { 2930 printf("%s: SelfID Error\n", sc->sc_sc1394.sc1394_dev.dv_xname); 2931 return -1; 2932 } 2933 count = OHCI_BITVAL(val, OHCI_SelfID_Size); 2934 2935 bus_dmamap_sync(sc->sc_dmat, sc->sc_buf_selfid.fb_dmamap, 2936 0, count << 2, BUS_DMASYNC_POSTREAD); 2937 gen = OHCI_BITVAL(buf[0], OHCI_SelfID_Gen); 2938 2939 #ifdef FW_DEBUG 2940 DPRINTFN(1, ("%s: SelfID: 0x%08x", sc->sc_sc1394.sc1394_dev.dv_xname, 2941 val)); 2942 for (i = 0; i < count; i++) 2943 DPRINTFN(2, ("%s%08x", i&7?" ":"\n ", buf[i])); 2944 DPRINTFN(1, ("\n")); 2945 #endif /* FW_DEBUG */ 2946 2947 for (i = 1; i < count; i += 2) { 2948 if (buf[i] != ~buf[i + 1]) 2949 break; 2950 if (buf[i] & 0x00000001) 2951 continue; /* more pkt */ 2952 if (buf[i] & 0x00800000) 2953 continue; /* external id */ 2954 sc->sc_rootid = (buf[i] & 0x3f000000) >> 24; 2955 if ((buf[i] & 0x00400800) == 0x00400800) 2956 sc->sc_irmid = sc->sc_rootid; 2957 } 2958 2959 val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount); 2960 if (OHCI_BITVAL(val, OHCI_SelfID_Gen) != gen) { 2961 if (OHCI_BITVAL(val, OHCI_SelfID_Gen) != 2962 OHCI_BITVAL(buf[0], OHCI_SelfID_Gen)) 2963 goto again; 2964 DPRINTF(("%s: SelfID Gen mismatch (%d, %d)\n", 2965 sc->sc_sc1394.sc1394_dev.dv_xname, gen, 2966 OHCI_BITVAL(val, OHCI_SelfID_Gen))); 2967 return -1; 2968 } 2969 if (i != count) { 2970 printf("%s: SelfID corrupted (%d, 0x%08x, 0x%08x)\n", 2971 sc->sc_sc1394.sc1394_dev.dv_xname, i, buf[i], buf[i + 1]); 2972 #if 1 2973 if (i == 1 && buf[i] == 0 && buf[i + 1] == 0) { 2974 /* 2975 * XXX: CXD3222 sometimes fails to DMA 2976 * selfid packet?? 2977 */ 2978 sc->sc_rootid = (count - 1) / 2 - 1; 2979 sc->sc_irmid = sc->sc_rootid; 2980 } else 2981 #endif 2982 return -1; 2983 } 2984 2985 val = OHCI_CSR_READ(sc, OHCI_REG_NodeId); 2986 if ((val & OHCI_NodeId_IDValid) == 0) { 2987 sc->sc_nodeid = 0xffff; /* invalid */ 2988 printf("%s: nodeid is invalid\n", 2989 sc->sc_sc1394.sc1394_dev.dv_xname); 2990 return -1; 2991 } 2992 sc->sc_nodeid = val & 0xffff; 2993 sc->sc_sc1394.sc1394_node_id = sc->sc_nodeid & OHCI_NodeId_NodeNumber; 2994 2995 DPRINTF(("%s: nodeid=0x%04x(%d), rootid=%d, irmid=%d\n", 2996 sc->sc_sc1394.sc1394_dev.dv_xname, sc->sc_nodeid, 2997 sc->sc_nodeid & OHCI_NodeId_NodeNumber, sc->sc_rootid, 2998 sc->sc_irmid)); 2999 3000 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) > sc->sc_rootid) 3001 return -1; 3002 3003 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == sc->sc_rootid) 3004 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet, 3005 OHCI_LinkControl_CycleMaster); 3006 else 3007 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear, 3008 OHCI_LinkControl_CycleMaster); 3009 return 0; 3010 } 3011 3012 /* 3013 * some CSRs are handled by driver. 3014 */ 3015 static void 3016 fwohci_csr_init(struct fwohci_softc *sc) 3017 { 3018 int i; 3019 static u_int32_t csr[] = { 3020 CSR_STATE_CLEAR, CSR_STATE_SET, CSR_SB_CYCLE_TIME, 3021 CSR_SB_BUS_TIME, CSR_SB_BUSY_TIMEOUT, CSR_SB_BUS_MANAGER_ID, 3022 CSR_SB_CHANNEL_AVAILABLE_HI, CSR_SB_CHANNEL_AVAILABLE_LO, 3023 CSR_SB_BROADCAST_CHANNEL 3024 }; 3025 3026 for (i = 0; i < sizeof(csr) / sizeof(csr[0]); i++) { 3027 fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_QUAD, 3028 CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL); 3029 fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD, 3030 CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL); 3031 } 3032 sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] = 31; /*XXX*/ 3033 } 3034 3035 static int 3036 fwohci_csr_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 3037 { 3038 struct fwohci_pkt res; 3039 u_int32_t reg; 3040 3041 /* 3042 * XXX need to do special functionality other than just r/w... 3043 */ 3044 reg = pkt->fp_hdr[2] - CSR_BASE_LO; 3045 3046 if ((reg & 0x03) != 0) { 3047 /* alignment error */ 3048 return IEEE1394_RCODE_ADDRESS_ERROR; 3049 } 3050 DPRINTFN(1, ("fwohci_csr_input: CSR[0x%04x]: 0x%08x", reg, 3051 *(u_int32_t *)(&sc->sc_csr[reg]))); 3052 if (pkt->fp_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD) { 3053 DPRINTFN(1, (" -> 0x%08x\n", 3054 ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base))); 3055 *(u_int32_t *)&sc->sc_csr[reg] = 3056 ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base); 3057 } else { 3058 DPRINTFN(1, ("\n")); 3059 res.fp_hdr[3] = htonl(*(u_int32_t *)&sc->sc_csr[reg]); 3060 res.fp_iov[0].iov_base = &res.fp_hdr[3]; 3061 res.fp_iov[0].iov_len = 4; 3062 res.fp_uio.uio_resid = 4; 3063 res.fp_uio.uio_iovcnt = 1; 3064 fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res); 3065 return -1; 3066 } 3067 return IEEE1394_RCODE_COMPLETE; 3068 } 3069 3070 /* 3071 * Mapping between nodeid and unique ID (EUI-64). 3072 * 3073 * Track old mappings and simply update their devices with the new id's when 3074 * they match an existing EUI. This allows proper renumeration of the bus. 3075 */ 3076 static void 3077 fwohci_uid_collect(struct fwohci_softc *sc) 3078 { 3079 int i; 3080 struct fwohci_uidtbl *fu; 3081 struct ieee1394_softc *iea; 3082 3083 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) 3084 iea->sc1394_node_id = 0xffff; 3085 3086 if (sc->sc_uidtbl != NULL) 3087 free(sc->sc_uidtbl, M_DEVBUF); 3088 sc->sc_uidtbl = malloc(sizeof(*fu) * (sc->sc_rootid + 1), M_DEVBUF, 3089 M_NOWAIT|M_ZERO); /* XXX M_WAITOK requires locks */ 3090 if (sc->sc_uidtbl == NULL) 3091 return; 3092 3093 for (i = 0, fu = sc->sc_uidtbl; i <= sc->sc_rootid; i++, fu++) { 3094 if (i == (sc->sc_nodeid & OHCI_NodeId_NodeNumber)) { 3095 memcpy(fu->fu_uid, sc->sc_sc1394.sc1394_guid, 8); 3096 fu->fu_valid = 3; 3097 3098 iea = (struct ieee1394_softc *)sc->sc_sc1394.sc1394_if; 3099 if (iea) { 3100 iea->sc1394_node_id = i; 3101 DPRINTF(("%s: Updating nodeid to %d\n", 3102 iea->sc1394_dev.dv_xname, 3103 iea->sc1394_node_id)); 3104 } 3105 } else { 3106 fu->fu_valid = 0; 3107 fwohci_uid_req(sc, i); 3108 } 3109 } 3110 if (sc->sc_rootid == 0) 3111 fwohci_check_nodes(sc); 3112 } 3113 3114 static void 3115 fwohci_uid_req(struct fwohci_softc *sc, int phyid) 3116 { 3117 struct fwohci_pkt pkt; 3118 3119 memset(&pkt, 0, sizeof(pkt)); 3120 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD; 3121 pkt.fp_hlen = 12; 3122 pkt.fp_dlen = 0; 3123 pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) | 3124 (pkt.fp_tcode << 4); 3125 pkt.fp_hdr[1] = ((0xffc0 | phyid) << 16) | CSR_BASE_HI; 3126 pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 12; 3127 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid, 3128 sc->sc_tlabel, fwohci_uid_input, (void *)0); 3129 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 3130 fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt); 3131 3132 pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) | 3133 (pkt.fp_tcode << 4); 3134 pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 16; 3135 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, phyid, 3136 sc->sc_tlabel, fwohci_uid_input, (void *)1); 3137 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 3138 fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt); 3139 } 3140 3141 static int 3142 fwohci_uid_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *res) 3143 { 3144 struct fwohci_uidtbl *fu; 3145 struct ieee1394_softc *iea; 3146 struct ieee1394_attach_args fwa; 3147 int i, n, done, rcode, found; 3148 3149 found = 0; 3150 3151 n = (res->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber; 3152 rcode = (res->fp_hdr[1] & 0x0000f000) >> 12; 3153 if (rcode != IEEE1394_RCODE_COMPLETE || 3154 sc->sc_uidtbl == NULL || 3155 n > sc->sc_rootid) 3156 return 0; 3157 fu = &sc->sc_uidtbl[n]; 3158 if (arg == 0) { 3159 memcpy(fu->fu_uid, res->fp_iov[0].iov_base, 4); 3160 fu->fu_valid |= 0x1; 3161 } else { 3162 memcpy(fu->fu_uid + 4, res->fp_iov[0].iov_base, 4); 3163 fu->fu_valid |= 0x2; 3164 } 3165 #ifdef FW_DEBUG 3166 if (fu->fu_valid == 0x3) 3167 DPRINTFN(1, ("fwohci_uid_input: " 3168 "Node %d, UID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", n, 3169 fu->fu_uid[0], fu->fu_uid[1], fu->fu_uid[2], fu->fu_uid[3], 3170 fu->fu_uid[4], fu->fu_uid[5], fu->fu_uid[6], fu->fu_uid[7])); 3171 #endif 3172 if (fu->fu_valid == 0x3) { 3173 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) 3174 if (memcmp(iea->sc1394_guid, fu->fu_uid, 8) == 0) { 3175 found = 1; 3176 iea->sc1394_node_id = n; 3177 DPRINTF(("%s: Updating nodeid to %d\n", 3178 iea->sc1394_dev.dv_xname, 3179 iea->sc1394_node_id)); 3180 if (iea->sc1394_callback.sc1394_reset) 3181 iea->sc1394_callback.sc1394_reset(iea, 3182 iea->sc1394_callback.sc1394_resetarg); 3183 break; 3184 } 3185 if (!found) { 3186 strcpy(fwa.name, "fwnode"); 3187 memcpy(fwa.uid, fu->fu_uid, 8); 3188 fwa.nodeid = n; 3189 iea = (struct ieee1394_softc *) 3190 config_found_sm(&sc->sc_sc1394.sc1394_dev, &fwa, 3191 fwohci_print, fwohci_submatch); 3192 if (iea != NULL) 3193 LIST_INSERT_HEAD(&sc->sc_nodelist, iea, 3194 sc1394_node); 3195 } 3196 } 3197 done = 1; 3198 3199 for (i = 0; i < sc->sc_rootid + 1; i++) { 3200 fu = &sc->sc_uidtbl[i]; 3201 if (fu->fu_valid != 0x3) { 3202 done = 0; 3203 break; 3204 } 3205 } 3206 if (done) 3207 fwohci_check_nodes(sc); 3208 3209 return 0; 3210 } 3211 3212 static void 3213 fwohci_check_nodes(struct fwohci_softc *sc) 3214 { 3215 struct device *detach = NULL; 3216 struct ieee1394_softc *iea; 3217 3218 LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) { 3219 3220 /* 3221 * Have to defer detachment until the next 3222 * loop iteration since config_detach 3223 * free's the softc and the loop iterator 3224 * needs data from the softc to move 3225 * forward. 3226 */ 3227 3228 if (detach) { 3229 config_detach(detach, 0); 3230 detach = NULL; 3231 } 3232 if (iea->sc1394_node_id == 0xffff) { 3233 detach = (struct device *)iea; 3234 LIST_REMOVE(iea, sc1394_node); 3235 } 3236 } 3237 if (detach) 3238 config_detach(detach, 0); 3239 } 3240 3241 static int 3242 fwohci_uid_lookup(struct fwohci_softc *sc, const u_int8_t *uid) 3243 { 3244 struct fwohci_uidtbl *fu; 3245 int n; 3246 static const u_int8_t bcast[] = 3247 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 3248 3249 fu = sc->sc_uidtbl; 3250 if (fu == NULL) { 3251 if (memcmp(uid, bcast, sizeof(bcast)) == 0) 3252 return IEEE1394_BCAST_PHY_ID; 3253 fwohci_uid_collect(sc); /* try to get */ 3254 return -1; 3255 } 3256 for (n = 0; n <= sc->sc_rootid; n++, fu++) { 3257 if (fu->fu_valid == 0x3 && memcmp(fu->fu_uid, uid, 8) == 0) 3258 return n; 3259 } 3260 if (memcmp(uid, bcast, sizeof(bcast)) == 0) 3261 return IEEE1394_BCAST_PHY_ID; 3262 for (n = 0, fu = sc->sc_uidtbl; n <= sc->sc_rootid; n++, fu++) { 3263 if (fu->fu_valid != 0x3) { 3264 /* 3265 * XXX: need timer before retransmission 3266 */ 3267 fwohci_uid_req(sc, n); 3268 } 3269 } 3270 return -1; 3271 } 3272 3273 /* 3274 * functions to support network interface 3275 */ 3276 static int 3277 fwohci_if_inreg(struct device *self, u_int32_t offhi, u_int32_t offlo, 3278 void (*handler)(struct device *, struct mbuf *)) 3279 { 3280 struct fwohci_softc *sc = (struct fwohci_softc *)self; 3281 3282 fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_BLOCK, offhi, offlo, 3283 handler ? fwohci_if_input : NULL, handler); 3284 fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA, 3285 (sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & IEEE1394_ISOCH_MASK) | 3286 OHCI_ASYNC_STREAM, 3287 1 << IEEE1394_TAG_GASP, 3288 handler ? fwohci_if_input : NULL, handler); 3289 return 0; 3290 } 3291 3292 static int 3293 fwohci_if_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 3294 { 3295 int n, len; 3296 struct mbuf *m; 3297 struct iovec *iov; 3298 void (*handler)(struct device *, struct mbuf *) = arg; 3299 3300 #ifdef FW_DEBUG 3301 int i; 3302 DPRINTFN(1, ("fwohci_if_input: tcode=0x%x, dlen=%d", pkt->fp_tcode, 3303 pkt->fp_dlen)); 3304 for (i = 0; i < pkt->fp_hlen/4; i++) 3305 DPRINTFN(2, ("%s%08x", i?" ":"\n ", pkt->fp_hdr[i])); 3306 DPRINTFN(2, ("$")); 3307 for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){ 3308 iov = &pkt->fp_iov[n]; 3309 for (i = 0; i < iov->iov_len; i++) 3310 DPRINTFN(2, ("%s%02x", (i%32)?((i%4)?"":" "):"\n ", 3311 ((u_int8_t *)iov->iov_base)[i])); 3312 DPRINTFN(2, ("$")); 3313 } 3314 DPRINTFN(1, ("\n")); 3315 #endif /* FW_DEBUG */ 3316 len = pkt->fp_dlen; 3317 MGETHDR(m, M_DONTWAIT, MT_DATA); 3318 if (m == NULL) 3319 return IEEE1394_RCODE_COMPLETE; 3320 m->m_len = 16; 3321 if (len + m->m_len > MHLEN) { 3322 MCLGET(m, M_DONTWAIT); 3323 if ((m->m_flags & M_EXT) == 0) { 3324 m_freem(m); 3325 return IEEE1394_RCODE_COMPLETE; 3326 } 3327 } 3328 n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber; 3329 if (sc->sc_uidtbl == NULL || n > sc->sc_rootid || 3330 sc->sc_uidtbl[n].fu_valid != 0x3) { 3331 printf("%s: packet from unknown node: phy id %d\n", 3332 sc->sc_sc1394.sc1394_dev.dv_xname, n); 3333 m_freem(m); 3334 fwohci_uid_req(sc, n); 3335 return IEEE1394_RCODE_COMPLETE; 3336 } 3337 memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8); 3338 if (pkt->fp_tcode == IEEE1394_TCODE_STREAM_DATA) { 3339 m->m_flags |= M_BCAST; 3340 mtod(m, u_int32_t *)[2] = mtod(m, u_int32_t *)[3] = 0; 3341 } else { 3342 mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]); 3343 mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]); 3344 } 3345 mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */ 3346 mtod(m, u_int8_t *)[9] = 3347 (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) & 3348 ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1); 3349 3350 m->m_pkthdr.rcvif = NULL; /* set in child */ 3351 m->m_pkthdr.len = len + m->m_len; 3352 /* 3353 * We may use receive buffer by external mbuf instead of copy here. 3354 * But asynchronous receive buffer must be operate in buffer fill 3355 * mode, so that each receive buffer will shared by multiple mbufs. 3356 * If upper layer doesn't free mbuf soon, e.g. application program 3357 * is suspended, buffer must be reallocated. 3358 * Isochronous buffer must be operate in packet buffer mode, and 3359 * it is easy to map receive buffer to external mbuf. But it is 3360 * used for broadcast/multicast only, and is expected not so 3361 * performance sensitive for now. 3362 * XXX: The performance may be important for multicast case, 3363 * so we should revisit here later. 3364 * -- onoe 3365 */ 3366 n = 0; 3367 iov = pkt->fp_uio.uio_iov; 3368 while (len > 0) { 3369 memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base, 3370 iov->iov_len); 3371 m->m_len += iov->iov_len; 3372 len -= iov->iov_len; 3373 iov++; 3374 } 3375 (*handler)(sc->sc_sc1394.sc1394_if, m); 3376 return IEEE1394_RCODE_COMPLETE; 3377 } 3378 3379 static int 3380 fwohci_if_input_iso(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 3381 { 3382 int n, len; 3383 int chan, tag; 3384 struct mbuf *m; 3385 struct iovec *iov; 3386 void (*handler)(struct device *, struct mbuf *) = arg; 3387 #ifdef FW_DEBUG 3388 int i; 3389 #endif 3390 3391 chan = (pkt->fp_hdr[0] & 0x00003f00) >> 8; 3392 tag = (pkt->fp_hdr[0] & 0x0000c000) >> 14; 3393 #ifdef FW_DEBUG 3394 DPRINTFN(1, ("fwohci_if_input_iso: " 3395 "tcode=0x%x, chan=%d, tag=%x, dlen=%d", 3396 pkt->fp_tcode, chan, tag, pkt->fp_dlen)); 3397 for (i = 0; i < pkt->fp_hlen/4; i++) 3398 DPRINTFN(2, ("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i])); 3399 DPRINTFN(2, ("$")); 3400 for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){ 3401 iov = &pkt->fp_iov[n]; 3402 for (i = 0; i < iov->iov_len; i++) 3403 DPRINTFN(2, ("%s%02x", 3404 (i%32)?((i%4)?"":" "):"\n\t", 3405 ((u_int8_t *)iov->iov_base)[i])); 3406 DPRINTFN(2, ("$")); 3407 } 3408 DPRINTFN(2, ("\n")); 3409 #endif /* FW_DEBUG */ 3410 len = pkt->fp_dlen; 3411 MGETHDR(m, M_DONTWAIT, MT_DATA); 3412 if (m == NULL) 3413 return IEEE1394_RCODE_COMPLETE; 3414 m->m_len = 16; 3415 if (m->m_len + len > MHLEN) { 3416 MCLGET(m, M_DONTWAIT); 3417 if ((m->m_flags & M_EXT) == 0) { 3418 m_freem(m); 3419 return IEEE1394_RCODE_COMPLETE; 3420 } 3421 } 3422 3423 m->m_flags |= M_BCAST; 3424 3425 if (tag == IEEE1394_TAG_GASP) { 3426 n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber; 3427 if (sc->sc_uidtbl == NULL || n > sc->sc_rootid || 3428 sc->sc_uidtbl[n].fu_valid != 0x3) { 3429 printf("%s: packet from unknown node: phy id %d\n", 3430 sc->sc_sc1394.sc1394_dev.dv_xname, n); 3431 m_freem(m); 3432 return IEEE1394_RCODE_COMPLETE; 3433 } 3434 memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8); 3435 mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]); 3436 mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]); 3437 mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */ 3438 mtod(m, u_int8_t *)[9] = 3439 (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) & 3440 ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1); 3441 } 3442 mtod(m, u_int8_t *)[14] = chan; 3443 mtod(m, u_int8_t *)[15] = tag; 3444 3445 3446 m->m_pkthdr.rcvif = NULL; /* set in child */ 3447 m->m_pkthdr.len = len + m->m_len; 3448 /* 3449 * We may use receive buffer by external mbuf instead of copy here. 3450 * But asynchronous receive buffer must be operate in buffer fill 3451 * mode, so that each receive buffer will shared by multiple mbufs. 3452 * If upper layer doesn't free mbuf soon, e.g. application program 3453 * is suspended, buffer must be reallocated. 3454 * Isochronous buffer must be operate in packet buffer mode, and 3455 * it is easy to map receive buffer to external mbuf. But it is 3456 * used for broadcast/multicast only, and is expected not so 3457 * performance sensitive for now. 3458 * XXX: The performance may be important for multicast case, 3459 * so we should revisit here later. 3460 * -- onoe 3461 */ 3462 n = 0; 3463 iov = pkt->fp_uio.uio_iov; 3464 while (len > 0) { 3465 memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base, 3466 iov->iov_len); 3467 m->m_len += iov->iov_len; 3468 len -= iov->iov_len; 3469 iov++; 3470 } 3471 (*handler)(sc->sc_sc1394.sc1394_if, m); 3472 return IEEE1394_RCODE_COMPLETE; 3473 } 3474 3475 3476 3477 static int 3478 fwohci_if_output(struct device *self, struct mbuf *m0, 3479 void (*callback)(struct device *, struct mbuf *)) 3480 { 3481 struct fwohci_softc *sc = (struct fwohci_softc *)self; 3482 struct fwohci_pkt pkt; 3483 u_int8_t *p; 3484 int n, error, spd, hdrlen, maxrec; 3485 #ifdef FW_DEBUG 3486 struct mbuf *m; 3487 #endif 3488 3489 p = mtod(m0, u_int8_t *); 3490 if (m0->m_flags & (M_BCAST | M_MCAST)) { 3491 spd = IEEE1394_SPD_S100; /*XXX*/ 3492 maxrec = 512; /*XXX*/ 3493 hdrlen = 8; 3494 } else { 3495 n = fwohci_uid_lookup(sc, p); 3496 if (n < 0) { 3497 printf("%s: nodeid unknown:" 3498 " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 3499 sc->sc_sc1394.sc1394_dev.dv_xname, 3500 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); 3501 error = EHOSTUNREACH; 3502 goto end; 3503 } 3504 if (n == IEEE1394_BCAST_PHY_ID) { 3505 printf("%s: broadcast with !M_MCAST\n", 3506 sc->sc_sc1394.sc1394_dev.dv_xname); 3507 #ifdef FW_DEBUG 3508 DPRINTFN(2, ("packet:")); 3509 for (m = m0; m != NULL; m = m->m_next) { 3510 for (n = 0; n < m->m_len; n++) 3511 DPRINTFN(2, ("%s%02x", (n%32)? 3512 ((n%4)?"":" "):"\n ", 3513 mtod(m, u_int8_t *)[n])); 3514 DPRINTFN(2, ("$")); 3515 } 3516 DPRINTFN(2, ("\n")); 3517 #endif 3518 error = EHOSTUNREACH; 3519 goto end; 3520 } 3521 maxrec = 2 << p[8]; 3522 spd = p[9]; 3523 hdrlen = 0; 3524 } 3525 if (spd > sc->sc_sc1394.sc1394_link_speed) { 3526 DPRINTF(("fwohci_if_output: spd (%d) is faster than %d\n", 3527 spd, sc->sc_sc1394.sc1394_link_speed)); 3528 spd = sc->sc_sc1394.sc1394_link_speed; 3529 } 3530 if (maxrec > (512 << spd)) { 3531 DPRINTF(("fwohci_if_output: maxrec (%d) is larger for spd (%d)" 3532 "\n", maxrec, spd)); 3533 maxrec = 512 << spd; 3534 } 3535 while (maxrec > sc->sc_sc1394.sc1394_max_receive) { 3536 DPRINTF(("fwohci_if_output: maxrec (%d) is larger than" 3537 " %d\n", maxrec, sc->sc_sc1394.sc1394_max_receive)); 3538 maxrec >>= 1; 3539 } 3540 if (maxrec < 512) { 3541 DPRINTF(("fwohci_if_output: maxrec (%d) is smaller than " 3542 "minimum\n", maxrec)); 3543 maxrec = 512; 3544 } 3545 3546 m_adj(m0, 16 - hdrlen); 3547 if (m0->m_pkthdr.len > maxrec) { 3548 DPRINTF(("fwohci_if_output: packet too big: hdr %d, pktlen " 3549 "%d, maxrec %d\n", hdrlen, m0->m_pkthdr.len, maxrec)); 3550 error = E2BIG; /*XXX*/ 3551 goto end; 3552 } 3553 3554 memset(&pkt, 0, sizeof(pkt)); 3555 pkt.fp_uio.uio_iov = pkt.fp_iov; 3556 pkt.fp_uio.uio_segflg = UIO_SYSSPACE; 3557 pkt.fp_uio.uio_rw = UIO_WRITE; 3558 if (m0->m_flags & (M_BCAST | M_MCAST)) { 3559 /* construct GASP header */ 3560 p = mtod(m0, u_int8_t *); 3561 p[0] = sc->sc_nodeid >> 8; 3562 p[1] = sc->sc_nodeid & 0xff; 3563 p[2] = 0x00; p[3] = 0x00; p[4] = 0x5e; 3564 p[5] = 0x00; p[6] = 0x00; p[7] = 0x01; 3565 pkt.fp_tcode = IEEE1394_TCODE_STREAM_DATA; 3566 pkt.fp_hlen = 8; 3567 pkt.fp_hdr[0] = (spd << 16) | (IEEE1394_TAG_GASP << 14) | 3568 ((sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & 3569 OHCI_NodeId_NodeNumber) << 8); 3570 pkt.fp_hdr[1] = m0->m_pkthdr.len << 16; 3571 } else { 3572 pkt.fp_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK; 3573 pkt.fp_hlen = 16; 3574 pkt.fp_hdr[0] = 0x00800100 | (sc->sc_tlabel << 10) | 3575 (spd << 16); 3576 pkt.fp_hdr[1] = 3577 (((sc->sc_nodeid & OHCI_NodeId_BusNumber) | n) << 16) | 3578 (p[10] << 8) | p[11]; 3579 pkt.fp_hdr[2] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15]; 3580 pkt.fp_hdr[3] = m0->m_pkthdr.len << 16; 3581 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 3582 } 3583 pkt.fp_hdr[0] |= (pkt.fp_tcode << 4); 3584 pkt.fp_dlen = m0->m_pkthdr.len; 3585 pkt.fp_m = m0; 3586 pkt.fp_callback = callback; 3587 error = fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt); 3588 m0 = pkt.fp_m; 3589 end: 3590 if (m0 != NULL) { 3591 if (callback) 3592 (*callback)(sc->sc_sc1394.sc1394_if, m0); 3593 else 3594 m_freem(m0); 3595 } 3596 return error; 3597 } 3598 3599 /* 3600 * High level routines to provide abstraction to attaching layers to 3601 * send/receive data. 3602 */ 3603 3604 /* 3605 * These break down into 4 routines as follows: 3606 * 3607 * int fwohci_read(struct ieee1394_abuf *) 3608 * 3609 * This routine will attempt to read a region from the requested node. 3610 * A callback must be provided which will be called when either the completed 3611 * read is done or an unrecoverable error occurs. This is mainly a convenience 3612 * routine since it will encapsulate retrying a region as quadlet vs. block 3613 * reads and recombining all the returned data. This could also be done with a 3614 * series of write/inreg's for each packet sent. 3615 * 3616 * int fwohci_write(struct ieee1394_abuf *) 3617 * 3618 * The work horse main entry point for putting packets on the bus. This is the 3619 * generalized interface for fwnode/etc code to put packets out onto the bus. 3620 * It accepts all standard ieee1394 tcodes (XXX: only a few today) and 3621 * optionally will callback via a func pointer to the calling code with the 3622 * resulting ACK code from the packet. If the ACK code is to be ignored (i.e. 3623 * no cb) then the write routine will take care of free'ing the abuf since the 3624 * fwnode/etc code won't have any knowledge of when to do this. This allows for 3625 * simple one-off packets to be sent from the upper-level code without worrying 3626 * about a callback for cleanup. 3627 * 3628 * int fwohci_inreg(struct ieee1394_abuf *, int) 3629 * 3630 * This is very simple. It evals the abuf passed in and registers an internal 3631 * handler as the callback for packets received for that operation. 3632 * The integer argument specifies whether on a block read/write operation to 3633 * allow sub-regions to be read/written (in block form) as well. 3634 * 3635 * XXX: This whole structure needs to be redone as a list of regions and 3636 * operations allowed on those regions. 3637 * 3638 * int fwohci_unreg(struct ieee1394_abuf *, int) 3639 * 3640 * This simply unregisters the respective callback done via inreg for items 3641 * which only need to register an area for a one-time operation (like a status 3642 * buffer a remote node will write to when the current operation is done). The 3643 * int argument specifies the same behavior as inreg, except in reverse (i.e. 3644 * it unregisters). 3645 */ 3646 3647 static int 3648 fwohci_read(struct ieee1394_abuf *ab) 3649 { 3650 struct fwohci_pkt pkt; 3651 struct ieee1394_softc *sc = ab->ab_req; 3652 struct fwohci_softc *psc = 3653 (struct fwohci_softc *)sc->sc1394_dev.dv_parent; 3654 struct fwohci_cb *fcb; 3655 u_int32_t high, lo; 3656 int rv, tcode; 3657 3658 /* Have to have a callback when reading. */ 3659 if (ab->ab_cb == NULL) 3660 return -1; 3661 3662 fcb = malloc(sizeof(struct fwohci_cb), M_DEVBUF, M_WAITOK); 3663 fcb->ab = ab; 3664 fcb->count = 0; 3665 fcb->abuf_valid = 1; 3666 3667 high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32); 3668 lo = (ab->ab_addr & 0x00000000ffffffffULL); 3669 3670 memset(&pkt, 0, sizeof(pkt)); 3671 pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high; 3672 pkt.fp_hdr[2] = lo; 3673 pkt.fp_dlen = 0; 3674 3675 if (ab->ab_length == 4) { 3676 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD; 3677 tcode = IEEE1394_TCODE_READ_RESP_QUAD; 3678 pkt.fp_hlen = 12; 3679 } else { 3680 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_BLOCK; 3681 pkt.fp_hlen = 16; 3682 tcode = IEEE1394_TCODE_READ_RESP_BLOCK; 3683 pkt.fp_hdr[3] = (ab->ab_length << 16); 3684 } 3685 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) | 3686 (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4); 3687 3688 pkt.fp_statusarg = fcb; 3689 pkt.fp_statuscb = fwohci_read_resp; 3690 3691 rv = fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id, 3692 psc->sc_tlabel, fwohci_read_resp, fcb); 3693 if (rv) 3694 return rv; 3695 rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt); 3696 if (rv) 3697 fwohci_handler_set(psc, tcode, ab->ab_req->sc1394_node_id, 3698 psc->sc_tlabel, NULL, NULL); 3699 psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f; 3700 fcb->count = 1; 3701 return rv; 3702 } 3703 3704 static int 3705 fwohci_write(struct ieee1394_abuf *ab) 3706 { 3707 struct fwohci_pkt pkt; 3708 struct ieee1394_softc *sc = ab->ab_req; 3709 struct fwohci_softc *psc = 3710 (struct fwohci_softc *)sc->sc1394_dev.dv_parent; 3711 u_int32_t high, lo; 3712 int rv; 3713 3714 if (ab->ab_length > IEEE1394_MAX_REC(sc->sc1394_max_receive)) { 3715 DPRINTF(("Packet too large: %d\n", ab->ab_length)); 3716 return E2BIG; 3717 } 3718 3719 if (ab->ab_data && ab->ab_uio) 3720 panic("Can't call with uio and data set"); 3721 if ((ab->ab_data == NULL) && (ab->ab_uio == NULL)) 3722 panic("One of either ab_data or ab_uio must be set"); 3723 3724 memset(&pkt, 0, sizeof(pkt)); 3725 3726 pkt.fp_tcode = ab->ab_tcode; 3727 if (ab->ab_data) { 3728 pkt.fp_uio.uio_iov = pkt.fp_iov; 3729 pkt.fp_uio.uio_segflg = UIO_SYSSPACE; 3730 pkt.fp_uio.uio_rw = UIO_WRITE; 3731 } else 3732 memcpy(&pkt.fp_uio, ab->ab_uio, sizeof(struct uio)); 3733 3734 pkt.fp_statusarg = ab; 3735 pkt.fp_statuscb = fwohci_write_ack; 3736 3737 switch (ab->ab_tcode) { 3738 case IEEE1394_TCODE_WRITE_RESP: 3739 pkt.fp_hlen = 12; 3740 case IEEE1394_TCODE_READ_RESP_QUAD: 3741 case IEEE1394_TCODE_READ_RESP_BLOCK: 3742 if (!pkt.fp_hlen) 3743 pkt.fp_hlen = 16; 3744 high = ab->ab_retlen; 3745 ab->ab_retlen = 0; 3746 lo = 0; 3747 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) | 3748 (ab->ab_tlabel << 10) | (pkt.fp_tcode << 4); 3749 break; 3750 default: 3751 pkt.fp_hlen = 16; 3752 high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32); 3753 lo = (ab->ab_addr & 0x00000000ffffffffULL); 3754 pkt.fp_hdr[0] = 0x00000100 | (sc->sc1394_link_speed << 16) | 3755 (psc->sc_tlabel << 10) | (pkt.fp_tcode << 4); 3756 psc->sc_tlabel = (psc->sc_tlabel + 1) & 0x3f; 3757 break; 3758 } 3759 3760 pkt.fp_hdr[1] = ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high; 3761 pkt.fp_hdr[2] = lo; 3762 if (pkt.fp_hlen == 16) { 3763 if (ab->ab_length == 4) { 3764 pkt.fp_hdr[3] = ab->ab_data[0]; 3765 pkt.fp_dlen = 0; 3766 } else { 3767 pkt.fp_hdr[3] = (ab->ab_length << 16); 3768 pkt.fp_dlen = ab->ab_length; 3769 if (ab->ab_data) { 3770 pkt.fp_uio.uio_iovcnt = 1; 3771 pkt.fp_uio.uio_resid = ab->ab_length; 3772 pkt.fp_iov[0].iov_base = ab->ab_data; 3773 pkt.fp_iov[0].iov_len = ab->ab_length; 3774 } 3775 } 3776 } 3777 switch (ab->ab_tcode) { 3778 case IEEE1394_TCODE_WRITE_RESP: 3779 case IEEE1394_TCODE_READ_RESP_QUAD: 3780 case IEEE1394_TCODE_READ_RESP_BLOCK: 3781 rv = fwohci_at_output(psc, psc->sc_ctx_atrs, &pkt); 3782 break; 3783 default: 3784 rv = fwohci_at_output(psc, psc->sc_ctx_atrq, &pkt); 3785 break; 3786 } 3787 return rv; 3788 } 3789 3790 static int 3791 fwohci_read_resp(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 3792 { 3793 struct fwohci_cb *fcb = arg; 3794 struct ieee1394_abuf *ab = fcb->ab; 3795 struct fwohci_pkt newpkt; 3796 u_int32_t *cur, high, lo; 3797 int i, tcode, rcode, status, rv; 3798 3799 /* 3800 * Both the ACK handling and normal response callbacks are handled here. 3801 * The main reason for this is the various error conditions that can 3802 * occur trying to block read some areas and the ways that gets reported 3803 * back to calling station. This is a variety of ACK codes, responses, 3804 * etc which makes it much more difficult to process if both aren't 3805 * handled here. 3806 */ 3807 3808 /* Check for status packet. */ 3809 3810 if (pkt->fp_tcode == -1) { 3811 status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK; 3812 rcode = -1; 3813 tcode = (pkt->fp_hdr[0] >> 4) & 0xf; 3814 if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) && 3815 (status != OHCI_CTXCTL_EVENT_ACK_PENDING)) 3816 DPRINTFN(2, ("Got status packet: 0x%02x\n", 3817 (unsigned int)status)); 3818 fcb->count--; 3819 3820 /* 3821 * Got all the ack's back and the buffer is invalid (i.e. the 3822 * callback has been called. Clean up. 3823 */ 3824 3825 if (fcb->abuf_valid == 0) { 3826 if (fcb->count == 0) 3827 free(fcb, M_DEVBUF); 3828 return IEEE1394_RCODE_COMPLETE; 3829 } 3830 } else { 3831 status = -1; 3832 tcode = pkt->fp_tcode; 3833 rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12; 3834 } 3835 3836 /* 3837 * Some area's (like the config rom want to be read as quadlets only. 3838 * 3839 * The current ideas to try are: 3840 * 3841 * Got an ACK_TYPE_ERROR on a block read. 3842 * 3843 * Got either RCODE_TYPE or RCODE_ADDRESS errors in a block read 3844 * response. 3845 * 3846 * In all cases construct a new packet for a quadlet read and let 3847 * mutli_resp handle the iteration over the space. 3848 */ 3849 3850 if (((status == OHCI_CTXCTL_EVENT_ACK_TYPE_ERROR) && 3851 (tcode == IEEE1394_TCODE_READ_REQ_BLOCK)) || 3852 (((rcode == IEEE1394_RCODE_TYPE_ERROR) || 3853 (rcode == IEEE1394_RCODE_ADDRESS_ERROR)) && 3854 (tcode == IEEE1394_TCODE_READ_RESP_BLOCK))) { 3855 3856 /* Read the area in quadlet chunks (internally track this). */ 3857 3858 memset(&newpkt, 0, sizeof(newpkt)); 3859 3860 high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32); 3861 lo = (ab->ab_addr & 0x00000000ffffffffULL); 3862 3863 newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD; 3864 newpkt.fp_hlen = 12; 3865 newpkt.fp_dlen = 0; 3866 newpkt.fp_hdr[1] = 3867 ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high; 3868 newpkt.fp_hdr[2] = lo; 3869 newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) | 3870 (newpkt.fp_tcode << 4); 3871 3872 rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, 3873 ab->ab_req->sc1394_node_id, sc->sc_tlabel, 3874 fwohci_read_multi_resp, fcb); 3875 if (rv) { 3876 (*ab->ab_cb)(ab, -1); 3877 goto cleanup; 3878 } 3879 newpkt.fp_statusarg = fcb; 3880 newpkt.fp_statuscb = fwohci_read_resp; 3881 rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt); 3882 if (rv) { 3883 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, 3884 ab->ab_req->sc1394_node_id, sc->sc_tlabel, NULL, 3885 NULL); 3886 (*ab->ab_cb)(ab, -1); 3887 goto cleanup; 3888 } 3889 fcb->count++; 3890 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 3891 return IEEE1394_RCODE_COMPLETE; 3892 } else if ((rcode != -1) || ((status != -1) && 3893 (status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) && 3894 (status != OHCI_CTXCTL_EVENT_ACK_PENDING))) { 3895 3896 /* 3897 * Recombine all the iov data into 1 chunk for higher 3898 * level code. 3899 */ 3900 3901 if (rcode != -1) { 3902 cur = ab->ab_data; 3903 for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) { 3904 /* 3905 * Make sure and don't exceed the buffer 3906 * allocated for return. 3907 */ 3908 if ((ab->ab_retlen + pkt->fp_iov[i].iov_len) > 3909 ab->ab_length) { 3910 memcpy(cur, pkt->fp_iov[i].iov_base, 3911 (ab->ab_length - ab->ab_retlen)); 3912 ab->ab_retlen = ab->ab_length; 3913 break; 3914 } 3915 memcpy(cur, pkt->fp_iov[i].iov_base, 3916 pkt->fp_iov[i].iov_len); 3917 cur += pkt->fp_iov[i].iov_len; 3918 ab->ab_retlen += pkt->fp_iov[i].iov_len; 3919 } 3920 } 3921 if (status != -1) 3922 /* XXX: Need a complete tlabel interface. */ 3923 for (i = 0; i < 64; i++) 3924 fwohci_handler_set(sc, 3925 IEEE1394_TCODE_READ_RESP_QUAD, 3926 ab->ab_req->sc1394_node_id, i, NULL, NULL); 3927 (*ab->ab_cb)(ab, rcode); 3928 goto cleanup; 3929 } else 3930 /* Good ack packet. */ 3931 return IEEE1394_RCODE_COMPLETE; 3932 3933 /* Can't get here unless ab->ab_cb has been called. */ 3934 3935 cleanup: 3936 fcb->abuf_valid = 0; 3937 if (fcb->count == 0) 3938 free(fcb, M_DEVBUF); 3939 return IEEE1394_RCODE_COMPLETE; 3940 } 3941 3942 static int 3943 fwohci_read_multi_resp(struct fwohci_softc *sc, void *arg, 3944 struct fwohci_pkt *pkt) 3945 { 3946 struct fwohci_cb *fcb = arg; 3947 struct ieee1394_abuf *ab = fcb->ab; 3948 struct fwohci_pkt newpkt; 3949 u_int32_t high, lo; 3950 int rcode, rv; 3951 3952 /* 3953 * Bad return codes from the wire, just return what's already in the 3954 * buf. 3955 */ 3956 3957 /* Make sure a response packet didn't arrive after a bad ACK. */ 3958 if (fcb->abuf_valid == 0) 3959 return IEEE1394_RCODE_COMPLETE; 3960 3961 rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12; 3962 3963 if (rcode) { 3964 (*ab->ab_cb)(ab, rcode); 3965 goto cleanup; 3966 } 3967 3968 if ((ab->ab_retlen + pkt->fp_iov[0].iov_len) > ab->ab_length) { 3969 memcpy(((char *)ab->ab_data + ab->ab_retlen), 3970 pkt->fp_iov[0].iov_base, (ab->ab_length - ab->ab_retlen)); 3971 ab->ab_retlen = ab->ab_length; 3972 } else { 3973 memcpy(((char *)ab->ab_data + ab->ab_retlen), 3974 pkt->fp_iov[0].iov_base, 4); 3975 ab->ab_retlen += 4; 3976 } 3977 /* Still more, loop and read 4 more bytes. */ 3978 if (ab->ab_retlen < ab->ab_length) { 3979 memset(&newpkt, 0, sizeof(newpkt)); 3980 3981 high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32); 3982 lo = (ab->ab_addr & 0x00000000ffffffffULL) + ab->ab_retlen; 3983 3984 newpkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD; 3985 newpkt.fp_hlen = 12; 3986 newpkt.fp_dlen = 0; 3987 newpkt.fp_hdr[1] = 3988 ((0xffc0 | ab->ab_req->sc1394_node_id) << 16) | high; 3989 newpkt.fp_hdr[2] = lo; 3990 newpkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) | 3991 (newpkt.fp_tcode << 4); 3992 3993 newpkt.fp_statusarg = fcb; 3994 newpkt.fp_statuscb = fwohci_read_resp; 3995 3996 /* 3997 * Bad return code. Just give up and return what's 3998 * come in now. 3999 */ 4000 rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, 4001 ab->ab_req->sc1394_node_id, sc->sc_tlabel, 4002 fwohci_read_multi_resp, fcb); 4003 if (rv) 4004 (*ab->ab_cb)(ab, -1); 4005 else { 4006 rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt); 4007 if (rv) { 4008 fwohci_handler_set(sc, 4009 IEEE1394_TCODE_READ_RESP_QUAD, 4010 ab->ab_req->sc1394_node_id, sc->sc_tlabel, 4011 NULL, NULL); 4012 (*ab->ab_cb)(ab, -1); 4013 } else { 4014 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; 4015 fcb->count++; 4016 return IEEE1394_RCODE_COMPLETE; 4017 } 4018 } 4019 } else 4020 (*ab->ab_cb)(ab, IEEE1394_RCODE_COMPLETE); 4021 4022 cleanup: 4023 /* Can't get here unless ab_cb has been called. */ 4024 fcb->abuf_valid = 0; 4025 if (fcb->count == 0) 4026 free(fcb, M_DEVBUF); 4027 return IEEE1394_RCODE_COMPLETE; 4028 } 4029 4030 static int 4031 fwohci_write_ack(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 4032 { 4033 struct ieee1394_abuf *ab = arg; 4034 u_int16_t status; 4035 4036 4037 status = pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK; 4038 if ((status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) && 4039 (status != OHCI_CTXCTL_EVENT_ACK_PENDING)) 4040 DPRINTF(("Got status packet: 0x%02x\n", 4041 (unsigned int)status)); 4042 4043 /* No callback means this level should free the buffers. */ 4044 if (ab->ab_cb) 4045 (*ab->ab_cb)(ab, status); 4046 else { 4047 if (ab->ab_data) 4048 free(ab->ab_data, M_1394DATA); 4049 free(ab, M_1394DATA); 4050 } 4051 return IEEE1394_RCODE_COMPLETE; 4052 } 4053 4054 static int 4055 fwohci_inreg(struct ieee1394_abuf *ab, int allow) 4056 { 4057 struct ieee1394_softc *sc = ab->ab_req; 4058 struct fwohci_softc *psc = 4059 (struct fwohci_softc *)sc->sc1394_dev.dv_parent; 4060 u_int32_t high, lo; 4061 int i, j, rv; 4062 4063 high = ((ab->ab_addr & 0x0000ffff00000000ULL) >> 32); 4064 lo = (ab->ab_addr & 0x00000000ffffffffULL); 4065 4066 rv = 0; 4067 switch (ab->ab_tcode) { 4068 case IEEE1394_TCODE_READ_REQ_QUAD: 4069 case IEEE1394_TCODE_WRITE_REQ_QUAD: 4070 if (ab->ab_cb) 4071 rv = fwohci_handler_set(psc, ab->ab_tcode, high, lo, 4072 fwohci_parse_input, ab); 4073 else 4074 fwohci_handler_set(psc, ab->ab_tcode, high, lo, NULL, 4075 NULL); 4076 break; 4077 case IEEE1394_TCODE_READ_REQ_BLOCK: 4078 case IEEE1394_TCODE_WRITE_REQ_BLOCK: 4079 if (allow) { 4080 for (i = 0; i < (ab->ab_length / 4); i++) { 4081 if (ab->ab_cb) { 4082 rv = fwohci_handler_set(psc, 4083 ab->ab_tcode, high, lo + (i * 4), 4084 fwohci_parse_input, ab); 4085 if (rv) 4086 break; 4087 } else 4088 fwohci_handler_set(psc, ab->ab_tcode, 4089 high, lo + (i * 4), NULL, NULL); 4090 } 4091 if (i != (ab->ab_length / 4)) { 4092 j = i + 1; 4093 for (i = 0; i < j; i++) 4094 fwohci_handler_set(psc, ab->ab_tcode, 4095 high, lo + (i * 4), NULL, NULL); 4096 } 4097 4098 /* 4099 * XXX: Need something to indicate writing a smaller 4100 * amount is ok. 4101 */ 4102 if (ab->ab_cb) 4103 ab->ab_subok = 1; 4104 } else { 4105 if (ab->ab_cb) 4106 rv = fwohci_handler_set(psc, ab->ab_tcode, high, 4107 lo, fwohci_parse_input, ab); 4108 else 4109 fwohci_handler_set(psc, ab->ab_tcode, high, lo, 4110 NULL, NULL); 4111 } 4112 break; 4113 default: 4114 DPRINTF(("Invalid registration tcode: %d\n", ab->ab_tcode)); 4115 return -1; 4116 break; 4117 } 4118 return rv; 4119 } 4120 4121 static int 4122 fwohci_unreg(struct ieee1394_abuf *ab, int allow) 4123 { 4124 void *save; 4125 int rv; 4126 4127 save = ab->ab_cb; 4128 ab->ab_cb = NULL; 4129 rv = fwohci_inreg(ab, allow); 4130 ab->ab_cb = save; 4131 return rv; 4132 } 4133 4134 static int 4135 fwohci_parse_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt) 4136 { 4137 struct ieee1394_abuf *ab = (struct ieee1394_abuf *)arg; 4138 u_int64_t addr; 4139 u_int8_t *cur; 4140 int i, count, ret; 4141 4142 ab->ab_tcode = (pkt->fp_hdr[0] >> 4) & 0xf; 4143 ab->ab_tlabel = (pkt->fp_hdr[0] >> 10) & 0x3f; 4144 addr = (((u_int64_t)(pkt->fp_hdr[1] & 0xffff) << 32) | pkt->fp_hdr[2]); 4145 4146 /* Make sure it's always 0 in case this gets reused multiple times. */ 4147 ab->ab_retlen = 0; 4148 4149 switch (ab->ab_tcode) { 4150 case IEEE1394_TCODE_READ_REQ_QUAD: 4151 ab->ab_retlen = 4; 4152 /* Response's (if required) will come from callback code */ 4153 ret = -1; 4154 break; 4155 case IEEE1394_TCODE_READ_REQ_BLOCK: 4156 ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff; 4157 if (ab->ab_subok) { 4158 if ((addr + ab->ab_retlen) > 4159 (ab->ab_addr + ab->ab_length)) 4160 return IEEE1394_RCODE_ADDRESS_ERROR; 4161 } else 4162 if (ab->ab_retlen != ab->ab_length) 4163 return IEEE1394_RCODE_ADDRESS_ERROR; 4164 /* Response's (if required) will come from callback code */ 4165 ret = -1; 4166 break; 4167 case IEEE1394_TCODE_WRITE_REQ_QUAD: 4168 ab->ab_retlen = 4; 4169 /* Fall through. */ 4170 4171 case IEEE1394_TCODE_WRITE_REQ_BLOCK: 4172 if (!ab->ab_retlen) 4173 ab->ab_retlen = (pkt->fp_hdr[3] >> 16) & 0xffff; 4174 if (ab->ab_subok) { 4175 if ((addr + ab->ab_retlen) > 4176 (ab->ab_addr + ab->ab_length)) 4177 return IEEE1394_RCODE_ADDRESS_ERROR; 4178 } else 4179 if (ab->ab_retlen != ab->ab_length) 4180 return IEEE1394_RCODE_ADDRESS_ERROR; 4181 4182 ab->ab_data = malloc(ab->ab_retlen, M_1394DATA, M_WAITOK); 4183 if (ab->ab_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD) 4184 ab->ab_data[0] = pkt->fp_hdr[3]; 4185 else { 4186 count = 0; 4187 cur = (u_int8_t *)ab->ab_data; 4188 for (i = 0; i < pkt->fp_uio.uio_iovcnt; i++) { 4189 memcpy(cur, pkt->fp_iov[i].iov_base, 4190 pkt->fp_iov[i].iov_len); 4191 cur += pkt->fp_iov[i].iov_len; 4192 count += pkt->fp_iov[i].iov_len; 4193 } 4194 if (ab->ab_retlen != count) 4195 panic("Packet claims %d length " 4196 "but only %d bytes returned\n", 4197 ab->ab_retlen, count); 4198 } 4199 ret = IEEE1394_RCODE_COMPLETE; 4200 break; 4201 default: 4202 panic("Got a callback for a tcode that wasn't requested: %d", 4203 ab->ab_tcode); 4204 break; 4205 } 4206 ab->ab_addr = addr; 4207 ab->ab_cb(ab, IEEE1394_RCODE_COMPLETE); 4208 return ret; 4209 } 4210 4211 static int 4212 fwohci_submatch(struct device *parent, struct cfdata *cf, void *aux) 4213 { 4214 struct ieee1394_attach_args *fwa = aux; 4215 4216 /* Both halves must be filled in for a match. */ 4217 if ((cf->fwbuscf_idhi == FWBUS_UNK_IDHI && 4218 cf->fwbuscf_idlo == FWBUS_UNK_IDLO) || 4219 (cf->fwbuscf_idhi == ntohl(*((u_int32_t *)&fwa->uid[0])) && 4220 cf->fwbuscf_idlo == ntohl(*((u_int32_t *)&fwa->uid[4])))) 4221 return (config_match(parent, cf, aux)); 4222 return 0; 4223 } 4224 4225 int 4226 fwohci_detach(struct fwohci_softc *sc, int flags) 4227 { 4228 int rv = 0; 4229 4230 if (sc->sc_sc1394.sc1394_if != NULL) 4231 rv = config_detach(sc->sc_sc1394.sc1394_if, flags); 4232 if (rv != 0) 4233 return (rv); 4234 4235 callout_stop(&sc->sc_selfid_callout); 4236 4237 if (sc->sc_powerhook != NULL) 4238 powerhook_disestablish(sc->sc_powerhook); 4239 if (sc->sc_shutdownhook != NULL) 4240 shutdownhook_disestablish(sc->sc_shutdownhook); 4241 4242 return (rv); 4243 } 4244 4245 int 4246 fwohci_activate(struct device *self, enum devact act) 4247 { 4248 struct fwohci_softc *sc = (struct fwohci_softc *)self; 4249 int s, rv = 0; 4250 4251 s = splhigh(); 4252 switch (act) { 4253 case DVACT_ACTIVATE: 4254 rv = EOPNOTSUPP; 4255 break; 4256 4257 case DVACT_DEACTIVATE: 4258 if (sc->sc_sc1394.sc1394_if != NULL) 4259 rv = config_deactivate(sc->sc_sc1394.sc1394_if); 4260 break; 4261 } 4262 splx(s); 4263 4264 return (rv); 4265 } 4266 4267 #ifdef FW_DEBUG 4268 static void 4269 fwohci_show_intr(struct fwohci_softc *sc, u_int32_t intmask) 4270 { 4271 4272 printf("%s: intmask=0x%08x:", sc->sc_sc1394.sc1394_dev.dv_xname, 4273 intmask); 4274 if (intmask & OHCI_Int_CycleTooLong) 4275 printf(" CycleTooLong"); 4276 if (intmask & OHCI_Int_UnrecoverableError) 4277 printf(" UnrecoverableError"); 4278 if (intmask & OHCI_Int_CycleInconsistent) 4279 printf(" CycleInconsistent"); 4280 if (intmask & OHCI_Int_BusReset) 4281 printf(" BusReset"); 4282 if (intmask & OHCI_Int_SelfIDComplete) 4283 printf(" SelfIDComplete"); 4284 if (intmask & OHCI_Int_LockRespErr) 4285 printf(" LockRespErr"); 4286 if (intmask & OHCI_Int_PostedWriteErr) 4287 printf(" PostedWriteErr"); 4288 if (intmask & OHCI_Int_ReqTxComplete) 4289 printf(" ReqTxComplete(0x%04x)", 4290 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST, 4291 OHCI_SUBREG_ContextControlClear)); 4292 if (intmask & OHCI_Int_RespTxComplete) 4293 printf(" RespTxComplete(0x%04x)", 4294 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE, 4295 OHCI_SUBREG_ContextControlClear)); 4296 if (intmask & OHCI_Int_ARRS) 4297 printf(" ARRS(0x%04x)", 4298 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE, 4299 OHCI_SUBREG_ContextControlClear)); 4300 if (intmask & OHCI_Int_ARRQ) 4301 printf(" ARRQ(0x%04x)", 4302 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST, 4303 OHCI_SUBREG_ContextControlClear)); 4304 if (intmask & OHCI_Int_IsochRx) 4305 printf(" IsochRx(0x%08x)", 4306 OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear)); 4307 if (intmask & OHCI_Int_IsochTx) 4308 printf(" IsochTx(0x%08x)", 4309 OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear)); 4310 if (intmask & OHCI_Int_RQPkt) 4311 printf(" RQPkt(0x%04x)", 4312 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_REQUEST, 4313 OHCI_SUBREG_ContextControlClear)); 4314 if (intmask & OHCI_Int_RSPkt) 4315 printf(" RSPkt(0x%04x)", 4316 OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_RX_RESPONSE, 4317 OHCI_SUBREG_ContextControlClear)); 4318 printf("\n"); 4319 } 4320 4321 static void 4322 fwohci_show_phypkt(struct fwohci_softc *sc, u_int32_t val) 4323 { 4324 u_int8_t key, phyid; 4325 4326 key = (val & 0xc0000000) >> 30; 4327 phyid = (val & 0x3f000000) >> 24; 4328 printf("%s: PHY packet from %d: ", 4329 sc->sc_sc1394.sc1394_dev.dv_xname, phyid); 4330 switch (key) { 4331 case 0: 4332 printf("PHY Config:"); 4333 if (val & 0x00800000) 4334 printf(" ForceRoot"); 4335 if (val & 0x00400000) 4336 printf(" Gap=%x", (val & 0x003f0000) >> 16); 4337 printf("\n"); 4338 break; 4339 case 1: 4340 printf("Link-on\n"); 4341 break; 4342 case 2: 4343 printf("SelfID:"); 4344 if (val & 0x00800000) { 4345 printf(" #%d", (val & 0x00700000) >> 20); 4346 } else { 4347 if (val & 0x00400000) 4348 printf(" LinkActive"); 4349 printf(" Gap=%x", (val & 0x003f0000) >> 16); 4350 printf(" Spd=S%d", 100 << ((val & 0x0000c000) >> 14)); 4351 if (val & 0x00000800) 4352 printf(" Cont"); 4353 if (val & 0x00000002) 4354 printf(" InitiateBusReset"); 4355 } 4356 if (val & 0x00000001) 4357 printf(" +"); 4358 printf("\n"); 4359 break; 4360 default: 4361 printf("unknown: 0x%08x\n", val); 4362 break; 4363 } 4364 } 4365 #endif /* FW_DEBUG */ 4366 4367 #if 0 4368 void fwohci_dumpreg(struct ieee1394_softc *, struct fwiso_regdump *); 4369 4370 void 4371 fwohci_dumpreg(struct ieee1394_softc *isc, struct fwiso_regdump *fr) 4372 { 4373 struct fwohci_softc *sc = (struct fwohci_softc *)isc; 4374 #if 0 4375 u_int32_t val; 4376 4377 printf("%s: dump reg\n", isc->sc1394_dev.dv_xname); 4378 printf("\tNodeID reg 0x%08x\n", 4379 OHCI_CSR_READ(sc, OHCI_REG_NodeId)); 4380 val = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer); 4381 printf("\tIsoCounter 0x%08x, %d %d %d", val, 4382 (val >> 25) & 0xfe, (val >> 12) & 0x1fff, val & 0xfff); 4383 val = OHCI_CSR_READ(sc, OHCI_REG_IntMaskSet); 4384 printf(" IntMask 0x%08x, %s\n", val, 4385 val & OHCI_Int_IsochTx ? "isoTx" : ""); 4386 4387 val = OHCI_SYNC_TX_DMA_READ(sc, 0, OHCI_SUBREG_ContextControlSet); 4388 printf("\tIT_CommandPtr 0x%08x ContextCtrl 0x%08x%s%s%s%s\n", 4389 OHCI_SYNC_TX_DMA_READ(sc, 0, OHCI_SUBREG_CommandPtr), 4390 val, 4391 val & OHCI_CTXCTL_RUN ? " run" : "", 4392 val & OHCI_CTXCTL_WAKE ? " wake" : "", 4393 val & OHCI_CTXCTL_DEAD ? " dead" : "", 4394 val & OHCI_CTXCTL_ACTIVE ? " active" : ""); 4395 #endif 4396 4397 fr->fr_nodeid = OHCI_CSR_READ(sc, OHCI_REG_NodeId); 4398 fr->fr_isocounter = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer); 4399 fr->fr_intmask = OHCI_CSR_READ(sc, OHCI_REG_IntMaskSet); 4400 fr->fr_it0_commandptr = OHCI_SYNC_TX_DMA_READ(sc, 0, OHCI_SUBREG_CommandPtr); 4401 fr->fr_it0_contextctrl = OHCI_SYNC_TX_DMA_READ(sc, 0, OHCI_SUBREG_ContextControlSet); 4402 4403 4404 } 4405 #endif 4406 4407 4408 u_int16_t 4409 fwohci_cycletimer(struct fwohci_softc *sc) 4410 { 4411 u_int32_t reg; 4412 4413 reg = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer); 4414 4415 return (reg >> 12)&0xffff; 4416 } 4417 4418 4419 u_int16_t 4420 fwohci_it_cycletimer(ieee1394_it_tag_t it) 4421 { 4422 struct fwohci_it_ctx *itc = (struct fwohci_it_ctx *)it; 4423 4424 return fwohci_cycletimer(itc->itc_sc); 4425 } 4426 4427 4428 4429 4430 4431 /* 4432 * return value: if positive value, number of DMA buffer segments. If 4433 * negative value, error happens. Never zero. 4434 */ 4435 static int 4436 fwohci_misc_dmabuf_alloc(bus_dma_tag_t dmat, int dsize, int segno, 4437 bus_dma_segment_t *segp, bus_dmamap_t *dmapp, void **mapp, 4438 const char *xname) 4439 { 4440 int nsegs; 4441 int error; 4442 4443 printf("fwohci_misc_desc_alloc: dsize %d segno %d\n", dsize, segno); 4444 4445 if ((error = bus_dmamem_alloc(dmat, dsize, PAGE_SIZE, 0, 4446 segp, segno, &nsegs, 0)) != 0) { 4447 printf("%s: unable to allocate descriptor buffer, error = %d\n", 4448 xname, error); 4449 goto fail_0; 4450 } 4451 4452 DPRINTF(("fwohci_misc_desc_alloc: %d segment[s]\n", nsegs)); 4453 4454 if ((error = bus_dmamem_map(dmat, segp, nsegs, dsize, (caddr_t *)mapp, 4455 BUS_DMA_COHERENT | BUS_DMA_WAITOK)) != 0) { 4456 printf("%s: unable to map descriptor buffer, error = %d\n", 4457 xname, error); 4458 goto fail_1; 4459 } 4460 4461 DPRINTF(("fwohci_misc_desc_alloc: %s map ok\n", xname)); 4462 4463 #ifdef FWOHCI_DEBUG 4464 { 4465 int loop; 4466 4467 for (loop = 0; loop < nsegs; ++loop) { 4468 printf("\t%.2d: 0x%lx - 0x%lx\n", loop, 4469 (long)segp[loop].ds_addr, 4470 (long)segp[loop].ds_addr + segp[loop].ds_len - 1); 4471 } 4472 } 4473 #endif /* FWOHCI_DEBUG */ 4474 4475 if ((error = bus_dmamap_create(dmat, dsize, nsegs, dsize, 4476 0, BUS_DMA_WAITOK, dmapp)) != 0) { 4477 printf("%s: unable to create descriptor buffer DMA map, " 4478 "error = %d\n", xname, error); 4479 goto fail_2; 4480 } 4481 4482 DPRINTF(("fwohci_misc_dmabuf_alloc: bus_dmamem_create success\n")); 4483 4484 if ((error = bus_dmamap_load(dmat, *dmapp, *mapp, dsize, NULL, 4485 BUS_DMA_WAITOK)) != 0) { 4486 printf("%s: unable to load descriptor buffer DMA map, " 4487 "error = %d\n", xname, error); 4488 goto fail_3; 4489 } 4490 4491 DPRINTF(("fwohci_it_desc_alloc: bus_dmamem_load success\n")); 4492 4493 return nsegs; 4494 4495 fail_3: 4496 bus_dmamap_destroy(dmat, *dmapp); 4497 fail_2: 4498 bus_dmamem_unmap(dmat, *mapp, dsize); 4499 fail_1: 4500 bus_dmamem_free(dmat, segp, nsegs); 4501 fail_0: 4502 return error; 4503 } 4504 4505 4506 static void 4507 fwohci_misc_dmabuf_free(bus_dma_tag_t dmat, int dsize, int nsegs, 4508 bus_dma_segment_t *segp, bus_dmamap_t *dmapp, caddr_t map) 4509 { 4510 bus_dmamap_destroy(dmat, *dmapp); 4511 bus_dmamem_unmap(dmat, map, dsize); 4512 bus_dmamem_free(dmat, segp, nsegs); 4513 } 4514 4515 4516 4517 4518 /* 4519 * Isochronous receive service 4520 */ 4521 4522 /* 4523 * static struct fwohci_ir_ctx * 4524 * fwohci_ir_ctx_construct(struct fwohci_softc *sc, int no, int ch, int tagbm, 4525 * int bufnum, int maxsize, int flags) 4526 */ 4527 static struct fwohci_ir_ctx * 4528 fwohci_ir_ctx_construct(struct fwohci_softc *sc, int no, int ch, int tagbm, 4529 int bufnum, int maxsize, int flags) 4530 { 4531 struct fwohci_ir_ctx *irc; 4532 int i; 4533 4534 printf("fwohci_ir_construct(%s, %d, %d, %x, %d, %d\n", 4535 sc->sc_sc1394.sc1394_dev.dv_xname, no, ch, tagbm, bufnum, maxsize); 4536 4537 if ((irc = malloc(sizeof(*irc), M_DEVBUF, M_WAITOK|M_ZERO)) == NULL) { 4538 return NULL; 4539 } 4540 4541 irc->irc_sc = sc; 4542 4543 irc->irc_num = no; 4544 irc->irc_status = 0; 4545 4546 irc->irc_channel = ch; 4547 irc->irc_tagbm = tagbm; 4548 4549 irc->irc_desc_num = bufnum; 4550 4551 irc->irc_flags = flags; 4552 4553 /* add header */ 4554 maxsize += 8; 4555 /* rounding up */ 4556 for (i = 32; i < maxsize; i <<= 1); 4557 printf("fwohci_ir_ctx_construct: maxsize %d => %d\n", 4558 maxsize, i); 4559 4560 maxsize = i; 4561 4562 irc->irc_maxsize = maxsize; 4563 irc->irc_buf_totalsize = bufnum * maxsize; 4564 4565 if (fwohci_ir_buf_setup(irc)) { 4566 /* cannot alloc descriptor */ 4567 return NULL; 4568 } 4569 4570 irc->irc_readtop = irc->irc_desc_map; 4571 irc->irc_writeend = irc->irc_desc_map + irc->irc_desc_num - 1; 4572 irc->irc_savedbranch = irc->irc_writeend->fd_branch; 4573 irc->irc_writeend->fd_branch = 0; 4574 /* sync */ 4575 4576 if (fwohci_ir_stop(irc) || fwohci_ir_init(irc)) { 4577 return NULL; 4578 } 4579 4580 irc->irc_status |= IRC_STATUS_READY; 4581 4582 return irc; 4583 } 4584 4585 4586 4587 /* 4588 * static void fwohci_ir_ctx_destruct(struct fwohci_ir_ctx *irc) 4589 * 4590 * This function release all DMA buffers and itself. 4591 */ 4592 static void 4593 fwohci_ir_ctx_destruct(struct fwohci_ir_ctx *irc) 4594 { 4595 fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat, irc->irc_buf_totalsize, 4596 irc->irc_buf_nsegs, irc->irc_buf_segs, 4597 &irc->irc_buf_dmamap, (caddr_t)irc->irc_buf); 4598 fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat, 4599 irc->irc_desc_size, 4600 irc->irc_desc_nsegs, &irc->irc_desc_seg, 4601 &irc->irc_desc_dmamap, (caddr_t)irc->irc_desc_map); 4602 4603 free(irc, M_DEVBUF); 4604 } 4605 4606 4607 4608 4609 /* 4610 * static int fwohci_ir_buf_setup(struct fwohci_ir_ctx *irc) 4611 * 4612 * Allocates descriptors for context DMA dedicated for 4613 * isochronous receive. 4614 * 4615 * This function returns 0 (zero) if it succeeds. Otherwise, 4616 * return negative value. 4617 */ 4618 static int 4619 fwohci_ir_buf_setup(struct fwohci_ir_ctx *irc) 4620 { 4621 int nsegs; 4622 struct fwohci_desc *fd; 4623 u_int32_t branch; 4624 int bufno = 0; /* DMA segment */ 4625 bus_size_t bufused = 0; /* offset in a DMA segment */ 4626 4627 irc->irc_desc_size = irc->irc_desc_num * sizeof(struct fwohci_desc); 4628 4629 nsegs = fwohci_misc_dmabuf_alloc(irc->irc_sc->sc_dmat, 4630 irc->irc_desc_size, 1, &irc->irc_desc_seg, &irc->irc_desc_dmamap, 4631 (void **)&irc->irc_desc_map, 4632 irc->irc_sc->sc_sc1394.sc1394_dev.dv_xname); 4633 4634 if (nsegs < 0) { 4635 printf("fwohci_ir_buf_alloc: cannot get descriptor\n"); 4636 return -1; 4637 } 4638 irc->irc_desc_nsegs = nsegs; 4639 4640 nsegs = fwohci_misc_dmabuf_alloc(irc->irc_sc->sc_dmat, 4641 irc->irc_buf_totalsize, 16, irc->irc_buf_segs, 4642 &irc->irc_buf_dmamap, (void **)&irc->irc_buf, 4643 irc->irc_sc->sc_sc1394.sc1394_dev.dv_xname); 4644 4645 if (nsegs < 0) { 4646 printf("fwohci_ir_buf_alloc: cannot get DMA buffer\n"); 4647 fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat, 4648 irc->irc_desc_size, 4649 irc->irc_desc_nsegs, &irc->irc_desc_seg, 4650 &irc->irc_desc_dmamap, (caddr_t)irc->irc_desc_map); 4651 return -1; 4652 } 4653 irc->irc_buf_nsegs = nsegs; 4654 4655 branch = irc->irc_desc_dmamap->dm_segs[0].ds_addr 4656 + sizeof(struct fwohci_desc); 4657 bufno = 0; 4658 bufused = 0; 4659 4660 for (fd = irc->irc_desc_map; 4661 fd < irc->irc_desc_map + irc->irc_desc_num; ++fd) { 4662 fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_LAST 4663 | OHCI_DESC_STATUS | OHCI_DESC_BRANCH; 4664 if (irc->irc_flags & IEEE1394_IR_SHORTDELAY) { 4665 fd->fd_flags |= OHCI_DESC_INTR_ALWAYS; 4666 } 4667 #if 0 4668 if ((fd - irc->irc_desc_map) % 64 == 0) { 4669 fd->fd_flags |= OHCI_DESC_INTR_ALWAYS; 4670 } 4671 #endif 4672 fd->fd_reqcount = irc->irc_maxsize; 4673 fd->fd_status = fd->fd_rescount = 0; 4674 4675 fd->fd_branch = branch | 0x01; 4676 branch += sizeof(struct fwohci_desc); 4677 4678 /* physical addr to data? */ 4679 fd->fd_data = 4680 (u_int32_t)((irc->irc_buf_segs[bufno].ds_addr + bufused)); 4681 bufused += irc->irc_maxsize; 4682 if (bufused > irc->irc_buf_segs[bufno].ds_len) { 4683 bufused = 0; 4684 if (++bufno == irc->irc_buf_nsegs) { 4685 /* fail */ 4686 printf("fwohci_ir_buf_setup fail\n"); 4687 4688 fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat, 4689 irc->irc_desc_size, 4690 irc->irc_desc_nsegs, &irc->irc_desc_seg, 4691 &irc->irc_desc_dmamap, 4692 (caddr_t)irc->irc_desc_map); 4693 fwohci_misc_dmabuf_free(irc->irc_sc->sc_dmat, 4694 irc->irc_buf_totalsize, 4695 irc->irc_buf_nsegs, irc->irc_buf_segs, 4696 &irc->irc_buf_dmamap, 4697 (caddr_t)irc->irc_buf); 4698 return -1; 4699 } 4700 } 4701 4702 #ifdef FWOHCI_DEBUG 4703 if (fd < irc->irc_desc_map + 4 4704 || (fd > irc->irc_desc_map + irc->irc_desc_num - 4)) { 4705 printf("fwohci_ir_buf_setup: desc %d %p buf %08x" 4706 " size %d branch %08x\n", 4707 fd - irc->irc_desc_map, fd, fd->fd_data, 4708 fd->fd_reqcount, fd->fd_branch); 4709 } 4710 #endif /* FWOHCI_DEBUG */ 4711 } 4712 4713 --fd; 4714 fd->fd_branch = irc->irc_desc_dmamap->dm_segs[0].ds_addr | 1; 4715 DPRINTF(("fwohci_ir_buf_setup: desc %d %p buf %08x size %d branch %08x\n", 4716 fd - irc->irc_desc_map, fd, fd->fd_data, fd->fd_reqcount, 4717 fd->fd_branch)); 4718 4719 return 0; 4720 } 4721 4722 4723 4724 /* 4725 * static void fwohci_ir_init(struct fwohci_ir_ctx *irc) 4726 * 4727 * This function initialise DMA engine. 4728 */ 4729 static int 4730 fwohci_ir_init(struct fwohci_ir_ctx *irc) 4731 { 4732 struct fwohci_softc *sc = irc->irc_sc; 4733 int n = irc->irc_num; 4734 u_int32_t ctxmatch; 4735 4736 ctxmatch = irc->irc_channel & IEEE1394_ISO_CHANNEL_MASK; 4737 4738 if (irc->irc_channel & IEEE1394_ISO_CHANNEL_ANY) { 4739 OHCI_SYNC_RX_DMA_WRITE(sc, n, 4740 OHCI_SUBREG_ContextControlSet, 4741 OHCI_CTXCTL_RX_MULTI_CHAN_MODE); 4742 4743 /* Receive all the isochronous channels */ 4744 OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskHiSet, 0xffffffff); 4745 OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskLoSet, 0xffffffff); 4746 ctxmatch = 0; 4747 } 4748 4749 ctxmatch |= ((irc->irc_tagbm & 0x0f) << OHCI_CTXMATCH_TAG_BITPOS); 4750 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextMatch, ctxmatch); 4751 4752 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear, 4753 OHCI_CTXCTL_RX_BUFFER_FILL | OHCI_CTXCTL_RX_CYCLE_MATCH_ENABLE); 4754 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet, 4755 OHCI_CTXCTL_RX_ISOCH_HEADER); 4756 4757 printf("fwohci_ir_init\n"); 4758 4759 return 0; 4760 } 4761 4762 4763 /* 4764 * static int fwohci_ir_start(struct fwohci_ir_ctx *irc) 4765 * 4766 * This function starts DMA engine. This function must call 4767 * after fwohci_ir_init() and active bit of context control 4768 * register negated. This function will not check it. 4769 */ 4770 static int 4771 fwohci_ir_start(struct fwohci_ir_ctx *irc) 4772 { 4773 struct fwohci_softc *sc = irc->irc_sc; 4774 int startidx = irc->irc_readtop - irc->irc_desc_map; 4775 u_int32_t startaddr; 4776 4777 startaddr = irc->irc_desc_dmamap->dm_segs[0].ds_addr 4778 + sizeof(struct fwohci_desc)*startidx; 4779 4780 OHCI_SYNC_RX_DMA_WRITE(sc, irc->irc_num, OHCI_SUBREG_CommandPtr, 4781 startaddr | 1); 4782 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, 4783 (1 << irc->irc_num)); 4784 OHCI_SYNC_RX_DMA_WRITE(sc, irc->irc_num, 4785 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN); 4786 4787 printf("fwohci_ir_start: CmdPtr %08x Ctx %08x startidx %d\n", 4788 OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, OHCI_SUBREG_CommandPtr), 4789 OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, OHCI_SUBREG_ContextControlSet), 4790 startidx); 4791 4792 irc->irc_status &= ~IRC_STATUS_READY; 4793 irc->irc_status |= IRC_STATUS_RUN; 4794 4795 if ((irc->irc_flags & IEEE1394_IR_TRIGGER_CIP_SYNC) == 0) { 4796 irc->irc_status |= IRC_STATUS_RECEIVE; 4797 } 4798 4799 return 0; 4800 } 4801 4802 4803 4804 /* 4805 * static int fwohci_ir_stop(struct fwohci_ir_ctx *irc) 4806 * 4807 * This function stops DMA engine. 4808 */ 4809 static int 4810 fwohci_ir_stop(struct fwohci_ir_ctx *irc) 4811 { 4812 struct fwohci_softc *sc = irc->irc_sc; 4813 int i; 4814 4815 printf("fwohci_ir_stop\n"); 4816 4817 OHCI_SYNC_RX_DMA_WRITE(sc, irc->irc_num, 4818 OHCI_SUBREG_ContextControlClear, 4819 OHCI_CTXCTL_RUN | OHCI_CTXCTL_DEAD); 4820 4821 i = 0; 4822 while (OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, 4823 OHCI_SUBREG_ContextControlSet) & OHCI_CTXCTL_ACTIVE) { 4824 #if 0 4825 u_int32_t reg = OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, 4826 OHCI_SUBREG_ContextControlClear); 4827 4828 printf("%s: %d intr IR_CommandPtr 0x%08x " 4829 "ContextCtrl 0x%08x%s%s%s%s\n", 4830 sc->sc_sc1394.sc1394_dev.dv_xname, i, 4831 OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, 4832 OHCI_SUBREG_CommandPtr), 4833 reg, 4834 reg & OHCI_CTXCTL_RUN ? " run" : "", 4835 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 4836 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 4837 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 4838 #endif 4839 if (i > 20) { 4840 printf("fwohci_ir_stop: %s does not stop\n", 4841 sc->sc_sc1394.sc1394_dev.dv_xname); 4842 return 1; 4843 } 4844 DELAY(10); 4845 } 4846 4847 irc->irc_status &= ~IRC_STATUS_RUN; 4848 4849 return 0; 4850 } 4851 4852 4853 4854 4855 4856 4857 static void 4858 fwohci_ir_intr(struct fwohci_softc *sc, struct fwohci_ir_ctx *irc) 4859 { 4860 const char *xname = sc->sc_sc1394.sc1394_dev.dv_xname; 4861 u_int32_t cmd, ctx; 4862 int idx; 4863 struct fwohci_desc *fd; 4864 4865 sc->sc_isocnt.ev_count++; 4866 4867 if (!(irc->irc_status & IRC_STATUS_RUN)) { 4868 printf("fwohci_ir_intr: not running\n"); 4869 return; 4870 } 4871 4872 bus_dmamap_sync(sc->sc_dmat, irc->irc_desc_dmamap, 4873 0, irc->irc_desc_size, BUS_DMASYNC_PREREAD); 4874 4875 ctx = OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, 4876 OHCI_SUBREG_ContextControlSet); 4877 4878 cmd = OHCI_SYNC_RX_DMA_READ(sc, irc->irc_num, 4879 OHCI_SUBREG_CommandPtr); 4880 4881 #define OHCI_CTXCTL_RUNNING (OHCI_CTXCTL_RUN|OHCI_CTXCTL_ACTIVE) 4882 #define OHCI_CTXCTL_RUNNING_MASK (OHCI_CTXCTL_RUNNING|OHCI_CTXCTL_DEAD) 4883 4884 idx = (cmd & 0xfffffff8) - (u_int32_t)irc->irc_desc_dmamap->dm_segs[0].ds_addr; 4885 idx /= sizeof(struct fwohci_desc); 4886 4887 if ((ctx & OHCI_CTXCTL_RUNNING_MASK) == OHCI_CTXCTL_RUNNING) { 4888 if (irc->irc_waitchan != NULL) { 4889 DPRINTF(("fwohci_ir_intr: wakeup " 4890 "ctx %d CmdPtr %08x Ctxctl %08x idx %d\n", 4891 irc->irc_num, cmd, ctx, idx)); 4892 #ifdef FWOHCI_WAIT_DEBUG 4893 irc->irc_cycle[1] = fwohci_cycletimer(irc->irc_sc); 4894 #endif 4895 wakeup((void *)irc->irc_waitchan); 4896 } 4897 selwakeup(&irc->irc_sel); 4898 return; 4899 } 4900 4901 fd = irc->irc_desc_map + idx; 4902 4903 printf("fwohci_ir_intr: %s error " 4904 "ctx %d CmdPtr %08x Ctxctl %08x idx %d\n", xname, 4905 irc->irc_num, cmd, ctx, idx); 4906 printf("\tfd flag %x branch %x stat %x rescnt %x total pkt %d\n", 4907 fd->fd_flags, fd->fd_branch, fd->fd_status,fd->fd_rescount, 4908 irc->irc_pktcount); 4909 } 4910 4911 4912 4913 4914 /* 4915 * static int fwohci_ir_ctx_packetnum(struct fwohci_ir_ctx *irc) 4916 * 4917 * This function obtains the lenth of descriptors with data. 4918 */ 4919 static int 4920 fwohci_ir_ctx_packetnum(struct fwohci_ir_ctx *irc) 4921 { 4922 struct fwohci_desc *fd = irc->irc_readtop; 4923 int i = 0; 4924 4925 /* XXX SYNC */ 4926 while (fd->fd_status != 0) { 4927 if (fd == irc->irc_readtop && i > 0) { 4928 printf("descriptor filled %d at %d\n", i, 4929 irc->irc_pktcount); 4930 #ifdef FWOHCI_WAIT_DEBUG 4931 irc->irc_cycle[2] = fwohci_cycletimer(irc->irc_sc); 4932 printf("cycletimer %d:%d %d:%d %d:%d\n", 4933 irc->irc_cycle[0]>>13, irc->irc_cycle[0]&0x1fff, 4934 irc->irc_cycle[1]>>13, irc->irc_cycle[1]&0x1fff, 4935 irc->irc_cycle[2]>>13, irc->irc_cycle[2]&0x1fff); 4936 #endif 4937 4938 break; 4939 } 4940 4941 ++i; 4942 ++fd; 4943 if (fd == irc->irc_desc_map + irc->irc_desc_num) { 4944 fd = irc->irc_desc_map; 4945 } 4946 4947 } 4948 4949 return i; 4950 } 4951 4952 4953 4954 4955 /* 4956 * int fwohci_ir_read(struct device *dev, ieee1394_ir_tag_t tag, 4957 * struct uio *uio, int headoffs, int flags) 4958 * 4959 * This function reads data from fwohci's isochronous receive 4960 * buffer. 4961 */ 4962 int 4963 fwohci_ir_read(struct device *dev, ieee1394_ir_tag_t tag, struct uio *uio, 4964 int headoffs, int flags) 4965 { 4966 struct fwohci_ir_ctx *irc = (struct fwohci_ir_ctx *)tag; 4967 int packetnum; 4968 int copylen, hdrshim, fwisohdrsiz; 4969 struct fwohci_desc *fd, *fdprev; 4970 u_int8_t *data; 4971 int status = 0; 4972 u_int32_t tmpbranch; 4973 int pktcount_prev = irc->irc_pktcount; 4974 #ifdef FW_DEBUG 4975 int totalread = 0; 4976 #endif 4977 4978 if (irc->irc_status & IRC_STATUS_READY) { 4979 printf("fwohci_ir_read: starting iso read engine\n"); 4980 fwohci_ir_start(irc); 4981 } 4982 4983 packetnum = fwohci_ir_ctx_packetnum(irc); 4984 4985 DPRINTF(("fwohci_ir_read resid %d DMA buf %d\n", 4986 uio->uio_resid, packetnum)); 4987 4988 if (packetnum == 0) { 4989 return EAGAIN; 4990 } 4991 4992 #ifdef USEDRAIN 4993 if (packetnum > irc->irc_desc_num - irc->irc_desc_num/4) { 4994 packetnum -= fwohci_ir_ctx_drain(irc); 4995 if (irc->irc_pktcount != 0) { 4996 printf("fwohci_ir_read overrun %d\n", 4997 irc->irc_pktcount); 4998 } 4999 } 5000 #endif /* USEDRAIN */ 5001 5002 fd = irc->irc_readtop; 5003 5004 #if 0 5005 if ((irc->irc_status & IRC_STATUS_RECEIVE) == 0 5006 && irc->irc_flags & IEEE1394_IR_TRIGGER_CIP_SYNC) { 5007 unsigned int s; 5008 int i = 0; 5009 5010 fdprev = fd; 5011 while (fd->fd_status != 0) { 5012 s = data[14] << 8; 5013 s |= data[15]; 5014 5015 if (s != 0x0000ffffu) { 5016 DPRINTF(("find header %x at %d\n", 5017 s, irc->irc_pktcount)); 5018 irc->irc_status |= IRC_STATUS_RECEIVE; 5019 break; 5020 } 5021 5022 fd->fd_rescount = 0; 5023 fd->fd_status = 0; 5024 5025 fdprev = fd; 5026 if (++fd == irc->irc_desc_map + irc->irc_desc_num) { 5027 fd = irc->irc_desc_map; 5028 data = irc->irc_buf; 5029 } 5030 ++i; 5031 } 5032 5033 /* XXX SYNC */ 5034 if (i > 0) { 5035 tmpbranch = fdprev->fd_branch; 5036 fdprev->fd_branch = 0; 5037 irc->irc_writeend->fd_branch = irc->irc_savedbranch; 5038 irc->irc_writeend = fdprev; 5039 irc->irc_savedbranch = tmpbranch; 5040 } 5041 /* XXX SYNC */ 5042 5043 if (fd->fd_status == 0) { 5044 return EAGAIN; 5045 } 5046 } 5047 #endif 5048 5049 hdrshim = 8; 5050 fwisohdrsiz = 0; 5051 data = irc->irc_buf + (fd - irc->irc_desc_map) * irc->irc_maxsize; 5052 if (irc->irc_flags & IEEE1394_IR_NEEDHEADER) { 5053 fwisohdrsiz = sizeof(struct fwiso_header); 5054 } 5055 5056 while (fd->fd_status != 0 && 5057 (copylen = fd->fd_reqcount - fd->fd_rescount - hdrshim - headoffs) 5058 + fwisohdrsiz < uio->uio_resid) { 5059 5060 DPRINTF(("pkt %04x:%04x uiomove %p, %d\n", 5061 fd->fd_status, fd->fd_rescount, 5062 (void *)(data + 8 + headoffs), copylen)); 5063 if ((irc->irc_status & IRC_STATUS_RECEIVE) == 0) { 5064 DPRINTF(("[%d]", copylen)); 5065 if (irc->irc_pktcount > 1000) { 5066 printf("no header found\n"); 5067 status = EIO; 5068 break; /* XXX */ 5069 } 5070 } else { 5071 DPRINTF(("<%d>", copylen)); 5072 } 5073 5074 if ((irc->irc_status & IRC_STATUS_RECEIVE) == 0 5075 && irc->irc_flags & IEEE1394_IR_TRIGGER_CIP_SYNC 5076 && copylen > 0) { 5077 unsigned int s; 5078 5079 s = data[14] << 8; 5080 s |= data[15]; 5081 5082 if (s != 0x0000ffffu) { 5083 DPRINTF(("find header %x at %d\n", 5084 s, irc->irc_pktcount)); 5085 irc->irc_status |= IRC_STATUS_RECEIVE; 5086 } 5087 } 5088 5089 if (irc->irc_status & IRC_STATUS_RECEIVE) { 5090 if (copylen > 0) { 5091 if (irc->irc_flags & IEEE1394_IR_NEEDHEADER) { 5092 struct fwiso_header fh; 5093 5094 fh.fh_timestamp = htonl((*(u_int32_t *)data) & 0xffff); 5095 fh.fh_speed = htonl((fd->fd_status >> 5)& 0x00000007); 5096 fh.fh_capture_size = htonl(copylen + 4); 5097 fh.fh_iso_header = htonl(*(u_int32_t *)(data + 4)); 5098 status = uiomove((void *)&fh, 5099 sizeof(fh), uio); 5100 if (status != 0) { 5101 /* An error happens */ 5102 printf("uio error in hdr\n"); 5103 break; 5104 } 5105 } 5106 status = uiomove((void *)(data + 8 + headoffs), 5107 copylen, uio); 5108 if (status != 0) { 5109 /* An error happens */ 5110 printf("uio error\n"); 5111 break; 5112 } 5113 #ifdef FW_DEBUG 5114 totalread += copylen; 5115 #endif 5116 } 5117 } 5118 5119 fd->fd_rescount = 0; 5120 fd->fd_status = 0; 5121 5122 #if 0 5123 /* advance writeend pointer and fill branch */ 5124 5125 tmpbranch = fd->fd_branch; 5126 fd->fd_branch = 0; 5127 irc->irc_writeend->fd_branch = irc->irc_savedbranch; 5128 irc->irc_writeend = fd; 5129 irc->irc_savedbranch = tmpbranch; 5130 #endif 5131 fdprev = fd; 5132 5133 data += irc->irc_maxsize; 5134 if (++fd == irc->irc_desc_map + irc->irc_desc_num) { 5135 fd = irc->irc_desc_map; 5136 data = irc->irc_buf; 5137 } 5138 ++irc->irc_pktcount; 5139 } 5140 5141 #if 1 5142 if (irc->irc_pktcount != pktcount_prev) { 5143 /* XXX SYNC */ 5144 tmpbranch = fdprev->fd_branch; 5145 fdprev->fd_branch = 0; 5146 irc->irc_writeend->fd_branch = irc->irc_savedbranch; 5147 irc->irc_writeend = fdprev; 5148 irc->irc_savedbranch = tmpbranch; 5149 /* XXX SYNC */ 5150 } 5151 #endif 5152 5153 if (!(OHCI_SYNC_RX_DMA_READ(irc->irc_sc, irc->irc_num, 5154 OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)) { 5155 /* do wake */ 5156 OHCI_SYNC_RX_DMA_WRITE(irc->irc_sc, irc->irc_num, 5157 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE); 5158 } 5159 5160 if (packetnum > irc->irc_maxqueuelen) { 5161 irc->irc_maxqueuelen = packetnum; 5162 irc->irc_maxqueuepos = irc->irc_pktcount; 5163 } 5164 5165 if (irc->irc_pktcount == pktcount_prev) { 5166 #if 0 5167 printf("fwohci_ir_read: process 0 packet, total %d\n", 5168 irc->irc_pktcount); 5169 if (++pktfail > 30) { 5170 return 0; 5171 } 5172 #endif 5173 return EAGAIN; 5174 } 5175 5176 irc->irc_readtop = fd; 5177 5178 DPRINTF(("fwochi_ir_read: process %d packet, total %d\n", 5179 totalread, irc->irc_pktcount)); 5180 5181 return status; 5182 } 5183 5184 5185 5186 5187 /* 5188 * int fwohci_ir_wait(struct device *dev, ieee1394_ir_tag_t tag, 5189 * void *wchan, char *name) 5190 * 5191 * This function waits till new data comes. 5192 */ 5193 int 5194 fwohci_ir_wait(struct device *dev, ieee1394_ir_tag_t tag, void *wchan, char *name) 5195 { 5196 struct fwohci_ir_ctx *irc = (struct fwohci_ir_ctx *)tag; 5197 struct fwohci_desc *fd; 5198 int pktnum; 5199 int stat; 5200 5201 if ((pktnum = fwohci_ir_ctx_packetnum(irc)) > 4) { 5202 DPRINTF(("fwohci_ir_wait enough data %d\n", pktnum)); 5203 return 0; 5204 } 5205 5206 fd = irc->irc_readtop + 32; 5207 if (fd >= irc->irc_desc_map + irc->irc_desc_num) { 5208 fd -= irc->irc_desc_num; 5209 } 5210 5211 irc->irc_waitchan = wchan; 5212 if ((irc->irc_flags & IEEE1394_IR_SHORTDELAY) == 0) { 5213 fd->fd_flags |= OHCI_DESC_INTR_ALWAYS; 5214 DPRINTF(("fwohci_ir_wait stops %d set intr %d\n", 5215 irc->irc_readtop - irc->irc_desc_map, 5216 fd - irc->irc_desc_map)); 5217 /* XXX SYNC */ 5218 } 5219 5220 #ifdef FWOHCI_WAIT_DEBUG 5221 irc->irc_cycle[0] = fwohci_cycletimer(irc->irc_sc); 5222 #endif 5223 5224 irc->irc_status |= IRC_STATUS_SLEEPING; 5225 if ((stat = tsleep(wchan, PCATCH|PRIBIO, name, hz*10)) != 0) { 5226 irc->irc_waitchan = NULL; 5227 fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS; 5228 if (stat == EWOULDBLOCK) { 5229 printf("fwohci_ir_wait: timeout\n"); 5230 return EIO; 5231 } else { 5232 return EINTR; 5233 } 5234 } 5235 5236 irc->irc_waitchan = NULL; 5237 if ((irc->irc_flags & IEEE1394_IR_SHORTDELAY) == 0) { 5238 fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS; 5239 /* XXX SYNC */ 5240 } 5241 5242 DPRINTF(("fwohci_ir_wait: wakeup\n")); 5243 5244 return 0; 5245 } 5246 5247 5248 5249 5250 /* 5251 * int fwohci_ir_select(struct device *dev, ieee1394_ir_tag_t tag, 5252 * struct proc *p) 5253 * 5254 * This function returns the number of packets in queue. 5255 */ 5256 int 5257 fwohci_ir_select(struct device *dev, ieee1394_ir_tag_t tag, struct proc *p) 5258 { 5259 struct fwohci_ir_ctx *irc = (struct fwohci_ir_ctx *)tag; 5260 int pktnum; 5261 5262 if (irc->irc_status & IRC_STATUS_READY) { 5263 printf("fwohci_ir_select: starting iso read engine\n"); 5264 fwohci_ir_start(irc); 5265 } 5266 5267 if ((pktnum = fwohci_ir_ctx_packetnum(irc)) == 0) { 5268 selrecord(p, &irc->irc_sel); 5269 } 5270 5271 return pktnum; 5272 } 5273 5274 5275 5276 #ifdef USEDRAIN 5277 /* 5278 * int fwohci_ir_ctx_drain(struct fwohci_ir_ctx *irc) 5279 * 5280 * This function will drain all the packets in receive DMA 5281 * buffer. 5282 */ 5283 static int 5284 fwohci_ir_ctx_drain(struct fwohci_ir_ctx *irc) 5285 { 5286 struct fwohci_desc *fd = irc->irc_readtop; 5287 u_int32_t reg; 5288 int count = 0; 5289 5290 reg = OHCI_SYNC_RX_DMA_READ(irc->irc_sc, irc->irc_num, 5291 OHCI_SUBREG_ContextControlClear); 5292 5293 printf("fwohci_ir_ctx_drain ctx%s%s%s%s\n", 5294 reg & OHCI_CTXCTL_RUN ? " run" : "", 5295 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 5296 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 5297 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 5298 5299 if ((reg & OHCI_CTXCTL_RUNNING_MASK) == OHCI_CTXCTL_RUN) { 5300 /* DMA engine is stopped */ 5301 u_int32_t startadr; 5302 5303 for (fd = irc->irc_desc_map; 5304 fd < irc->irc_desc_map + irc->irc_desc_num; 5305 ++fd) { 5306 fd->fd_status = 0; 5307 } 5308 5309 /* Restore branch addr of the last descriptor */ 5310 irc->irc_writeend->fd_branch = irc->irc_savedbranch; 5311 5312 irc->irc_readtop = irc->irc_desc_map; 5313 irc->irc_writeend = irc->irc_desc_map + irc->irc_desc_num - 1; 5314 irc->irc_savedbranch = irc->irc_writeend->fd_branch; 5315 irc->irc_writeend->fd_branch = 0; 5316 5317 count = irc->irc_desc_num; 5318 5319 OHCI_SYNC_RX_DMA_WRITE(irc->irc_sc, irc->irc_num, 5320 OHCI_SUBREG_ContextControlClear, 5321 OHCI_CTXCTL_RUN | OHCI_CTXCTL_DEAD); 5322 5323 startadr = (u_int32_t)irc->irc_desc_dmamap->dm_segs[0].ds_addr; 5324 5325 printf("fwohci_ir_ctx_drain: remove %d pkts\n", count); 5326 5327 OHCI_SYNC_RX_DMA_WRITE(irc->irc_sc, irc->irc_num, 5328 OHCI_SUBREG_CommandPtr, startadr | 1); 5329 5330 OHCI_SYNC_RX_DMA_WRITE(irc->irc_sc, irc->irc_num, 5331 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN); 5332 } else { 5333 const int removecount = irc->irc_desc_num/2; 5334 u_int32_t tmpbranch; 5335 5336 for (count = 0; count < removecount; ++count) { 5337 if (fd->fd_status == 0) { 5338 break; 5339 } 5340 5341 fd->fd_status = 0; 5342 5343 tmpbranch = fd->fd_branch; 5344 fd->fd_branch = 0; 5345 irc->irc_writeend->fd_branch = irc->irc_savedbranch; 5346 irc->irc_writeend = fd; 5347 irc->irc_savedbranch = tmpbranch; 5348 5349 if (++fd == irc->irc_desc_map + irc->irc_desc_num) { 5350 fd = irc->irc_desc_map; 5351 } 5352 ++count; 5353 } 5354 5355 printf("fwohci_ir_ctx_drain: remove %d pkts\n", count); 5356 } 5357 5358 return count; 5359 } 5360 #endif /* USEDRAIN */ 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 /* 5371 * service routines for isochronous transmit 5372 */ 5373 5374 5375 struct fwohci_it_ctx * 5376 fwohci_it_ctx_construct(struct fwohci_softc *sc, int no, int ch, int tag, int maxsize) 5377 { 5378 struct fwohci_it_ctx *itc; 5379 size_t dmastrsize; 5380 struct fwohci_it_dmabuf *dmastr; 5381 struct fwohci_desc *desc; 5382 bus_addr_t descphys; 5383 int nodesc; 5384 int i, j; 5385 5386 if ((itc = malloc(sizeof(*itc), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) { 5387 return itc; 5388 } 5389 5390 itc->itc_num = no; 5391 itc->itc_flags = 0; 5392 itc->itc_sc = sc; 5393 itc->itc_bufnum = FWOHCI_IT_BUFNUM; 5394 5395 itc->itc_channel = ch; 5396 itc->itc_tag = tag; 5397 itc->itc_speed = OHCI_CTXCTL_SPD_100; /* XXX */ 5398 5399 itc->itc_outpkt = 0; 5400 5401 itc->itc_maxsize = maxsize; 5402 5403 dmastrsize = sizeof(struct fwohci_it_dmabuf)*itc->itc_bufnum; 5404 5405 if ((dmastr = malloc(dmastrsize, M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) { 5406 goto error_1; 5407 } 5408 itc->itc_buf = dmastr; 5409 5410 /* 5411 * Get memory for descriptors. One buffer will have 256 5412 * packet entry and 1 trailing descriptor for writing scratch. 5413 * 4-byte space for scratch. 5414 */ 5415 itc->itc_descsize = (256*3 + 1)*itc->itc_bufnum; 5416 5417 if (fwohci_it_desc_alloc(itc)) { 5418 printf("%s: cannot get enough memory for descriptor\n", 5419 sc->sc_sc1394.sc1394_dev.dv_xname); 5420 goto error_2; 5421 } 5422 5423 /* prepare DMA buffer */ 5424 nodesc = itc->itc_descsize/itc->itc_bufnum; 5425 desc = (struct fwohci_desc *)itc->itc_descmap; 5426 descphys = itc->itc_dseg.ds_addr; 5427 5428 for (i = 0; i < itc->itc_bufnum; ++i) { 5429 5430 if (fwohci_itd_construct(itc, &dmastr[i], i, desc, 5431 descphys, nodesc, 5432 itc->itc_maxsize, itc->itc_scratch_paddr)) { 5433 goto error_3; 5434 } 5435 desc += nodesc; 5436 descphys += sizeof(struct fwohci_desc)*nodesc; 5437 } 5438 5439 #if 1 5440 itc->itc_buf_start = itc->itc_buf; 5441 itc->itc_buf_end = itc->itc_buf; 5442 itc->itc_buf_linkend = itc->itc_buf; 5443 #else 5444 itc->itc_bufidx_start = 0; 5445 itc->itc_bufidx_end = 0; 5446 itc->itc_bufidx_linkend = 0; 5447 #endif 5448 itc->itc_buf_cnt = 0; 5449 itc->itc_waitchan = NULL; 5450 *itc->itc_scratch = 0xffffffff; 5451 5452 return itc; 5453 5454 error_3: 5455 for (j = 0; j < i; ++j) { 5456 fwohci_itd_destruct(&dmastr[j]); 5457 } 5458 fwohci_it_desc_free(itc); 5459 error_2: 5460 free(itc->itc_buf, M_DEVBUF); 5461 error_1: 5462 free(itc, M_DEVBUF); 5463 5464 return NULL; 5465 } 5466 5467 5468 5469 void 5470 fwohci_it_ctx_destruct(struct fwohci_it_ctx *itc) 5471 { 5472 int i; 5473 5474 for (i = 0; i < itc->itc_bufnum; ++i) { 5475 fwohci_itd_destruct(&itc->itc_buf[i]); 5476 } 5477 5478 fwohci_it_desc_free(itc); 5479 free(itc, M_DEVBUF); 5480 } 5481 5482 5483 /* 5484 * static int fwohci_it_desc_alloc(struct fwohci_it_ctx *itc) 5485 * 5486 * Allocates descriptors for context DMA dedicated for 5487 * isochronous transmit. 5488 * 5489 * This function returns 0 (zero) if it succeeds. Otherwise, 5490 * return negative value. 5491 */ 5492 static int 5493 fwohci_it_desc_alloc(struct fwohci_it_ctx *itc) 5494 { 5495 bus_dma_tag_t dmat = itc->itc_sc->sc_dmat; 5496 const char *xname = itc->itc_sc->sc_sc1394.sc1394_dev.dv_xname; 5497 int error, dsize; 5498 5499 /* add for scratch */ 5500 itc->itc_descsize++; 5501 5502 /* rounding up to 256 */ 5503 if ((itc->itc_descsize & 0x0ff) != 0) { 5504 itc->itc_descsize = 5505 (itc->itc_descsize & ~0x0ff) + 0x100; 5506 } 5507 /* remove for scratch */ 5508 5509 itc->itc_descsize--; 5510 printf("%s: fwohci_it_desc_alloc will allocate %d descs\n", 5511 xname, itc->itc_descsize); 5512 5513 /* 5514 * allocate descriptor buffer 5515 */ 5516 dsize = sizeof(struct fwohci_desc) * itc->itc_descsize; 5517 5518 printf("%s: fwohci_it_desc_alloc: descriptor %d, dsize %d\n", 5519 xname, itc->itc_descsize, dsize); 5520 5521 if ((error = bus_dmamem_alloc(dmat, dsize, PAGE_SIZE, 0, 5522 &itc->itc_dseg, 1, &itc->itc_dnsegs, 0)) != 0) { 5523 printf("%s: unable to allocate descriptor buffer, error = %d\n", 5524 xname, error); 5525 goto fail_0; 5526 } 5527 5528 printf("fwohci_it_desc_alloc: %d segment[s]\n", itc->itc_dnsegs); 5529 5530 if ((error = bus_dmamem_map(dmat, &itc->itc_dseg, 5531 itc->itc_dnsegs, dsize, (caddr_t *)&itc->itc_descmap, 5532 BUS_DMA_COHERENT | BUS_DMA_WAITOK)) != 0) { 5533 printf("%s: unable to map descriptor buffer, error = %d\n", 5534 xname, error); 5535 goto fail_1; 5536 } 5537 5538 printf("fwohci_it_desc_alloc: bus_dmamem_map success dseg %lx:%lx\n", 5539 (long)itc->itc_dseg.ds_addr, (long)itc->itc_dseg.ds_len); 5540 5541 if ((error = bus_dmamap_create(dmat, dsize, itc->itc_dnsegs, 5542 dsize, 0, BUS_DMA_WAITOK, &itc->itc_ddmamap)) != 0) { 5543 printf("%s: unable to create descriptor buffer DMA map, " 5544 "error = %d\n", xname, error); 5545 goto fail_2; 5546 } 5547 5548 printf("fwohci_it_desc_alloc: bus_dmamem_create success\n"); 5549 5550 { 5551 int loop; 5552 5553 for (loop = 0; loop < itc->itc_ddmamap->dm_nsegs; ++loop) { 5554 printf("\t%.2d: 0x%lx - 0x%lx\n", loop, 5555 (long)itc->itc_ddmamap->dm_segs[loop].ds_addr, 5556 (long)itc->itc_ddmamap->dm_segs[loop].ds_addr + 5557 (long)itc->itc_ddmamap->dm_segs[loop].ds_len - 1); 5558 } 5559 } 5560 5561 if ((error = bus_dmamap_load(dmat, itc->itc_ddmamap, 5562 itc->itc_descmap, dsize, NULL, BUS_DMA_WAITOK)) != 0) { 5563 printf("%s: unable to load descriptor buffer DMA map, " 5564 "error = %d\n", xname, error); 5565 goto fail_3; 5566 } 5567 5568 printf("%s: fwohci_it_desc_alloc: get DMA memory phys:0x%08x vm:%p\n", 5569 xname, (int)itc->itc_ddmamap->dm_segs[0].ds_addr, itc->itc_descmap); 5570 5571 itc->itc_scratch = (u_int32_t *)(itc->itc_descmap 5572 + (sizeof(struct fwohci_desc))*itc->itc_descsize); 5573 itc->itc_scratch_paddr = 5574 itc->itc_ddmamap->dm_segs[0].ds_addr 5575 + (sizeof(struct fwohci_desc))*itc->itc_descsize; 5576 5577 printf("%s: scratch %p, 0x%x\n", xname, itc->itc_scratch, 5578 (int)itc->itc_scratch_paddr); 5579 5580 /* itc->itc_scratch_paddr = vtophys(itc->itc_scratch); */ 5581 5582 return 0; 5583 5584 fail_3: 5585 bus_dmamap_destroy(dmat, itc->itc_ddmamap); 5586 fail_2: 5587 bus_dmamem_unmap(dmat, (caddr_t)itc->itc_descmap, dsize); 5588 fail_1: 5589 bus_dmamem_free(dmat, &itc->itc_dseg, itc->itc_dnsegs); 5590 fail_0: 5591 itc->itc_dnsegs = 0; 5592 itc->itc_descmap = NULL; 5593 return error; 5594 } 5595 5596 5597 static void 5598 fwohci_it_desc_free(struct fwohci_it_ctx *itc) 5599 { 5600 bus_dma_tag_t dmat = itc->itc_sc->sc_dmat; 5601 int dsize = sizeof(struct fwohci_desc) * itc->itc_descsize + 4; 5602 5603 bus_dmamap_destroy(dmat, itc->itc_ddmamap); 5604 bus_dmamem_unmap(dmat, (caddr_t)itc->itc_descmap, dsize); 5605 bus_dmamem_free(dmat, &itc->itc_dseg, itc->itc_dnsegs); 5606 5607 itc->itc_dnsegs = 0; 5608 itc->itc_descmap = NULL; 5609 } 5610 5611 5612 5613 /* 5614 * int fwohci_it_ctx_writedata(ieee1394_it_tag_t it, int ndata, 5615 * struct ieee1394_it_datalist *itdata, int flags) 5616 * 5617 * This function will write packet data to DMA buffer in the 5618 * context. This function will parse ieee1394_it_datalist 5619 * command and fill DMA buffer. This function will return the 5620 * number of written packets, or error code if the return value 5621 * is negative. 5622 * 5623 * When this funtion returns positive value but smaller than 5624 * ndata, it reaches at the ent of DMA buffer. 5625 */ 5626 int 5627 fwohci_it_ctx_writedata(ieee1394_it_tag_t it, int ndata, 5628 struct ieee1394_it_datalist *itdata, int flags) 5629 { 5630 struct fwohci_it_ctx *itc = (struct fwohci_it_ctx *)it; 5631 int rv; 5632 int writepkt = 0; 5633 struct fwohci_it_dmabuf *itd; 5634 int i = 0; 5635 5636 itd = itc->itc_buf_end; 5637 5638 while (ndata > 0) { 5639 int s; 5640 5641 if (fwohci_itd_isfull(itd) || fwohci_itd_islocked(itd)) { 5642 if (itc->itc_buf_cnt == itc->itc_bufnum) { 5643 /* no space to write */ 5644 printf("sleeping: start linkend end %d %d %d " 5645 "bufcnt %d\n", 5646 itc->itc_buf_start->itd_num, 5647 itc->itc_buf_linkend->itd_num, 5648 itc->itc_buf_end->itd_num, 5649 itc->itc_buf_cnt); 5650 5651 itc->itc_waitchan = itc; 5652 if (tsleep((void *)itc->itc_waitchan, 5653 PCATCH, "fwohci it", 0) == EWOULDBLOCK) { 5654 itc->itc_waitchan = NULL; 5655 printf("fwohci0 signal\n"); 5656 break; 5657 } 5658 printf("waking: start linkend end %d %d %d\n", 5659 itc->itc_buf_start->itd_num, 5660 itc->itc_buf_linkend->itd_num, 5661 itc->itc_buf_end->itd_num); 5662 5663 itc->itc_waitchan = itc; 5664 i = 0; 5665 } else { 5666 /* 5667 * Use next buffer. This DMA buffer is full 5668 * or locked. 5669 */ 5670 INC_BUF(itc, itd); 5671 } 5672 } 5673 5674 if (++i > 10) { 5675 panic("why loop so much %d", itc->itc_buf_cnt); 5676 break; 5677 } 5678 5679 s = splbio(); 5680 5681 if (fwohci_itd_hasdata(itd) == 0) { 5682 ++itc->itc_buf_cnt; 5683 DPRINTF(("<buf cnt %d>\n", itc->itc_buf_cnt)); 5684 } 5685 5686 rv = fwohci_itd_writedata(itd, ndata, itdata); 5687 DPRINTF(("fwohci_it_ctx_writedata: buf %d ndata %d rv %d\n", 5688 itd->itd_num, ndata, rv)); 5689 5690 if (itc->itc_buf_start == itc->itc_buf_linkend 5691 && (itc->itc_flags & ITC_FLAGS_RUN) != 0) { 5692 5693 #ifdef DEBUG_USERADD 5694 printf("fwohci_it_ctx_writedata: emergency!\n"); 5695 #endif 5696 if (itc->itc_buf_linkend != itc->itc_buf_end 5697 && fwohci_itd_hasdata(itc->itc_buf_end)) { 5698 struct fwohci_it_dmabuf *itdn = itc->itc_buf_linkend; 5699 5700 INC_BUF(itc, itdn); 5701 printf("connecting %d after %d\n", 5702 itdn->itd_num, 5703 itc->itc_buf_linkend->itd_num); 5704 if (fwohci_itd_link(itc->itc_buf_linkend, itdn)) { 5705 printf("fwohci_it_ctx_writedata:" 5706 " cannot link correctly\n"); 5707 return -1; 5708 } 5709 itc->itc_buf_linkend = itdn; 5710 } 5711 } 5712 5713 splx(s); 5714 5715 if (rv < 0) { 5716 /* some errors happend */ 5717 break; 5718 } 5719 5720 writepkt += rv; 5721 ndata -= rv; 5722 itdata += rv; 5723 itc->itc_buf_end = itd; 5724 } 5725 5726 /* Start DMA engine if stopped */ 5727 if ((itc->itc_flags & ITC_FLAGS_RUN) == 0) { 5728 if (itc->itc_buf_cnt > itc->itc_bufnum - 1 || flags) { 5729 /* run */ 5730 printf("fwohci_itc_ctl_writedata: DMA engine start\n"); 5731 fwohci_it_ctx_run(itc); 5732 } 5733 } 5734 5735 return writepkt; 5736 } 5737 5738 5739 5740 static void 5741 fwohci_it_ctx_run(struct fwohci_it_ctx *itc) 5742 { 5743 struct fwohci_softc *sc = itc->itc_sc; 5744 int ctx = itc->itc_num; 5745 struct fwohci_it_dmabuf *itd 5746 = (struct fwohci_it_dmabuf *)itc->itc_buf_start; 5747 u_int32_t reg; 5748 int i; 5749 5750 if (itc->itc_flags & ITC_FLAGS_RUN) { 5751 return; 5752 } 5753 itc->itc_flags |= ITC_FLAGS_RUN; 5754 5755 /* 5756 * dirty, but I can't imagine better place to save branch addr 5757 * of top DMA buffer and substitute 0 to it. 5758 */ 5759 itd->itd_savedbranch = itd->itd_lastdesc->fd_branch; 5760 itd->itd_lastdesc->fd_branch = 0; 5761 5762 if (itc->itc_buf_cnt > 1) { 5763 struct fwohci_it_dmabuf *itdn = itd; 5764 5765 #if 0 5766 INC_BUF(itc, itdn); 5767 5768 if (fwohci_itd_link(itd, itdn)) { 5769 printf("fwohci_it_ctx_run: cannot link correctly\n"); 5770 return; 5771 } 5772 itc->itc_buf_linkend = itdn; 5773 #else 5774 for (;;) { 5775 INC_BUF(itc, itdn); 5776 5777 if (itdn == itc->itc_buf_end) { 5778 break; 5779 } 5780 if (fwohci_itd_link(itd, itdn)) { 5781 printf("fwohci_it_ctx_run: cannot link\n"); 5782 return; 5783 } 5784 itd = itdn; 5785 } 5786 itc->itc_buf_linkend = itd; 5787 #endif 5788 } else { 5789 itd->itd_lastdesc->fd_flags |= OHCI_DESC_INTR_ALWAYS; 5790 itc->itc_buf_linkend = itc->itc_buf_end; 5791 itc->itc_buf_end->itd_flags |= ITD_FLAGS_LOCK; 5792 5793 /* sanity check */ 5794 if (itc->itc_buf_end != itc->itc_buf_start) { 5795 printf("buf start & end differs %p %p\n", 5796 itc->itc_buf_end, itc->itc_buf_start); 5797 } 5798 #if 0 5799 { 5800 u_int32_t *fdp; 5801 u_int32_t adr; 5802 int i; 5803 5804 printf("fwohci_it_ctx_run: itc_buf_cnt 1, DMA buf %d\n", 5805 itd->itd_num); 5806 printf(" last desc %p npacket %d, %d 0x%04x%04x", 5807 itd->itd_lastdesc, itd->itd_npacket, 5808 (itd->itd_lastdesc - itd->itd_desc)/3, 5809 itd->itd_lastdesc->fd_flags, 5810 itd->itd_lastdesc->fd_reqcount); 5811 fdp = (u_int32_t *)itd->itd_desc; 5812 adr = (u_int32_t)itd->itd_desc_phys; /* XXX */ 5813 5814 for (i = 0; i < 7*4; ++i) { 5815 if (i % 4 == 0) { 5816 printf("\n%x:", adr + 4*i); 5817 } 5818 printf(" %08x", fdp[i]); 5819 } 5820 5821 if (itd->itd_npacket > 4) { 5822 printf("\n..."); 5823 i = (itd->itd_npacket - 2)*12 + 4; 5824 } else { 5825 i = 2*12 + 4; 5826 } 5827 for (;i < itd->itd_npacket*12 + 4; ++i) { 5828 if (i % 4 == 0) { 5829 printf("\n%x:", adr + 4*i); 5830 } 5831 printf(" %08x", fdp[i]); 5832 } 5833 printf("\n"); 5834 } 5835 #endif 5836 } 5837 { 5838 struct fwohci_desc *fd; 5839 5840 printf("fwohci_it_ctx_run: link start linkend end %d %d %d\n", 5841 itc->itc_buf_start->itd_num, 5842 itc->itc_buf_linkend->itd_num, 5843 itc->itc_buf_end->itd_num); 5844 5845 fd = itc->itc_buf_start->itd_desc; 5846 if ((fd->fd_flags & 0xff00) != OHCI_DESC_STORE_VALUE) { 5847 printf("fwohci_it_ctx_run: start buf not with STORE\n"); 5848 } 5849 fd += 3; 5850 if ((fd->fd_flags & OHCI_DESC_INTR_ALWAYS) == 0) { 5851 printf("fwohci_it_ctx_run: start buf does not have intr\n"); 5852 } 5853 5854 fd = itc->itc_buf_linkend->itd_desc; 5855 if ((fd->fd_flags & 0xff00) != OHCI_DESC_STORE_VALUE) { 5856 printf("fwohci_it_ctx_run: linkend buf not with STORE\n"); 5857 } 5858 fd += 3; 5859 if ((fd->fd_flags & OHCI_DESC_INTR_ALWAYS) == 0) { 5860 printf("fwohci_it_ctx_run: linkend buf does not have intr\n"); 5861 } 5862 } 5863 5864 *itc->itc_scratch = 0xffffffff; 5865 5866 OHCI_SYNC_TX_DMA_WRITE(sc, ctx, OHCI_SUBREG_ContextControlClear, 5867 0xffff0000); 5868 reg = OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_ContextControlSet); 5869 5870 printf("fwohci_it_ctx_run start for ctx %d\n", ctx); 5871 printf("%s: bfr IT_CommandPtr 0x%08x ContextCtrl 0x%08x%s%s%s%s\n", 5872 sc->sc_sc1394.sc1394_dev.dv_xname, 5873 OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_CommandPtr), 5874 reg, 5875 reg & OHCI_CTXCTL_RUN ? " run" : "", 5876 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 5877 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 5878 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 5879 5880 OHCI_SYNC_TX_DMA_WRITE(sc, ctx, OHCI_SUBREG_ContextControlClear, 5881 OHCI_CTXCTL_RUN); 5882 5883 reg = OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_ContextControlSet); 5884 i = 0; 5885 while (reg & (OHCI_CTXCTL_ACTIVE | OHCI_CTXCTL_RUN)) { 5886 delay(100); 5887 if (++i > 1000) { 5888 printf("%s: cannot stop iso transmit engine\n", 5889 sc->sc_sc1394.sc1394_dev.dv_xname); 5890 break; 5891 } 5892 reg = OHCI_SYNC_TX_DMA_READ(sc, ctx, 5893 OHCI_SUBREG_ContextControlSet); 5894 } 5895 5896 printf("%s: itm IT_CommandPtr 0x%08x ContextCtrl 0x%08x%s%s%s%s\n", 5897 sc->sc_sc1394.sc1394_dev.dv_xname, 5898 OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_CommandPtr), 5899 reg, 5900 reg & OHCI_CTXCTL_RUN ? " run" : "", 5901 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 5902 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 5903 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 5904 5905 printf("%s: writing CommandPtr to 0x%08x\n", 5906 sc->sc_sc1394.sc1394_dev.dv_xname, 5907 (int)itc->itc_buf_start->itd_desc_phys); 5908 OHCI_SYNC_TX_DMA_WRITE(sc, ctx, OHCI_SUBREG_CommandPtr, 5909 fwohci_itd_list_head(itc->itc_buf_start) | 4); 5910 5911 OHCI_SYNC_TX_DMA_WRITE(sc, ctx, OHCI_SUBREG_ContextControlSet, 5912 OHCI_CTXCTL_RUN | OHCI_CTXCTL_WAKE); 5913 5914 reg = OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_ContextControlSet); 5915 5916 printf("%s: aft IT_CommandPtr 0x%08x ContextCtrl 0x%08x%s%s%s%s\n", 5917 sc->sc_sc1394.sc1394_dev.dv_xname, 5918 OHCI_SYNC_TX_DMA_READ(sc, ctx, OHCI_SUBREG_CommandPtr), 5919 reg, 5920 reg & OHCI_CTXCTL_RUN ? " run" : "", 5921 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 5922 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 5923 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 5924 } 5925 5926 5927 5928 int 5929 fwohci_it_ctx_flush(ieee1394_it_tag_t it) 5930 { 5931 struct fwohci_it_ctx *itc = (struct fwohci_it_ctx *)it; 5932 int rv = 0; 5933 5934 if ((itc->itc_flags & ITC_FLAGS_RUN) == 0 5935 && itc->itc_buf_cnt > 0) { 5936 printf("fwohci_it_ctx_flush: %s flushing\n", 5937 itc->itc_sc->sc_sc1394.sc1394_dev.dv_xname); 5938 5939 fwohci_it_ctx_run(itc); 5940 rv = 1; 5941 } 5942 5943 return rv; 5944 } 5945 5946 5947 /* 5948 * static void fwohci_it_intr(struct fwohci_softc *sc, 5949 * struct fwochi_it_ctx *itc) 5950 * 5951 * This function is the interrupt handler for isochronous 5952 * transmit interrupt. This function will 1) unlink used 5953 * (already transmitted) buffers, 2) link new filled buffers, if 5954 * necessary and 3) say some free dma buffers exist to 5955 * fwiso_write() 5956 */ 5957 static void 5958 fwohci_it_intr(struct fwohci_softc *sc, struct fwohci_it_ctx *itc) 5959 { 5960 struct fwohci_it_dmabuf *itd, *newstartbuf; 5961 u_int16_t scratchval; 5962 u_int32_t reg; 5963 5964 reg = OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, 5965 OHCI_SUBREG_ContextControlSet); 5966 5967 /* print out debug info */ 5968 #ifdef FW_DEBUG 5969 printf("fwohci_it_intr: CTX %d\n", itc->itc_num); 5970 5971 printf("fwohci_it_intr: %s: IT_CommandPtr 0x%08x " 5972 "ContextCtrl 0x%08x%s%s%s%s\n", 5973 sc->sc_sc1394.sc1394_dev.dv_xname, 5974 OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, OHCI_SUBREG_CommandPtr), 5975 reg, 5976 reg & OHCI_CTXCTL_RUN ? " run" : "", 5977 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 5978 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 5979 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 5980 printf("fwohci_it_intr: %s: scratch %x start %d end %d valid %d\n", 5981 sc->sc_sc1394.sc1394_dev.dv_xname, *itc->itc_scratch, 5982 itc->itc_buf_start->itd_num, itc->itc_buf_end->itd_num, 5983 itc->itc_buf_cnt); 5984 { 5985 u_int32_t reg 5986 = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer); 5987 printf("\t\tIsoCounter 0x%08x, %d %d %d\n", reg, 5988 (reg >> 25) & 0xfe, (reg >> 12) & 0x1fff, reg & 0xfff); 5989 } 5990 #endif /* FW_DEBUG */ 5991 /* end print out debug info */ 5992 5993 scratchval = (*itc->itc_scratch) & 0x0000ffff; 5994 *itc->itc_scratch = 0xffffffff; 5995 5996 if ((reg & OHCI_CTXCTL_ACTIVE) == 0 && scratchval != 0xffff) { 5997 /* DMA engine has been stopped */ 5998 printf("DMA engine stopped\n"); 5999 printf("fwohci_it_intr: %s: IT_CommandPtr 0x%08x " 6000 "ContextCtrl 0x%08x%s%s%s%s\n", 6001 sc->sc_sc1394.sc1394_dev.dv_xname, 6002 OHCI_SYNC_TX_DMA_READ(sc, itc->itc_num, OHCI_SUBREG_CommandPtr), 6003 reg, 6004 reg & OHCI_CTXCTL_RUN ? " run" : "", 6005 reg & OHCI_CTXCTL_WAKE ? " wake" : "", 6006 reg & OHCI_CTXCTL_DEAD ? " dead" : "", 6007 reg & OHCI_CTXCTL_ACTIVE ? " active" : ""); 6008 printf("fwohci_it_intr: %s: scratch %x start %d end %d valid %d\n", 6009 sc->sc_sc1394.sc1394_dev.dv_xname, *itc->itc_scratch, 6010 itc->itc_buf_start->itd_num, itc->itc_buf_end->itd_num, 6011 itc->itc_buf_cnt); 6012 { 6013 u_int32_t reg 6014 = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer); 6015 printf("\t\tIsoCounter 0x%08x, %d %d %d\n", reg, 6016 (reg >> 25) & 0xfe, (reg >> 12) & 0x1fff, reg & 0xfff); 6017 } 6018 printf("\t\tbranch of lastdesc 0x%08x\n", 6019 itc->itc_buf_start->itd_lastdesc->fd_branch); 6020 6021 scratchval = 0xffff; 6022 itc->itc_flags &= ~ITC_FLAGS_RUN; 6023 } 6024 6025 /* unlink old buffers */ 6026 if (scratchval != 0xffff) { 6027 /* normal path */ 6028 newstartbuf = &itc->itc_buf[scratchval]; 6029 } else { 6030 /* DMA engine stopped */ 6031 newstartbuf = itc->itc_buf_linkend; 6032 INC_BUF(itc, newstartbuf); 6033 } 6034 6035 itd = (struct fwohci_it_dmabuf *)itc->itc_buf_start; 6036 itc->itc_buf_start = newstartbuf; 6037 while (itd != newstartbuf) { 6038 itc->itc_outpkt += itd->itd_npacket; 6039 fwohci_itd_unlink(itd); 6040 INC_BUF(itc, itd); 6041 --itc->itc_buf_cnt; 6042 DPRINTF(("<buf cnt %d>\n", itc->itc_buf_cnt)); 6043 } 6044 6045 #ifdef DEBUG_USERADD 6046 if (scratchval != 0xffff) { 6047 printf("fwohci0: intr start %d dataend %d %d\n", scratchval, 6048 itc->itc_buf_end->itd_num, itc->itc_outpkt); 6049 } 6050 #endif 6051 6052 if (scratchval == 0xffff) { 6053 /* no data supplied */ 6054 printf("fwohci_it_intr: no it data. output total %d\n", 6055 itc->itc_outpkt); 6056 6057 if (itc->itc_buf_cnt > 0) { 6058 printf("fwohci_it_intr: it DMA stops " 6059 "w/ valid databuf %d buf %d data %d" 6060 " intr reg 0x%08x\n", 6061 itc->itc_buf_cnt, 6062 itc->itc_buf_end->itd_num, 6063 fwohci_itd_hasdata(itc->itc_buf_end), 6064 OHCI_CSR_READ(sc, OHCI_REG_IntEventSet)); 6065 } else { 6066 /* All the data gone */ 6067 itc->itc_buf_start 6068 = itc->itc_buf_end 6069 = itc->itc_buf_linkend 6070 = &itc->itc_buf[0]; 6071 printf("fwohci_it_intr: all packets gone\n"); 6072 } 6073 6074 itc->itc_flags &= ~ITC_FLAGS_RUN; 6075 6076 OHCI_SYNC_TX_DMA_WRITE(sc, itc->itc_num, 6077 OHCI_SUBREG_ContextControlClear, 0xffffffff); 6078 OHCI_SYNC_TX_DMA_WRITE(sc, itc->itc_num, 6079 OHCI_SUBREG_CommandPtr, 0); 6080 OHCI_SYNC_TX_DMA_WRITE(sc, itc->itc_num, 6081 OHCI_SUBREG_ContextControlClear, 0x1f); 6082 6083 /* send message */ 6084 if (itc->itc_waitchan != NULL) { 6085 wakeup((void *)itc->itc_waitchan); 6086 } 6087 6088 return; 6089 } 6090 6091 #if 0 6092 /* unlink old buffers */ 6093 newstartbuf = &itc->itc_buf[scratchval]; 6094 6095 itd = (struct fwohci_it_dmabuf *)itc->itc_buf_start; 6096 itc->itc_buf_start = newstartbuf; 6097 while (itd != newstartbuf) { 6098 itc->itc_outpkt += itd->itd_npacket; 6099 fwohci_itd_unlink(itd); 6100 INC_BUF(itc, itd); 6101 --itc->itc_buf_cnt; 6102 DPRINTF(("<buf cnt %d>\n", itc->itc_buf_cnt)); 6103 } 6104 #endif 6105 6106 /* sanity check */ 6107 { 6108 int startidx, endidx, linkendidx; 6109 6110 startidx = itc->itc_buf_start->itd_num; 6111 endidx = itc->itc_buf_end->itd_num; 6112 linkendidx = itc->itc_buf_linkend->itd_num; 6113 6114 if (startidx < endidx) { 6115 if (linkendidx < startidx 6116 || endidx < linkendidx) { 6117 printf("funny, linkend is not between start " 6118 "and end [%d, %d]: %d\n", 6119 startidx, endidx, linkendidx); 6120 } 6121 } else if (startidx > endidx) { 6122 if (linkendidx < startidx 6123 && endidx < linkendidx) { 6124 printf("funny, linkend is not between start " 6125 "and end [%d, %d]: %d\n", 6126 startidx, endidx, linkendidx); 6127 } 6128 } else { 6129 if (linkendidx != startidx) { 6130 printf("funny, linkend is not between start " 6131 "and end [%d, %d]: %d\n", 6132 startidx, endidx, linkendidx); 6133 } 6134 6135 } 6136 } 6137 6138 /* link if some valid DMA buffers exist */ 6139 if (itc->itc_buf_cnt > 1 6140 && itc->itc_buf_linkend != itc->itc_buf_end) { 6141 struct fwohci_it_dmabuf *itdprev; 6142 int i; 6143 6144 DPRINTF(("CTX %d: start linkend dataend bufs %d, %d, %d, %d\n", 6145 itc->itc_num, 6146 itc->itc_buf_start->itd_num, 6147 itc->itc_buf_linkend->itd_num, 6148 itc->itc_buf_end->itd_num, 6149 itc->itc_buf_cnt)); 6150 6151 itd = itdprev = itc->itc_buf_linkend; 6152 INC_BUF(itc, itd); 6153 6154 #if 0 6155 if (fwohci_itd_isfilled(itd) || itc->itc_buf_cnt == 2) { 6156 while (itdprev != itc->itc_buf_end) { 6157 6158 if (fwohci_itd_link(itdprev, itd)) { 6159 break; 6160 } 6161 6162 itdprev = itd; 6163 INC_BUF(itc, itd); 6164 } 6165 itc->itc_buf_linkend = itdprev; 6166 } 6167 #endif 6168 i = 0; 6169 while (itdprev != itc->itc_buf_end) { 6170 if (!fwohci_itd_isfilled(itd) && itc->itc_buf_cnt > 2) { 6171 break; 6172 } 6173 6174 if (fwohci_itd_link(itdprev, itd)) { 6175 break; 6176 } 6177 6178 itdprev = itd; 6179 INC_BUF(itc, itd); 6180 6181 itc->itc_buf_linkend = itdprev; 6182 ++i; 6183 } 6184 6185 if (i > 0) { 6186 DPRINTF(("CTX %d: start linkend dataend bufs %d, %d, %d, %d\n", 6187 itc->itc_num, 6188 itc->itc_buf_start->itd_num, 6189 itc->itc_buf_linkend->itd_num, 6190 itc->itc_buf_end->itd_num, 6191 itc->itc_buf_cnt)); 6192 } 6193 } else { 6194 struct fwohci_it_dmabuf *le; 6195 6196 le = itc->itc_buf_linkend; 6197 6198 printf("CTX %d: start linkend dataend bufs %d, %d, %d, %d no buffer added\n", 6199 itc->itc_num, 6200 itc->itc_buf_start->itd_num, 6201 itc->itc_buf_linkend->itd_num, 6202 itc->itc_buf_end->itd_num, 6203 itc->itc_buf_cnt); 6204 printf("\tlast descriptor %s %04x %08x\n", 6205 le->itd_lastdesc->fd_flags & OHCI_DESC_INTR_ALWAYS ? "intr" : "", 6206 le->itd_lastdesc->fd_flags, 6207 le->itd_lastdesc->fd_branch); 6208 } 6209 6210 /* send message */ 6211 if (itc->itc_waitchan != NULL) { 6212 /* */ 6213 wakeup((void *)itc->itc_waitchan); 6214 } 6215 } 6216 6217 6218 6219 /* 6220 * int fwohci_itd_construct(struct fwohci_it_ctx *itc, 6221 * struct fwohci_it_dmabuf *itd, int num, 6222 * struct fwohci_desc *desc, bus_addr_t phys, 6223 * int descsize, int maxsize, paddr_t scratch) 6224 * 6225 * 6226 * 6227 */ 6228 int 6229 fwohci_itd_construct(struct fwohci_it_ctx *itc, struct fwohci_it_dmabuf *itd, 6230 int num, struct fwohci_desc *desc, bus_addr_t phys, int descsize, 6231 int maxsize, paddr_t scratch) 6232 { 6233 const char *xname = itc->itc_sc->sc_sc1394.sc1394_dev.dv_xname; 6234 struct fwohci_desc *fd; 6235 struct fwohci_desc *descend; 6236 int npkt; 6237 int bufno = 0; /* DMA segment */ 6238 bus_size_t bufused = 0; /* offset in a DMA segment */ 6239 int roundsize; 6240 int tag = itc->itc_tag; 6241 int ch = itc->itc_channel; 6242 6243 itd->itd_ctx = itc; 6244 itd->itd_num = num; 6245 6246 if (descsize > 1024*3) { 6247 printf("%s: fwohci_itd_construct[%d] descsize %d too big\n", 6248 xname, num, descsize); 6249 return -1; 6250 } 6251 6252 itd->itd_desc = desc; 6253 itd->itd_descsize = descsize; 6254 itd->itd_desc_phys = phys; 6255 6256 itd->itd_lastdesc = desc; 6257 itd->itd_npacket = 0; 6258 6259 printf("%s: fwohci_itd_construct[%d] desc %p descsize %d, maxsize %d\n", 6260 xname, itd->itd_num, itd->itd_desc, itd->itd_descsize, maxsize); 6261 6262 if (descsize < 4) { 6263 /* too small descriptor array. at least 4 */ 6264 return -1; 6265 } 6266 6267 /* count up how many packet can handle */ 6268 itd->itd_maxpacket = (descsize - 1)/3; 6269 6270 /* rounding up to power of 2. minimum 16 */ 6271 roundsize = 16; 6272 for (roundsize = 16; roundsize < maxsize; roundsize <<= 1); 6273 itd->itd_maxsize = roundsize; 6274 6275 printf("\t\tdesc%d [%x, %lx]\n", itd->itd_num, 6276 (u_int32_t)phys, 6277 (unsigned long)((u_int32_t)phys 6278 + (itd->itd_maxpacket*3 + 1)*sizeof(struct fwohci_desc))); 6279 printf("%s: fwohci_itd_construct[%d] npkt %d maxsize round up to %d\n", 6280 xname, itd->itd_num, itd->itd_maxpacket, itd->itd_maxsize); 6281 6282 /* obtain DMA buffer */ 6283 if (fwohci_itd_dmabuf_alloc(itd)) { 6284 /* cannot allocate memory for DMA buffer */ 6285 return -1; 6286 } 6287 6288 /* 6289 * make descriptor chain 6290 * 6291 * First descriptor group has a STORE_VALUE, OUTPUT_IMMEDIATE 6292 * and OUTPUT_LAST descriptors Second and after that, a 6293 * descriptor group has an OUTPUT_IMMEDIATE and an OUTPUT_LAST 6294 * descriptor. 6295 */ 6296 descend = desc + descsize; 6297 6298 /* set store value descriptor for 1st descriptor group */ 6299 desc->fd_flags = OHCI_DESC_STORE_VALUE; 6300 desc->fd_reqcount = num; /* write number of DMA buffer class */ 6301 desc->fd_data = scratch; /* at physical memory 'scratch' */ 6302 desc->fd_branch = 0; 6303 desc->fd_status = desc->fd_rescount = 0; 6304 6305 itd->itd_store = desc; 6306 itd->itd_store_phys = phys; 6307 6308 ++desc; 6309 phys += 16; 6310 6311 npkt = 0; 6312 /* make OUTPUT_DESC chain for packets */ 6313 for (fd = desc; fd + 2 < descend; fd += 3, ++npkt) { 6314 struct fwohci_desc *fi = fd; 6315 struct fwohci_desc *fl = fd + 2; 6316 u_int32_t *fi_data = (u_int32_t *)(fd + 1); 6317 6318 #if 0 6319 if (npkt > itd->itd_maxpacket - 3) { 6320 printf("%s: %3d fi fl %p %p\n", xname, npkt, fi,fl); 6321 } 6322 #endif 6323 6324 fi->fd_reqcount = 8; /* data size for OHCI command */ 6325 fi->fd_flags = OHCI_DESC_IMMED; 6326 fi->fd_data = 0; 6327 fi->fd_branch = 0; /* branch for error */ 6328 fi->fd_status = fi->fd_rescount = 0; 6329 6330 /* channel and tag is unchanged */ 6331 *fi_data = OHCI_ITHEADER_VAL(TAG, tag) | 6332 OHCI_ITHEADER_VAL(CHAN, ch) | 6333 OHCI_ITHEADER_VAL(TCODE, IEEE1394_TCODE_STREAM_DATA); 6334 *++fi_data = 0; 6335 *++fi_data = 0; 6336 *++fi_data = 0; 6337 6338 fl->fd_flags = OHCI_DESC_OUTPUT | OHCI_DESC_LAST | 6339 OHCI_DESC_BRANCH; 6340 fl->fd_branch = 6341 (phys + sizeof(struct fwohci_desc)*(npkt + 1)*3) | 0x03; 6342 fl->fd_status = fl->fd_rescount = 0; 6343 6344 #ifdef FW_DEBUG 6345 if (npkt > itd->itd_maxpacket - 3) { 6346 DPRINTF(("%s: %3d fi fl fl branch %p %p 0x%x\n", 6347 xname, npkt, fi, fl, (int)fl->fd_branch)); 6348 } 6349 #endif 6350 6351 /* physical addr to data? */ 6352 fl->fd_data = 6353 (u_int32_t)((itd->itd_seg[bufno].ds_addr + bufused)); 6354 bufused += itd->itd_maxsize; 6355 if (bufused > itd->itd_seg[bufno].ds_len) { 6356 bufused = 0; 6357 if (++bufno == itd->itd_nsegs) { 6358 /* fail */ 6359 break; 6360 } 6361 } 6362 } 6363 6364 #if 0 6365 if (itd->itd_num == 0) { 6366 u_int32_t *fdp; 6367 u_int32_t adr; 6368 int i = 0; 6369 6370 fdp = (u_int32_t *)itd->itd_desc; 6371 adr = (u_int32_t)itd->itd_desc_phys; /* XXX */ 6372 6373 printf("fwohci_itd_construct: audit DMA desc chain. %d\n", 6374 itd->itd_maxpacket); 6375 for (i = 0; i < itd->itd_maxpacket*12 + 4; ++i) { 6376 if (i % 4 == 0) { 6377 printf("\n%x:", adr + 4*i); 6378 } 6379 printf(" %08x", fdp[i]); 6380 } 6381 printf("\n"); 6382 6383 } 6384 #endif 6385 /* last branch should be 0 */ 6386 --fd; 6387 fd->fd_branch = 0; 6388 6389 printf("%s: pkt %d %d maxdesc %p\n", 6390 xname, npkt, itd->itd_maxpacket, descend); 6391 6392 return 0; 6393 } 6394 6395 void 6396 fwohci_itd_destruct(struct fwohci_it_dmabuf *itd) 6397 { 6398 const char *xname = itd->itd_ctx->itc_sc->sc_sc1394.sc1394_dev.dv_xname; 6399 6400 printf("%s: fwohci_itd_destruct %d\n", xname, itd->itd_num); 6401 6402 fwohci_itd_dmabuf_free(itd); 6403 } 6404 6405 6406 /* 6407 * static int fwohci_itd_dmabuf_alloc(struct fwohci_it_dmabuf *itd) 6408 * 6409 * This function allocates DMA memory for fwohci_it_dmabuf. This 6410 * function will return 0 when it succeeds and return non-zero 6411 * value when it fails. 6412 */ 6413 static int 6414 fwohci_itd_dmabuf_alloc(struct fwohci_it_dmabuf *itd) 6415 { 6416 const char *xname = itd->itd_ctx->itc_sc->sc_sc1394.sc1394_dev.dv_xname; 6417 bus_dma_tag_t dmat = itd->itd_ctx->itc_sc->sc_dmat; 6418 6419 int dmasize = itd->itd_maxsize * itd->itd_maxpacket; 6420 int error; 6421 6422 DPRINTF(("%s: fwohci_itd_dmabuf_alloc[%d] dmasize %d maxpkt %d\n", 6423 xname, itd->itd_num, dmasize, itd->itd_maxpacket)); 6424 6425 if ((error = bus_dmamem_alloc(dmat, dmasize, PAGE_SIZE, 0, 6426 itd->itd_seg, FWOHCI_MAX_ITDATASEG, &itd->itd_nsegs, 0)) != 0) { 6427 printf("%s: unable to allocate data buffer, error = %d\n", 6428 xname, error); 6429 goto fail_0; 6430 } 6431 6432 /* checking memory range */ 6433 #ifdef FW_DEBUG 6434 { 6435 int loop; 6436 6437 for (loop = 0; loop < itd->itd_nsegs; ++loop) { 6438 DPRINTF(("\t%.2d: 0x%lx - 0x%lx\n", loop, 6439 (long)itd->itd_seg[loop].ds_addr, 6440 (long)itd->itd_seg[loop].ds_addr 6441 + (long)itd->itd_seg[loop].ds_len - 1)); 6442 } 6443 } 6444 #endif 6445 6446 if ((error = bus_dmamem_map(dmat, itd->itd_seg, itd->itd_nsegs, 6447 dmasize, (caddr_t *)&itd->itd_buf, 6448 BUS_DMA_COHERENT | BUS_DMA_WAITOK)) != 0) { 6449 printf("%s: unable to map data buffer, error = %d\n", 6450 xname, error); 6451 goto fail_1; 6452 } 6453 6454 DPRINTF(("fwohci_it_data_alloc[%d]: bus_dmamem_map addr %p\n", 6455 itd->itd_num, itd->itd_buf)); 6456 6457 if ((error = bus_dmamap_create(dmat, /*chunklen*/dmasize, 6458 itd->itd_nsegs, dmasize, 0, BUS_DMA_WAITOK, 6459 &itd->itd_dmamap)) != 0) { 6460 printf("%s: unable to create data buffer DMA map, " 6461 "error = %d\n", xname, error); 6462 goto fail_2; 6463 } 6464 6465 DPRINTF(("fwohci_it_data_alloc: bus_dmamem_create\n")); 6466 6467 if ((error = bus_dmamap_load(dmat, itd->itd_dmamap, 6468 itd->itd_buf, dmasize, NULL, BUS_DMA_WAITOK)) != 0) { 6469 printf("%s: unable to load data buffer DMA map, error = %d\n", 6470 xname, error); 6471 goto fail_3; 6472 } 6473 6474 DPRINTF(("fwohci_itd_dmabuf_alloc: load DMA memory vm %p\n", 6475 itd->itd_buf)); 6476 DPRINTF(("\tmapsize %ld nsegs %d\n", 6477 (long)itd->itd_dmamap->dm_mapsize, itd->itd_dmamap->dm_nsegs)); 6478 6479 #ifdef FW_DEBUG 6480 { 6481 int loop; 6482 6483 for (loop = 0; loop < itd->itd_dmamap->dm_nsegs; ++loop) { 6484 DPRINTF(("\t%.2d: 0x%lx - 0x%lx\n", loop, 6485 (long)itd->itd_dmamap->dm_segs[loop].ds_addr, 6486 (long)itd->itd_dmamap->dm_segs[loop].ds_addr + 6487 (long)itd->itd_dmamap->dm_segs[loop].ds_len - 1)); 6488 } 6489 } 6490 #endif 6491 6492 return 0; 6493 6494 fail_3: 6495 bus_dmamap_destroy(dmat, itd->itd_dmamap); 6496 fail_2: 6497 bus_dmamem_unmap(dmat, (caddr_t)itd->itd_buf, dmasize); 6498 fail_1: 6499 bus_dmamem_free(dmat, itd->itd_seg, itd->itd_nsegs); 6500 fail_0: 6501 itd->itd_nsegs = 0; 6502 itd->itd_maxpacket = 0; 6503 return error; 6504 } 6505 6506 /* 6507 * static void fwohci_itd_dmabuf_free(struct fwohci_it_dmabuf *itd) 6508 * 6509 * This function will release memory resource allocated by 6510 * fwohci_itd_dmabuf_alloc(). 6511 */ 6512 static void 6513 fwohci_itd_dmabuf_free(struct fwohci_it_dmabuf *itd) 6514 { 6515 bus_dma_tag_t dmat = itd->itd_ctx->itc_sc->sc_dmat; 6516 int dmasize = itd->itd_maxsize * itd->itd_maxpacket; 6517 6518 bus_dmamap_destroy(dmat, itd->itd_dmamap); 6519 bus_dmamem_unmap(dmat, (caddr_t)itd->itd_buf, dmasize); 6520 bus_dmamem_free(dmat, itd->itd_seg, itd->itd_nsegs); 6521 6522 itd->itd_nsegs = 0; 6523 itd->itd_maxpacket = 0; 6524 } 6525 6526 6527 6528 /* 6529 * int fwohci_itd_link(struct fwohci_it_dmabuf *itd, 6530 * struct fwohci_it_dmabuf *itdc) 6531 * 6532 * This function will concatinate two descriptor chains in dmabuf 6533 * itd and itdc. The descriptor link in itdc follows one in itd. 6534 * This function will move interrrupt packet from the end of itd 6535 * to the top of itdc. 6536 * 6537 * This function will return 0 whel this funcion suceeds. If an 6538 * error happens, return a negative value. 6539 */ 6540 int 6541 fwohci_itd_link(struct fwohci_it_dmabuf *itd, struct fwohci_it_dmabuf *itdc) 6542 { 6543 struct fwohci_desc *fd1, *fdc; 6544 6545 if (itdc->itd_lastdesc == itdc->itd_desc) { 6546 /* no valid data */ 6547 printf("fwohci_itd_link: no data\n"); 6548 return -1; 6549 } 6550 6551 if (itdc->itd_flags & ITD_FLAGS_LOCK) { 6552 /* used already */ 6553 printf("fwohci_itd_link: link locked\n"); 6554 return -1; 6555 } 6556 itdc->itd_flags |= ITD_FLAGS_LOCK; 6557 /* for the first one */ 6558 itd->itd_flags |= ITD_FLAGS_LOCK; 6559 6560 DPRINTF(("linking %d after %d: add %d pkts\n", 6561 itdc->itd_num, itd->itd_num, itdc->itd_npacket)); 6562 6563 /* XXX: should sync cache */ 6564 6565 fd1 = itd->itd_lastdesc; 6566 fdc = itdc->itd_desc + 3; /* OUTPUT_LAST in the first descriptor */ 6567 6568 /* sanity check */ 6569 #define OUTPUT_LAST_DESC (OHCI_DESC_OUTPUT | OHCI_DESC_LAST | OHCI_DESC_BRANCH) 6570 if ((fd1->fd_flags & OUTPUT_LAST_DESC) != OUTPUT_LAST_DESC) { 6571 printf("funny! not OUTPUT_LAST descriptor %p\n", fd1); 6572 } 6573 if (itd->itd_lastdesc - itd->itd_desc != 3 * itd->itd_npacket) { 6574 printf("funny! packet number inconsistency %ld <=> %ld\n", 6575 (long)(itd->itd_lastdesc - itd->itd_desc), 6576 (long)(3*itd->itd_npacket)); 6577 } 6578 6579 fd1->fd_flags &= ~OHCI_DESC_INTR_ALWAYS; 6580 fdc->fd_flags |= OHCI_DESC_INTR_ALWAYS; 6581 fd1->fd_branch = itdc->itd_desc_phys | 4; 6582 6583 itdc->itd_lastdesc->fd_flags |= OHCI_DESC_INTR_ALWAYS; 6584 /* save branch addr of lastdesc and substitute 0 to it */ 6585 itdc->itd_savedbranch = itdc->itd_lastdesc->fd_branch; 6586 itdc->itd_lastdesc->fd_branch = 0; 6587 6588 DPRINTF(("%s: link (%d %d), add pkt %d/%d branch 0x%x next saved 0x%x\n", 6589 itd->itd_ctx->itc_sc->sc_sc1394.sc1394_dev.dv_xname, 6590 itd->itd_num, itdc->itd_num, 6591 itdc->itd_npacket, itdc->itd_maxpacket, 6592 (int)fd1->fd_branch, (int)itdc->itd_savedbranch)); 6593 6594 /* XXX: should sync cache */ 6595 6596 return 0; 6597 } 6598 6599 6600 /* 6601 * int fwohci_itd_unlink(struct fwohci_it_dmabuf *itd) 6602 * 6603 * This function will unlink the descriptor chain from valid link 6604 * of descriptors. The target descriptor is specified by the 6605 * arguent. 6606 */ 6607 int 6608 fwohci_itd_unlink(struct fwohci_it_dmabuf *itd) 6609 { 6610 struct fwohci_desc *fd; 6611 6612 /* XXX: should sync cache */ 6613 6614 fd = itd->itd_lastdesc; 6615 6616 fd->fd_branch = itd->itd_savedbranch; 6617 DPRINTF(("%s: unlink buf %d branch restored 0x%x\n", 6618 itd->itd_ctx->itc_sc->sc_sc1394.sc1394_dev.dv_xname, 6619 itd->itd_num, (int)fd->fd_branch)); 6620 6621 fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS; 6622 itd->itd_lastdesc = itd->itd_desc; 6623 6624 fd = itd->itd_desc + 3; /* 1st OUTPUT_LAST */ 6625 fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS; 6626 6627 /* XXX: should sync cache */ 6628 6629 itd->itd_npacket = 0; 6630 itd->itd_lastdesc = itd->itd_desc; 6631 itd->itd_flags &= ~ITD_FLAGS_LOCK; 6632 6633 return 0; 6634 } 6635 6636 6637 /* 6638 * static int fwohci_itd_writedata(struct fwohci_it_dmabuf *, int ndata, 6639 * struct ieee1394_it_datalist *); 6640 * 6641 * This function will return the number of written data, or 6642 * negative value if an error happens 6643 */ 6644 int 6645 fwohci_itd_writedata(struct fwohci_it_dmabuf *itd, int ndata, 6646 struct ieee1394_it_datalist *itdata) 6647 { 6648 int writepkt; 6649 int i; 6650 u_int8_t *p; 6651 struct fwohci_desc *fd; 6652 u_int32_t *fd_idata; 6653 const int dspace = 6654 itd->itd_maxpacket - itd->itd_npacket < ndata ? 6655 itd->itd_maxpacket - itd->itd_npacket : ndata; 6656 6657 if (itd->itd_flags & ITD_FLAGS_LOCK || dspace == 0) { 6658 /* it is locked: cannot write anything */ 6659 if (itd->itd_flags & ITD_FLAGS_LOCK) { 6660 DPRINTF(("fwohci_itd_writedata: buf %d lock flag %s," 6661 " dspace %d\n", 6662 itd->itd_num, 6663 itd->itd_flags & ITD_FLAGS_LOCK ? "ON" : "OFF", 6664 dspace)); 6665 return 0; /* not an error */ 6666 } 6667 } 6668 6669 /* sanity check */ 6670 if (itd->itd_maxpacket < itd->itd_npacket) { 6671 printf("fwohci_itd_writedata: funny! # pkt > maxpkt" 6672 "%d %d\n", itd->itd_npacket, itd->itd_maxpacket); 6673 } 6674 6675 p = itd->itd_buf + itd->itd_maxsize * itd->itd_npacket; 6676 fd = itd->itd_lastdesc; 6677 6678 DPRINTF(("fwohci_itd_writedata(%d[%p], %d, 0x%p) invoked:\n", 6679 itd->itd_num, itd, ndata, itdata)); 6680 6681 for (writepkt = 0; writepkt < dspace; ++writepkt) { 6682 u_int8_t *p1 = p; 6683 int cpysize; 6684 int totalsize = 0; 6685 6686 DPRINTF(("writing %d ", writepkt)); 6687 6688 for (i = 0; i < 4; ++i) { 6689 switch (itdata->it_cmd[i]&IEEE1394_IT_CMD_MASK) { 6690 case IEEE1394_IT_CMD_IMMED: 6691 memcpy(p1, &itdata->it_u[i].id_data, 8); 6692 p1 += 8; 6693 totalsize += 8; 6694 break; 6695 case IEEE1394_IT_CMD_PTR: 6696 cpysize = itdata->it_cmd[i]&IEEE1394_IT_CMD_SIZE; 6697 DPRINTF(("fwohci_itd_writedata: cpy %d %p\n", 6698 cpysize, itdata->it_u[i].id_addr)); 6699 if (totalsize + cpysize > itd->itd_maxsize) { 6700 /* error: too big size */ 6701 break; 6702 } 6703 memcpy(p1, itdata->it_u[i].id_addr, cpysize); 6704 totalsize += cpysize; 6705 break; 6706 case IEEE1394_IT_CMD_NOP: 6707 break; 6708 default: 6709 /* unknown command */ 6710 break; 6711 } 6712 } 6713 6714 /* only for DV test */ 6715 if (totalsize != 488) { 6716 printf("error: totalsize %d at %d\n", 6717 totalsize, writepkt); 6718 } 6719 6720 DPRINTF(("totalsize %d ", totalsize)); 6721 6722 /* fill iso command in OUTPUT_IMMED descriptor */ 6723 6724 /* XXX: sync cache */ 6725 fd += 2; /* next to first descriptor */ 6726 fd_idata = (u_int32_t *)fd; 6727 6728 /* 6729 * Umm, should tag, channel and tcode be written 6730 * previously in itd_construct? 6731 */ 6732 #if 0 6733 *fd_idata = OHCI_ITHEADER_VAL(TAG, tag) | 6734 OHCI_ITHEADER_VAL(CHAN, ch) | 6735 OHCI_ITHEADER_VAL(TCODE, IEEE1394_TCODE_STREAM_DATA); 6736 #endif 6737 *++fd_idata = totalsize << 16; 6738 6739 /* fill data in OUTPUT_LAST descriptor */ 6740 ++fd; 6741 /* intr check... */ 6742 if (fd->fd_flags & OHCI_DESC_INTR_ALWAYS) { 6743 printf("uncleared INTR flag in desc %ld\n", 6744 (long)(fd - itd->itd_desc - 1)/3); 6745 } 6746 fd->fd_flags &= ~OHCI_DESC_INTR_ALWAYS; 6747 6748 if ((fd - itd->itd_desc - 1)/3 != itd->itd_maxpacket - 1) { 6749 u_int32_t bcal; 6750 6751 bcal = (fd - itd->itd_desc + 1)*sizeof(struct fwohci_desc) + (u_int32_t)itd->itd_desc_phys; 6752 if (bcal != (fd->fd_branch & 0xfffffff0)) { 6753 6754 printf("uum, branch differ at %d, %x %x %ld/%d\n", 6755 itd->itd_num, 6756 bcal, 6757 fd->fd_branch, 6758 (long)((fd - itd->itd_desc - 1)/3), 6759 itd->itd_maxpacket); 6760 } 6761 } else { 6762 /* the last pcaket */ 6763 if (fd->fd_branch != 0) { 6764 printf("uum, branch differ at %d, %x %x %ld/%d\n", 6765 itd->itd_num, 6766 0, 6767 fd->fd_branch, 6768 (long)((fd - itd->itd_desc - 1)/3), 6769 itd->itd_maxpacket); 6770 } 6771 } 6772 6773 /* sanity check */ 6774 if (fd->fd_flags != OUTPUT_LAST_DESC) { 6775 printf("fwohci_itd_writedata: dmabuf %d desc inconsistent %d\n", 6776 itd->itd_num, writepkt + itd->itd_npacket); 6777 break; 6778 } 6779 fd->fd_reqcount = totalsize; 6780 /* XXX: sync cache */ 6781 6782 ++itdata; 6783 p += itd->itd_maxsize; 6784 } 6785 6786 DPRINTF(("loop start %d, %d times %d\n", 6787 itd->itd_npacket, dspace, writepkt)); 6788 6789 itd->itd_npacket += writepkt; 6790 itd->itd_lastdesc = fd; 6791 6792 return writepkt; 6793 } 6794 6795 6796 6797 6798 6799 int 6800 fwohci_itd_isfilled(struct fwohci_it_dmabuf *itd) 6801 { 6802 6803 return itd->itd_npacket*2 > itd->itd_maxpacket ? 1 : 0; 6804 } 6805