135863739SMike Smith /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
435863739SMike Smith * Copyright (c) 2000 Michael Smith
5c6eafcf2SScott Long * Copyright (c) 2001 Scott Long
635863739SMike Smith * Copyright (c) 2000 BSDi
7c6eafcf2SScott Long * Copyright (c) 2001 Adaptec, Inc.
835863739SMike Smith * All rights reserved.
935863739SMike Smith *
1035863739SMike Smith * Redistribution and use in source and binary forms, with or without
1135863739SMike Smith * modification, are permitted provided that the following conditions
1235863739SMike Smith * are met:
1335863739SMike Smith * 1. Redistributions of source code must retain the above copyright
1435863739SMike Smith * notice, this list of conditions and the following disclaimer.
1535863739SMike Smith * 2. Redistributions in binary form must reproduce the above copyright
1635863739SMike Smith * notice, this list of conditions and the following disclaimer in the
1735863739SMike Smith * documentation and/or other materials provided with the distribution.
1835863739SMike Smith *
1935863739SMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2035863739SMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2135863739SMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2235863739SMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2335863739SMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2435863739SMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2535863739SMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2635863739SMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2735863739SMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2835863739SMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2935863739SMike Smith * SUCH DAMAGE.
3035863739SMike Smith */
3135863739SMike Smith
32aad970f1SDavid E. O'Brien #include <sys/cdefs.h>
33f6c4dd3fSScott Long #include "opt_aac.h"
34f6c4dd3fSScott Long
3535863739SMike Smith #include <sys/param.h>
3635863739SMike Smith #include <sys/systm.h>
3735863739SMike Smith #include <sys/kernel.h>
38fe12f24bSPoul-Henning Kamp #include <sys/module.h>
3935863739SMike Smith
4035863739SMike Smith #include <sys/bus.h>
4135863739SMike Smith #include <sys/conf.h>
4235863739SMike Smith #include <sys/disk.h>
4335863739SMike Smith
4436e0bf6eSScott Long #include <vm/vm.h>
4536e0bf6eSScott Long #include <vm/pmap.h>
4636e0bf6eSScott Long
4736e0bf6eSScott Long #include <machine/md_var.h>
4835863739SMike Smith #include <machine/bus.h>
4935863739SMike Smith #include <sys/rman.h>
5035863739SMike Smith
5135863739SMike Smith #include <dev/aac/aacreg.h>
520b0594cdSScott Long #include <sys/aac_ioctl.h>
5335863739SMike Smith #include <dev/aac/aacvar.h>
5435863739SMike Smith
5535863739SMike Smith /*
5635863739SMike Smith * Interface to parent.
5735863739SMike Smith */
5835863739SMike Smith static int aac_disk_probe(device_t dev);
5935863739SMike Smith static int aac_disk_attach(device_t dev);
6035863739SMike Smith static int aac_disk_detach(device_t dev);
6135863739SMike Smith
6235863739SMike Smith /*
6335863739SMike Smith * Interface to the device switch.
6435863739SMike Smith */
657540e65eSScott Long static disk_open_t aac_disk_open;
667540e65eSScott Long static disk_close_t aac_disk_close;
677540e65eSScott Long static disk_strategy_t aac_disk_strategy;
682c6b49f6SPoul-Henning Kamp static dumper_t aac_disk_dump;
6935863739SMike Smith
7035863739SMike Smith static device_method_t aac_disk_methods[] = {
7135863739SMike Smith DEVMETHOD(device_probe, aac_disk_probe),
7235863739SMike Smith DEVMETHOD(device_attach, aac_disk_attach),
7335863739SMike Smith DEVMETHOD(device_detach, aac_disk_detach),
74da4882c2SMarius Strobl DEVMETHOD_END
7535863739SMike Smith };
7635863739SMike Smith
7735863739SMike Smith static driver_t aac_disk_driver = {
7835863739SMike Smith "aacd",
7935863739SMike Smith aac_disk_methods,
8035863739SMike Smith sizeof(struct aac_disk)
8135863739SMike Smith };
8235863739SMike Smith
835a2ae6d0SJohn Baldwin DRIVER_MODULE(aacd, aac, aac_disk_driver, NULL, NULL);
8435863739SMike Smith
85914da7d0SScott Long /*
8635863739SMike Smith * Handle open from generic layer.
8735863739SMike Smith *
8835863739SMike Smith * This is called by the diskslice code on first open in order to get the
89453130d9SPedro F. Giffuni * basic device geometry parameters.
9035863739SMike Smith */
9135863739SMike Smith static int
aac_disk_open(struct disk * dp)927540e65eSScott Long aac_disk_open(struct disk *dp)
9335863739SMike Smith {
94914da7d0SScott Long struct aac_disk *sc;
9535863739SMike Smith
9631a0399eSEd Maste fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
9735863739SMike Smith
987540e65eSScott Long sc = (struct aac_disk *)dp->d_drv1;
99914da7d0SScott Long
100f30ac74cSScott Long if (sc == NULL) {
101f30ac74cSScott Long printf("aac_disk_open: No Softc\n");
10235863739SMike Smith return (ENXIO);
103f30ac74cSScott Long }
10435863739SMike Smith
10535863739SMike Smith /* check that the controller is up and running */
106f30ac74cSScott Long if (sc->ad_controller->aac_state & AAC_STATE_SUSPEND) {
107dbb34a64SEd Maste device_printf(sc->ad_controller->aac_dev,
108dbb34a64SEd Maste "Controller Suspended controller state = 0x%x\n",
109f30ac74cSScott Long sc->ad_controller->aac_state);
11035863739SMike Smith return(ENXIO);
111f30ac74cSScott Long }
11235863739SMike Smith
11335863739SMike Smith sc->ad_flags |= AAC_DISK_OPEN;
11435863739SMike Smith return (0);
11535863739SMike Smith }
11635863739SMike Smith
117914da7d0SScott Long /*
11835863739SMike Smith * Handle last close of the disk device.
11935863739SMike Smith */
12035863739SMike Smith static int
aac_disk_close(struct disk * dp)1217540e65eSScott Long aac_disk_close(struct disk *dp)
12235863739SMike Smith {
123914da7d0SScott Long struct aac_disk *sc;
12435863739SMike Smith
12531a0399eSEd Maste fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
12635863739SMike Smith
1277540e65eSScott Long sc = (struct aac_disk *)dp->d_drv1;
128914da7d0SScott Long
12935863739SMike Smith if (sc == NULL)
13035863739SMike Smith return (ENXIO);
13135863739SMike Smith
13235863739SMike Smith sc->ad_flags &= ~AAC_DISK_OPEN;
13335863739SMike Smith return (0);
13435863739SMike Smith }
13535863739SMike Smith
136914da7d0SScott Long /*
13735863739SMike Smith * Handle an I/O request.
13835863739SMike Smith */
13935863739SMike Smith static void
aac_disk_strategy(struct bio * bp)14035863739SMike Smith aac_disk_strategy(struct bio *bp)
14135863739SMike Smith {
142914da7d0SScott Long struct aac_disk *sc;
14335863739SMike Smith
1447540e65eSScott Long sc = (struct aac_disk *)bp->bio_disk->d_drv1;
14531a0399eSEd Maste fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
146914da7d0SScott Long
14735863739SMike Smith /* bogus disk? */
14835863739SMike Smith if (sc == NULL) {
14935863739SMike Smith bp->bio_flags |= BIO_ERROR;
15035863739SMike Smith bp->bio_error = EINVAL;
15135863739SMike Smith biodone(bp);
15235863739SMike Smith return;
15335863739SMike Smith }
15435863739SMike Smith
15536e0bf6eSScott Long /* do-nothing operation? */
15636e0bf6eSScott Long if (bp->bio_bcount == 0) {
15736e0bf6eSScott Long bp->bio_resid = bp->bio_bcount;
15836e0bf6eSScott Long biodone(bp);
15936e0bf6eSScott Long return;
16036e0bf6eSScott Long }
16136e0bf6eSScott Long
162d176b803SScott Long if ((bp->bio_cmd != BIO_READ) && (bp->bio_cmd != BIO_WRITE)) {
163d176b803SScott Long biofinish(bp, NULL, EOPNOTSUPP);
164d176b803SScott Long return;
165d176b803SScott Long }
166d176b803SScott Long
16735863739SMike Smith /* perform accounting */
16835863739SMike Smith
16935863739SMike Smith /* pass the bio to the controller - it can work out who we are */
170bb6fe253SScott Long mtx_lock(&sc->ad_controller->aac_io_lock);
17135863739SMike Smith aac_submit_bio(bp);
172bb6fe253SScott Long mtx_unlock(&sc->ad_controller->aac_io_lock);
17335863739SMike Smith }
17435863739SMike Smith
175914da7d0SScott Long /*
176cbfd045bSScott Long * Map the S/G elements for doing a dump.
177cbfd045bSScott Long */
178cbfd045bSScott Long static void
aac_dump_map_sg(void * arg,bus_dma_segment_t * segs,int nsegs,int error)179cbfd045bSScott Long aac_dump_map_sg(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
180cbfd045bSScott Long {
181cbfd045bSScott Long struct aac_fib *fib;
182cbfd045bSScott Long struct aac_blockwrite *bw;
183cbfd045bSScott Long struct aac_sg_table *sg;
184cbfd045bSScott Long int i;
185cbfd045bSScott Long
186cbfd045bSScott Long fib = (struct aac_fib *)arg;
187cbfd045bSScott Long bw = (struct aac_blockwrite *)&fib->data[0];
188cbfd045bSScott Long sg = &bw->SgMap;
189cbfd045bSScott Long
190cbfd045bSScott Long if (sg != NULL) {
191cbfd045bSScott Long sg->SgCount = nsegs;
192cbfd045bSScott Long for (i = 0; i < nsegs; i++) {
193ed339297SScott Long if (segs[i].ds_addr >= BUS_SPACE_MAXADDR_32BIT)
194ed339297SScott Long return;
195cbfd045bSScott Long sg->SgEntry[i].SgAddress = segs[i].ds_addr;
196cbfd045bSScott Long sg->SgEntry[i].SgByteCount = segs[i].ds_len;
197cbfd045bSScott Long }
198cbfd045bSScott Long fib->Header.Size = nsegs * sizeof(struct aac_sg_entry);
199cbfd045bSScott Long }
200cbfd045bSScott Long }
201cbfd045bSScott Long
202cbfd045bSScott Long /*
20377cd5850SEd Maste * Map the S/G elements for doing a dump on 64-bit capable devices.
20477cd5850SEd Maste */
20577cd5850SEd Maste static void
aac_dump_map_sg64(void * arg,bus_dma_segment_t * segs,int nsegs,int error)20677cd5850SEd Maste aac_dump_map_sg64(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
20777cd5850SEd Maste {
20877cd5850SEd Maste struct aac_fib *fib;
20977cd5850SEd Maste struct aac_blockwrite64 *bw;
21077cd5850SEd Maste struct aac_sg_table64 *sg;
21177cd5850SEd Maste int i;
21277cd5850SEd Maste
21377cd5850SEd Maste fib = (struct aac_fib *)arg;
21477cd5850SEd Maste bw = (struct aac_blockwrite64 *)&fib->data[0];
21577cd5850SEd Maste sg = &bw->SgMap64;
21677cd5850SEd Maste
21777cd5850SEd Maste if (sg != NULL) {
21877cd5850SEd Maste sg->SgCount = nsegs;
21977cd5850SEd Maste for (i = 0; i < nsegs; i++) {
22077cd5850SEd Maste sg->SgEntry64[i].SgAddress = segs[i].ds_addr;
22177cd5850SEd Maste sg->SgEntry64[i].SgByteCount = segs[i].ds_len;
22277cd5850SEd Maste }
22377cd5850SEd Maste fib->Header.Size = nsegs * sizeof(struct aac_sg_entry64);
22477cd5850SEd Maste }
22577cd5850SEd Maste }
22677cd5850SEd Maste
22777cd5850SEd Maste /*
22836e0bf6eSScott Long * Dump memory out to an array
22936e0bf6eSScott Long *
23035ea6959SJung-uk Kim * Send out one command at a time with up to maxio of data.
23136e0bf6eSScott Long */
23236e0bf6eSScott Long static int
aac_disk_dump(void * arg,void * virtual,off_t offset,size_t length)233489ba222SMitchell Horne aac_disk_dump(void *arg, void *virtual, off_t offset, size_t length)
23436e0bf6eSScott Long {
235914da7d0SScott Long struct aac_disk *ad;
23636e0bf6eSScott Long struct aac_softc *sc;
237cbfd045bSScott Long struct aac_fib *fib;
23835ea6959SJung-uk Kim size_t len, maxio;
239cbfd045bSScott Long int size;
240cbfd045bSScott Long static bus_dmamap_t dump_datamap;
241cbfd045bSScott Long static int first = 0;
2422c6b49f6SPoul-Henning Kamp struct disk *dp;
24377cd5850SEd Maste bus_dmamap_callback_t *callback;
24477cd5850SEd Maste u_int32_t command;
24536e0bf6eSScott Long
2462c6b49f6SPoul-Henning Kamp dp = arg;
2477540e65eSScott Long ad = dp->d_drv1;
24836e0bf6eSScott Long
24936e0bf6eSScott Long if (ad == NULL)
250cbfd045bSScott Long return (EINVAL);
25136e0bf6eSScott Long
25236e0bf6eSScott Long sc= ad->ad_controller;
25336e0bf6eSScott Long
254cbfd045bSScott Long if (!first) {
255cbfd045bSScott Long first = 1;
256cbfd045bSScott Long if (bus_dmamap_create(sc->aac_buffer_dmat, 0, &dump_datamap)) {
257dbb34a64SEd Maste device_printf(sc->aac_dev,
258dbb34a64SEd Maste "bus_dmamap_create failed\n");
259cbfd045bSScott Long return (ENOMEM);
26036e0bf6eSScott Long }
26136e0bf6eSScott Long }
26236e0bf6eSScott Long
26303b5fe51SScott Long /* Skip aac_alloc_sync_fib(). We don't want to mess with sleep locks */
26403b5fe51SScott Long fib = &sc->aac_common->ac_sync_fib;
26536e0bf6eSScott Long
266cbfd045bSScott Long while (length > 0) {
26735ea6959SJung-uk Kim maxio = sc->aac_max_sectors << 9;
26835ea6959SJung-uk Kim len = (length > maxio) ? maxio : length;
26977cd5850SEd Maste if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
27077cd5850SEd Maste struct aac_blockwrite *bw;
27177cd5850SEd Maste bw = (struct aac_blockwrite *)&fib->data[0];
272cbfd045bSScott Long bw->Command = VM_CtBlockWrite;
273cbfd045bSScott Long bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
274cbfd045bSScott Long bw->BlockNumber = offset / AAC_BLOCK_SIZE;
275cbfd045bSScott Long bw->ByteCount = len;
276cbfd045bSScott Long bw->Stable = CUNSTABLE;
27777cd5850SEd Maste command = ContainerCommand;
27877cd5850SEd Maste callback = aac_dump_map_sg;
27977cd5850SEd Maste size = sizeof(struct aac_blockwrite);
28077cd5850SEd Maste } else {
28177cd5850SEd Maste struct aac_blockwrite64 *bw;
28277cd5850SEd Maste bw = (struct aac_blockwrite64 *)&fib->data[0];
28377cd5850SEd Maste bw->Command = VM_CtHostWrite64;
28477cd5850SEd Maste bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
28577cd5850SEd Maste bw->BlockNumber = offset / AAC_BLOCK_SIZE;
28677cd5850SEd Maste bw->SectorCount = len / AAC_BLOCK_SIZE;
28777cd5850SEd Maste bw->Pad = 0;
28877cd5850SEd Maste bw->Flags = 0;
28977cd5850SEd Maste command = ContainerCommand64;
29077cd5850SEd Maste callback = aac_dump_map_sg64;
29177cd5850SEd Maste size = sizeof(struct aac_blockwrite64);
29277cd5850SEd Maste }
293ed339297SScott Long
294ed339297SScott Long /*
295ed339297SScott Long * There really isn't any way to recover from errors or
296ed339297SScott Long * resource shortages here. Oh well. Because of that, don't
297ed339297SScott Long * bother trying to send the command from the callback; there
298ed339297SScott Long * is too much required context.
299ed339297SScott Long */
300ed339297SScott Long if (bus_dmamap_load(sc->aac_buffer_dmat, dump_datamap, virtual,
30177cd5850SEd Maste len, callback, fib, BUS_DMA_NOWAIT) != 0)
302cbe4fd54SScott Long return (ENOMEM);
303ed339297SScott Long
304cbfd045bSScott Long bus_dmamap_sync(sc->aac_buffer_dmat, dump_datamap,
305cbfd045bSScott Long BUS_DMASYNC_PREWRITE);
30636e0bf6eSScott Long
307cbfd045bSScott Long /* fib->Header.Size is set in aac_dump_map_sg */
30877cd5850SEd Maste size += fib->Header.Size;
309cbfd045bSScott Long
31077cd5850SEd Maste if (aac_sync_fib(sc, command, 0, fib, size)) {
311dbb34a64SEd Maste device_printf(sc->aac_dev,
312489ba222SMitchell Horne "Error dumping block to 0x%jx\n",
313489ba222SMitchell Horne (uintmax_t)offset);
314cbfd045bSScott Long return (EIO);
31536e0bf6eSScott Long }
316ed339297SScott Long
317cbe4fd54SScott Long bus_dmamap_sync(sc->aac_buffer_dmat, dump_datamap,
318cbe4fd54SScott Long BUS_DMASYNC_POSTWRITE);
319cbe4fd54SScott Long
320cbe4fd54SScott Long bus_dmamap_unload(sc->aac_buffer_dmat, dump_datamap);
321cbe4fd54SScott Long
322cbfd045bSScott Long length -= len;
323cbfd045bSScott Long offset += len;
324eec256deSAlexander Kabaev virtual = (uint8_t *)virtual + len;
32536e0bf6eSScott Long }
32636e0bf6eSScott Long
32736e0bf6eSScott Long return (0);
32836e0bf6eSScott Long }
32936e0bf6eSScott Long
330914da7d0SScott Long /*
33135863739SMike Smith * Handle completion of an I/O request.
33235863739SMike Smith */
33335863739SMike Smith void
aac_biodone(struct bio * bp)3340b94a66eSMike Smith aac_biodone(struct bio *bp)
33535863739SMike Smith {
33631a0399eSEd Maste fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
337914da7d0SScott Long
338ce61627aSSean Bruno if (bp->bio_flags & BIO_ERROR) {
339ce61627aSSean Bruno bp->bio_resid = bp->bio_bcount;
340f90c382cSPoul-Henning Kamp disk_err(bp, "hard error", -1, 1);
341ce61627aSSean Bruno }
3429e2e96d8SScott Long
34335863739SMike Smith biodone(bp);
34435863739SMike Smith }
34535863739SMike Smith
346914da7d0SScott Long /*
34735863739SMike Smith * Stub only.
34835863739SMike Smith */
34935863739SMike Smith static int
aac_disk_probe(device_t dev)35035863739SMike Smith aac_disk_probe(device_t dev)
35135863739SMike Smith {
35235863739SMike Smith
35331a0399eSEd Maste fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
35435863739SMike Smith
35535863739SMike Smith return (0);
35635863739SMike Smith }
35735863739SMike Smith
358914da7d0SScott Long /*
35935863739SMike Smith * Attach a unit to the controller.
36035863739SMike Smith */
36135863739SMike Smith static int
aac_disk_attach(device_t dev)36235863739SMike Smith aac_disk_attach(device_t dev)
36335863739SMike Smith {
364914da7d0SScott Long struct aac_disk *sc;
36535863739SMike Smith
366914da7d0SScott Long sc = (struct aac_disk *)device_get_softc(dev);
36731a0399eSEd Maste fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
368914da7d0SScott Long
36935863739SMike Smith /* initialise our softc */
370c6eafcf2SScott Long sc->ad_controller =
371c6eafcf2SScott Long (struct aac_softc *)device_get_softc(device_get_parent(dev));
37235863739SMike Smith sc->ad_container = device_get_ivars(dev);
37335863739SMike Smith sc->ad_dev = dev;
37435863739SMike Smith
375c6eafcf2SScott Long /*
376c6eafcf2SScott Long * require that extended translation be enabled - other drivers read the
377c6eafcf2SScott Long * disk!
378c6eafcf2SScott Long */
37935863739SMike Smith sc->ad_size = sc->ad_container->co_mntobj.Capacity;
380523da39bSEd Maste if (sc->ad_controller->flags & AAC_FLAGS_LBA_64BIT)
381523da39bSEd Maste sc->ad_size += (u_int64_t)
382523da39bSEd Maste sc->ad_container->co_mntobj.CapacityHigh << 32;
38335863739SMike Smith if (sc->ad_size >= (2 * 1024 * 1024)) { /* 2GB */
38435863739SMike Smith sc->ad_heads = 255;
38535863739SMike Smith sc->ad_sectors = 63;
386eeba0d10SMike Smith } else if (sc->ad_size >= (1 * 1024 * 1024)) { /* 1GB */
38735863739SMike Smith sc->ad_heads = 128;
38835863739SMike Smith sc->ad_sectors = 32;
38935863739SMike Smith } else {
39035863739SMike Smith sc->ad_heads = 64;
39135863739SMike Smith sc->ad_sectors = 32;
39235863739SMike Smith }
39335863739SMike Smith sc->ad_cylinders = (sc->ad_size / (sc->ad_heads * sc->ad_sectors));
39435863739SMike Smith
395523da39bSEd Maste device_printf(dev, "%juMB (%ju sectors)\n",
396523da39bSEd Maste (intmax_t)sc->ad_size / ((1024 * 1024) / AAC_BLOCK_SIZE),
397523da39bSEd Maste (intmax_t)sc->ad_size);
39835863739SMike Smith
39935863739SMike Smith /* attach a generic disk device to ourselves */
40036e0bf6eSScott Long sc->unit = device_get_unit(dev);
4010b7ed341SPoul-Henning Kamp sc->ad_disk = disk_alloc();
4020b7ed341SPoul-Henning Kamp sc->ad_disk->d_drv1 = sc;
4038fce673cSMarius Strobl sc->ad_disk->d_flags = DISKFLAG_UNMAPPED_BIO;
4040b7ed341SPoul-Henning Kamp sc->ad_disk->d_name = "aacd";
40535ea6959SJung-uk Kim sc->ad_disk->d_maxsize = sc->ad_controller->aac_max_sectors << 9;
4060b7ed341SPoul-Henning Kamp sc->ad_disk->d_open = aac_disk_open;
4070b7ed341SPoul-Henning Kamp sc->ad_disk->d_close = aac_disk_close;
4080b7ed341SPoul-Henning Kamp sc->ad_disk->d_strategy = aac_disk_strategy;
4090b7ed341SPoul-Henning Kamp sc->ad_disk->d_dump = aac_disk_dump;
4100b7ed341SPoul-Henning Kamp sc->ad_disk->d_sectorsize = AAC_BLOCK_SIZE;
4110b7ed341SPoul-Henning Kamp sc->ad_disk->d_mediasize = (off_t)sc->ad_size * AAC_BLOCK_SIZE;
4120b7ed341SPoul-Henning Kamp sc->ad_disk->d_fwsectors = sc->ad_sectors;
4130b7ed341SPoul-Henning Kamp sc->ad_disk->d_fwheads = sc->ad_heads;
4140b7ed341SPoul-Henning Kamp sc->ad_disk->d_unit = sc->unit;
4150b7ed341SPoul-Henning Kamp disk_create(sc->ad_disk, DISK_VERSION);
41635863739SMike Smith
41735863739SMike Smith return (0);
41835863739SMike Smith }
41935863739SMike Smith
420914da7d0SScott Long /*
42135863739SMike Smith * Disconnect ourselves from the system.
42235863739SMike Smith */
42335863739SMike Smith static int
aac_disk_detach(device_t dev)42435863739SMike Smith aac_disk_detach(device_t dev)
42535863739SMike Smith {
426914da7d0SScott Long struct aac_disk *sc;
42735863739SMike Smith
428914da7d0SScott Long sc = (struct aac_disk *)device_get_softc(dev);
42931a0399eSEd Maste fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
430914da7d0SScott Long
43135863739SMike Smith if (sc->ad_flags & AAC_DISK_OPEN)
43235863739SMike Smith return(EBUSY);
43335863739SMike Smith
4340b7ed341SPoul-Henning Kamp disk_destroy(sc->ad_disk);
43535863739SMike Smith
43635863739SMike Smith return(0);
43735863739SMike Smith }
438