diff options
| author | Hidetoshi Shimokawa <simokawa@FreeBSD.org> | 2003-01-05 13:50:05 +0000 |
|---|---|---|
| committer | Hidetoshi Shimokawa <simokawa@FreeBSD.org> | 2003-01-05 13:50:05 +0000 |
| commit | 2ecca1d0340625319336df897b0f39d61a293d9e (patch) | |
| tree | 1303f4846b5681379608db184378d6e9c19c107a /sys/dev/firewire | |
| parent | 02ba829d041f62e759bb4ebdfd8e26c69e9a2d39 (diff) | |
Notes
Diffstat (limited to 'sys/dev/firewire')
| -rw-r--r-- | sys/dev/firewire/firewire.c | 42 | ||||
| -rw-r--r-- | sys/dev/firewire/firewire.h | 2 | ||||
| -rw-r--r-- | sys/dev/firewire/firewirebusreg.h | 38 | ||||
| -rw-r--r-- | sys/dev/firewire/firewirereg.h | 2 | ||||
| -rw-r--r-- | sys/dev/firewire/fwdev.c | 5 | ||||
| -rw-r--r-- | sys/dev/firewire/fwohci.c | 490 | ||||
| -rw-r--r-- | sys/dev/firewire/fwohci_pci.c | 128 | ||||
| -rw-r--r-- | sys/dev/firewire/fwohcireg.h | 34 | ||||
| -rw-r--r-- | sys/dev/firewire/fwohcivar.h | 6 | ||||
| -rw-r--r-- | sys/dev/firewire/sbp.c | 56 |
10 files changed, 480 insertions, 323 deletions
diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c index 75940eb55b6e..f6b9d05816c6 100644 --- a/sys/dev/firewire/firewire.c +++ b/sys/dev/firewire/firewire.c @@ -95,6 +95,8 @@ static device_method_t firewire_methods[] = { DEVMETHOD(device_probe, firewire_match), DEVMETHOD(device_attach, firewire_attach), DEVMETHOD(device_detach, firewire_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), DEVMETHOD(device_shutdown, bus_generic_shutdown), /* Bus interface */ @@ -104,7 +106,6 @@ static device_method_t firewire_methods[] = { { 0, 0 } }; char linkspeed[7][0x10]={"S100","S200","S400","S800","S1600","S3200","Unknown"}; -u_int maxrec[6]={512,1024,2048,4096,8192,0}; #define MAX_GAPHOP 16 u_int gap_cnt[] = {1, 1, 4, 6, 9, 12, 14, 17, @@ -330,7 +331,7 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) struct tcode_info *info; if(xfer == NULL) return EINVAL; - if(xfer->send.len > fc->maxrec){ + if(xfer->send.len > MAXREC(fc->maxrec)){ printf("send.len > maxrec\n"); return EINVAL; } @@ -367,8 +368,8 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) return EINVAL; } if(!(xferq->queued < xferq->maxq)){ - printf("%s:Discard a packet (queued=%d)\n", - device_get_nameunit(fc->dev), xferq->queued); + device_printf(fc->bdev, "Discard a packet (queued=%d)\n", + xferq->queued); return EINVAL; } @@ -492,7 +493,6 @@ firewire_attach( device_t dev ) fc = (struct firewire_comm *)device_get_softc(pa); sc->fc = fc; - sc->fc->dev = dev; unitmask = UNIT2MIN(device_get_unit(dev)); @@ -1161,7 +1161,7 @@ void fw_sidrcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int off) self_id++; fc->topology_map->self_id_count ++; } - printf("%s: %d nodes", device_get_nameunit(fc->dev), fc->max_node + 1); + device_printf(fc->bdev, "%d nodes", fc->max_node + 1); /* CRC */ fc->topology_map->crc = fw_crc16( (u_int32_t *)&fc->topology_map->generation, @@ -1204,7 +1204,8 @@ void fw_sidrcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int off) } }else{ fc->status = FWBUSMGRDONE; - printf("%s: BMR = %x\n", device_get_nameunit(fc->dev), CSRARC(fc, BUS_MGR_ID)); + device_printf(fc->bdev, "BMR = %x\n", + CSRARC(fc, BUS_MGR_ID)); } free(buf, M_DEVBUF); #if 1 @@ -1341,7 +1342,7 @@ loop: TAILQ_INSERT_BEFORE(tfwdev, fwdev, link); } - device_printf(fc->dev, "New %s device ID:%08x%08x\n", + device_printf(fc->bdev, "New %s device ID:%08x%08x\n", linkspeed[fwdev->speed], fc->ongoeui.hi, fc->ongoeui.lo); @@ -1629,22 +1630,23 @@ fw_attach_dev(struct firewire_comm *fc) device_t *devlistp; int devcnt; struct firewire_dev_comm *fdc; + u_int32_t spec, ver; for(fwdev = TAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = TAILQ_NEXT(fwdev, link)){ if(fwdev->status == FWDEVINIT){ - fwdev->spec = getcsrdata(fwdev, CSRKEY_SPEC); - if(fwdev->spec == 0) + spec = getcsrdata(fwdev, CSRKEY_SPEC); + if(spec == 0) continue; - fwdev->ver = getcsrdata(fwdev, CSRKEY_VER); - if(fwdev->ver == 0) + ver = getcsrdata(fwdev, CSRKEY_VER); + if(ver == 0) continue; fwdev->maxrec = (fwdev->csrrom[2] >> 12) & 0xf; - device_printf(fc->dev, "Device "); - switch(fwdev->spec){ + device_printf(fc->bdev, "Device "); + switch(spec){ case CSRVAL_ANSIT10: - switch(fwdev->ver){ + switch(ver){ case CSRVAL_T10SBP2: printf("SBP-II"); break; @@ -1653,7 +1655,7 @@ fw_attach_dev(struct firewire_comm *fc) } break; case CSRVAL_1394TA: - switch(fwdev->ver){ + switch(ver){ case CSR_PROTAVC: printf("AV/C"); break; @@ -1911,8 +1913,8 @@ fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u case FWACT_CH: if(fc->ir[bind->xfer->sub]->queued >= fc->ir[bind->xfer->sub]->maxq){ - printf("%s:Discard a packet %x %d\n", - device_get_nameunit(fc->dev), + device_printf(fc->bdev, + "Discard a packet %x %d\n", bind->xfer->sub, fc->ir[bind->xfer->sub]->queued); goto err; @@ -2011,8 +2013,8 @@ fw_try_bmr_callback(struct fw_xfer *xfer) rfp = (struct fw_pkt *)xfer->recv.buf; CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, ntohl(rfp->mode.lres.payload[0]) & 0x3f); - printf("%s: new bus manager %d ", - device_get_nameunit(fc->dev), CSRARC(fc, BUS_MGR_ID)); + device_printf(fc->bdev, "new bus manager %d ", + CSRARC(fc, BUS_MGR_ID)); if((htonl(rfp->mode.lres.payload[0]) & 0x3f) == fc->nodeid){ printf("(me)\n"); /* If I am bus manager, optimize gapcount */ diff --git a/sys/dev/firewire/firewire.h b/sys/dev/firewire/firewire.h index 032e59be716a..a30ce8a2b8cc 100644 --- a/sys/dev/firewire/firewire.h +++ b/sys/dev/firewire/firewire.h @@ -89,6 +89,7 @@ struct fw_reg_req_t{ unsigned long data; }; +#define MAXREC(x) (2 << (x)) #define FWPMAX_S400 (2048 + 20) /* MAXREC plus space for control data */ #define FWMAXQUEUE 128 @@ -544,7 +545,6 @@ struct fw_crom_buf { #define FW_SBINDADDR _IOWR('S', 3, struct fw_asybindreq) #define FW_CBINDADDR _IOWR('S', 4, struct fw_asybindreq) #define FW_GTPMAP _IOR('S', 5, struct fw_topology_map) -#define FW_GSPMAP _IOW('S', 6, struct fw_speed_map *) #define FW_GCROM _IOWR('S', 7, struct fw_crom_buf) #define FWOHCI_RDREG _IOWR('S', 80, struct fw_reg_req_t) diff --git a/sys/dev/firewire/firewirebusreg.h b/sys/dev/firewire/firewirebusreg.h deleted file mode 100644 index 63886a8172c9..000000000000 --- a/sys/dev/firewire/firewirebusreg.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the acknowledgement as bellow: - * - * This product includes software developed by K. Kobayashi and H. Shimokawa - * - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - * - */ -struct firewire_bus{ - device_t bdev; -}; diff --git a/sys/dev/firewire/firewirereg.h b/sys/dev/firewire/firewirereg.h index 86bd43b4ac1e..9549a299c22f 100644 --- a/sys/dev/firewire/firewirereg.h +++ b/sys/dev/firewire/firewirereg.h @@ -47,8 +47,10 @@ typedef struct proc fw_proc; struct fw_device{ u_int16_t dst; struct fw_eui64 eui; +#if 0 u_int32_t spec; u_int32_t ver; +#endif u_int8_t speed; u_int8_t maxrec; u_int8_t nport; diff --git a/sys/dev/firewire/fwdev.c b/sys/dev/firewire/fwdev.c index ae8a7009450f..1c9a70d705da 100644 --- a/sys/dev/firewire/fwdev.c +++ b/sys/dev/firewire/fwdev.c @@ -832,11 +832,6 @@ error: bcopy(sc->fc->topology_map, data, (sc->fc->topology_map->crc_len + 1) * 4); break; - case FW_GSPMAP: - /* speed_map is larger than a page */ - err = copyout(sc->fc->speed_map, *(void **)data, - (sc->fc->speed_map->crc_len + 1) * 4); - break; case FW_GCROM: for (fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL; fwdev = TAILQ_NEXT(fwdev, link)) { diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c index 5966910b5232..b76ba8901a24 100644 --- a/sys/dev/firewire/fwohci.c +++ b/sys/dev/firewire/fwohci.c @@ -69,7 +69,6 @@ #include <vm/pmap.h> /* for vtophys proto */ #include <dev/firewire/firewire.h> -#include <dev/firewire/firewirebusreg.h> #include <dev/firewire/firewirereg.h> #include <dev/firewire/fwohcireg.h> #include <dev/firewire/fwohcivar.h> @@ -92,7 +91,6 @@ char fwohcicode[32][0x20]={ "Undef","ack data_err","ack type_err",""}; #define MAX_SPEED 2 extern char linkspeed[MAX_SPEED+1][0x10]; -extern int maxrec[MAX_SPEED+1]; static char dbcond[4][0x10]={"NEV","C=1", "C=0", "ALL"}; u_int32_t tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31}; @@ -321,7 +319,14 @@ again: } if(i >= MAX_RETRY) { device_printf(sc->fc.dev, "cannot read phy\n"); +#if 0 return 0; /* XXX */ +#else + if (++retry < MAX_RETRY) { + DELAY(1000); + goto again; + } +#endif } /* Make sure that SCLK is started */ stat = OREAD(sc, FWOHCI_INTSTAT); @@ -390,14 +395,189 @@ fwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) return err; } +static int +fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) +{ + u_int32_t reg, reg2; + int e1394a = 1; +/* + * probe PHY parameters + * 0. to prove PHY version, whether compliance of 1394a. + * 1. to probe maximum speed supported by the PHY and + * number of port supported by core-logic. + * It is not actually available port on your PC . + */ + OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS); +#if 0 + /* XXX wait for SCLK. */ + DELAY(100000); +#endif + reg = fwphy_rddata(sc, FW_PHY_SPD_REG); + + if((reg >> 5) != 7 ){ + sc->fc.mode &= ~FWPHYASYST; + sc->fc.nport = reg & FW_PHY_NP; + sc->fc.speed = reg & FW_PHY_SPD >> 6; + if (sc->fc.speed > MAX_SPEED) { + device_printf(dev, "invalid speed %d (fixed to %d).\n", + sc->fc.speed, MAX_SPEED); + sc->fc.speed = MAX_SPEED; + } + device_printf(dev, + "Phy 1394 only %s, %d ports.\n", + linkspeed[sc->fc.speed], sc->fc.nport); + }else{ + reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG); + sc->fc.mode |= FWPHYASYST; + sc->fc.nport = reg & FW_PHY_NP; + sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; + if (sc->fc.speed > MAX_SPEED) { + device_printf(dev, "invalid speed %d (fixed to %d).\n", + sc->fc.speed, MAX_SPEED); + sc->fc.speed = MAX_SPEED; + } + device_printf(dev, + "Phy 1394a available %s, %d ports.\n", + linkspeed[sc->fc.speed], sc->fc.nport); + + /* check programPhyEnable */ + reg2 = fwphy_rddata(sc, 5); +#if 0 + if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) { +#else /* XXX force to enable 1394a */ + if (e1394a) { +#endif + if (bootverbose) + device_printf(dev, + "Enable 1394a Enhancements\n"); + /* enable EAA EMC */ + reg2 |= 0x03; + /* set aPhyEnhanceEnable */ + OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN); + OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY); + } else { + /* for safe */ + reg2 &= ~0x83; + } + reg2 = fwphy_wrdata(sc, 5, reg2); + } + + reg = fwphy_rddata(sc, FW_PHY_SPD_REG); + if((reg >> 5) == 7 ){ + reg = fwphy_rddata(sc, 4); + reg |= 1 << 6; + fwphy_wrdata(sc, 4, reg); + reg = fwphy_rddata(sc, 4); + } + return 0; +} + + +void +fwohci_reset(struct fwohci_softc *sc, device_t dev) +{ + int i, max_rec, speed; + u_int32_t reg, reg2; + struct fwohcidb_tr *db_tr; + + /* Disable interrupt */ + OWRITE(sc, FWOHCI_INTMASKCLR, ~0); + + /* Now stopping all DMA channel */ + OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); + + OWRITE(sc, OHCI_IR_MASKCLR, ~0); + for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ + OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); + } + + /* FLUSH FIFO and reset Transmitter/Reciever */ + OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); + if (bootverbose) + device_printf(dev, "resetting OHCI..."); + i = 0; + while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { + if (i++ > 100) break; + DELAY(1000); + } + if (bootverbose) + printf("done (loop=%d)\n", i); + + /* Probe phy */ + fwohci_probe_phy(sc, dev); + + /* Probe link */ + reg = OREAD(sc, OHCI_BUS_OPT); + reg2 = reg | OHCI_BUSFNC; + max_rec = (reg & 0x0000f000) >> 12; + speed = (reg & 0x00000007); + device_printf(dev, "Link %s, max_rec %d bytes.\n", + linkspeed[speed], MAXREC(max_rec)); + /* XXX fix max_rec */ + sc->fc.maxrec = sc->fc.speed + 8; + if (max_rec != sc->fc.maxrec) { + reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12); + device_printf(dev, "max_rec %d -> %d\n", + MAXREC(max_rec), MAXREC(sc->fc.maxrec)); + } + if (bootverbose) + device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); + OWRITE(sc, OHCI_BUS_OPT, reg2); + + /* Initialize registers */ + OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]); + OWRITE(sc, OHCI_CROMPTR, vtophys(&sc->fc.config_rom[0])); + OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND); + OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR); + OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf)); + OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID); + fw_busreset(&sc->fc); + + /* Enable link */ + OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN); + + /* Force to start async RX DMA */ + sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING; + sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING; + fwohci_rx_enable(sc, &sc->arrq); + fwohci_rx_enable(sc, &sc->arrs); + + /* Initialize async TX */ + OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); + OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); + /* AT Retries */ + OWRITE(sc, FWOHCI_RETRY, + /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */ + (0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ; + for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ; + i ++, db_tr = STAILQ_NEXT(db_tr, link)){ + db_tr->xfer = NULL; + } + for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ; + i ++, db_tr = STAILQ_NEXT(db_tr, link)){ + db_tr->xfer = NULL; + } + + + /* Enable interrupt */ + OWRITE(sc, FWOHCI_INTMASK, + OHCI_INT_ERR | OHCI_INT_PHY_SID + | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS + | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS + | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR); + fwohci_set_intr(&sc->fc, 1); + +} + int fwohci_init(struct fwohci_softc *sc, device_t dev) { - int err = 0; int i; - u_int32_t reg, reg2; - struct fwohcidb_tr *db_tr; - int e1394a = 1; + u_int32_t reg; reg = OREAD(sc, OHCI_VERSION); device_printf(dev, "OHCI version %x.%x (ROM=%d)\n", @@ -432,8 +612,8 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) sc->arrq.ndesc = 1; sc->arrs.ndesc = 1; - sc->atrq.ndesc = 10; - sc->atrs.ndesc = 10 / 2; + sc->atrq.ndesc = 6; /* equal to maximum of mbuf chains */ + sc->atrs.ndesc = 6 / 2; sc->arrq.ndb = NDB; sc->arrs.ndb = NDB / 2; @@ -457,6 +637,7 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) contigmalloc(CROMSIZE * 2, M_DEVBUF, M_NOWAIT, 0, ~0, 1<<10, 0); if(sc->cromptr == NULL){ + device_printf(dev, "cromptr alloc failed."); return ENOMEM; } sc->fc.dev = dev; @@ -471,135 +652,32 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4); - - fw_init(&sc->fc); - -/* Disable interrupt */ - OWRITE(sc, FWOHCI_INTMASKCLR, ~0); - -/* Now stopping all DMA channel */ - OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); - - OWRITE(sc, OHCI_IR_MASKCLR, ~0); - for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ - OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); - } - -/* FLUSH FIFO and reset Transmitter/Reciever */ - OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); - if (bootverbose) - device_printf(dev, "resetting OHCI..."); - i = 0; - while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { - if (i++ > 100) break; - DELAY(1000); - } - if (bootverbose) - printf("done (loop=%d)\n", i); - - reg = OREAD(sc, OHCI_BUS_OPT); - reg2 = reg | OHCI_BUSFNC; - /* XXX */ - if (((reg & 0x0000f000) >> 12) < 10) - reg2 = (reg2 & 0xffff0fff) | (10 << 12); - if (bootverbose) - device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); - OWRITE(sc, OHCI_BUS_OPT, reg2); - - OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]); - OWRITE(sc, OHCI_CROMPTR, vtophys(&sc->fc.config_rom[0])); - OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND); - OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR); - -/* - * probe PHY parameters - * 0. to prove PHY version, whether compliance of 1394a. - * 1. to probe maximum speed supported by the PHY and - * number of port supported by core-logic. - * It is not actually available port on your PC . - */ - OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS); -#if 0 - /* XXX wait for SCLK. */ - DELAY(100000); -#endif - reg = fwphy_rddata(sc, FW_PHY_SPD_REG); - - if((reg >> 5) != 7 ){ - sc->fc.mode &= ~FWPHYASYST; - sc->fc.nport = reg & FW_PHY_NP; - sc->fc.speed = reg & FW_PHY_SPD >> 6; - if (sc->fc.speed > MAX_SPEED) { - device_printf(dev, "invalid speed %d (fixed to %d).\n", - sc->fc.speed, MAX_SPEED); - sc->fc.speed = MAX_SPEED; - } - sc->fc.maxrec = maxrec[sc->fc.speed]; - device_printf(dev, - "Link 1394 only %s, %d ports, maxrec %d bytes.\n", - linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec); - }else{ - reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG); - sc->fc.mode |= FWPHYASYST; - sc->fc.nport = reg & FW_PHY_NP; - sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; - if (sc->fc.speed > MAX_SPEED) { - device_printf(dev, "invalid speed %d (fixed to %d).\n", - sc->fc.speed, MAX_SPEED); - sc->fc.speed = MAX_SPEED; - } - sc->fc.maxrec = maxrec[sc->fc.speed]; - device_printf(dev, - "Link 1394a available %s, %d ports, maxrec %d bytes.\n", - linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec); - - /* check programPhyEnable */ - reg2 = fwphy_rddata(sc, 5); -#if 0 - if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) { -#else /* XXX force to enable 1394a */ - if (e1394a) { -#endif - if (bootverbose) - device_printf(dev, - "Enable 1394a Enhancements\n"); - /* enable EAA EMC */ - reg2 |= 0x03; - /* set aPhyEnhanceEnable */ - OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN); - OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY); - } else { - /* for safe */ - reg2 &= ~0x83; - } - reg2 = fwphy_wrdata(sc, 5, reg2); - } - - reg = fwphy_rddata(sc, FW_PHY_SPD_REG); - if((reg >> 5) == 7 ){ - reg = fwphy_rddata(sc, 4); - reg |= 1 << 6; - fwphy_wrdata(sc, 4, reg); - reg = fwphy_rddata(sc, 4); - } /* SID recieve buffer must allign 2^11 */ #define OHCI_SIDSIZE (1 << 11) sc->fc.sid_buf = (u_int32_t *) vm_page_alloc_contig( OHCI_SIDSIZE, 0x10000, 0xffffffff, OHCI_SIDSIZE); - OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf)); - sc->fc.sid_buf++; - OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID); + if (sc->fc.sid_buf == NULL) { + device_printf(dev, "sid_buf alloc failed.\n"); + return ENOMEM; + } + fwohci_db_init(&sc->arrq); + if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; + fwohci_db_init(&sc->arrs); + if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; fwohci_db_init(&sc->atrq); + if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; + fwohci_db_init(&sc->atrs); + if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; reg = OREAD(sc, FWOHCIGUID_H); for( i = 0 ; i < 4 ; i ++){ @@ -629,35 +707,10 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) sc->fc.poll = fwohci_poll; sc->fc.set_intr = fwohci_set_intr; - /* enable link */ - OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN); - fw_busreset(&sc->fc); - fwohci_rx_enable(sc, &sc->arrq); - fwohci_rx_enable(sc, &sc->arrs); - - for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ; - i ++, db_tr = STAILQ_NEXT(db_tr, link)){ - db_tr->xfer = NULL; - } - for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ; - i ++, db_tr = STAILQ_NEXT(db_tr, link)){ - db_tr->xfer = NULL; - } - sc->atrq.flags = sc->atrs.flags = 0; - - OWRITE(sc, FWOHCI_RETRY, - (0xffff << 16 )| (0x0f << 8) | (0x0f << 4) | 0x0f) ; - OWRITE(sc, FWOHCI_INTMASK, - OHCI_INT_ERR | OHCI_INT_PHY_SID - | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS - | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS - | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR); - fwohci_set_intr(&sc->fc, 1); - - OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); - OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); + fw_init(&sc->fc); + fwohci_reset(sc, dev); - return err; + return 0; } void @@ -677,6 +730,31 @@ fwohci_cyctimer(struct firewire_comm *fc) return(OREAD(sc, OHCI_CYCLETIMER)); } +int +fwohci_detach(struct fwohci_softc *sc, device_t dev) +{ + int i; + + if (sc->fc.sid_buf != NULL) + contigfree((void *)(uintptr_t)sc->fc.sid_buf, + OHCI_SIDSIZE, M_DEVBUF); + if (sc->cromptr != NULL) + contigfree((void *)sc->cromptr, CROMSIZE * 2, M_DEVBUF); + + fwohci_db_free(&sc->arrq); + fwohci_db_free(&sc->arrs); + + fwohci_db_free(&sc->atrq); + fwohci_db_free(&sc->atrs); + + for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ + fwohci_db_free(&sc->it[i]); + fwohci_db_free(&sc->ir[i]); + } + + return 0; +} + #define LAST_DB(dbtr, db) do { \ struct fwohcidb_tr *_dbtr = (dbtr); \ int _cnt = _dbtr->dbcnt; \ @@ -697,6 +775,7 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) volatile struct fwohcidb *db; struct mbuf *m; struct tcode_info *info; + static int maxdesc=0; if(&sc->atrq == dbch){ off = OHCI_ATQOFF; @@ -772,18 +851,30 @@ txloop: db_tr->dbcnt++; } else { /* XXX we assume mbuf chain is shorter than ndesc */ - m = xfer->mbuf; - do { + for (m = xfer->mbuf; m != NULL; m = m->m_next) { + if (m->m_len == 0) + /* unrecoverable error could ocurre. */ + continue; + if (db_tr->dbcnt >= dbch->ndesc) { + device_printf(sc->fc.dev, + "dbch->ndesc is too small" + ", trancated.\n"); + break; + } db->db.desc.addr = vtophys(mtod(m, caddr_t)); db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len; db->db.desc.status = 0; db++; db_tr->dbcnt++; - m = m->m_next; - } while (m != NULL); + } } } + if (maxdesc < db_tr->dbcnt) { + maxdesc = db_tr->dbcnt; + if (bootverbose) + device_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc); + } /* last db */ LAST_DB(db_tr, db); db->db.desc.cmd |= OHCI_OUTPUT_LAST @@ -1015,21 +1106,26 @@ fwohci_db_free(struct fwohci_dbch *dbch) struct fwohcidb_tr *db_tr; int idb; + if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) + return; + if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0; idb < dbch->ndb; db_tr = STAILQ_NEXT(db_tr, link), idb++){ - free(db_tr->buf, M_DEVBUF); - db_tr->buf = NULL; + if (db_tr->buf != NULL) { + free(db_tr->buf, M_DEVBUF); + db_tr->buf = NULL; + } } } dbch->ndb = 0; db_tr = STAILQ_FIRST(&dbch->db_trq); contigfree((void *)(uintptr_t)(volatile void *)db_tr->db, sizeof(struct fwohcidb) * dbch->ndesc * dbch->ndb, M_DEVBUF); - /* Attach DB to DMA ch. */ free(db_tr, M_DEVBUF); STAILQ_INIT(&dbch->db_trq); + dbch->flags &= ~FWOHCI_DBCH_INIT; } static void @@ -1038,26 +1134,27 @@ fwohci_db_init(struct fwohci_dbch *dbch) int idb; struct fwohcidb *db; struct fwohcidb_tr *db_tr; + + + if ((dbch->flags & FWOHCI_DBCH_INIT) != 0) + goto out; + /* allocate DB entries and attach one to each DMA channels */ /* DB entry must start at 16 bytes bounary. */ - dbch->frag.buf = NULL; - dbch->frag.len = 0; - dbch->frag.plen = 0; - dbch->xferq.queued = 0; - dbch->pdb_tr = NULL; - STAILQ_INIT(&dbch->db_trq); db_tr = (struct fwohcidb_tr *) malloc(sizeof(struct fwohcidb_tr) * dbch->ndb, - M_DEVBUF, M_DONTWAIT); + M_DEVBUF, M_DONTWAIT | M_ZERO); if(db_tr == NULL){ + printf("fwohci_db_init: malloc failed\n"); return; } db = (struct fwohcidb *) contigmalloc(sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb, M_DEVBUF, M_DONTWAIT, 0x10000, 0xffffffff, PAGE_SIZE, 0ul); if(db == NULL){ - printf("fwochi_db_init: contigmalloc failed\n"); + printf("fwohci_db_init: contigmalloc failed\n"); + free(db_tr, M_DEVBUF); return; } bzero(db, sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb); @@ -1066,22 +1163,29 @@ fwohci_db_init(struct fwohci_dbch *dbch) db_tr->dbcnt = 0; db_tr->db = &db[idb * dbch->ndesc]; STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link); - if(!(dbch->xferq.flag & FWXFERQ_PACKET) && - (idb % dbch->xferq.bnpacket == 0)){ - dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].start - = (caddr_t)db_tr; - } - if((!(dbch->xferq.flag & FWXFERQ_PACKET)) && - ((idb + 1)% dbch->xferq.bnpacket == 0)){ - dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].end - = (caddr_t)db_tr; + if (!(dbch->xferq.flag & FWXFERQ_PACKET) && + dbch->xferq.bnpacket != 0) { + /* XXX what those for? */ + if (idb % dbch->xferq.bnpacket == 0) + dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket + ].start = (caddr_t)db_tr; + if ((idb + 1) % dbch->xferq.bnpacket == 0) + dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket + ].end = (caddr_t)db_tr; } db_tr++; } STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next = STAILQ_FIRST(&dbch->db_trq); +out: + dbch->frag.buf = NULL; + dbch->frag.len = 0; + dbch->frag.plen = 0; + dbch->xferq.queued = 0; + dbch->pdb_tr = NULL; dbch->top = STAILQ_FIRST(&dbch->db_trq); dbch->bottom = dbch->top; + dbch->flags = FWOHCI_DBCH_INIT; } static int @@ -1256,6 +1360,7 @@ fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) } } dbch->xferq.flag |= FWXFERQ_RUNNING; + dbch->top = STAILQ_FIRST(&dbch->db_trq); for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ dbch->bottom = STAILQ_NEXT(dbch->bottom, link); } @@ -1455,10 +1560,9 @@ fwohci_irx_enable(struct firewire_comm *fc, int dmach) } int -fwohci_shutdown(device_t dev) +fwohci_shutdown(struct fwohci_softc *sc, device_t dev) { u_int i; - struct fwohci_softc *sc = device_get_softc(dev); /* Now stopping all DMA channel */ OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); @@ -1482,6 +1586,28 @@ fwohci_shutdown(device_t dev) | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS | OHCI_INT_PHY_BUS_R); +/* XXX Link down? Bus reset? */ + return 0; +} + +int +fwohci_resume(struct fwohci_softc *sc, device_t dev) +{ + int i; + + fwohci_reset(sc, dev); + /* XXX resume isochronus receive automatically. (how about TX?) */ + for(i = 0; i < sc->fc.nisodma; i ++) { + if((sc->ir[i].xferq.flag & FWXFERQ_RUNNING) != 0) { + device_printf(sc->fc.dev, + "resume iso receive ch: %d\n", i); + sc->ir[i].xferq.flag &= ~FWXFERQ_RUNNING; + sc->fc.irx_enable(&sc->fc, i); + } + } + + bus_generic_resume(dev); + sc->fc.ibr(&sc->fc); return 0; } @@ -1639,7 +1765,7 @@ fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count) plen -= 4; /* chop control info */ buf = malloc( FWPMAX_S400, M_DEVBUF, M_NOWAIT); if(buf == NULL) goto sidout; - bcopy((void *)(uintptr_t)(volatile void *)fc->sid_buf, + bcopy((void *)(uintptr_t)(volatile void *)(fc->sid_buf + 1), buf, plen); fw_sidrcv(fc, buf, plen, 0); } @@ -1743,7 +1869,7 @@ fwohci_set_intr(struct firewire_comm *fc, int enable) sc = (struct fwohci_softc *)fc; if (bootverbose) - device_printf(sc->fc.dev, "fwochi_set_intr: %d\n", enable); + device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable); if (enable) { sc->intmask |= OHCI_INT_EN; OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN); diff --git a/sys/dev/firewire/fwohci_pci.c b/sys/dev/firewire/fwohci_pci.c index ef22f1930a97..f96a9cffd34b 100644 --- a/sys/dev/firewire/fwohci_pci.c +++ b/sys/dev/firewire/fwohci_pci.c @@ -47,7 +47,6 @@ #include <pci/pcireg.h> #include <dev/firewire/firewire.h> -#include <dev/firewire/firewirebusreg.h> #include <dev/firewire/firewirereg.h> #include <dev/firewire/fwohcireg.h> @@ -63,58 +62,62 @@ static int fwohci_pci_probe( device_t dev ) { #if 1 - if ((pci_get_vendor(dev) == FW_VENDORID_NEC) && - (pci_get_device(dev) == FW_DEVICE_UPD861)) { + u_int32_t id; + + id = (pci_get_vendor(dev) << 16) | pci_get_device(dev); + if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD861)) { device_set_desc(dev, "NEC uPD72861"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_TI) && - (pci_get_device(dev) == FW_DEVICE_TITSB22)) { + if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB22)) { device_set_desc(dev, "Texas Instruments TSB12LV22"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_TI) && - (pci_get_device(dev) == FW_DEVICE_TITSB23)) { + if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB23)) { device_set_desc(dev, "Texas Instruments TSB12LV23"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_TI) && - (pci_get_device(dev) == FW_DEVICE_TITSB26)) { + if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB26)) { device_set_desc(dev, "Texas Instruments TSB12LV26"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_TI) && - (pci_get_device(dev) == FW_DEVICE_TITSB43)) { + if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43)) { device_set_desc(dev, "Texas Instruments TSB43AA22"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_SONY) && - (pci_get_device(dev) == FW_DEVICE_CX3022)) { + if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43A)) { + device_set_desc(dev, "Texas Instruments TSB43AB22/A"); + return 0; + } + if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4450)) { + device_set_desc(dev, "Texas Instruments PCI4450"); + return 0; + } + if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4410A)) { + device_set_desc(dev, "Texas Instruments PCI4410A"); + return 0; + } + if (id == (FW_VENDORID_SONY | FW_DEVICE_CX3022)) { device_set_desc(dev, "SONY CX3022"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_VIA) && - (pci_get_device(dev) == FW_DEVICE_VT6306)) { + if (id == (FW_VENDORID_VIA | FW_DEVICE_VT6306)) { device_set_desc(dev, "VIA VT6306"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_RICOH) && - (pci_get_device(dev) == FW_DEVICE_R5C552)) { + if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C552)) { device_set_desc(dev, "Ricoh R5C552"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_APPLE) && - (pci_get_device(dev) == FW_DEVICE_PANGEA)) { + if (id == (FW_VENDORID_APPLE | FW_DEVICE_PANGEA)) { device_set_desc(dev, "Apple Pangea"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_APPLE) && - (pci_get_device(dev) == FW_DEVICE_UNINORTH)) { + if (id == (FW_VENDORID_APPLE | FW_DEVICE_UNINORTH)) { device_set_desc(dev, "Apple UniNorth"); return 0; } - if ((pci_get_vendor(dev) == FW_VENDORID_LUCENT) && - (pci_get_device(dev) == FW_DEVICE_FW322)) { + if (id == (FW_VENDORID_LUCENT | FW_DEVICE_FW322)) { device_set_desc(dev, "Lucent FW322/323"); return 0; } @@ -122,7 +125,7 @@ fwohci_pci_probe( device_t dev ) if (pci_get_class(dev) == PCIC_SERIALBUS && pci_get_subclass(dev) == PCIS_SERIALBUS_FW && pci_get_progif(dev) == PCI_INTERFACE_OHCI) { - printf("XXXfw: vendid=%x, dev=%x\n", pci_get_vendor(dev), + device_printf(dev, "vendor=%x, dev=%x\n", pci_get_vendor(dev), pci_get_device(dev)); device_set_desc(dev, "1394 Open Host Controller Interface"); return 0; @@ -140,27 +143,10 @@ fwohci_dummy_intr(void *arg) #endif static int -fwohci_pci_attach(device_t self) +fwohci_pci_init(device_t self) { - fwohci_softc_t *sc = device_get_softc(self); - int err; - int rid; int latency, cache_line; u_int16_t cmd; -#if __FreeBSD_version < 500000 - int intr; - /* For the moment, put in a message stating what is wrong */ - intr = pci_read_config(self, PCIR_INTLINE, 1); - if (intr == 0 || intr == 255) { - device_printf(self, "Invalid irq %d\n", intr); -#ifdef __i386__ - device_printf(self, "Please switch PNP-OS to 'No' in BIOS\n"); -#endif -#if 0 - return ENXIO; -#endif - } -#endif cmd = pci_read_config(self, PCIR_COMMAND, 2); cmd |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; @@ -185,7 +171,33 @@ fwohci_pci_attach(device_t self) #endif if (bootverbose) device_printf(self, "cache size %d.\n", (int) cache_line); -/**/ + + return 0; +} + +static int +fwohci_pci_attach(device_t self) +{ + fwohci_softc_t *sc = device_get_softc(self); + int err; + int rid; +#if __FreeBSD_version < 500000 + int intr; + /* For the moment, put in a message stating what is wrong */ + intr = pci_read_config(self, PCIR_INTLINE, 1); + if (intr == 0 || intr == 255) { + device_printf(self, "Invalid irq %d\n", intr); +#ifdef __i386__ + device_printf(self, "Please switch PNP-OS to 'No' in BIOS\n"); +#endif +#if 0 + return ENXIO; +#endif + } +#endif + + fwohci_pci_init(self); + rid = PCI_CBMEM; sc->bsr = bus_alloc_resource(self, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE); @@ -249,6 +261,8 @@ fwohci_pci_detach(device_t self) s = splfw(); + + fwohci_shutdown(sc, self); bus_generic_detach(self); /* disable interrupts that might have been switched on */ @@ -284,6 +298,8 @@ fwohci_pci_detach(device_t self) sc->bst = 0; sc->bsh = 0; } + + fwohci_detach(sc, self); splx(s); return 0; @@ -292,14 +308,34 @@ fwohci_pci_detach(device_t self) static int fwohci_pci_suspend(device_t dev) { - device_printf(dev, "fwoch_pci_suspend\n"); + int err; + + device_printf(dev, "fwohci_pci_suspend\n"); + err = bus_generic_suspend(dev); + if (err) + return err; + /* fwohci_shutdown(dev); */ return 0; } static int fwohci_pci_resume(device_t dev) { - device_printf(dev, "fwoch_pci_resume\n"); + fwohci_softc_t *sc = device_get_softc(dev); + + device_printf(dev, "fwohci_pci_resume: power_state = 0x%08x\n", + pci_get_powerstate(dev)); + fwohci_pci_init(dev); + fwohci_resume(sc, dev); + return 0; +} + +static int +fwohci_pci_shutdown(device_t dev) +{ + fwohci_softc_t *sc = device_get_softc(dev); + + fwohci_shutdown(sc, dev); return 0; } @@ -308,9 +344,9 @@ static device_method_t fwohci_methods[] = { DEVMETHOD(device_probe, fwohci_pci_probe), DEVMETHOD(device_attach, fwohci_pci_attach), DEVMETHOD(device_detach, fwohci_pci_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, fwohci_pci_suspend), DEVMETHOD(device_resume, fwohci_pci_resume), + DEVMETHOD(device_shutdown, fwohci_pci_shutdown), /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), diff --git a/sys/dev/firewire/fwohcireg.h b/sys/dev/firewire/fwohcireg.h index cb399b6beb78..572370d2f454 100644 --- a/sys/dev/firewire/fwohcireg.h +++ b/sys/dev/firewire/fwohcireg.h @@ -35,22 +35,25 @@ */ #define PCI_CBMEM 0x10 -#define FW_VENDORID_NEC 0x1033 -#define FW_VENDORID_TI 0x104c -#define FW_VENDORID_SONY 0x104d -#define FW_VENDORID_VIA 0x1106 -#define FW_VENDORID_RICOH 0x1180 -#define FW_VENDORID_APPLE 0x106b -#define FW_VENDORID_LUCENT 0x11c1 +#define FW_VENDORID_NEC (0x1033 << 16) +#define FW_VENDORID_TI (0x104c << 16) +#define FW_VENDORID_SONY (0x104d << 16) +#define FW_VENDORID_VIA (0x1106 << 16) +#define FW_VENDORID_RICOH (0x1180 << 16) +#define FW_VENDORID_APPLE (0x106b << 16) +#define FW_VENDORID_LUCENT (0x11c1 << 16) #define FW_DEVICE_UPD861 0x0063 #define FW_DEVICE_TITSB22 0x8009 #define FW_DEVICE_TITSB23 0x8019 #define FW_DEVICE_TITSB26 0x8020 #define FW_DEVICE_TITSB43 0x8021 +#define FW_DEVICE_TITSB43A 0x8023 +#define FW_DEVICE_TIPCI4450 0x8011 +#define FW_DEVICE_TIPCI4410A 0x8017 #define FW_DEVICE_CX3022 0x8039 #define FW_DEVICE_VT6306 0x3044 -#define FW_DEVICE_R5C552 0x1180 +#define FW_DEVICE_R5C552 0x0552 #define FW_DEVICE_PANGEA 0x0030 #define FW_DEVICE_UNINORTH 0x0031 #define FW_DEVICE_FW322 0x5811 @@ -169,13 +172,14 @@ struct ohci_registers { fwohcireg_t dummy1[3]; /* dummy 0x44-0x4c */ fwohcireg_t hcc_cntl_set; /* HCC control set 0x50 */ fwohcireg_t hcc_cntl_clr; /* HCC control clr 0x54 */ -#define OHCI_HCC_BIGEND (1 << 30) -#define OHCI_HCC_PRPHY (1 << 23) -#define OHCI_HCC_PHYEN (1 << 22) -#define OHCI_HCC_LPS (1 << 19) -#define OHCI_HCC_POSTWR (1 << 18) -#define OHCI_HCC_LINKEN (1 << 17) -#define OHCI_HCC_RESET (1 << 16) +#define OHCI_HCC_BIBIV (1 << 31) /* BIBimage Valid */ +#define OHCI_HCC_BIGEND (1 << 30) /* noByteSwapData */ +#define OHCI_HCC_PRPHY (1 << 23) /* programPhyEnable */ +#define OHCI_HCC_PHYEN (1 << 22) /* aPhyEnhanceEnable */ +#define OHCI_HCC_LPS (1 << 19) /* LPS */ +#define OHCI_HCC_POSTWR (1 << 18) /* postedWriteEnable */ +#define OHCI_HCC_LINKEN (1 << 17) /* linkEnable */ +#define OHCI_HCC_RESET (1 << 16) /* softReset */ fwohcireg_t dummy2[2]; /* dummy 0x58-0x5c */ fwohcireg_t dummy3[1]; /* dummy 0x60 */ fwohcireg_t sid_buf; /* self id buffer 0x64 */ diff --git a/sys/dev/firewire/fwohcivar.h b/sys/dev/firewire/fwohcivar.h index 6b7c95460f77..5e657cfe10c0 100644 --- a/sys/dev/firewire/fwohcivar.h +++ b/sys/dev/firewire/fwohcivar.h @@ -58,6 +58,7 @@ typedef struct fwohci_softc { caddr_t buf; } frag; int flags; +#define FWOHCI_DBCH_INIT (1<<0) #define FWOHCI_DBCH_FULL (1<<1) int buf_offset; } arrq, arrs, atrq, atrs, it[OHCI_DMA_ITCH], ir[OHCI_DMA_IRCH]; @@ -67,4 +68,7 @@ typedef struct fwohci_softc { } fwohci_softc_t; void fwohci_intr __P((void *arg)); int fwohci_init __P((struct fwohci_softc *, device_t)); -int fwohci_shutdown __P((device_t dev)); +void fwohci_reset __P((struct fwohci_softc *, device_t)); +int fwohci_detach __P((struct fwohci_softc *, device_t)); +int fwohci_resume __P((struct fwohci_softc *, device_t)); +int fwohci_shutdown __P((struct fwohci_softc *, device_t dev)); diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c index fbbd373c5310..0567974d28b0 100644 --- a/sys/dev/firewire/sbp.c +++ b/sys/dev/firewire/sbp.c @@ -253,8 +253,9 @@ struct sbp_dev{ #define SBP_DEV_ATTACHED 5 /* in operation */ #define SBP_DEV_DEAD 6 /* unavailable unit */ #define SBP_DEV_RETRY 7 /* unavailable unit */ - int status; - int lun_id; + u_int8_t status; + u_int8_t type; + u_int16_t lun_id; struct cam_path *path; struct sbp_target *target; struct sbp_login_res login; @@ -388,7 +389,6 @@ END_DEBUG static void sbp_show_sdev_info(struct sbp_dev *sdev, int new) { - int lun; struct fw_device *fwdev; printf("%s:%d:%d ", @@ -400,11 +400,10 @@ sbp_show_sdev_info(struct sbp_dev *sdev, int new) return; } fwdev = sdev->target->fwdev; - lun = getcsrdata(fwdev, 0x14); printf("ordered:%d type:%d EUI:%08x%08x node:%d " "speed:%d maxrec:%d", - (lun & 0x00400000) >> 22, - (lun & 0x001f0000) >> 16, + (sdev->type & 0x40) >> 6, + (sdev->type & 0x1f), fwdev->eui.hi, fwdev->eui.lo, fwdev->dst, @@ -422,9 +421,11 @@ sbp_show_sdev_info(struct sbp_dev *sdev, int new) static struct sbp_target * sbp_alloc_target(struct sbp_softc *sbp, struct fw_device *fwdev) { - int i, lun; + int i, maxlun, lun; struct sbp_target *target; struct sbp_dev *sdev; + struct crom_context cc; + struct csrreg *reg; SBP_DEBUG(1) printf("sbp_alloc_target\n"); @@ -448,10 +449,26 @@ END_DEBUG } target->mgm_hi = 0xffff; target->mgm_lo = 0xf0000000 | target->mgm_lo << 2; - /* XXX should probe all luns */ /* XXX num_lun may be changed. realloc luns? */ - lun = getcsrdata(target->fwdev, 0x14) & 0xff; - target->num_lun = lun + 1; + crom_init_context(&cc, target->fwdev->csrrom); + /* XXX shoud parse appropriate unit directories only */ + maxlun = -1; + while (cc.depth >= 0) { + reg = crom_search_key(&cc, CROM_LUN); + if (reg == NULL) + break; + lun = reg->val & 0xff; +SBP_DEBUG(0) + printf("target %d lun %d found\n", target->target_id, lun); +END_DEBUG + if (maxlun < lun) + maxlun = lun; + crom_next(&cc); + } + target->num_lun = maxlun + 1; + if (maxlun < 0) { + printf("no lun found!\n"); + } target->luns = (struct sbp_dev *) malloc( sizeof(struct sbp_dev) * target->num_lun, M_SBP, M_NOWAIT | M_ZERO); @@ -460,10 +477,17 @@ END_DEBUG sdev->lun_id = i; sdev->target = target; STAILQ_INIT(&sdev->ocbs); - if (i == lun) - sdev->status = SBP_DEV_RESET; - else - sdev->status = SBP_DEV_DEAD; + sdev->status = SBP_DEV_DEAD; + } + crom_init_context(&cc, target->fwdev->csrrom); + while (cc.depth >= 0) { + reg = crom_search_key(&cc, CROM_LUN); + if (reg == NULL) + break; + lun = reg->val & 0xff; + target->luns[lun].status = SBP_DEV_RESET; + target->luns[lun].type = (reg->val & 0x0f00) >> 16; + crom_next(&cc); } return target; } @@ -1097,7 +1121,7 @@ END_DEBUG fp->mode.wreqb.dest_lo = htonl(sdev->target->mgm_lo); fp->mode.wreqb.len = htons(8); fp->mode.wreqb.extcode = 0; - fp->mode.wreqb.payload[0] = htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16)); + fp->mode.wreqb.payload[0] = htonl(nid << 16); fp->mode.wreqb.payload[1] = htonl(vtophys(&ocb->orb[0])); sbp_enqueue_ocb(sdev, ocb); @@ -1643,7 +1667,9 @@ sbp_detach_target(struct sbp_target *target) struct sbp_dev *sdev; if (target->luns != NULL) { +SBP_DEBUG(0) printf("sbp_detach_target %d\n", target->target_id); +END_DEBUG for (i=0; i < target->num_lun; i++) { sdev = &target->luns[i]; if (sdev->status == SBP_DEV_RESET || |
