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