123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704 |
- /*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include <sys/cdefs.h>
- __FBSDID("$FreeBSD$");
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/sysctl.h>
- #include <sys/disk.h>
- #include <sys/bio.h>
- #include <sys/bus.h>
- #include <sys/conf.h>
- #include <sys/kernel.h>
- #include <sys/kthread.h>
- #include <sys/lock.h>
- #include <sys/malloc.h>
- #include <sys/module.h>
- #include <sys/mutex.h>
- #include <vm/vm.h>
- #include <vm/pmap.h>
- #include <machine/pio.h>
- #include <machine/bus.h>
- #include <machine/platform.h>
- #include <machine/resource.h>
- #include <sys/bus.h>
- #include <sys/rman.h>
- #include <geom/geom_disk.h>
- #include "ps3bus.h"
- #include "ps3-hvcall.h"
- #define PS3DISK_LOCK_INIT(_sc) \
- mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3disk", MTX_DEF)
- #define PS3DISK_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
- #define PS3DISK_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
- #define PS3DISK_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
- #define PS3DISK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
- #define PS3DISK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
- #define LV1_STORAGE_ATA_HDDOUT 0x23
- static SYSCTL_NODE(_hw, OID_AUTO, ps3disk, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
- "PS3 Disk driver parameters");
- #ifdef PS3DISK_DEBUG
- static int ps3disk_debug = 0;
- SYSCTL_INT(_hw_ps3disk, OID_AUTO, debug, CTLFLAG_RW, &ps3disk_debug,
- 0, "control debugging printfs");
- TUNABLE_INT("hw.ps3disk.debug", &ps3disk_debug);
- enum {
- PS3DISK_DEBUG_INTR = 0x00000001,
- PS3DISK_DEBUG_TASK = 0x00000002,
- PS3DISK_DEBUG_READ = 0x00000004,
- PS3DISK_DEBUG_WRITE = 0x00000008,
- PS3DISK_DEBUG_FLUSH = 0x00000010,
- PS3DISK_DEBUG_ANY = 0xffffffff
- };
- #define DPRINTF(sc, m, fmt, ...) \
- do { \
- if (sc->sc_debug & (m)) \
- printf(fmt, __VA_ARGS__); \
- } while (0)
- #else
- #define DPRINTF(sc, m, fmt, ...)
- #endif
- struct ps3disk_region {
- uint64_t r_id;
- uint64_t r_start;
- uint64_t r_size;
- uint64_t r_flags;
- };
- struct ps3disk_softc {
- device_t sc_dev;
- struct mtx sc_mtx;
- uint64_t sc_blksize;
- uint64_t sc_nblocks;
- uint64_t sc_nregs;
- struct ps3disk_region *sc_reg;
- int sc_irqid;
- struct resource *sc_irq;
- void *sc_irqctx;
- struct disk **sc_disk;
- struct bio_queue_head sc_bioq;
- struct bio_queue_head sc_deferredq;
- struct proc *sc_task;
- bus_dma_tag_t sc_dmatag;
- int sc_running;
- int sc_debug;
- };
- static int ps3disk_open(struct disk *dp);
- static int ps3disk_close(struct disk *dp);
- static void ps3disk_strategy(struct bio *bp);
- static void ps3disk_task(void *arg);
- static void ps3disk_intr(void *arg);
- static int ps3disk_get_disk_geometry(struct ps3disk_softc *sc);
- static int ps3disk_enum_regions(struct ps3disk_softc *sc);
- static void ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
- int error);
- static void ps3disk_sysctlattach(struct ps3disk_softc *sc);
- static MALLOC_DEFINE(M_PS3DISK, "ps3disk", "PS3 Disk");
- static int
- ps3disk_probe(device_t dev)
- {
- if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
- ps3bus_get_devtype(dev) != PS3_DEVTYPE_DISK)
- return (ENXIO);
- device_set_desc(dev, "Playstation 3 Disk");
- return (BUS_PROBE_SPECIFIC);
- }
- static int
- ps3disk_attach(device_t dev)
- {
- struct ps3disk_softc *sc;
- struct disk *d;
- intmax_t mb;
- uint64_t junk;
- char unit;
- int i, err;
- sc = device_get_softc(dev);
- sc->sc_dev = dev;
- PS3DISK_LOCK_INIT(sc);
- err = ps3disk_get_disk_geometry(sc);
- if (err) {
- device_printf(dev, "Could not get disk geometry\n");
- err = ENXIO;
- goto fail_destroy_lock;
- }
- device_printf(dev, "block size %lu total blocks %lu\n",
- sc->sc_blksize, sc->sc_nblocks);
- err = ps3disk_enum_regions(sc);
- if (err) {
- device_printf(dev, "Could not enumerate disk regions\n");
- err = ENXIO;
- goto fail_destroy_lock;
- }
- device_printf(dev, "Found %lu regions\n", sc->sc_nregs);
- if (!sc->sc_nregs) {
- err = ENXIO;
- goto fail_destroy_lock;
- }
- /* Setup interrupt handler */
- sc->sc_irqid = 0;
- sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
- RF_ACTIVE);
- if (!sc->sc_irq) {
- device_printf(dev, "Could not allocate IRQ\n");
- err = ENXIO;
- goto fail_free_regions;
- }
- err = bus_setup_intr(dev, sc->sc_irq,
- INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
- NULL, ps3disk_intr, sc, &sc->sc_irqctx);
- if (err) {
- device_printf(dev, "Could not setup IRQ\n");
- err = ENXIO;
- goto fail_release_intr;
- }
- /* Setup DMA */
- err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
- BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
- busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
- if (err) {
- device_printf(dev, "Could not create DMA tag\n");
- err = ENXIO;
- goto fail_teardown_intr;
- }
- /* Setup disks */
- sc->sc_disk = malloc(sc->sc_nregs * sizeof(struct disk *),
- M_PS3DISK, M_ZERO | M_WAITOK);
- if (!sc->sc_disk) {
- device_printf(dev, "Could not allocate disk(s)\n");
- err = ENOMEM;
- goto fail_teardown_intr;
- }
- for (i = 0; i < sc->sc_nregs; i++) {
- struct ps3disk_region *rp = &sc->sc_reg[i];
- d = sc->sc_disk[i] = disk_alloc();
- d->d_open = ps3disk_open;
- d->d_close = ps3disk_close;
- d->d_strategy = ps3disk_strategy;
- d->d_name = "ps3disk";
- d->d_drv1 = sc;
- d->d_maxsize = PAGE_SIZE;
- d->d_sectorsize = sc->sc_blksize;
- d->d_unit = i;
- d->d_mediasize = sc->sc_reg[i].r_size * sc->sc_blksize;
- d->d_flags |= DISKFLAG_CANFLUSHCACHE;
- mb = d->d_mediasize >> 20;
- unit = 'M';
- if (mb >= 10240) {
- unit = 'G';
- mb /= 1024;
- }
- /* Test to see if we can read this region */
- err = lv1_storage_read(ps3bus_get_device(dev), d->d_unit,
- 0, 0, rp->r_flags, 0, &junk);
- device_printf(dev, "region %d %ju%cB%s\n", i, mb, unit,
- (err == LV1_DENIED_BY_POLICY) ? " (hypervisor protected)"
- : "");
- if (err != LV1_DENIED_BY_POLICY)
- disk_create(d, DISK_VERSION);
- }
- err = 0;
- bioq_init(&sc->sc_bioq);
- bioq_init(&sc->sc_deferredq);
- kproc_create(&ps3disk_task, sc, &sc->sc_task, 0, 0, "ps3disk");
- ps3disk_sysctlattach(sc);
- sc->sc_running = 1;
- return (0);
- fail_teardown_intr:
- bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
- fail_release_intr:
- bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
- fail_free_regions:
- free(sc->sc_reg, M_PS3DISK);
- fail_destroy_lock:
- PS3DISK_LOCK_DESTROY(sc);
- return (err);
- }
- static int
- ps3disk_detach(device_t dev)
- {
- struct ps3disk_softc *sc = device_get_softc(dev);
- int i;
- for (i = 0; i < sc->sc_nregs; i++)
- disk_destroy(sc->sc_disk[i]);
- bus_dma_tag_destroy(sc->sc_dmatag);
- bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
- bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
- free(sc->sc_disk, M_PS3DISK);
- free(sc->sc_reg, M_PS3DISK);
- PS3DISK_LOCK_DESTROY(sc);
- return (0);
- }
- static int
- ps3disk_open(struct disk *dp)
- {
- return (0);
- }
- static int
- ps3disk_close(struct disk *dp)
- {
- return (0);
- }
- /* Process deferred blocks */
- static void
- ps3disk_task(void *arg)
- {
- struct ps3disk_softc *sc = (struct ps3disk_softc *) arg;
- struct bio *bp;
- while (1) {
- kproc_suspend_check(sc->sc_task);
- tsleep(&sc->sc_deferredq, PRIBIO, "ps3disk", 10);
- PS3DISK_LOCK(sc);
- bp = bioq_takefirst(&sc->sc_deferredq);
- PS3DISK_UNLOCK(sc);
- if (bp == NULL)
- continue;
- if (bp->bio_driver1 != NULL) {
- bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
- bp->bio_driver1);
- bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
- bp->bio_driver1);
- }
- ps3disk_strategy(bp);
- }
- kproc_exit(0);
- }
- static void
- ps3disk_strategy(struct bio *bp)
- {
- struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1;
- int err;
- if (sc == NULL) {
- bp->bio_flags |= BIO_ERROR;
- bp->bio_error = EINVAL;
- biodone(bp);
- return;
- }
- PS3DISK_LOCK(sc);
- bp->bio_resid = bp->bio_bcount;
- bioq_insert_tail(&sc->sc_bioq, bp);
- DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: bio_cmd 0x%02x\n",
- __func__, bp->bio_cmd);
- err = 0;
- if (bp->bio_cmd == BIO_FLUSH) {
- bp->bio_driver1 = 0;
- err = lv1_storage_send_device_command(
- ps3bus_get_device(sc->sc_dev), LV1_STORAGE_ATA_HDDOUT,
- 0, 0, 0, 0, (uint64_t *)&bp->bio_driver2);
- if (err == LV1_BUSY)
- err = EAGAIN;
- } else if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
- if (bp->bio_bcount % sc->sc_blksize != 0) {
- err = EINVAL;
- } else {
- bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
- (bus_dmamap_t *)(&bp->bio_driver1));
- err = bus_dmamap_load(sc->sc_dmatag,
- (bus_dmamap_t)(bp->bio_driver1), bp->bio_data,
- bp->bio_bcount, ps3disk_transfer, bp, 0);
- if (err == EINPROGRESS)
- err = 0;
- }
- } else {
- err = EINVAL;
- }
- if (err == EAGAIN) {
- bioq_remove(&sc->sc_bioq, bp);
- bioq_insert_tail(&sc->sc_deferredq, bp);
- } else if (err != 0) {
- bp->bio_error = err;
- bp->bio_flags |= BIO_ERROR;
- bioq_remove(&sc->sc_bioq, bp);
- disk_err(bp, "hard error", -1, 1);
- biodone(bp);
- }
- PS3DISK_UNLOCK(sc);
- }
- static void
- ps3disk_intr(void *arg)
- {
- struct ps3disk_softc *sc = (struct ps3disk_softc *) arg;
- device_t dev = sc->sc_dev;
- uint64_t devid = ps3bus_get_device(dev);
- struct bio *bp;
- uint64_t tag, status;
- if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
- return;
- PS3DISK_LOCK(sc);
- DPRINTF(sc, PS3DISK_DEBUG_INTR, "%s: tag 0x%016lx "
- "status 0x%016lx\n", __func__, tag, status);
- /* Locate the matching request */
- TAILQ_FOREACH(bp, &sc->sc_bioq.queue, bio_queue) {
- if ((uint64_t)bp->bio_driver2 != tag)
- continue;
- if (status != 0) {
- device_printf(sc->sc_dev, "%s error (%#lx)\n",
- (bp->bio_cmd == BIO_READ) ? "Read" : "Write",
- status);
- bp->bio_error = EIO;
- bp->bio_flags |= BIO_ERROR;
- } else {
- bp->bio_error = 0;
- bp->bio_resid = 0;
- bp->bio_flags |= BIO_DONE;
- }
- if (bp->bio_driver1 != NULL) {
- if (bp->bio_cmd == BIO_READ)
- bus_dmamap_sync(sc->sc_dmatag, (bus_dmamap_t)
- bp->bio_driver1, BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
- bp->bio_driver1);
- bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
- bp->bio_driver1);
- }
- bioq_remove(&sc->sc_bioq, bp);
- biodone(bp);
- break;
- }
- if (bioq_first(&sc->sc_deferredq) != NULL)
- wakeup(&sc->sc_deferredq);
- PS3DISK_UNLOCK(sc);
- }
- static int
- ps3disk_get_disk_geometry(struct ps3disk_softc *sc)
- {
- device_t dev = sc->sc_dev;
- uint64_t bus_index = ps3bus_get_busidx(dev);
- uint64_t dev_index = ps3bus_get_devidx(dev);
- uint64_t junk;
- int err;
- err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
- (lv1_repository_string("bus") >> 32) | bus_index,
- lv1_repository_string("dev") | dev_index,
- lv1_repository_string("blk_size"), 0, &sc->sc_blksize, &junk);
- if (err) {
- device_printf(dev, "Could not get block size (0x%08x)\n", err);
- return (ENXIO);
- }
- err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
- (lv1_repository_string("bus") >> 32) | bus_index,
- lv1_repository_string("dev") | dev_index,
- lv1_repository_string("n_blocks"), 0, &sc->sc_nblocks, &junk);
- if (err) {
- device_printf(dev, "Could not get total number of blocks "
- "(0x%08x)\n", err);
- err = ENXIO;
- }
- return (err);
- }
- static int
- ps3disk_enum_regions(struct ps3disk_softc *sc)
- {
- device_t dev = sc->sc_dev;
- uint64_t bus_index = ps3bus_get_busidx(dev);
- uint64_t dev_index = ps3bus_get_devidx(dev);
- uint64_t junk;
- int i, err;
- /* Read number of regions */
- err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
- (lv1_repository_string("bus") >> 32) | bus_index,
- lv1_repository_string("dev") | dev_index,
- lv1_repository_string("n_regs"), 0, &sc->sc_nregs, &junk);
- if (err) {
- device_printf(dev, "Could not get number of regions (0x%08x)\n",
- err);
- err = ENXIO;
- goto fail;
- }
- if (!sc->sc_nregs)
- return 0;
- sc->sc_reg = malloc(sc->sc_nregs * sizeof(struct ps3disk_region),
- M_PS3DISK, M_ZERO | M_WAITOK);
- if (!sc->sc_reg) {
- err = ENOMEM;
- goto fail;
- }
- /* Setup regions */
- for (i = 0; i < sc->sc_nregs; i++) {
- err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
- (lv1_repository_string("bus") >> 32) | bus_index,
- lv1_repository_string("dev") | dev_index,
- lv1_repository_string("region") | i,
- lv1_repository_string("id"), &sc->sc_reg[i].r_id, &junk);
- if (err) {
- device_printf(dev, "Could not get region id (0x%08x)\n",
- err);
- err = ENXIO;
- goto fail;
- }
- err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
- (lv1_repository_string("bus") >> 32) | bus_index,
- lv1_repository_string("dev") | dev_index,
- lv1_repository_string("region") | i,
- lv1_repository_string("start"), &sc->sc_reg[i].r_start,
- &junk);
- if (err) {
- device_printf(dev, "Could not get region start "
- "(0x%08x)\n", err);
- err = ENXIO;
- goto fail;
- }
- err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
- (lv1_repository_string("bus") >> 32) | bus_index,
- lv1_repository_string("dev") | dev_index,
- lv1_repository_string("region") | i,
- lv1_repository_string("size"), &sc->sc_reg[i].r_size,
- &junk);
- if (err) {
- device_printf(dev, "Could not get region size "
- "(0x%08x)\n", err);
- err = ENXIO;
- goto fail;
- }
- if (i == 0)
- sc->sc_reg[i].r_flags = 0x2;
- else
- sc->sc_reg[i].r_flags = 0;
- }
- return (0);
- fail:
- sc->sc_nregs = 0;
- if (sc->sc_reg)
- free(sc->sc_reg, M_PS3DISK);
- return (err);
- }
- static void
- ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
- {
- struct bio *bp = (struct bio *)(arg);
- struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1;
- struct ps3disk_region *rp = &sc->sc_reg[bp->bio_disk->d_unit];
- uint64_t devid = ps3bus_get_device(sc->sc_dev);
- uint64_t block;
- int i, err;
- /* Locks already held by busdma */
- PS3DISK_ASSERT_LOCKED(sc);
- if (error) {
- bp->bio_error = error;
- bp->bio_flags |= BIO_ERROR;
- bioq_remove(&sc->sc_bioq, bp);
- biodone(bp);
- return;
- }
- block = bp->bio_pblkno;
- for (i = 0; i < nsegs; i++) {
- KASSERT((segs[i].ds_len % sc->sc_blksize) == 0,
- ("DMA fragments not blocksize multiples"));
- if (bp->bio_cmd == BIO_READ) {
- err = lv1_storage_read(devid, rp->r_id,
- block, segs[i].ds_len/sc->sc_blksize,
- rp->r_flags, segs[i].ds_addr,
- (uint64_t *)&bp->bio_driver2);
- } else {
- bus_dmamap_sync(sc->sc_dmatag,
- (bus_dmamap_t)bp->bio_driver1,
- BUS_DMASYNC_PREWRITE);
- err = lv1_storage_write(devid, rp->r_id,
- block, segs[i].ds_len/sc->sc_blksize,
- rp->r_flags, segs[i].ds_addr,
- (uint64_t *)&bp->bio_driver2);
- }
- if (err) {
- if (err == LV1_BUSY) {
- bioq_remove(&sc->sc_bioq, bp);
- bioq_insert_tail(&sc->sc_deferredq, bp);
- } else {
- bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
- bp->bio_driver1);
- bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
- bp->bio_driver1);
- device_printf(sc->sc_dev, "Could not read "
- "sectors (0x%08x)\n", err);
- bp->bio_error = EINVAL;
- bp->bio_flags |= BIO_ERROR;
- bioq_remove(&sc->sc_bioq, bp);
- biodone(bp);
- }
- break;
- }
- DPRINTF(sc, PS3DISK_DEBUG_READ, "%s: tag 0x%016lx\n",
- __func__, sc->sc_bounce_tag);
- }
- }
- #ifdef PS3DISK_DEBUG
- static int
- ps3disk_sysctl_debug(SYSCTL_HANDLER_ARGS)
- {
- struct ps3disk_softc *sc = arg1;
- int debug, error;
- debug = sc->sc_debug;
- error = sysctl_handle_int(oidp, &debug, 0, req);
- if (error || !req->newptr)
- return error;
- sc->sc_debug = debug;
- return 0;
- }
- #endif
- static void
- ps3disk_sysctlattach(struct ps3disk_softc *sc)
- {
- #ifdef PS3DISK_DEBUG
- struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
- struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
- sc->sc_debug = ps3disk_debug;
- SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
- "debug", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
- ps3disk_sysctl_debug, "I", "control debugging printfs");
- #endif
- }
- static device_method_t ps3disk_methods[] = {
- DEVMETHOD(device_probe, ps3disk_probe),
- DEVMETHOD(device_attach, ps3disk_attach),
- DEVMETHOD(device_detach, ps3disk_detach),
- {0, 0},
- };
- static driver_t ps3disk_driver = {
- "ps3disk",
- ps3disk_methods,
- sizeof(struct ps3disk_softc),
- };
- static devclass_t ps3disk_devclass;
- DRIVER_MODULE(ps3disk, ps3bus, ps3disk_driver, ps3disk_devclass, 0, 0);
|