openap-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[openap-cvs] : linux/arch/i386/wl11000 Makefile,NONE,1.1 config.c,NONE,1


From: David C Wang <address@hidden>
Subject: [openap-cvs] : linux/arch/i386/wl11000 Makefile,NONE,1.1 config.c,NONE,1.1 led.c,NONE,1.1 watchdog.c,NONE,1.1
Date: Tue, 14 May 2002 19:20:02 -0400

Update of /cvsroot/openap/linux/arch/i386/wl11000
In directory subversions:/tmp/cvs-serv15552/linux/arch/i386/wl11000

Added Files:
        Makefile config.c led.c watchdog.c 
Log Message:
updated linux kernel pristine sources to openap release 1.1


--- NEW FILE ---
#
# Makefile for Linux arch/i386/wl11000 source directory
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...

O_TARGET := wl11000.o

obj-y := config.o watchdog.o led.o

include $(TOPDIR)/Rules.make

--- NEW FILE ---
/*
   linux/arch/i386/wl11000/config.c 
   
   Initialize wl11000SA.
   
   Copyright (C) 2001-2002 Instant802 Networks Inc. , All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 2 of the License, or (at your option)
   any later version.  

   David Kimdon <address@hidden>, January 15, 2001:
     - Initial distribution.

*/

#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/time.h>

extern int wl11000_led_init(void);
extern int wl11000_watchdog_init(void);

spinlock_t wl11000_io_lock = SPIN_LOCK_UNLOCKED;

void __init wl11000_config(void) {
        struct timeval tv;

        /* We don't have a RTC on board.  The kernel doesn't know that and
         * gets a bogus value for the current time. Zero it. */
        tv.tv_sec = 0;
        tv.tv_usec = 0;
        do_settimeofday(&tv);
        
        wl11000_led_init();
        wl11000_watchdog_init();
}

--- NEW FILE ---
/*
   linux/arch/i386/wl11000/led.c 
   
   led driver for wl11000SA.
   
   Copyright (C) 2001-2002 Instant802 Networks Inc. , All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 2 of the License, or (at your option)
   any later version.  

   This driver controls the two GPIO connected LEDs on the wl11000SA board :
   wireless activity and wireless link.  
   
   There are three other LEDs that we don't touch : power, ethernet link and
   ethernet activity.

   David Kimdon <address@hidden>, January 15, 2001:
     - Initial distribution.

*/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/timer.h>
#include <asm/wl11000.h>

#define LED_BR_DELAY (HZ/2)
#define LED_RX 0x04
#define LED_BR 0x08

static int led_initialized = 0;

static struct timer_list led_timer;
static int led_br_blinking = 0;


void wl11000_set_led(unsigned int state)
{
        u16 leds = 0;
        unsigned long flags;

        if (!led_initialized)
                return;

        spin_lock_irqsave(&wl11000_io_lock, flags);
        outb(0xa8, 0x22);
        leds = 0xFF & inb(0x23);
        spin_unlock_irqrestore(&wl11000_io_lock, flags);

        switch (state) {

        case WL11000_LED_RX_ON:
                leds |= LED_RX;
                break;

        case WL11000_LED_RX_OFF:
                leds &= ~LED_RX;
                break;

        case WL11000_LED_BR_ON:
                led_br_blinking = 0;
                del_timer_sync(&led_timer);
                leds |= LED_BR;
                break;

        case WL11000_LED_BR_OFF:
                led_br_blinking = 0;
                del_timer_sync(&led_timer);
                leds &= ~LED_BR;
                break;

        case WL11000_LED_BR_BLINK:
                if (!led_br_blinking) {
                        led_br_blinking = 1;
                        led_timer.expires = jiffies + LED_BR_DELAY;
                        add_timer(&led_timer);
                }
                break;
        }

        outw(0xa8 | (leds << 8), 0x22);
}



static void led_br_blink(unsigned long unused)
{
        unsigned char led;
        unsigned long flags;

        spin_lock_irqsave(&wl11000_io_lock, flags);
        outb(0xa8, 0x22);
        led = inb(0x23);
        spin_unlock_irqrestore(&wl11000_io_lock, flags);

        if (led & LED_BR)
                led &= ~LED_BR;
        else
                led |= LED_BR;

        outw(0xa8 | (led << 8), 0x22);

        if (led_br_blinking) {
                led_timer.expires = jiffies + LED_BR_DELAY;
                add_timer(&led_timer);
        }
}


int __init wl11000_led_init(void)
{
        wl11000_set_led(WL11000_LED_RX_OFF);
        wl11000_set_led(WL11000_LED_BR_OFF);

        init_timer(&led_timer);
        led_timer.function = led_br_blink;
        led_timer.data = 0;

        led_br_blinking = 0;
        led_initialized = 1;

        return 0;
}

static void __exit wl11000_led_cleanup(void)
{
        wl11000_set_led(WL11000_LED_RX_OFF);
        wl11000_set_led(WL11000_LED_BR_OFF);
        led_br_blinking = 0;
        del_timer(&led_timer);
}

module_init(wl11000_led_init);
module_exit(wl11000_led_cleanup);

--- NEW FILE ---
/*
   linux/arch/i386/wl11000/watchdog.c 
   
   Watchdog driver for wl11000SA.
   
   Copyright (C) 2001-2002 Instant802 Networks Inc. , All Rights Reserved.

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 2 of the License, or (at your option)
   any later version.  

   The underlying watchdog is a Microchip Technology Inc. TC1232.  The TC1232
   is connected to GPIO 30 (watchdog enable/disable) and 31 (watchdog clock).
   The watchdog is disabled by the bootloader and enabeld here.  When the
   watchdog is enabled (GPIO 31 = 1) the clock (GPIO 31) needs to be toggled
   every 600 ms.

   This driver is a combination of a software and a hardware watchdog.  This
   allows us to monitor userspace without imposing timing requirements on it
   that it can't commit to.  At very small intervals wl11000_watchdog_ack() is
   called.  It considers whether or not we should ack the hardware watchdog.
   If we have heard from userspace recently we'll ack the watchdog, otherwise
   we don't and allow the machine to reboot.

   To disable the watchdog (for example while reflashing the unit) an ioctl is
   available.
   
   David Kimdon <address@hidden>, January 15, 2001:
     - Initial distribution.

*/

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>

#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/wl11000.h>

#define OUR_NAME "wl11000 watchdog"
#define KERNELSPACE_PERIOD (HZ/20)
#define USERSPACE_PERIOD (HZ * 60)

#define CONFIG_WATCHDOG_NOWAYOUT 1

/* 
 Cutoff for the next userspace ping.  If we don't get something in time we'll
 allow the hardware watchdog to reboot us.
*/
static unsigned long next_userspace;

static unsigned int watchdog_enabled = 0;
static unsigned int watchdog_is_open = 0;
static struct timer_list watchdog_timer;


static inline void watchdog_schedule_ack(void)
{
        watchdog_timer.expires = jiffies + KERNELSPACE_PERIOD;
        add_timer(&watchdog_timer);
}


void wl11000_watchdog_ack(unsigned long reschedule)
{
        unsigned long flags;
        unsigned int dog;

        if (watchdog_enabled) {

                if (time_before(jiffies, next_userspace)) {
                        spin_lock_irqsave(&wl11000_io_lock, flags);
                        outb(0xa9, 0x22);
                        dog = 0xFF & inb(0x23);
                        spin_unlock_irqrestore(&wl11000_io_lock, flags);

                        if (dog & 0x80) {
                                outw(0x40a9, 0x22);
                        } else {
                                outw(0xC0a9, 0x22);
                        }

                } else {
                        printk(OUR_NAME
                               ": userspace ping not received.\n");
                }

                if (reschedule) {
                        watchdog_schedule_ack();
                }
        }
}


static ssize_t watchdog_write(struct file *file, const char *inbuf,
                              size_t size, loff_t * off)
{
        if (size) {
                next_userspace = jiffies + USERSPACE_PERIOD;
                return 1;
        }
        return 0;
}


static void watchdog_enable(void)
{
        next_userspace = jiffies + USERSPACE_PERIOD;
        watchdog_enabled = 1;
        watchdog_schedule_ack();
        outw(0x40a9, 0x22);     /* enable hardware watchdog */
        printk(KERN_INFO OUR_NAME
               ": enabled. userspace %d s, kernelspace %d ms.\n",
               USERSPACE_PERIOD / HZ, KERNELSPACE_PERIOD * 1000 / HZ);
}

static int watchdog_open(struct inode *inode, struct file *file)
{
        switch (MINOR(inode->i_rdev)) {
        case WATCHDOG_MINOR:
                if (watchdog_is_open) {
                        return -EBUSY;
                }

                if (!watchdog_enabled) {
                        watchdog_enable();
                }
                watchdog_is_open = 1;
                MOD_INC_USE_COUNT;
                break;
        default:
                return -ENODEV;
        }
        return 0;
}


/*
   If the watchdog is already disabled when the device is closed (presumably
   because someone used the WDIOS_DISABLECARD ioctl) we don't touch the state
   of the watchdog.  This way even if CONFIG_WATCHDOG_NOWAYOUT is defined it is
   possible to disable the watchdog once it has been enabled, but it isn't as
   simple as just closing the device.  
*/
static int watchdog_release(struct inode *inode, struct file *file)
{
        if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
                if (watchdog_enabled) {
                        watchdog_enabled = 0;
                        del_timer_sync(&watchdog_timer);
#ifndef CONFIG_WATCHDOG_NOWAYOUT
                        outw(0x80a9, 0x22);     /* disable hardware watchdog */
                        printk(KERN_INFO OUR_NAME ": disabled.\n");
#endif
                }
                watchdog_is_open = 0;
                MOD_DEC_USE_COUNT;
        }
        return 0;
}

static int watchdog_ioctl(struct inode *inode, struct file *file,
                          unsigned int cmd, unsigned long arg)
{
        int rv;

        switch (cmd) {

        default:
                return -ENOTTY;

        case WDIOC_SETOPTIONS:
                if (copy_from_user(&rv, (int *) arg, sizeof(int)))
                        return -EFAULT;

                if (rv & WDIOS_DISABLECARD) {
                        if (watchdog_enabled) {
                                watchdog_enabled = 0;
                                del_timer_sync(&watchdog_timer);
                                outw(0x80a9, 0x22);     /* disable hardware 
watchdog */
                                printk(KERN_INFO OUR_NAME ": disabled.\n");
                        }
                }

                if (rv & WDIOS_ENABLECARD) {
                        if (!watchdog_enabled) {
                                watchdog_enable();
                        }
                }
                return 0;
        }

}


struct file_operations watchdog_fops = {
        write:watchdog_write,
        open:watchdog_open,
        release:watchdog_release,
        ioctl:watchdog_ioctl,
};


static struct miscdevice watchdog_miscdev = {
        WATCHDOG_MINOR,
        "watchdog",
        &watchdog_fops
};


int __init wl11000_watchdog_init(void)
{
        misc_register(&watchdog_miscdev);
        init_timer(&watchdog_timer);
        watchdog_timer.function = wl11000_watchdog_ack;
        watchdog_timer.data = 1;

        return 0;
}


void __exit wl11000_watchdog_cleanup(void)
{
        misc_deregister(&watchdog_miscdev);
}

module_init(wl11000_watchdog_init);
module_exit(wl11000_watchdog_cleanup);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]