193289cfcSWarner Losh /*- 293289cfcSWarner Losh * Copyright (C) 2017 Olivier Houchard 393289cfcSWarner Losh * 493289cfcSWarner Losh * Redistribution and use in source and binary forms, with or without 593289cfcSWarner Losh * modification, are permitted provided that the following conditions 693289cfcSWarner Losh * are met: 793289cfcSWarner Losh * 1. Redistributions of source code must retain the above copyright 893289cfcSWarner Losh * notice, this list of conditions and the following disclaimer. 993289cfcSWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 1093289cfcSWarner Losh * notice, this list of conditions and the following disclaimer in the 1193289cfcSWarner Losh * documentation and/or other materials provided with the distribution. 1293289cfcSWarner Losh * 1393289cfcSWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1493289cfcSWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1593289cfcSWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1693289cfcSWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1793289cfcSWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1893289cfcSWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1993289cfcSWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2093289cfcSWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2193289cfcSWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2293289cfcSWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2393289cfcSWarner Losh * SUCH DAMAGE. 2493289cfcSWarner Losh */ 2593289cfcSWarner Losh 2693289cfcSWarner Losh #include <sys/cdefs.h> 2793289cfcSWarner Losh __FBSDID("$FreeBSD$"); 2893289cfcSWarner Losh #include <sys/param.h> 2993289cfcSWarner Losh #include <sys/systm.h> 3093289cfcSWarner Losh #include <sys/buf.h> 3193289cfcSWarner Losh #include <sys/bus.h> 3293289cfcSWarner Losh #include <sys/conf.h> 3393289cfcSWarner Losh #include <sys/proc.h> 3493289cfcSWarner Losh #include <sys/smp.h> 3593289cfcSWarner Losh 3693289cfcSWarner Losh #include "nvme_private.h" 3793289cfcSWarner Losh 3893289cfcSWarner Losh static int nvme_ahci_probe(device_t dev); 3993289cfcSWarner Losh static int nvme_ahci_attach(device_t dev); 4093289cfcSWarner Losh static int nvme_ahci_detach(device_t dev); 4193289cfcSWarner Losh 4293289cfcSWarner Losh static device_method_t nvme_ahci_methods[] = { 4393289cfcSWarner Losh /* Device interface */ 4493289cfcSWarner Losh DEVMETHOD(device_probe, nvme_ahci_probe), 4593289cfcSWarner Losh DEVMETHOD(device_attach, nvme_ahci_attach), 4693289cfcSWarner Losh DEVMETHOD(device_detach, nvme_ahci_detach), 4793289cfcSWarner Losh DEVMETHOD(device_shutdown, nvme_shutdown), 4893289cfcSWarner Losh { 0, 0 } 4993289cfcSWarner Losh }; 5093289cfcSWarner Losh 5193289cfcSWarner Losh static driver_t nvme_ahci_driver = { 5293289cfcSWarner Losh "nvme", 5393289cfcSWarner Losh nvme_ahci_methods, 5493289cfcSWarner Losh sizeof(struct nvme_controller), 5593289cfcSWarner Losh }; 5693289cfcSWarner Losh 5793289cfcSWarner Losh DRIVER_MODULE(nvme, ahci, nvme_ahci_driver, nvme_devclass, NULL, 0); 5893289cfcSWarner Losh 5993289cfcSWarner Losh static int 6093289cfcSWarner Losh nvme_ahci_probe (device_t device) 6193289cfcSWarner Losh { 6293289cfcSWarner Losh return (0); 6393289cfcSWarner Losh } 6493289cfcSWarner Losh 6593289cfcSWarner Losh static int 6693289cfcSWarner Losh nvme_ahci_attach(device_t dev) 6793289cfcSWarner Losh { 6893289cfcSWarner Losh struct nvme_controller*ctrlr = DEVICE2SOFTC(dev); 6993289cfcSWarner Losh int ret; 7093289cfcSWarner Losh 7193289cfcSWarner Losh /* Map MMIO registers */ 7293289cfcSWarner Losh ctrlr->resource_id = 0; 7393289cfcSWarner Losh 7493289cfcSWarner Losh ctrlr->resource = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 7593289cfcSWarner Losh &ctrlr->resource_id, RF_ACTIVE); 7693289cfcSWarner Losh 7793289cfcSWarner Losh if(ctrlr->resource == NULL) { 7893289cfcSWarner Losh nvme_printf(ctrlr, "unable to allocate mem resource\n"); 7993289cfcSWarner Losh ret = ENOMEM; 8093289cfcSWarner Losh goto bad; 8193289cfcSWarner Losh } 8293289cfcSWarner Losh ctrlr->bus_tag = rman_get_bustag(ctrlr->resource); 8393289cfcSWarner Losh ctrlr->bus_handle = rman_get_bushandle(ctrlr->resource); 8493289cfcSWarner Losh ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle; 8593289cfcSWarner Losh 8693289cfcSWarner Losh /* Allocate and setup IRQ */ 8793289cfcSWarner Losh ctrlr->rid = 0; 8893289cfcSWarner Losh ctrlr->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 8993289cfcSWarner Losh &ctrlr->rid, RF_SHAREABLE | RF_ACTIVE); 9093289cfcSWarner Losh if (ctrlr->res == NULL) { 91*e3bdf3daSAlexander Motin nvme_printf(ctrlr, "unable to allocate shared interrupt\n"); 9293289cfcSWarner Losh ret = ENOMEM; 9393289cfcSWarner Losh goto bad; 9493289cfcSWarner Losh } 9593289cfcSWarner Losh 96*e3bdf3daSAlexander Motin ctrlr->msi_count = 0; 9793289cfcSWarner Losh ctrlr->num_io_queues = 1; 9893289cfcSWarner Losh if (bus_setup_intr(dev, ctrlr->res, 99*e3bdf3daSAlexander Motin INTR_TYPE_MISC | INTR_MPSAFE, NULL, nvme_ctrlr_shared_handler, 10093289cfcSWarner Losh ctrlr, &ctrlr->tag) != 0) { 101*e3bdf3daSAlexander Motin nvme_printf(ctrlr, "unable to setup shared interrupt\n"); 10293289cfcSWarner Losh ret = ENOMEM; 10393289cfcSWarner Losh goto bad; 10493289cfcSWarner Losh } 10593289cfcSWarner Losh ctrlr->tag = (void *)0x1; 10693289cfcSWarner Losh 10793289cfcSWarner Losh return nvme_attach(dev); 10893289cfcSWarner Losh bad: 10993289cfcSWarner Losh if (ctrlr->resource != NULL) { 11093289cfcSWarner Losh bus_release_resource(dev, SYS_RES_MEMORY, 11193289cfcSWarner Losh ctrlr->resource_id, ctrlr->resource); 11293289cfcSWarner Losh } 11393289cfcSWarner Losh if (ctrlr->res) 11493289cfcSWarner Losh bus_release_resource(ctrlr->dev, SYS_RES_IRQ, 11593289cfcSWarner Losh rman_get_rid(ctrlr->res), ctrlr->res); 11693289cfcSWarner Losh return (ret); 11793289cfcSWarner Losh } 11893289cfcSWarner Losh 11993289cfcSWarner Losh static int 12093289cfcSWarner Losh nvme_ahci_detach(device_t dev) 12193289cfcSWarner Losh { 12293289cfcSWarner Losh 12393289cfcSWarner Losh return (nvme_detach(dev)); 12493289cfcSWarner Losh } 125