summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornate <nate@FreeBSD.org>1996-04-23 16:03:08 +0000
committernate <nate@FreeBSD.org>1996-04-23 16:03:08 +0000
commit298d7dcd873991421a7d88124324aee9b16065fd (patch)
treeb983a04d64d9a3fc2e560a452fdf34ac7ad9e577
parentceb677462bce88b520fd1537aee505485cc9de55 (diff)
downloadFreeBSD-src-298d7dcd873991421a7d88124324aee9b16065fd.zip
FreeBSD-src-298d7dcd873991421a7d88124324aee9b16065fd.tar.gz
Adds the APM hooks into the generic pccard kernel files. With this code
in place device drivers can now register power-down/power-up routines so that we can use common routines to power-up/power-down cards for insert/removals, suspend/resume, etc.. Reviewed by: phk Submitted by: the 'Nomads'
-rw-r--r--sys/i386/apm/apm.c4
-rw-r--r--sys/i386/bios/apm.c4
-rw-r--r--sys/i386/include/apm_bios.h4
-rw-r--r--sys/pccard/pccard.c119
-rw-r--r--sys/pccard/pcic.c4
-rw-r--r--sys/pccard/slot.h2
6 files changed, 121 insertions, 16 deletions
diff --git a/sys/i386/apm/apm.c b/sys/i386/apm/apm.c
index f6b490b..e175cd5 100644
--- a/sys/i386/apm/apm.c
+++ b/sys/i386/apm/apm.c
@@ -14,7 +14,7 @@
*
* Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
*
- * $Id: apm.c,v 1.38 1996/04/18 19:21:47 nate Exp $
+ * $Id: apm.c,v 1.39 1996/04/22 19:40:18 nate Exp $
*/
#include "apm.h"
@@ -356,7 +356,6 @@ apm_hook_establish(int apmh, struct apmhook *ah)
return apm_add_hook(&hook[apmh], ah);
}
-#ifdef notused
/* disestablish an apm hook */
void
apm_hook_disestablish(int apmh, struct apmhook *ah)
@@ -366,7 +365,6 @@ apm_hook_disestablish(int apmh, struct apmhook *ah)
apm_del_hook(&hook[apmh], ah);
}
-#endif /* notused */
static struct timeval suspend_time;
diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c
index f6b490b..e175cd5 100644
--- a/sys/i386/bios/apm.c
+++ b/sys/i386/bios/apm.c
@@ -14,7 +14,7 @@
*
* Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
*
- * $Id: apm.c,v 1.38 1996/04/18 19:21:47 nate Exp $
+ * $Id: apm.c,v 1.39 1996/04/22 19:40:18 nate Exp $
*/
#include "apm.h"
@@ -356,7 +356,6 @@ apm_hook_establish(int apmh, struct apmhook *ah)
return apm_add_hook(&hook[apmh], ah);
}
-#ifdef notused
/* disestablish an apm hook */
void
apm_hook_disestablish(int apmh, struct apmhook *ah)
@@ -366,7 +365,6 @@ apm_hook_disestablish(int apmh, struct apmhook *ah)
apm_del_hook(&hook[apmh], ah);
}
-#endif /* notused */
static struct timeval suspend_time;
diff --git a/sys/i386/include/apm_bios.h b/sys/i386/include/apm_bios.h
index 6e2e03c..3abdbd5 100644
--- a/sys/i386/include/apm_bios.h
+++ b/sys/i386/include/apm_bios.h
@@ -12,7 +12,7 @@
*
* Aug, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
*
- * $Id: apm_bios.h,v 1.8 1996/03/12 05:51:35 nate Exp $
+ * $Id: apm_bios.h,v 1.9 1996/03/13 00:41:45 nate Exp $
*/
#ifndef _MACHINE_APM_BIOS_H_
@@ -135,9 +135,7 @@ struct apmhook {
void apm_suspend(void);
struct apmhook *apm_hook_establish (int apmh, struct apmhook *);
-#ifdef notused
void apm_hook_disestablish (int apmh, struct apmhook *);
-#endif
void apm_cpu_idle(void);
void apm_cpu_busy(void);
diff --git a/sys/pccard/pccard.c b/sys/pccard/pccard.c
index 8f42572..3e3440a 100644
--- a/sys/pccard/pccard.c
+++ b/sys/pccard/pccard.c
@@ -54,6 +54,11 @@
#include <i386/isa/isa_device.h>
#include <i386/isa/icu.h>
+#include "apm.h"
+#if NAPM > 0
+#include <machine/apm_bios.h>
+#endif /* NAPM > 0 */
+
#include <pccard/card.h>
#include <pccard/driver.h>
#include <pccard/slot.h>
@@ -82,6 +87,20 @@ static int invalid_io_memory(unsigned long, int);
static struct pccard_drv *find_driver(char *);
static void remove_device(struct pccard_dev *);
static void slot_irq_handler(int);
+static void power_off_slot(void *);
+
+#if NAPM > 0
+/*
+ * For the APM stuff, the apmhook structure is kept
+ * separate from the slot structure so that the slot
+ * drivers do not need to know about the hooks (or the
+ * data structures).
+ */
+static int slot_suspend(void *arg);
+static int slot_resume(void *arg);
+static struct apmhook s_hook[MAXSLOT]; /* APM suspend */
+static struct apmhook r_hook[MAXSLOT]; /* APM resume */
+#endif /* NAPM > 0 */
static struct slot *pccard_slots[MAXSLOT]; /* slot entries */
static struct slot *slot_list;
@@ -221,6 +240,12 @@ pccard_remove_controller(struct slot_ctrl *cp)
last->next = next;
else
slot_list = next;
+#if NAPM > 0
+ apm_hook_disestablish(APM_HOOK_SUSPEND,
+ &s_hook[sp->slot]);
+ apm_hook_disestablish(APM_HOOK_RESUME,
+ &r_hook[sp->slot]);
+#endif
if (cp->extra && sp->cdata)
FREE(sp->cdata, M_DEVBUF);
FREE(sp, M_DEVBUF);
@@ -245,6 +270,21 @@ pccard_remove_controller(struct slot_ctrl *cp)
}
/*
+ * Power off the slot.
+ * (doing it immediately makes the removal of some cards unstable)
+ */
+static void
+power_off_slot(void *arg)
+{
+ struct slot *sp = (struct slot *)arg;
+
+ sp->pwr_off_pending = 0;
+
+ /* Power off the slot. */
+ sp->ctrl->disable(sp);
+}
+
+/*
* disable_slot - Disables the slot by removing
* the power and unmapping the I/O
*/
@@ -282,7 +322,8 @@ disable_slot(struct slot *sp)
}
}
/* Power off the slot. */
- sp->ctrl->disable(sp);
+ timeout(power_off_slot, (caddr_t)sp, hz / 4);
+ sp->pwr_off_pending = 1;
/* De-activate all contexts. */
for (i = 0; i < sp->ctrl->maxmem; i++)
@@ -298,6 +339,40 @@ disable_slot(struct slot *sp)
}
/*
+ * APM hooks for suspending and resuming.
+ */
+#if NAPM > 0
+static int
+slot_suspend(void *arg)
+{
+ struct slot *sp = arg;
+ struct pccard_dev *dp;
+
+ for (dp = sp->devices; dp; dp = dp->next)
+ (void) dp->drv->suspend(dp);
+ if (!sp->suspend_power)
+ sp->ctrl->disable(sp);
+ return (0);
+}
+
+static int
+slot_resume(void *arg)
+{
+ struct slot *sp = arg;
+ struct pccard_dev *dp;
+
+ if (!sp->suspend_power)
+ sp->ctrl->power(sp);
+ if (sp->irq)
+ sp->ctrl->mapirq(sp, sp->irq);
+ for (dp = sp->devices; dp; dp = dp->next)
+ (void) dp->drv->init(dp, 0);
+ return (0);
+}
+#endif /* NAPM > 0 */
+
+
+/*
* pccard_alloc_slot - Called from controller probe
* routine, this function allocates a new PC-CARD slot
* and initialises the data structures using the data provided.
@@ -345,6 +420,24 @@ pccard_alloc_slot(struct slot_ctrl *cp)
printf("PC-Card %s (%d mem & %d I/O windows)\n",
cp->name, cp->maxmem, cp->maxio);
}
+#if NAPM > 0
+ {
+ struct apmhook *ap;
+
+ ap = &s_hook[sp->slot];
+ ap->ah_fun = slot_suspend;
+ ap->ah_arg = (void *)sp;
+ ap->ah_name = cp->name;
+ ap->ah_order = APM_MID_ORDER;
+ apm_hook_establish(APM_HOOK_SUSPEND, ap);
+ ap = &r_hook[sp->slot];
+ ap->ah_fun = slot_resume;
+ ap->ah_arg = (void *)sp;
+ ap->ah_name = cp->name;
+ ap->ah_order = APM_MID_ORDER;
+ apm_hook_establish(APM_HOOK_RESUME, ap);
+ }
+#endif /* NAPM > 0 */
return(sp);
}
@@ -528,19 +621,26 @@ inserted(void *arg)
*/
sp->pwr.vcc = 50;
sp->pwr.vpp = 0;
+ untimeout(power_off_slot, (caddr_t)sp);
+ if (sp->pwr_off_pending)
+ sp->ctrl->disable(sp);
+ sp->pwr_off_pending = 0;
sp->ctrl->power(sp);
printf("Card inserted, slot %d\n", sp->slot);
/*
* Now start resetting the card.
*/
sp->ctrl->reset(sp);
+#if NAPM > 0
+ sp->suspend_power = 0;
+#endif
}
/*
* Insert/Remove beep
*/
-static int beepok = 1;
+static int beepok = 0;
static void enable_beep(void *dummy)
{
@@ -572,8 +672,10 @@ int s;
sp->state = empty;
splx(s);
printf("Card removed, slot %d\n", sp->slot);
- sysbeep(PCCARD_BEEP_PITCH0, PCCARD_BEEP_DURATION0);
- beepok = 0;
+ if (beepok) {
+ sysbeep(PCCARD_BEEP_PITCH0, PCCARD_BEEP_DURATION0);
+ beepok = 0;
+ }
timeout(enable_beep, (void *)NULL, hz/5);
selwakeup(&sp->selp);
}
@@ -581,8 +683,10 @@ int s;
case card_inserted:
sp->insert_seq = 1;
timeout(inserted, (void *)sp, hz/4);
- sysbeep(PCCARD_BEEP_PITCH0, PCCARD_BEEP_DURATION0);
- beepok = 0;
+ if (beepok) {
+ sysbeep(PCCARD_BEEP_PITCH0, PCCARD_BEEP_DURATION0);
+ beepok = 0;
+ }
timeout(enable_beep, (void *)NULL, hz/5);
break;
}
@@ -750,6 +854,9 @@ crdioctl(dev_t dev, int cmd, caddr_t data, int fflag, struct proc *p)
struct mem_desc *mp;
struct io_desc *ip;
+ /* beep is disabled until the 1st call of crdioctl() */
+ enable_beep(NULL);
+
if (sp == 0 && cmd != PIOCRWMEM)
return(ENXIO);
switch(cmd) {
diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c
index 5499dd3..456b251 100644
--- a/sys/pccard/pcic.c
+++ b/sys/pccard/pcic.c
@@ -630,6 +630,8 @@ pcic_probe ()
pcicintr, 0, &pcic_imask);
if (pcic_irq < 0)
printf("pcic: failed to allocate IRQ\n");
+ else
+ printf("pcic: controller irq %d\n", pcic_irq);
}
/*
* Check for a card in this slot.
@@ -800,7 +802,7 @@ pcic_reset(void *chan)
putb(sp, PCIC_TIME_CMD0, 0x6);
putb(sp, PCIC_TIME_RECOV0, 0x0);
putb(sp, PCIC_TIME_SETUP1, 1);
- putb(sp, PCIC_TIME_CMD1, 0x5F);
+ putb(sp, PCIC_TIME_CMD1, 0xf);
putb(sp, PCIC_TIME_RECOV1, 0);
}
selwakeup(&slotp->selp);
diff --git a/sys/pccard/slot.h b/sys/pccard/slot.h
index 42681e8..fb9b23e 100644
--- a/sys/pccard/slot.h
+++ b/sys/pccard/slot.h
@@ -125,6 +125,8 @@ struct slot {
struct power pwr; /* Power values */
struct slot_ctrl *ctrl; /* Per-controller data */
void *cdata; /* Controller specific data */
+ int suspend_power; /* Leave powered on during suspend */
+ int pwr_off_pending;/* Power status of slot */
#ifdef DEVFS
void *devfs_token;
#endif /* DEVFS*/
OpenPOWER on IntegriCloud