2 * Copyright (c) 2003 Hidetoshi Shimokawa
3 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the acknowledgement as bellow:
17 * This product includes software developed by K. Kobayashi and H. Shimokawa
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
38 #include <sys/param.h>
39 #include <sys/systm.h>
41 #include <sys/malloc.h>
42 #include <sys/sockio.h>
43 #include <sys/sysctl.h>
45 #include <sys/kernel.h>
47 #include <sys/endian.h>
50 #include <machine/bus.h>
51 #include <machine/md_var.h>
53 #include <dev/firewire/firewire.h>
54 #include <dev/firewire/firewirereg.h>
55 #include <dev/firewire/fwdma.h>
56 #include <dev/firewire/fwohcireg.h>
57 #include <dev/firewire/fwohcivar.h>
58 #include <dev/firewire/firewire_phy.h>
62 static int nocyclemaster;
63 int firewire_phydma_enable = 1;
64 SYSCTL_DECL(_hw_firewire);
65 SYSCTL_INT(_hw_firewire, OID_AUTO, nocyclemaster, CTLFLAG_RWTUN,
66 &nocyclemaster, 0, "Do not send cycle start packets");
67 SYSCTL_INT(_hw_firewire, OID_AUTO, phydma_enable, CTLFLAG_RWTUN,
68 &firewire_phydma_enable, 0, "Allow physical request DMA from firewire");
70 static char dbcode[16][0x10] = {"OUTM", "OUTL", "INPM", "INPL",
71 "STOR", "LOAD", "NOP ", "STOP",};
73 static char dbkey[8][0x10] = {"ST0", "ST1", "ST2", "ST3",
74 "UNDEF", "REG", "SYS", "DEV"};
75 static char dbcond[4][0x10] = {"NEV", "C=1", "C=0", "ALL"};
76 char fwohcicode[32][0x20]= {
77 "No stat", "Undef", "long", "miss Ack err",
78 "FIFO underrun", "FIFO overrun", "desc err", "data read err",
79 "data write err", "bus reset", "timeout", "tcode err",
80 "Undef", "Undef", "unknown event", "flushed",
81 "Undef" ,"ack complete", "ack pend", "Undef",
82 "ack busy_X", "ack busy_A", "ack busy_B", "Undef",
83 "Undef", "Undef", "Undef", "ack tardy",
84 "Undef", "ack data_err", "ack type_err", ""};
87 extern char *linkspeed[];
88 uint32_t tagbit[4] = {1 << 28, 1 << 29, 1 << 30, 1 << 31};
90 static struct tcode_info tinfo[] = {
91 /* hdr_len block flag valid_response */
92 /* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL, FWTCODE_WRES},
93 /* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_WRES},
94 /* 2 WRES */ {12, FWTI_RES, 0xff},
95 /* 3 XXX */ { 0, 0, 0xff},
96 /* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESQ},
97 /* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESB},
98 /* 6 RRESQ */ {16, FWTI_RES, 0xff},
99 /* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY, 0xff},
100 /* 8 CYCS */ { 0, 0, 0xff},
101 /* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_LRES},
102 /* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR, 0xff},
103 /* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY, 0xff},
104 /* c XXX */ { 0, 0, 0xff},
105 /* d XXX */ { 0, 0, 0xff},
106 /* e PHY */ {12, FWTI_REQ, 0xff},
107 /* f XXX */ { 0, 0, 0xff}
117 #define OHCI_WRITE_SIGMASK 0xffff0000
118 #define OHCI_READ_SIGMASK 0xffff0000
120 #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
121 #define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r))
123 static void fwohci_ibr (struct firewire_comm *);
124 static void fwohci_db_init (struct fwohci_softc *, struct fwohci_dbch *);
125 static void fwohci_db_free (struct fwohci_dbch *);
126 static void fwohci_arcv (struct fwohci_softc *, struct fwohci_dbch *, int);
127 static void fwohci_txd (struct fwohci_softc *, struct fwohci_dbch *);
128 static void fwohci_start_atq (struct firewire_comm *);
129 static void fwohci_start_ats (struct firewire_comm *);
130 static void fwohci_start (struct fwohci_softc *, struct fwohci_dbch *);
131 static uint32_t fwphy_wrdata (struct fwohci_softc *, uint32_t, uint32_t);
132 static uint32_t fwphy_rddata (struct fwohci_softc *, uint32_t);
133 static int fwohci_rx_enable (struct fwohci_softc *, struct fwohci_dbch *);
134 static int fwohci_tx_enable (struct fwohci_softc *, struct fwohci_dbch *);
135 static int fwohci_irx_enable (struct firewire_comm *, int);
136 static int fwohci_irx_disable (struct firewire_comm *, int);
137 #if BYTE_ORDER == BIG_ENDIAN
138 static void fwohci_irx_post (struct firewire_comm *, uint32_t *);
140 static int fwohci_itxbuf_enable (struct firewire_comm *, int);
141 static int fwohci_itx_disable (struct firewire_comm *, int);
142 static void fwohci_timeout (void *);
143 static void fwohci_set_intr (struct firewire_comm *, int);
145 static int fwohci_add_rx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int, struct fwdma_alloc *);
146 static int fwohci_add_tx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int);
147 static void dump_db (struct fwohci_softc *, uint32_t);
148 static void print_db (struct fwohcidb_tr *, struct fwohcidb *, uint32_t , uint32_t);
149 static void dump_dma (struct fwohci_softc *, uint32_t);
150 static uint32_t fwohci_cyctimer (struct firewire_comm *);
151 static void fwohci_rbuf_update (struct fwohci_softc *, int);
152 static void fwohci_tbuf_update (struct fwohci_softc *, int);
153 void fwohci_txbufdb (struct fwohci_softc *, int , struct fw_bulkxfer *);
154 static void fwohci_task_busreset(void *, int);
155 static void fwohci_task_sid(void *, int);
156 static void fwohci_task_dma(void *, int);
159 * memory allocated for DMA programs
161 #define DMA_PROG_ALLOC (8 * PAGE_SIZE)
163 #define NDB FWMAXQUEUE
165 #define OHCI_VERSION 0x00
166 #define OHCI_ATRETRY 0x08
167 #define OHCI_CROMHDR 0x18
168 #define OHCI_BUS_OPT 0x20
169 #define OHCI_BUSIRMC (1U << 31)
170 #define OHCI_BUSCMC (1 << 30)
171 #define OHCI_BUSISC (1 << 29)
172 #define OHCI_BUSBMC (1 << 28)
173 #define OHCI_BUSPMC (1 << 27)
174 #define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\
175 OHCI_BUSBMC | OHCI_BUSPMC
177 #define OHCI_EUID_HI 0x24
178 #define OHCI_EUID_LO 0x28
180 #define OHCI_CROMPTR 0x34
181 #define OHCI_HCCCTL 0x50
182 #define OHCI_HCCCTLCLR 0x54
183 #define OHCI_AREQHI 0x100
184 #define OHCI_AREQHICLR 0x104
185 #define OHCI_AREQLO 0x108
186 #define OHCI_AREQLOCLR 0x10c
187 #define OHCI_PREQHI 0x110
188 #define OHCI_PREQHICLR 0x114
189 #define OHCI_PREQLO 0x118
190 #define OHCI_PREQLOCLR 0x11c
191 #define OHCI_PREQUPPER 0x120
192 #define OHCI_PREQUPPER_MAX 0xffff0000
194 #define OHCI_SID_BUF 0x64
195 #define OHCI_SID_CNT 0x68
196 #define OHCI_SID_ERR (1U << 31)
197 #define OHCI_SID_CNT_MASK 0xffc
199 #define OHCI_IT_STAT 0x90
200 #define OHCI_IT_STATCLR 0x94
201 #define OHCI_IT_MASK 0x98
202 #define OHCI_IT_MASKCLR 0x9c
204 #define OHCI_IR_STAT 0xa0
205 #define OHCI_IR_STATCLR 0xa4
206 #define OHCI_IR_MASK 0xa8
207 #define OHCI_IR_MASKCLR 0xac
209 #define OHCI_LNKCTL 0xe0
210 #define OHCI_LNKCTLCLR 0xe4
212 #define OHCI_PHYACCESS 0xec
213 #define OHCI_CYCLETIMER 0xf0
215 #define OHCI_DMACTL(off) (off)
216 #define OHCI_DMACTLCLR(off) (off + 4)
217 #define OHCI_DMACMD(off) (off + 0xc)
218 #define OHCI_DMAMATCH(off) (off + 0x10)
220 #define OHCI_ATQOFF 0x180
221 #define OHCI_ATQCTL OHCI_ATQOFF
222 #define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4)
223 #define OHCI_ATQCMD (OHCI_ATQOFF + 0xc)
224 #define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10)
226 #define OHCI_ATSOFF 0x1a0
227 #define OHCI_ATSCTL OHCI_ATSOFF
228 #define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4)
229 #define OHCI_ATSCMD (OHCI_ATSOFF + 0xc)
230 #define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10)
232 #define OHCI_ARQOFF 0x1c0
233 #define OHCI_ARQCTL OHCI_ARQOFF
234 #define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4)
235 #define OHCI_ARQCMD (OHCI_ARQOFF + 0xc)
236 #define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10)
238 #define OHCI_ARSOFF 0x1e0
239 #define OHCI_ARSCTL OHCI_ARSOFF
240 #define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4)
241 #define OHCI_ARSCMD (OHCI_ARSOFF + 0xc)
242 #define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10)
244 #define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH))
245 #define OHCI_ITCTL(CH) (OHCI_ITOFF(CH))
246 #define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4)
247 #define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc)
249 #define OHCI_IROFF(CH) (0x400 + 0x20 * (CH))
250 #define OHCI_IRCTL(CH) (OHCI_IROFF(CH))
251 #define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4)
252 #define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc)
253 #define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10)
255 d_ioctl_t fwohci_ioctl;
258 * Communication with PHY device
260 /* XXX need lock for phy access */
262 fwphy_wrdata(struct fwohci_softc *sc, uint32_t addr, uint32_t data)
269 fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) |
270 (data << PHYDEV_WRDATA));
271 OWRITE(sc, OHCI_PHYACCESS, fun);
274 return (fwphy_rddata(sc, addr));
278 fwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
280 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
284 #define OHCI_CSR_DATA 0x0c
285 #define OHCI_CSR_COMP 0x10
286 #define OHCI_CSR_CONT 0x14
287 #define OHCI_BUS_MANAGER_ID 0
289 OWRITE(sc, OHCI_CSR_DATA, node);
290 OWRITE(sc, OHCI_CSR_COMP, 0x3f);
291 OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
292 for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
294 bm = OREAD(sc, OHCI_CSR_DATA);
295 if ((bm & 0x3f) == 0x3f)
298 device_printf(sc->fc.dev, "%s: %d->%d (loop=%d)\n",
299 __func__, bm, node, i);
304 fwphy_rddata(struct fwohci_softc *sc, u_int addr)
310 #define MAX_RETRY 100
312 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
313 fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
314 OWRITE(sc, OHCI_PHYACCESS, fun);
315 for (i = 0; i < MAX_RETRY; i++) {
316 fun = OREAD(sc, OHCI_PHYACCESS);
317 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
321 if (i >= MAX_RETRY) {
323 device_printf(sc->fc.dev, "%s: failed(1).\n", __func__);
324 if (++retry < MAX_RETRY) {
329 /* Make sure that SCLK is started */
330 stat = OREAD(sc, FWOHCI_INTSTAT);
331 if ((stat & OHCI_INT_REG_FAIL) != 0 ||
332 ((fun >> PHYDEV_REGADDR) & 0xf) != addr) {
334 device_printf(sc->fc.dev, "%s: failed(2).\n", __func__);
335 if (++retry < MAX_RETRY) {
340 if (firewire_debug > 1 || retry >= MAX_RETRY)
341 device_printf(sc->fc.dev,
342 "%s:: 0x%x loop=%d, retry=%d\n",
343 __func__, addr, i, retry);
345 return ((fun >> PHYDEV_RDDATA) & 0xff);
348 /* Device specific ioctl. */
350 fwohci_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
352 struct firewire_softc *sc;
353 struct fwohci_softc *fc;
354 int unit = DEV2UNIT(dev);
356 struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data;
357 uint32_t *dmach = (uint32_t *) data;
359 sc = devclass_get_softc(firewire_devclass, unit);
363 fc = (struct fwohci_softc *)sc->fc;
370 #define OHCI_MAX_REG 0x800
371 if (reg->addr <= OHCI_MAX_REG) {
372 OWRITE(fc, reg->addr, reg->data);
373 reg->data = OREAD(fc, reg->addr);
379 if (reg->addr <= OHCI_MAX_REG) {
380 reg->data = OREAD(fc, reg->addr);
385 /* Read DMA descriptors for debug */
387 if (*dmach <= OHCI_MAX_DMA_CH) {
388 dump_dma(fc, *dmach);
394 /* Read/Write Phy registers */
395 #define OHCI_MAX_PHY_REG 0xf
396 case FWOHCI_RDPHYREG:
397 if (reg->addr <= OHCI_MAX_PHY_REG)
398 reg->data = fwphy_rddata(fc, reg->addr);
402 case FWOHCI_WRPHYREG:
403 if (reg->addr <= OHCI_MAX_PHY_REG)
404 reg->data = fwphy_wrdata(fc, reg->addr, reg->data);
416 fwohci_probe_phy(struct fwohci_softc *sc, device_t dev)
422 * probe PHY parameters
423 * 0. to prove PHY version, whether compliance of 1394a.
424 * 1. to probe maximum speed supported by the PHY and
425 * number of port supported by core-logic.
426 * It is not actually available port on your PC .
428 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
431 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
433 if ((reg >> 5) != 7) {
434 sc->fc.mode &= ~FWPHYASYST;
435 sc->fc.nport = reg & FW_PHY_NP;
436 sc->fc.speed = reg & FW_PHY_SPD >> 6;
437 if (sc->fc.speed > MAX_SPEED) {
438 device_printf(dev, "invalid speed %d (fixed to %d).\n",
439 sc->fc.speed, MAX_SPEED);
440 sc->fc.speed = MAX_SPEED;
443 "Phy 1394 only %s, %d ports.\n",
444 linkspeed[sc->fc.speed], sc->fc.nport);
446 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
447 sc->fc.mode |= FWPHYASYST;
448 sc->fc.nport = reg & FW_PHY_NP;
449 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
450 if (sc->fc.speed > MAX_SPEED) {
451 device_printf(dev, "invalid speed %d (fixed to %d).\n",
452 sc->fc.speed, MAX_SPEED);
453 sc->fc.speed = MAX_SPEED;
456 "Phy 1394a available %s, %d ports.\n",
457 linkspeed[sc->fc.speed], sc->fc.nport);
459 /* check programPhyEnable */
460 reg2 = fwphy_rddata(sc, 5);
462 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
463 #else /* XXX force to enable 1394a */
468 "Enable 1394a Enhancements\n");
471 /* set aPhyEnhanceEnable */
472 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
473 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
478 reg2 = fwphy_wrdata(sc, 5, reg2);
481 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
482 if ((reg >> 5) == 7) {
483 reg = fwphy_rddata(sc, 4);
485 fwphy_wrdata(sc, 4, reg);
486 reg = fwphy_rddata(sc, 4);
493 fwohci_reset(struct fwohci_softc *sc, device_t dev)
495 int i, max_rec, speed;
497 struct fwohcidb_tr *db_tr;
499 /* Disable interrupts */
500 OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
502 /* Now stopping all DMA channels */
503 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
504 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
505 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
506 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
508 OWRITE(sc, OHCI_IR_MASKCLR, ~0);
509 for (i = 0; i < sc->fc.nisodma; i++) {
510 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
511 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
514 /* FLUSH FIFO and reset Transmitter/Receiver */
515 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
517 device_printf(dev, "resetting OHCI...");
519 while (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
520 if (i++ > 100) break;
524 printf("done (loop=%d)\n", i);
527 fwohci_probe_phy(sc, dev);
530 reg = OREAD(sc, OHCI_BUS_OPT);
531 reg2 = reg | OHCI_BUSFNC;
532 max_rec = (reg & 0x0000f000) >> 12;
533 speed = (reg & 0x00000007);
534 device_printf(dev, "Link %s, max_rec %d bytes.\n",
535 linkspeed[speed], MAXREC(max_rec));
536 /* XXX fix max_rec */
537 sc->fc.maxrec = sc->fc.speed + 8;
538 if (max_rec != sc->fc.maxrec) {
539 reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12);
540 device_printf(dev, "max_rec %d -> %d\n",
541 MAXREC(max_rec), MAXREC(sc->fc.maxrec));
544 device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
545 OWRITE(sc, OHCI_BUS_OPT, reg2);
547 /* Initialize registers */
548 OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
549 OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr);
550 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
551 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
552 OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr);
553 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
556 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
558 /* Force to start async RX DMA */
559 sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING;
560 sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING;
561 fwohci_rx_enable(sc, &sc->arrq);
562 fwohci_rx_enable(sc, &sc->arrs);
564 /* Initialize async TX */
565 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
566 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
569 OWRITE(sc, FWOHCI_RETRY,
570 /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */
571 (0xffff << 16) | (0x0f << 8) | (0x0f << 4) | 0x0f);
573 sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq);
574 sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq);
575 sc->atrq.bottom = sc->atrq.top;
576 sc->atrs.bottom = sc->atrs.top;
578 for (i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb;
579 i++, db_tr = STAILQ_NEXT(db_tr, link)) {
582 for (i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb;
583 i++, db_tr = STAILQ_NEXT(db_tr, link)) {
587 /* Enable interrupts */
588 sc->intmask = (OHCI_INT_ERR | OHCI_INT_PHY_SID
589 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
590 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
591 | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
592 sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT;
593 sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT;
594 OWRITE(sc, FWOHCI_INTMASK, sc->intmask);
595 fwohci_set_intr(&sc->fc, 1);
599 fwohci_init(struct fwohci_softc *sc, device_t dev)
606 reg = OREAD(sc, OHCI_VERSION);
607 mver = (reg >> 16) & 0xff;
608 device_printf(dev, "OHCI version %x.%x (ROM=%d)\n",
609 mver, reg & 0xff, (reg >> 24) & 1);
610 if (mver < 1 || mver > 9) {
611 device_printf(dev, "invalid OHCI version\n");
615 /* Available Isochronous DMA channel probe */
616 OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
617 OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
618 reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
619 OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
620 OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
621 for (i = 0; i < 0x20; i++)
622 if ((reg & (1 << i)) == 0)
625 device_printf(dev, "No. of Isochronous channels is %d.\n", i);
629 sc->fc.arq = &sc->arrq.xferq;
630 sc->fc.ars = &sc->arrs.xferq;
631 sc->fc.atq = &sc->atrq.xferq;
632 sc->fc.ats = &sc->atrs.xferq;
634 sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
635 sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
636 sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
637 sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
639 sc->arrq.xferq.start = NULL;
640 sc->arrs.xferq.start = NULL;
641 sc->atrq.xferq.start = fwohci_start_atq;
642 sc->atrs.xferq.start = fwohci_start_ats;
644 sc->arrq.xferq.buf = NULL;
645 sc->arrs.xferq.buf = NULL;
646 sc->atrq.xferq.buf = NULL;
647 sc->atrs.xferq.buf = NULL;
649 sc->arrq.xferq.dmach = -1;
650 sc->arrs.xferq.dmach = -1;
651 sc->atrq.xferq.dmach = -1;
652 sc->atrs.xferq.dmach = -1;
656 sc->atrq.ndesc = 8; /* equal to maximum of mbuf chains */
660 sc->arrs.ndb = NDB / 2;
662 sc->atrs.ndb = NDB / 2;
664 for (i = 0; i < sc->fc.nisodma; i++) {
665 sc->fc.it[i] = &sc->it[i].xferq;
666 sc->fc.ir[i] = &sc->ir[i].xferq;
667 sc->it[i].xferq.dmach = i;
668 sc->ir[i].xferq.dmach = i;
673 sc->fc.tcode = tinfo;
676 sc->fc.config_rom = fwdma_malloc(&sc->fc, CROMSIZE, CROMSIZE,
677 &sc->crom_dma, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
678 if (sc->fc.config_rom == NULL) {
679 device_printf(dev, "config_rom alloc failed.");
684 bzero(&sc->fc.config_rom[0], CROMSIZE);
685 sc->fc.config_rom[1] = 0x31333934;
686 sc->fc.config_rom[2] = 0xf000a002;
687 sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
688 sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
689 sc->fc.config_rom[5] = 0;
690 sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
692 sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
695 /* SID receive buffer must align 2^11 */
696 #define OHCI_SIDSIZE (1 << 11)
697 sc->sid_buf = fwdma_malloc(&sc->fc, OHCI_SIDSIZE, OHCI_SIDSIZE,
698 &sc->sid_dma, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
699 if (sc->sid_buf == NULL) {
700 device_printf(dev, "sid_buf alloc failed.");
704 fwdma_malloc(&sc->fc, sizeof(uint32_t), sizeof(uint32_t),
705 &sc->dummy_dma, BUS_DMA_WAITOK);
707 if (sc->dummy_dma.v_addr == NULL) {
708 device_printf(dev, "dummy_dma alloc failed.");
712 fwohci_db_init(sc, &sc->arrq);
713 if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0)
716 fwohci_db_init(sc, &sc->arrs);
717 if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0)
720 fwohci_db_init(sc, &sc->atrq);
721 if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0)
724 fwohci_db_init(sc, &sc->atrs);
725 if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0)
728 sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H);
729 sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L);
730 for (i = 0; i < 8; i++)
731 ui[i] = FW_EUI64_BYTE(&sc->fc.eui,i);
732 device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
733 ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]);
735 sc->fc.ioctl = fwohci_ioctl;
736 sc->fc.cyctimer = fwohci_cyctimer;
737 sc->fc.set_bmr = fwohci_set_bus_manager;
738 sc->fc.ibr = fwohci_ibr;
739 sc->fc.irx_enable = fwohci_irx_enable;
740 sc->fc.irx_disable = fwohci_irx_disable;
742 sc->fc.itx_enable = fwohci_itxbuf_enable;
743 sc->fc.itx_disable = fwohci_itx_disable;
744 #if BYTE_ORDER == BIG_ENDIAN
745 sc->fc.irx_post = fwohci_irx_post;
747 sc->fc.irx_post = NULL;
749 sc->fc.itx_post = NULL;
750 sc->fc.timeout = fwohci_timeout;
751 sc->fc.poll = fwohci_poll;
752 sc->fc.set_intr = fwohci_set_intr;
754 sc->intmask = sc->irstat = sc->itstat = 0;
756 /* Init task queue */
757 sc->fc.taskqueue = taskqueue_create_fast("fw_taskq", M_WAITOK,
758 taskqueue_thread_enqueue, &sc->fc.taskqueue);
759 taskqueue_start_threads(&sc->fc.taskqueue, 1, PI_NET, "fw%d_taskq",
760 device_get_unit(dev));
761 TASK_INIT(&sc->fwohci_task_busreset, 2, fwohci_task_busreset, sc);
762 TASK_INIT(&sc->fwohci_task_sid, 1, fwohci_task_sid, sc);
763 TASK_INIT(&sc->fwohci_task_dma, 0, fwohci_task_dma, sc);
766 fwohci_reset(sc, dev);
772 fwohci_timeout(void *arg)
774 struct fwohci_softc *sc;
776 sc = (struct fwohci_softc *)arg;
780 fwohci_cyctimer(struct firewire_comm *fc)
782 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
783 return (OREAD(sc, OHCI_CYCLETIMER));
787 fwohci_detach(struct fwohci_softc *sc, device_t dev)
791 if (sc->sid_buf != NULL)
792 fwdma_free(&sc->fc, &sc->sid_dma);
793 if (sc->fc.config_rom != NULL)
794 fwdma_free(&sc->fc, &sc->crom_dma);
796 fwohci_db_free(&sc->arrq);
797 fwohci_db_free(&sc->arrs);
799 fwohci_db_free(&sc->atrq);
800 fwohci_db_free(&sc->atrs);
802 for (i = 0; i < sc->fc.nisodma; i++) {
803 fwohci_db_free(&sc->it[i]);
804 fwohci_db_free(&sc->ir[i]);
806 if (sc->fc.taskqueue != NULL) {
807 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_busreset);
808 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_sid);
809 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_dma);
810 taskqueue_drain(sc->fc.taskqueue, &sc->fc.task_timeout);
811 taskqueue_free(sc->fc.taskqueue);
812 sc->fc.taskqueue = NULL;
818 #define LAST_DB(dbtr, db) do { \
819 struct fwohcidb_tr *_dbtr = (dbtr); \
820 int _cnt = _dbtr->dbcnt; \
821 db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \
825 fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error)
827 struct fwohcidb_tr *db_tr;
829 bus_dma_segment_t *s;
832 db_tr = (struct fwohcidb_tr *)arg;
833 db = &db_tr->db[db_tr->dbcnt];
835 if (firewire_debug || error != EFBIG)
836 printf("fwohci_execute_db: error=%d\n", error);
839 for (i = 0; i < nseg; i++) {
841 FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr);
842 FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len);
843 FWOHCI_DMA_WRITE(db->db.desc.res, 0);
850 fwohci_execute_db2(void *arg, bus_dma_segment_t *segs, int nseg,
851 bus_size_t size, int error)
853 fwohci_execute_db(arg, segs, nseg, error);
857 fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
860 int tcode, hdr_len, pl_off;
863 struct fw_xfer *xfer;
865 struct fwohci_txpkthdr *ohcifp;
866 struct fwohcidb_tr *db_tr;
869 struct tcode_info *info;
870 static int maxdesc=0;
872 FW_GLOCK_ASSERT(&sc->fc);
874 if (&sc->atrq == dbch) {
876 } else if (&sc->atrs == dbch) {
882 if (dbch->flags & FWOHCI_DBCH_FULL)
887 xfer = STAILQ_FIRST(&dbch->xferq.q);
892 if (dbch->xferq.queued == 0) {
893 device_printf(sc->fc.dev, "TX queue empty\n");
896 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
898 xfer->flag = FWXF_START;
900 fp = &xfer->send.hdr;
901 tcode = fp->mode.common.tcode;
903 ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
904 info = &tinfo[tcode];
905 hdr_len = pl_off = info->hdr_len;
907 ld = &ohcifp->mode.ld[0];
908 ld[0] = ld[1] = ld[2] = ld[3] = 0;
909 for (i = 0; i < pl_off; i+= 4)
910 ld[i/4] = fp->mode.ld[i/4];
912 ohcifp->mode.common.spd = xfer->send.spd & 0x7;
913 if (tcode == FWTCODE_STREAM) {
915 ohcifp->mode.stream.len = fp->mode.stream.len;
916 } else if (tcode == FWTCODE_PHY) {
918 ld[1] = fp->mode.ld[1];
919 ld[2] = fp->mode.ld[2];
920 ohcifp->mode.common.spd = 0;
921 ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
923 ohcifp->mode.asycomm.dst = fp->mode.hdr.dst;
924 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
925 ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
928 FWOHCI_DMA_WRITE(db->db.desc.cmd,
929 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len);
930 FWOHCI_DMA_WRITE(db->db.desc.addr, 0);
931 FWOHCI_DMA_WRITE(db->db.desc.res, 0);
932 /* Specify bound timer of asy. response */
933 if (&sc->atrs == dbch) {
934 FWOHCI_DMA_WRITE(db->db.desc.res,
935 (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13));
937 #if BYTE_ORDER == BIG_ENDIAN
938 if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ)
940 for (i = 0; i < hdr_len/4; i++)
941 FWOHCI_DMA_WRITE(ld[i], ld[i]);
946 db = &db_tr->db[db_tr->dbcnt];
947 if (xfer->send.pay_len > 0) {
950 if (xfer->mbuf == NULL) {
951 err = bus_dmamap_load(dbch->dmat, db_tr->dma_map,
952 &xfer->send.payload[0], xfer->send.pay_len,
953 fwohci_execute_db, db_tr,
956 /* XXX we can handle only 6 (=8-2) mbuf chains */
957 err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
959 fwohci_execute_db2, db_tr,
965 device_printf(sc->fc.dev, "EFBIG.\n");
966 m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
968 m_copydata(xfer->mbuf, 0,
969 xfer->mbuf->m_pkthdr.len,
971 m0->m_len = m0->m_pkthdr.len =
972 xfer->mbuf->m_pkthdr.len;
977 device_printf(sc->fc.dev, "m_getcl failed.\n");
981 printf("dmamap_load: err=%d\n", err);
982 bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
983 BUS_DMASYNC_PREWRITE);
984 #if 0 /* OHCI_OUTPUT_MODE == 0 */
985 for (i = 2; i < db_tr->dbcnt; i++)
986 FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd,
990 if (maxdesc < db_tr->dbcnt) {
991 maxdesc = db_tr->dbcnt;
993 device_printf(sc->fc.dev, "%s: maxdesc %d\n", __func__, maxdesc);
997 FWOHCI_DMA_SET(db->db.desc.cmd,
998 OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
999 FWOHCI_DMA_WRITE(db->db.desc.depend,
1000 STAILQ_NEXT(db_tr, link)->bus_addr);
1003 fsegment = db_tr->dbcnt;
1004 if (dbch->pdb_tr != NULL) {
1005 LAST_DB(dbch->pdb_tr, db);
1006 FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt);
1008 dbch->xferq.queued++;
1009 dbch->pdb_tr = db_tr;
1010 db_tr = STAILQ_NEXT(db_tr, link);
1011 if (db_tr != dbch->bottom) {
1014 device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n");
1015 dbch->flags |= FWOHCI_DBCH_FULL;
1019 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1020 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1022 if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1023 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
1026 device_printf(sc->fc.dev, "start AT DMA status=%x\n",
1027 OREAD(sc, OHCI_DMACTL(off)));
1028 OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | fsegment);
1029 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1030 dbch->xferq.flag |= FWXFERQ_RUNNING;
1038 fwohci_start_atq(struct firewire_comm *fc)
1040 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1042 fwohci_start(sc, &(sc->atrq));
1043 FW_GUNLOCK(&sc->fc);
1048 fwohci_start_ats(struct firewire_comm *fc)
1050 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1052 fwohci_start(sc, &(sc->atrs));
1053 FW_GUNLOCK(&sc->fc);
1058 fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1061 struct fwohcidb_tr *tr;
1062 struct fwohcidb *db;
1063 struct fw_xfer *xfer;
1067 struct firewire_comm *fc = (struct firewire_comm *)sc;
1069 if (&sc->atrq == dbch) {
1072 } else if (&sc->atrs == dbch) {
1081 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
1082 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
1083 while (dbch->xferq.queued > 0) {
1085 status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT;
1086 if (!(status & OHCI_CNTL_DMA_ACTIVE)) {
1087 if (fc->status != FWBUSINIT)
1088 /* maybe out of order?? */
1091 bus_dmamap_sync(dbch->dmat, tr->dma_map,
1092 BUS_DMASYNC_POSTWRITE);
1093 bus_dmamap_unload(dbch->dmat, tr->dma_map);
1095 if (firewire_debug > 1)
1098 if (status & OHCI_CNTL_DMA_DEAD) {
1100 OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
1101 device_printf(sc->fc.dev, "force reset AT FIFO\n");
1102 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
1103 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
1104 OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
1106 stat = status & FWOHCIEV_MASK;
1108 case FWOHCIEV_ACKPEND:
1109 case FWOHCIEV_ACKCOMPL:
1112 case FWOHCIEV_ACKBSA:
1113 case FWOHCIEV_ACKBSB:
1114 case FWOHCIEV_ACKBSX:
1117 case FWOHCIEV_FLUSHED:
1118 case FWOHCIEV_ACKTARD:
1121 case FWOHCIEV_MISSACK:
1122 case FWOHCIEV_UNDRRUN:
1123 case FWOHCIEV_OVRRUN:
1124 case FWOHCIEV_DESCERR:
1125 case FWOHCIEV_DTRDERR:
1126 case FWOHCIEV_TIMEOUT:
1127 case FWOHCIEV_TCODERR:
1128 case FWOHCIEV_UNKNOWN:
1129 case FWOHCIEV_ACKDERR:
1130 case FWOHCIEV_ACKTERR:
1135 if (tr->xfer != NULL) {
1137 if (xfer->flag & FWXF_RCVD) {
1140 printf("already rcvd\n");
1144 microtime(&xfer->tv);
1145 xfer->flag = FWXF_SENT;
1147 xfer->flag = FWXF_BUSY;
1149 xfer->recv.pay_len = 0;
1151 } else if (stat != FWOHCIEV_ACKPEND) {
1152 if (stat != FWOHCIEV_ACKCOMPL)
1153 xfer->flag = FWXF_SENTERR;
1155 xfer->recv.pay_len = 0;
1160 * The watchdog timer takes care of split
1161 * transaction timeout for ACKPEND case.
1164 printf("this shouldn't happen\n");
1167 dbch->xferq.queued--;
1172 tr = STAILQ_NEXT(tr, link);
1174 if (dbch->bottom == dbch->top) {
1175 /* we reaches the end of context program */
1176 if (firewire_debug && dbch->xferq.queued > 0)
1177 printf("queued > 0\n");
1182 if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
1183 printf("make free slot\n");
1184 dbch->flags &= ~FWOHCI_DBCH_FULL;
1186 fwohci_start(sc, dbch);
1193 fwohci_db_free(struct fwohci_dbch *dbch)
1195 struct fwohcidb_tr *db_tr;
1198 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1201 for (db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0; idb < dbch->ndb;
1202 db_tr = STAILQ_NEXT(db_tr, link), idb++) {
1203 if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 &&
1204 db_tr->buf != NULL) {
1205 fwdma_free_size(dbch->dmat, db_tr->dma_map,
1206 db_tr->buf, dbch->xferq.psize);
1208 } else if (db_tr->dma_map != NULL)
1209 bus_dmamap_destroy(dbch->dmat, db_tr->dma_map);
1212 db_tr = STAILQ_FIRST(&dbch->db_trq);
1213 fwdma_free_multiseg(dbch->am);
1215 STAILQ_INIT(&dbch->db_trq);
1216 dbch->flags &= ~FWOHCI_DBCH_INIT;
1220 fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1223 struct fwohcidb_tr *db_tr;
1225 if ((dbch->flags & FWOHCI_DBCH_INIT) != 0)
1228 /* create dma_tag for buffers */
1229 #define MAX_REQCOUNT 0xffff
1230 if (bus_dma_tag_create(/*parent*/ sc->fc.dmat,
1231 /*alignment*/ 1, /*boundary*/ 0,
1232 /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT,
1233 /*highaddr*/ BUS_SPACE_MAXADDR,
1234 /*filter*/NULL, /*filterarg*/NULL,
1235 /*maxsize*/ dbch->xferq.psize,
1236 /*nsegments*/ dbch->ndesc > 3 ? dbch->ndesc - 2 : 1,
1237 /*maxsegsz*/ MAX_REQCOUNT,
1239 /*lockfunc*/busdma_lock_mutex,
1240 /*lockarg*/FW_GMTX(&sc->fc),
1244 /* allocate DB entries and attach one to each DMA channels */
1245 /* DB entry must start at 16 bytes bounary. */
1246 STAILQ_INIT(&dbch->db_trq);
1247 db_tr = (struct fwohcidb_tr *)
1248 malloc(sizeof(struct fwohcidb_tr) * dbch->ndb,
1249 M_FW, M_WAITOK | M_ZERO);
1251 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1252 dbch->am = fwdma_malloc_multiseg(&sc->fc, sizeof(struct fwohcidb),
1253 DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK);
1254 if (dbch->am == NULL) {
1255 printf("fwohci_db_init: fwdma_malloc_multiseg failed\n");
1259 /* Attach DB to DMA ch. */
1260 for (idb = 0; idb < dbch->ndb; idb++) {
1262 db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1263 db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1264 /* create dmamap for buffers */
1265 /* XXX do we need 4bytes alignment tag? */
1266 /* XXX don't alloc dma_map for AR */
1267 if (bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) {
1268 printf("bus_dmamap_create failed\n");
1269 dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1270 fwohci_db_free(dbch);
1273 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1274 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1275 if (idb % dbch->xferq.bnpacket == 0)
1276 dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1277 ].start = (caddr_t)db_tr;
1278 if ((idb + 1) % dbch->xferq.bnpacket == 0)
1279 dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1280 ].end = (caddr_t)db_tr;
1284 STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1285 = STAILQ_FIRST(&dbch->db_trq);
1287 dbch->xferq.queued = 0;
1288 dbch->pdb_tr = NULL;
1289 dbch->top = STAILQ_FIRST(&dbch->db_trq);
1290 dbch->bottom = dbch->top;
1291 dbch->flags = FWOHCI_DBCH_INIT;
1295 fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1297 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1299 OWRITE(sc, OHCI_ITCTLCLR(dmach),
1300 OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1301 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1302 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1303 /* XXX we cannot free buffers until the DMA really stops */
1304 pause("fwitxd", hz);
1305 fwohci_db_free(&sc->it[dmach]);
1306 sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1311 fwohci_irx_disable(struct firewire_comm *fc, int dmach)
1313 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1315 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1316 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1317 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1318 /* XXX we cannot free buffers until the DMA really stops */
1319 pause("fwirxd", hz);
1320 fwohci_db_free(&sc->ir[dmach]);
1321 sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1325 #if BYTE_ORDER == BIG_ENDIAN
1327 fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld)
1329 qld[0] = FWOHCI_DMA_READ(qld[0]);
1335 fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1338 int idb, z, i, dmach = 0, ldesc;
1340 struct fwohcidb_tr *db_tr;
1341 struct fwohcidb *db;
1343 if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) {
1348 for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1349 if (&sc->it[dmach] == dbch) {
1350 off = OHCI_ITOFF(dmach);
1358 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1360 dbch->xferq.flag |= FWXFERQ_RUNNING;
1361 for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1362 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1365 for (idb = 0; idb < dbch->ndb; idb++) {
1366 fwohci_add_tx_buf(dbch, db_tr, idb);
1367 if (STAILQ_NEXT(db_tr, link) == NULL) {
1371 ldesc = db_tr->dbcnt - 1;
1372 FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1373 STAILQ_NEXT(db_tr, link)->bus_addr | z);
1374 db[ldesc].db.desc.depend = db[0].db.desc.depend;
1375 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1376 if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1378 db[ldesc].db.desc.cmd,
1379 OHCI_INTERRUPT_ALWAYS);
1380 /* OHCI 1.1 and above */
1383 OHCI_INTERRUPT_ALWAYS);
1386 db_tr = STAILQ_NEXT(db_tr, link);
1389 dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1394 fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1397 int idb, z, i, dmach = 0, ldesc;
1399 struct fwohcidb_tr *db_tr;
1400 struct fwohcidb *db;
1403 if (&sc->arrq == dbch) {
1405 } else if (&sc->arrs == dbch) {
1408 for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1409 if (&sc->ir[dmach] == dbch) {
1410 off = OHCI_IROFF(dmach);
1419 if (dbch->xferq.flag & FWXFERQ_STREAM) {
1420 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1423 if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1428 dbch->xferq.flag |= FWXFERQ_RUNNING;
1429 dbch->top = STAILQ_FIRST(&dbch->db_trq);
1430 for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1431 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1434 for (idb = 0; idb < dbch->ndb; idb++) {
1435 fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1436 if (STAILQ_NEXT(db_tr, link) == NULL)
1439 ldesc = db_tr->dbcnt - 1;
1440 FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1441 STAILQ_NEXT(db_tr, link)->bus_addr | z);
1442 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1443 if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1445 db[ldesc].db.desc.cmd,
1446 OHCI_INTERRUPT_ALWAYS);
1448 db[ldesc].db.desc.depend,
1452 db_tr = STAILQ_NEXT(db_tr, link);
1455 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf);
1456 dbch->buf_offset = 0;
1457 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1458 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1459 if (dbch->xferq.flag & FWXFERQ_STREAM) {
1462 OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z);
1464 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1469 fwohci_next_cycle(struct firewire_comm *fc, int cycle_now)
1471 int sec, cycle, cycle_match;
1473 cycle = cycle_now & 0x1fff;
1474 sec = cycle_now >> 13;
1475 #define CYCLE_MOD 0x10
1477 #define CYCLE_DELAY 8 /* min delay to start DMA */
1479 #define CYCLE_DELAY 7000 /* min delay to start DMA */
1481 cycle = cycle + CYCLE_DELAY;
1482 if (cycle >= 8000) {
1486 cycle = roundup2(cycle, CYCLE_MOD);
1487 if (cycle >= 8000) {
1494 cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1496 return (cycle_match);
1500 fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1502 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1504 unsigned short tag, ich;
1505 struct fwohci_dbch *dbch;
1506 int cycle_match, cycle_now, s, ldesc;
1508 struct fw_bulkxfer *first, *chunk, *prev;
1509 struct fw_xferq *it;
1511 dbch = &sc->it[dmach];
1514 tag = (it->flag >> 6) & 3;
1515 ich = it->flag & 0x3f;
1516 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
1517 dbch->ndb = it->bnpacket * it->bnchunk;
1519 fwohci_db_init(sc, dbch);
1520 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1523 err = fwohci_tx_enable(sc, dbch);
1528 ldesc = dbch->ndesc - 1;
1531 prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1532 while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1533 struct fwohcidb *db;
1535 fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
1536 BUS_DMASYNC_PREWRITE);
1537 fwohci_txbufdb(sc, dmach, chunk);
1539 db = ((struct fwohcidb_tr *)(prev->end))->db;
1540 #if 0 /* XXX necessary? */
1541 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1542 OHCI_BRANCH_ALWAYS);
1544 #if 0 /* if bulkxfer->npacket changes */
1545 db[ldesc].db.desc.depend = db[0].db.desc.depend =
1546 ((struct fwohcidb_tr *)
1547 (chunk->start))->bus_addr | dbch->ndesc;
1549 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
1550 FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1553 STAILQ_REMOVE_HEAD(&it->stvalid, link);
1554 STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
1558 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1559 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1561 stat = OREAD(sc, OHCI_ITCTL(dmach));
1562 if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
1563 printf("stat 0x%x\n", stat);
1565 if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
1569 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1571 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1572 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1573 OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1574 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1576 first = STAILQ_FIRST(&it->stdma);
1577 OWRITE(sc, OHCI_ITCMD(dmach),
1578 ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
1579 if (firewire_debug > 1) {
1580 printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
1582 dump_dma(sc, ITX_CH + dmach);
1585 if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
1587 /* Don't start until all chunks are buffered */
1588 if (STAILQ_FIRST(&it->stfree) != NULL)
1592 /* Clear cycle match counter bits */
1593 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1595 /* 2bit second + 13bit cycle */
1596 cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1597 cycle_match = fwohci_next_cycle(fc, cycle_now);
1599 OWRITE(sc, OHCI_ITCTL(dmach),
1600 OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
1601 | OHCI_CNTL_DMA_RUN);
1603 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1605 if (firewire_debug > 1) {
1606 printf("cycle_match: 0x%04x->0x%04x\n",
1607 cycle_now, cycle_match);
1608 dump_dma(sc, ITX_CH + dmach);
1609 dump_db(sc, ITX_CH + dmach);
1611 } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1612 device_printf(sc->fc.dev,
1613 "IT DMA underrun (0x%08x)\n", stat);
1614 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1621 fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1623 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1624 int err = 0, s, ldesc;
1625 unsigned short tag, ich;
1627 struct fwohci_dbch *dbch;
1628 struct fwohcidb_tr *db_tr;
1629 struct fw_bulkxfer *first, *prev, *chunk;
1630 struct fw_xferq *ir;
1632 dbch = &sc->ir[dmach];
1635 if ((ir->flag & FWXFERQ_RUNNING) == 0) {
1636 tag = (ir->flag >> 6) & 3;
1637 ich = ir->flag & 0x3f;
1638 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1641 dbch->ndb = ir->bnpacket * ir->bnchunk;
1643 fwohci_db_init(sc, dbch);
1644 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1646 err = fwohci_rx_enable(sc, dbch);
1651 first = STAILQ_FIRST(&ir->stfree);
1652 if (first == NULL) {
1653 device_printf(fc->dev, "IR DMA no free chunk\n");
1657 ldesc = dbch->ndesc - 1;
1659 if ((ir->flag & FWXFERQ_HANDLER) == 0)
1661 prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
1662 while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1663 struct fwohcidb *db;
1665 #if 1 /* XXX for if_fwe */
1666 if (chunk->mbuf != NULL) {
1667 db_tr = (struct fwohcidb_tr *)(chunk->start);
1669 err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
1670 chunk->mbuf, fwohci_execute_db2, db_tr,
1672 FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
1673 OHCI_UPDATE | OHCI_INPUT_LAST |
1674 OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1677 db = ((struct fwohcidb_tr *)(chunk->end))->db;
1678 FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
1679 FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1681 db = ((struct fwohcidb_tr *)(prev->end))->db;
1682 FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1684 STAILQ_REMOVE_HEAD(&ir->stfree, link);
1685 STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
1688 if ((ir->flag & FWXFERQ_HANDLER) == 0)
1690 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1691 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1693 stat = OREAD(sc, OHCI_IRCTL(dmach));
1694 if (stat & OHCI_CNTL_DMA_ACTIVE)
1696 if (stat & OHCI_CNTL_DMA_RUN) {
1697 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1698 device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat);
1702 printf("start IR DMA 0x%x\n", stat);
1703 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1704 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1705 OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1706 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1707 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1708 OWRITE(sc, OHCI_IRCMD(dmach),
1709 ((struct fwohcidb_tr *)(first->start))->bus_addr
1711 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1712 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1714 dump_db(sc, IRX_CH + dmach);
1720 fwohci_stop(struct fwohci_softc *sc, device_t dev)
1724 fwohci_set_intr(&sc->fc, 0);
1726 /* Now stopping all DMA channel */
1727 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1728 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1729 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1730 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1732 for (i = 0; i < sc->fc.nisodma; i++) {
1733 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1734 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1737 #if 0 /* Let dcons(4) be accessed */
1738 /* Stop interrupt */
1739 OWRITE(sc, FWOHCI_INTMASKCLR,
1740 OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1742 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1743 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1744 | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1745 | OHCI_INT_PHY_BUS_R);
1747 /* FLUSH FIFO and reset Transmitter/Receiver */
1748 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1751 /* XXX Link down? Bus reset? */
1756 fwohci_resume(struct fwohci_softc *sc, device_t dev)
1759 struct fw_xferq *ir;
1760 struct fw_bulkxfer *chunk;
1762 fwohci_reset(sc, dev);
1763 /* XXX resume isochronous receive automatically. (how about TX?) */
1764 for (i = 0; i < sc->fc.nisodma; i++) {
1765 ir = &sc->ir[i].xferq;
1766 if ((ir->flag & FWXFERQ_RUNNING) != 0) {
1767 device_printf(sc->fc.dev,
1768 "resume iso receive ch: %d\n", i);
1769 ir->flag &= ~FWXFERQ_RUNNING;
1770 /* requeue stdma to stfree */
1771 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
1772 STAILQ_REMOVE_HEAD(&ir->stdma, link);
1773 STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
1775 sc->fc.irx_enable(&sc->fc, i);
1779 bus_generic_resume(dev);
1780 sc->fc.ibr(&sc->fc);
1786 fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1788 if (stat & OREAD(sc, FWOHCI_INTMASK))
1789 device_printf(fc->dev, "INTERRUPT < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s> 0x%08x, 0x%08x\n",
1790 stat & OHCI_INT_EN ? "DMA_EN ":"",
1791 stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1792 stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1793 stat & OHCI_INT_ERR ? "INT_ERR ":"",
1794 stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1795 stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1796 stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1797 stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1798 stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1799 stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1800 stat & OHCI_INT_PHY_SID ? "SID ":"",
1801 stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1802 stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1803 stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1804 stat & OHCI_INT_DMA_IT ? "DMA_IT " :"",
1805 stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"",
1806 stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"",
1807 stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"",
1808 stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"",
1809 stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"",
1810 stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"",
1811 stat, OREAD(sc, FWOHCI_INTMASK)
1817 fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count)
1819 struct firewire_comm *fc = (struct firewire_comm *)sc;
1820 uintmax_t prequpper;
1821 uint32_t node_id, plen;
1823 FW_GLOCK_ASSERT(fc);
1824 if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1825 fc->status = FWBUSRESET;
1826 /* Disable bus reset interrupt until sid recv. */
1827 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1829 device_printf(fc->dev, "%s: BUS reset\n", __func__);
1830 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1831 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1833 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1834 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1835 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1836 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1839 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset);
1841 if (stat & OHCI_INT_PHY_SID) {
1842 /* Enable bus reset interrupt */
1843 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1844 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
1846 /* Allow async. request to us */
1847 OWRITE(sc, OHCI_AREQHI, 1 << 31);
1848 if (firewire_phydma_enable) {
1849 /* allow from all nodes */
1850 OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1851 OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1852 prequpper = ((uintmax_t)Maxmem << PAGE_SHIFT) >> 16;
1853 if (prequpper > OHCI_PREQUPPER_MAX) {
1854 device_printf(fc->dev,
1855 "Physical memory size of 0x%jx exceeds "
1856 "fire wire address space. Limiting dma "
1857 "to memory below 0x%jx\n",
1858 (uintmax_t)Maxmem << PAGE_SHIFT,
1859 (uintmax_t)OHCI_PREQUPPER_MAX << 16);
1860 prequpper = OHCI_PREQUPPER_MAX;
1862 OWRITE(sc, OHCI_PREQUPPER, prequpper & 0xffffffff);
1864 /* Set ATRetries register */
1865 OWRITE(sc, OHCI_ATRETRY, 1<<(13 + 16) | 0xfff);
1868 * Checking whether the node is root or not. If root, turn on
1871 node_id = OREAD(sc, FWOHCI_NODEID);
1872 plen = OREAD(sc, OHCI_SID_CNT);
1874 fc->nodeid = node_id & 0x3f;
1875 device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ",
1876 __func__, fc->nodeid, (plen >> 16) & 0xff);
1877 if (!(node_id & OHCI_NODE_VALID)) {
1878 device_printf(fc->dev, "%s: Bus reset failure\n",
1885 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
1886 if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
1887 printf("CYCLEMASTER mode\n");
1888 OWRITE(sc, OHCI_LNKCTL,
1889 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1891 printf("non CYCLEMASTER mode\n");
1892 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1893 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1896 fc->status = FWBUSINIT;
1899 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid);
1902 if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active))
1903 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma);
1907 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count)
1909 uint32_t irstat, itstat;
1911 struct firewire_comm *fc = (struct firewire_comm *)sc;
1913 if (stat & OHCI_INT_DMA_IR) {
1914 irstat = atomic_readandclear_int(&sc->irstat);
1915 for (i = 0; i < fc->nisodma; i++) {
1916 struct fwohci_dbch *dbch;
1918 if ((irstat & (1 << i)) != 0) {
1920 if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
1921 device_printf(sc->fc.dev,
1922 "dma(%d) not active\n", i);
1925 fwohci_rbuf_update(sc, i);
1929 if (stat & OHCI_INT_DMA_IT) {
1930 itstat = atomic_readandclear_int(&sc->itstat);
1931 for (i = 0; i < fc->nisodma; i++) {
1932 if ((itstat & (1 << i)) != 0) {
1933 fwohci_tbuf_update(sc, i);
1937 if (stat & OHCI_INT_DMA_PRRS) {
1939 dump_dma(sc, ARRS_CH);
1940 dump_db(sc, ARRS_CH);
1942 fwohci_arcv(sc, &sc->arrs, count);
1944 if (stat & OHCI_INT_DMA_PRRQ) {
1946 dump_dma(sc, ARRQ_CH);
1947 dump_db(sc, ARRQ_CH);
1949 fwohci_arcv(sc, &sc->arrq, count);
1951 if (stat & OHCI_INT_CYC_LOST) {
1952 if (sc->cycle_lost >= 0)
1954 if (sc->cycle_lost > 10) {
1955 sc->cycle_lost = -1;
1957 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
1959 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1960 device_printf(fc->dev, "too many cycles lost, "
1961 "no cycle master present?\n");
1964 if (stat & OHCI_INT_DMA_ATRQ) {
1965 fwohci_txd(sc, &(sc->atrq));
1967 if (stat & OHCI_INT_DMA_ATRS) {
1968 fwohci_txd(sc, &(sc->atrs));
1970 if (stat & OHCI_INT_PW_ERR) {
1971 device_printf(fc->dev, "posted write error\n");
1973 if (stat & OHCI_INT_ERR) {
1974 device_printf(fc->dev, "unrecoverable error\n");
1976 if (stat & OHCI_INT_PHY_INT) {
1977 device_printf(fc->dev, "phy int\n");
1982 fwohci_task_busreset(void *arg, int pending)
1984 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1987 fw_busreset(&sc->fc, FWBUSRESET);
1988 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
1989 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
1990 FW_GUNLOCK(&sc->fc);
1994 fwohci_task_sid(void *arg, int pending)
1996 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1997 struct firewire_comm *fc = &sc->fc;
2003 * We really should have locking
2004 * here. Not sure why it's not
2006 plen = OREAD(sc, OHCI_SID_CNT);
2008 if (plen & OHCI_SID_ERR) {
2009 device_printf(fc->dev, "SID Error\n");
2012 plen &= OHCI_SID_CNT_MASK;
2013 if (plen < 4 || plen > OHCI_SIDSIZE) {
2014 device_printf(fc->dev, "invalid SID len = %d\n", plen);
2017 plen -= 4; /* chop control info */
2018 buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2020 device_printf(fc->dev, "malloc failed\n");
2023 for (i = 0; i < plen / 4; i++)
2024 buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2026 /* pending all pre-bus_reset packets */
2027 fwohci_txd(sc, &sc->atrq);
2028 fwohci_txd(sc, &sc->atrs);
2029 fwohci_arcv(sc, &sc->arrs, -1);
2030 fwohci_arcv(sc, &sc->arrq, -1);
2032 fw_sidrcv(fc, buf, plen);
2037 fwohci_task_dma(void *arg, int pending)
2039 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2043 stat = atomic_readandclear_int(&sc->intstat);
2045 fwohci_intr_dma(sc, stat, -1);
2052 fwohci_check_stat(struct fwohci_softc *sc)
2054 uint32_t stat, irstat, itstat;
2056 FW_GLOCK_ASSERT(&sc->fc);
2057 stat = OREAD(sc, FWOHCI_INTSTAT);
2058 if (stat == 0xffffffff) {
2059 if (!bus_child_present(sc->fc.dev))
2060 return (FILTER_HANDLED);
2061 device_printf(sc->fc.dev, "device physically ejected?\n");
2062 return (FILTER_STRAY);
2065 OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
2067 stat &= sc->intmask;
2069 return (FILTER_STRAY);
2071 atomic_set_int(&sc->intstat, stat);
2072 if (stat & OHCI_INT_DMA_IR) {
2073 irstat = OREAD(sc, OHCI_IR_STAT);
2074 OWRITE(sc, OHCI_IR_STATCLR, irstat);
2075 atomic_set_int(&sc->irstat, irstat);
2077 if (stat & OHCI_INT_DMA_IT) {
2078 itstat = OREAD(sc, OHCI_IT_STAT);
2079 OWRITE(sc, OHCI_IT_STATCLR, itstat);
2080 atomic_set_int(&sc->itstat, itstat);
2083 fwohci_intr_core(sc, stat, -1);
2084 return (FILTER_HANDLED);
2088 fwohci_intr(void *arg)
2090 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2093 fwohci_check_stat(sc);
2094 FW_GUNLOCK(&sc->fc);
2098 fwohci_poll(struct firewire_comm *fc, int quick, int count)
2100 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2103 fwohci_check_stat(sc);
2108 fwohci_set_intr(struct firewire_comm *fc, int enable)
2110 struct fwohci_softc *sc;
2112 sc = (struct fwohci_softc *)fc;
2114 device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
2116 sc->intmask |= OHCI_INT_EN;
2117 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
2119 sc->intmask &= ~OHCI_INT_EN;
2120 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2125 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2127 struct firewire_comm *fc = &sc->fc;
2128 struct fwohcidb *db;
2129 struct fw_bulkxfer *chunk;
2130 struct fw_xferq *it;
2131 uint32_t stat, count;
2135 ldesc = sc->it[dmach].ndesc - 1;
2136 s = splfw(); /* unnecessary ? */
2138 fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2140 dump_db(sc, ITX_CH + dmach);
2141 while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2142 db = ((struct fwohcidb_tr *)(chunk->end))->db;
2143 stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2144 >> OHCI_STATUS_SHIFT;
2145 db = ((struct fwohcidb_tr *)(chunk->start))->db;
2147 count = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2151 STAILQ_REMOVE_HEAD(&it->stdma, link);
2152 switch (stat & FWOHCIEV_MASK) {
2153 case FWOHCIEV_ACKCOMPL:
2155 device_printf(fc->dev, "0x%08x\n", count);
2159 device_printf(fc->dev,
2160 "Isochronous transmit err %02x(%s)\n",
2161 stat, fwohcicode[stat & 0x1f]);
2163 STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2173 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2175 struct firewire_comm *fc = &sc->fc;
2176 struct fwohcidb_tr *db_tr;
2177 struct fw_bulkxfer *chunk;
2178 struct fw_xferq *ir;
2183 ldesc = sc->ir[dmach].ndesc - 1;
2188 if ((ir->flag & FWXFERQ_HANDLER) == 0)
2190 fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2191 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2192 db_tr = (struct fwohcidb_tr *)chunk->end;
2193 stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res)
2194 >> OHCI_STATUS_SHIFT;
2198 if (chunk->mbuf != NULL) {
2199 bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map,
2200 BUS_DMASYNC_POSTREAD);
2201 bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map);
2202 } else if (ir->buf != NULL) {
2203 fwdma_sync_multiseg(ir->buf, chunk->poffset,
2204 ir->bnpacket, BUS_DMASYNC_POSTREAD);
2207 printf("fwohci_rbuf_update: this shouldn't happened\n");
2210 STAILQ_REMOVE_HEAD(&ir->stdma, link);
2211 STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2212 switch (stat & FWOHCIEV_MASK) {
2213 case FWOHCIEV_ACKCOMPL:
2217 chunk->resp = EINVAL;
2218 device_printf(fc->dev,
2219 "Isochronous receive err %02x(%s)\n",
2220 stat, fwohcicode[stat & 0x1f]);
2224 if ((ir->flag & FWXFERQ_HANDLER) == 0)
2229 if (ir->flag & FWXFERQ_HANDLER)
2236 dump_dma(struct fwohci_softc *sc, uint32_t ch)
2238 uint32_t off, cntl, stat, cmd, match;
2242 } else if (ch == 1) {
2244 } else if (ch == 2) {
2246 } else if (ch == 3) {
2248 } else if (ch < IRX_CH) {
2249 off = OHCI_ITCTL(ch - ITX_CH);
2251 off = OHCI_IRCTL(ch - IRX_CH);
2253 cntl = stat = OREAD(sc, off);
2254 cmd = OREAD(sc, off + 0xc);
2255 match = OREAD(sc, off + 0x10);
2257 device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2264 device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2266 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2267 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2268 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2269 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2270 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2271 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2272 fwohcicode[stat & 0x1f],
2276 device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2281 dump_db(struct fwohci_softc *sc, uint32_t ch)
2283 struct fwohci_dbch *dbch;
2284 struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
2285 struct fwohcidb *curr = NULL, *prev, *next = NULL;
2292 } else if (ch == 1) {
2295 } else if (ch == 2) {
2298 } else if (ch == 3) {
2301 } else if (ch < IRX_CH) {
2302 off = OHCI_ITCTL(ch - ITX_CH);
2303 dbch = &sc->it[ch - ITX_CH];
2305 off = OHCI_IRCTL(ch - IRX_CH);
2306 dbch = &sc->ir[ch - IRX_CH];
2308 cmd = OREAD(sc, off + 0xc);
2310 if (dbch->ndb == 0) {
2311 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2316 for (idb = 0; idb < dbch->ndb; idb++) {
2317 cp = STAILQ_NEXT(pp, link);
2322 np = STAILQ_NEXT(cp, link);
2323 for (jdb = 0; jdb < dbch->ndesc; jdb++) {
2324 if ((cmd & 0xfffffff0) == cp->bus_addr) {
2334 pp = STAILQ_NEXT(pp, link);
2344 printf("Prev DB %d\n", ch);
2345 print_db(pp, prev, ch, dbch->ndesc);
2347 printf("Current DB %d\n", ch);
2348 print_db(cp, curr, ch, dbch->ndesc);
2350 printf("Next DB %d\n", ch);
2351 print_db(np, next, ch, dbch->ndesc);
2354 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2360 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2361 uint32_t ch, uint32_t max)
2368 printf("No Descriptor is found\n");
2372 printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2384 for (i = 0; i <= max; i++) {
2385 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2386 res = FWOHCI_DMA_READ(db[i].db.desc.res);
2387 key = cmd & OHCI_KEY_MASK;
2388 stat = res >> OHCI_STATUS_SHIFT;
2389 printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2390 (uintmax_t)db_tr->bus_addr,
2391 dbcode[(cmd >> 28) & 0xf],
2392 dbkey[(cmd >> 24) & 0x7],
2393 dbcond[(cmd >> 20) & 0x3],
2394 dbcond[(cmd >> 18) & 0x3],
2395 cmd & OHCI_COUNT_MASK,
2396 FWOHCI_DMA_READ(db[i].db.desc.addr),
2397 FWOHCI_DMA_READ(db[i].db.desc.depend),
2399 res & OHCI_COUNT_MASK);
2400 if (stat & 0xff00) {
2401 printf(" %s%s%s%s%s%s %s(%x)\n",
2402 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2403 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2404 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2405 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2406 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2407 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2408 fwohcicode[stat & 0x1f],
2412 printf(" Nostat\n");
2414 if (key == OHCI_KEY_ST2) {
2415 printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2416 FWOHCI_DMA_READ(db[i + 1].db.immed[0]),
2417 FWOHCI_DMA_READ(db[i + 1].db.immed[1]),
2418 FWOHCI_DMA_READ(db[i + 1].db.immed[2]),
2419 FWOHCI_DMA_READ(db[i + 1].db.immed[3]));
2421 if (key == OHCI_KEY_DEVICE) {
2424 if ((cmd & OHCI_BRANCH_MASK)
2425 == OHCI_BRANCH_ALWAYS) {
2428 if ((cmd & OHCI_CMD_MASK)
2429 == OHCI_OUTPUT_LAST) {
2432 if ((cmd & OHCI_CMD_MASK)
2433 == OHCI_INPUT_LAST) {
2436 if (key == OHCI_KEY_ST2) {
2444 fwohci_ibr(struct firewire_comm *fc)
2446 struct fwohci_softc *sc;
2449 device_printf(fc->dev, "Initiate bus reset\n");
2450 sc = (struct fwohci_softc *)fc;
2454 * Make sure our cached values from the config rom are
2457 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2458 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2461 * Set root hold-off bit so that non cyclemaster capable node
2462 * shouldn't became the root node.
2465 fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2466 fun |= FW_PHY_IBR | FW_PHY_RHB;
2467 fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2468 #else /* Short bus reset */
2469 fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2470 fun |= FW_PHY_ISBR | FW_PHY_RHB;
2471 fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2477 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2479 struct fwohcidb_tr *db_tr, *fdb_tr;
2480 struct fwohci_dbch *dbch;
2481 struct fwohcidb *db;
2483 struct fwohci_txpkthdr *ohcifp;
2484 unsigned short chtag;
2487 FW_GLOCK_ASSERT(&sc->fc);
2489 dbch = &sc->it[dmach];
2490 chtag = sc->it[dmach].xferq.flag & 0xff;
2492 db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2493 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2495 device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2497 for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2499 fp = (struct fw_pkt *)db_tr->buf;
2500 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2501 ohcifp->mode.ld[0] = fp->mode.ld[0];
2502 ohcifp->mode.common.spd = 0 & 0x7;
2503 ohcifp->mode.stream.len = fp->mode.stream.len;
2504 ohcifp->mode.stream.chtag = chtag;
2505 ohcifp->mode.stream.tcode = 0xa;
2506 #if BYTE_ORDER == BIG_ENDIAN
2507 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2508 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2511 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2512 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2513 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2514 #if 0 /* if bulkxfer->npackets changes */
2515 db[2].db.desc.cmd = OHCI_OUTPUT_LAST
2517 | OHCI_BRANCH_ALWAYS;
2518 db[0].db.desc.depend =
2519 = db[dbch->ndesc - 1].db.desc.depend
2520 = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2522 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2523 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2525 bulkxfer->end = (caddr_t)db_tr;
2526 db_tr = STAILQ_NEXT(db_tr, link);
2528 db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2529 FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2530 FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2531 #if 0 /* if bulkxfer->npackets changes */
2532 db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2533 /* OHCI 1.1 and above */
2534 db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2537 db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2538 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2539 device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2545 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2548 struct fwohcidb *db = db_tr->db;
2549 struct fw_xferq *it;
2557 db_tr->buf = fwdma_v_addr(it->buf, poffset);
2560 FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2561 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2562 FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2563 bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2564 FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2565 fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2567 FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2568 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2570 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2571 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2577 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2578 int poffset, struct fwdma_alloc *dummy_dma)
2580 struct fwohcidb *db = db_tr->db;
2581 struct fw_xferq *ir;
2587 if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2588 if (db_tr->buf == NULL) {
2589 db_tr->buf = fwdma_malloc_size(dbch->dmat,
2590 &db_tr->dma_map, ir->psize, &dbuf[0],
2592 if (db_tr->buf == NULL)
2596 dsiz[0] = ir->psize;
2597 bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2598 BUS_DMASYNC_PREREAD);
2601 if (dummy_dma != NULL) {
2602 dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2603 dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2605 dsiz[db_tr->dbcnt] = ir->psize;
2606 if (ir->buf != NULL) {
2607 db_tr->buf = fwdma_v_addr(ir->buf, poffset);
2608 dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset);
2612 for (i = 0; i < db_tr->dbcnt; i++) {
2613 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2614 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2615 if (ir->flag & FWXFERQ_STREAM) {
2616 FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2618 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2620 ldesc = db_tr->dbcnt - 1;
2621 if (ir->flag & FWXFERQ_STREAM) {
2622 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2624 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2630 fwohci_arcv_swap(struct fw_pkt *fp, int len)
2635 #if BYTE_ORDER == BIG_ENDIAN
2639 ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2641 printf("ld0: x%08x\n", ld0);
2643 fp0 = (struct fw_pkt *)&ld0;
2644 /* determine length to swap */
2645 switch (fp0->mode.common.tcode) {
2650 case FWOHCITCODE_PHY:
2661 printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2664 hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2667 printf("splitted header\n");
2670 #if BYTE_ORDER == BIG_ENDIAN
2671 for (i = 0; i < slen/4; i++)
2672 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2678 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2680 struct tcode_info *info;
2683 info = &tinfo[fp->mode.common.tcode];
2684 r = info->hdr_len + sizeof(uint32_t);
2685 if ((info->flag & FWTI_BLOCK_ASY) != 0)
2686 r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2688 if (r == sizeof(uint32_t)) {
2690 device_printf(sc->fc.dev, "Unknown tcode %d\n",
2691 fp->mode.common.tcode);
2695 if (r > dbch->xferq.psize) {
2696 device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2705 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2706 struct fwohcidb_tr *db_tr, uint32_t off, int wake)
2708 struct fwohcidb *db = &db_tr->db[0];
2710 FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2711 FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2712 FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2713 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
2714 dbch->bottom = db_tr;
2717 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2721 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2723 struct fwohcidb_tr *db_tr;
2724 struct iovec vec[2];
2725 struct fw_pkt pktbuf;
2729 uint32_t stat, off, status, event;
2731 int len, plen, hlen, pcnt, offset;
2736 if (&sc->arrq == dbch) {
2738 } else if (&sc->arrs == dbch) {
2747 /* XXX we cannot handle a packet which lies in more than two buf */
2748 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
2749 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
2750 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2751 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2752 while (status & OHCI_CNTL_DMA_ACTIVE) {
2755 if (off == OHCI_ARQOFF)
2756 printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2757 db_tr->bus_addr, status, resCount);
2759 len = dbch->xferq.psize - resCount;
2760 ld = (uint8_t *)db_tr->buf;
2761 if (dbch->pdb_tr == NULL) {
2762 len -= dbch->buf_offset;
2763 ld += dbch->buf_offset;
2766 bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2767 BUS_DMASYNC_POSTREAD);
2769 if (count >= 0 && count-- == 0)
2771 if (dbch->pdb_tr != NULL) {
2772 /* we have a fragment in previous buffer */
2775 offset = dbch->buf_offset;
2778 buf = dbch->pdb_tr->buf + offset;
2779 rlen = dbch->xferq.psize - offset;
2781 printf("rlen=%d, offset=%d\n",
2782 rlen, dbch->buf_offset);
2783 if (dbch->buf_offset < 0) {
2784 /* splitted in header, pull up */
2787 p = (char *)&pktbuf;
2788 bcopy(buf, p, rlen);
2790 /* this must be too long but harmless */
2791 rlen = sizeof(pktbuf) - rlen;
2793 printf("why rlen < 0\n");
2794 bcopy(db_tr->buf, p, rlen);
2797 hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf));
2799 printf("hlen should be positive.");
2802 offset = sizeof(pktbuf);
2803 vec[0].iov_base = (char *)&pktbuf;
2804 vec[0].iov_len = offset;
2806 /* splitted in payload */
2808 vec[0].iov_base = buf;
2809 vec[0].iov_len = rlen;
2811 fp=(struct fw_pkt *)vec[0].iov_base;
2814 /* no fragment in previous buffer */
2815 fp=(struct fw_pkt *)ld;
2816 hlen = fwohci_arcv_swap(fp, len);
2820 dbch->pdb_tr = db_tr;
2821 dbch->buf_offset = - dbch->buf_offset;
2823 if (resCount != 0) {
2824 printf("resCount=%d hlen=%d\n",
2833 plen = fwohci_get_plen(sc, dbch, fp) - offset;
2835 /* minimum header size + trailer
2836 = sizeof(fw_pkt) so this shouldn't happens */
2837 printf("plen(%d) is negative! offset=%d\n",
2844 dbch->pdb_tr = db_tr;
2846 printf("splitted payload\n");
2848 if (resCount != 0) {
2849 printf("resCount=%d plen=%d"
2851 resCount, plen, len);
2856 vec[nvec].iov_base = ld;
2857 vec[nvec].iov_len = plen;
2861 dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2863 printf("nvec == 0\n");
2865 /* DMA result-code will be written at the tail of packet */
2866 stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer)));
2868 printf("plen: %d, stat %x\n",
2871 spd = (stat >> 21) & 0x3;
2872 event = (stat >> 16) & 0x1f;
2874 case FWOHCIEV_ACKPEND:
2876 printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
2879 case FWOHCIEV_ACKCOMPL:
2881 struct fw_rcv_buf rb;
2883 if ((vec[nvec-1].iov_len -=
2884 sizeof(struct fwohci_trailer)) == 0)
2893 case FWOHCIEV_BUSRST:
2894 if ((sc->fc.status != FWBUSRESET) &&
2895 (sc->fc.status != FWBUSINIT))
2896 printf("got BUSRST packet!?\n");
2899 device_printf(sc->fc.dev,
2900 "Async DMA Receive error err=%02x %s"
2901 " plen=%d offset=%d len=%d status=0x%08x"
2902 " tcode=0x%x, stat=0x%08x\n",
2903 event, fwohcicode[event], plen,
2904 dbch->buf_offset, len,
2905 OREAD(sc, OHCI_DMACTL(off)),
2906 fp->mode.common.tcode, stat);
2913 if (dbch->pdb_tr != NULL) {
2914 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr,
2916 dbch->pdb_tr = NULL;
2921 if (resCount == 0) {
2922 /* done on this buffer */
2923 if (dbch->pdb_tr == NULL) {
2924 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1);
2925 dbch->buf_offset = 0;
2927 if (dbch->pdb_tr != db_tr)
2928 printf("pdb_tr != db_tr\n");
2929 db_tr = STAILQ_NEXT(db_tr, link);
2930 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2931 >> OHCI_STATUS_SHIFT;
2932 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2934 /* XXX check buffer overrun */
2937 dbch->buf_offset = dbch->xferq.psize - resCount;
2940 /* XXX make sure DMA is not dead */
2944 printf("fwohci_arcv: no packets\n");
2950 device_printf(sc->fc.dev, "AR DMA status=%x, ",
2951 OREAD(sc, OHCI_DMACTL(off)));
2952 dbch->pdb_tr = NULL;
2953 /* skip until resCount != 0 */
2954 printf(" skip buffer");
2955 while (resCount == 0) {
2957 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0);
2958 db_tr = STAILQ_NEXT(db_tr, link);
2959 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2964 dbch->buf_offset = dbch->xferq.psize - resCount;
2965 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);