1 // Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org>
2 // This code is licensed to you under the terms of the GNU GPL, version 2;
3 // see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
8 // Low-level IPC access.
10 static u32 ipc_read(u32 reg)
12 return read32(0x0d000000 + 4*reg);
15 static void ipc_write(u32 reg, u32 value)
17 write32(0x0d000000 + 4*reg, value);
20 static void ipc_bell(u32 w)
22 ipc_write(1, (ipc_read(1) & 0x30) | w);
25 static void ipc_wait_ack(void)
27 while ((ipc_read(1) & 0x22) != 0x22)
31 static void ipc_wait_reply(void)
33 while ((ipc_read(1) & 0x14) != 0x14)
37 static void ipc_irq_ack(void)
39 ipc_write(12, 0x40000000);
43 // Mid-level IPC access.
52 } ipc __attribute__((aligned(64)));
54 static void ipc_send_request(void)
56 sync_after_write(&ipc, 0x40);
58 ipc_write(0, virt_to_phys(&ipc));
67 static void ipc_recv_reply(void)
80 if (reply == virt_to_phys(&ipc))
84 sync_before_read(&ipc, sizeof ipc);
88 // High-level IPC access.
90 int ios_open(const char *filename, u32 mode)
92 sync_after_write(filename, strlen(filename) + 1);
93 memset(&ipc, 0, sizeof ipc);
97 ipc.arg[0] = virt_to_phys(filename);
106 int ios_close(int fd)
108 memset(&ipc, 0, sizeof ipc);
120 int ios_read(int fd, void *data, u32 len)
122 memset(&ipc, 0, sizeof ipc);
126 ipc.arg[0] = virt_to_phys(data);
133 sync_before_read(data, len);
138 int ios_seek(int fd, int where, int whence)
140 memset(&ipc, 0, sizeof ipc);
154 int ios_ioctl(int fd, u32 n, const void *in, u32 inlen, void *out, u32 outlen)
156 memset(&ipc, 0, sizeof ipc);
159 sync_after_write(in, inlen);
161 sync_after_write(out, outlen);
166 ipc.arg[1] = virt_to_phys(in);
168 ipc.arg[3] = virt_to_phys(out);
175 sync_before_read(out, outlen);
180 int ios_ioctlv(int fd, u32 n, u32 in_count, u32 out_count, struct ioctlv *vec)
184 memset(&ipc, 0, sizeof ipc);
186 for (i = 0; i < in_count + out_count; i++)
188 sync_after_write(vec[i].data, vec[i].len);
189 vec[i].data = (void *)virt_to_phys(vec[i].data);
192 sync_after_write(vec, (in_count + out_count) * sizeof *vec);
197 ipc.arg[1] = in_count;
198 ipc.arg[2] = out_count;
199 ipc.arg[3] = virt_to_phys(vec);
204 for (i = in_count; i < in_count + out_count; i++)
206 vec[i].data = phys_to_virt((u32)vec[i].data);
207 sync_before_read(vec[i].data, vec[i].len);
214 // Cleanup any old state.
216 static void ipc_cleanup_reply(void)
218 if ((ipc_read(1) & 0x14) != 0x14)
228 static void ipc_cleanup_request(void)
230 if ((ipc_read(1) & 0x22) == 0x22)
234 static void releasse_old_stm_callback(void)
236 *((u32 *)0x80000018) = 0x00000014;
237 sync_after_write((void*)0x80000014, 8);
239 int fd = ios_open("/dev/stm/immediate",0);
241 printf("STM Immediate open failed!\n");
245 int err = ios_ioctl(fd, 0x3002, 0, 0, 0, 0);
246 if (err < 0 && err != -6)
247 printf("Eventhook release failed with code %d\n", err);
256 //printf("Flushing IPC transactions");
257 for (i = 0; i < 10; i++) {
258 ipc_cleanup_request();
264 //printf(" Done.\n");
266 //printf("Closing file descriptors...");
267 for (i = 0; i < 32; i++)
269 //printf(" Done.\n");
271 releasse_old_stm_callback();