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