summaryrefslogtreecommitdiffstats
path: root/sys/dev/amr
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2003-10-10 22:49:40 +0000
committerps <ps@FreeBSD.org>2003-10-10 22:49:40 +0000
commit592158f5ce62f282f2676d220c95a828787891d4 (patch)
treea6978cccd00c136d8bb48afbe113b368f63cbbbf /sys/dev/amr
parent8248f74b0cd4b641c9c69f7f5dcdf56f900c28b8 (diff)
downloadFreeBSD-src-592158f5ce62f282f2676d220c95a828787891d4.zip
FreeBSD-src-592158f5ce62f282f2676d220c95a828787891d4.tar.gz
crashdump support.
Some bits by: Rajesh Prabhakaran <rajeshpr@lsil.com>
Diffstat (limited to 'sys/dev/amr')
-rw-r--r--sys/dev/amr/amr.c67
-rw-r--r--sys/dev/amr/amr_disk.c28
-rw-r--r--sys/dev/amr/amrvar.h1
3 files changed, 84 insertions, 12 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index 8c252b9..524c65e 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -977,20 +977,22 @@ amr_quartz_poll_command(struct amr_command *ac)
s = splbio();
- count=0;
- while (sc->amr_busyslots){
- tsleep(sc, PRIBIO | PCATCH, "amrpoll", hz);
- if(count++>10) {
- break;
+ if (sc->amr_state & AMR_STATE_INTEN) {
+ count=0;
+ while (sc->amr_busyslots) {
+ tsleep(sc, PRIBIO | PCATCH, "amrpoll", hz);
+ if(count++>10) {
+ break;
+ }
}
- }
- if(sc->amr_busyslots) {
- device_printf(sc->amr_dev, "adapter is busy\n");
- splx(s);
- amr_unmapcmd(ac);
- ac->ac_status=0;
- return(1);
+ if(sc->amr_busyslots) {
+ device_printf(sc->amr_dev, "adapter is busy\n");
+ splx(s);
+ amr_unmapcmd(ac);
+ ac->ac_status=0;
+ return(1);
+ }
}
bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, AMR_MBOX_CMDSIZE);
@@ -1779,6 +1781,47 @@ amr_describe_controller(struct amr_softc *sc)
free(ae, M_DEVBUF);
}
+int
+amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks)
+{
+ struct amr_command *ac;
+ int error = EIO;
+
+ debug_called(1);
+
+ sc->amr_state &= ~AMR_STATE_INTEN;
+
+ /* get ourselves a command buffer */
+ if ((ac = amr_alloccmd(sc)) == NULL)
+ goto out;
+ /* set command flags */
+ ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
+
+ /* point the command at our data */
+ ac->ac_data = data;
+ ac->ac_length = blks * AMR_BLKSIZE;
+
+ /* build the command proper */
+ ac->ac_mailbox.mb_command = AMR_CMD_LWRITE;
+ ac->ac_mailbox.mb_blkcount = blks;
+ ac->ac_mailbox.mb_lba = lba;
+ ac->ac_mailbox.mb_drive = unit;
+
+ /* can't assume that interrupts are going to work here, so play it safe */
+ if (sc->amr_poll_command(ac))
+ goto out;
+ error = ac->ac_status;
+
+ out:
+ if (ac != NULL)
+ amr_releasecmd(ac);
+
+ sc->amr_state |= AMR_STATE_INTEN;
+ return (error);
+}
+
+
+
#ifdef AMR_DEBUG
/********************************************************************************
* Print the command (ac) in human-readable format
diff --git a/sys/dev/amr/amr_disk.c b/sys/dev/amr/amr_disk.c
index 96d1c44..42d09a2 100644
--- a/sys/dev/amr/amr_disk.c
+++ b/sys/dev/amr/amr_disk.c
@@ -142,6 +142,33 @@ amrd_open(struct disk *dp)
return (0);
}
+/********************************************************************************
+ * System crashdump support
+ */
+
+static int
+amrd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
+{
+
+ struct amrd_softc *amrd_sc;
+ struct amr_softc *amr_sc;
+ int error;
+ struct disk *dp;
+
+ dp = arg;
+ amrd_sc = (struct amrd_softc *)dp->d_drv1;
+ amr_sc = (struct amr_softc *)amrd_sc->amrd_controller;
+ if (!amrd_sc || !amr_sc)
+ return(ENXIO);
+
+ if (length > 0) {
+ int driveno = amrd_sc->amrd_drive - amr_sc->amr_drive;
+ if ((error = amr_dump_blocks(amr_sc,driveno,offset / AMR_BLKSIZE ,(void *)virtual,(int) length / AMR_BLKSIZE )) != 0)
+ return(error);
+
+ }
+ return(0);
+}
/*
* Read/write routine for a buffer. Finds the proper unit, range checks
@@ -225,6 +252,7 @@ amrd_attach(device_t dev)
sc->amrd_disk.d_open = amrd_open;
sc->amrd_disk.d_strategy = amrd_strategy;
sc->amrd_disk.d_name = "amrd";
+ sc->amrd_disk.d_dump = (dumper_t *)amrd_dump;
disk_create(sc->amrd_unit, &sc->amrd_disk, 0, NULL, NULL);
#ifdef FREEBSD_4
disks_registered++;
diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h
index a28fa47..1191954 100644
--- a/sys/dev/amr/amrvar.h
+++ b/sys/dev/amr/amrvar.h
@@ -261,6 +261,7 @@ struct amrd_softc
* Interface between driver core and disk driver (should be using a bus?)
*/
extern int amr_submit_bio(struct amr_softc *sc, struct bio *bio);
+extern int amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks);
extern void amrd_intr(void *data);
/********************************************************************************
OpenPOWER on IntegriCloud