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'
This commit is contained in:
Nate Williams 1996-04-23 16:03:08 +00:00
parent d9fd44dd79
commit ceff12b4c4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=15360
6 changed files with 121 additions and 16 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);
@ -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) {

View file

@ -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);

View file

@ -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*/