]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/firewire/fwohci.c
Merge compiler-rt trunk r321414 to contrib/compiler-rt.
[FreeBSD/FreeBSD.git] / sys / dev / firewire / fwohci.c
1 /*-
2  * SPDX-License-Identifier: BSD-4-Clause
3  *
4  * Copyright (c) 2003 Hidetoshi Shimokawa
5  * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the acknowledgement as bellow:
18  *
19  *    This product includes software developed by K. Kobayashi and H. Shimokawa
20  *
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $FreeBSD$
37  *
38  */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43 #include <sys/malloc.h>
44 #include <sys/sockio.h>
45 #include <sys/sysctl.h>
46 #include <sys/bus.h>
47 #include <sys/kernel.h>
48 #include <sys/conf.h>
49 #include <sys/endian.h>
50 #include <sys/kdb.h>
51
52 #include <machine/bus.h>
53 #include <machine/md_var.h>
54
55 #include <dev/firewire/firewire.h>
56 #include <dev/firewire/firewirereg.h>
57 #include <dev/firewire/fwdma.h>
58 #include <dev/firewire/fwohcireg.h>
59 #include <dev/firewire/fwohcivar.h>
60 #include <dev/firewire/firewire_phy.h>
61
62 #undef OHCI_DEBUG
63
64 static int nocyclemaster;
65 int firewire_phydma_enable = 1;
66 SYSCTL_DECL(_hw_firewire);
67 SYSCTL_INT(_hw_firewire, OID_AUTO, nocyclemaster, CTLFLAG_RWTUN,
68         &nocyclemaster, 0, "Do not send cycle start packets");
69 SYSCTL_INT(_hw_firewire, OID_AUTO, phydma_enable, CTLFLAG_RWTUN,
70         &firewire_phydma_enable, 0, "Allow physical request DMA from firewire");
71
72 static char dbcode[16][0x10] = {"OUTM", "OUTL", "INPM", "INPL",
73                                 "STOR", "LOAD", "NOP ", "STOP",};
74
75 static char dbkey[8][0x10] = {"ST0", "ST1", "ST2", "ST3",
76                               "UNDEF", "REG", "SYS", "DEV"};
77 static char dbcond[4][0x10] = {"NEV", "C=1", "C=0", "ALL"};
78 char fwohcicode[32][0x20]= {
79         "No stat", "Undef", "long", "miss Ack err",
80         "FIFO underrun", "FIFO overrun", "desc err", "data read err",
81         "data write err", "bus reset", "timeout", "tcode err",
82         "Undef", "Undef", "unknown event", "flushed",
83         "Undef" ,"ack complete", "ack pend", "Undef",
84         "ack busy_X", "ack busy_A", "ack busy_B", "Undef",
85         "Undef", "Undef", "Undef", "ack tardy",
86         "Undef", "ack data_err", "ack type_err", ""};
87
88 #define MAX_SPEED 3
89 extern char *linkspeed[];
90 uint32_t tagbit[4] = {1 << 28, 1 << 29, 1 << 30, 1 << 31};
91
92 static struct tcode_info tinfo[] = {
93 /*              hdr_len block   flag    valid_response */
94 /* 0 WREQQ  */ {16,     FWTI_REQ | FWTI_TLABEL, FWTCODE_WRES},
95 /* 1 WREQB  */ {16,     FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_WRES},
96 /* 2 WRES   */ {12,     FWTI_RES, 0xff},
97 /* 3 XXX    */ { 0,     0, 0xff},
98 /* 4 RREQQ  */ {12,     FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESQ},
99 /* 5 RREQB  */ {16,     FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESB},
100 /* 6 RRESQ  */ {16,     FWTI_RES, 0xff},
101 /* 7 RRESB  */ {16,     FWTI_RES | FWTI_BLOCK_ASY, 0xff},
102 /* 8 CYCS   */ { 0,     0, 0xff},
103 /* 9 LREQ   */ {16,     FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_LRES},
104 /* a STREAM */ { 4,     FWTI_REQ | FWTI_BLOCK_STR, 0xff},
105 /* b LRES   */ {16,     FWTI_RES | FWTI_BLOCK_ASY, 0xff},
106 /* c XXX    */ { 0,     0, 0xff},
107 /* d XXX    */ { 0,     0, 0xff},
108 /* e PHY    */ {12,     FWTI_REQ, 0xff},
109 /* f XXX    */ { 0,     0, 0xff}
110 };
111
112 #define ATRQ_CH 0
113 #define ATRS_CH 1
114 #define ARRQ_CH 2
115 #define ARRS_CH 3
116 #define ITX_CH 4
117 #define IRX_CH 0x24
118
119 #define OHCI_WRITE_SIGMASK 0xffff0000
120 #define OHCI_READ_SIGMASK 0xffff0000
121
122 #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
123 #define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r))
124
125 static void fwohci_ibr (struct firewire_comm *);
126 static void fwohci_db_init (struct fwohci_softc *, struct fwohci_dbch *);
127 static void fwohci_db_free (struct fwohci_dbch *);
128 static void fwohci_arcv (struct fwohci_softc *, struct fwohci_dbch *, int);
129 static void fwohci_txd (struct fwohci_softc *, struct fwohci_dbch *);
130 static void fwohci_start_atq (struct firewire_comm *);
131 static void fwohci_start_ats (struct firewire_comm *);
132 static void fwohci_start (struct fwohci_softc *, struct fwohci_dbch *);
133 static uint32_t fwphy_wrdata (struct fwohci_softc *, uint32_t, uint32_t);
134 static uint32_t fwphy_rddata (struct fwohci_softc *, uint32_t);
135 static int fwohci_rx_enable (struct fwohci_softc *, struct fwohci_dbch *);
136 static int fwohci_tx_enable (struct fwohci_softc *, struct fwohci_dbch *);
137 static int fwohci_irx_enable (struct firewire_comm *, int);
138 static int fwohci_irx_disable (struct firewire_comm *, int);
139 #if BYTE_ORDER == BIG_ENDIAN
140 static void fwohci_irx_post (struct firewire_comm *, uint32_t *);
141 #endif
142 static int fwohci_itxbuf_enable (struct firewire_comm *, int);
143 static int fwohci_itx_disable (struct firewire_comm *, int);
144 static void fwohci_timeout (void *);
145 static void fwohci_set_intr (struct firewire_comm *, int);
146
147 static int fwohci_add_rx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int, struct fwdma_alloc *);
148 static int fwohci_add_tx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int);
149 static void dump_db (struct fwohci_softc *, uint32_t);
150 static void print_db (struct fwohcidb_tr *, struct fwohcidb *, uint32_t , uint32_t);
151 static void dump_dma (struct fwohci_softc *, uint32_t);
152 static uint32_t fwohci_cyctimer (struct firewire_comm *);
153 static void fwohci_rbuf_update (struct fwohci_softc *, int);
154 static void fwohci_tbuf_update (struct fwohci_softc *, int);
155 void fwohci_txbufdb (struct fwohci_softc *, int , struct fw_bulkxfer *);
156 static void fwohci_task_busreset(void *, int);
157 static void fwohci_task_sid(void *, int);
158 static void fwohci_task_dma(void *, int);
159
160 /*
161  * memory allocated for DMA programs
162  */
163 #define DMA_PROG_ALLOC          (8 * PAGE_SIZE)
164
165 #define NDB FWMAXQUEUE
166
167 #define OHCI_VERSION            0x00
168 #define OHCI_ATRETRY            0x08
169 #define OHCI_CROMHDR            0x18
170 #define OHCI_BUS_OPT            0x20
171 #define OHCI_BUSIRMC            (1U << 31)
172 #define OHCI_BUSCMC             (1 << 30)
173 #define OHCI_BUSISC             (1 << 29)
174 #define OHCI_BUSBMC             (1 << 28)
175 #define OHCI_BUSPMC             (1 << 27)
176 #define OHCI_BUSFNC             OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\
177                                 OHCI_BUSBMC | OHCI_BUSPMC
178
179 #define OHCI_EUID_HI            0x24
180 #define OHCI_EUID_LO            0x28
181
182 #define OHCI_CROMPTR            0x34
183 #define OHCI_HCCCTL             0x50
184 #define OHCI_HCCCTLCLR          0x54
185 #define OHCI_AREQHI             0x100
186 #define OHCI_AREQHICLR          0x104
187 #define OHCI_AREQLO             0x108
188 #define OHCI_AREQLOCLR          0x10c
189 #define OHCI_PREQHI             0x110
190 #define OHCI_PREQHICLR          0x114
191 #define OHCI_PREQLO             0x118
192 #define OHCI_PREQLOCLR          0x11c
193 #define OHCI_PREQUPPER          0x120
194 #define OHCI_PREQUPPER_MAX      0xffff0000
195
196 #define OHCI_SID_BUF            0x64
197 #define OHCI_SID_CNT            0x68
198 #define OHCI_SID_ERR            (1U << 31)
199 #define OHCI_SID_CNT_MASK       0xffc
200
201 #define OHCI_IT_STAT            0x90
202 #define OHCI_IT_STATCLR         0x94
203 #define OHCI_IT_MASK            0x98
204 #define OHCI_IT_MASKCLR         0x9c
205
206 #define OHCI_IR_STAT            0xa0
207 #define OHCI_IR_STATCLR         0xa4
208 #define OHCI_IR_MASK            0xa8
209 #define OHCI_IR_MASKCLR         0xac
210
211 #define OHCI_LNKCTL             0xe0
212 #define OHCI_LNKCTLCLR          0xe4
213
214 #define OHCI_PHYACCESS          0xec
215 #define OHCI_CYCLETIMER         0xf0
216
217 #define OHCI_DMACTL(off)        (off)
218 #define OHCI_DMACTLCLR(off)     (off + 4)
219 #define OHCI_DMACMD(off)        (off + 0xc)
220 #define OHCI_DMAMATCH(off)      (off + 0x10)
221
222 #define OHCI_ATQOFF             0x180
223 #define OHCI_ATQCTL             OHCI_ATQOFF
224 #define OHCI_ATQCTLCLR          (OHCI_ATQOFF + 4)
225 #define OHCI_ATQCMD             (OHCI_ATQOFF + 0xc)
226 #define OHCI_ATQMATCH           (OHCI_ATQOFF + 0x10)
227
228 #define OHCI_ATSOFF             0x1a0
229 #define OHCI_ATSCTL             OHCI_ATSOFF
230 #define OHCI_ATSCTLCLR          (OHCI_ATSOFF + 4)
231 #define OHCI_ATSCMD             (OHCI_ATSOFF + 0xc)
232 #define OHCI_ATSMATCH           (OHCI_ATSOFF + 0x10)
233
234 #define OHCI_ARQOFF             0x1c0
235 #define OHCI_ARQCTL             OHCI_ARQOFF
236 #define OHCI_ARQCTLCLR          (OHCI_ARQOFF + 4)
237 #define OHCI_ARQCMD             (OHCI_ARQOFF + 0xc)
238 #define OHCI_ARQMATCH           (OHCI_ARQOFF + 0x10)
239
240 #define OHCI_ARSOFF             0x1e0
241 #define OHCI_ARSCTL             OHCI_ARSOFF
242 #define OHCI_ARSCTLCLR          (OHCI_ARSOFF + 4)
243 #define OHCI_ARSCMD             (OHCI_ARSOFF + 0xc)
244 #define OHCI_ARSMATCH           (OHCI_ARSOFF + 0x10)
245
246 #define OHCI_ITOFF(CH)          (0x200 + 0x10 * (CH))
247 #define OHCI_ITCTL(CH)          (OHCI_ITOFF(CH))
248 #define OHCI_ITCTLCLR(CH)       (OHCI_ITOFF(CH) + 4)
249 #define OHCI_ITCMD(CH)          (OHCI_ITOFF(CH) + 0xc)
250
251 #define OHCI_IROFF(CH)          (0x400 + 0x20 * (CH))
252 #define OHCI_IRCTL(CH)          (OHCI_IROFF(CH))
253 #define OHCI_IRCTLCLR(CH)       (OHCI_IROFF(CH) + 4)
254 #define OHCI_IRCMD(CH)          (OHCI_IROFF(CH) + 0xc)
255 #define OHCI_IRMATCH(CH)        (OHCI_IROFF(CH) + 0x10)
256
257 d_ioctl_t fwohci_ioctl;
258
259 /*
260  * Communication with PHY device
261  */
262 /* XXX need lock for phy access */
263 static uint32_t
264 fwphy_wrdata(struct fwohci_softc *sc, uint32_t addr, uint32_t data)
265 {
266         uint32_t fun;
267
268         addr &= 0xf;
269         data &= 0xff;
270
271         fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) |
272               (data << PHYDEV_WRDATA));
273         OWRITE(sc, OHCI_PHYACCESS, fun);
274         DELAY(100);
275
276         return (fwphy_rddata(sc, addr));
277 }
278
279 static uint32_t
280 fwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
281 {
282         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
283         int i;
284         uint32_t bm;
285
286 #define OHCI_CSR_DATA   0x0c
287 #define OHCI_CSR_COMP   0x10
288 #define OHCI_CSR_CONT   0x14
289 #define OHCI_BUS_MANAGER_ID     0
290
291         OWRITE(sc, OHCI_CSR_DATA, node);
292         OWRITE(sc, OHCI_CSR_COMP, 0x3f);
293         OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
294         for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
295                 DELAY(10);
296         bm = OREAD(sc, OHCI_CSR_DATA);
297         if ((bm & 0x3f) == 0x3f)
298                 bm = node;
299         if (firewire_debug)
300                 device_printf(sc->fc.dev, "%s: %d->%d (loop=%d)\n",
301                                 __func__, bm, node, i);
302         return (bm);
303 }
304
305 static uint32_t
306 fwphy_rddata(struct fwohci_softc *sc, u_int addr)
307 {
308         uint32_t fun, stat;
309         u_int i, retry = 0;
310
311         addr &= 0xf;
312 #define MAX_RETRY 100
313 again:
314         OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
315         fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
316         OWRITE(sc, OHCI_PHYACCESS, fun);
317         for (i = 0; i < MAX_RETRY; i++) {
318                 fun = OREAD(sc, OHCI_PHYACCESS);
319                 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
320                         break;
321                 DELAY(100);
322         }
323         if (i >= MAX_RETRY) {
324                 if (firewire_debug)
325                         device_printf(sc->fc.dev, "%s: failed(1).\n", __func__);
326                 if (++retry < MAX_RETRY) {
327                         DELAY(100);
328                         goto again;
329                 }
330         }
331         /* Make sure that SCLK is started */
332         stat = OREAD(sc, FWOHCI_INTSTAT);
333         if ((stat & OHCI_INT_REG_FAIL) != 0 ||
334                         ((fun >> PHYDEV_REGADDR) & 0xf) != addr) {
335                 if (firewire_debug)
336                         device_printf(sc->fc.dev, "%s: failed(2).\n", __func__);
337                 if (++retry < MAX_RETRY) {
338                         DELAY(100);
339                         goto again;
340                 }
341         }
342         if (firewire_debug > 1 || retry >= MAX_RETRY)
343                 device_printf(sc->fc.dev,
344                     "%s:: 0x%x loop=%d, retry=%d\n",
345                         __func__, addr, i, retry);
346 #undef MAX_RETRY
347         return ((fun >> PHYDEV_RDDATA) & 0xff);
348 }
349
350 /* Device specific ioctl. */
351 int
352 fwohci_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
353 {
354         struct firewire_softc *sc;
355         struct fwohci_softc *fc;
356         int unit = DEV2UNIT(dev);
357         int err = 0;
358         struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data;
359         uint32_t *dmach = (uint32_t *) data;
360
361         sc = devclass_get_softc(firewire_devclass, unit);
362         if (sc == NULL)
363                 return (EINVAL);
364
365         fc = (struct fwohci_softc *)sc->fc;
366
367         if (!data)
368                 return (EINVAL);
369
370         switch (cmd) {
371         case FWOHCI_WRREG:
372 #define OHCI_MAX_REG 0x800
373                 if (reg->addr <= OHCI_MAX_REG) {
374                         OWRITE(fc, reg->addr, reg->data);
375                         reg->data = OREAD(fc, reg->addr);
376                 } else {
377                         err = EINVAL;
378                 }
379                 break;
380         case FWOHCI_RDREG:
381                 if (reg->addr <= OHCI_MAX_REG) {
382                         reg->data = OREAD(fc, reg->addr);
383                 } else {
384                         err = EINVAL;
385                 }
386                 break;
387 /* Read DMA descriptors for debug  */
388         case DUMPDMA:
389                 if (*dmach <= OHCI_MAX_DMA_CH) {
390                         dump_dma(fc, *dmach);
391                         dump_db(fc, *dmach);
392                 } else {
393                         err = EINVAL;
394                 }
395                 break;
396 /* Read/Write Phy registers */
397 #define OHCI_MAX_PHY_REG 0xf
398         case FWOHCI_RDPHYREG:
399                 if (reg->addr <= OHCI_MAX_PHY_REG)
400                         reg->data = fwphy_rddata(fc, reg->addr);
401                 else
402                         err = EINVAL;
403                 break;
404         case FWOHCI_WRPHYREG:
405                 if (reg->addr <= OHCI_MAX_PHY_REG)
406                         reg->data = fwphy_wrdata(fc, reg->addr, reg->data);
407                 else
408                         err = EINVAL;
409                 break;
410         default:
411                 err = EINVAL;
412                 break;
413         }
414         return err;
415 }
416
417 static int
418 fwohci_probe_phy(struct fwohci_softc *sc, device_t dev)
419 {
420         uint32_t reg, reg2;
421         int e1394a = 1;
422
423         /*
424          * probe PHY parameters
425          * 0. to prove PHY version, whether compliance of 1394a.
426          * 1. to probe maximum speed supported by the PHY and
427          *    number of port supported by core-logic.
428          *    It is not actually available port on your PC .
429          */
430         OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
431         DELAY(500);
432
433         reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
434
435         if ((reg >> 5) != 7) {
436                 sc->fc.mode &= ~FWPHYASYST;
437                 sc->fc.nport = reg & FW_PHY_NP;
438                 sc->fc.speed = reg & FW_PHY_SPD >> 6;
439                 if (sc->fc.speed > MAX_SPEED) {
440                         device_printf(dev, "invalid speed %d (fixed to %d).\n",
441                                 sc->fc.speed, MAX_SPEED);
442                         sc->fc.speed = MAX_SPEED;
443                 }
444                 device_printf(dev,
445                         "Phy 1394 only %s, %d ports.\n",
446                         linkspeed[sc->fc.speed], sc->fc.nport);
447         } else {
448                 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
449                 sc->fc.mode |= FWPHYASYST;
450                 sc->fc.nport = reg & FW_PHY_NP;
451                 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
452                 if (sc->fc.speed > MAX_SPEED) {
453                         device_printf(dev, "invalid speed %d (fixed to %d).\n",
454                                 sc->fc.speed, MAX_SPEED);
455                         sc->fc.speed = MAX_SPEED;
456                 }
457                 device_printf(dev,
458                         "Phy 1394a available %s, %d ports.\n",
459                         linkspeed[sc->fc.speed], sc->fc.nport);
460
461                 /* check programPhyEnable */
462                 reg2 = fwphy_rddata(sc, 5);
463 #if 0
464                 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
465 #else   /* XXX force to enable 1394a */
466                 if (e1394a) {
467 #endif
468                         if (firewire_debug)
469                                 device_printf(dev,
470                                         "Enable 1394a Enhancements\n");
471                         /* enable EAA EMC */
472                         reg2 |= 0x03;
473                         /* set aPhyEnhanceEnable */
474                         OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
475                         OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
476                 } else {
477                         /* for safe */
478                         reg2 &= ~0x83;
479                 }
480                 reg2 = fwphy_wrdata(sc, 5, reg2);
481         }
482
483         reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
484         if ((reg >> 5) == 7) {
485                 reg = fwphy_rddata(sc, 4);
486                 reg |= 1 << 6;
487                 fwphy_wrdata(sc, 4, reg);
488                 reg = fwphy_rddata(sc, 4);
489         }
490         return 0;
491 }
492
493
494 void
495 fwohci_reset(struct fwohci_softc *sc, device_t dev)
496 {
497         int i, max_rec, speed;
498         uint32_t reg, reg2;
499         struct fwohcidb_tr *db_tr;
500
501         /* Disable interrupts */
502         OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
503
504         /* Now stopping all DMA channels */
505         OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
506         OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
507         OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
508         OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
509
510         OWRITE(sc, OHCI_IR_MASKCLR, ~0);
511         for (i = 0; i < sc->fc.nisodma; i++) {
512                 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
513                 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
514         }
515
516         /* FLUSH FIFO and reset Transmitter/Receiver */
517         OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
518         if (firewire_debug)
519                 device_printf(dev, "resetting OHCI...");
520         i = 0;
521         while (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
522                 if (i++ > 100) break;
523                 DELAY(1000);
524         }
525         if (firewire_debug)
526                 printf("done (loop=%d)\n", i);
527
528         /* Probe phy */
529         fwohci_probe_phy(sc, dev);
530
531         /* Probe link */
532         reg = OREAD(sc, OHCI_BUS_OPT);
533         reg2 = reg | OHCI_BUSFNC;
534         max_rec = (reg & 0x0000f000) >> 12;
535         speed = (reg & 0x00000007);
536         device_printf(dev, "Link %s, max_rec %d bytes.\n",
537                         linkspeed[speed], MAXREC(max_rec));
538         /* XXX fix max_rec */
539         sc->fc.maxrec = sc->fc.speed + 8;
540         if (max_rec != sc->fc.maxrec) {
541                 reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12);
542                 device_printf(dev, "max_rec %d -> %d\n",
543                                 MAXREC(max_rec), MAXREC(sc->fc.maxrec));
544         }
545         if (firewire_debug)
546                 device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
547         OWRITE(sc, OHCI_BUS_OPT, reg2);
548
549         /* Initialize registers */
550         OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
551         OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr);
552         OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
553         OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
554         OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr);
555         OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
556
557         /* Enable link */
558         OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
559
560         /* Force to start async RX DMA */
561         sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING;
562         sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING;
563         fwohci_rx_enable(sc, &sc->arrq);
564         fwohci_rx_enable(sc, &sc->arrs);
565
566         /* Initialize async TX */
567         OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
568         OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
569
570         /* AT Retries */
571         OWRITE(sc, FWOHCI_RETRY,
572                 /* CycleLimit   PhyRespRetries ATRespRetries ATReqRetries */
573                 (0xffff << 16) | (0x0f << 8) | (0x0f << 4) | 0x0f);
574
575         sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq);
576         sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq);
577         sc->atrq.bottom = sc->atrq.top;
578         sc->atrs.bottom = sc->atrs.top;
579
580         for (i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb;
581             i++, db_tr = STAILQ_NEXT(db_tr, link)) {
582                 db_tr->xfer = NULL;
583         }
584         for (i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb;
585             i++, db_tr = STAILQ_NEXT(db_tr, link)) {
586                 db_tr->xfer = NULL;
587         }
588
589         /* Enable interrupts */
590         sc->intmask =  (OHCI_INT_ERR  | OHCI_INT_PHY_SID
591                         | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
592                         | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
593                         | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
594         sc->intmask |=  OHCI_INT_DMA_IR | OHCI_INT_DMA_IT;
595         sc->intmask |=  OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT;
596         OWRITE(sc, FWOHCI_INTMASK, sc->intmask);
597         fwohci_set_intr(&sc->fc, 1);
598 }
599
600 int
601 fwohci_init(struct fwohci_softc *sc, device_t dev)
602 {
603         int i, mver;
604         uint32_t reg;
605         uint8_t ui[8];
606
607 /* OHCI version */
608         reg = OREAD(sc, OHCI_VERSION);
609         mver = (reg >> 16) & 0xff;
610         device_printf(dev, "OHCI version %x.%x (ROM=%d)\n",
611                         mver, reg & 0xff, (reg >> 24) & 1);
612         if (mver < 1 || mver > 9) {
613                 device_printf(dev, "invalid OHCI version\n");
614                 return (ENXIO);
615         }
616
617 /* Available Isochronous DMA channel probe */
618         OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
619         OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
620         reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
621         OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
622         OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
623         for (i = 0; i < 0x20; i++)
624                 if ((reg & (1 << i)) == 0)
625                         break;
626         sc->fc.nisodma = i;
627         device_printf(dev, "No. of Isochronous channels is %d.\n", i);
628         if (i == 0)
629                 return (ENXIO);
630
631         sc->fc.arq = &sc->arrq.xferq;
632         sc->fc.ars = &sc->arrs.xferq;
633         sc->fc.atq = &sc->atrq.xferq;
634         sc->fc.ats = &sc->atrs.xferq;
635
636         sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
637         sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
638         sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
639         sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
640
641         sc->arrq.xferq.start = NULL;
642         sc->arrs.xferq.start = NULL;
643         sc->atrq.xferq.start = fwohci_start_atq;
644         sc->atrs.xferq.start = fwohci_start_ats;
645
646         sc->arrq.xferq.buf = NULL;
647         sc->arrs.xferq.buf = NULL;
648         sc->atrq.xferq.buf = NULL;
649         sc->atrs.xferq.buf = NULL;
650
651         sc->arrq.xferq.dmach = -1;
652         sc->arrs.xferq.dmach = -1;
653         sc->atrq.xferq.dmach = -1;
654         sc->atrs.xferq.dmach = -1;
655
656         sc->arrq.ndesc = 1;
657         sc->arrs.ndesc = 1;
658         sc->atrq.ndesc = 8;     /* equal to maximum of mbuf chains */
659         sc->atrs.ndesc = 2;
660
661         sc->arrq.ndb = NDB;
662         sc->arrs.ndb = NDB / 2;
663         sc->atrq.ndb = NDB;
664         sc->atrs.ndb = NDB / 2;
665
666         for (i = 0; i < sc->fc.nisodma; i++) {
667                 sc->fc.it[i] = &sc->it[i].xferq;
668                 sc->fc.ir[i] = &sc->ir[i].xferq;
669                 sc->it[i].xferq.dmach = i;
670                 sc->ir[i].xferq.dmach = i;
671                 sc->it[i].ndb = 0;
672                 sc->ir[i].ndb = 0;
673         }
674
675         sc->fc.tcode = tinfo;
676         sc->fc.dev = dev;
677
678         sc->fc.config_rom = fwdma_malloc(&sc->fc, CROMSIZE, CROMSIZE,
679             &sc->crom_dma, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
680         if (sc->fc.config_rom == NULL) {
681                 device_printf(dev, "config_rom alloc failed.");
682                 return ENOMEM;
683         }
684
685 #if 0
686         bzero(&sc->fc.config_rom[0], CROMSIZE);
687         sc->fc.config_rom[1] = 0x31333934;
688         sc->fc.config_rom[2] = 0xf000a002;
689         sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
690         sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
691         sc->fc.config_rom[5] = 0;
692         sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
693
694         sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
695 #endif
696
697 /* SID receive buffer must align 2^11 */
698 #define OHCI_SIDSIZE    (1 << 11)
699         sc->sid_buf = fwdma_malloc(&sc->fc, OHCI_SIDSIZE, OHCI_SIDSIZE,
700             &sc->sid_dma, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
701         if (sc->sid_buf == NULL) {
702                 device_printf(dev, "sid_buf alloc failed.");
703                 return ENOMEM;
704         }
705
706         fwdma_malloc(&sc->fc, sizeof(uint32_t), sizeof(uint32_t),
707             &sc->dummy_dma, BUS_DMA_WAITOK);
708
709         if (sc->dummy_dma.v_addr == NULL) {
710                 device_printf(dev, "dummy_dma alloc failed.");
711                 return ENOMEM;
712         }
713
714         fwohci_db_init(sc, &sc->arrq);
715         if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0)
716                 return ENOMEM;
717
718         fwohci_db_init(sc, &sc->arrs);
719         if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0)
720                 return ENOMEM;
721
722         fwohci_db_init(sc, &sc->atrq);
723         if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0)
724                 return ENOMEM;
725
726         fwohci_db_init(sc, &sc->atrs);
727         if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0)
728                 return ENOMEM;
729
730         sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H);
731         sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L);
732         for (i = 0; i < 8; i++)
733                 ui[i] = FW_EUI64_BYTE(&sc->fc.eui,i);
734         device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
735                 ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]);
736
737         sc->fc.ioctl = fwohci_ioctl;
738         sc->fc.cyctimer = fwohci_cyctimer;
739         sc->fc.set_bmr = fwohci_set_bus_manager;
740         sc->fc.ibr = fwohci_ibr;
741         sc->fc.irx_enable = fwohci_irx_enable;
742         sc->fc.irx_disable = fwohci_irx_disable;
743
744         sc->fc.itx_enable = fwohci_itxbuf_enable;
745         sc->fc.itx_disable = fwohci_itx_disable;
746 #if BYTE_ORDER == BIG_ENDIAN
747         sc->fc.irx_post = fwohci_irx_post;
748 #else
749         sc->fc.irx_post = NULL;
750 #endif
751         sc->fc.itx_post = NULL;
752         sc->fc.timeout = fwohci_timeout;
753         sc->fc.poll = fwohci_poll;
754         sc->fc.set_intr = fwohci_set_intr;
755
756         sc->intmask = sc->irstat = sc->itstat = 0;
757
758         /* Init task queue */
759         sc->fc.taskqueue = taskqueue_create_fast("fw_taskq", M_WAITOK,
760                 taskqueue_thread_enqueue, &sc->fc.taskqueue);
761         taskqueue_start_threads(&sc->fc.taskqueue, 1, PI_NET, "fw%d_taskq",
762                 device_get_unit(dev));
763         TASK_INIT(&sc->fwohci_task_busreset, 2, fwohci_task_busreset, sc);
764         TASK_INIT(&sc->fwohci_task_sid, 1, fwohci_task_sid, sc);
765         TASK_INIT(&sc->fwohci_task_dma, 0, fwohci_task_dma, sc);
766
767         fw_init(&sc->fc);
768         fwohci_reset(sc, dev);
769
770         return 0;
771 }
772
773 void
774 fwohci_timeout(void *arg)
775 {
776         struct fwohci_softc *sc;
777
778         sc = (struct fwohci_softc *)arg;
779 }
780
781 uint32_t
782 fwohci_cyctimer(struct firewire_comm *fc)
783 {
784         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
785         return (OREAD(sc, OHCI_CYCLETIMER));
786 }
787
788 int
789 fwohci_detach(struct fwohci_softc *sc, device_t dev)
790 {
791         int i;
792
793         if (sc->sid_buf != NULL)
794                 fwdma_free(&sc->fc, &sc->sid_dma);
795         if (sc->fc.config_rom != NULL)
796                 fwdma_free(&sc->fc, &sc->crom_dma);
797
798         fwohci_db_free(&sc->arrq);
799         fwohci_db_free(&sc->arrs);
800
801         fwohci_db_free(&sc->atrq);
802         fwohci_db_free(&sc->atrs);
803
804         for (i = 0; i < sc->fc.nisodma; i++) {
805                 fwohci_db_free(&sc->it[i]);
806                 fwohci_db_free(&sc->ir[i]);
807         }
808         if (sc->fc.taskqueue != NULL) {
809                 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_busreset);
810                 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_sid);
811                 taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_dma);
812                 taskqueue_drain(sc->fc.taskqueue, &sc->fc.task_timeout);
813                 taskqueue_free(sc->fc.taskqueue);
814                 sc->fc.taskqueue = NULL;
815         }
816
817         return 0;
818 }
819
820 #define LAST_DB(dbtr, db) do {                                          \
821         struct fwohcidb_tr *_dbtr = (dbtr);                             \
822         int _cnt = _dbtr->dbcnt;                                        \
823         db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0];                   \
824 } while (0)
825
826 static void
827 fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error)
828 {
829         struct fwohcidb_tr *db_tr;
830         struct fwohcidb *db;
831         bus_dma_segment_t *s;
832         int i;
833
834         db_tr = (struct fwohcidb_tr *)arg;
835         db = &db_tr->db[db_tr->dbcnt];
836         if (error) {
837                 if (firewire_debug || error != EFBIG)
838                         printf("fwohci_execute_db: error=%d\n", error);
839                 return;
840         }
841         for (i = 0; i < nseg; i++) {
842                 s = &segs[i];
843                 FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr);
844                 FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len);
845                 FWOHCI_DMA_WRITE(db->db.desc.res, 0);
846                 db++;
847                 db_tr->dbcnt++;
848         }
849 }
850
851 static void
852 fwohci_execute_db2(void *arg, bus_dma_segment_t *segs, int nseg,
853     bus_size_t size, int error)
854 {
855         fwohci_execute_db(arg, segs, nseg, error);
856 }
857
858 static void
859 fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
860 {
861         int i;
862         int tcode, hdr_len, pl_off;
863         int fsegment = -1;
864         uint32_t off;
865         struct fw_xfer *xfer;
866         struct fw_pkt *fp;
867         struct fwohci_txpkthdr *ohcifp;
868         struct fwohcidb_tr *db_tr;
869         struct fwohcidb *db;
870         uint32_t *ld;
871         struct tcode_info *info;
872         static int maxdesc=0;
873
874         FW_GLOCK_ASSERT(&sc->fc);
875
876         if (&sc->atrq == dbch) {
877                 off = OHCI_ATQOFF;
878         } else if (&sc->atrs == dbch) {
879                 off = OHCI_ATSOFF;
880         } else {
881                 return;
882         }
883
884         if (dbch->flags & FWOHCI_DBCH_FULL)
885                 return;
886
887         db_tr = dbch->top;
888 txloop:
889         xfer = STAILQ_FIRST(&dbch->xferq.q);
890         if (xfer == NULL) {
891                 goto kick;
892         }
893 #if 0
894         if (dbch->xferq.queued == 0) {
895                 device_printf(sc->fc.dev, "TX queue empty\n");
896         }
897 #endif
898         STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
899         db_tr->xfer = xfer;
900         xfer->flag = FWXF_START;
901
902         fp = &xfer->send.hdr;
903         tcode = fp->mode.common.tcode;
904
905         ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
906         info = &tinfo[tcode];
907         hdr_len = pl_off = info->hdr_len;
908
909         ld = &ohcifp->mode.ld[0];
910         ld[0] = ld[1] = ld[2] = ld[3] = 0;
911         for (i = 0; i < pl_off; i+= 4)
912                 ld[i/4] = fp->mode.ld[i/4];
913
914         ohcifp->mode.common.spd = xfer->send.spd & 0x7;
915         if (tcode == FWTCODE_STREAM) {
916                 hdr_len = 8;
917                 ohcifp->mode.stream.len = fp->mode.stream.len;
918         } else if (tcode == FWTCODE_PHY) {
919                 hdr_len = 12;
920                 ld[1] = fp->mode.ld[1];
921                 ld[2] = fp->mode.ld[2];
922                 ohcifp->mode.common.spd = 0;
923                 ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
924         } else {
925                 ohcifp->mode.asycomm.dst = fp->mode.hdr.dst;
926                 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
927                 ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
928         }
929         db = &db_tr->db[0];
930         FWOHCI_DMA_WRITE(db->db.desc.cmd,
931                         OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len);
932         FWOHCI_DMA_WRITE(db->db.desc.addr, 0);
933         FWOHCI_DMA_WRITE(db->db.desc.res, 0);
934 /* Specify bound timer of asy. response */
935         if (&sc->atrs == dbch) {
936                 FWOHCI_DMA_WRITE(db->db.desc.res,
937                          (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13));
938         }
939 #if BYTE_ORDER == BIG_ENDIAN
940         if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ)
941                 hdr_len = 12;
942         for (i = 0; i < hdr_len/4; i++)
943                 FWOHCI_DMA_WRITE(ld[i], ld[i]);
944 #endif
945
946 again:
947         db_tr->dbcnt = 2;
948         db = &db_tr->db[db_tr->dbcnt];
949         if (xfer->send.pay_len > 0) {
950                 int err;
951                 /* handle payload */
952                 if (xfer->mbuf == NULL) {
953                         err = bus_dmamap_load(dbch->dmat, db_tr->dma_map,
954                                 &xfer->send.payload[0], xfer->send.pay_len,
955                                 fwohci_execute_db, db_tr,
956                                 /*flags*/0);
957                 } else {
958                         /* XXX we can handle only 6 (=8-2) mbuf chains */
959                         err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
960                                 xfer->mbuf,
961                                 fwohci_execute_db2, db_tr,
962                                 /* flags */0);
963                         if (err == EFBIG) {
964                                 struct mbuf *m0;
965
966                                 if (firewire_debug)
967                                         device_printf(sc->fc.dev, "EFBIG.\n");
968                                 m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
969                                 if (m0 != NULL) {
970                                         m_copydata(xfer->mbuf, 0,
971                                                 xfer->mbuf->m_pkthdr.len,
972                                                 mtod(m0, caddr_t));
973                                         m0->m_len = m0->m_pkthdr.len =
974                                                 xfer->mbuf->m_pkthdr.len;
975                                         m_freem(xfer->mbuf);
976                                         xfer->mbuf = m0;
977                                         goto again;
978                                 }
979                                 device_printf(sc->fc.dev, "m_getcl failed.\n");
980                         }
981                 }
982                 if (err)
983                         printf("dmamap_load: err=%d\n", err);
984                 bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
985                                                 BUS_DMASYNC_PREWRITE);
986 #if 0 /* OHCI_OUTPUT_MODE == 0 */
987                 for (i = 2; i < db_tr->dbcnt; i++)
988                         FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd,
989                                                 OHCI_OUTPUT_MORE);
990 #endif
991         }
992         if (maxdesc < db_tr->dbcnt) {
993                 maxdesc = db_tr->dbcnt;
994                 if (firewire_debug)
995                         device_printf(sc->fc.dev, "%s: maxdesc %d\n", __func__, maxdesc);
996         }
997         /* last db */
998         LAST_DB(db_tr, db);
999         FWOHCI_DMA_SET(db->db.desc.cmd,
1000                 OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1001         FWOHCI_DMA_WRITE(db->db.desc.depend,
1002                         STAILQ_NEXT(db_tr, link)->bus_addr);
1003
1004         if (fsegment == -1)
1005                 fsegment = db_tr->dbcnt;
1006         if (dbch->pdb_tr != NULL) {
1007                 LAST_DB(dbch->pdb_tr, db);
1008                 FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt);
1009         }
1010         dbch->xferq.queued++;
1011         dbch->pdb_tr = db_tr;
1012         db_tr = STAILQ_NEXT(db_tr, link);
1013         if (db_tr != dbch->bottom) {
1014                 goto txloop;
1015         } else {
1016                 device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n");
1017                 dbch->flags |= FWOHCI_DBCH_FULL;
1018         }
1019 kick:
1020         /* kick asy q */
1021         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1022         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1023
1024         if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1025                 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
1026         } else {
1027                 if (firewire_debug)
1028                         device_printf(sc->fc.dev, "start AT DMA status=%x\n",
1029                                         OREAD(sc, OHCI_DMACTL(off)));
1030                 OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | fsegment);
1031                 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1032                 dbch->xferq.flag |= FWXFERQ_RUNNING;
1033         }
1034
1035         dbch->top = db_tr;
1036         return;
1037 }
1038
1039 static void
1040 fwohci_start_atq(struct firewire_comm *fc)
1041 {
1042         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1043         FW_GLOCK(&sc->fc);
1044         fwohci_start(sc, &(sc->atrq));
1045         FW_GUNLOCK(&sc->fc);
1046         return;
1047 }
1048
1049 static void
1050 fwohci_start_ats(struct firewire_comm *fc)
1051 {
1052         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1053         FW_GLOCK(&sc->fc);
1054         fwohci_start(sc, &(sc->atrs));
1055         FW_GUNLOCK(&sc->fc);
1056         return;
1057 }
1058
1059 void
1060 fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1061 {
1062         int s, ch, err = 0;
1063         struct fwohcidb_tr *tr;
1064         struct fwohcidb *db;
1065         struct fw_xfer *xfer;
1066         uint32_t off;
1067         u_int stat, status;
1068         int     packets;
1069         struct firewire_comm *fc = (struct firewire_comm *)sc;
1070
1071         if (&sc->atrq == dbch) {
1072                 off = OHCI_ATQOFF;
1073                 ch = ATRQ_CH;
1074         } else if (&sc->atrs == dbch) {
1075                 off = OHCI_ATSOFF;
1076                 ch = ATRS_CH;
1077         } else {
1078                 return;
1079         }
1080         s = splfw();
1081         tr = dbch->bottom;
1082         packets = 0;
1083         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
1084         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
1085         while (dbch->xferq.queued > 0) {
1086                 LAST_DB(tr, db);
1087                 status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT;
1088                 if (!(status & OHCI_CNTL_DMA_ACTIVE)) {
1089                         if (fc->status != FWBUSINIT)
1090                                 /* maybe out of order?? */
1091                                 goto out;
1092                 }
1093                 bus_dmamap_sync(dbch->dmat, tr->dma_map,
1094                         BUS_DMASYNC_POSTWRITE);
1095                 bus_dmamap_unload(dbch->dmat, tr->dma_map);
1096 #if 1
1097                 if (firewire_debug > 1)
1098                         dump_db(sc, ch);
1099 #endif
1100                 if (status & OHCI_CNTL_DMA_DEAD) {
1101                         /* Stop DMA */
1102                         OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
1103                         device_printf(sc->fc.dev, "force reset AT FIFO\n");
1104                         OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
1105                         OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
1106                         OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
1107                 }
1108                 stat = status & FWOHCIEV_MASK;
1109                 switch (stat) {
1110                 case FWOHCIEV_ACKPEND:
1111                 case FWOHCIEV_ACKCOMPL:
1112                         err = 0;
1113                         break;
1114                 case FWOHCIEV_ACKBSA:
1115                 case FWOHCIEV_ACKBSB:
1116                 case FWOHCIEV_ACKBSX:
1117                         err = EBUSY;
1118                         break;
1119                 case FWOHCIEV_FLUSHED:
1120                 case FWOHCIEV_ACKTARD:
1121                         err = EAGAIN;
1122                         break;
1123                 case FWOHCIEV_MISSACK:
1124                 case FWOHCIEV_UNDRRUN:
1125                 case FWOHCIEV_OVRRUN:
1126                 case FWOHCIEV_DESCERR:
1127                 case FWOHCIEV_DTRDERR:
1128                 case FWOHCIEV_TIMEOUT:
1129                 case FWOHCIEV_TCODERR:
1130                 case FWOHCIEV_UNKNOWN:
1131                 case FWOHCIEV_ACKDERR:
1132                 case FWOHCIEV_ACKTERR:
1133                 default:
1134                         err = EINVAL;
1135                         break;
1136                 }
1137                 if (tr->xfer != NULL) {
1138                         xfer = tr->xfer;
1139                         if (xfer->flag & FWXF_RCVD) {
1140 #if 0
1141                                 if (firewire_debug)
1142                                         printf("already rcvd\n");
1143 #endif
1144                                 fw_xfer_done(xfer);
1145                         } else {
1146                                 microtime(&xfer->tv);
1147                                 xfer->flag = FWXF_SENT;
1148                                 if (err == EBUSY) {
1149                                         xfer->flag = FWXF_BUSY;
1150                                         xfer->resp = err;
1151                                         xfer->recv.pay_len = 0;
1152                                         fw_xfer_done(xfer);
1153                                 } else if (stat != FWOHCIEV_ACKPEND) {
1154                                         if (stat != FWOHCIEV_ACKCOMPL)
1155                                                 xfer->flag = FWXF_SENTERR;
1156                                         xfer->resp = err;
1157                                         xfer->recv.pay_len = 0;
1158                                         fw_xfer_done(xfer);
1159                                 }
1160                         }
1161                         /*
1162                          * The watchdog timer takes care of split
1163                          * transaction timeout for ACKPEND case.
1164                          */
1165                 } else {
1166                         printf("this shouldn't happen\n");
1167                 }
1168                 FW_GLOCK(fc);
1169                 dbch->xferq.queued--;
1170                 FW_GUNLOCK(fc);
1171                 tr->xfer = NULL;
1172
1173                 packets++;
1174                 tr = STAILQ_NEXT(tr, link);
1175                 dbch->bottom = tr;
1176                 if (dbch->bottom == dbch->top) {
1177                         /* we reaches the end of context program */
1178                         if (firewire_debug && dbch->xferq.queued > 0)
1179                                 printf("queued > 0\n");
1180                         break;
1181                 }
1182         }
1183 out:
1184         if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
1185                 printf("make free slot\n");
1186                 dbch->flags &= ~FWOHCI_DBCH_FULL;
1187                 FW_GLOCK(fc);
1188                 fwohci_start(sc, dbch);
1189                 FW_GUNLOCK(fc);
1190         }
1191         splx(s);
1192 }
1193
1194 static void
1195 fwohci_db_free(struct fwohci_dbch *dbch)
1196 {
1197         struct fwohcidb_tr *db_tr;
1198         int idb;
1199
1200         if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1201                 return;
1202
1203         for (db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0; idb < dbch->ndb;
1204             db_tr = STAILQ_NEXT(db_tr, link), idb++) {
1205                 if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 &&
1206                     db_tr->buf != NULL) {
1207                         fwdma_free_size(dbch->dmat, db_tr->dma_map,
1208                                         db_tr->buf, dbch->xferq.psize);
1209                         db_tr->buf = NULL;
1210                 } else if (db_tr->dma_map != NULL)
1211                         bus_dmamap_destroy(dbch->dmat, db_tr->dma_map);
1212         }
1213         dbch->ndb = 0;
1214         db_tr = STAILQ_FIRST(&dbch->db_trq);
1215         fwdma_free_multiseg(dbch->am);
1216         free(db_tr, M_FW);
1217         STAILQ_INIT(&dbch->db_trq);
1218         dbch->flags &= ~FWOHCI_DBCH_INIT;
1219 }
1220
1221 static void
1222 fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1223 {
1224         int     idb;
1225         struct fwohcidb_tr *db_tr;
1226
1227         if ((dbch->flags & FWOHCI_DBCH_INIT) != 0)
1228                 goto out;
1229
1230         /* create dma_tag for buffers */
1231 #define MAX_REQCOUNT    0xffff
1232         if (bus_dma_tag_create(/*parent*/ sc->fc.dmat,
1233                         /*alignment*/ 1, /*boundary*/ 0,
1234                         /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT,
1235                         /*highaddr*/ BUS_SPACE_MAXADDR,
1236                         /*filter*/NULL, /*filterarg*/NULL,
1237                         /*maxsize*/ dbch->xferq.psize,
1238                         /*nsegments*/ dbch->ndesc > 3 ? dbch->ndesc - 2 : 1,
1239                         /*maxsegsz*/ MAX_REQCOUNT,
1240                         /*flags*/ 0,
1241                         /*lockfunc*/busdma_lock_mutex,
1242                         /*lockarg*/FW_GMTX(&sc->fc),
1243                         &dbch->dmat))
1244                 return;
1245
1246         /* allocate DB entries and attach one to each DMA channels */
1247         /* DB entry must start at 16 bytes bounary. */
1248         STAILQ_INIT(&dbch->db_trq);
1249         db_tr = (struct fwohcidb_tr *)
1250                 malloc(sizeof(struct fwohcidb_tr) * dbch->ndb,
1251                 M_FW, M_WAITOK | M_ZERO);
1252
1253 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1254         dbch->am = fwdma_malloc_multiseg(&sc->fc, sizeof(struct fwohcidb),
1255                 DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK);
1256         if (dbch->am == NULL) {
1257                 printf("fwohci_db_init: fwdma_malloc_multiseg failed\n");
1258                 free(db_tr, M_FW);
1259                 return;
1260         }
1261         /* Attach DB to DMA ch. */
1262         for (idb = 0; idb < dbch->ndb; idb++) {
1263                 db_tr->dbcnt = 0;
1264                 db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1265                 db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1266                 /* create dmamap for buffers */
1267                 /* XXX do we need 4bytes alignment tag? */
1268                 /* XXX don't alloc dma_map for AR */
1269                 if (bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) {
1270                         printf("bus_dmamap_create failed\n");
1271                         dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1272                         fwohci_db_free(dbch);
1273                         return;
1274                 }
1275                 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1276                 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1277                         if (idb % dbch->xferq.bnpacket == 0)
1278                                 dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1279                                                 ].start = (caddr_t)db_tr;
1280                         if ((idb + 1) % dbch->xferq.bnpacket == 0)
1281                                 dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1282                                                 ].end = (caddr_t)db_tr;
1283                 }
1284                 db_tr++;
1285         }
1286         STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1287                         = STAILQ_FIRST(&dbch->db_trq);
1288 out:
1289         dbch->xferq.queued = 0;
1290         dbch->pdb_tr = NULL;
1291         dbch->top = STAILQ_FIRST(&dbch->db_trq);
1292         dbch->bottom = dbch->top;
1293         dbch->flags = FWOHCI_DBCH_INIT;
1294 }
1295
1296 static int
1297 fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1298 {
1299         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1300
1301         OWRITE(sc, OHCI_ITCTLCLR(dmach),
1302                         OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1303         OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1304         OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1305         /* XXX we cannot free buffers until the DMA really stops */
1306         pause("fwitxd", hz);
1307         fwohci_db_free(&sc->it[dmach]);
1308         sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1309         return 0;
1310 }
1311
1312 static int
1313 fwohci_irx_disable(struct firewire_comm *fc, int dmach)
1314 {
1315         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1316
1317         OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1318         OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1319         OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1320         /* XXX we cannot free buffers until the DMA really stops */
1321         pause("fwirxd", hz);
1322         fwohci_db_free(&sc->ir[dmach]);
1323         sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1324         return 0;
1325 }
1326
1327 #if BYTE_ORDER == BIG_ENDIAN
1328 static void
1329 fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld)
1330 {
1331         qld[0] = FWOHCI_DMA_READ(qld[0]);
1332         return;
1333 }
1334 #endif
1335
1336 static int
1337 fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1338 {
1339         int err = 0;
1340         int idb, z, i, dmach = 0, ldesc;
1341         uint32_t off = 0;
1342         struct fwohcidb_tr *db_tr;
1343         struct fwohcidb *db;
1344
1345         if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) {
1346                 err = EINVAL;
1347                 return err;
1348         }
1349         z = dbch->ndesc;
1350         for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1351                 if (&sc->it[dmach] == dbch) {
1352                         off = OHCI_ITOFF(dmach);
1353                         break;
1354                 }
1355         }
1356         if (off == 0) {
1357                 err = EINVAL;
1358                 return err;
1359         }
1360         if (dbch->xferq.flag & FWXFERQ_RUNNING)
1361                 return err;
1362         dbch->xferq.flag |= FWXFERQ_RUNNING;
1363         for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1364                 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1365         }
1366         db_tr = dbch->top;
1367         for (idb = 0; idb < dbch->ndb; idb++) {
1368                 fwohci_add_tx_buf(dbch, db_tr, idb);
1369                 if (STAILQ_NEXT(db_tr, link) == NULL) {
1370                         break;
1371                 }
1372                 db = db_tr->db;
1373                 ldesc = db_tr->dbcnt - 1;
1374                 FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1375                                 STAILQ_NEXT(db_tr, link)->bus_addr | z);
1376                 db[ldesc].db.desc.depend = db[0].db.desc.depend;
1377                 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1378                         if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1379                                 FWOHCI_DMA_SET(
1380                                         db[ldesc].db.desc.cmd,
1381                                         OHCI_INTERRUPT_ALWAYS);
1382                                 /* OHCI 1.1 and above */
1383                                 FWOHCI_DMA_SET(
1384                                         db[0].db.desc.cmd,
1385                                         OHCI_INTERRUPT_ALWAYS);
1386                         }
1387                 }
1388                 db_tr = STAILQ_NEXT(db_tr, link);
1389         }
1390         FWOHCI_DMA_CLEAR(
1391                 dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1392         return err;
1393 }
1394
1395 static int
1396 fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1397 {
1398         int err = 0;
1399         int idb, z, i, dmach = 0, ldesc;
1400         uint32_t off = 0;
1401         struct fwohcidb_tr *db_tr;
1402         struct fwohcidb *db;
1403
1404         z = dbch->ndesc;
1405         if (&sc->arrq == dbch) {
1406                 off = OHCI_ARQOFF;
1407         } else if (&sc->arrs == dbch) {
1408                 off = OHCI_ARSOFF;
1409         } else {
1410                 for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1411                         if (&sc->ir[dmach] == dbch) {
1412                                 off = OHCI_IROFF(dmach);
1413                                 break;
1414                         }
1415                 }
1416         }
1417         if (off == 0) {
1418                 err = EINVAL;
1419                 return err;
1420         }
1421         if (dbch->xferq.flag & FWXFERQ_STREAM) {
1422                 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1423                         return err;
1424         } else {
1425                 if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1426                         err = EBUSY;
1427                         return err;
1428                 }
1429         }
1430         dbch->xferq.flag |= FWXFERQ_RUNNING;
1431         dbch->top = STAILQ_FIRST(&dbch->db_trq);
1432         for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1433                 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1434         }
1435         db_tr = dbch->top;
1436         for (idb = 0; idb < dbch->ndb; idb++) {
1437                 fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1438                 if (STAILQ_NEXT(db_tr, link) == NULL)
1439                         break;
1440                 db = db_tr->db;
1441                 ldesc = db_tr->dbcnt - 1;
1442                 FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1443                         STAILQ_NEXT(db_tr, link)->bus_addr | z);
1444                 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1445                         if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1446                                 FWOHCI_DMA_SET(
1447                                         db[ldesc].db.desc.cmd,
1448                                         OHCI_INTERRUPT_ALWAYS);
1449                                 FWOHCI_DMA_CLEAR(
1450                                         db[ldesc].db.desc.depend,
1451                                         0xf);
1452                         }
1453                 }
1454                 db_tr = STAILQ_NEXT(db_tr, link);
1455         }
1456         FWOHCI_DMA_CLEAR(
1457                 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf);
1458         dbch->buf_offset = 0;
1459         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1460         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1461         if (dbch->xferq.flag & FWXFERQ_STREAM) {
1462                 return err;
1463         } else {
1464                 OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z);
1465         }
1466         OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1467         return err;
1468 }
1469
1470 static int
1471 fwohci_next_cycle(struct firewire_comm *fc, int cycle_now)
1472 {
1473         int sec, cycle, cycle_match;
1474
1475         cycle = cycle_now & 0x1fff;
1476         sec = cycle_now >> 13;
1477 #define CYCLE_MOD       0x10
1478 #if 1
1479 #define CYCLE_DELAY     8       /* min delay to start DMA */
1480 #else
1481 #define CYCLE_DELAY     7000    /* min delay to start DMA */
1482 #endif
1483         cycle = cycle + CYCLE_DELAY;
1484         if (cycle >= 8000) {
1485                 sec++;
1486                 cycle -= 8000;
1487         }
1488         cycle = roundup2(cycle, CYCLE_MOD);
1489         if (cycle >= 8000) {
1490                 sec++;
1491                 if (cycle == 8000)
1492                         cycle = 0;
1493                 else
1494                         cycle = CYCLE_MOD;
1495         }
1496         cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1497
1498         return (cycle_match);
1499 }
1500
1501 static int
1502 fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1503 {
1504         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1505         int err = 0;
1506         unsigned short tag, ich;
1507         struct fwohci_dbch *dbch;
1508         int cycle_match, cycle_now, s, ldesc;
1509         uint32_t stat;
1510         struct fw_bulkxfer *first, *chunk, *prev;
1511         struct fw_xferq *it;
1512
1513         dbch = &sc->it[dmach];
1514         it = &dbch->xferq;
1515
1516         tag = (it->flag >> 6) & 3;
1517         ich = it->flag & 0x3f;
1518         if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
1519                 dbch->ndb = it->bnpacket * it->bnchunk;
1520                 dbch->ndesc = 3;
1521                 fwohci_db_init(sc, dbch);
1522                 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1523                         return ENOMEM;
1524
1525                 err = fwohci_tx_enable(sc, dbch);
1526         }
1527         if (err)
1528                 return err;
1529
1530         ldesc = dbch->ndesc - 1;
1531         s = splfw();
1532         FW_GLOCK(fc);
1533         prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1534         while  ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1535                 struct fwohcidb *db;
1536
1537                 fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
1538                                         BUS_DMASYNC_PREWRITE);
1539                 fwohci_txbufdb(sc, dmach, chunk);
1540                 if (prev != NULL) {
1541                         db = ((struct fwohcidb_tr *)(prev->end))->db;
1542 #if 0 /* XXX necessary? */
1543                         FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1544                                                 OHCI_BRANCH_ALWAYS);
1545 #endif
1546 #if 0 /* if bulkxfer->npacket changes */
1547                         db[ldesc].db.desc.depend = db[0].db.desc.depend =
1548                                 ((struct fwohcidb_tr *)
1549                                 (chunk->start))->bus_addr | dbch->ndesc;
1550 #else
1551                         FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
1552                         FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1553 #endif
1554                 }
1555                 STAILQ_REMOVE_HEAD(&it->stvalid, link);
1556                 STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
1557                 prev = chunk;
1558         }
1559         FW_GUNLOCK(fc);
1560         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1561         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1562         splx(s);
1563         stat = OREAD(sc, OHCI_ITCTL(dmach));
1564         if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
1565                 printf("stat 0x%x\n", stat);
1566
1567         if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
1568                 return 0;
1569
1570 #if 0
1571         OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1572 #endif
1573         OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1574         OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1575         OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1576         OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1577
1578         first = STAILQ_FIRST(&it->stdma);
1579         OWRITE(sc, OHCI_ITCMD(dmach),
1580                 ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
1581         if (firewire_debug > 1) {
1582                 printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
1583 #if 1
1584                 dump_dma(sc, ITX_CH + dmach);
1585 #endif
1586         }
1587         if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
1588 #if 1
1589                 /* Don't start until all chunks are buffered */
1590                 if (STAILQ_FIRST(&it->stfree) != NULL)
1591                         goto out;
1592 #endif
1593 #if 1
1594                 /* Clear cycle match counter bits */
1595                 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1596
1597                 /* 2bit second + 13bit cycle */
1598                 cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1599                 cycle_match = fwohci_next_cycle(fc, cycle_now);
1600
1601                 OWRITE(sc, OHCI_ITCTL(dmach),
1602                                 OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
1603                                 | OHCI_CNTL_DMA_RUN);
1604 #else
1605                 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1606 #endif
1607                 if (firewire_debug > 1) {
1608                         printf("cycle_match: 0x%04x->0x%04x\n",
1609                                                 cycle_now, cycle_match);
1610                         dump_dma(sc, ITX_CH + dmach);
1611                         dump_db(sc, ITX_CH + dmach);
1612                 }
1613         } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1614                 device_printf(sc->fc.dev,
1615                         "IT DMA underrun (0x%08x)\n", stat);
1616                 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1617         }
1618 out:
1619         return err;
1620 }
1621
1622 static int
1623 fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1624 {
1625         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1626         int err = 0, s, ldesc;
1627         unsigned short tag, ich;
1628         uint32_t stat;
1629         struct fwohci_dbch *dbch;
1630         struct fwohcidb_tr *db_tr;
1631         struct fw_bulkxfer *first, *prev, *chunk;
1632         struct fw_xferq *ir;
1633
1634         dbch = &sc->ir[dmach];
1635         ir = &dbch->xferq;
1636
1637         if ((ir->flag & FWXFERQ_RUNNING) == 0) {
1638                 tag = (ir->flag >> 6) & 3;
1639                 ich = ir->flag & 0x3f;
1640                 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1641
1642                 ir->queued = 0;
1643                 dbch->ndb = ir->bnpacket * ir->bnchunk;
1644                 dbch->ndesc = 2;
1645                 fwohci_db_init(sc, dbch);
1646                 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1647                         return ENOMEM;
1648                 err = fwohci_rx_enable(sc, dbch);
1649         }
1650         if (err)
1651                 return err;
1652
1653         first = STAILQ_FIRST(&ir->stfree);
1654         if (first == NULL) {
1655                 device_printf(fc->dev, "IR DMA no free chunk\n");
1656                 return 0;
1657         }
1658
1659         ldesc = dbch->ndesc - 1;
1660         s = splfw();
1661         if ((ir->flag & FWXFERQ_HANDLER) == 0)
1662                 FW_GLOCK(fc);
1663         prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
1664         while  ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1665                 struct fwohcidb *db;
1666
1667 #if 1 /* XXX for if_fwe */
1668                 if (chunk->mbuf != NULL) {
1669                         db_tr = (struct fwohcidb_tr *)(chunk->start);
1670                         db_tr->dbcnt = 1;
1671                         err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
1672                                         chunk->mbuf, fwohci_execute_db2, db_tr,
1673                                         /* flags */0);
1674                         FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
1675                                 OHCI_UPDATE | OHCI_INPUT_LAST |
1676                                 OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1677                 }
1678 #endif
1679                 db = ((struct fwohcidb_tr *)(chunk->end))->db;
1680                 FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
1681                 FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1682                 if (prev != NULL) {
1683                         db = ((struct fwohcidb_tr *)(prev->end))->db;
1684                         FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1685                 }
1686                 STAILQ_REMOVE_HEAD(&ir->stfree, link);
1687                 STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
1688                 prev = chunk;
1689         }
1690         if ((ir->flag & FWXFERQ_HANDLER) == 0)
1691                 FW_GUNLOCK(fc);
1692         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1693         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1694         splx(s);
1695         stat = OREAD(sc, OHCI_IRCTL(dmach));
1696         if (stat & OHCI_CNTL_DMA_ACTIVE)
1697                 return 0;
1698         if (stat & OHCI_CNTL_DMA_RUN) {
1699                 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1700                 device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat);
1701         }
1702
1703         if (firewire_debug)
1704                 printf("start IR DMA 0x%x\n", stat);
1705         OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1706         OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1707         OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1708         OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1709         OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1710         OWRITE(sc, OHCI_IRCMD(dmach),
1711                 ((struct fwohcidb_tr *)(first->start))->bus_addr
1712                                                         | dbch->ndesc);
1713         OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1714         OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1715 #if 0
1716         dump_db(sc, IRX_CH + dmach);
1717 #endif
1718         return err;
1719 }
1720
1721 int
1722 fwohci_stop(struct fwohci_softc *sc, device_t dev)
1723 {
1724         u_int i;
1725
1726         fwohci_set_intr(&sc->fc, 0);
1727
1728 /* Now stopping all DMA channel */
1729         OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1730         OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1731         OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1732         OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1733
1734         for (i = 0; i < sc->fc.nisodma; i++) {
1735                 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1736                 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1737         }
1738
1739 #if 0 /* Let dcons(4) be accessed */
1740 /* Stop interrupt */
1741         OWRITE(sc, FWOHCI_INTMASKCLR,
1742                         OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1743                         | OHCI_INT_PHY_INT
1744                         | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1745                         | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1746                         | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1747                         | OHCI_INT_PHY_BUS_R);
1748
1749 /* FLUSH FIFO and reset Transmitter/Receiver */
1750         OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1751 #endif
1752
1753 /* XXX Link down?  Bus reset? */
1754         return 0;
1755 }
1756
1757 int
1758 fwohci_resume(struct fwohci_softc *sc, device_t dev)
1759 {
1760         int i;
1761         struct fw_xferq *ir;
1762         struct fw_bulkxfer *chunk;
1763
1764         fwohci_reset(sc, dev);
1765         /* XXX resume isochronous receive automatically. (how about TX?) */
1766         for (i = 0; i < sc->fc.nisodma; i++) {
1767                 ir = &sc->ir[i].xferq;
1768                 if ((ir->flag & FWXFERQ_RUNNING) != 0) {
1769                         device_printf(sc->fc.dev,
1770                                 "resume iso receive ch: %d\n", i);
1771                         ir->flag &= ~FWXFERQ_RUNNING;
1772                         /* requeue stdma to stfree */
1773                         while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
1774                                 STAILQ_REMOVE_HEAD(&ir->stdma, link);
1775                                 STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
1776                         }
1777                         sc->fc.irx_enable(&sc->fc, i);
1778                 }
1779         }
1780
1781         bus_generic_resume(dev);
1782         sc->fc.ibr(&sc->fc);
1783         return 0;
1784 }
1785
1786 #ifdef OHCI_DEBUG
1787 static void
1788 fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1789 {
1790         if (stat & OREAD(sc, FWOHCI_INTMASK))
1791                 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",
1792                         stat & OHCI_INT_EN ? "DMA_EN ":"",
1793                         stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1794                         stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1795                         stat & OHCI_INT_ERR ? "INT_ERR ":"",
1796                         stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1797                         stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1798                         stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1799                         stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1800                         stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1801                         stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1802                         stat & OHCI_INT_PHY_SID ? "SID ":"",
1803                         stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1804                         stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1805                         stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1806                         stat & OHCI_INT_DMA_IT  ? "DMA_IT " :"",
1807                         stat & OHCI_INT_DMA_PRRS  ? "DMA_PRRS " :"",
1808                         stat & OHCI_INT_DMA_PRRQ  ? "DMA_PRRQ " :"",
1809                         stat & OHCI_INT_DMA_ARRS  ? "DMA_ARRS " :"",
1810                         stat & OHCI_INT_DMA_ARRQ  ? "DMA_ARRQ " :"",
1811                         stat & OHCI_INT_DMA_ATRS  ? "DMA_ATRS " :"",
1812                         stat & OHCI_INT_DMA_ATRQ  ? "DMA_ATRQ " :"",
1813                         stat, OREAD(sc, FWOHCI_INTMASK)
1814                 );
1815 }
1816 #endif
1817
1818 static void
1819 fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count)
1820 {
1821         struct firewire_comm *fc = (struct firewire_comm *)sc;
1822         uintmax_t prequpper;
1823         uint32_t node_id, plen;
1824
1825         FW_GLOCK_ASSERT(fc);
1826         if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1827                 fc->status = FWBUSRESET;
1828                 /* Disable bus reset interrupt until sid recv. */
1829                 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1830
1831                 device_printf(fc->dev, "%s: BUS reset\n", __func__);
1832                 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1833                 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1834
1835                 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1836                 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1837                 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1838                 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1839
1840                 if (!kdb_active)
1841                         taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset);
1842         }
1843         if (stat & OHCI_INT_PHY_SID) {
1844                 /* Enable bus reset interrupt */
1845                 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1846                 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
1847
1848                 /* Allow async. request to us */
1849                 OWRITE(sc, OHCI_AREQHI, 1 << 31);
1850                 if (firewire_phydma_enable) {
1851                         /* allow from all nodes */
1852                         OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1853                         OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1854                         prequpper = ((uintmax_t)Maxmem << PAGE_SHIFT) >> 16;
1855                         if (prequpper > OHCI_PREQUPPER_MAX) {
1856                                 device_printf(fc->dev,
1857                                     "Physical memory size of 0x%jx exceeds "
1858                                     "fire wire address space.  Limiting dma "
1859                                     "to memory below 0x%jx\n",
1860                                     (uintmax_t)Maxmem << PAGE_SHIFT,
1861                                     (uintmax_t)OHCI_PREQUPPER_MAX << 16);
1862                                 prequpper = OHCI_PREQUPPER_MAX;
1863                         }
1864                         OWRITE(sc, OHCI_PREQUPPER, prequpper & 0xffffffff);
1865                         if (OREAD(sc, OHCI_PREQUPPER) !=
1866                             (prequpper & 0xffffffff)) {
1867                                 device_printf(fc->dev,
1868                                    "PhysicalUpperBound register is not "
1869                                    "implemented.  Physical memory access "
1870                                    "is limited to the first 4GB\n");
1871                                 device_printf(fc->dev,
1872                                    "PhysicalUpperBound = 0x%08x\n",
1873                                     OREAD(sc, OHCI_PREQUPPER));
1874                         }
1875                 }
1876                 /* Set ATRetries register */
1877                 OWRITE(sc, OHCI_ATRETRY, 1<<(13 + 16) | 0xfff);
1878
1879                 /*
1880                  * Checking whether the node is root or not. If root, turn on
1881                  * cycle master.
1882                  */
1883                 node_id = OREAD(sc, FWOHCI_NODEID);
1884                 plen = OREAD(sc, OHCI_SID_CNT);
1885
1886                 fc->nodeid = node_id & 0x3f;
1887                 device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ",
1888                                 __func__, fc->nodeid, (plen >> 16) & 0xff);
1889                 if (!(node_id & OHCI_NODE_VALID)) {
1890                         device_printf(fc->dev, "%s: Bus reset failure\n",
1891                                 __func__);
1892                         goto sidout;
1893                 }
1894
1895                 /* cycle timer */
1896                 sc->cycle_lost = 0;
1897                 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
1898                 if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
1899                         printf("CYCLEMASTER mode\n");
1900                         OWRITE(sc, OHCI_LNKCTL,
1901                                 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1902                 } else {
1903                         printf("non CYCLEMASTER mode\n");
1904                         OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1905                         OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1906                 }
1907
1908                 fc->status = FWBUSINIT;
1909
1910                 if (!kdb_active)
1911                         taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid);
1912         }
1913 sidout:
1914         if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active))
1915                 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma);
1916 }
1917
1918 static void
1919 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count)
1920 {
1921         uint32_t irstat, itstat;
1922         u_int i;
1923         struct firewire_comm *fc = (struct firewire_comm *)sc;
1924
1925         if (stat & OHCI_INT_DMA_IR) {
1926                 irstat = atomic_readandclear_int(&sc->irstat);
1927                 for (i = 0; i < fc->nisodma; i++) {
1928                         struct fwohci_dbch *dbch;
1929
1930                         if ((irstat & (1 << i)) != 0) {
1931                                 dbch = &sc->ir[i];
1932                                 if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
1933                                         device_printf(sc->fc.dev,
1934                                                 "dma(%d) not active\n", i);
1935                                         continue;
1936                                 }
1937                                 fwohci_rbuf_update(sc, i);
1938                         }
1939                 }
1940         }
1941         if (stat & OHCI_INT_DMA_IT) {
1942                 itstat = atomic_readandclear_int(&sc->itstat);
1943                 for (i = 0; i < fc->nisodma; i++) {
1944                         if ((itstat & (1 << i)) != 0) {
1945                                 fwohci_tbuf_update(sc, i);
1946                         }
1947                 }
1948         }
1949         if (stat & OHCI_INT_DMA_PRRS) {
1950 #if 0
1951                 dump_dma(sc, ARRS_CH);
1952                 dump_db(sc, ARRS_CH);
1953 #endif
1954                 fwohci_arcv(sc, &sc->arrs, count);
1955         }
1956         if (stat & OHCI_INT_DMA_PRRQ) {
1957 #if 0
1958                 dump_dma(sc, ARRQ_CH);
1959                 dump_db(sc, ARRQ_CH);
1960 #endif
1961                 fwohci_arcv(sc, &sc->arrq, count);
1962         }
1963         if (stat & OHCI_INT_CYC_LOST) {
1964                 if (sc->cycle_lost >= 0)
1965                         sc->cycle_lost++;
1966                 if (sc->cycle_lost > 10) {
1967                         sc->cycle_lost = -1;
1968 #if 0
1969                         OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
1970 #endif
1971                         OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1972                         device_printf(fc->dev, "too many cycles lost, "
1973                          "no cycle master present?\n");
1974                 }
1975         }
1976         if (stat & OHCI_INT_DMA_ATRQ) {
1977                 fwohci_txd(sc, &(sc->atrq));
1978         }
1979         if (stat & OHCI_INT_DMA_ATRS) {
1980                 fwohci_txd(sc, &(sc->atrs));
1981         }
1982         if (stat & OHCI_INT_PW_ERR) {
1983                 device_printf(fc->dev, "posted write error\n");
1984         }
1985         if (stat & OHCI_INT_ERR) {
1986                 device_printf(fc->dev, "unrecoverable error\n");
1987         }
1988         if (stat & OHCI_INT_PHY_INT) {
1989                 device_printf(fc->dev, "phy int\n");
1990         }
1991 }
1992
1993 static void
1994 fwohci_task_busreset(void *arg, int pending)
1995 {
1996         struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1997
1998         FW_GLOCK(&sc->fc);
1999         fw_busreset(&sc->fc, FWBUSRESET);
2000         OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2001         OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2002         FW_GUNLOCK(&sc->fc);
2003 }
2004
2005 static void
2006 fwohci_task_sid(void *arg, int pending)
2007 {
2008         struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2009         struct firewire_comm *fc = &sc->fc;
2010         uint32_t *buf;
2011         int i, plen;
2012
2013
2014         /*
2015          * We really should have locking
2016          * here.  Not sure why it's not
2017          */
2018         plen = OREAD(sc, OHCI_SID_CNT);
2019
2020         if (plen & OHCI_SID_ERR) {
2021                 device_printf(fc->dev, "SID Error\n");
2022                 return;
2023         }
2024         plen &= OHCI_SID_CNT_MASK;
2025         if (plen < 4 || plen > OHCI_SIDSIZE) {
2026                 device_printf(fc->dev, "invalid SID len = %d\n", plen);
2027                 return;
2028         }
2029         plen -= 4; /* chop control info */
2030         buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2031         if (buf == NULL) {
2032                 device_printf(fc->dev, "malloc failed\n");
2033                 return;
2034         }
2035         for (i = 0; i < plen / 4; i++)
2036                 buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2037
2038         /* pending all pre-bus_reset packets */
2039         fwohci_txd(sc, &sc->atrq);
2040         fwohci_txd(sc, &sc->atrs);
2041         fwohci_arcv(sc, &sc->arrs, -1);
2042         fwohci_arcv(sc, &sc->arrq, -1);
2043         fw_drain_txq(fc);
2044         fw_sidrcv(fc, buf, plen);
2045         free(buf, M_FW);
2046 }
2047
2048 static void
2049 fwohci_task_dma(void *arg, int pending)
2050 {
2051         struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2052         uint32_t stat;
2053
2054 again:
2055         stat = atomic_readandclear_int(&sc->intstat);
2056         if (stat)
2057                 fwohci_intr_dma(sc, stat, -1);
2058         else
2059                 return;
2060         goto again;
2061 }
2062
2063 static int
2064 fwohci_check_stat(struct fwohci_softc *sc)
2065 {
2066         uint32_t stat, irstat, itstat;
2067
2068         FW_GLOCK_ASSERT(&sc->fc);
2069         stat = OREAD(sc, FWOHCI_INTSTAT);
2070         if (stat == 0xffffffff) {
2071                 if (!bus_child_present(sc->fc.dev))
2072                         return (FILTER_HANDLED);
2073                 device_printf(sc->fc.dev, "device physically ejected?\n");
2074                 return (FILTER_STRAY);
2075         }
2076         if (stat)
2077                 OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
2078
2079         stat &= sc->intmask;
2080         if (stat == 0)
2081                 return (FILTER_STRAY);
2082
2083         atomic_set_int(&sc->intstat, stat);
2084         if (stat & OHCI_INT_DMA_IR) {
2085                 irstat = OREAD(sc, OHCI_IR_STAT);
2086                 OWRITE(sc, OHCI_IR_STATCLR, irstat);
2087                 atomic_set_int(&sc->irstat, irstat);
2088         }
2089         if (stat & OHCI_INT_DMA_IT) {
2090                 itstat = OREAD(sc, OHCI_IT_STAT);
2091                 OWRITE(sc, OHCI_IT_STATCLR, itstat);
2092                 atomic_set_int(&sc->itstat, itstat);
2093         }
2094
2095         fwohci_intr_core(sc, stat, -1);
2096         return (FILTER_HANDLED);
2097 }
2098
2099 void
2100 fwohci_intr(void *arg)
2101 {
2102         struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2103
2104         FW_GLOCK(&sc->fc);
2105         fwohci_check_stat(sc);
2106         FW_GUNLOCK(&sc->fc);
2107 }
2108
2109 void
2110 fwohci_poll(struct firewire_comm *fc, int quick, int count)
2111 {
2112         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2113
2114         FW_GLOCK(fc);
2115         fwohci_check_stat(sc);
2116         FW_GUNLOCK(fc);
2117 }
2118
2119 static void
2120 fwohci_set_intr(struct firewire_comm *fc, int enable)
2121 {
2122         struct fwohci_softc *sc;
2123
2124         sc = (struct fwohci_softc *)fc;
2125         if (firewire_debug)
2126                 device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
2127         if (enable) {
2128                 sc->intmask |= OHCI_INT_EN;
2129                 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
2130         } else {
2131                 sc->intmask &= ~OHCI_INT_EN;
2132                 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2133         }
2134 }
2135
2136 static void
2137 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2138 {
2139         struct firewire_comm *fc = &sc->fc;
2140         struct fwohcidb *db;
2141         struct fw_bulkxfer *chunk;
2142         struct fw_xferq *it;
2143         uint32_t stat, count;
2144         int s, w=0, ldesc;
2145
2146         it = fc->it[dmach];
2147         ldesc = sc->it[dmach].ndesc - 1;
2148         s = splfw(); /* unnecessary ? */
2149         FW_GLOCK(fc);
2150         fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2151         if (firewire_debug)
2152                 dump_db(sc, ITX_CH + dmach);
2153         while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2154                 db = ((struct fwohcidb_tr *)(chunk->end))->db;
2155                 stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2156                                 >> OHCI_STATUS_SHIFT;
2157                 db = ((struct fwohcidb_tr *)(chunk->start))->db;
2158                 /* timestamp */
2159                 count = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2160                                 & OHCI_COUNT_MASK;
2161                 if (stat == 0)
2162                         break;
2163                 STAILQ_REMOVE_HEAD(&it->stdma, link);
2164                 switch (stat & FWOHCIEV_MASK) {
2165                 case FWOHCIEV_ACKCOMPL:
2166 #if 0
2167                         device_printf(fc->dev, "0x%08x\n", count);
2168 #endif
2169                         break;
2170                 default:
2171                         device_printf(fc->dev,
2172                                 "Isochronous transmit err %02x(%s)\n",
2173                                         stat, fwohcicode[stat & 0x1f]);
2174                 }
2175                 STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2176                 w++;
2177         }
2178         FW_GUNLOCK(fc);
2179         splx(s);
2180         if (w)
2181                 wakeup(it);
2182 }
2183
2184 static void
2185 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2186 {
2187         struct firewire_comm *fc = &sc->fc;
2188         struct fwohcidb_tr *db_tr;
2189         struct fw_bulkxfer *chunk;
2190         struct fw_xferq *ir;
2191         uint32_t stat;
2192         int w = 0, ldesc;
2193
2194         ir = fc->ir[dmach];
2195         ldesc = sc->ir[dmach].ndesc - 1;
2196
2197 #if 0
2198         dump_db(sc, dmach);
2199 #endif
2200         if ((ir->flag & FWXFERQ_HANDLER) == 0)
2201                 FW_GLOCK(fc);
2202         fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2203         while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2204                 db_tr = (struct fwohcidb_tr *)chunk->end;
2205                 stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res)
2206                                 >> OHCI_STATUS_SHIFT;
2207                 if (stat == 0)
2208                         break;
2209
2210                 if (chunk->mbuf != NULL) {
2211                         bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map,
2212                                                 BUS_DMASYNC_POSTREAD);
2213                         bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map);
2214                 } else if (ir->buf != NULL) {
2215                         fwdma_sync_multiseg(ir->buf, chunk->poffset,
2216                                 ir->bnpacket, BUS_DMASYNC_POSTREAD);
2217                 } else {
2218                         /* XXX */
2219                         printf("fwohci_rbuf_update: this shouldn't happened\n");
2220                 }
2221
2222                 STAILQ_REMOVE_HEAD(&ir->stdma, link);
2223                 STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2224                 switch (stat & FWOHCIEV_MASK) {
2225                 case FWOHCIEV_ACKCOMPL:
2226                         chunk->resp = 0;
2227                         break;
2228                 default:
2229                         chunk->resp = EINVAL;
2230                         device_printf(fc->dev,
2231                                 "Isochronous receive err %02x(%s)\n",
2232                                         stat, fwohcicode[stat & 0x1f]);
2233                 }
2234                 w++;
2235         }
2236         if ((ir->flag & FWXFERQ_HANDLER) == 0)
2237                 FW_GUNLOCK(fc);
2238         if (w == 0)
2239                 return;
2240
2241         if (ir->flag & FWXFERQ_HANDLER)
2242                 ir->hand(ir);
2243         else
2244                 wakeup(ir);
2245 }
2246
2247 void
2248 dump_dma(struct fwohci_softc *sc, uint32_t ch)
2249 {
2250         uint32_t off, cntl, stat, cmd, match;
2251
2252         if (ch == 0) {
2253                 off = OHCI_ATQOFF;
2254         } else if (ch == 1) {
2255                 off = OHCI_ATSOFF;
2256         } else if (ch == 2) {
2257                 off = OHCI_ARQOFF;
2258         } else if (ch == 3) {
2259                 off = OHCI_ARSOFF;
2260         } else if (ch < IRX_CH) {
2261                 off = OHCI_ITCTL(ch - ITX_CH);
2262         } else {
2263                 off = OHCI_IRCTL(ch - IRX_CH);
2264         }
2265         cntl = stat = OREAD(sc, off);
2266         cmd = OREAD(sc, off + 0xc);
2267         match = OREAD(sc, off + 0x10);
2268
2269         device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2270                 ch,
2271                 cntl,
2272                 cmd,
2273                 match);
2274         stat &= 0xffff;
2275         if (stat) {
2276                 device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2277                         ch,
2278                         stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2279                         stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2280                         stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2281                         stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2282                         stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2283                         stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2284                         fwohcicode[stat & 0x1f],
2285                         stat & 0x1f
2286                 );
2287         } else {
2288                 device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2289         }
2290 }
2291
2292 void
2293 dump_db(struct fwohci_softc *sc, uint32_t ch)
2294 {
2295         struct fwohci_dbch *dbch;
2296         struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
2297         struct fwohcidb *curr = NULL, *prev, *next = NULL;
2298         int idb, jdb;
2299         uint32_t cmd, off;
2300
2301         if (ch == 0) {
2302                 off = OHCI_ATQOFF;
2303                 dbch = &sc->atrq;
2304         } else if (ch == 1) {
2305                 off = OHCI_ATSOFF;
2306                 dbch = &sc->atrs;
2307         } else if (ch == 2) {
2308                 off = OHCI_ARQOFF;
2309                 dbch = &sc->arrq;
2310         } else if (ch == 3) {
2311                 off = OHCI_ARSOFF;
2312                 dbch = &sc->arrs;
2313         } else if (ch < IRX_CH) {
2314                 off = OHCI_ITCTL(ch - ITX_CH);
2315                 dbch = &sc->it[ch - ITX_CH];
2316         } else {
2317                 off = OHCI_IRCTL(ch - IRX_CH);
2318                 dbch = &sc->ir[ch - IRX_CH];
2319         }
2320         cmd = OREAD(sc, off + 0xc);
2321
2322         if (dbch->ndb == 0) {
2323                 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2324                 return;
2325         }
2326         pp = dbch->top;
2327         prev = pp->db;
2328         for (idb = 0; idb < dbch->ndb; idb++) {
2329                 cp = STAILQ_NEXT(pp, link);
2330                 if (cp == NULL) {
2331                         curr = NULL;
2332                         goto outdb;
2333                 }
2334                 np = STAILQ_NEXT(cp, link);
2335                 for (jdb = 0; jdb < dbch->ndesc; jdb++) {
2336                         if ((cmd  & 0xfffffff0) == cp->bus_addr) {
2337                                 curr = cp->db;
2338                                 if (np != NULL) {
2339                                         next = np->db;
2340                                 } else {
2341                                         next = NULL;
2342                                 }
2343                                 goto outdb;
2344                         }
2345                 }
2346                 pp = STAILQ_NEXT(pp, link);
2347                 if (pp == NULL) {
2348                         curr = NULL;
2349                         goto outdb;
2350                 }
2351                 prev = pp->db;
2352         }
2353 outdb:
2354         if (curr != NULL) {
2355 #if 0
2356                 printf("Prev DB %d\n", ch);
2357                 print_db(pp, prev, ch, dbch->ndesc);
2358 #endif
2359                 printf("Current DB %d\n", ch);
2360                 print_db(cp, curr, ch, dbch->ndesc);
2361 #if 0
2362                 printf("Next DB %d\n", ch);
2363                 print_db(np, next, ch, dbch->ndesc);
2364 #endif
2365         } else {
2366                 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2367         }
2368         return;
2369 }
2370
2371 void
2372 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2373                 uint32_t ch, uint32_t max)
2374 {
2375         fwohcireg_t stat;
2376         int i, key;
2377         uint32_t cmd, res;
2378
2379         if (db == NULL) {
2380                 printf("No Descriptor is found\n");
2381                 return;
2382         }
2383
2384         printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2385                 ch,
2386                 "Current",
2387                 "OP  ",
2388                 "KEY",
2389                 "INT",
2390                 "BR ",
2391                 "len",
2392                 "Addr",
2393                 "Depend",
2394                 "Stat",
2395                 "Cnt");
2396         for (i = 0; i <= max; i++) {
2397                 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2398                 res = FWOHCI_DMA_READ(db[i].db.desc.res);
2399                 key = cmd & OHCI_KEY_MASK;
2400                 stat = res >> OHCI_STATUS_SHIFT;
2401                 printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2402                                 (uintmax_t)db_tr->bus_addr,
2403                                 dbcode[(cmd >> 28) & 0xf],
2404                                 dbkey[(cmd >> 24) & 0x7],
2405                                 dbcond[(cmd >> 20) & 0x3],
2406                                 dbcond[(cmd >> 18) & 0x3],
2407                                 cmd & OHCI_COUNT_MASK,
2408                                 FWOHCI_DMA_READ(db[i].db.desc.addr),
2409                                 FWOHCI_DMA_READ(db[i].db.desc.depend),
2410                                 stat,
2411                                 res & OHCI_COUNT_MASK);
2412                 if (stat & 0xff00) {
2413                         printf(" %s%s%s%s%s%s %s(%x)\n",
2414                                 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2415                                 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2416                                 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2417                                 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2418                                 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2419                                 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2420                                 fwohcicode[stat & 0x1f],
2421                                 stat & 0x1f
2422                         );
2423                 } else {
2424                         printf(" Nostat\n");
2425                 }
2426                 if (key == OHCI_KEY_ST2) {
2427                         printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2428                                 FWOHCI_DMA_READ(db[i + 1].db.immed[0]),
2429                                 FWOHCI_DMA_READ(db[i + 1].db.immed[1]),
2430                                 FWOHCI_DMA_READ(db[i + 1].db.immed[2]),
2431                                 FWOHCI_DMA_READ(db[i + 1].db.immed[3]));
2432                 }
2433                 if (key == OHCI_KEY_DEVICE) {
2434                         return;
2435                 }
2436                 if ((cmd & OHCI_BRANCH_MASK)
2437                                 == OHCI_BRANCH_ALWAYS) {
2438                         return;
2439                 }
2440                 if ((cmd & OHCI_CMD_MASK)
2441                                 == OHCI_OUTPUT_LAST) {
2442                         return;
2443                 }
2444                 if ((cmd & OHCI_CMD_MASK)
2445                                 == OHCI_INPUT_LAST) {
2446                         return;
2447                 }
2448                 if (key == OHCI_KEY_ST2) {
2449                         i++;
2450                 }
2451         }
2452         return;
2453 }
2454
2455 void
2456 fwohci_ibr(struct firewire_comm *fc)
2457 {
2458         struct fwohci_softc *sc;
2459         uint32_t fun;
2460
2461         device_printf(fc->dev, "Initiate bus reset\n");
2462         sc = (struct fwohci_softc *)fc;
2463
2464         FW_GLOCK(fc);
2465         /*
2466          * Make sure our cached values from the config rom are
2467          * initialised.
2468          */
2469         OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2470         OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2471
2472         /*
2473          * Set root hold-off bit so that non cyclemaster capable node
2474          * shouldn't became the root node.
2475          */
2476 #if 1
2477         fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2478         fun |= FW_PHY_IBR | FW_PHY_RHB;
2479         fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2480 #else   /* Short bus reset */
2481         fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2482         fun |= FW_PHY_ISBR | FW_PHY_RHB;
2483         fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2484 #endif
2485         FW_GUNLOCK(fc);
2486 }
2487
2488 void
2489 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2490 {
2491         struct fwohcidb_tr *db_tr, *fdb_tr;
2492         struct fwohci_dbch *dbch;
2493         struct fwohcidb *db;
2494         struct fw_pkt *fp;
2495         struct fwohci_txpkthdr *ohcifp;
2496         unsigned short chtag;
2497         int idb;
2498
2499         FW_GLOCK_ASSERT(&sc->fc);
2500
2501         dbch = &sc->it[dmach];
2502         chtag = sc->it[dmach].xferq.flag & 0xff;
2503
2504         db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2505         fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2506 /*
2507 device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2508 */
2509         for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2510                 db = db_tr->db;
2511                 fp = (struct fw_pkt *)db_tr->buf;
2512                 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2513                 ohcifp->mode.ld[0] = fp->mode.ld[0];
2514                 ohcifp->mode.common.spd = 0 & 0x7;
2515                 ohcifp->mode.stream.len = fp->mode.stream.len;
2516                 ohcifp->mode.stream.chtag = chtag;
2517                 ohcifp->mode.stream.tcode = 0xa;
2518 #if BYTE_ORDER == BIG_ENDIAN
2519                 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2520                 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2521 #endif
2522
2523                 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2524                 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2525                 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2526 #if 0 /* if bulkxfer->npackets changes */
2527                 db[2].db.desc.cmd = OHCI_OUTPUT_LAST
2528                         | OHCI_UPDATE
2529                         | OHCI_BRANCH_ALWAYS;
2530                 db[0].db.desc.depend =
2531                         = db[dbch->ndesc - 1].db.desc.depend
2532                         = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2533 #else
2534                 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2535                 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2536 #endif
2537                 bulkxfer->end = (caddr_t)db_tr;
2538                 db_tr = STAILQ_NEXT(db_tr, link);
2539         }
2540         db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2541         FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2542         FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2543 #if 0 /* if bulkxfer->npackets changes */
2544         db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2545         /* OHCI 1.1 and above */
2546         db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2547 #endif
2548 /*
2549         db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2550         fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2551 device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2552 */
2553         return;
2554 }
2555
2556 static int
2557 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2558                                                                 int poffset)
2559 {
2560         struct fwohcidb *db = db_tr->db;
2561         struct fw_xferq *it;
2562         int err = 0;
2563
2564         it = &dbch->xferq;
2565         if (it->buf == 0) {
2566                 err = EINVAL;
2567                 return err;
2568         }
2569         db_tr->buf = fwdma_v_addr(it->buf, poffset);
2570         db_tr->dbcnt = 3;
2571
2572         FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2573                 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2574         FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2575         bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2576         FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2577         fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2578
2579         FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2580                 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2581 #if 1
2582         FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2583         FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2584 #endif
2585         return 0;
2586 }
2587
2588 int
2589 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2590                 int poffset, struct fwdma_alloc *dummy_dma)
2591 {
2592         struct fwohcidb *db = db_tr->db;
2593         struct fw_xferq *ir;
2594         int i, ldesc;
2595         bus_addr_t dbuf[2];
2596         int dsiz[2];
2597
2598         ir = &dbch->xferq;
2599         if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2600                 if (db_tr->buf == NULL) {
2601                         db_tr->buf = fwdma_malloc_size(dbch->dmat,
2602                             &db_tr->dma_map, ir->psize, &dbuf[0],
2603                             BUS_DMA_NOWAIT);
2604                         if (db_tr->buf == NULL)
2605                                 return (ENOMEM);
2606                 }
2607                 db_tr->dbcnt = 1;
2608                 dsiz[0] = ir->psize;
2609                 bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2610                         BUS_DMASYNC_PREREAD);
2611         } else {
2612                 db_tr->dbcnt = 0;
2613                 if (dummy_dma != NULL) {
2614                         dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2615                         dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2616                 }
2617                 dsiz[db_tr->dbcnt] = ir->psize;
2618                 if (ir->buf != NULL) {
2619                         db_tr->buf = fwdma_v_addr(ir->buf, poffset);
2620                         dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset);
2621                 }
2622                 db_tr->dbcnt++;
2623         }
2624         for (i = 0; i < db_tr->dbcnt; i++) {
2625                 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2626                 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2627                 if (ir->flag & FWXFERQ_STREAM) {
2628                         FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2629                 }
2630                 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2631         }
2632         ldesc = db_tr->dbcnt - 1;
2633         if (ir->flag & FWXFERQ_STREAM) {
2634                 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2635         }
2636         FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2637         return 0;
2638 }
2639
2640
2641 static int
2642 fwohci_arcv_swap(struct fw_pkt *fp, int len)
2643 {
2644         struct fw_pkt *fp0;
2645         uint32_t ld0;
2646         int slen, hlen;
2647 #if BYTE_ORDER == BIG_ENDIAN
2648         int i;
2649 #endif
2650
2651         ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2652 #if 0
2653         printf("ld0: x%08x\n", ld0);
2654 #endif
2655         fp0 = (struct fw_pkt *)&ld0;
2656         /* determine length to swap */
2657         switch (fp0->mode.common.tcode) {
2658         case FWTCODE_RREQQ:
2659         case FWTCODE_WRES:
2660         case FWTCODE_WREQQ:
2661         case FWTCODE_RRESQ:
2662         case FWOHCITCODE_PHY:
2663                 slen = 12;
2664                 break;
2665         case FWTCODE_RREQB:
2666         case FWTCODE_WREQB:
2667         case FWTCODE_LREQ:
2668         case FWTCODE_RRESB:
2669         case FWTCODE_LRES:
2670                 slen = 16;
2671                 break;
2672         default:
2673                 printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2674                 return (0);
2675         }
2676         hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2677         if (hlen > len) {
2678                 if (firewire_debug)
2679                         printf("splitted header\n");
2680                 return (-hlen);
2681         }
2682 #if BYTE_ORDER == BIG_ENDIAN
2683         for (i = 0; i < slen/4; i++)
2684                 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2685 #endif
2686         return (hlen);
2687 }
2688
2689 static int
2690 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2691 {
2692         struct tcode_info *info;
2693         int r;
2694
2695         info = &tinfo[fp->mode.common.tcode];
2696         r = info->hdr_len + sizeof(uint32_t);
2697         if ((info->flag & FWTI_BLOCK_ASY) != 0)
2698                 r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2699
2700         if (r == sizeof(uint32_t)) {
2701                 /* XXX */
2702                 device_printf(sc->fc.dev, "Unknown tcode %d\n",
2703                                                 fp->mode.common.tcode);
2704                 return (-1);
2705         }
2706
2707         if (r > dbch->xferq.psize) {
2708                 device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2709                 return (-1);
2710                 /* panic ? */
2711         }
2712
2713         return r;
2714 }
2715
2716 static void
2717 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2718     struct fwohcidb_tr *db_tr, uint32_t off, int wake)
2719 {
2720         struct fwohcidb *db = &db_tr->db[0];
2721
2722         FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2723         FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2724         FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2725         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
2726         dbch->bottom = db_tr;
2727
2728         if (wake)
2729                 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2730 }
2731
2732 static void
2733 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2734 {
2735         struct fwohcidb_tr *db_tr;
2736         struct iovec vec[2];
2737         struct fw_pkt pktbuf;
2738         int nvec;
2739         struct fw_pkt *fp;
2740         uint8_t *ld;
2741         uint32_t stat, off, status, event;
2742         u_int spd;
2743         int len, plen, hlen, pcnt, offset;
2744         int s;
2745         caddr_t buf;
2746         int resCount;
2747
2748         if (&sc->arrq == dbch) {
2749                 off = OHCI_ARQOFF;
2750         } else if (&sc->arrs == dbch) {
2751                 off = OHCI_ARSOFF;
2752         } else {
2753                 return;
2754         }
2755
2756         s = splfw();
2757         db_tr = dbch->top;
2758         pcnt = 0;
2759         /* XXX we cannot handle a packet which lies in more than two buf */
2760         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
2761         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
2762         status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2763         resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2764         while (status & OHCI_CNTL_DMA_ACTIVE) {
2765 #if 0
2766
2767                 if (off == OHCI_ARQOFF)
2768                         printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2769                             db_tr->bus_addr, status, resCount);
2770 #endif
2771                 len = dbch->xferq.psize - resCount;
2772                 ld = (uint8_t *)db_tr->buf;
2773                 if (dbch->pdb_tr == NULL) {
2774                         len -= dbch->buf_offset;
2775                         ld += dbch->buf_offset;
2776                 }
2777                 if (len > 0)
2778                         bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2779                                         BUS_DMASYNC_POSTREAD);
2780                 while (len > 0) {
2781                         if (count >= 0 && count-- == 0)
2782                                 goto out;
2783                         if (dbch->pdb_tr != NULL) {
2784                                 /* we have a fragment in previous buffer */
2785                                 int rlen;
2786
2787                                 offset = dbch->buf_offset;
2788                                 if (offset < 0)
2789                                         offset = - offset;
2790                                 buf = dbch->pdb_tr->buf + offset;
2791                                 rlen = dbch->xferq.psize - offset;
2792                                 if (firewire_debug)
2793                                         printf("rlen=%d, offset=%d\n",
2794                                                 rlen, dbch->buf_offset);
2795                                 if (dbch->buf_offset < 0) {
2796                                         /* splitted in header, pull up */
2797                                         char *p;
2798
2799                                         p = (char *)&pktbuf;
2800                                         bcopy(buf, p, rlen);
2801                                         p += rlen;
2802                                         /* this must be too long but harmless */
2803                                         rlen = sizeof(pktbuf) - rlen;
2804                                         if (rlen < 0)
2805                                                 printf("why rlen < 0\n");
2806                                         bcopy(db_tr->buf, p, rlen);
2807                                         ld += rlen;
2808                                         len -= rlen;
2809                                         hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf));
2810                                         if (hlen <= 0) {
2811                                                 printf("hlen should be positive.");
2812                                                 goto err;
2813                                         }
2814                                         offset = sizeof(pktbuf);
2815                                         vec[0].iov_base = (char *)&pktbuf;
2816                                         vec[0].iov_len = offset;
2817                                 } else {
2818                                         /* splitted in payload */
2819                                         offset = rlen;
2820                                         vec[0].iov_base = buf;
2821                                         vec[0].iov_len = rlen;
2822                                 }
2823                                 fp=(struct fw_pkt *)vec[0].iov_base;
2824                                 nvec = 1;
2825                         } else {
2826                                 /* no fragment in previous buffer */
2827                                 fp=(struct fw_pkt *)ld;
2828                                 hlen = fwohci_arcv_swap(fp, len);
2829                                 if (hlen == 0)
2830                                         goto err;
2831                                 if (hlen < 0) {
2832                                         dbch->pdb_tr = db_tr;
2833                                         dbch->buf_offset = - dbch->buf_offset;
2834                                         /* sanity check */
2835                                         if (resCount != 0) {
2836                                                 printf("resCount=%d hlen=%d\n",
2837                                                     resCount, hlen);
2838                                                     goto err;
2839                                         }
2840                                         goto out;
2841                                 }
2842                                 offset = 0;
2843                                 nvec = 0;
2844                         }
2845                         plen = fwohci_get_plen(sc, dbch, fp) - offset;
2846                         if (plen < 0) {
2847                                 /* minimum header size + trailer
2848                                 = sizeof(fw_pkt) so this shouldn't happens */
2849                                 printf("plen(%d) is negative! offset=%d\n",
2850                                     plen, offset);
2851                                 goto err;
2852                         }
2853                         if (plen > 0) {
2854                                 len -= plen;
2855                                 if (len < 0) {
2856                                         dbch->pdb_tr = db_tr;
2857                                         if (firewire_debug)
2858                                                 printf("splitted payload\n");
2859                                         /* sanity check */
2860                                         if (resCount != 0) {
2861                                                 printf("resCount=%d plen=%d"
2862                                                     " len=%d\n",
2863                                                     resCount, plen, len);
2864                                                 goto err;
2865                                         }
2866                                         goto out;
2867                                 }
2868                                 vec[nvec].iov_base = ld;
2869                                 vec[nvec].iov_len = plen;
2870                                 nvec++;
2871                                 ld += plen;
2872                         }
2873                         dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2874                         if (nvec == 0)
2875                                 printf("nvec == 0\n");
2876
2877 /* DMA result-code will be written at the tail of packet */
2878                         stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer)));
2879 #if 0
2880                         printf("plen: %d, stat %x\n",
2881                             plen ,stat);
2882 #endif
2883                         spd = (stat >> 21) & 0x3;
2884                         event = (stat >> 16) & 0x1f;
2885                         switch (event) {
2886                         case FWOHCIEV_ACKPEND:
2887 #if 0
2888                                 printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
2889 #endif
2890                                 /* fall through */
2891                         case FWOHCIEV_ACKCOMPL:
2892                         {
2893                                 struct fw_rcv_buf rb;
2894
2895                                 if ((vec[nvec-1].iov_len -=
2896                                         sizeof(struct fwohci_trailer)) == 0)
2897                                         nvec--;
2898                                 rb.fc = &sc->fc;
2899                                 rb.vec = vec;
2900                                 rb.nvec = nvec;
2901                                 rb.spd = spd;
2902                                 fw_rcv(&rb);
2903                                 break;
2904                         }
2905                         case FWOHCIEV_BUSRST:
2906                                 if ((sc->fc.status != FWBUSRESET) &&
2907                                     (sc->fc.status != FWBUSINIT))
2908                                         printf("got BUSRST packet!?\n");
2909                                 break;
2910                         default:
2911                                 device_printf(sc->fc.dev,
2912                                     "Async DMA Receive error err=%02x %s"
2913                                     " plen=%d offset=%d len=%d status=0x%08x"
2914                                     " tcode=0x%x, stat=0x%08x\n",
2915                                     event, fwohcicode[event], plen,
2916                                     dbch->buf_offset, len,
2917                                     OREAD(sc, OHCI_DMACTL(off)),
2918                                     fp->mode.common.tcode, stat);
2919 #if 1 /* XXX */
2920                                 goto err;
2921 #endif
2922                                 break;
2923                         }
2924                         pcnt++;
2925                         if (dbch->pdb_tr != NULL) {
2926                                 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr,
2927                                     off, 1);
2928                                 dbch->pdb_tr = NULL;
2929                         }
2930
2931                 }
2932 out:
2933                 if (resCount == 0) {
2934                         /* done on this buffer */
2935                         if (dbch->pdb_tr == NULL) {
2936                                 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1);
2937                                 dbch->buf_offset = 0;
2938                         } else
2939                                 if (dbch->pdb_tr != db_tr)
2940                                         printf("pdb_tr != db_tr\n");
2941                         db_tr = STAILQ_NEXT(db_tr, link);
2942                         status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2943                                                 >> OHCI_STATUS_SHIFT;
2944                         resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2945                                                 & OHCI_COUNT_MASK;
2946                         /* XXX check buffer overrun */
2947                         dbch->top = db_tr;
2948                 } else {
2949                         dbch->buf_offset = dbch->xferq.psize - resCount;
2950                         break;
2951                 }
2952                 /* XXX make sure DMA is not dead */
2953         }
2954 #if 0
2955         if (pcnt < 1)
2956                 printf("fwohci_arcv: no packets\n");
2957 #endif
2958         splx(s);
2959         return;
2960
2961 err:
2962         device_printf(sc->fc.dev, "AR DMA status=%x, ",
2963                                         OREAD(sc, OHCI_DMACTL(off)));
2964         dbch->pdb_tr = NULL;
2965         /* skip until resCount != 0 */
2966         printf(" skip buffer");
2967         while (resCount == 0) {
2968                 printf(" #");
2969                 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0);
2970                 db_tr = STAILQ_NEXT(db_tr, link);
2971                 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2972                                                 & OHCI_COUNT_MASK;
2973         }
2974         printf(" done\n");
2975         dbch->top = db_tr;
2976         dbch->buf_offset = dbch->xferq.psize - resCount;
2977         OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2978         splx(s);
2979 }