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