diff options
author | ps <ps@FreeBSD.org> | 2003-10-10 22:49:40 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2003-10-10 22:49:40 +0000 |
commit | 592158f5ce62f282f2676d220c95a828787891d4 (patch) | |
tree | a6978cccd00c136d8bb48afbe113b368f63cbbbf /sys/dev/amr | |
parent | 8248f74b0cd4b641c9c69f7f5dcdf56f900c28b8 (diff) | |
download | FreeBSD-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.c | 67 | ||||
-rw-r--r-- | sys/dev/amr/amr_disk.c | 28 | ||||
-rw-r--r-- | sys/dev/amr/amrvar.h | 1 |
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); /******************************************************************************** |