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