2 * Copyright (c) 2003 Hidetoshi Shimokawa
3 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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:
17 * This product includes software developed by K. Kobayashi and H. Shimokawa
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.
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.
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 $
45 #include <sys/param.h>
46 #include <sys/systm.h>
48 #include <sys/malloc.h>
49 #include <sys/sockio.h>
51 #include <sys/kernel.h>
53 #include <sys/device.h>
54 #include <sys/endian.h>
56 #include <sys/thread2.h>
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>
65 static char dbcode
[16][0x10]={"OUTM", "OUTL","INPM","INPL",
66 "STOR","LOAD","NOP ","STOP",};
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",""};
82 extern char *linkspeed
[];
83 u_int32_t tagbit
[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31};
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
},
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
},
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
},
101 /* e PHY */ {12, FWTI_REQ
},
105 #define OHCI_WRITE_SIGMASK 0xffff0000
106 #define OHCI_READ_SIGMASK 0xffff0000
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))
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
*);
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);
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
*);
143 static void fwohci_complete(void *, int);
147 * memory allocated for DMA programs
149 #define DMA_PROG_ALLOC (8 * PAGE_SIZE)
151 #define NDB FWMAXQUEUE
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
165 #define OHCI_EUID_HI 0x24
166 #define OHCI_EUID_LO 0x28
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
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
186 #define OHCI_IT_STAT 0x90
187 #define OHCI_IT_STATCLR 0x94
188 #define OHCI_IT_MASK 0x98
189 #define OHCI_IT_MASKCLR 0x9c
191 #define OHCI_IR_STAT 0xa0
192 #define OHCI_IR_STATCLR 0xa4
193 #define OHCI_IR_MASK 0xa8
194 #define OHCI_IR_MASKCLR 0xac
196 #define OHCI_LNKCTL 0xe0
197 #define OHCI_LNKCTLCLR 0xe4
199 #define OHCI_PHYACCESS 0xec
200 #define OHCI_CYCLETIMER 0xf0
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)
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)
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)
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)
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)
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)
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)
242 d_ioctl_t fwohci_ioctl
;
245 * Communication with PHY device
248 fwphy_wrdata( struct fwohci_softc
*sc
, u_int32_t addr
, u_int32_t data
)
255 fun
= (PHYDEV_WRCMD
| (addr
<< PHYDEV_REGADDR
) | (data
<< PHYDEV_WRDATA
));
256 OWRITE(sc
, OHCI_PHYACCESS
, fun
);
259 return(fwphy_rddata( sc
, addr
));
263 fwohci_set_bus_manager(struct firewire_comm
*fc
, u_int node
)
265 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
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
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
++)
279 bm
= OREAD(sc
, OHCI_CSR_DATA
);
280 if((bm
& 0x3f) == 0x3f)
283 device_printf(sc
->fc
.dev
,
284 "fw_set_bus_manager: %d->%d (loop=%d)\n", bm
, node
, i
);
290 fwphy_rddata(struct fwohci_softc
*sc
, u_int addr
)
296 #define MAX_RETRY 100
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)
309 device_printf(sc
->fc
.dev
, "phy read failed(1).\n");
310 if (++retry
< MAX_RETRY
) {
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
) {
320 device_printf(sc
->fc
.dev
, "phy read failed(2).\n");
321 if (++retry
< MAX_RETRY
) {
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
);
330 return((fun
>> PHYDEV_RDDATA
)& 0xff);
332 /* Device specific ioctl. */
334 fwohci_ioctl (struct dev_ioctl_args
*ap
)
336 cdev_t dev
= ap
->a_head
.a_dev
;
337 struct firewire_softc
*sc
;
338 struct fwohci_softc
*fc
;
339 int unit
= DEV2UNIT(dev
);
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
;
344 sc
= devclass_get_softc(firewire_devclass
, unit
);
348 fc
= (struct fwohci_softc
*)sc
->fc
;
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
);
364 if(reg
->addr
<= OHCI_MAX_REG
){
365 reg
->data
= OREAD(fc
, reg
->addr
);
370 /* Read DMA descriptors for debug */
372 if(*dmach
<= OHCI_MAX_DMA_CH
){
373 dump_dma(fc
, *dmach
);
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
);
387 case FWOHCI_WRPHYREG
:
388 if (reg
->addr
<= OHCI_MAX_PHY_REG
)
389 reg
->data
= fwphy_wrdata(fc
, reg
->addr
, reg
->data
);
401 fwohci_probe_phy(struct fwohci_softc
*sc
, device_t dev
)
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 .
412 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_LPS
);
415 reg
= fwphy_rddata(sc
, FW_PHY_SPD_REG
);
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
;
427 "Phy 1394 only %s, %d ports.\n",
428 linkspeed
[sc
->fc
.speed
], sc
->fc
.nport
);
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
;
440 "Phy 1394a available %s, %d ports.\n",
441 linkspeed
[sc
->fc
.speed
], sc
->fc
.nport
);
443 /* check programPhyEnable */
444 reg2
= fwphy_rddata(sc
, 5);
446 if (e1394a
&& (OREAD(sc
, OHCI_HCCCTL
) & OHCI_HCC_PRPHY
)) {
447 #else /* XXX force to enable 1394a */
452 "Enable 1394a Enhancements\n");
455 /* set aPhyEnhanceEnable */
456 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_PHYEN
);
457 OWRITE(sc
, OHCI_HCCCTLCLR
, OHCI_HCC_PRPHY
);
462 reg2
= fwphy_wrdata(sc
, 5, reg2
);
465 reg
= fwphy_rddata(sc
, FW_PHY_SPD_REG
);
466 if((reg
>> 5) == 7 ){
467 reg
= fwphy_rddata(sc
, 4);
469 fwphy_wrdata(sc
, 4, reg
);
470 reg
= fwphy_rddata(sc
, 4);
477 fwohci_reset(struct fwohci_softc
*sc
, device_t dev
)
479 int i
, max_rec
, speed
;
481 struct fwohcidb_tr
*db_tr
;
483 /* Disable interrupt */
484 OWRITE(sc
, FWOHCI_INTMASKCLR
, ~0);
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
);
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
);
498 /* FLUSH FIFO and reset Transmitter/Reciever */
499 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_RESET
);
501 device_printf(dev
, "resetting OHCI...");
503 while(OREAD(sc
, OHCI_HCCCTL
) & OHCI_HCC_RESET
) {
504 if (i
++ > 100) break;
508 kprintf("done (loop=%d)\n", i
);
511 fwohci_probe_phy(sc
, dev
);
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
));
528 device_printf(dev
, "BUS_OPT 0x%x -> 0x%x\n", reg
, reg2
);
529 OWRITE(sc
, OHCI_BUS_OPT
, reg2
);
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
);
540 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_LINKEN
);
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
);
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
);
553 OWRITE(sc
, FWOHCI_RETRY
,
554 /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */
555 (0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ;
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
;
562 for( i
= 0, db_tr
= sc
->atrq
.top
; i
< sc
->atrq
.ndb
;
563 i
++, db_tr
= STAILQ_NEXT(db_tr
, link
)){
566 for( i
= 0, db_tr
= sc
->atrs
.top
; i
< sc
->atrs
.ndb
;
567 i
++, db_tr
= STAILQ_NEXT(db_tr
, link
)){
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);
583 fwohci_init(struct fwohci_softc
*sc
, device_t dev
)
590 TASK_INIT(&sc
->fwohci_task_complete
, 0, fwohci_complete
, sc
);
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");
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)
613 device_printf(dev
, "No. of Isochronous channel is %d.\n", i
);
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
;
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
);
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
;
632 sc
->arrq
.xferq
.buf
= NULL
;
633 sc
->arrs
.xferq
.buf
= NULL
;
634 sc
->atrq
.xferq
.buf
= NULL
;
635 sc
->atrs
.xferq
.buf
= NULL
;
637 sc
->arrq
.xferq
.dmach
= -1;
638 sc
->arrs
.xferq
.dmach
= -1;
639 sc
->atrq
.xferq
.dmach
= -1;
640 sc
->atrs
.xferq
.dmach
= -1;
644 sc
->atrq
.ndesc
= 8; /* equal to maximum of mbuf chains */
648 sc
->arrs
.ndb
= NDB
/ 2;
650 sc
->atrs
.ndb
= NDB
/ 2;
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
;
661 sc
->fc
.tcode
= tinfo
;
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.");
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);
680 sc
->fc
.config_rom
[0] |= fw_crc16(&sc
->fc
.config_rom
[1], 5*4);
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.");
693 fwdma_malloc(&sc
->fc
, sizeof(u_int32_t
), sizeof(u_int32_t
),
694 &sc
->dummy_dma
, BUS_DMA_WAITOK
);
696 if (sc
->dummy_dma
.v_addr
== NULL
) {
697 device_printf(dev
, "dummy_dma alloc failed.");
701 fwohci_db_init(sc
, &sc
->arrq
);
702 if ((sc
->arrq
.flags
& FWOHCI_DBCH_INIT
) == 0)
705 fwohci_db_init(sc
, &sc
->arrs
);
706 if ((sc
->arrs
.flags
& FWOHCI_DBCH_INIT
) == 0)
709 fwohci_db_init(sc
, &sc
->atrq
);
710 if ((sc
->atrq
.flags
& FWOHCI_DBCH_INIT
) == 0)
713 fwohci_db_init(sc
, &sc
->atrs
);
714 if ((sc
->atrs
.flags
& FWOHCI_DBCH_INIT
) == 0)
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]);
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
;
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
;
736 sc
->fc
.irx_post
= NULL
;
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
;
743 sc
->intmask
= sc
->irstat
= sc
->itstat
= 0;
746 fwohci_reset(sc
, dev
);
752 fwohci_timeout(void *arg
)
757 fwohci_cyctimer(struct firewire_comm
*fc
)
759 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
760 return(OREAD(sc
, OHCI_CYCLETIMER
));
764 fwohci_detach(struct fwohci_softc
*sc
, device_t dev
)
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
);
773 fwohci_db_free(&sc
->arrq
);
774 fwohci_db_free(&sc
->arrs
);
776 fwohci_db_free(&sc
->atrq
);
777 fwohci_db_free(&sc
->atrs
);
779 for( i
= 0 ; i
< sc
->fc
.nisodma
; i
++ ){
780 fwohci_db_free(&sc
->it
[i
]);
781 fwohci_db_free(&sc
->ir
[i
]);
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]; \
794 fwohci_execute_db(void *arg
, bus_dma_segment_t
*segs
, int nseg
, int error
)
796 struct fwohcidb_tr
*db_tr
;
798 bus_dma_segment_t
*s
;
801 db_tr
= (struct fwohcidb_tr
*)arg
;
802 db
= &db_tr
->db
[db_tr
->dbcnt
];
804 if (firewire_debug
|| error
!= EFBIG
)
805 kprintf("fwohci_execute_db: error=%d\n", error
);
808 for (i
= 0; i
< nseg
; 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);
819 fwohci_execute_db2(void *arg
, bus_dma_segment_t
*segs
, int nseg
,
820 bus_size_t size
, int error
)
822 fwohci_execute_db(arg
, segs
, nseg
, error
);
826 fwohci_start(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
829 int tcode
, hdr_len
, pl_off
;
832 struct fw_xfer
*xfer
;
834 struct fwohci_txpkthdr
*ohcifp
;
835 struct fwohcidb_tr
*db_tr
;
838 struct tcode_info
*info
;
839 static int maxdesc
=0;
841 if(&sc
->atrq
== dbch
){
843 }else if(&sc
->atrs
== dbch
){
849 if (dbch
->flags
& FWOHCI_DBCH_FULL
)
855 xfer
= STAILQ_FIRST(&dbch
->xferq
.q
);
859 if(dbch
->xferq
.queued
== 0 ){
860 device_printf(sc
->fc
.dev
, "TX queue empty\n");
862 STAILQ_REMOVE_HEAD(&dbch
->xferq
.q
, link
);
864 xfer
->state
= FWXF_START
;
866 fp
= &xfer
->send
.hdr
;
867 tcode
= fp
->mode
.common
.tcode
;
869 ohcifp
= (struct fwohci_txpkthdr
*) db_tr
->db
[1].db
.immed
;
870 info
= &tinfo
[tcode
];
871 hdr_len
= pl_off
= info
->hdr_len
;
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];
878 ohcifp
->mode
.common
.spd
= xfer
->send
.spd
& 0x7;
879 if (tcode
== FWTCODE_STREAM
){
881 ohcifp
->mode
.stream
.len
= fp
->mode
.stream
.len
;
882 } else if (tcode
== FWTCODE_PHY
) {
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
;
889 ohcifp
->mode
.asycomm
.dst
= fp
->mode
.hdr
.dst
;
890 ohcifp
->mode
.asycomm
.srcbus
= OHCI_ASYSRCBUS
;
891 ohcifp
->mode
.asycomm
.tlrt
|= FWRETRY_X
;
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));
903 #if BYTE_ORDER == BIG_ENDIAN
904 if (tcode
== FWTCODE_WREQQ
|| tcode
== FWTCODE_RRESQ
)
906 for (i
= 0; i
< hdr_len
/4; i
++)
907 FWOHCI_DMA_WRITE(ld
[i
], ld
[i
]);
912 db
= &db_tr
->db
[db_tr
->dbcnt
];
913 if (xfer
->send
.pay_len
> 0) {
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
,
922 /* XXX we can handle only 6 (=8-2) mbuf chains */
923 err
= bus_dmamap_load_mbuf(dbch
->dmat
, db_tr
->dma_map
,
925 fwohci_execute_db2
, db_tr
,
931 device_printf(sc
->fc
.dev
, "EFBIG.\n");
932 m0
= m_getcl(M_NOWAIT
, MT_DATA
, M_PKTHDR
);
934 m_copydata(xfer
->mbuf
, 0,
935 xfer
->mbuf
->m_pkthdr
.len
,
937 m0
->m_len
= m0
->m_pkthdr
.len
=
938 xfer
->mbuf
->m_pkthdr
.len
;
943 device_printf(sc
->fc
.dev
, "m_getcl failed.\n");
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
,
956 if (maxdesc
< db_tr
->dbcnt
) {
957 maxdesc
= db_tr
->dbcnt
;
959 device_printf(sc
->fc
.dev
, "maxdesc: %d\n", maxdesc
);
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
);
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
);
974 dbch
->pdb_tr
= db_tr
;
975 db_tr
= STAILQ_NEXT(db_tr
, link
);
976 if(db_tr
!= dbch
->bottom
){
979 device_printf(sc
->fc
.dev
, "fwohci_start: lack of db_trq\n");
980 dbch
->flags
|= FWOHCI_DBCH_FULL
;
984 fwdma_sync_multiseg_all(dbch
->am
, BUS_DMASYNC_PREREAD
);
985 fwdma_sync_multiseg_all(dbch
->am
, BUS_DMASYNC_PREWRITE
);
987 if(dbch
->xferq
.flag
& FWXFERQ_RUNNING
) {
988 OWRITE(sc
, OHCI_DMACTL(off
), OHCI_CNTL_DMA_WAKE
);
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
;
1004 fwohci_start_atq(struct firewire_comm
*fc
)
1006 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1007 fwohci_start( sc
, &(sc
->atrq
));
1012 fwohci_start_ats(struct firewire_comm
*fc
)
1014 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1015 fwohci_start( sc
, &(sc
->atrs
));
1020 fwohci_txd(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
1023 struct fwohcidb_tr
*tr
;
1024 struct fwohcidb
*db
;
1025 struct fw_xfer
*xfer
;
1029 struct firewire_comm
*fc
= (struct firewire_comm
*)sc
;
1031 if(&sc
->atrq
== dbch
){
1034 }else if(&sc
->atrs
== dbch
){
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){
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?? */
1053 bus_dmamap_sync(dbch
->dmat
, tr
->dma_map
,
1054 BUS_DMASYNC_POSTWRITE
);
1055 bus_dmamap_unload(dbch
->dmat
, tr
->dma_map
);
1060 if(status
& OHCI_CNTL_DMA_DEAD
) {
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
);
1068 stat
= status
& FWOHCIEV_MASK
;
1070 case FWOHCIEV_ACKPEND
:
1071 case FWOHCIEV_ACKCOMPL
:
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
]);
1080 case FWOHCIEV_FLUSHED
:
1081 case FWOHCIEV_ACKTARD
:
1082 device_printf(sc
->fc
.dev
, "txd err=%2x %s\n", stat
, fwohcicode
[stat
]);
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
:
1096 device_printf(sc
->fc
.dev
, "txd err=%2x %s\n",
1097 stat
, fwohcicode
[stat
]);
1101 if (tr
->xfer
!= NULL
) {
1103 if (xfer
->state
== FWXF_RCVD
) {
1106 kprintf("already rcvd\n");
1110 xfer
->state
= FWXF_SENT
;
1111 if (err
== EBUSY
&& fc
->status
!= FWBUSRESET
) {
1112 xfer
->state
= FWXF_BUSY
;
1114 if (xfer
->retry_req
!= NULL
)
1115 xfer
->retry_req(xfer
);
1117 xfer
->recv
.pay_len
= 0;
1120 } else if (stat
!= FWOHCIEV_ACKPEND
) {
1121 if (stat
!= FWOHCIEV_ACKCOMPL
)
1122 xfer
->state
= FWXF_SENTERR
;
1124 xfer
->recv
.pay_len
= 0;
1129 * The watchdog timer takes care of split
1130 * transcation timeout for ACKPEND case.
1133 kprintf("this shouldn't happen\n");
1135 dbch
->xferq
.queued
--;
1139 tr
= STAILQ_NEXT(tr
, link
);
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");
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
);
1158 fwohci_db_free(struct fwohci_dbch
*dbch
)
1160 struct fwohcidb_tr
*db_tr
;
1163 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) == 0)
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
);
1173 } else if (db_tr
->dma_map
!= NULL
)
1174 bus_dmamap_destroy(dbch
->dmat
, db_tr
->dma_map
);
1177 db_tr
= STAILQ_FIRST(&dbch
->db_trq
);
1178 fwdma_free_multiseg(dbch
->am
);
1180 STAILQ_INIT(&dbch
->db_trq
);
1181 dbch
->flags
&= ~FWOHCI_DBCH_INIT
;
1185 fwohci_db_init(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
1188 struct fwohcidb_tr
*db_tr
;
1190 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) != 0)
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
,
1202 /*maxsize*/ dbch
->xferq
.psize
,
1203 /*nsegments*/ dbch
->ndesc
> 3 ? dbch
->ndesc
- 2 : 1,
1204 /*maxsegsz*/ MAX_REQCOUNT
,
1206 #if defined(__FreeBSD__) && __FreeBSD_version >= 501102
1207 /*lockfunc*/busdma_lock_mutex
,
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
);
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");
1228 /* Attach DB to DMA ch. */
1229 for(idb
= 0 ; idb
< dbch
->ndb
; idb
++){
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
);
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
;
1253 STAILQ_LAST(&dbch
->db_trq
, fwohcidb_tr
,link
)->link
.stqe_next
1254 = STAILQ_FIRST(&dbch
->db_trq
);
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
;
1264 fwohci_itx_disable(struct firewire_comm
*fc
, int dmach
)
1266 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
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
;
1281 fwohci_irx_disable(struct firewire_comm
*fc
, int dmach
)
1283 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
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
;
1296 #if BYTE_ORDER == BIG_ENDIAN
1298 fwohci_irx_post (struct firewire_comm
*fc
, u_int32_t
*qld
)
1300 qld
[0] = FWOHCI_DMA_READ(qld
[0]);
1306 fwohci_tx_enable(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
1309 int idb
, z
, i
, dmach
= 0, ldesc
;
1311 struct fwohcidb_tr
*db_tr
;
1312 struct fwohcidb
*db
;
1314 if(!(dbch
->xferq
.flag
& FWXFERQ_EXTBUF
)){
1319 for(dmach
= 0 ; dmach
< sc
->fc
.nisodma
; dmach
++){
1320 if( &sc
->it
[dmach
] == dbch
){
1321 off
= OHCI_ITOFF(dmach
);
1329 if(dbch
->xferq
.flag
& FWXFERQ_RUNNING
)
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
);
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
){
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){
1349 db
[ldesc
].db
.desc
.cmd
,
1350 OHCI_INTERRUPT_ALWAYS
);
1351 /* OHCI 1.1 and above */
1354 OHCI_INTERRUPT_ALWAYS
);
1357 db_tr
= STAILQ_NEXT(db_tr
, link
);
1360 dbch
->bottom
->db
[dbch
->bottom
->dbcnt
- 1].db
.desc
.depend
, 0xf);
1365 fwohci_rx_enable(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
1368 int idb
, z
, i
, dmach
= 0, ldesc
;
1370 struct fwohcidb_tr
*db_tr
;
1371 struct fwohcidb
*db
;
1374 if(&sc
->arrq
== dbch
){
1376 }else if(&sc
->arrs
== dbch
){
1379 for(dmach
= 0 ; dmach
< sc
->fc
.nisodma
; dmach
++){
1380 if( &sc
->ir
[dmach
] == dbch
){
1381 off
= OHCI_IROFF(dmach
);
1390 if(dbch
->xferq
.flag
& FWXFERQ_STREAM
){
1391 if(dbch
->xferq
.flag
& FWXFERQ_RUNNING
)
1394 if(dbch
->xferq
.flag
& FWXFERQ_RUNNING
){
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
);
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
)
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){
1416 db
[ldesc
].db
.desc
.cmd
,
1417 OHCI_INTERRUPT_ALWAYS
);
1419 db
[ldesc
].db
.desc
.depend
,
1423 db_tr
= STAILQ_NEXT(db_tr
, link
);
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
){
1433 OWRITE(sc
, OHCI_DMACMD(off
), dbch
->top
->bus_addr
| z
);
1435 OWRITE(sc
, OHCI_DMACTL(off
), OHCI_CNTL_DMA_RUN
);
1440 fwohci_next_cycle(struct firewire_comm
*fc
, int cycle_now
)
1442 int sec
, cycle
, cycle_match
;
1444 cycle
= cycle_now
& 0x1fff;
1445 sec
= cycle_now
>> 13;
1446 #define CYCLE_MOD 0x10
1448 #define CYCLE_DELAY 8 /* min delay to start DMA */
1450 #define CYCLE_DELAY 7000 /* min delay to start DMA */
1452 cycle
= cycle
+ CYCLE_DELAY
;
1453 if (cycle
>= 8000) {
1457 cycle
= roundup2(cycle
, CYCLE_MOD
);
1458 if (cycle
>= 8000) {
1465 cycle_match
= ((sec
<< 13) | cycle
) & 0x7ffff;
1467 return(cycle_match
);
1471 fwohci_itxbuf_enable(struct firewire_comm
*fc
, int dmach
)
1473 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1475 struct fwohci_dbch
*dbch
;
1476 int cycle_match
, cycle_now
, ldesc
;
1478 struct fw_bulkxfer
*first
, *chunk
, *prev
;
1479 struct fw_xferq
*it
;
1481 dbch
= &sc
->it
[dmach
];
1484 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) == 0) {
1485 dbch
->ndb
= it
->bnpacket
* it
->bnchunk
;
1487 fwohci_db_init(sc
, dbch
);
1488 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) == 0)
1490 err
= fwohci_tx_enable(sc
, dbch
);
1495 ldesc
= dbch
->ndesc
- 1;
1497 prev
= STAILQ_LAST(&it
->stdma
, fw_bulkxfer
, link
);
1498 while ((chunk
= STAILQ_FIRST(&it
->stvalid
)) != NULL
) {
1499 struct fwohcidb
*db
;
1501 fwdma_sync_multiseg(it
->buf
, chunk
->poffset
, it
->bnpacket
,
1502 BUS_DMASYNC_PREWRITE
);
1503 fwohci_txbufdb(sc
, dmach
, chunk
);
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
);
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
;
1515 FWOHCI_DMA_SET(db
[0].db
.desc
.depend
, dbch
->ndesc
);
1516 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.depend
, dbch
->ndesc
);
1519 STAILQ_REMOVE_HEAD(&it
->stvalid
, link
);
1520 STAILQ_INSERT_TAIL(&it
->stdma
, chunk
, link
);
1523 fwdma_sync_multiseg_all(dbch
->am
, BUS_DMASYNC_PREWRITE
);
1524 fwdma_sync_multiseg_all(dbch
->am
, BUS_DMASYNC_PREREAD
);
1526 stat
= OREAD(sc
, OHCI_ITCTL(dmach
));
1527 if (firewire_debug
&& (stat
& OHCI_CNTL_CYCMATCH_S
))
1528 kprintf("stat 0x%x\n", stat
);
1530 if (stat
& (OHCI_CNTL_DMA_ACTIVE
| OHCI_CNTL_CYCMATCH_S
))
1534 OWRITE(sc
, OHCI_ITCTLCLR(dmach
), OHCI_CNTL_DMA_RUN
);
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
);
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
);
1547 dump_dma(sc
, ITX_CH
+ dmach
);
1550 if ((stat
& OHCI_CNTL_DMA_RUN
) == 0) {
1552 /* Don't start until all chunks are buffered */
1553 if (STAILQ_FIRST(&it
->stfree
) != NULL
)
1557 /* Clear cycle match counter bits */
1558 OWRITE(sc
, OHCI_ITCTLCLR(dmach
), 0xffff0000);
1560 /* 2bit second + 13bit cycle */
1561 cycle_now
= (fc
->cyctimer(fc
) >> 12) & 0x7fff;
1562 cycle_match
= fwohci_next_cycle(fc
, cycle_now
);
1564 OWRITE(sc
, OHCI_ITCTL(dmach
),
1565 OHCI_CNTL_CYCMATCH_S
| (cycle_match
<< 16)
1566 | OHCI_CNTL_DMA_RUN
);
1568 OWRITE(sc
, OHCI_ITCTL(dmach
), OHCI_CNTL_DMA_RUN
);
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
);
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
);
1586 fwohci_irx_enable(struct firewire_comm
*fc
, int dmach
)
1588 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1590 unsigned short tag
, ich
;
1592 struct fwohci_dbch
*dbch
;
1593 struct fwohcidb_tr
*db_tr
;
1594 struct fw_bulkxfer
*first
, *prev
, *chunk
;
1595 struct fw_xferq
*ir
;
1597 dbch
= &sc
->ir
[dmach
];
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
);
1606 dbch
->ndb
= ir
->bnpacket
* ir
->bnchunk
;
1608 fwohci_db_init(sc
, dbch
);
1609 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) == 0)
1611 err
= fwohci_rx_enable(sc
, dbch
);
1616 first
= STAILQ_FIRST(&ir
->stfree
);
1617 if (first
== NULL
) {
1618 device_printf(fc
->dev
, "IR DMA no free chunk\n");
1622 ldesc
= dbch
->ndesc
- 1;
1624 prev
= STAILQ_LAST(&ir
->stdma
, fw_bulkxfer
, link
);
1625 while ((chunk
= STAILQ_FIRST(&ir
->stfree
)) != NULL
) {
1626 struct fwohcidb
*db
;
1628 #if 1 /* XXX for if_fwe */
1629 if (chunk
->mbuf
!= NULL
) {
1630 db_tr
= (struct fwohcidb_tr
*)(chunk
->start
);
1632 err
= bus_dmamap_load_mbuf(dbch
->dmat
, db_tr
->dma_map
,
1633 chunk
->mbuf
, fwohci_execute_db2
, db_tr
,
1635 FWOHCI_DMA_SET(db_tr
->db
[1].db
.desc
.cmd
,
1636 OHCI_UPDATE
| OHCI_INPUT_LAST
|
1637 OHCI_INTERRUPT_ALWAYS
| OHCI_BRANCH_ALWAYS
);
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);
1644 db
= ((struct fwohcidb_tr
*)(prev
->end
))->db
;
1645 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.depend
, dbch
->ndesc
);
1647 STAILQ_REMOVE_HEAD(&ir
->stfree
, link
);
1648 STAILQ_INSERT_TAIL(&ir
->stdma
, chunk
, link
);
1651 fwdma_sync_multiseg_all(dbch
->am
, BUS_DMASYNC_PREWRITE
);
1652 fwdma_sync_multiseg_all(dbch
->am
, BUS_DMASYNC_PREREAD
);
1654 stat
= OREAD(sc
, OHCI_IRCTL(dmach
));
1655 if (stat
& OHCI_CNTL_DMA_ACTIVE
)
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
);
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
1672 OWRITE(sc
, OHCI_IRCTL(dmach
), OHCI_CNTL_DMA_RUN
);
1673 OWRITE(sc
, FWOHCI_INTMASK
, OHCI_INT_DMA_IR
);
1675 dump_db(sc
, IRX_CH
+ dmach
);
1681 fwohci_stop(struct fwohci_softc
*sc
, device_t dev
)
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
);
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
);
1696 /* FLUSH FIFO and reset Transmitter/Reciever */
1697 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_RESET
);
1699 /* Stop interrupt */
1700 OWRITE(sc
, FWOHCI_INTMASKCLR
,
1701 OHCI_INT_EN
| OHCI_INT_ERR
| OHCI_INT_PHY_SID
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
);
1708 if (sc
->fc
.arq
!= NULL
&& sc
->fc
.arq
->maxq
> 0)
1709 fw_drain_txq(&sc
->fc
);
1711 /* XXX Link down? Bus reset? */
1716 fwohci_resume(struct fwohci_softc
*sc
, device_t dev
)
1719 struct fw_xferq
*ir
;
1720 struct fw_bulkxfer
*chunk
;
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
);
1735 sc
->fc
.irx_enable(&sc
->fc
, i
);
1739 bus_generic_resume(dev
);
1740 sc
->fc
.ibr(&sc
->fc
);
1746 fwohci_intr_body(struct fwohci_softc
*sc
, u_int32_t stat
, int count
)
1748 u_int32_t irstat
, itstat
;
1750 struct firewire_comm
*fc
= (struct firewire_comm
*)sc
;
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
)
1780 if(stat
& OHCI_INT_PHY_BUS_R
){
1781 if (fc
->status
== FWBUSRESET
)
1783 /* Disable bus reset interrupt until sid recv. */
1784 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_PHY_BUS_R
);
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
);
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
;
1796 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_PHY_BUS_R
);
1799 OWRITE(sc
, OHCI_CROMHDR
, ntohl(sc
->fc
.config_rom
[0]));
1800 OWRITE(sc
, OHCI_BUS_OPT
, ntohl(sc
->fc
.config_rom
[2]));
1803 if((stat
& OHCI_INT_DMA_IR
)){
1805 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_DMA_IR
);
1807 irstat
= atomic_readandclear_int(&sc
->irstat
);
1808 for(i
= 0; i
< fc
->nisodma
; i
++){
1809 struct fwohci_dbch
*dbch
;
1811 if((irstat
& (1 << i
)) != 0){
1813 if ((dbch
->xferq
.flag
& FWXFERQ_OPEN
) == 0) {
1814 device_printf(sc
->fc
.dev
,
1815 "dma(%d) not active\n", i
);
1818 fwohci_rbuf_update(sc
, i
);
1822 if((stat
& OHCI_INT_DMA_IT
)){
1824 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_DMA_IT
);
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
);
1833 if((stat
& OHCI_INT_DMA_PRRS
)){
1835 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_DMA_PRRS
);
1838 dump_dma(sc
, ARRS_CH
);
1839 dump_db(sc
, ARRS_CH
);
1841 fwohci_arcv(sc
, &sc
->arrs
, count
);
1843 if((stat
& OHCI_INT_DMA_PRRQ
)){
1845 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_DMA_PRRQ
);
1848 dump_dma(sc
, ARRQ_CH
);
1849 dump_db(sc
, ARRQ_CH
);
1851 fwohci_arcv(sc
, &sc
->arrq
, count
);
1853 if(stat
& OHCI_INT_PHY_SID
){
1854 u_int32_t
*buf
, node_id
;
1858 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_PHY_SID
);
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);
1871 ** Checking whether the node is root or not. If root, turn on
1874 node_id
= OREAD(sc
, FWOHCI_NODEID
);
1875 plen
= OREAD(sc
, OHCI_SID_CNT
);
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");
1883 if (node_id
& OHCI_NODE_ROOT
) {
1884 kprintf("CYCLEMASTER mode\n");
1885 OWRITE(sc
, OHCI_LNKCTL
,
1886 OHCI_CNTL_CYCMTR
| OHCI_CNTL_CYCTIMER
);
1888 kprintf("non CYCLEMASTER mode\n");
1889 OWRITE(sc
, OHCI_LNKCTLCLR
, OHCI_CNTL_CYCMTR
);
1890 OWRITE(sc
, OHCI_LNKCTL
, OHCI_CNTL_CYCTIMER
);
1892 fc
->nodeid
= node_id
& 0x3f;
1894 if (plen
& OHCI_SID_ERR
) {
1895 device_printf(fc
->dev
, "SID Error\n");
1898 plen
&= OHCI_SID_CNT_MASK
;
1899 if (plen
< 4 || plen
> OHCI_SIDSIZE
) {
1900 device_printf(fc
->dev
, "invalid SID len = %d\n", plen
);
1903 plen
-= 4; /* chop control info */
1904 buf
= (u_int32_t
*)kmalloc(OHCI_SIDSIZE
, M_FW
, M_INTWAIT
);
1906 device_printf(fc
->dev
, "malloc failed\n");
1909 for (i
= 0; i
< plen
/ 4; i
++)
1910 buf
[i
] = FWOHCI_DMA_READ(sc
->sid_buf
[i
+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);
1919 fw_sidrcv(fc
, buf
, plen
);
1923 if((stat
& OHCI_INT_DMA_ATRQ
)){
1925 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_DMA_ATRQ
);
1927 fwohci_txd(sc
, &(sc
->atrq
));
1929 if((stat
& OHCI_INT_DMA_ATRS
)){
1931 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_DMA_ATRS
);
1933 fwohci_txd(sc
, &(sc
->atrs
));
1935 if((stat
& OHCI_INT_PW_ERR
)){
1937 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_PW_ERR
);
1939 /* permanently mask unsupported interrupt source */
1940 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_PW_ERR
);
1941 device_printf(fc
->dev
, "posted write error\n");
1943 if((stat
& OHCI_INT_ERR
)){
1945 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_ERR
);
1947 /* permanently mask unsupported interrupt source */
1948 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_ERR
);
1949 device_printf(fc
->dev
, "unrecoverable error\n");
1951 if((stat
& OHCI_INT_PHY_INT
)) {
1953 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_PHY_INT
);
1955 /* permanently mask unsupported interrupt source */
1956 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_PHY_INT
);
1957 /*device_printf(fc->dev, "phy int\n");*/
1963 #if FWOHCI_TASKQUEUE
1965 fwohci_complete(void *arg
, int pending
)
1967 struct fwohci_softc
*sc
= (struct fwohci_softc
*)arg
;
1971 stat
= atomic_readandclear_int(&sc
->intstat
);
1973 fwohci_intr_body(sc
, stat
, -1);
1981 fwochi_check_stat(struct fwohci_softc
*sc
)
1983 u_int32_t stat
, irstat
, itstat
;
1985 stat
= OREAD(sc
, FWOHCI_INTSTAT
);
1986 if (stat
== 0xffffffff) {
1987 device_printf(sc
->fc
.dev
,
1988 "device physically ejected?\n");
1993 OWRITE(sc
, FWOHCI_INTSTATCLR
, stat
);
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
);
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
);
2009 fwohci_intr(void *arg
)
2011 struct fwohci_softc
*sc
= (struct fwohci_softc
*)arg
;
2013 #if !FWOHCI_TASKQUEUE
2014 u_int32_t bus_reset
= 0;
2017 if (!(sc
->intmask
& OHCI_INT_EN
)) {
2022 #if !FWOHCI_TASKQUEUE
2025 stat
= fwochi_check_stat(sc
);
2026 if (stat
== 0 || stat
== 0xffffffff)
2028 #if FWOHCI_TASKQUEUE
2029 atomic_set_int(&sc
->intstat
, stat
);
2030 /* XXX mask bus reset intr. during bus reset phase */
2032 taskqueue_enqueue(taskqueue_swi_giant
, &sc
->fwohci_task_complete
);
2034 /* We cannot clear bus reset event during bus reset phase */
2035 if ((stat
& ~bus_reset
) == 0)
2037 bus_reset
= stat
& OHCI_INT_PHY_BUS_R
;
2038 fwohci_intr_body(sc
, stat
, -1);
2044 fwohci_poll(struct firewire_comm
*fc
, int quick
, int count
)
2047 struct fwohci_softc
*sc
;
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
;
2059 stat
= fwochi_check_stat(sc
);
2060 if (stat
== 0 || stat
== 0xffffffff)
2064 fwohci_intr_body(sc
, stat
, count
);
2069 fwohci_set_intr(struct firewire_comm
*fc
, int enable
)
2071 struct fwohci_softc
*sc
;
2073 sc
= (struct fwohci_softc
*)fc
;
2075 device_printf(sc
->fc
.dev
, "fwohci_set_intr: %d\n", enable
);
2077 sc
->intmask
|= OHCI_INT_EN
;
2078 OWRITE(sc
, FWOHCI_INTMASK
, OHCI_INT_EN
);
2080 sc
->intmask
&= ~OHCI_INT_EN
;
2081 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_EN
);
2086 fwohci_tbuf_update(struct fwohci_softc
*sc
, int dmach
)
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
;
2096 ldesc
= sc
->it
[dmach
].ndesc
- 1;
2097 crit_enter(); /* unnecessary? */
2098 fwdma_sync_multiseg_all(sc
->it
[dmach
].am
, BUS_DMASYNC_POSTREAD
);
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
;
2107 count
= FWOHCI_DMA_READ(db
[ldesc
].db
.desc
.res
)
2111 STAILQ_REMOVE_HEAD(&it
->stdma
, link
);
2112 switch (stat
& FWOHCIEV_MASK
){
2113 case FWOHCIEV_ACKCOMPL
:
2115 device_printf(fc
->dev
, "0x%08x\n", count
);
2119 device_printf(fc
->dev
,
2120 "Isochronous transmit err %02x(%s)\n",
2121 stat
, fwohcicode
[stat
& 0x1f]);
2123 STAILQ_INSERT_TAIL(&it
->stfree
, chunk
, link
);
2132 fwohci_rbuf_update(struct fwohci_softc
*sc
, int dmach
)
2134 struct firewire_comm
*fc
= &sc
->fc
;
2135 struct fwohcidb_tr
*db_tr
;
2136 struct fw_bulkxfer
*chunk
;
2137 struct fw_xferq
*ir
;
2142 ldesc
= sc
->ir
[dmach
].ndesc
- 1;
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
;
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
);
2164 kprintf("fwohci_rbuf_update: this shouldn't happen\n");
2167 STAILQ_REMOVE_HEAD(&ir
->stdma
, link
);
2168 STAILQ_INSERT_TAIL(&ir
->stvalid
, chunk
, link
);
2169 switch (stat
& FWOHCIEV_MASK
) {
2170 case FWOHCIEV_ACKCOMPL
:
2174 chunk
->resp
= EINVAL
;
2175 device_printf(fc
->dev
,
2176 "Isochronous receive err %02x(%s)\n",
2177 stat
, fwohcicode
[stat
& 0x1f]);
2183 if (ir
->flag
& FWXFERQ_HANDLER
)
2191 dump_dma(struct fwohci_softc
*sc
, u_int32_t ch
)
2193 u_int32_t off
, cntl
, stat
, cmd
, match
;
2203 }else if(ch
< IRX_CH
){
2204 off
= OHCI_ITCTL(ch
- ITX_CH
);
2206 off
= OHCI_IRCTL(ch
- IRX_CH
);
2208 cntl
= stat
= OREAD(sc
, off
);
2209 cmd
= OREAD(sc
, off
+ 0xc);
2210 match
= OREAD(sc
, off
+ 0x10);
2212 device_printf(sc
->fc
.dev
, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2219 device_printf(sc
->fc
.dev
, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
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],
2231 device_printf(sc
->fc
.dev
, "dma %d ch: Nostat\n", ch
);
2236 dump_db(struct fwohci_softc
*sc
, u_int32_t ch
)
2238 struct fwohci_dbch
*dbch
;
2239 struct fwohcidb_tr
*cp
= NULL
, *pp
, *np
= NULL
;
2240 struct fwohcidb
*curr
= NULL
;
2242 struct fwohcidb
*prev
, *next
= NULL
;
2258 }else if(ch
< IRX_CH
){
2259 off
= OHCI_ITCTL(ch
- ITX_CH
);
2260 dbch
= &sc
->it
[ch
- ITX_CH
];
2262 off
= OHCI_IRCTL(ch
- IRX_CH
);
2263 dbch
= &sc
->ir
[ch
- IRX_CH
];
2265 cmd
= OREAD(sc
, off
+ 0xc);
2267 if( dbch
->ndb
== 0 ){
2268 device_printf(sc
->fc
.dev
, "No DB is attached ch=%d\n", ch
);
2275 for(idb
= 0 ; idb
< dbch
->ndb
; idb
++ ){
2280 cp
= STAILQ_NEXT(pp
, link
);
2285 np
= STAILQ_NEXT(cp
, link
);
2286 for(jdb
= 0 ; jdb
< dbch
->ndesc
; jdb
++ ){
2287 if ((cmd
& 0xfffffff0) == cp
->bus_addr
) {
2299 pp
= STAILQ_NEXT(pp
, link
);
2307 kprintf("Prev DB %d\n", ch
);
2308 print_db(pp
, prev
, ch
, dbch
->ndesc
);
2310 kprintf("Current DB %d\n", ch
);
2311 print_db(cp
, curr
, ch
, dbch
->ndesc
);
2313 kprintf("Next DB %d\n", ch
);
2314 print_db(np
, next
, ch
, dbch
->ndesc
);
2317 kprintf("dbdump err ch = %d cmd = 0x%08x\n", ch
, cmd
);
2323 print_db(struct fwohcidb_tr
*db_tr
, struct fwohcidb
*db
,
2324 u_int32_t ch
, u_int32_t max
)
2331 kprintf("No Descriptor is found\n");
2335 kprintf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
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
),
2362 (u_int
)(res
& OHCI_COUNT_MASK
));
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],
2375 kprintf(" Nostat\n");
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]));
2384 if(key
== OHCI_KEY_DEVICE
){
2387 if((cmd
& OHCI_BRANCH_MASK
)
2388 == OHCI_BRANCH_ALWAYS
){
2391 if((cmd
& OHCI_CMD_MASK
)
2392 == OHCI_OUTPUT_LAST
){
2395 if((cmd
& OHCI_CMD_MASK
)
2396 == OHCI_INPUT_LAST
){
2399 if(key
== OHCI_KEY_ST2
){
2407 fwohci_ibr(struct firewire_comm
*fc
)
2409 struct fwohci_softc
*sc
;
2412 device_printf(fc
->dev
, "Initiate bus reset\n");
2413 sc
= (struct fwohci_softc
*)fc
;
2416 * Set root hold-off bit so that non cyclemaster capable node
2417 * shouldn't became the root node.
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
);
2431 fwohci_txbufdb(struct fwohci_softc
*sc
, int dmach
, struct fw_bulkxfer
*bulkxfer
)
2433 struct fwohcidb_tr
*db_tr
;
2435 struct fwohcidb_tr
*fdb_tr
;
2437 struct fwohci_dbch
*dbch
;
2438 struct fwohcidb
*db
;
2440 struct fwohci_txpkthdr
*ohcifp
;
2441 unsigned short chtag
;
2444 dbch
= &sc
->it
[dmach
];
2445 chtag
= sc
->it
[dmach
].xferq
.flag
& 0xff;
2447 db_tr
= (struct fwohcidb_tr
*)(bulkxfer
->start
);
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
);
2453 for (idb
= 0; idb
< dbch
->xferq
.bnpacket
; idb
++) {
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]);
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
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
;
2478 FWOHCI_DMA_SET(db
[0].db
.desc
.depend
, dbch
->ndesc
);
2479 FWOHCI_DMA_SET(db
[dbch
->ndesc
- 1].db
.desc
.depend
, dbch
->ndesc
);
2481 bulkxfer
->end
= (caddr_t
)db_tr
;
2482 db_tr
= STAILQ_NEXT(db_tr
, link
);
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
;
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);
2501 fwohci_add_tx_buf(struct fwohci_dbch
*dbch
, struct fwohcidb_tr
*db_tr
,
2504 struct fwohcidb
*db
= db_tr
->db
;
2505 struct fw_xferq
*it
;
2509 if(it
->buf
== NULL
) {
2513 db_tr
->buf
= fwdma_v_addr(it
->buf
, poffset
);
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
));
2523 FWOHCI_DMA_WRITE(db
[2].db
.desc
.cmd
,
2524 OHCI_OUTPUT_LAST
| OHCI_UPDATE
| OHCI_BRANCH_ALWAYS
);
2526 FWOHCI_DMA_WRITE(db
[0].db
.desc
.res
, 0);
2527 FWOHCI_DMA_WRITE(db
[2].db
.desc
.res
, 0);
2533 fwohci_add_rx_buf(struct fwohci_dbch
*dbch
, struct fwohcidb_tr
*db_tr
,
2534 int poffset
, struct fwdma_alloc
*dummy_dma
)
2536 struct fwohcidb
*db
= db_tr
->db
;
2537 struct fw_xferq
*ir
;
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
)
2549 dsiz
[0] = ir
->psize
;
2550 bus_dmamap_sync(dbch
->dmat
, db_tr
->dma_map
,
2551 BUS_DMASYNC_PREREAD
);
2554 if (dummy_dma
!= NULL
) {
2555 dsiz
[db_tr
->dbcnt
] = sizeof(u_int32_t
);
2556 dbuf
[db_tr
->dbcnt
++] = dummy_dma
->bus_addr
;
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
);
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
);
2571 FWOHCI_DMA_WRITE(db
[i
].db
.desc
.res
, dsiz
[i
]);
2573 ldesc
= db_tr
->dbcnt
- 1;
2574 if (ir
->flag
& FWXFERQ_STREAM
) {
2575 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.cmd
, OHCI_INPUT_LAST
);
2577 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.cmd
, OHCI_BRANCH_ALWAYS
);
2583 fwohci_arcv_swap(struct fw_pkt
*fp
, int len
)
2588 #if BYTE_ORDER == BIG_ENDIAN
2592 ld0
= FWOHCI_DMA_READ(fp
->mode
.ld
[0]);
2594 kprintf("ld0: x%08x\n", ld0
);
2596 fp0
= (struct fw_pkt
*)&ld0
;
2597 /* determine length to swap */
2598 switch (fp0
->mode
.common
.tcode
) {
2603 case FWOHCITCODE_PHY
:
2604 #if BYTE_ORDER == BIG_ENDIAN
2613 #if BYTE_ORDER == BIG_ENDIAN
2618 kprintf("Unknown tcode %d\n", fp0
->mode
.common
.tcode
);
2621 hlen
= tinfo
[fp0
->mode
.common
.tcode
].hdr_len
;
2624 kprintf("split header\n");
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
]);
2635 fwohci_get_plen(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
, struct fw_pkt
*fp
)
2637 struct tcode_info
*info
;
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
));
2645 if (r
== sizeof(u_int32_t
))
2647 device_printf(sc
->fc
.dev
, "Unknown tcode %d\n",
2648 fp
->mode
.common
.tcode
);
2650 if (r
> dbch
->xferq
.psize
) {
2651 device_printf(sc
->fc
.dev
, "Invalid packet length %d\n", r
);
2659 fwohci_arcv_free_buf(struct fwohci_dbch
*dbch
, struct fwohcidb_tr
*db_tr
)
2661 struct fwohcidb
*db
= &db_tr
->db
[0];
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
;
2671 fwohci_arcv(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
, int count
)
2673 struct fwohcidb_tr
*db_tr
;
2674 struct iovec vec
[2];
2675 struct fw_pkt pktbuf
;
2679 u_int32_t stat
, status
;
2681 int len
, plen
, hlen
, pcnt
, offset
;
2685 if (&sc
->arrq
!= dbch
&& &sc
->arrs
!= dbch
)
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
;
2697 kprintf("status 0x%04x, resCount 0x%04x\n", status
, resCount
);
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
;
2707 bus_dmamap_sync(dbch
->dmat
, db_tr
->dma_map
,
2708 BUS_DMASYNC_POSTREAD
);
2710 if (count
>= 0 && count
-- == 0)
2712 if(dbch
->pdb_tr
!= NULL
){
2713 /* we have a fragment in previous buffer */
2716 offset
= dbch
->buf_offset
;
2719 buf
= dbch
->pdb_tr
->buf
+ offset
;
2720 rlen
= dbch
->xferq
.psize
- offset
;
2722 kprintf("rlen=%d, offset=%d\n",
2723 rlen
, dbch
->buf_offset
);
2724 if (dbch
->buf_offset
< 0) {
2725 /* split in header, pull up */
2728 p
= (char *)&pktbuf
;
2729 bcopy(buf
, p
, rlen
);
2731 /* this must be too long but harmless */
2732 rlen
= sizeof(pktbuf
) - rlen
;
2734 kprintf("why rlen < 0\n");
2735 bcopy(db_tr
->buf
, p
, rlen
);
2738 hlen
= fwohci_arcv_swap(&pktbuf
, sizeof(pktbuf
));
2740 kprintf("hlen < 0 shouldn't happen");
2742 offset
= sizeof(pktbuf
);
2743 vec
[0].iov_base
= (char *)&pktbuf
;
2744 vec
[0].iov_len
= offset
;
2746 /* split in payload */
2748 vec
[0].iov_base
= buf
;
2749 vec
[0].iov_len
= rlen
;
2751 fp
=(struct fw_pkt
*)vec
[0].iov_base
;
2754 /* no fragment in previous buffer */
2755 fp
=(struct fw_pkt
*)ld
;
2756 hlen
= fwohci_arcv_swap(fp
, len
);
2758 /* XXX need reset */
2761 dbch
->pdb_tr
= db_tr
;
2762 dbch
->buf_offset
= - dbch
->buf_offset
;
2765 kprintf("resCount = %d !?\n",
2767 /* XXX clear pdb_tr */
2773 plen
= fwohci_get_plen(sc
, dbch
, fp
) - offset
;
2775 /* minimum header size + trailer
2776 = sizeof(fw_pkt) so this shouldn't happens */
2777 kprintf("plen(%d) is negative! offset=%d\n",
2779 /* XXX clear pdb_tr */
2785 dbch
->pdb_tr
= db_tr
;
2787 kprintf("split payload\n");
2790 kprintf("resCount = %d !?\n",
2792 /* XXX clear pdb_tr */
2795 vec
[nvec
].iov_base
= ld
;
2796 vec
[nvec
].iov_len
= plen
;
2800 dbch
->buf_offset
= ld
- (u_int8_t
*)db_tr
->buf
;
2802 kprintf("nvec == 0\n");
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;
2808 stat
= ((struct fwohci_trailer
*)(ld
- sizeof(struct fwohci_trailer
)))->stat
;
2811 kprintf("plen: %d, stat %x\n",
2814 spd
= (stat
>> 5) & 0x3;
2817 case FWOHCIEV_ACKPEND
:
2819 kprintf("fwohci_arcv: ack pending tcode=0x%x..\n", fp
->mode
.common
.tcode
);
2822 case FWOHCIEV_ACKCOMPL
:
2824 struct fw_rcv_buf rb
;
2826 if ((vec
[nvec
-1].iov_len
-=
2827 sizeof(struct fwohci_trailer
)) == 0)
2836 case FWOHCIEV_BUSRST
:
2837 if (sc
->fc
.status
!= FWBUSRESET
)
2838 kprintf("got BUSRST packet!?\n");
2841 device_printf(sc
->fc
.dev
, "Async DMA Receive error err = %02x %s\n", stat
, fwohcicode
[stat
]);
2848 if (dbch
->pdb_tr
!= NULL
) {
2849 fwohci_arcv_free_buf(dbch
, dbch
->pdb_tr
);
2850 dbch
->pdb_tr
= NULL
;
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;
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
)
2868 /* XXX check buffer overrun */
2871 dbch
->buf_offset
= dbch
->xferq
.psize
- resCount
;
2874 /* XXX make sure DMA is not dead */
2878 kprintf("fwohci_arcv: no packets\n");