summaryrefslogtreecommitdiff
path: root/sys/dev/firewire
diff options
context:
space:
mode:
authorHidetoshi Shimokawa <simokawa@FreeBSD.org>2003-01-05 13:50:05 +0000
committerHidetoshi Shimokawa <simokawa@FreeBSD.org>2003-01-05 13:50:05 +0000
commit2ecca1d0340625319336df897b0f39d61a293d9e (patch)
tree1303f4846b5681379608db184378d6e9c19c107a /sys/dev/firewire
parent02ba829d041f62e759bb4ebdfd8e26c69e9a2d39 (diff)
Notes
Diffstat (limited to 'sys/dev/firewire')
-rw-r--r--sys/dev/firewire/firewire.c42
-rw-r--r--sys/dev/firewire/firewire.h2
-rw-r--r--sys/dev/firewire/firewirebusreg.h38
-rw-r--r--sys/dev/firewire/firewirereg.h2
-rw-r--r--sys/dev/firewire/fwdev.c5
-rw-r--r--sys/dev/firewire/fwohci.c490
-rw-r--r--sys/dev/firewire/fwohci_pci.c128
-rw-r--r--sys/dev/firewire/fwohcireg.h34
-rw-r--r--sys/dev/firewire/fwohcivar.h6
-rw-r--r--sys/dev/firewire/sbp.c56
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 ||