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