summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/firewire/fwohci.c336
-rw-r--r--sys/dev/firewire/fwohci_pci.c5
-rw-r--r--sys/dev/firewire/fwohcivar.h1
3 files changed, 182 insertions, 160 deletions
diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c
index 2aa0020..0d72363 100644
--- a/sys/dev/firewire/fwohci.c
+++ b/sys/dev/firewire/fwohci.c
@@ -397,14 +397,172 @@ fwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
return err;
}
-int
-fwohci_init(struct fwohci_softc *sc, device_t dev)
+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;
+ }
+ 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);
+ }
+ return 0;
+}
+
+
+void
+fwohci_reset(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;
+
+/* 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);
+
+ fwohci_probe_phy(sc, dev);
+
+ OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf));
+ OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
+
+ /* 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;
+ }
+
+ 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);
+}
+
+int
+fwohci_init(struct fwohci_softc *sc, device_t dev)
+{
+ int i;
+ u_int32_t reg;
reg = OREAD(sc, OHCI_VERSION);
device_printf(dev, "OHCI version %x.%x (ROM=%d)\n",
@@ -479,121 +637,6 @@ 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)
@@ -604,10 +647,7 @@ fwohci_init(struct fwohci_softc *sc, device_t dev)
return ENOMEM;
}
- OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf));
- sc->fc.sid_buf++;
- OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
-
+
fwohci_db_init(&sc->arrq);
if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0)
return ENOMEM;
@@ -652,34 +692,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;
- }
-
- 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
@@ -1120,15 +1136,15 @@ 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 thoes 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++;
}
@@ -1694,7 +1710,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);
}
diff --git a/sys/dev/firewire/fwohci_pci.c b/sys/dev/firewire/fwohci_pci.c
index 3d5f011..b8e6ac2 100644
--- a/sys/dev/firewire/fwohci_pci.c
+++ b/sys/dev/firewire/fwohci_pci.c
@@ -253,6 +253,8 @@ fwohci_pci_detach(device_t self)
s = splfw();
+
+ fwohci_shutdown(self);
bus_generic_detach(self);
/* disable interrupts that might have been switched on */
@@ -305,7 +307,10 @@ fwohci_pci_suspend(device_t dev)
static int
fwohci_pci_resume(device_t dev)
{
+ fwohci_softc_t *sc = device_get_softc(dev);
+
device_printf(dev, "fwoch_pci_resume\n");
+ fwohci_reset(sc, dev);
return 0;
}
diff --git a/sys/dev/firewire/fwohcivar.h b/sys/dev/firewire/fwohcivar.h
index 0a77c7e..fcfa26e 100644
--- a/sys/dev/firewire/fwohcivar.h
+++ b/sys/dev/firewire/fwohcivar.h
@@ -68,5 +68,6 @@ typedef struct fwohci_softc {
} fwohci_softc_t;
void fwohci_intr __P((void *arg));
int fwohci_init __P((struct fwohci_softc *, device_t));
+void fwohci_reset __P((struct fwohci_softc *, device_t));
int fwohci_detach __P((struct fwohci_softc *, device_t));
int fwohci_shutdown __P((device_t dev));
OpenPOWER on IntegriCloud