Deleted Added
sdiff udiff text old ( 119289 ) new ( 120660 )
full compact
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:

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

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: head/sys/dev/firewire/fwohci.c 120660 2003-10-02 04:06:56Z simokawa $
35 *
36 */
37
38#define ATRQ_CH 0
39#define ATRS_CH 1
40#define ARRQ_CH 2
41#define ARRS_CH 3
42#define ITX_CH 4

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

133static int fwohci_itxbuf_enable __P((struct firewire_comm *, int));
134static int fwohci_itx_disable __P((struct firewire_comm *, int));
135static void fwohci_timeout __P((void *));
136static void fwohci_set_intr __P((struct firewire_comm *, int));
137
138static int fwohci_add_rx_buf __P((struct fwohci_dbch *, struct fwohcidb_tr *, int, struct fwdma_alloc *));
139static int fwohci_add_tx_buf __P((struct fwohci_dbch *, struct fwohcidb_tr *, int));
140static void dump_db __P((struct fwohci_softc *, u_int32_t));
141static void print_db __P((struct fwohcidb_tr *, struct fwohcidb *, u_int32_t , u_int32_t));
142static void dump_dma __P((struct fwohci_softc *, u_int32_t));
143static u_int32_t fwohci_cyctimer __P((struct firewire_comm *));
144static void fwohci_rbuf_update __P((struct fwohci_softc *, int));
145static void fwohci_tbuf_update __P((struct fwohci_softc *, int));
146void fwohci_txbufdb __P((struct fwohci_softc *, int , struct fw_bulkxfer *));
147#if FWOHCI_TASKQUEUE
148static void fwohci_complete(void *, int);
149#endif

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

794 int _cnt = _dbtr->dbcnt; \
795 db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \
796} while (0)
797
798static void
799fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error)
800{
801 struct fwohcidb_tr *db_tr;
802 struct fwohcidb *db;
803 bus_dma_segment_t *s;
804 int i;
805
806 db_tr = (struct fwohcidb_tr *)arg;
807 db = &db_tr->db[db_tr->dbcnt];
808 if (error) {
809 if (firewire_debug || error != EFBIG)
810 printf("fwohci_execute_db: error=%d\n", error);

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

826{
827 fwohci_execute_db(arg, segs, nseg, error);
828}
829
830static void
831fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
832{
833 int i, s;
834 int tcode, hdr_len, pl_off;
835 int fsegment = -1;
836 u_int32_t off;
837 struct fw_xfer *xfer;
838 struct fw_pkt *fp;
839 struct fwohci_txpkthdr *ohcifp;
840 struct fwohcidb_tr *db_tr;
841 struct fwohcidb *db;
842 u_int32_t *ld;
843 struct tcode_info *info;
844 static int maxdesc=0;
845
846 if(&sc->atrq == dbch){
847 off = OHCI_ATQOFF;
848 }else if(&sc->atrs == dbch){
849 off = OHCI_ATSOFF;
850 }else{

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

863 }
864 if(dbch->xferq.queued == 0 ){
865 device_printf(sc->fc.dev, "TX queue empty\n");
866 }
867 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
868 db_tr->xfer = xfer;
869 xfer->state = FWXF_START;
870
871 fp = &xfer->send.hdr;
872 tcode = fp->mode.common.tcode;
873
874 ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
875 info = &tinfo[tcode];
876 hdr_len = pl_off = info->hdr_len;
877
878 ld = &ohcifp->mode.ld[0];
879 ld[0] = ld[1] = ld[2] = ld[3] = 0;
880 for( i = 0 ; i < pl_off ; i+= 4)
881 ld[i/4] = fp->mode.ld[i/4];
882
883 ohcifp->mode.common.spd = xfer->send.spd & 0x7;
884 if (tcode == FWTCODE_STREAM ){
885 hdr_len = 8;
886 ohcifp->mode.stream.len = fp->mode.stream.len;
887 } else if (tcode == FWTCODE_PHY) {
888 hdr_len = 12;
889 ld[1] = fp->mode.ld[1];
890 ld[2] = fp->mode.ld[2];
891 ohcifp->mode.common.spd = 0;

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

910 hdr_len = 12;
911 for (i = 0; i < hdr_len/4; i ++)
912 FWOHCI_DMA_WRITE(ld[i], ld[i]);
913#endif
914
915again:
916 db_tr->dbcnt = 2;
917 db = &db_tr->db[db_tr->dbcnt];
918 if (xfer->send.pay_len > 0) {
919 int err;
920 /* handle payload */
921 if (xfer->mbuf == NULL) {
922 err = bus_dmamap_load(dbch->dmat, db_tr->dma_map,
923 &xfer->send.payload[0], xfer->send.pay_len,
924 fwohci_execute_db, db_tr,
925 /*flags*/0);
926 } else {
927 /* XXX we can handle only 6 (=8-2) mbuf chains */
928 err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
929 xfer->mbuf,
930 fwohci_execute_db2, db_tr,
931 /* flags */0);

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

1021 return;
1022}
1023
1024void
1025fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1026{
1027 int s, ch, err = 0;
1028 struct fwohcidb_tr *tr;
1029 struct fwohcidb *db;
1030 struct fw_xfer *xfer;
1031 u_int32_t off;
1032 u_int stat, status;
1033 int packets;
1034 struct firewire_comm *fc = (struct firewire_comm *)sc;
1035
1036 if(&sc->atrq == dbch){
1037 off = OHCI_ATQOFF;

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

1114 } else {
1115 xfer->state = FWXF_SENT;
1116 if (err == EBUSY && fc->status != FWBUSRESET) {
1117 xfer->state = FWXF_BUSY;
1118 xfer->resp = err;
1119 if (xfer->retry_req != NULL)
1120 xfer->retry_req(xfer);
1121 else {
1122 xfer->recv.pay_len = 0;
1123 fw_xfer_done(xfer);
1124 }
1125 } else if (stat != FWOHCIEV_ACKPEND) {
1126 if (stat != FWOHCIEV_ACKCOMPL)
1127 xfer->state = FWXF_SENTERR;
1128 xfer->resp = err;
1129 xfer->recv.pay_len = 0;
1130 fw_xfer_done(xfer);
1131 }
1132 }
1133 /*
1134 * The watchdog timer takes care of split
1135 * transcation timeout for ACKPEND case.
1136 */
1137 } else {

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

1310
1311static int
1312fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1313{
1314 int err = 0;
1315 int idb, z, i, dmach = 0, ldesc;
1316 u_int32_t off = NULL;
1317 struct fwohcidb_tr *db_tr;
1318 struct fwohcidb *db;
1319
1320 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1321 err = EINVAL;
1322 return err;
1323 }
1324 z = dbch->ndesc;
1325 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1326 if( &sc->it[dmach] == dbch){

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

1369
1370static int
1371fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1372{
1373 int err = 0;
1374 int idb, z, i, dmach = 0, ldesc;
1375 u_int32_t off = NULL;
1376 struct fwohcidb_tr *db_tr;
1377 struct fwohcidb *db;
1378
1379 z = dbch->ndesc;
1380 if(&sc->arrq == dbch){
1381 off = OHCI_ARQOFF;
1382 }else if(&sc->arrs == dbch){
1383 off = OHCI_ARSOFF;
1384 }else{
1385 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){

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

1500 }
1501 if(err)
1502 return err;
1503
1504 ldesc = dbch->ndesc - 1;
1505 s = splfw();
1506 prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link);
1507 while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
1508 struct fwohcidb *db;
1509
1510 fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
1511 BUS_DMASYNC_PREWRITE);
1512 fwohci_txbufdb(sc, dmach, chunk);
1513 if (prev != NULL) {
1514 db = ((struct fwohcidb_tr *)(prev->end))->db;
1515#if 0 /* XXX necessary? */
1516 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,

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

1627 device_printf(fc->dev, "IR DMA no free chunk\n");
1628 return 0;
1629 }
1630
1631 ldesc = dbch->ndesc - 1;
1632 s = splfw();
1633 prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link);
1634 while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
1635 struct fwohcidb *db;
1636
1637#if 1 /* XXX for if_fwe */
1638 if (chunk->mbuf != NULL) {
1639 db_tr = (struct fwohcidb_tr *)(chunk->start);
1640 db_tr->dbcnt = 1;
1641 err = bus_dmamap_load_mbuf(dbch->dmat, db_tr->dma_map,
1642 chunk->mbuf, fwohci_execute_db2, db_tr,
1643 /* flags */0);

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

2095 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
2096 }
2097}
2098
2099static void
2100fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2101{
2102 struct firewire_comm *fc = &sc->fc;
2103 struct fwohcidb *db;
2104 struct fw_bulkxfer *chunk;
2105 struct fw_xferq *it;
2106 u_int32_t stat, count;
2107 int s, w=0, ldesc;
2108
2109 it = fc->it[dmach];
2110 ldesc = sc->it[dmach].ndesc - 1;
2111 s = splfw(); /* unnecessary ? */

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

2141 if (w)
2142 wakeup(it);
2143}
2144
2145static void
2146fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2147{
2148 struct firewire_comm *fc = &sc->fc;
2149 struct fwohcidb_tr *db_tr;
2150 struct fw_bulkxfer *chunk;
2151 struct fw_xferq *ir;
2152 u_int32_t stat;
2153 int s, w=0, ldesc;
2154
2155 ir = fc->ir[dmach];
2156 ldesc = sc->ir[dmach].ndesc - 1;
2157#if 0

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

2246 }
2247}
2248
2249void
2250dump_db(struct fwohci_softc *sc, u_int32_t ch)
2251{
2252 struct fwohci_dbch *dbch;
2253 struct fwohcidb_tr *cp = NULL, *pp, *np = NULL;
2254 struct fwohcidb *curr = NULL, *prev, *next = NULL;
2255 int idb, jdb;
2256 u_int32_t cmd, off;
2257 if(ch == 0){
2258 off = OHCI_ATQOFF;
2259 dbch = &sc->atrq;
2260 }else if(ch == 1){
2261 off = OHCI_ATSOFF;
2262 dbch = &sc->atrs;

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

2320#endif
2321 }else{
2322 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2323 }
2324 return;
2325}
2326
2327void
2328print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db,
2329 u_int32_t ch, u_int32_t max)
2330{
2331 fwohcireg_t stat;
2332 int i, key;
2333 u_int32_t cmd, res;
2334
2335 if(db == NULL){
2336 printf("No Descriptor is found\n");

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

2437#endif
2438}
2439
2440void
2441fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2442{
2443 struct fwohcidb_tr *db_tr, *fdb_tr;
2444 struct fwohci_dbch *dbch;
2445 struct fwohcidb *db;
2446 struct fw_pkt *fp;
2447 struct fwohci_txpkthdr *ohcifp;
2448 unsigned short chtag;
2449 int idb;
2450
2451 dbch = &sc->it[dmach];
2452 chtag = sc->it[dmach].xferq.flag & 0xff;
2453
2454 db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2455 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2456/*
2457device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2458*/
2459 for (idb = 0; idb < dbch->xferq.bnpacket; idb ++) {
2460 db = db_tr->db;
2461 fp = (struct fw_pkt *)db_tr->buf;
2462 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2463 ohcifp->mode.ld[0] = fp->mode.ld[0];
2464 ohcifp->mode.common.spd = 0 & 0x7;
2465 ohcifp->mode.stream.len = fp->mode.stream.len;
2466 ohcifp->mode.stream.chtag = chtag;
2467 ohcifp->mode.stream.tcode = 0xa;
2468#if BYTE_ORDER == BIG_ENDIAN
2469 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2470 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);

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

2502*/
2503 return;
2504}
2505
2506static int
2507fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2508 int poffset)
2509{
2510 struct fwohcidb *db = db_tr->db;
2511 struct fw_xferq *it;
2512 int err = 0;
2513
2514 it = &dbch->xferq;
2515 if(it->buf == 0){
2516 err = EINVAL;
2517 return err;
2518 }
2519 db_tr->buf = fwdma_v_addr(it->buf, poffset);
2520 db_tr->dbcnt = 3;
2521
2522 FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2523 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2524 FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2525 bzero((void *)&db[1].db.immed[0], sizeof(db[1].db.immed));
2526 FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2527 fwdma_bus_addr(it->buf, poffset) + sizeof(u_int32_t));
2528
2529 FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2530 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2531#if 1
2532 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2533 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2534#endif
2535 return 0;
2536}
2537
2538int
2539fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2540 int poffset, struct fwdma_alloc *dummy_dma)
2541{
2542 struct fwohcidb *db = db_tr->db;
2543 struct fw_xferq *ir;
2544 int i, ldesc;
2545 bus_addr_t dbuf[2];
2546 int dsiz[2];
2547
2548 ir = &dbch->xferq;
2549 if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2550 db_tr->buf = fwdma_malloc_size(dbch->dmat, &db_tr->dma_map,

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

2585}
2586
2587
2588static int
2589fwohci_arcv_swap(struct fw_pkt *fp, int len)
2590{
2591 struct fw_pkt *fp0;
2592 u_int32_t ld0;
2593 int slen, hlen;
2594#if BYTE_ORDER == BIG_ENDIAN
2595 int i;
2596#endif
2597
2598 ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2599#if 0
2600 printf("ld0: x%08x\n", ld0);
2601#endif
2602 fp0 = (struct fw_pkt *)&ld0;
2603 /* determine length to swap */
2604 switch (fp0->mode.common.tcode) {
2605 case FWTCODE_RREQQ:
2606 case FWTCODE_WRES:
2607 case FWTCODE_WREQQ:
2608 case FWTCODE_RRESQ:
2609 case FWOHCITCODE_PHY:
2610 slen = 12;
2611 break;
2612 case FWTCODE_RREQB:
2613 case FWTCODE_WREQB:
2614 case FWTCODE_LREQ:
2615 case FWTCODE_RRESB:
2616 case FWTCODE_LRES:
2617 slen = 16;
2618 break;
2619 default:
2620 printf("Unknown tcode %d\n", fp0->mode.common.tcode);
2621 return(0);
2622 }
2623 hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2624 if (hlen > len) {
2625 if (firewire_debug)
2626 printf("splitted header\n");
2627 return(-hlen);
2628 }
2629#if BYTE_ORDER == BIG_ENDIAN
2630 for(i = 0; i < slen/4; i ++)
2631 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2632#endif
2633 return(hlen);
2634}
2635
2636static int
2637fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp)
2638{
2639 struct tcode_info *info;
2640 int r;
2641
2642 info = &tinfo[fp->mode.common.tcode];
2643 r = info->hdr_len + sizeof(u_int32_t);
2644 if ((info->flag & FWTI_BLOCK_ASY) != 0)
2645 r += roundup2(fp->mode.wreqb.len, sizeof(u_int32_t));
2646
2647 if (r == sizeof(u_int32_t))
2648 /* XXX */
2649 device_printf(sc->fc.dev, "Unknown tcode %d\n",
2650 fp->mode.common.tcode);
2651
2652 if (r > dbch->xferq.psize) {
2653 device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
2654 /* panic ? */
2655 }
2656
2657 return r;
2658}
2659
2660static void
2661fwohci_arcv_free_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr)
2662{
2663 struct fwohcidb *db = &db_tr->db[0];
2664
2665 FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2666 FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2667 FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1);
2668 fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREWRITE);
2669 dbch->bottom = db_tr;
2670}
2671

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

2775 }
2776 offset = 0;
2777 nvec = 0;
2778 }
2779 plen = fwohci_get_plen(sc, dbch, fp) - offset;
2780 if (plen < 0) {
2781 /* minimum header size + trailer
2782 = sizeof(fw_pkt) so this shouldn't happens */
2783 printf("plen(%d) is negative! offset=%d\n",
2784 plen, offset);
2785 goto out;
2786 }
2787 if (plen > 0) {
2788 len -= plen;
2789 if (len < 0) {
2790 dbch->pdb_tr = db_tr;
2791 if (firewire_debug)
2792 printf("splitted payload\n");

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

2806
2807/* DMA result-code will be written at the tail of packet */
2808#if BYTE_ORDER == BIG_ENDIAN
2809 stat = FWOHCI_DMA_READ(((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat) >> 16;
2810#else
2811 stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat;
2812#endif
2813#if 0
2814 printf("plen: %d, stat %x\n",
2815 plen ,stat);
2816#endif
2817 spd = (stat >> 5) & 0x3;
2818 stat &= 0x1f;
2819 switch(stat){
2820 case FWOHCIEV_ACKPEND:
2821#if 0
2822 printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode);
2823#endif
2824 /* fall through */
2825 case FWOHCIEV_ACKCOMPL:
2826 {
2827 struct fw_rcv_buf rb;
2828
2829 if ((vec[nvec-1].iov_len -=
2830 sizeof(struct fwohci_trailer)) == 0)
2831 nvec--;
2832 rb.fc = &sc->fc;
2833 rb.vec = vec;
2834 rb.nvec = nvec;
2835 rb.spd = spd;
2836 fw_rcv(&rb);
2837 break;
2838 }
2839 case FWOHCIEV_BUSRST:
2840 if (sc->fc.status != FWBUSRESET)
2841 printf("got BUSRST packet!?\n");
2842 break;
2843 default:
2844 device_printf(sc->fc.dev, "Async DMA Receive error err = %02x %s\n", stat, fwohcicode[stat]);
2845#if 0 /* XXX */
2846 goto out;

--- 38 unchanged lines hidden ---