#include "nvme.h"
static int nvme_probe (device_t dev);
static int nvme_attach (device_t dev);
static int nvme_detach (device_t dev);
static int nvme_shutdown (device_t dev);
#if 0
static int nvme_suspend (device_t dev);
static int nvme_resume (device_t dev);
#endif
static device_method_t nvme_methods[] = {
DEVMETHOD(device_probe, nvme_probe),
DEVMETHOD(device_attach, nvme_attach),
DEVMETHOD(device_detach, nvme_detach),
DEVMETHOD(device_shutdown, nvme_shutdown),
#if 0
DEVMETHOD(device_suspend, nvme_suspend),
DEVMETHOD(device_resume, nvme_resume),
#endif
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD_END
};
static devclass_t nvme_devclass;
static driver_t nvme_driver = {
"nvme",
nvme_methods,
sizeof(nvme_softc_t)
};
DRIVER_MODULE(nvme, pci, nvme_driver, nvme_devclass, NULL, NULL);
MODULE_VERSION(nvme, 1);
static int
nvme_probe(device_t dev)
{
const nvme_device_t *ad;
if (kgetenv("hint.nvme.disabled"))
return(ENXIO);
ad = nvme_lookup_device(dev);
if (ad) {
device_set_desc(dev, ad->name);
return(-5);
}
return(ENXIO);
}
static int
nvme_attach(device_t dev)
{
nvme_softc_t *sc = device_get_softc(dev);
int error;
sc->dev = dev;
sc->ad = nvme_lookup_device(dev);
if (sc->ad == NULL)
return(ENXIO);
KKASSERT(sizeof(nvme_admin_data_t) == NVME_MAX_ADMIN_BUFFER);
KKASSERT(sizeof(nvme_allres_t) == 16);
KKASSERT(sizeof(nvme_allcmd_t) == 64);
error = sc->ad->attach(dev);
return error;
}
static int
nvme_detach(device_t dev)
{
nvme_softc_t *sc = device_get_softc(dev);
int error = 0;
if (sc->ad) {
error = sc->ad->detach(dev);
sc->ad = NULL;
}
return(error);
}
static int
nvme_shutdown(device_t dev)
{
return nvme_detach(dev);
}
#if 0
static int
nvme_suspend(device_t dev)
{
return (0);
}
static int
nvme_resume(device_t dev)
{
return (0);
}
#endif
u_int32_t
nvme_read(nvme_softc_t *sc, bus_size_t r)
{
bus_space_barrier(sc->iot, sc->ioh, r, 4,
BUS_SPACE_BARRIER_READ);
return (bus_space_read_4(sc->iot, sc->ioh, r));
}
u_int64_t
nvme_read8(nvme_softc_t *sc, bus_size_t r)
{
bus_space_barrier(sc->iot, sc->ioh, r, 8,
BUS_SPACE_BARRIER_READ);
return (bus_space_read_8(sc->iot, sc->ioh, r));
}
void
nvme_write(nvme_softc_t *sc, bus_size_t r, u_int32_t v)
{
bus_space_write_4(sc->iot, sc->ioh, r, v);
bus_space_barrier(sc->iot, sc->ioh, r, 4,
BUS_SPACE_BARRIER_WRITE);
}
void
nvme_write8(nvme_softc_t *sc, bus_size_t r, u_int64_t v)
{
bus_space_write_8(sc->iot, sc->ioh, r, v);
bus_space_barrier(sc->iot, sc->ioh, r, 8,
BUS_SPACE_BARRIER_WRITE);
}
void
nvme_os_sleep(int ms)
{
int slpticks;
slpticks = hz * ms / 1000 + 1;
tsleep(&slpticks, 0, "nvslp", slpticks);
}
int
nvme_os_softsleep(void)
{
int slpticks = 0;
if (hz >= 1000) {
tsleep(&slpticks, 0, "nvslp", hz / 1000);
return(1);
} else {
tsleep(&slpticks, 0, "nvslp", 1);
return(1000 / hz);
}
}
void
nvme_os_hardsleep(int us)
{
DELAY(us);
}