diff options
author | nate <nate@FreeBSD.org> | 1996-04-23 16:03:08 +0000 |
---|---|---|
committer | nate <nate@FreeBSD.org> | 1996-04-23 16:03:08 +0000 |
commit | 298d7dcd873991421a7d88124324aee9b16065fd (patch) | |
tree | b983a04d64d9a3fc2e560a452fdf34ac7ad9e577 /sys | |
parent | ceb677462bce88b520fd1537aee505485cc9de55 (diff) | |
download | FreeBSD-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'
Diffstat (limited to 'sys')
-rw-r--r-- | sys/i386/apm/apm.c | 4 | ||||
-rw-r--r-- | sys/i386/bios/apm.c | 4 | ||||
-rw-r--r-- | sys/i386/include/apm_bios.h | 4 | ||||
-rw-r--r-- | sys/pccard/pccard.c | 119 | ||||
-rw-r--r-- | sys/pccard/pcic.c | 4 | ||||
-rw-r--r-- | sys/pccard/slot.h | 2 |
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*/ |