summaryrefslogtreecommitdiff
path: root/obsolete-buildroot/sources/openwrt-diag.c
blob: 73bdac918e0591678d305dbbb52b9e5fddd7b9b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// replacement diag module
// (c) 2004 openwrt 
// mbm at alt dot org
//
// initial release 2004/03/28

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/sysctl.h>
#include <asm/io.h>
#include <typedefs.h>
#include <bcm4710.h>
#include <sbutils.h>

static void *sbh;

// v2.x - - - - -
#define DIAG_GPIO (1<<1)
#define DMZ_GPIO  (1<<7)

static void set_gpio(uint32 mask, uint32 value) {
	sb_gpiocontrol(sbh,mask,0);
	sb_gpioouten(sbh,mask,mask);
	sb_gpioout(sbh,mask,value);
}

static void v2_set_diag(u8 state) {
	set_gpio(DIAG_GPIO,state);
}
static void v2_set_dmz(u8 state) {
	set_gpio(DMZ_GPIO,state);
}

// v1.x - - - - -
#define LED_DIAG   0x13
#define LED_DMZ    0x12

static void v1_set_diag(u8 state) {
	if (!state) {
		*(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF;
	} else {
		*(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG);
	}
}
static void v1_set_dmz(u8 state) {
	if (!state) {
		*(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF;
	} else {
		*(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ);
	}
}

// - - - - -
#define BIT_DMZ         0x01
#define BIT_DIAG        0x04

void (*set_diag)(u8 state);
void (*set_dmz)(u8 state);

static unsigned int diag = 0;
static struct timer_list timer;

static void diag_change()
{
	printk(KERN_INFO "led -> %02x\n",diag);

	set_diag(0xFF); // off
	set_dmz(0xFF); // off

	if(diag & BIT_DIAG)
		set_diag(0x00); // on
	if(diag & BIT_DMZ)
		set_dmz(0x00); // on
}

static int proc_diag(ctl_table *table, int write, struct file *filp,
		void *buffer, size_t *lenp)
{
	int r;
	r = proc_dointvec(table, write, filp, buffer, lenp);
	if (write && !r) {
		diag_change();
	}
	return r;
}

// - - - - -
static struct ctl_table_header *diag_sysctl_header;

static ctl_table sys_diag[] = {
         { 
	   ctl_name: 2000,
	   procname: "diag", 
	   data: &diag,
	   maxlen: sizeof(diag), 
	   mode: 0644,
	   proc_handler: proc_diag
	 },
         { 0 }
};

static int __init diag_init()
{
	u32 board_type;
	sbh = sb_kattach();
	sb_gpiosetcore(sbh);

	board_type = sb_boardtype(sbh);
	printk(KERN_INFO "diag board_type: %08x\n",board_type);

	if (board_type & 0x400) {
		board_type=1;
		set_diag=v1_set_diag;
		set_dmz=v1_set_dmz;
	} else {
		board_type=2;
		set_diag=v2_set_diag;
		set_dmz=v2_set_dmz;
	}
	printk(KERN_INFO "using v%d hardware\n",board_type);

	diag_sysctl_header = register_sysctl_table(sys_diag, 0);
	diag_change();

	return 0;
}

static void __exit diag_exit()
{
	unregister_sysctl_table(diag_sysctl_header);
	del_timer(&timer);
}

module_init(diag_init);
module_exit(diag_exit);