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