1 /*- 2 * Copyright (C) 2017 Olivier Houchard 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/buf.h> 31 #include <sys/bus.h> 32 #include <sys/conf.h> 33 #include <sys/proc.h> 34 #include <sys/smp.h> 35 36 #include "nvme_private.h" 37 38 static int nvme_ahci_probe(device_t dev); 39 static int nvme_ahci_attach(device_t dev); 40 static int nvme_ahci_detach(device_t dev); 41 42 static device_method_t nvme_ahci_methods[] = { 43 /* Device interface */ 44 DEVMETHOD(device_probe, nvme_ahci_probe), 45 DEVMETHOD(device_attach, nvme_ahci_attach), 46 DEVMETHOD(device_detach, nvme_ahci_detach), 47 DEVMETHOD(device_shutdown, nvme_shutdown), 48 { 0, 0 } 49 }; 50 51 static driver_t nvme_ahci_driver = { 52 "nvme", 53 nvme_ahci_methods, 54 sizeof(struct nvme_controller), 55 }; 56 57 DRIVER_MODULE(nvme, ahci, nvme_ahci_driver, nvme_devclass, NULL, 0); 58 MODULE_VERSION(nvme_ahci, 1); 59 60 static int 61 nvme_ahci_probe (device_t device) 62 { 63 return (0); 64 } 65 66 static int 67 nvme_ahci_attach(device_t dev) 68 { 69 struct nvme_controller*ctrlr = DEVICE2SOFTC(dev); 70 int ret; 71 72 /* Map MMIO registers */ 73 ctrlr->resource_id = 0; 74 75 ctrlr->resource = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 76 &ctrlr->resource_id, RF_ACTIVE); 77 78 if(ctrlr->resource == NULL) { 79 nvme_printf(ctrlr, "unable to allocate mem resource\n"); 80 ret = ENOMEM; 81 goto bad; 82 } 83 ctrlr->bus_tag = rman_get_bustag(ctrlr->resource); 84 ctrlr->bus_handle = rman_get_bushandle(ctrlr->resource); 85 ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle; 86 87 /* Allocate and setup IRQ */ 88 ctrlr->rid = 0; 89 ctrlr->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 90 &ctrlr->rid, RF_SHAREABLE | RF_ACTIVE); 91 92 if (ctrlr->res == NULL) { 93 nvme_printf(ctrlr, "unable to allocate shared IRQ\n"); 94 ret = ENOMEM; 95 goto bad; 96 } 97 98 ctrlr->msix_enabled = 0; 99 ctrlr->num_io_queues = 1; 100 ctrlr->num_cpus_per_ioq = mp_ncpus; 101 if (bus_setup_intr(dev, ctrlr->res, 102 INTR_TYPE_MISC | INTR_MPSAFE, NULL, nvme_ctrlr_intx_handler, 103 ctrlr, &ctrlr->tag) != 0) { 104 nvme_printf(ctrlr, "unable to setup intx handler\n"); 105 ret = ENOMEM; 106 goto bad; 107 } 108 ctrlr->tag = (void *)0x1; 109 110 return nvme_attach(dev); 111 bad: 112 if (ctrlr->resource != NULL) { 113 bus_release_resource(dev, SYS_RES_MEMORY, 114 ctrlr->resource_id, ctrlr->resource); 115 } 116 if (ctrlr->res) 117 bus_release_resource(ctrlr->dev, SYS_RES_IRQ, 118 rman_get_rid(ctrlr->res), ctrlr->res); 119 return (ret); 120 } 121 122 static int 123 nvme_ahci_detach(device_t dev) 124 { 125 126 return (nvme_detach(dev)); 127 } 128