port-work; won't compile or even work
[ppcskel.git] / input.c
1 /*
2         BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader.
3         Requires mini.
4
5         Input-handling functions for BootMii. Inspired by GC_PAD.c from GCLIB.
6
7 Copyright (C) 2008, 2009        Haxx Enterprises <bushing@gmail.com>
8 Copyright (C) 2009              Andre Heider "dhewg" <dhewg@wiibrew.org>
9 Copyright (C) 2009              John Kelley <wiidev@kelley.ca>
10 Copyright (C) 2009              bLAStY <blasty@bootmii.org>
11
12 # This code is licensed to you under the terms of the GNU GPL, version 2;
13 # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
14 */
15
16 #include "bootmii_ppc.h"
17 #include "input.h"
18 #include "string.h"
19
20 #define PADREG(x) (0xCD006400 + (x)*4)
21
22 static GC_Pad _pad;
23
24 static void gcpad_init(void) { 
25         write32(PADREG(0), 0x00400300); // read pad on channel 1
26         write32(PADREG(3), 0x00400300);
27         write32(PADREG(6), 0x00400300);
28         write32(PADREG(8), 0x00400300);
29         write32(PADREG(12), 0x000701f0); // enable poll chan 1, X = 7, Y = 1
30         write32(PADREG(14), 0x80000000); // transfer all buffer
31 }
32
33 static void gpio_init(void) {
34         // setup power and eject button hollywood IRQ for PPC
35         mask32(0x0d8000fc, 0, 0x41); // set GPIO owner to PPC
36         mask32(0x0d80003c, 1<<10, 0);
37         mask32(0x0d800034, 0, 1<<10);
38         mask32(0x0d8000d4, 0, 0x41);
39         mask32(0x0d8000cc, 0, 0x41);
40 }
41
42 void input_init(void) {
43         memset(&_pad, 0, sizeof(GC_Pad));
44
45         gpio_init();
46         gcpad_init();
47
48         // Check for any pending GPIO irq's, which should be ACK'd so we don't get ghost presses later.
49         // Try over and over again, until we are out of them.
50         while (read32(0x0d800030) & (1<<10)) {
51                 if (read32(0x0d8000f0) & 1) {
52                         while(read32(0x0d8000c8) & 1);
53                         write32(0x0d8000d0, 1);
54                 } else if (read32(0x0d8000f0) & 0x40) {
55                         write32(0x0d8000d0, 0x40);
56                 }
57
58                 write32(0x0d800030, 1<<10);
59         }
60
61         // No IRQ's left to be ACK'd, continue our business.
62 }
63
64 u16 pad_read(GC_Pad *pad, int chan) {
65         u32 pdata = read32(PADREG(3 * chan + 1));
66         u32 pdata2 = read32(PADREG(3 * chan + 2));
67
68         u16 btns = pdata >> 16;
69
70         if (pad) {
71                 u16 prev = pad->btns_held;
72
73                 pad->btns_held = btns;
74                 pad->btns_up = prev & ~btns;
75                 pad->btns_down = btns & (btns ^ prev);
76
77                 pad->x = 128 + ((pdata >> 8) & 0xff);
78                 pad->y = 128 - (pdata & 0xff);
79
80                 pad->cx = 128 + (pdata2 >> 24);
81                 pad->cy = 128 - ((pdata2 >> 16) & 0xff);
82                 pad->l = (pdata2 >> 8) & 0xff;
83                 pad->r = pdata2 & 0xff;
84
85                 return pad->btns_down;
86         }
87
88         return btns;
89 }
90
91 // TODO: Hackity hack, prevent ghost presses
92 static u8 reset_delay = 5;
93
94
95 u16 gpio_read(void) {
96         u16 res = 0;
97         u32 irq_flag = 0;
98
99         if (!((read32(0x0C003000) >> 16) & 1) && reset_delay == 0) {
100                 res |= GPIO_RESET;
101                 reset_delay = 5;
102         }
103
104         if (reset_delay > 0)
105                 reset_delay--;
106
107         if (read32(0x0d800030) & (1<<10)) {
108                 irq_flag = read32(0x0d8000f0);
109
110                 if (irq_flag & 1) {
111                         res |= GPIO_POWER;
112
113                         while(read32(0x0d8000c8) & 1);
114                         write32(0x0d8000d0, 1);
115                 } else if (irq_flag & 0x40) {
116                         res |= GPIO_EJECT;
117
118                         while(read32(0x0d8000c8) & 0x40);
119                         write32(0x0d8000d0, 0x40);
120                 }
121
122                 write32(0x0d800030, 1<<10); // ack GPIO irq
123         }
124
125         return res;
126 }
127
128 u16 input_read(void) {
129         return pad_read(&_pad, 0) | gpio_read();
130 }
131
132 u16 input_wait(void) {
133         u16 res;
134
135         do {
136                 udelay(20000);
137                 res = input_read();
138         } while (!(res & PAD_ANY));
139         
140         return res;
141 }
142