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