]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/firewire/fwohci.c
Upgrade to OpenSSH 6.9p1.
[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/Reciever */
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 recieve 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. responce */
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         if (db_tr == NULL) {
1251                 printf("fwohci_db_init: malloc(1) failed\n");
1252                 return;
1253         }
1254
1255 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1256         dbch->am = fwdma_malloc_multiseg(&sc->fc, sizeof(struct fwohcidb),
1257                 DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK);
1258         if (dbch->am == NULL) {
1259                 printf("fwohci_db_init: fwdma_malloc_multiseg failed\n");
1260                 free(db_tr, M_FW);
1261                 return;
1262         }
1263         /* Attach DB to DMA ch. */
1264         for (idb = 0; idb < dbch->ndb; idb++) {
1265                 db_tr->dbcnt = 0;
1266                 db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1267                 db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1268                 /* create dmamap for buffers */
1269                 /* XXX do we need 4bytes alignment tag? */
1270                 /* XXX don't alloc dma_map for AR */
1271                 if (bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) {
1272                         printf("bus_dmamap_create failed\n");
1273                         dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1274                         fwohci_db_free(dbch);
1275                         return;
1276                 }
1277                 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1278                 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1279                         if (idb % dbch->xferq.bnpacket == 0)
1280                                 dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1281                                                 ].start = (caddr_t)db_tr;
1282                         if ((idb + 1) % dbch->xferq.bnpacket == 0)
1283                                 dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket
1284                                                 ].end = (caddr_t)db_tr;
1285                 }
1286                 db_tr++;
1287         }
1288         STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1289                         = STAILQ_FIRST(&dbch->db_trq);
1290 out:
1291         dbch->xferq.queued = 0;
1292         dbch->pdb_tr = NULL;
1293         dbch->top = STAILQ_FIRST(&dbch->db_trq);
1294         dbch->bottom = dbch->top;
1295         dbch->flags = FWOHCI_DBCH_INIT;
1296 }
1297
1298 static int
1299 fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1300 {
1301         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1302
1303         OWRITE(sc, OHCI_ITCTLCLR(dmach),
1304                         OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1305         OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1306         OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1307         /* XXX we cannot free buffers until the DMA really stops */
1308         pause("fwitxd", hz);
1309         fwohci_db_free(&sc->it[dmach]);
1310         sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1311         return 0;
1312 }
1313
1314 static int
1315 fwohci_irx_disable(struct firewire_comm *fc, int dmach)
1316 {
1317         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1318
1319         OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1320         OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1321         OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1322         /* XXX we cannot free buffers until the DMA really stops */
1323         pause("fwirxd", hz);
1324         fwohci_db_free(&sc->ir[dmach]);
1325         sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1326         return 0;
1327 }
1328
1329 #if BYTE_ORDER == BIG_ENDIAN
1330 static void
1331 fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld)
1332 {
1333         qld[0] = FWOHCI_DMA_READ(qld[0]);
1334         return;
1335 }
1336 #endif
1337
1338 static int
1339 fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1340 {
1341         int err = 0;
1342         int idb, z, i, dmach = 0, ldesc;
1343         uint32_t off = 0;
1344         struct fwohcidb_tr *db_tr;
1345         struct fwohcidb *db;
1346
1347         if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) {
1348                 err = EINVAL;
1349                 return err;
1350         }
1351         z = dbch->ndesc;
1352         for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1353                 if (&sc->it[dmach] == dbch) {
1354                         off = OHCI_ITOFF(dmach);
1355                         break;
1356                 }
1357         }
1358         if (off == 0) {
1359                 err = EINVAL;
1360                 return err;
1361         }
1362         if (dbch->xferq.flag & FWXFERQ_RUNNING)
1363                 return err;
1364         dbch->xferq.flag |= FWXFERQ_RUNNING;
1365         for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1366                 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1367         }
1368         db_tr = dbch->top;
1369         for (idb = 0; idb < dbch->ndb; idb++) {
1370                 fwohci_add_tx_buf(dbch, db_tr, idb);
1371                 if (STAILQ_NEXT(db_tr, link) == NULL) {
1372                         break;
1373                 }
1374                 db = db_tr->db;
1375                 ldesc = db_tr->dbcnt - 1;
1376                 FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1377                                 STAILQ_NEXT(db_tr, link)->bus_addr | z);
1378                 db[ldesc].db.desc.depend = db[0].db.desc.depend;
1379                 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1380                         if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1381                                 FWOHCI_DMA_SET(
1382                                         db[ldesc].db.desc.cmd,
1383                                         OHCI_INTERRUPT_ALWAYS);
1384                                 /* OHCI 1.1 and above */
1385                                 FWOHCI_DMA_SET(
1386                                         db[0].db.desc.cmd,
1387                                         OHCI_INTERRUPT_ALWAYS);
1388                         }
1389                 }
1390                 db_tr = STAILQ_NEXT(db_tr, link);
1391         }
1392         FWOHCI_DMA_CLEAR(
1393                 dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1394         return err;
1395 }
1396
1397 static int
1398 fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1399 {
1400         int err = 0;
1401         int idb, z, i, dmach = 0, ldesc;
1402         uint32_t off = 0;
1403         struct fwohcidb_tr *db_tr;
1404         struct fwohcidb *db;
1405
1406         z = dbch->ndesc;
1407         if (&sc->arrq == dbch) {
1408                 off = OHCI_ARQOFF;
1409         } else if (&sc->arrs == dbch) {
1410                 off = OHCI_ARSOFF;
1411         } else {
1412                 for (dmach = 0; dmach < sc->fc.nisodma; dmach++) {
1413                         if (&sc->ir[dmach] == dbch) {
1414                                 off = OHCI_IROFF(dmach);
1415                                 break;
1416                         }
1417                 }
1418         }
1419         if (off == 0) {
1420                 err = EINVAL;
1421                 return err;
1422         }
1423         if (dbch->xferq.flag & FWXFERQ_STREAM) {
1424                 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1425                         return err;
1426         } else {
1427                 if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1428                         err = EBUSY;
1429                         return err;
1430                 }
1431         }
1432         dbch->xferq.flag |= FWXFERQ_RUNNING;
1433         dbch->top = STAILQ_FIRST(&dbch->db_trq);
1434         for (i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++) {
1435                 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1436         }
1437         db_tr = dbch->top;
1438         for (idb = 0; idb < dbch->ndb; idb++) {
1439                 fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1440                 if (STAILQ_NEXT(db_tr, link) == NULL)
1441                         break;
1442                 db = db_tr->db;
1443                 ldesc = db_tr->dbcnt - 1;
1444                 FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1445                         STAILQ_NEXT(db_tr, link)->bus_addr | z);
1446                 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1447                         if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1448                                 FWOHCI_DMA_SET(
1449                                         db[ldesc].db.desc.cmd,
1450                                         OHCI_INTERRUPT_ALWAYS);
1451                                 FWOHCI_DMA_CLEAR(
1452                                         db[ldesc].db.desc.depend,
1453                                         0xf);
1454                         }
1455                 }
1456                 db_tr = STAILQ_NEXT(db_tr, link);
1457         }
1458         FWOHCI_DMA_CLEAR(
1459                 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf);
1460         dbch->buf_offset = 0;
1461         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1462         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1463         if (dbch->xferq.flag & FWXFERQ_STREAM) {
1464                 return err;
1465         } else {
1466                 OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z);
1467         }
1468         OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1469         return err;
1470 }
1471
1472 static int
1473 fwohci_next_cycle(struct firewire_comm *fc, int cycle_now)
1474 {
1475         int sec, cycle, cycle_match;
1476
1477         cycle = cycle_now & 0x1fff;
1478         sec = cycle_now >> 13;
1479 #define CYCLE_MOD       0x10
1480 #if 1
1481 #define CYCLE_DELAY     8       /* min delay to start DMA */
1482 #else
1483 #define CYCLE_DELAY     7000    /* min delay to start DMA */
1484 #endif
1485         cycle = cycle + CYCLE_DELAY;
1486         if (cycle >= 8000) {
1487                 sec++;
1488                 cycle -= 8000;
1489         }
1490         cycle = roundup2(cycle, CYCLE_MOD);
1491         if (cycle >= 8000) {
1492                 sec++;
1493                 if (cycle == 8000)
1494                         cycle = 0;
1495                 else
1496                         cycle = CYCLE_MOD;
1497         }
1498         cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1499
1500         return (cycle_match);
1501 }
1502
1503 static int
1504 fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1505 {
1506         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1507         int err = 0;
1508         unsigned short tag, ich;
1509         struct fwohci_dbch *dbch;
1510         int cycle_match, cycle_now, s, ldesc;
1511         uint32_t stat;
1512         struct fw_bulkxfer *first, *chunk, *prev;
1513         struct fw_xferq *it;
1514
1515         dbch = &sc->it[dmach];
1516         it = &dbch->xferq;
1517
1518         tag = (it->flag >> 6) & 3;
1519         ich = it->flag & 0x3f;
1520         if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
1521                 dbch->ndb = it->bnpacket * it->bnchunk;
1522                 dbch->ndesc = 3;
1523                 fwohci_db_init(sc, dbch);
1524                 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1525                         return ENOMEM;
1526
1527                 err = fwohci_tx_enable(sc, dbch);
1528         }
1529         if (err)
1530                 return err;
1531
1532         ldesc = dbch->ndesc - 1;
1533         s = splfw();
1534         FW_GLOCK(fc);
1535         prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1536         while  ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1537                 struct fwohcidb *db;
1538
1539                 fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
1540                                         BUS_DMASYNC_PREWRITE);
1541                 fwohci_txbufdb(sc, dmach, chunk);
1542                 if (prev != NULL) {
1543                         db = ((struct fwohcidb_tr *)(prev->end))->db;
1544 #if 0 /* XXX necessary? */
1545                         FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1546                                                 OHCI_BRANCH_ALWAYS);
1547 #endif
1548 #if 0 /* if bulkxfer->npacket changes */
1549                         db[ldesc].db.desc.depend = db[0].db.desc.depend =
1550                                 ((struct fwohcidb_tr *)
1551                                 (chunk->start))->bus_addr | dbch->ndesc;
1552 #else
1553                         FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
1554                         FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1555 #endif
1556                 }
1557                 STAILQ_REMOVE_HEAD(&it->stvalid, link);
1558                 STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
1559                 prev = chunk;
1560         }
1561         FW_GUNLOCK(fc);
1562         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1563         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1564         splx(s);
1565         stat = OREAD(sc, OHCI_ITCTL(dmach));
1566         if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
1567                 printf("stat 0x%x\n", stat);
1568
1569         if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
1570                 return 0;
1571
1572 #if 0
1573         OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1574 #endif
1575         OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1576         OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1577         OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1578         OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1579
1580         first = STAILQ_FIRST(&it->stdma);
1581         OWRITE(sc, OHCI_ITCMD(dmach),
1582                 ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
1583         if (firewire_debug > 1) {
1584                 printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
1585 #if 1
1586                 dump_dma(sc, ITX_CH + dmach);
1587 #endif
1588         }
1589         if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
1590 #if 1
1591                 /* Don't start until all chunks are buffered */
1592                 if (STAILQ_FIRST(&it->stfree) != NULL)
1593                         goto out;
1594 #endif
1595 #if 1
1596                 /* Clear cycle match counter bits */
1597                 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1598
1599                 /* 2bit second + 13bit cycle */
1600                 cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1601                 cycle_match = fwohci_next_cycle(fc, cycle_now);
1602
1603                 OWRITE(sc, OHCI_ITCTL(dmach),
1604                                 OHCI_CNTL_CYCMATCH_S | (cycle_match << 16)
1605                                 | OHCI_CNTL_DMA_RUN);
1606 #else
1607                 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1608 #endif
1609                 if (firewire_debug > 1) {
1610                         printf("cycle_match: 0x%04x->0x%04x\n",
1611                                                 cycle_now, cycle_match);
1612                         dump_dma(sc, ITX_CH + dmach);
1613                         dump_db(sc, ITX_CH + dmach);
1614                 }
1615         } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1616                 device_printf(sc->fc.dev,
1617                         "IT DMA underrun (0x%08x)\n", stat);
1618                 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1619         }
1620 out:
1621         return err;
1622 }
1623
1624 static int
1625 fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1626 {
1627         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1628         int err = 0, s, ldesc;
1629         unsigned short tag, ich;
1630         uint32_t stat;
1631         struct fwohci_dbch *dbch;
1632         struct fwohcidb_tr *db_tr;
1633         struct fw_bulkxfer *first, *prev, *chunk;
1634         struct fw_xferq *ir;
1635
1636         dbch = &sc->ir[dmach];
1637         ir = &dbch->xferq;
1638
1639         if ((ir->flag & FWXFERQ_RUNNING) == 0) {
1640                 tag = (ir->flag >> 6) & 3;
1641                 ich = ir->flag & 0x3f;
1642                 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1643
1644                 ir->queued = 0;
1645                 dbch->ndb = ir->bnpacket * ir->bnchunk;
1646                 dbch->ndesc = 2;
1647                 fwohci_db_init(sc, dbch);
1648                 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1649                         return ENOMEM;
1650                 err = fwohci_rx_enable(sc, dbch);
1651         }
1652         if (err)
1653                 return err;
1654
1655         first = STAILQ_FIRST(&ir->stfree);
1656         if (first == NULL) {
1657                 device_printf(fc->dev, "IR DMA no free chunk\n");
1658                 return 0;
1659         }
1660
1661         ldesc = dbch->ndesc - 1;
1662         s = splfw();
1663         if ((ir->flag & FWXFERQ_HANDLER) == 0)
1664                 FW_GLOCK(fc);
1665         prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
1666         while  ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1667                 struct fwohcidb *db;
1668
1669 #if 1 /* XXX for if_fwe */
1670                 if (chunk->mbuf != NULL) {
1671                         db_tr = (struct fwohcidb_tr *)(chunk->start);
1672                         db_tr->dbcnt = 1;
1673                         err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
1674                                         chunk->mbuf, fwohci_execute_db2, db_tr,
1675                                         /* flags */0);
1676                         FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
1677                                 OHCI_UPDATE | OHCI_INPUT_LAST |
1678                                 OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1679                 }
1680 #endif
1681                 db = ((struct fwohcidb_tr *)(chunk->end))->db;
1682                 FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
1683                 FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1684                 if (prev != NULL) {
1685                         db = ((struct fwohcidb_tr *)(prev->end))->db;
1686                         FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
1687                 }
1688                 STAILQ_REMOVE_HEAD(&ir->stfree, link);
1689                 STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
1690                 prev = chunk;
1691         }
1692         if ((ir->flag & FWXFERQ_HANDLER) == 0)
1693                 FW_GUNLOCK(fc);
1694         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
1695         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD);
1696         splx(s);
1697         stat = OREAD(sc, OHCI_IRCTL(dmach));
1698         if (stat & OHCI_CNTL_DMA_ACTIVE)
1699                 return 0;
1700         if (stat & OHCI_CNTL_DMA_RUN) {
1701                 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1702                 device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat);
1703         }
1704
1705         if (firewire_debug)
1706                 printf("start IR DMA 0x%x\n", stat);
1707         OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1708         OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1709         OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1710         OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1711         OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1712         OWRITE(sc, OHCI_IRCMD(dmach),
1713                 ((struct fwohcidb_tr *)(first->start))->bus_addr
1714                                                         | dbch->ndesc);
1715         OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1716         OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1717 #if 0
1718         dump_db(sc, IRX_CH + dmach);
1719 #endif
1720         return err;
1721 }
1722
1723 int
1724 fwohci_stop(struct fwohci_softc *sc, device_t dev)
1725 {
1726         u_int i;
1727
1728         fwohci_set_intr(&sc->fc, 0);
1729
1730 /* Now stopping all DMA channel */
1731         OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1732         OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1733         OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1734         OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1735
1736         for (i = 0; i < sc->fc.nisodma; i++) {
1737                 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1738                 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1739         }
1740
1741 #if 0 /* Let dcons(4) be accessed */
1742 /* Stop interrupt */
1743         OWRITE(sc, FWOHCI_INTMASKCLR,
1744                         OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1745                         | OHCI_INT_PHY_INT
1746                         | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1747                         | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1748                         | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1749                         | OHCI_INT_PHY_BUS_R);
1750
1751 /* FLUSH FIFO and reset Transmitter/Reciever */
1752         OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1753 #endif
1754
1755 /* XXX Link down?  Bus reset? */
1756         return 0;
1757 }
1758
1759 int
1760 fwohci_resume(struct fwohci_softc *sc, device_t dev)
1761 {
1762         int i;
1763         struct fw_xferq *ir;
1764         struct fw_bulkxfer *chunk;
1765
1766         fwohci_reset(sc, dev);
1767         /* XXX resume isochronous receive automatically. (how about TX?) */
1768         for (i = 0; i < sc->fc.nisodma; i++) {
1769                 ir = &sc->ir[i].xferq;
1770                 if ((ir->flag & FWXFERQ_RUNNING) != 0) {
1771                         device_printf(sc->fc.dev,
1772                                 "resume iso receive ch: %d\n", i);
1773                         ir->flag &= ~FWXFERQ_RUNNING;
1774                         /* requeue stdma to stfree */
1775                         while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
1776                                 STAILQ_REMOVE_HEAD(&ir->stdma, link);
1777                                 STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
1778                         }
1779                         sc->fc.irx_enable(&sc->fc, i);
1780                 }
1781         }
1782
1783         bus_generic_resume(dev);
1784         sc->fc.ibr(&sc->fc);
1785         return 0;
1786 }
1787
1788 #ifdef OHCI_DEBUG
1789 static void
1790 fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1791 {
1792         if (stat & OREAD(sc, FWOHCI_INTMASK))
1793                 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",
1794                         stat & OHCI_INT_EN ? "DMA_EN ":"",
1795                         stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1796                         stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1797                         stat & OHCI_INT_ERR ? "INT_ERR ":"",
1798                         stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1799                         stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1800                         stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1801                         stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1802                         stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1803                         stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1804                         stat & OHCI_INT_PHY_SID ? "SID ":"",
1805                         stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1806                         stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1807                         stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1808                         stat & OHCI_INT_DMA_IT  ? "DMA_IT " :"",
1809                         stat & OHCI_INT_DMA_PRRS  ? "DMA_PRRS " :"",
1810                         stat & OHCI_INT_DMA_PRRQ  ? "DMA_PRRQ " :"",
1811                         stat & OHCI_INT_DMA_ARRS  ? "DMA_ARRS " :"",
1812                         stat & OHCI_INT_DMA_ARRQ  ? "DMA_ARRQ " :"",
1813                         stat & OHCI_INT_DMA_ATRS  ? "DMA_ATRS " :"",
1814                         stat & OHCI_INT_DMA_ATRQ  ? "DMA_ATRQ " :"",
1815                         stat, OREAD(sc, FWOHCI_INTMASK)
1816                 );
1817 }
1818 #endif
1819
1820 static void
1821 fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count)
1822 {
1823         struct firewire_comm *fc = (struct firewire_comm *)sc;
1824         uintmax_t prequpper;
1825         uint32_t node_id, plen;
1826
1827         FW_GLOCK_ASSERT(fc);
1828         if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1829                 fc->status = FWBUSRESET;
1830                 /* Disable bus reset interrupt until sid recv. */
1831                 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1832
1833                 device_printf(fc->dev, "%s: BUS reset\n", __func__);
1834                 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1835                 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1836
1837                 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1838                 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1839                 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1840                 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1841
1842                 if (!kdb_active)
1843                         taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset);
1844         }
1845         if (stat & OHCI_INT_PHY_SID) {
1846                 /* Enable bus reset interrupt */
1847                 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1848                 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
1849
1850                 /* Allow async. request to us */
1851                 OWRITE(sc, OHCI_AREQHI, 1 << 31);
1852                 if (firewire_phydma_enable) {
1853                         /* allow from all nodes */
1854                         OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1855                         OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1856                         prequpper = ((uintmax_t)Maxmem << PAGE_SHIFT) >> 16;
1857                         if (prequpper > OHCI_PREQUPPER_MAX) {
1858                                 device_printf(fc->dev,
1859                                     "Physical memory size of 0x%jx exceeds "
1860                                     "fire wire address space.  Limiting dma "
1861                                     "to memory below 0x%jx\n",
1862                                     (uintmax_t)Maxmem << PAGE_SHIFT,
1863                                     (uintmax_t)OHCI_PREQUPPER_MAX << 16);
1864                                 prequpper = OHCI_PREQUPPER_MAX;
1865                         }
1866                         OWRITE(sc, OHCI_PREQUPPER, prequpper & 0xffffffff);
1867                 }
1868                 /* Set ATRetries register */
1869                 OWRITE(sc, OHCI_ATRETRY, 1<<(13 + 16) | 0xfff);
1870
1871                 /*
1872                  * Checking whether the node is root or not. If root, turn on
1873                  * cycle master.
1874                  */
1875                 node_id = OREAD(sc, FWOHCI_NODEID);
1876                 plen = OREAD(sc, OHCI_SID_CNT);
1877
1878                 fc->nodeid = node_id & 0x3f;
1879                 device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ",
1880                                 __func__, fc->nodeid, (plen >> 16) & 0xff);
1881                 if (!(node_id & OHCI_NODE_VALID)) {
1882                         device_printf(fc->dev, "%s: Bus reset failure\n",
1883                                 __func__);
1884                         goto sidout;
1885                 }
1886
1887                 /* cycle timer */
1888                 sc->cycle_lost = 0;
1889                 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
1890                 if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
1891                         printf("CYCLEMASTER mode\n");
1892                         OWRITE(sc, OHCI_LNKCTL,
1893                                 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1894                 } else {
1895                         printf("non CYCLEMASTER mode\n");
1896                         OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1897                         OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1898                 }
1899
1900                 fc->status = FWBUSINIT;
1901
1902                 if (!kdb_active)
1903                         taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid);
1904         }
1905 sidout:
1906         if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active))
1907                 taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma);
1908 }
1909
1910 static void
1911 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count)
1912 {
1913         uint32_t irstat, itstat;
1914         u_int i;
1915         struct firewire_comm *fc = (struct firewire_comm *)sc;
1916
1917         if (stat & OHCI_INT_DMA_IR) {
1918                 irstat = atomic_readandclear_int(&sc->irstat);
1919                 for (i = 0; i < fc->nisodma; i++) {
1920                         struct fwohci_dbch *dbch;
1921
1922                         if ((irstat & (1 << i)) != 0) {
1923                                 dbch = &sc->ir[i];
1924                                 if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
1925                                         device_printf(sc->fc.dev,
1926                                                 "dma(%d) not active\n", i);
1927                                         continue;
1928                                 }
1929                                 fwohci_rbuf_update(sc, i);
1930                         }
1931                 }
1932         }
1933         if (stat & OHCI_INT_DMA_IT) {
1934                 itstat = atomic_readandclear_int(&sc->itstat);
1935                 for (i = 0; i < fc->nisodma; i++) {
1936                         if ((itstat & (1 << i)) != 0) {
1937                                 fwohci_tbuf_update(sc, i);
1938                         }
1939                 }
1940         }
1941         if (stat & OHCI_INT_DMA_PRRS) {
1942 #if 0
1943                 dump_dma(sc, ARRS_CH);
1944                 dump_db(sc, ARRS_CH);
1945 #endif
1946                 fwohci_arcv(sc, &sc->arrs, count);
1947         }
1948         if (stat & OHCI_INT_DMA_PRRQ) {
1949 #if 0
1950                 dump_dma(sc, ARRQ_CH);
1951                 dump_db(sc, ARRQ_CH);
1952 #endif
1953                 fwohci_arcv(sc, &sc->arrq, count);
1954         }
1955         if (stat & OHCI_INT_CYC_LOST) {
1956                 if (sc->cycle_lost >= 0)
1957                         sc->cycle_lost++;
1958                 if (sc->cycle_lost > 10) {
1959                         sc->cycle_lost = -1;
1960 #if 0
1961                         OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
1962 #endif
1963                         OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1964                         device_printf(fc->dev, "too many cycles lost, "
1965                          "no cycle master present?\n");
1966                 }
1967         }
1968         if (stat & OHCI_INT_DMA_ATRQ) {
1969                 fwohci_txd(sc, &(sc->atrq));
1970         }
1971         if (stat & OHCI_INT_DMA_ATRS) {
1972                 fwohci_txd(sc, &(sc->atrs));
1973         }
1974         if (stat & OHCI_INT_PW_ERR) {
1975                 device_printf(fc->dev, "posted write error\n");
1976         }
1977         if (stat & OHCI_INT_ERR) {
1978                 device_printf(fc->dev, "unrecoverable error\n");
1979         }
1980         if (stat & OHCI_INT_PHY_INT) {
1981                 device_printf(fc->dev, "phy int\n");
1982         }
1983 }
1984
1985 static void
1986 fwohci_task_busreset(void *arg, int pending)
1987 {
1988         struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1989
1990         FW_GLOCK(&sc->fc);
1991         fw_busreset(&sc->fc, FWBUSRESET);
1992         OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
1993         OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
1994         FW_GUNLOCK(&sc->fc);
1995 }
1996
1997 static void
1998 fwohci_task_sid(void *arg, int pending)
1999 {
2000         struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2001         struct firewire_comm *fc = &sc->fc;
2002         uint32_t *buf;
2003         int i, plen;
2004
2005
2006         /*
2007          * We really should have locking
2008          * here.  Not sure why it's not
2009          */
2010         plen = OREAD(sc, OHCI_SID_CNT);
2011
2012         if (plen & OHCI_SID_ERR) {
2013                 device_printf(fc->dev, "SID Error\n");
2014                 return;
2015         }
2016         plen &= OHCI_SID_CNT_MASK;
2017         if (plen < 4 || plen > OHCI_SIDSIZE) {
2018                 device_printf(fc->dev, "invalid SID len = %d\n", plen);
2019                 return;
2020         }
2021         plen -= 4; /* chop control info */
2022         buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2023         if (buf == NULL) {
2024                 device_printf(fc->dev, "malloc failed\n");
2025                 return;
2026         }
2027         for (i = 0; i < plen / 4; i++)
2028                 buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2029
2030         /* pending all pre-bus_reset packets */
2031         fwohci_txd(sc, &sc->atrq);
2032         fwohci_txd(sc, &sc->atrs);
2033         fwohci_arcv(sc, &sc->arrs, -1);
2034         fwohci_arcv(sc, &sc->arrq, -1);
2035         fw_drain_txq(fc);
2036         fw_sidrcv(fc, buf, plen);
2037         free(buf, M_FW);
2038 }
2039
2040 static void
2041 fwohci_task_dma(void *arg, int pending)
2042 {
2043         struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2044         uint32_t stat;
2045
2046 again:
2047         stat = atomic_readandclear_int(&sc->intstat);
2048         if (stat)
2049                 fwohci_intr_dma(sc, stat, -1);
2050         else
2051                 return;
2052         goto again;
2053 }
2054
2055 static int
2056 fwohci_check_stat(struct fwohci_softc *sc)
2057 {
2058         uint32_t stat, irstat, itstat;
2059
2060         FW_GLOCK_ASSERT(&sc->fc);
2061         stat = OREAD(sc, FWOHCI_INTSTAT);
2062         if (stat == 0xffffffff) {
2063                 if (!bus_child_present(sc->fc.dev))
2064                         return (FILTER_HANDLED);
2065                 device_printf(sc->fc.dev, "device physically ejected?\n");
2066                 return (FILTER_STRAY);
2067         }
2068         if (stat)
2069                 OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
2070
2071         stat &= sc->intmask;
2072         if (stat == 0)
2073                 return (FILTER_STRAY);
2074
2075         atomic_set_int(&sc->intstat, stat);
2076         if (stat & OHCI_INT_DMA_IR) {
2077                 irstat = OREAD(sc, OHCI_IR_STAT);
2078                 OWRITE(sc, OHCI_IR_STATCLR, irstat);
2079                 atomic_set_int(&sc->irstat, irstat);
2080         }
2081         if (stat & OHCI_INT_DMA_IT) {
2082                 itstat = OREAD(sc, OHCI_IT_STAT);
2083                 OWRITE(sc, OHCI_IT_STATCLR, itstat);
2084                 atomic_set_int(&sc->itstat, itstat);
2085         }
2086
2087         fwohci_intr_core(sc, stat, -1);
2088         return (FILTER_HANDLED);
2089 }
2090
2091 void
2092 fwohci_intr(void *arg)
2093 {
2094         struct fwohci_softc *sc = (struct fwohci_softc *)arg;
2095
2096         FW_GLOCK(&sc->fc);
2097         fwohci_check_stat(sc);
2098         FW_GUNLOCK(&sc->fc);
2099 }
2100
2101 void
2102 fwohci_poll(struct firewire_comm *fc, int quick, int count)
2103 {
2104         struct fwohci_softc *sc = (struct fwohci_softc *)fc;
2105
2106         FW_GLOCK(fc);
2107         fwohci_check_stat(sc);
2108         FW_GUNLOCK(fc);
2109 }
2110
2111 static void
2112 fwohci_set_intr(struct firewire_comm *fc, int enable)
2113 {
2114         struct fwohci_softc *sc;
2115
2116         sc = (struct fwohci_softc *)fc;
2117         if (firewire_debug)
2118                 device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable);
2119         if (enable) {
2120                 sc->intmask |= OHCI_INT_EN;
2121                 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
2122         } else {
2123                 sc->intmask &= ~OHCI_INT_EN;
2124                 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2125         }
2126 }
2127
2128 static void
2129 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2130 {
2131         struct firewire_comm *fc = &sc->fc;
2132         struct fwohcidb *db;
2133         struct fw_bulkxfer *chunk;
2134         struct fw_xferq *it;
2135         uint32_t stat, count;
2136         int s, w=0, ldesc;
2137
2138         it = fc->it[dmach];
2139         ldesc = sc->it[dmach].ndesc - 1;
2140         s = splfw(); /* unnecessary ? */
2141         FW_GLOCK(fc);
2142         fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2143         if (firewire_debug)
2144                 dump_db(sc, ITX_CH + dmach);
2145         while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2146                 db = ((struct fwohcidb_tr *)(chunk->end))->db;
2147                 stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2148                                 >> OHCI_STATUS_SHIFT;
2149                 db = ((struct fwohcidb_tr *)(chunk->start))->db;
2150                 /* timestamp */
2151                 count = FWOHCI_DMA_READ(db[ldesc].db.desc.res)
2152                                 & OHCI_COUNT_MASK;
2153                 if (stat == 0)
2154                         break;
2155                 STAILQ_REMOVE_HEAD(&it->stdma, link);
2156                 switch (stat & FWOHCIEV_MASK) {
2157                 case FWOHCIEV_ACKCOMPL:
2158 #if 0
2159                         device_printf(fc->dev, "0x%08x\n", count);
2160 #endif
2161                         break;
2162                 default:
2163                         device_printf(fc->dev,
2164                                 "Isochronous transmit err %02x(%s)\n",
2165                                         stat, fwohcicode[stat & 0x1f]);
2166                 }
2167                 STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2168                 w++;
2169         }
2170         FW_GUNLOCK(fc);
2171         splx(s);
2172         if (w)
2173                 wakeup(it);
2174 }
2175
2176 static void
2177 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2178 {
2179         struct firewire_comm *fc = &sc->fc;
2180         struct fwohcidb_tr *db_tr;
2181         struct fw_bulkxfer *chunk;
2182         struct fw_xferq *ir;
2183         uint32_t stat;
2184         int w = 0, ldesc;
2185
2186         ir = fc->ir[dmach];
2187         ldesc = sc->ir[dmach].ndesc - 1;
2188
2189 #if 0
2190         dump_db(sc, dmach);
2191 #endif
2192         if ((ir->flag & FWXFERQ_HANDLER) == 0)
2193                 FW_GLOCK(fc);
2194         fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2195         while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2196                 db_tr = (struct fwohcidb_tr *)chunk->end;
2197                 stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res)
2198                                 >> OHCI_STATUS_SHIFT;
2199                 if (stat == 0)
2200                         break;
2201
2202                 if (chunk->mbuf != NULL) {
2203                         bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map,
2204                                                 BUS_DMASYNC_POSTREAD);
2205                         bus_dmamap_unload(sc->ir[dmach].dmat, db_tr->dma_map);
2206                 } else if (ir->buf != NULL) {
2207                         fwdma_sync_multiseg(ir->buf, chunk->poffset,
2208                                 ir->bnpacket, BUS_DMASYNC_POSTREAD);
2209                 } else {
2210                         /* XXX */
2211                         printf("fwohci_rbuf_update: this shouldn't happend\n");
2212                 }
2213
2214                 STAILQ_REMOVE_HEAD(&ir->stdma, link);
2215                 STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2216                 switch (stat & FWOHCIEV_MASK) {
2217                 case FWOHCIEV_ACKCOMPL:
2218                         chunk->resp = 0;
2219                         break;
2220                 default:
2221                         chunk->resp = EINVAL;
2222                         device_printf(fc->dev,
2223                                 "Isochronous receive err %02x(%s)\n",
2224                                         stat, fwohcicode[stat & 0x1f]);
2225                 }
2226                 w++;
2227         }
2228         if ((ir->flag & FWXFERQ_HANDLER) == 0)
2229                 FW_GUNLOCK(fc);
2230         if (w == 0)
2231                 return;
2232
2233         if (ir->flag & FWXFERQ_HANDLER)
2234                 ir->hand(ir);
2235         else
2236                 wakeup(ir);
2237 }
2238
2239 void
2240 dump_dma(struct fwohci_softc *sc, uint32_t ch)
2241 {
2242         uint32_t off, cntl, stat, cmd, match;
2243
2244         if (ch == 0) {
2245                 off = OHCI_ATQOFF;
2246         } else if (ch == 1) {
2247                 off = OHCI_ATSOFF;
2248         } else if (ch == 2) {
2249                 off = OHCI_ARQOFF;
2250         } else if (ch == 3) {
2251                 off = OHCI_ARSOFF;
2252         } else if (ch < IRX_CH) {
2253                 off = OHCI_ITCTL(ch - ITX_CH);
2254         } else {
2255                 off = OHCI_IRCTL(ch - IRX_CH);
2256         }
2257         cntl = stat = OREAD(sc, off);
2258         cmd = OREAD(sc, off + 0xc);
2259         match = OREAD(sc, off + 0x10);
2260
2261         device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2262                 ch,
2263                 cntl,
2264                 cmd,
2265                 match);
2266         stat &= 0xffff;
2267         if (stat) {
2268                 device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2269                         ch,
2270                         stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2271                         stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2272                         stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2273                         stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2274                         stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2275                         stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2276                         fwohcicode[stat & 0x1f],
2277                         stat & 0x1f
2278                 );
2279         } else {
2280                 device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2281         }
2282 }
2283
2284 void
2285 dump_db(struct fwohci_softc *sc, uint32_t ch)
2286 {
2287         struct fwohci_dbch *dbch;
2288         struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
2289         struct fwohcidb *curr = NULL, *prev, *next = NULL;
2290         int idb, jdb;
2291         uint32_t cmd, off;
2292
2293         if (ch == 0) {
2294                 off = OHCI_ATQOFF;
2295                 dbch = &sc->atrq;
2296         } else if (ch == 1) {
2297                 off = OHCI_ATSOFF;
2298                 dbch = &sc->atrs;
2299         } else if (ch == 2) {
2300                 off = OHCI_ARQOFF;
2301                 dbch = &sc->arrq;
2302         } else if (ch == 3) {
2303                 off = OHCI_ARSOFF;
2304                 dbch = &sc->arrs;
2305         } else if (ch < IRX_CH) {
2306                 off = OHCI_ITCTL(ch - ITX_CH);
2307                 dbch = &sc->it[ch - ITX_CH];
2308         } else {
2309                 off = OHCI_IRCTL(ch - IRX_CH);
2310                 dbch = &sc->ir[ch - IRX_CH];
2311         }
2312         cmd = OREAD(sc, off + 0xc);
2313
2314         if (dbch->ndb == 0) {
2315                 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2316                 return;
2317         }
2318         pp = dbch->top;
2319         prev = pp->db;
2320         for (idb = 0; idb < dbch->ndb; idb++) {
2321                 cp = STAILQ_NEXT(pp, link);
2322                 if (cp == NULL) {
2323                         curr = NULL;
2324                         goto outdb;
2325                 }
2326                 np = STAILQ_NEXT(cp, link);
2327                 for (jdb = 0; jdb < dbch->ndesc; jdb++) {
2328                         if ((cmd  & 0xfffffff0) == cp->bus_addr) {
2329                                 curr = cp->db;
2330                                 if (np != NULL) {
2331                                         next = np->db;
2332                                 } else {
2333                                         next = NULL;
2334                                 }
2335                                 goto outdb;
2336                         }
2337                 }
2338                 pp = STAILQ_NEXT(pp, link);
2339                 if (pp == NULL) {
2340                         curr = NULL;
2341                         goto outdb;
2342                 }
2343                 prev = pp->db;
2344         }
2345 outdb:
2346         if (curr != NULL) {
2347 #if 0
2348                 printf("Prev DB %d\n", ch);
2349                 print_db(pp, prev, ch, dbch->ndesc);
2350 #endif
2351                 printf("Current DB %d\n", ch);
2352                 print_db(cp, curr, ch, dbch->ndesc);
2353 #if 0
2354                 printf("Next DB %d\n", ch);
2355                 print_db(np, next, ch, dbch->ndesc);
2356 #endif
2357         } else {
2358                 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2359         }
2360         return;
2361 }
2362
2363 void
2364 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2365                 uint32_t ch, uint32_t max)
2366 {
2367         fwohcireg_t stat;
2368         int i, key;
2369         uint32_t cmd, res;
2370
2371         if (db == NULL) {
2372                 printf("No Descriptor is found\n");
2373                 return;
2374         }
2375
2376         printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2377                 ch,
2378                 "Current",
2379                 "OP  ",
2380                 "KEY",
2381                 "INT",
2382                 "BR ",
2383                 "len",
2384                 "Addr",
2385                 "Depend",
2386                 "Stat",
2387                 "Cnt");
2388         for (i = 0; i <= max; i++) {
2389                 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2390                 res = FWOHCI_DMA_READ(db[i].db.desc.res);
2391                 key = cmd & OHCI_KEY_MASK;
2392                 stat = res >> OHCI_STATUS_SHIFT;
2393                 printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2394                                 (uintmax_t)db_tr->bus_addr,
2395                                 dbcode[(cmd >> 28) & 0xf],
2396                                 dbkey[(cmd >> 24) & 0x7],
2397                                 dbcond[(cmd >> 20) & 0x3],
2398                                 dbcond[(cmd >> 18) & 0x3],
2399                                 cmd & OHCI_COUNT_MASK,
2400                                 FWOHCI_DMA_READ(db[i].db.desc.addr),
2401                                 FWOHCI_DMA_READ(db[i].db.desc.depend),
2402                                 stat,
2403                                 res & OHCI_COUNT_MASK);
2404                 if (stat & 0xff00) {
2405                         printf(" %s%s%s%s%s%s %s(%x)\n",
2406                                 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2407                                 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2408                                 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2409                                 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2410                                 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2411                                 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2412                                 fwohcicode[stat & 0x1f],
2413                                 stat & 0x1f
2414                         );
2415                 } else {
2416                         printf(" Nostat\n");
2417                 }
2418                 if (key == OHCI_KEY_ST2) {
2419                         printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2420                                 FWOHCI_DMA_READ(db[i + 1].db.immed[0]),
2421                                 FWOHCI_DMA_READ(db[i + 1].db.immed[1]),
2422                                 FWOHCI_DMA_READ(db[i + 1].db.immed[2]),
2423                                 FWOHCI_DMA_READ(db[i + 1].db.immed[3]));
2424                 }
2425                 if (key == OHCI_KEY_DEVICE) {
2426                         return;
2427                 }
2428                 if ((cmd & OHCI_BRANCH_MASK)
2429                                 == OHCI_BRANCH_ALWAYS) {
2430                         return;
2431                 }
2432                 if ((cmd & OHCI_CMD_MASK)
2433                                 == OHCI_OUTPUT_LAST) {
2434                         return;
2435                 }
2436                 if ((cmd & OHCI_CMD_MASK)
2437                                 == OHCI_INPUT_LAST) {
2438                         return;
2439                 }
2440                 if (key == OHCI_KEY_ST2) {
2441                         i++;
2442                 }
2443         }
2444         return;
2445 }
2446
2447 void
2448 fwohci_ibr(struct firewire_comm *fc)
2449 {
2450         struct fwohci_softc *sc;
2451         uint32_t fun;
2452
2453         device_printf(fc->dev, "Initiate bus reset\n");
2454         sc = (struct fwohci_softc *)fc;
2455
2456         FW_GLOCK(fc);
2457         /*
2458          * Make sure our cached values from the config rom are
2459          * initialised.
2460          */
2461         OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2462         OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2463
2464         /*
2465          * Set root hold-off bit so that non cyclemaster capable node
2466          * shouldn't became the root node.
2467          */
2468 #if 1
2469         fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
2470         fun |= FW_PHY_IBR | FW_PHY_RHB;
2471         fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
2472 #else   /* Short bus reset */
2473         fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2474         fun |= FW_PHY_ISBR | FW_PHY_RHB;
2475         fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2476 #endif
2477         FW_GUNLOCK(fc);
2478 }
2479
2480 void
2481 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2482 {
2483         struct fwohcidb_tr *db_tr, *fdb_tr;
2484         struct fwohci_dbch *dbch;
2485         struct fwohcidb *db;
2486         struct fw_pkt *fp;
2487         struct fwohci_txpkthdr *ohcifp;
2488         unsigned short chtag;
2489         int idb;
2490
2491         FW_GLOCK_ASSERT(&sc->fc);
2492
2493         dbch = &sc->it[dmach];
2494         chtag = sc->it[dmach].xferq.flag & 0xff;
2495
2496         db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2497         fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2498 /*
2499 device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2500 */
2501         for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2502                 db = db_tr->db;
2503                 fp = (struct fw_pkt *)db_tr->buf;
2504                 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2505                 ohcifp->mode.ld[0] = fp->mode.ld[0];
2506                 ohcifp->mode.common.spd = 0 & 0x7;
2507                 ohcifp->mode.stream.len = fp->mode.stream.len;
2508                 ohcifp->mode.stream.chtag = chtag;
2509                 ohcifp->mode.stream.tcode = 0xa;
2510 #if BYTE_ORDER == BIG_ENDIAN
2511                 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2512                 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2513 #endif
2514
2515                 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2516                 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2517                 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2518 #if 0 /* if bulkxfer->npackets changes */
2519                 db[2].db.desc.cmd = OHCI_OUTPUT_LAST
2520                         | OHCI_UPDATE
2521                         | OHCI_BRANCH_ALWAYS;
2522                 db[0].db.desc.depend =
2523                         = db[dbch->ndesc - 1].db.desc.depend
2524                         = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2525 #else
2526                 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2527                 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2528 #endif
2529                 bulkxfer->end = (caddr_t)db_tr;
2530                 db_tr = STAILQ_NEXT(db_tr, link);
2531         }
2532         db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2533         FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2534         FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2535 #if 0 /* if bulkxfer->npackets changes */
2536         db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2537         /* OHCI 1.1 and above */
2538         db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2539 #endif
2540 /*
2541         db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2542         fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2543 device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2544 */
2545         return;
2546 }
2547
2548 static int
2549 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2550                                                                 int poffset)
2551 {
2552         struct fwohcidb *db = db_tr->db;
2553         struct fw_xferq *it;
2554         int err = 0;
2555
2556         it = &dbch->xferq;
2557         if (it->buf == 0) {
2558                 err = EINVAL;
2559                 return err;
2560         }
2561         db_tr->buf = fwdma_v_addr(it->buf, poffset);
2562         db_tr->dbcnt = 3;
2563
2564         FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2565                 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2566         FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2567         bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2568         FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2569         fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2570
2571         FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2572                 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2573 #if 1
2574         FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2575         FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2576 #endif
2577         return 0;
2578 }
2579
2580 int
2581 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2582                 int poffset, struct fwdma_alloc *dummy_dma)
2583 {
2584         struct fwohcidb *db = db_tr->db;
2585         struct fw_xferq *ir;
2586         int i, ldesc;
2587         bus_addr_t dbuf[2];
2588         int dsiz[2];
2589
2590         ir = &dbch->xferq;
2591         if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2592                 if (db_tr->buf == NULL) {
2593                         db_tr->buf = fwdma_malloc_size(dbch->dmat,
2594                             &db_tr->dma_map, ir->psize, &dbuf[0],
2595                             BUS_DMA_NOWAIT);
2596                         if (db_tr->buf == NULL)
2597                                 return (ENOMEM);
2598                 }
2599                 db_tr->dbcnt = 1;
2600                 dsiz[0] = ir->psize;
2601                 bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2602                         BUS_DMASYNC_PREREAD);
2603         } else {
2604                 db_tr->dbcnt = 0;
2605                 if (dummy_dma != NULL) {
2606                         dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2607                         dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2608                 }
2609                 dsiz[db_tr->dbcnt] = ir->psize;
2610                 if (ir->buf != NULL) {
2611                         db_tr->buf = fwdma_v_addr(ir->buf, poffset);
2612                         dbuf[db_tr->dbcnt] = fwdma_bus_addr(ir->buf, poffset);
2613                 }
2614                 db_tr->dbcnt++;
2615         }
2616         for (i = 0; i < db_tr->dbcnt; i++) {
2617                 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2618                 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2619                 if (ir->flag & FWXFERQ_STREAM) {
2620                         FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2621                 }
2622                 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2623         }
2624         ldesc = db_tr->dbcnt - 1;
2625         if (ir->flag & FWXFERQ_STREAM) {
2626                 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2627         }
2628         FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2629         return 0;
2630 }
2631
2632
2633 static int
2634 fwohci_arcv_swap(struct fw_pkt *fp, int len)
2635 {
2636         struct fw_pkt *fp0;
2637         uint32_t ld0;
2638         int slen, hlen;
2639 #if BYTE_ORDER == BIG_ENDIAN
2640         int i;
2641 #endif
2642
2643         ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2644 #if 0
2645         printf("ld0: x%08x\n", ld0);
2646 #endif
2647         fp0 = (struct fw_pkt *)&ld0;
2648         /* determine length to swap */
2649         switch (fp0->mode.common.tcode) {
2650         case FWTCODE_RREQQ:
2651         case FWTCODE_WRES:
2652         case FWTCODE_WREQQ:
2653         case FWTCODE_RRESQ:
2654         case FWOHCITCODE_PHY:
2655                 slen = 12;
2656                 break;
2657         case FWTCODE_RREQB:
2658         case FWTCODE_WREQB:
2659         case FWTCODE_LREQ:
2660         case FWTCODE_RRESB:
2661         case FWTCODE_LRES:
2662                 slen = 16;
2663                 break;
2664         default:
2665                 printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2666                 return (0);
2667         }
2668         hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2669         if (hlen > len) {
2670                 if (firewire_debug)
2671                         printf("splitted header\n");
2672                 return (-hlen);
2673         }
2674 #if BYTE_ORDER == BIG_ENDIAN
2675         for (i = 0; i < slen/4; i++)
2676                 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2677 #endif
2678         return (hlen);
2679 }
2680
2681 static int
2682 fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2683 {
2684         struct tcode_info *info;
2685         int r;
2686
2687         info = &tinfo[fp->mode.common.tcode];
2688         r = info->hdr_len + sizeof(uint32_t);
2689         if ((info->flag & FWTI_BLOCK_ASY) != 0)
2690                 r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2691
2692         if (r == sizeof(uint32_t)) {
2693                 /* XXX */
2694                 device_printf(sc->fc.dev, "Unknown tcode %d\n",
2695                                                 fp->mode.common.tcode);
2696                 return (-1);
2697         }
2698
2699         if (r > dbch->xferq.psize) {
2700                 device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2701                 return (-1);
2702                 /* panic ? */
2703         }
2704
2705         return r;
2706 }
2707
2708 static void
2709 fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2710     struct fwohcidb_tr *db_tr, uint32_t off, int wake)
2711 {
2712         struct fwohcidb *db = &db_tr->db[0];
2713
2714         FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2715         FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2716         FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2717         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
2718         dbch->bottom = db_tr;
2719
2720         if (wake)
2721                 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2722 }
2723
2724 static void
2725 fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2726 {
2727         struct fwohcidb_tr *db_tr;
2728         struct iovec vec[2];
2729         struct fw_pkt pktbuf;
2730         int nvec;
2731         struct fw_pkt *fp;
2732         uint8_t *ld;
2733         uint32_t stat, off, status, event;
2734         u_int spd;
2735         int len, plen, hlen, pcnt, offset;
2736         int s;
2737         caddr_t buf;
2738         int resCount;
2739
2740         if (&sc->arrq == dbch) {
2741                 off = OHCI_ARQOFF;
2742         } else if (&sc->arrs == dbch) {
2743                 off = OHCI_ARSOFF;
2744         } else {
2745                 return;
2746         }
2747
2748         s = splfw();
2749         db_tr = dbch->top;
2750         pcnt = 0;
2751         /* XXX we cannot handle a packet which lies in more than two buf */
2752         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTREAD);
2753         fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_POSTWRITE);
2754         status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2755         resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2756         while (status & OHCI_CNTL_DMA_ACTIVE) {
2757 #if 0
2758
2759                 if (off == OHCI_ARQOFF)
2760                         printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2761                             db_tr->bus_addr, status, resCount);
2762 #endif
2763                 len = dbch->xferq.psize - resCount;
2764                 ld = (uint8_t *)db_tr->buf;
2765                 if (dbch->pdb_tr == NULL) {
2766                         len -= dbch->buf_offset;
2767                         ld += dbch->buf_offset;
2768                 }
2769                 if (len > 0)
2770                         bus_dmamap_sync(dbch->dmat, db_tr->dma_map,
2771                                         BUS_DMASYNC_POSTREAD);
2772                 while (len > 0) {
2773                         if (count >= 0 && count-- == 0)
2774                                 goto out;
2775                         if (dbch->pdb_tr != NULL) {
2776                                 /* we have a fragment in previous buffer */
2777                                 int rlen;
2778
2779                                 offset = dbch->buf_offset;
2780                                 if (offset < 0)
2781                                         offset = - offset;
2782                                 buf = dbch->pdb_tr->buf + offset;
2783                                 rlen = dbch->xferq.psize - offset;
2784                                 if (firewire_debug)
2785                                         printf("rlen=%d, offset=%d\n",
2786                                                 rlen, dbch->buf_offset);
2787                                 if (dbch->buf_offset < 0) {
2788                                         /* splitted in header, pull up */
2789                                         char *p;
2790
2791                                         p = (char *)&pktbuf;
2792                                         bcopy(buf, p, rlen);
2793                                         p += rlen;
2794                                         /* this must be too long but harmless */
2795                                         rlen = sizeof(pktbuf) - rlen;
2796                                         if (rlen < 0)
2797                                                 printf("why rlen < 0\n");
2798                                         bcopy(db_tr->buf, p, rlen);
2799                                         ld += rlen;
2800                                         len -= rlen;
2801                                         hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf));
2802                                         if (hlen <= 0) {
2803                                                 printf("hlen should be positive.");
2804                                                 goto err;
2805                                         }
2806                                         offset = sizeof(pktbuf);
2807                                         vec[0].iov_base = (char *)&pktbuf;
2808                                         vec[0].iov_len = offset;
2809                                 } else {
2810                                         /* splitted in payload */
2811                                         offset = rlen;
2812                                         vec[0].iov_base = buf;
2813                                         vec[0].iov_len = rlen;
2814                                 }
2815                                 fp=(struct fw_pkt *)vec[0].iov_base;
2816                                 nvec = 1;
2817                         } else {
2818                                 /* no fragment in previous buffer */
2819                                 fp=(struct fw_pkt *)ld;
2820                                 hlen = fwohci_arcv_swap(fp, len);
2821                                 if (hlen == 0)
2822                                         goto err;
2823                                 if (hlen < 0) {
2824                                         dbch->pdb_tr = db_tr;
2825                                         dbch->buf_offset = - dbch->buf_offset;
2826                                         /* sanity check */
2827                                         if (resCount != 0) {
2828                                                 printf("resCount=%d hlen=%d\n",
2829                                                     resCount, hlen);
2830                                                     goto err;
2831                                         }
2832                                         goto out;
2833                                 }
2834                                 offset = 0;
2835                                 nvec = 0;
2836                         }
2837                         plen = fwohci_get_plen(sc, dbch, fp) - offset;
2838                         if (plen < 0) {
2839                                 /* minimum header size + trailer
2840                                 = sizeof(fw_pkt) so this shouldn't happens */
2841                                 printf("plen(%d) is negative! offset=%d\n",
2842                                     plen, offset);
2843                                 goto err;
2844                         }
2845                         if (plen > 0) {
2846                                 len -= plen;
2847                                 if (len < 0) {
2848                                         dbch->pdb_tr = db_tr;
2849                                         if (firewire_debug)
2850                                                 printf("splitted payload\n");
2851                                         /* sanity check */
2852                                         if (resCount != 0) {
2853                                                 printf("resCount=%d plen=%d"
2854                                                     " len=%d\n",
2855                                                     resCount, plen, len);
2856                                                 goto err;
2857                                         }
2858                                         goto out;
2859                                 }
2860                                 vec[nvec].iov_base = ld;
2861                                 vec[nvec].iov_len = plen;
2862                                 nvec++;
2863                                 ld += plen;
2864                         }
2865                         dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2866                         if (nvec == 0)
2867                                 printf("nvec == 0\n");
2868
2869 /* DMA result-code will be written at the tail of packet */
2870                         stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer)));
2871 #if 0
2872                         printf("plen: %d, stat %x\n",
2873                             plen ,stat);
2874 #endif
2875                         spd = (stat >> 21) & 0x3;
2876                         event = (stat >> 16) & 0x1f;
2877                         switch (event) {
2878                         case FWOHCIEV_ACKPEND:
2879 #if 0
2880                                 printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
2881 #endif
2882                                 /* fall through */
2883                         case FWOHCIEV_ACKCOMPL:
2884                         {
2885                                 struct fw_rcv_buf rb;
2886
2887                                 if ((vec[nvec-1].iov_len -=
2888                                         sizeof(struct fwohci_trailer)) == 0)
2889                                         nvec--;
2890                                 rb.fc = &sc->fc;
2891                                 rb.vec = vec;
2892                                 rb.nvec = nvec;
2893                                 rb.spd = spd;
2894                                 fw_rcv(&rb);
2895                                 break;
2896                         }
2897                         case FWOHCIEV_BUSRST:
2898                                 if ((sc->fc.status != FWBUSRESET) &&
2899                                     (sc->fc.status != FWBUSINIT))
2900                                         printf("got BUSRST packet!?\n");
2901                                 break;
2902                         default:
2903                                 device_printf(sc->fc.dev,
2904                                     "Async DMA Receive error err=%02x %s"
2905                                     " plen=%d offset=%d len=%d status=0x%08x"
2906                                     " tcode=0x%x, stat=0x%08x\n",
2907                                     event, fwohcicode[event], plen,
2908                                     dbch->buf_offset, len,
2909                                     OREAD(sc, OHCI_DMACTL(off)),
2910                                     fp->mode.common.tcode, stat);
2911 #if 1 /* XXX */
2912                                 goto err;
2913 #endif
2914                                 break;
2915                         }
2916                         pcnt++;
2917                         if (dbch->pdb_tr != NULL) {
2918                                 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr,
2919                                     off, 1);
2920                                 dbch->pdb_tr = NULL;
2921                         }
2922
2923                 }
2924 out:
2925                 if (resCount == 0) {
2926                         /* done on this buffer */
2927                         if (dbch->pdb_tr == NULL) {
2928                                 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1);
2929                                 dbch->buf_offset = 0;
2930                         } else
2931                                 if (dbch->pdb_tr != db_tr)
2932                                         printf("pdb_tr != db_tr\n");
2933                         db_tr = STAILQ_NEXT(db_tr, link);
2934                         status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2935                                                 >> OHCI_STATUS_SHIFT;
2936                         resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2937                                                 & OHCI_COUNT_MASK;
2938                         /* XXX check buffer overrun */
2939                         dbch->top = db_tr;
2940                 } else {
2941                         dbch->buf_offset = dbch->xferq.psize - resCount;
2942                         break;
2943                 }
2944                 /* XXX make sure DMA is not dead */
2945         }
2946 #if 0
2947         if (pcnt < 1)
2948                 printf("fwohci_arcv: no packets\n");
2949 #endif
2950         splx(s);
2951         return;
2952
2953 err:
2954         device_printf(sc->fc.dev, "AR DMA status=%x, ",
2955                                         OREAD(sc, OHCI_DMACTL(off)));
2956         dbch->pdb_tr = NULL;
2957         /* skip until resCount != 0 */
2958         printf(" skip buffer");
2959         while (resCount == 0) {
2960                 printf(" #");
2961                 fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0);
2962                 db_tr = STAILQ_NEXT(db_tr, link);
2963                 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2964                                                 & OHCI_COUNT_MASK;
2965         }
2966         printf(" done\n");
2967         dbch->top = db_tr;
2968         dbch->buf_offset = dbch->xferq.psize - resCount;
2969         OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
2970         splx(s);
2971 }