summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2005-06-28 15:09:37 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2005-06-28 15:09:37 +0000
commita90165c97cf041ad9a474064474991ad70e89e8e (patch)
tree45a22d89d405cd1fa3cc2f1db6d43363f04f0a8e /sys/dev/ic
parent17167bdf513aca7e711d2d481806d66ea040ad6b (diff)
implement ami_schwartz_poll() per the FIXME leftover from the hackathon.
ok mickey@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/ami.c74
1 files changed, 68 insertions, 6 deletions
diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c
index 296826c5894..c4c175ab289 100644
--- a/sys/dev/ic/ami.c
+++ b/sys/dev/ic/ami.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ami.c,v 1.43 2005/06/28 13:58:05 mickey Exp $ */
+/* $OpenBSD: ami.c,v 1.44 2005/06/28 15:09:36 marco Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -935,16 +935,78 @@ ami_schwartz_done(sc, mbox)
}
int
-ami_schwartz_poll(sc, cmd)
+ami_schwartz_poll(sc, mbox)
struct ami_softc *sc;
- struct ami_iocmd *cmd;
+ struct ami_iocmd *mbox;
{
- /* FIXME add the actual code here */
+ u_int8_t status;
+ u_int32_t i;
+ int rv;
- if (sc->sc_dis_poll)
+ if (sc->sc_dis_poll) {
+ return 1; /* fail */
+ }
+
+ for (i = 0; i < AMI_MAX_POLLWAIT; i++) {
+ if (!(bus_space_read_1(sc->iot, sc->ioh, AMI_SMBSTAT) & AMI_SMBST_BUSY))
+ break;
+ delay(1);
+ }
+ if (i >= AMI_MAX_POLLWAIT) {
+ AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
+ return (EBUSY);
+ }
+
+ memcpy((struct ami_iocmd *)sc->sc_mbox, mbox, 16);
+ bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, 16,
+ BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
+
+ sc->sc_mbox->acc_busy = 1;
+ sc->sc_mbox->acc_poll = 0;
+ sc->sc_mbox->acc_ack = 0;
+ /* send command to firmware */
+ bus_space_write_1(sc->iot, sc->ioh, AMI_SCMD, AMI_SCMD_EXEC);
+
+ /* wait until no longer busy */
+ for (i = 0; i < AMI_MAX_POLLWAIT; i++) {
+ if (!(bus_space_read_1(sc->iot, sc->ioh, AMI_SMBSTAT) & AMI_SMBST_BUSY))
+ break;
+ delay(1);
+ }
+ if (i >= AMI_MAX_POLLWAIT) {
+ printf("%s: command not accepted, polling disabled\n",
+ sc->sc_dev.dv_xname);
+ sc->sc_dis_poll = 1;
return 1; /* fail */
+ }
+
+ /* wait for interrupt bit */
+ for (i = 0; i < AMI_MAX_POLLWAIT; i++) {
+ status = bus_space_read_1(sc->iot, sc->ioh, AMI_ISTAT);
+ if (status & AMI_ISTAT_PEND)
+ break;
+ delay(1);
+ }
+ if (i >= AMI_MAX_POLLWAIT) {
+ printf("%s: interrupt didn't arrive, polling disabled\n",
+ sc->sc_dev.dv_xname);
+ sc->sc_dis_poll = 1;
+ return 1; /* fail */
+ }
+
+ /* write ststus back to firmware */
+ bus_space_write_1(sc->iot, sc->ioh, AMI_ISTAT, status);
+
+ /* copy mailbox and status back */
+ bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, 128,
+ BUS_DMASYNC_PREREAD);
+ *mbox = *sc->sc_mbox;
+ rv = sc->sc_mbox->acc_status;
+
+ /* ack interrupt */
+ bus_space_write_1(sc->iot, sc->ioh, AMI_SCMD, AMI_SCMD_ACK);
- return 1;
+ return rv;
}
int