Eric, for your viewing pleasure, patches to arch/i386/kernel/process.c


#define CONFIG_LINUXBIOS_PM
#ifdef CONFIG_LINUXBIOS_PM
#include <linux/pci.h>

// reset for sis 503
void
sis503_reset(struct pci_dev *dev)
{
        unsigned char b;
        unsigned short acpi_base;

        printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n");

        /* Enable ACPI by set B7 on Reg 0x40, LPC */
        pci_read_config_byte(dev, 0x40, &b);
        pci_write_config_byte(dev, 0x40, b | 0x80);
        printk(KERN_ERR __FUNCTION__ ": enabled ACPI. \n");

        /* get the ACPI base address for register 0x74,0x75 of LPC */
        pci_read_config_word(dev, 0x74, &acpi_base);
        printk(KERN_ERR __FUNCTION__ ":acpi base: %x\n", acpi_base);

        /* Set software watchdog timer init value */
        outb(0x03, 0x4a + acpi_base);
        printk(KERN_ERR __FUNCTION__ ": set the dog. \n");

        printk(KERN_ERR __FUNCTION__ ": enabling dog. \n");
        /* Software watchdog enable, issue PCIRST# when time expire */
        outb(0x8f, 0x4b + acpi_base);

        printk(KERN_ERR __FUNCTION__ ": We should reset soon. \n");
}

// power off for sis 503
void
sis503_off(struct pci_dev *dev)
{
        unsigned char b;
        unsigned short acpi_base;

        printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n");
        /* Enable ACPI by set B7 on Reg 0x40, LPC */
        pci_read_config_byte(dev, 0x40, &b);
        pci_write_config_byte(dev, 0x40, b | 0x80);
        printk(KERN_ERR __FUNCTION__ ": enabled ACPI. \n");

        /* get the ACPI base address for register 0x74,0x75 of LPC */
        pci_read_config_word(dev, 0x74, &acpi_base);
        printk (KERN_ERR __FUNCTION__ ":acpi base: %x\n", acpi_base);

        /* ACPI Register 5, Bit 10-12, Sleeping Type,
           set to 101 -> S5, soft_off */
        outb(0x14, 0x05 + acpi_base);
        printk(KERN_ERR __FUNCTION__ ": DONE setting sleep type. \n");

        /* ACPI Register 5, Bit 13, Sleep Enable */
        outb(0x20 | 0x14, 0x05 + acpi_base);
        printk(KERN_ERR __FUNCTION__ ": DONE sleep enable. \n");
}

struct linuxbios_control {
        u_short vendor, device;
        void (*poweroff)(struct pci_dev *);
        void (*reset)(struct pci_dev *);
};

struct linuxbios_control controls[] = {
        {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, sis503_off, sis503_reset}
};

// for the machine we're on, find the reset/power off control stuff. 
struct linuxbios_control *findcontrol(struct pci_dev **d)
{
        struct linuxbios_control *lb = controls, *retval = 0;
        int i;

        printk(KERN_ERR __FUNCTION__ ": Find vendor 0x%x device 0x%x\n",
               lb->vendor, lb->device);
        for(lb = controls, i = 0;
            (i < sizeof(controls)/sizeof(controls[0])) && (! retval);
            i++, lb++)
        {
                *d = pci_find_device(lb->vendor, lb->device, 0);
                if (*d)
                        retval = lb;
        }

        printk(KERN_ERR __FUNCTION__ ": result of find is %p\n", retval);
        return retval;
}

// power off in the linuxbios world
void
linuxbios_poweroff(void)
{
        struct linuxbios_control *lb = 0;
        struct pci_dev *dev;

        printk(KERN_ERR __FUNCTION__ ": find an lb\n");
        lb = findcontrol(&dev);

        printk(KERN_ERR __FUNCTION__ ": found lb %p, call %p\n",
               lb, lb ? lb->poweroff : 0);
        if (lb && (lb->poweroff))
                lb->poweroff(dev);
        printk(KERN_ERR __FUNCTION__ ": Returning? Can't happen, I
thought?\n");
}

// reset in the linuxbios world
void
linuxbios_reset(void)
{
        struct linuxbios_control *lb = 0;
        struct pci_dev *dev;

        printk(KERN_ERR __FUNCTION__ ": find an lb\n");
        lb = findcontrol(&dev);

        printk(KERN_ERR __FUNCTION__ ": found lb %p, call %p\n",
               lb, lb ? lb->reset : 0);
        if (lb && (lb->reset))
                lb->reset(dev);
        printk(KERN_ERR __FUNCTION__ ": Returning? Can't happen, I
thought?\n");
}

#endif


// modified for the linuxbios power off stuff.
void machine_power_off(void)
{
        printk("MACHINE_POWER_OFF\n");
#ifdef CONFIG_LINUXBIOS_PM
        linuxbios_poweroff();
#endif

        if (pm_power_off)
                pm_power_off();
}



Reply via email to