diff --git a/sys/i386/apm/apm.c b/sys/i386/apm/apm.c index f6b490ba06f3..e175cd52eac6 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 f6b490ba06f3..e175cd52eac6 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 6e2e03cbf9b6..3abdbd5cbf2f 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 8f42572d1991..3e3440a4b76a 100644 --- a/sys/pccard/pccard.c +++ b/sys/pccard/pccard.c @@ -54,6 +54,11 @@ #include #include +#include "apm.h" +#if NAPM > 0 +#include +#endif /* NAPM > 0 */ + #include #include #include @@ -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); @@ -244,6 +269,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++) @@ -297,6 +338,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 @@ -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 5499dd30cb1b..456b2518dfd2 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 42681e826f08..fb9b23e17fb6 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*/