2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
34 #define OCS_COPYRIGHT "Copyright (C) 2017 Broadcom. All rights reserved."
38 * Implementation of required FreeBSD PCI interface functions
43 #include <sys/sysctl.h>
44 #include <sys/malloc.h>
46 static MALLOC_DEFINE(M_OCS, "OCS", "OneCore Storage data");
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
51 #include <machine/bus.h>
54 * Tunable parameters for transport
59 int loglevel = LOG_INFO;
60 int ramlog_size = 1*1024*1024;
61 int ddump_saved_size = 0;
62 static const char *queue_topology = "eq cq rq cq mq $nulp($nwq(cq wq:ulp=$rpt1)) cq wq:len=256:class=1";
64 static void ocs_release_bus(struct ocs_softc *);
65 static int32_t ocs_intr_alloc(struct ocs_softc *);
66 static int32_t ocs_intr_setup(struct ocs_softc *);
67 static int32_t ocs_intr_teardown(struct ocs_softc *);
68 static int ocs_pci_intx_filter(void *);
69 static void ocs_pci_intr(void *);
70 static int32_t ocs_init_dma_tag(struct ocs_softc *ocs);
72 static int32_t ocs_setup_fcports(ocs_t *ocs);
74 ocs_t *ocs_devices[MAX_OCS_DEVICES];
77 * @brief Check support for the given device
79 * Determine support for a given device by examining the PCI vendor and
82 * @param dev device abstraction
84 * @return 0 if device is supported, ENXIO otherwise
87 ocs_pci_probe(device_t dev)
91 if (pci_get_vendor(dev) != PCI_VENDOR_EMULEX) {
95 switch (pci_get_device(dev)) {
96 case PCI_PRODUCT_EMULEX_OCE16001:
97 desc = "Emulex LightPulse FC Adapter";
99 case PCI_PRODUCT_EMULEX_LPE31004:
100 desc = "Emulex LightPulse FC Adapter";
102 case PCI_PRODUCT_EMULEX_OCE50102:
103 desc = "Emulex LightPulse 10GbE FCoE/NIC Adapter";
109 device_set_desc(dev, desc);
111 return BUS_PROBE_DEFAULT;
115 ocs_map_bars(device_t dev, struct ocs_softc *ocs)
119 * Map PCI BAR0 register into the CPU's space.
122 ocs->reg[0].rid = PCIR_BAR(PCI_64BIT_BAR0);
123 ocs->reg[0].res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
124 &ocs->reg[0].rid, RF_ACTIVE);
126 if (ocs->reg[0].res == NULL) {
127 device_printf(dev, "bus_alloc_resource failed rid=%#x\n",
132 ocs->reg[0].btag = rman_get_bustag(ocs->reg[0].res);
133 ocs->reg[0].bhandle = rman_get_bushandle(ocs->reg[0].res);
138 ocs_setup_params(struct ocs_softc *ocs)
141 const char *hw_war_version;
142 /* Setup tunable parameters */
143 ocs->ctrlmask = ctrlmask;
146 ocs->ethernet_license = 0;
147 ocs->num_scsi_ios = 8192;
149 ocs->hlm_group_size = 8;
150 ocs->logmask = logmask;
152 ocs->config_tgt = FALSE;
153 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
156 ocs->config_tgt = TRUE;
157 device_printf(ocs->dev, "Enabling target\n");
161 ocs->config_ini = TRUE;
162 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
165 ocs->config_ini = FALSE;
166 device_printf(ocs->dev, "Disabling initiator\n");
169 ocs->enable_ini = ocs->config_ini;
171 if (!ocs->config_ini && !ocs->config_tgt) {
172 device_printf(ocs->dev, "Unsupported, both initiator and target mode disabled.\n");
176 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
177 "logmask", &logmask)) {
178 device_printf(ocs->dev, "logmask = %#x\n", logmask);
181 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
182 "logdest", &logdest)) {
183 device_printf(ocs->dev, "logdest = %#x\n", logdest);
186 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
187 "loglevel", &loglevel)) {
188 device_printf(ocs->dev, "loglevel = %#x\n", loglevel);
191 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
192 "ramlog_size", &ramlog_size)) {
193 device_printf(ocs->dev, "ramlog_size = %#x\n", ramlog_size);
196 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
197 "ddump_saved_size", &ddump_saved_size)) {
198 device_printf(ocs->dev, "ddump_saved_size= %#x\n", ddump_saved_size);
201 /* If enabled, initailize a RAM logging buffer */
203 ocs->ramlog = ocs_ramlog_init(ocs, ramlog_size/OCS_RAMLOG_DEFAULT_BUFFERS,
204 OCS_RAMLOG_DEFAULT_BUFFERS);
205 /* If NULL was returned, then we'll simply skip using the ramlog but */
206 /* set logdest to 1 to ensure that we at least get default logging. */
207 if (ocs->ramlog == NULL) {
212 /* initialize a saved ddump */
213 if (ddump_saved_size) {
214 if (ocs_textbuf_alloc(ocs, &ocs->ddump_saved, ddump_saved_size)) {
215 ocs_log_err(ocs, "failed to allocate memory for saved ddump\n");
219 if (0 == resource_string_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
220 "hw_war_version", &hw_war_version)) {
221 device_printf(ocs->dev, "hw_war_version = %s\n", hw_war_version);
222 ocs->hw_war_version = strdup(hw_war_version, M_OCS);
225 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
226 "explicit_buffer_list", &i)) {
227 ocs->explicit_buffer_list = i;
230 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
231 "ethernet_license", &i)) {
232 ocs->ethernet_license = i;
235 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
237 device_printf(ocs->dev, "speed = %d Mbps\n", i);
240 ocs->desc = device_get_desc(ocs->dev);
242 ocs_device_lock_init(ocs);
243 ocs->driver_version = STR_BE_MAJOR "." STR_BE_MINOR "." STR_BE_BUILD "." STR_BE_BRANCH;
244 ocs->model = ocs_pci_model(ocs->pci_vendor, ocs->pci_device);
246 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
248 device_printf(ocs->dev, "enable_hlm = %d\n", i);
250 if (ocs->enable_hlm) {
251 ocs->hlm_group_size = 8;
253 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
254 "hlm_group_size", &i)) {
255 ocs->hlm_group_size = i;
257 device_printf(ocs->dev, "hlm_group_size = %d\n", i);
261 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
262 "num_scsi_ios", &i)) {
263 ocs->num_scsi_ios = i;
264 device_printf(ocs->dev, "num_scsi_ios = %d\n", ocs->num_scsi_ios);
266 ocs->num_scsi_ios = 8192;
269 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
272 device_printf(ocs->dev, "Setting topology=%#x\n", i);
275 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
277 if (i >= 0 && i <= 254) {
278 device_printf(ocs->dev, "num_vports = %d\n", i);
281 device_printf(ocs->dev, "num_vports: %d not supported \n", i);
285 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
286 "external_loopback", &i)) {
287 device_printf(ocs->dev, "external_loopback = %d\n", i);
288 ocs->external_loopback = i;
291 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
292 "tgt_rscn_delay", &i)) {
293 device_printf(ocs->dev, "tgt_rscn_delay = %d\n", i);
294 ocs->tgt_rscn_delay_msec = i * 1000;
297 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
298 "tgt_rscn_period", &i)) {
299 device_printf(ocs->dev, "tgt_rscn_period = %d\n", i);
300 ocs->tgt_rscn_period_msec = i * 1000;
303 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev),
304 "target_io_timer", &i)) {
305 device_printf(ocs->dev, "target_io_timer = %d\n", i);
306 ocs->target_io_timer_sec = i;
309 hw_global.queue_topology_string = queue_topology;
310 ocs->rq_selection_policy = 0;
312 ocs->filter_def = "0,0,0,0";
318 ocs_setup_fcports(ocs_t *ocs)
320 uint32_t i = 0, role = 0;
321 uint64_t sli_wwpn, sli_wwnn;
323 ocs_xport_t *xport = ocs->xport;
324 ocs_vport_spec_t *vport;
325 ocs_fcport *fcp = NULL;
327 size = sizeof(ocs_fcport) * (ocs->num_vports + 1);
329 ocs->fcports = ocs_malloc(ocs, size, M_ZERO|M_NOWAIT);
330 if (ocs->fcports == NULL) {
331 device_printf(ocs->dev, "Can't allocate fcport \n");
335 role = (ocs->enable_ini)? KNOB_ROLE_INITIATOR: 0 |
336 (ocs->enable_tgt)? KNOB_ROLE_TARGET: 0;
338 fcp = FCPORT(ocs, i);
342 ocs_list_foreach(&xport->vport_list, vport) {
343 fcp = FCPORT(ocs, i);
344 vport->tgt_data = fcp;
348 if (ocs_hw_get_def_wwn(ocs, i, &sli_wwpn, &sli_wwnn)) {
349 ocs_log_err(ocs, "Get default wwn failed \n");
354 vport->wwpn = ocs_be64toh(sli_wwpn);
355 vport->wwnn = ocs_be64toh(sli_wwnn);
357 ocs_log_debug(ocs, "VPort wwpn: %lx wwnn: %lx \n", vport->wwpn, vport->wwnn);
364 ocs_device_attach(ocs_t *ocs)
370 ocs_log_warn(ocs, "%s: Device is already attached\n", __func__);
374 /* Allocate transport object and bring online */
375 ocs->xport = ocs_xport_alloc(ocs);
376 if (ocs->xport == NULL) {
377 device_printf(ocs->dev, "failed to allocate transport object\n");
379 } else if (ocs_xport_attach(ocs->xport) != 0) {
380 device_printf(ocs->dev, "%s: failed to attach transport object\n", __func__);
381 goto fail_xport_attach;
382 } else if (ocs_xport_initialize(ocs->xport) != 0) {
383 device_printf(ocs->dev, "%s: failed to initialize transport object\n", __func__);
384 goto fail_xport_init;
387 if (ocs_init_dma_tag(ocs)) {
388 goto fail_intr_setup;
391 for (i = 0; (io = ocs_io_get_instance(ocs, i)); i++) {
392 if (bus_dmamap_create(ocs->buf_dmat, 0, &io->tgt_io.dmap)) {
393 device_printf(ocs->dev, "%s: bad dma map create\n", __func__);
396 io->tgt_io.state = OCS_CAM_IO_FREE;
399 if (ocs_setup_fcports(ocs)) {
400 device_printf(ocs->dev, "FCports creation failed\n");
401 goto fail_intr_setup;
404 if(ocs_cam_attach(ocs)) {
405 device_printf(ocs->dev, "cam attach failed \n");
406 goto fail_intr_setup;
409 if (ocs_intr_setup(ocs)) {
410 device_printf(ocs->dev, "Interrupt setup failed\n");
411 goto fail_intr_setup;
414 if (ocs->enable_ini || ocs->enable_tgt) {
415 if (ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE)) {
416 device_printf(ocs->dev, "Can't init port\n");
417 goto fail_xport_online;
421 ocs->attached = true;
426 if (ocs_xport_control(ocs->xport, OCS_XPORT_SHUTDOWN)) {
427 device_printf(ocs->dev, "Transport Shutdown timed out\n");
429 ocs_intr_teardown(ocs);
432 ocs_xport_detach(ocs->xport);
434 ocs_scsi_tgt_del_device(ocs);
436 ocs_xport_free(ocs->xport);
440 ocs_free(ocs, ocs->xport, sizeof(*(ocs->xport)));
446 * @brief Connect the driver to the given device
448 * If the probe routine is successful, the OS will give the driver
449 * the opportunity to connect itself to the device. This routine
450 * maps PCI resources (memory BARs and interrupts) and initialize a
453 * @param dev device abstraction
455 * @return 0 if the driver attaches to the device, ENXIO otherwise
459 ocs_pci_attach(device_t dev)
461 struct ocs_softc *ocs;
464 instance = device_get_unit(dev);
466 ocs = (struct ocs_softc *)device_get_softc(dev);
468 device_printf(dev, "cannot allocate softc\n");
471 memset(ocs, 0, sizeof(struct ocs_softc));
473 if (instance < ARRAY_SIZE(ocs_devices)) {
474 ocs_devices[instance] = ocs;
476 device_printf(dev, "got unexpected ocs instance number %d\n", instance);
479 ocs->instance_index = instance;
483 pci_enable_io(dev, SYS_RES_MEMORY);
484 pci_enable_busmaster(dev);
486 ocs->pci_vendor = pci_get_vendor(dev);
487 ocs->pci_device = pci_get_device(dev);
488 snprintf(ocs->businfo, sizeof(ocs->businfo), "%02X:%02X:%02X",
489 pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
491 /* Map all memory BARs */
492 if (ocs_map_bars(dev, ocs)) {
493 device_printf(dev, "Failed to map pci bars\n");
497 /* create a root DMA tag for the device */
498 if (bus_dma_tag_create(bus_get_dma_tag(dev),
499 1, /* byte alignment */
500 0, /* no boundary restrictions */
501 BUS_SPACE_MAXADDR, /* no minimum low address */
502 BUS_SPACE_MAXADDR, /* no maximum high address */
503 NULL, /* no filter function */
504 NULL, /* or arguments */
505 BUS_SPACE_MAXSIZE, /* max size covered by tag */
506 BUS_SPACE_UNRESTRICTED, /* no segment count restrictions */
507 BUS_SPACE_MAXSIZE, /* no segment length restrictions */
509 NULL, /* no lock manipulation function */
510 NULL, /* or arguments */
512 device_printf(dev, "parent DMA tag allocation failed\n");
516 if (ocs_intr_alloc(ocs)) {
517 device_printf(dev, "Interrupt allocation failed\n");
521 if (PCIC_SERIALBUS == pci_get_class(dev) &&
522 PCIS_SERIALBUS_FC == pci_get_subclass(dev))
523 ocs->ocs_xport = OCS_XPORT_FC;
525 device_printf(dev, "unsupported class (%#x : %#x)\n",
531 /* Setup tunable parameters */
532 if (ocs_setup_params(ocs)) {
533 device_printf(ocs->dev, "failed to setup params\n");
537 if (ocs_device_attach(ocs)) {
538 device_printf(ocs->dev, "failed to attach device\n");
542 ocs->fc_type = FC_TYPE_FCP;
544 ocs_debug_attach(ocs);
549 ocs_ramlog_free(ocs, ocs->ramlog);
550 ocs_device_lock_free(ocs);
551 free(ocs->hw_war_version, M_OCS);
553 ocs_release_bus(ocs);
558 * @brief free resources when pci device detach
560 * @param ocs pointer to ocs structure
562 * @return 0 for success, a negative error code value for failure.
566 ocs_device_detach(ocs_t *ocs)
572 if (!ocs->attached) {
573 ocs_log_warn(ocs, "%s: Device is not attached\n", __func__);
577 ocs->attached = FALSE;
579 rc = ocs_xport_control(ocs->xport, OCS_XPORT_SHUTDOWN);
581 ocs_log_err(ocs, "%s: Transport Shutdown timed out\n", __func__);
584 ocs_intr_teardown(ocs);
586 if (ocs_xport_detach(ocs->xport) != 0) {
587 ocs_log_err(ocs, "%s: Transport detach failed\n", __func__);
591 ocs_free(ocs, ocs->fcports, sizeof(*(ocs->fcports)));
593 for (i = 0; (io = ocs_io_get_instance(ocs, i)); i++) {
594 if (bus_dmamap_destroy(ocs->buf_dmat, io->tgt_io.dmap)) {
595 device_printf(ocs->dev, "%s: bad dma map destroy\n", __func__);
598 bus_dma_tag_destroy(ocs->dmat);
599 ocs_xport_free(ocs->xport);
607 * @brief Detach the driver from the given device
609 * If the driver is a loadable module, this routine gets called at unload
610 * time. This routine will stop the device and free any allocated resources.
612 * @param dev device abstraction
614 * @return 0 if the driver detaches from the device, ENXIO otherwise
617 ocs_pci_detach(device_t dev)
619 struct ocs_softc *ocs;
621 ocs = (struct ocs_softc *)device_get_softc(dev);
623 device_printf(dev, "no driver context?!?\n");
627 if (ocs->config_tgt && ocs->enable_tgt) {
628 device_printf(dev, "can't detach with target mode enabled\n");
632 ocs_device_detach(ocs);
635 * Workaround for OCS SCSI Transport quirk.
637 * CTL requires that target mode is disabled prior to unloading the
638 * driver (ie ocs->enable_tgt = FALSE), but once the target is disabled,
639 * the transport will not call ocs_scsi_tgt_del_device() which deallocates
640 * CAM resources. The workaround is to explicitly make the call here.
643 ocs_scsi_tgt_del_device(ocs);
645 /* free strdup created buffer.*/
646 free(ocs->hw_war_version, M_OCS);
648 ocs_device_lock_free(ocs);
650 ocs_debug_detach(ocs);
652 ocs_ramlog_free(ocs, ocs->ramlog);
654 ocs_release_bus(ocs);
660 * @brief Notify driver of system shutdown
662 * @param dev device abstraction
664 * @return 0 if the driver attaches to the device, ENXIO otherwise
667 ocs_pci_shutdown(device_t dev)
669 device_printf(dev, "%s\n", __func__);
674 * @brief Release bus resources allocated within the soft context
676 * @param ocs Pointer to the driver's context
681 ocs_release_bus(struct ocs_softc *ocs)
687 ocs_intr_teardown(ocs);
690 bus_release_resource(ocs->dev, SYS_RES_IRQ,
691 rman_get_rid(ocs->irq), ocs->irq);
694 pci_release_msi(ocs->dev);
701 bus_dma_tag_destroy(ocs->dmat);
703 for (i = 0; i < PCI_MAX_BAR; i++) {
704 if (ocs->reg[i].res) {
705 bus_release_resource(ocs->dev, SYS_RES_MEMORY,
714 * @brief Allocate and initialize interrupts
716 * @param ocs Pointer to the driver's context
721 ocs_intr_alloc(struct ocs_softc *ocs)
725 if (pci_alloc_msix(ocs->dev, &ocs->n_vec)) {
726 device_printf(ocs->dev, "MSI-X allocation failed\n");
727 if (pci_alloc_msi(ocs->dev, &ocs->n_vec)) {
728 device_printf(ocs->dev, "MSI allocation failed \n");
737 ocs->irq = bus_alloc_resource_any(ocs->dev, SYS_RES_IRQ, &ocs->irqid,
738 RF_ACTIVE | RF_SHAREABLE);
739 if (NULL == ocs->irq) {
740 device_printf(ocs->dev, "could not allocate interrupt\n");
744 ocs->intr_ctx.vec = 0;
745 ocs->intr_ctx.softc = ocs;
746 snprintf(ocs->intr_ctx.name, sizeof(ocs->intr_ctx.name),
748 device_get_nameunit(ocs->dev),
755 * @brief Create and attach an interrupt handler
757 * @param ocs Pointer to the driver's context
759 * @return 0 on success, non-zero otherwise
762 ocs_intr_setup(struct ocs_softc *ocs)
764 driver_filter_t *filter = NULL;
766 if (0 == ocs->n_vec) {
767 filter = ocs_pci_intx_filter;
770 if (bus_setup_intr(ocs->dev, ocs->irq, INTR_MPSAFE | INTR_TYPE_CAM,
771 filter, ocs_pci_intr, &ocs->intr_ctx,
773 device_printf(ocs->dev, "could not initialize interrupt\n");
781 * @brief Detach an interrupt handler
783 * @param ocs Pointer to the driver's context
785 * @return 0 on success, non-zero otherwise
788 ocs_intr_teardown(struct ocs_softc *ocs)
792 printf("%s: bad driver context?!?\n", __func__);
797 bus_teardown_intr(ocs->dev, ocs->irq, ocs->tag);
805 * @brief PCI interrupt handler
807 * @param arg pointer to the driver's software context
809 * @return FILTER_HANDLED if interrupt is processed, FILTER_STRAY otherwise
812 ocs_pci_intx_filter(void *arg)
814 ocs_intr_ctx_t *intr = arg;
815 struct ocs_softc *ocs = NULL;
823 #ifndef PCIM_STATUS_INTR
824 #define PCIM_STATUS_INTR 0x0008
826 val = pci_read_config(ocs->dev, PCIR_STATUS, 2);
828 device_printf(ocs->dev, "%s: pci_read_config(PCIR_STATUS) failed\n", __func__);
831 if (0 == (val & PCIM_STATUS_INTR)) {
835 val = pci_read_config(ocs->dev, PCIR_COMMAND, 2);
836 val |= PCIM_CMD_INTxDIS;
837 pci_write_config(ocs->dev, PCIR_COMMAND, val, 2);
839 return FILTER_SCHEDULE_THREAD;
843 * @brief interrupt handler
845 * @param context pointer to the interrupt context
848 ocs_pci_intr(void *context)
850 ocs_intr_ctx_t *intr = context;
851 struct ocs_softc *ocs = intr->softc;
853 mtx_lock(&ocs->sim_lock);
854 ocs_hw_process(&ocs->hw, intr->vec, OCS_OS_MAX_ISR_TIME_MSEC);
855 mtx_unlock(&ocs->sim_lock);
859 * @brief Initialize DMA tag
861 * @param ocs the driver instance's software context
863 * @return 0 on success, non-zero otherwise
866 ocs_init_dma_tag(struct ocs_softc *ocs)
868 uint32_t max_sgl = 0;
869 uint32_t max_sge = 0;
872 * IOs can't use the parent DMA tag and must create their
873 * own, based primarily on a restricted number of DMA segments.
874 * This is more of a BSD requirement than a SLI Port requirement
876 ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &max_sgl);
877 ocs_hw_get(&ocs->hw, OCS_HW_MAX_SGE, &max_sge);
879 if (bus_dma_tag_create(ocs->dmat,
880 1, /* byte alignment */
881 0, /* no boundary restrictions */
882 BUS_SPACE_MAXADDR, /* no minimum low address */
883 BUS_SPACE_MAXADDR, /* no maximum high address */
884 NULL, /* no filter function */
885 NULL, /* or arguments */
886 BUS_SPACE_MAXSIZE, /* max size covered by tag */
887 max_sgl, /* segment count restrictions */
888 max_sge, /* segment length restrictions */
890 NULL, /* no lock manipulation function */
891 NULL, /* or arguments */
893 device_printf(ocs->dev, "%s: bad bus_dma_tag_create(buf_dmat)\n", __func__);
900 ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len)
906 * @brief return pointer to ocs structure given instance index
908 * A pointer to an ocs structure is returned given an instance index.
910 * @param index index to ocs_devices array
912 * @return ocs pointer
915 ocs_t *ocs_get_instance(uint32_t index)
917 if (index < ARRAY_SIZE(ocs_devices)) {
918 return ocs_devices[index];
924 * @brief Return instance index of an opaque ocs structure
926 * Returns the ocs instance index
928 * @param os pointer to ocs instance
930 * @return pointer to ocs instance index
933 ocs_instance(void *os)
936 return ocs->instance_index;
939 static device_method_t ocs_methods[] = {
940 DEVMETHOD(device_probe, ocs_pci_probe),
941 DEVMETHOD(device_attach, ocs_pci_attach),
942 DEVMETHOD(device_detach, ocs_pci_detach),
943 DEVMETHOD(device_shutdown, ocs_pci_shutdown),
947 static driver_t ocs_driver = {
950 sizeof(struct ocs_softc)
953 static devclass_t ocs_devclass;
955 DRIVER_MODULE(ocs_fc, pci, ocs_driver, ocs_devclass, 0, 0);
956 MODULE_VERSION(ocs_fc, 1);