Deleted Added
sdiff udiff text old ( 109890 ) new ( 109892 )
full compact
1/*
2 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $FreeBSD: head/sys/dev/firewire/fwohci.c 109890 2003-01-26 15:39:04Z simokawa $
34 *
35 */
36
37#define ATRQ_CH 0
38#define ATRS_CH 1
39#define ARRQ_CH 2
40#define ARRS_CH 3
41#define ITX_CH 4

--- 781 unchanged lines hidden (view full) ---

823 ohcifp->mode.common.spd = 0;
824 ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
825 } else {
826 ohcifp->mode.asycomm.dst = ntohs(fp->mode.hdr.dst);
827 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
828 ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
829 }
830 db = &db_tr->db[0];
831 db->db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len;
832 db->db.desc.status = 0;
833/* Specify bound timer of asy. responce */
834 if(&sc->atrs == dbch){
835 db->db.desc.count
836 = (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13);
837 }
838
839 db_tr->dbcnt = 2;
840 db = &db_tr->db[db_tr->dbcnt];
841 if(len > hdr_off){
842 if (xfer->mbuf == NULL) {
843 db->db.desc.addr
844 = vtophys(xfer->send.buf + xfer->send.off) + hdr_off;
845 db->db.desc.cmd
846 = OHCI_OUTPUT_MORE | ((len - hdr_off) & 0xffff);
847 db->db.desc.status = 0;
848
849 db_tr->dbcnt++;
850 } else {
851 int mchain=0;
852 /* XXX we assume mbuf chain is shorter than ndesc */
853 for (m = xfer->mbuf; m != NULL; m = m->m_next) {
854 if (m->m_len == 0)
855 /* unrecoverable error could occur. */
856 continue;
857 mchain++;
858 if (db_tr->dbcnt >= dbch->ndesc)
859 continue;
860 db->db.desc.addr
861 = vtophys(mtod(m, caddr_t));
862 db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len;
863 db->db.desc.status = 0;
864 db++;
865 db_tr->dbcnt++;
866 }
867 if (mchain > dbch->ndesc - 2)
868 device_printf(sc->fc.dev,
869 "dbch->ndesc(%d) is too small for"
870 " mbuf chain(%d), trancated.\n",
871 dbch->ndesc, mchain);
872 }
873 }
874 if (maxdesc < db_tr->dbcnt) {
875 maxdesc = db_tr->dbcnt;
876 if (bootverbose)
877 device_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc);
878 }
879 /* last db */
880 LAST_DB(db_tr, db);
881 db->db.desc.cmd |= OHCI_OUTPUT_LAST
882 | OHCI_INTERRUPT_ALWAYS
883 | OHCI_BRANCH_ALWAYS;
884 db->db.desc.depend = vtophys(STAILQ_NEXT(db_tr, link)->db);
885
886 if(fsegment == -1 )
887 fsegment = db_tr->dbcnt;
888 if (dbch->pdb_tr != NULL) {
889 LAST_DB(dbch->pdb_tr, db);

--- 403 unchanged lines hidden (view full) ---

1293
1294static int
1295fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1296{
1297 int err = 0;
1298 int idb, z, i, dmach = 0;
1299 u_int32_t off = NULL;
1300 struct fwohcidb_tr *db_tr;
1301
1302 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1303 err = EINVAL;
1304 return err;
1305 }
1306 z = dbch->ndesc;
1307 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1308 if( &sc->it[dmach] == dbch){

--- 14 unchanged lines hidden (view full) ---

1323 db_tr = dbch->top;
1324 for( idb = 0 ; idb < dbch->ndb ; idb ++){
1325 fwohci_add_tx_buf(db_tr,
1326 dbch->xferq.psize, dbch->xferq.flag,
1327 dbch->xferq.buf + dbch->xferq.psize * idb);
1328 if(STAILQ_NEXT(db_tr, link) == NULL){
1329 break;
1330 }
1331 db_tr->db[0].db.desc.depend
1332 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1333 db_tr->db[db_tr->dbcnt - 1].db.desc.depend
1334 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1335 if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1336 if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1337 db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
1338 |= OHCI_INTERRUPT_ALWAYS;
1339 db_tr->db[0].db.desc.depend &= ~0xf;
1340 db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
1341 ~0xf;
1342 /* OHCI 1.1 and above */
1343 db_tr->db[0].db.desc.cmd
1344 |= OHCI_INTERRUPT_ALWAYS;
1345 }
1346 }
1347 db_tr = STAILQ_NEXT(db_tr, link);
1348 }
1349 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
1350 return err;
1351}
1352
1353static int
1354fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1355{
1356 int err = 0;
1357 int idb, z, i, dmach = 0;
1358 u_int32_t off = NULL;
1359 struct fwohcidb_tr *db_tr;
1360
1361 z = dbch->ndesc;
1362 if(&sc->arrq == dbch){
1363 off = OHCI_ARQOFF;
1364 }else if(&sc->arrs == dbch){
1365 off = OHCI_ARSOFF;
1366 }else{
1367 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){

--- 30 unchanged lines hidden (view full) ---

1398 fwohci_add_rx_buf(db_tr,
1399 dbch->xferq.psize, dbch->xferq.flag,
1400 dbch->xferq.buf + dbch->xferq.psize * idb,
1401 dbch->dummy + sizeof(u_int32_t) * idb);
1402 }
1403 if(STAILQ_NEXT(db_tr, link) == NULL){
1404 break;
1405 }
1406 db_tr->db[db_tr->dbcnt - 1].db.desc.depend
1407 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1408 if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1409 if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1410 db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
1411 |= OHCI_INTERRUPT_ALWAYS;
1412 db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
1413 ~0xf;
1414 }
1415 }
1416 db_tr = STAILQ_NEXT(db_tr, link);
1417 }
1418 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
1419 dbch->buf_offset = 0;
1420 if(dbch->xferq.flag & FWXFERQ_STREAM){
1421 return err;

--- 54 unchanged lines hidden (view full) ---

1476 fwohci_db_init(dbch);
1477 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1478 return ENOMEM;
1479 err = fwohci_tx_enable(sc, dbch);
1480 }
1481 if(err)
1482 return err;
1483
1484 s = splfw();
1485 prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1486 while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1487 volatile struct fwohcidb *db;
1488
1489 fwohci_txbufdb(sc, dmach, chunk);
1490 ldesc = dbch->ndesc - 1;
1491 db = ((struct fwohcidb_tr *)(chunk->end))->db;
1492 db[ldesc].db.desc.status = db[0].db.desc.status = 0;
1493 db[ldesc].db.desc.count = db[0].db.desc.count = 0;
1494 db[ldesc].db.desc.depend &= ~0xf;
1495 db[0].db.desc.depend &= ~0xf;
1496 if (prev != NULL) {
1497 db = ((struct fwohcidb_tr *)(prev->end))->db;
1498 db[ldesc].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
1499 db[ldesc].db.desc.depend = db[0].db.desc.depend =
1500 vtophys(((struct fwohcidb_tr *)
1501 (chunk->start))->db) | dbch->ndesc;
1502 }
1503 STAILQ_REMOVE_HEAD(&it->stvalid, link);
1504 STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
1505 prev = chunk;
1506 }
1507 splx(s);
1508 stat = OREAD(sc, OHCI_ITCTL(dmach));
1509 if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))

--- 100 unchanged lines hidden (view full) ---

1610 while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1611 volatile struct fwohcidb *db;
1612
1613 db = ((struct fwohcidb_tr *)(chunk->end))->db;
1614 db[ldesc].db.desc.status = db[ldesc].db.desc.count = 0;
1615 db[ldesc].db.desc.depend &= ~0xf;
1616 if (prev != NULL) {
1617 db = ((struct fwohcidb_tr *)(prev->end))->db;
1618 db[ldesc].db.desc.depend =
1619 vtophys(((struct fwohcidb_tr *)
1620 (chunk->start))->db) | dbch->ndesc;
1621 }
1622 STAILQ_REMOVE_HEAD(&ir->stfree, link);
1623 STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
1624 prev = chunk;
1625 }
1626 splx(s);
1627 stat = OREAD(sc, OHCI_IRCTL(dmach));
1628 if (stat & OHCI_CNTL_DMA_ACTIVE)

--- 575 unchanged lines hidden (view full) ---

2204 "INT",
2205 "BR ",
2206 "len",
2207 "Addr",
2208 "Depend",
2209 "Stat",
2210 "Cnt");
2211 for( i = 0 ; i <= max ; i ++){
2212 key = db[i].db.desc.cmd & OHCI_KEY_MASK;
2213#if __FreeBSD_version >= 500000
2214 printf("%08tx %s %s %s %s %5d %08x %08x %04x:%04x",
2215#else
2216 printf("%08x %s %s %s %s %5d %08x %08x %04x:%04x",
2217#endif
2218 vtophys(&db[i]),
2219 dbcode[(db[i].db.desc.cmd >> 28) & 0xf],
2220 dbkey[(db[i].db.desc.cmd >> 24) & 0x7],
2221 dbcond[(db[i].db.desc.cmd >> 20) & 0x3],
2222 dbcond[(db[i].db.desc.cmd >> 18) & 0x3],
2223 db[i].db.desc.cmd & 0xffff,
2224 db[i].db.desc.addr,
2225 db[i].db.desc.depend,
2226 db[i].db.desc.status,
2227 db[i].db.desc.count);
2228 stat = db[i].db.desc.status;
2229 if(stat & 0xff00){
2230 printf(" %s%s%s%s%s%s %s(%x)\n",
2231 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",

--- 13 unchanged lines hidden (view full) ---

2245 db[i+1].db.immed[0],
2246 db[i+1].db.immed[1],
2247 db[i+1].db.immed[2],
2248 db[i+1].db.immed[3]);
2249 }
2250 if(key == OHCI_KEY_DEVICE){
2251 return;
2252 }
2253 if((db[i].db.desc.cmd & OHCI_BRANCH_MASK)
2254 == OHCI_BRANCH_ALWAYS){
2255 return;
2256 }
2257 if((db[i].db.desc.cmd & OHCI_CMD_MASK)
2258 == OHCI_OUTPUT_LAST){
2259 return;
2260 }
2261 if((db[i].db.desc.cmd & OHCI_CMD_MASK)
2262 == OHCI_INPUT_LAST){
2263 return;
2264 }
2265 if(key == OHCI_KEY_ST2 ){
2266 i++;
2267 }
2268 }
2269 return;

--- 22 unchanged lines hidden (view full) ---

2292#endif
2293}
2294
2295void
2296fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2297{
2298 struct fwohcidb_tr *db_tr, *fdb_tr;
2299 struct fwohci_dbch *dbch;
2300 struct fw_pkt *fp;
2301 volatile struct fwohci_txpkthdr *ohcifp;
2302 unsigned short chtag;
2303 int idb;
2304
2305 dbch = &sc->it[dmach];
2306 chtag = sc->it[dmach].xferq.flag & 0xff;
2307
2308 db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2309 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2310/*
2311device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), vtophys(fdb_tr->db));
2312*/
2313 for( idb = 0 ; idb < bulkxfer->npacket ; idb ++){
2314 db_tr->db[0].db.desc.cmd
2315 = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
2316 fp = (struct fw_pkt *)db_tr->buf;
2317 ohcifp = (volatile struct fwohci_txpkthdr *)
2318 db_tr->db[1].db.immed;
2319 ohcifp->mode.ld[0] = ntohl(fp->mode.ld[0]);
2320 ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
2321 ohcifp->mode.stream.chtag = chtag;
2322 ohcifp->mode.stream.tcode = 0xa;
2323 ohcifp->mode.stream.spd = 0;
2324
2325 db_tr->db[2].db.desc.cmd
2326 = OHCI_OUTPUT_LAST
2327 | OHCI_UPDATE
2328 | OHCI_BRANCH_ALWAYS
2329 | ((ntohs(fp->mode.stream.len) ) & 0xffff);
2330 db_tr->db[2].db.desc.status = 0;
2331 db_tr->db[2].db.desc.count = 0;
2332 db_tr->db[0].db.desc.depend
2333 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2334 db_tr->db[dbch->ndesc - 1].db.desc.depend
2335 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2336 bulkxfer->end = (caddr_t)db_tr;
2337 db_tr = STAILQ_NEXT(db_tr, link);
2338 }
2339 db_tr = (struct fwohcidb_tr *)bulkxfer->end;
2340 db_tr->db[0].db.desc.depend &= ~0xf;
2341 db_tr->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
2342 db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
2343 /* OHCI 1.1 and above */
2344 db_tr->db[0].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
2345
2346 db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2347 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2348/*
2349device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, vtophys(db_tr->db), vtophys(fdb_tr->db));
2350*/
2351 return;
2352}
2353
2354static int
2355fwohci_add_tx_buf(struct fwohcidb_tr *db_tr, unsigned short size,
2356 int mode, void *buf)
2357{
2358 volatile struct fwohcidb *db = db_tr->db;
2359 int err = 0;
2360 if(buf == 0){
2361 err = EINVAL;
2362 return err;
2363 }
2364 db_tr->buf = buf;
2365 db_tr->dbcnt = 3;
2366 db_tr->dummy = NULL;
2367
2368 db[0].db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
2369
2370 db[2].db.desc.depend = 0;
2371 db[2].db.desc.addr = vtophys(buf) + sizeof(u_int32_t);
2372 db[2].db.desc.cmd = OHCI_OUTPUT_MORE;
2373
2374 db[0].db.desc.status = 0;
2375 db[0].db.desc.count = 0;
2376
2377 db[2].db.desc.status = 0;
2378 db[2].db.desc.count = 0;
2379 if( mode & FWXFERQ_STREAM ){
2380 db[2].db.desc.cmd |= OHCI_OUTPUT_LAST;
2381 if(mode & FWXFERQ_PACKET ){
2382 db[2].db.desc.cmd
2383 |= OHCI_INTERRUPT_ALWAYS;
2384 }
2385 }
2386 db[2].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
2387 return 1;
2388}
2389
2390int
2391fwohci_add_rx_buf(struct fwohcidb_tr *db_tr, unsigned short size, int mode,
2392 void *buf, void *dummy)
2393{
2394 volatile struct fwohcidb *db = db_tr->db;

--- 21 unchanged lines hidden (view full) ---

2416 db_tr->dummy = dummy;
2417 dsiz[0] = sizeof(u_int32_t);
2418 dsiz[1] = size;
2419 dbuf[0] = dummy;
2420 dbuf[1] = buf;
2421 }
2422 for(i = 0 ; i < db_tr->dbcnt ; i++){
2423 db[i].db.desc.addr = vtophys(dbuf[i]) ;
2424 db[i].db.desc.cmd = OHCI_INPUT_MORE | dsiz[i];
2425 if( mode & FWXFERQ_STREAM ){
2426 db[i].db.desc.cmd |= OHCI_UPDATE;
2427 }
2428 db[i].db.desc.status = 0;
2429 db[i].db.desc.count = dsiz[i];
2430 }
2431 if( mode & FWXFERQ_STREAM ){
2432 db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_INPUT_LAST;
2433 if(mode & FWXFERQ_PACKET ){
2434 db[db_tr->dbcnt - 1].db.desc.cmd
2435 |= OHCI_INTERRUPT_ALWAYS;
2436 }
2437 }
2438 db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
2439 return 1;
2440}
2441
2442static void
2443fwohci_ircv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2444{
2445 struct fwohcidb_tr *db_tr = dbch->top, *odb_tr;
2446 struct firewire_comm *fc = (struct firewire_comm *)sc;

--- 319 unchanged lines hidden ---