#include <OS.h>
#include <KernelExport.h>
#include <lock.h>
#include <SupportDefs.h>
#include <PCI.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "util.h"
#include "fwdebug.h"
#include "fwglue.h"
#include "queue.h"
#include "firewire.h"
#include "iec13213.h"
#include "firewirereg.h"
#include "fwdma.h"
#include "fwohcireg.h"
#include "fwohcivar.h"
#define PCIM_CMD_IOS 0x0001
#define PCIM_CMD_MEMEN 0x0002
#define PCIM_CMD_BUSMASTEREN 0x0004
#define PCIM_CMD_MWRICEN 0x0010
#define PCIM_CMD_PERRESPEN 0x0040
#define PCIM_CMD_SERRESPEN 0x0100
extern pci_module_info *gPci;
extern pci_info *pciInfo[MAX_CARDS];
extern fwohci_softc_t *gFwohci_softc[MAX_CARDS];
extern struct firewire_softc *gFirewire_softc[MAX_CARDS];
status_t
fwohci_pci_detach(int index)
{
fwohci_softc_t *sc = gFwohci_softc[index];
int s;
s = splfw();
fwohci_stop(sc);
firewire_detach(gFirewire_softc[index]);
OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
remove_io_interrupt_handler (sc->irq, fwohci_intr, sc);
delete_area(sc->regArea);
fwohci_detach(sc);
mtx_destroy(FW_GMTX(&sc->fc));
splx(s);
return B_OK;
}
static void
fwohci_pci_add_child(int index)
{
struct fwohci_softc *sc;
int err = 0;
sc = gFwohci_softc[index];
err = firewire_attach(&sc->fc, gFirewire_softc[index]);
if (err) {
device_printf(dev, "firewire_attach failed with err=%d\n",
err);
fwohci_pci_detach(index);
return;
}
}
status_t
fwohci_pci_attach(int index)
{
fwohci_softc_t *sc = gFwohci_softc[index];
pci_info *info = pciInfo[index];
uint32 olatency, latency, ocache_line, cache_line;
uint32 val;
mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF);
val = gPci->read_pci_config(info->bus, info->device, info->function,
PCI_command, 2);
val |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
#if 1
val &= ~PCIM_CMD_MWRICEN;
val &= ~(PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN);
#endif
gPci->write_pci_config(info->bus, info->device, info->function,
PCI_command, 2, val);
if (info->vendor_id == FW_VENDORID_SUN && info->device_id == (FW_DEVICE_PCIO2FW >> 16) &&
info->u.h0.interrupt_pin == 0)
info->u.h0.interrupt_pin = 3;
latency = olatency = gPci->read_pci_config(info->bus, info->device, info->function,
PCI_latency, 1);
#define DEF_LATENCY 0x20
if (olatency < DEF_LATENCY) {
latency = DEF_LATENCY;
gPci->write_pci_config(info->bus, info->device, info->function,
PCI_latency, 1, latency);
}
cache_line = ocache_line = gPci->read_pci_config(info->bus, info->device,
info->function, PCI_line_size, 1);
#define DEF_CACHE_LINE 8
if (ocache_line < DEF_CACHE_LINE) {
cache_line = DEF_CACHE_LINE;
gPci->write_pci_config(info->bus, info->device, info->function,
PCI_line_size, 1, cache_line);
}
TRACE("latency timer %lx -> %lx.\n", olatency, latency);
TRACE("cache size %lx -> %lx.\n", ocache_line, cache_line);
sc->irq = gPci->read_pci_config(info->bus, info->device, info->function,
PCI_interrupt_line, 1);
if (sc->irq == 0 || sc->irq == 0xff) {
ERROR("no IRQ assigned\n");
goto err;
}
TRACE("IRQ %d\n", sc->irq);
TRACE("hardware register address %lx\n", info->u.h0.base_registers[0]);
sc->regArea = map_mem(&sc->regAddr, (void *)info->u.h0.base_registers[0], 0x800,
B_READ_AREA | B_WRITE_AREA, "fw ohci register");
if (sc->regArea < B_OK) {
ERROR("can't map hardware registers\n");
goto err;
}
TRACE("mapped registers to %p\n", sc->regAddr);
if (install_io_interrupt_handler(sc->irq, fwohci_intr,
sc, 0) < B_OK) {
ERROR("can't install interrupt handler\n");
goto err;
}
if (fwohci_init(sc) < B_OK){
ERROR("fwohci_init failed");
goto err;
}
fwohci_pci_add_child(index);
return B_OK;
err:
delete_area(sc->regArea);
mtx_destroy(FW_GMTX(&sc->fc));
return B_ERROR;
}