Change the kernel dev_t, representing a pointer to a specinfo structure,
[dragonfly.git] / sys / dev / raid / ips / ips_disk.c
index 6cd8214..09ef3cd 100644 (file)
@@ -25,7 +25,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ips/ips_disk.c,v 1.4 2003/09/22 04:59:07 njl Exp $
- * $DragonFly: src/sys/dev/raid/ips/ips_disk.c,v 1.5 2004/10/06 02:12:31 y0netan1 Exp $
+ * $DragonFly: src/sys/dev/raid/ips/ips_disk.c,v 1.10 2006/09/10 01:26:35 dillon Exp $
  */
 
 #include <sys/devicestat.h>
 #include <dev/raid/ips/ips_disk.h>
 #include <sys/stat.h>
 
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/md_var.h>
+
 static int ipsd_probe(device_t dev);
 static int ipsd_attach(device_t dev);
 static int ipsd_detach(device_t dev);
 
-static disk_open_t ipsd_open;
-static disk_close_t ipsd_close;
-static disk_strategy_t ipsd_strategy;
-
-static struct cdevsw ipsd_cdevsw = {
-       .d_name         = "ipsd",
-       .d_maj          = IPSD_CDEV_MAJOR,
-       .d_flags        = D_DISK,
-       .d_port         = NULL,
-       .d_clone        = NULL,
-       .old_open       = ipsd_open,
-       .old_close      = ipsd_close,
-       .old_strategy   = ipsd_strategy,
-       .old_read       = physread,
-       .old_write      = physwrite,
+#if 0
+static int ipsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length);
+static void ipsd_dump_map_sg(void *arg, bus_dma_segment_t *segs, int nsegs,
+                            int error);
+static void ipsd_dump_block_complete(ips_command_t *command);
+#endif
+
+static d_open_t ipsd_open;
+static d_close_t ipsd_close;
+static d_strategy_t ipsd_strategy;
+static d_dump_t ipsd_dump_helper;
+
+static struct dev_ops ipsd_ops = {
+       { "ipsd", IPSD_CDEV_MAJOR, D_DISK },
+       .d_open =       ipsd_open,
+       .d_close =      ipsd_close,
+       .d_strategy =   ipsd_strategy,
+       .d_read =       physread,
+       .d_write =      physwrite,
+       .d_dump =       ipsd_dump_helper,
 };
 
 static device_method_t ipsd_methods[] = {
@@ -76,8 +85,9 @@ DRIVER_MODULE(ipsd, ips, ipsd_driver, ipsd_devclass, 0, 0);
  * the geometry and size of the disk
  */
 static int
-ipsd_open(dev_t dev, int oflags, int devtype, d_thread_t *td)
+ipsd_open(struct dev_open_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        ipsdisk_softc_t *dsc = dev->si_drv1;
 
        if (dsc == NULL)
@@ -88,8 +98,9 @@ ipsd_open(dev_t dev, int oflags, int devtype, d_thread_t *td)
 }
 
 static int
-ipsd_close(dev_t dev, int oflags, int devtype, d_thread_t *td)
+ipsd_close(struct dev_close_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        ipsdisk_softc_t *dsc = dev->si_drv1;
 
        dsc->state &= ~IPS_DEV_OPEN;
@@ -99,30 +110,39 @@ ipsd_close(dev_t dev, int oflags, int devtype, d_thread_t *td)
 
 /* ipsd_finish is called to clean up and return a completed IO request */
 void
-ipsd_finish(struct bio *iobuf)
+ipsd_finish(struct bio *bio)
 {
+       struct buf *bp = bio->bio_buf;
        ipsdisk_softc_t *dsc;
 
-       dsc = iobuf->bio_disk->d_drv1;
-       if (iobuf->bio_flags & BIO_ERROR) {
-               device_printf(dsc->dev, "iobuf error %d\n", iobuf->bio_error);
-       } else
-               iobuf->bio_resid = 0;
-       devstat_end_transaction_buf(&dsc->stats, iobuf);
-       biodone(iobuf);
+       dsc = bio->bio_driver_info;
+       if (bp->b_flags & B_ERROR) {
+               device_printf(dsc->dev, "iobuf error %d\n", bp->b_error);
+       } else {
+               bp->b_resid = 0;
+       }
+       devstat_end_transaction_buf(&dsc->stats, bp);
+       biodone(bio);
+       ips_start_io_request(dsc->sc);
 }
 
 
-static void
-ipsd_strategy(struct bio *iobuf)
+static int
+ipsd_strategy(struct dev_strategy_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
+       struct bio *bio = ap->a_bio;
        ipsdisk_softc_t *dsc;
 
-       dsc = iobuf->bio_disk->d_drv1;
+       dsc = dev->si_drv1;
        DEVICE_PRINTF(8, dsc->dev, "in strategy\n");
-       iobuf->bio_driver1 = (void *)(uintptr_t)dsc->sc->drives[dsc->disk_number].drivenum;
+       bio->bio_driver_info = dsc;
        devstat_start_transaction(&dsc->stats);
-       ips_start_io_request(dsc->sc, iobuf);
+       lockmgr(&dsc->sc->queue_lock, LK_EXCLUSIVE|LK_RETRY);
+       bioq_insert_tail(&dsc->sc->bio_queue, bio);
+       ips_start_io_request(dsc->sc);
+       lockmgr(&dsc->sc->queue_lock, LK_RELEASE);
+       return(0);
 }
 
 static int
@@ -163,8 +183,7 @@ ipsd_attach(device_t dev)
                          DEVSTAT_NO_ORDERED_TAGS,
                          DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_SCSI,
                          DEVSTAT_PRIORITY_DISK);
-       dsc->ipsd_dev_t = disk_create(dsc->unit, &dsc->ipsd_disk, 0,
-           &ipsd_cdevsw);
+       dsc->ipsd_dev_t = disk_create(dsc->unit, &dsc->ipsd_disk, 0, &ipsd_ops);
        dsc->ipsd_dev_t->si_drv1 = dsc;
        dsc->ipsd_dev_t->si_iosize_max = IPS_MAX_IO_SIZE;
        label = &dsc->ipsd_disk.d_label;
@@ -195,3 +214,162 @@ ipsd_detach(device_t dev)
        return 0;
 }
 
+static int
+ipsd_dump_helper(struct dev_dump_args *ap)
+{
+       printf("dump support for IPS not yet working, will not dump\n");
+       return (ENODEV);
+
+#if 0
+       long blkcnt;
+       caddr_t va;
+       vm_offset_t addr, a;
+       int dumppages = MAXDUMPPGS;
+       int i;
+
+       addr = 0;
+       blkcnt = howmany(PAGE_SIZE, secsize);
+       while (count > 0) {
+               va = NULL;
+               if (count / blkcnt < dumppages)
+                       dumppages = count / blkcnt;
+               for (i = 0; i < dumppages; i++) {
+                       a = addr + (i * PAGE_SIZE);
+                       if (!is_physical_memory(a))
+                               a = 0;
+                       va = pmap_kenter_temporary(trunc_page(a), i);
+               }
+
+               ipsd_dump(dev, va, 0, blkno, PAGE_SIZE * dumppages);
+               if (dumpstatus(addr, (off_t)count * DEV_BSIZE) < 0)
+                       return (EINTR);
+               blkno += blkcnt * dumppages;
+               count -= blkcnt * dumppages;
+               addr += PAGE_SIZE * dumppages;
+       }
+       return (0);
+#endif
+}
+
+#if 0
+
+static int
+ipsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
+          size_t length)
+{
+       cdev_t dev = arg;
+       ips_softc_t *sc;
+       ips_command_t *command;
+       ips_io_cmd *command_struct;
+       ipsdisk_softc_t *dsc;
+       off_t off;
+       uint8_t *va;
+       int len;
+       int error = 0;
+
+       dsc = dev->si_drv1;
+       if (dsc == NULL)
+               return (EINVAL);
+       sc = dsc->sc;
+
+       if (ips_get_free_cmd(sc, &command, 0) != 0) {
+               printf("ipsd: failed to get cmd for dump\n");
+               return (ENOMEM);
+       }
+
+       command->data_dmatag = sc->sg_dmatag;
+       command->callback = ipsd_dump_block_complete;
+
+       command_struct = (ips_io_cmd *)command->command_buffer;
+       command_struct->id = command->id;
+       command_struct->drivenum = sc->drives[dsc->disk_number].drivenum;
+
+       off = offset;
+       va = virtual;
+
+       while (length > 0) {
+               len = length > IPS_MAX_IO_SIZE ? IPS_MAX_IO_SIZE : length;
+               command_struct->lba = off / IPS_BLKSIZE;
+               if (bus_dmamap_load(command->data_dmatag, command->data_dmamap,
+                   va, len, ipsd_dump_map_sg, command, 0) != 0) {
+                       error = EIO;
+                       break;
+               }
+               if (COMMAND_ERROR(&command->status)) {
+                       error = EIO;
+                       break;
+               }
+
+               length -= len;
+               off += len;
+               va += len;
+       }
+       ips_insert_free_cmd(command->sc, command);
+       return(error);
+}
+
+static void
+ipsd_dump_map_sg(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+       ips_softc_t *sc;
+       ips_command_t *command;
+       ips_sg_element_t *sg_list;
+       ips_io_cmd *command_struct;
+       int i, length;
+
+       command = (ips_command_t *)arg;
+       sc = command->sc;
+       length = 0;
+
+       if (error) {
+               printf("ipsd_dump_map_sg: error %d\n", error);
+               command->status.value = IPS_ERROR_STATUS;
+               return;
+       }
+
+       command_struct = (ips_io_cmd *)command->command_buffer;
+
+       if (nsegs != 1) {
+               command_struct->segnum = nsegs;
+               sg_list = (ips_sg_element_t *)((uint8_t *)
+                   command->command_buffer + IPS_COMMAND_LEN);
+               for (i = 0; i < nsegs; i++) {
+                       sg_list[i].addr = segs[i].ds_addr;
+                       sg_list[i].len = segs[i].ds_len;
+                       length += segs[i].ds_len;
+               }
+               command_struct->buffaddr =
+                   (uint32_t)command->command_phys_addr + IPS_COMMAND_LEN;
+               command_struct->command = IPS_SG_WRITE_CMD;
+       } else {
+               command_struct->buffaddr = segs[0].ds_addr;
+               length = segs[0].ds_len;
+               command_struct->segnum = 0;
+               command_struct->command = IPS_WRITE_CMD;
+       }
+
+       length = (length + IPS_BLKSIZE - 1) / IPS_BLKSIZE;
+       command_struct->length = length;
+       bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
+           BUS_DMASYNC_PREWRITE);
+       bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
+           BUS_DMASYNC_PREWRITE);
+
+       sc->ips_issue_cmd(command);
+       sc->ips_poll_cmd(command);
+       return;
+}
+
+static void
+ipsd_dump_block_complete(ips_command_t *command)
+{
+       if (COMMAND_ERROR(&command->status)) {
+               printf("ipsd_dump completion error= 0x%x\n",
+                      command->status.value);
+       }
+       bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
+           BUS_DMASYNC_POSTWRITE);
+       bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
+}
+
+#endif