aboutsummaryrefslogtreecommitdiffstats
path: root/roms/SLOF/slof/ppc64.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/SLOF/slof/ppc64.c')
-rw-r--r--roms/SLOF/slof/ppc64.c280
1 files changed, 280 insertions, 0 deletions
diff --git a/roms/SLOF/slof/ppc64.c b/roms/SLOF/slof/ppc64.c
new file mode 100644
index 000000000..ca6cafffc
--- /dev/null
+++ b/roms/SLOF/slof/ppc64.c
@@ -0,0 +1,280 @@
+/******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <cpu.h>
+
+void asm_cout(long Character,long UART,long NVRAM);
+
+/* the exception frame should be page aligned
+ * the_exception_frame is used by the handler to store a copy of all
+ * registers after an exception; this copy can then be used by paflof's
+ * exception handler to printout a register dump */
+cell the_exception_frame[0x400 / CELLSIZE] __attribute__ ((aligned(PAGE_SIZE)));;
+
+/* the_client_frame is the register save area when starting a client */
+cell the_client_frame[0x1000 / CELLSIZE] __attribute__ ((aligned(0x100)));
+cell the_client_stack[0x8000 / CELLSIZE] __attribute__ ((aligned(0x100)));
+/* THE forth stack */
+cell the_data_stack[0x2000 / CELLSIZE] __attribute__ ((aligned(0x100)));
+/* the forth return stack */
+cell the_return_stack[0x2000 / CELLSIZE] __attribute__ ((aligned(0x100)));
+
+/* forth stack and return-stack pointers */
+cell *restrict dp;
+cell *restrict rp;
+
+/* terminal input buffer */
+cell the_tib[0x1000 / CELLSIZE] __attribute__ ((aligned(0x100)));
+/* temporary string buffers */
+char the_pockets[NUMPOCKETS * POCKETSIZE] __attribute__ ((aligned(0x100)));
+
+cell the_comp_buffer[0x1000 / CELLSIZE] __attribute__ ((aligned(0x100)));
+
+cell the_heap[HEAP_SIZE / CELLSIZE] __attribute__ ((aligned(0x1000)));
+cell *the_heap_start = &the_heap[0];
+cell *the_heap_end = &the_heap[HEAP_SIZE / CELLSIZE];
+
+extern void io_putchar(unsigned char);
+extern unsigned long call_c(cell arg0, cell arg1, cell arg2, cell entry);
+
+
+static long writeLogByte_wrapper(long x, long y)
+{
+ unsigned long result;
+
+ SET_CI;
+ result = writeLogByte(x, y);
+ CLR_CI;
+
+ return result;
+}
+
+
+/**
+ * Standard write function for the libc.
+ *
+ * @param fd file descriptor (should always be 1 or 2)
+ * @param buf pointer to the array with the output characters
+ * @param count number of bytes to be written
+ * @return the number of bytes that have been written successfully
+ */
+ssize_t write(int fd, const void *buf, size_t count)
+{
+ char *ptr = (char *)buf;
+ int len;
+
+ if (fd != 1 && fd != 2)
+ return 0;
+
+ if (!init_engine || fd == 2) {
+ len = count;
+ while (len-- > 0) {
+ if (*ptr == '\n')
+ io_putchar('\r');
+ io_putchar(*ptr++);
+ }
+ return count;
+ }
+
+ while ((ptr = strchr(buf, '\n')) != NULL) {
+ forth_push((long)buf);
+ forth_push((long)ptr - (long)buf);
+ forth_eval("type cr");
+ buf = ptr + 1;
+ }
+ len = strlen(buf);
+ if (len) {
+ forth_push((long)buf);
+ forth_push(len);
+ forth_eval("type");
+ }
+
+ return count;
+}
+
+/* This should probably be temporary until a better solution is found */
+void
+asm_cout(long Character, long UART, long NVRAM __attribute__((unused)))
+{
+ if (UART)
+ io_putchar(Character);
+}
+
+static type_u find_method(type_u phandle, const char *name)
+{
+ forth_push((type_u)name);
+ forth_push(strlen(name));
+ forth_push(phandle);
+ forth_eval("find-method");
+ if (forth_pop())
+ return forth_pop();
+
+ return 0;
+}
+
+#define FILEIO_TYPE_EMPTY 0
+#define FILEIO_TYPE_FILE 1
+#define FILEIO_TYPE_SOCKET 2
+
+struct fileio_type {
+ int type;
+ type_u read_xt;
+ type_u write_xt;
+};
+
+#define FILEIO_MAX 32
+static struct fileio_type fd_array[FILEIO_MAX];
+
+int socket(int domain, int type, int proto, char *mac_addr)
+{
+ const char mac_prop_name[] = "local-mac-address";
+ type_u phandle;
+ uint8_t *prop_addr;
+ int prop_len;
+ int fd;
+
+ if (!(domain == AF_INET || domain == AF_INET6))
+ return -1;
+
+ if (type != SOCK_DGRAM || proto != 0)
+ return -1;
+
+ /* search free file descriptor (and skip stdio handlers) */
+ for (fd = 3; fd < FILEIO_MAX; ++fd) {
+ if (fd_array[fd].type == FILEIO_TYPE_EMPTY) {
+ break;
+ }
+ }
+ if (fd == FILEIO_MAX) {
+ puts("Can not open socket, file descriptor list is full");
+ return -2;
+ }
+
+ /* Assume that obp-tftp package is the current one, so
+ * my-parent is the NIC node that we are interested in */
+ forth_eval("my-parent ?dup IF ihandle>phandle THEN");
+ phandle = forth_pop();
+ if (phandle == 0) {
+ puts("Can not open socket, no parent instance");
+ return -1;
+ }
+ fd_array[fd].read_xt = find_method(phandle, "read");
+ if (!fd_array[fd].read_xt) {
+ puts("Can not open socket, no 'read' method");
+ return -1;
+ }
+ fd_array[fd].write_xt = find_method(phandle, "write");
+ if (!fd_array[fd].write_xt) {
+ puts("Can not open socket, no 'write' method");
+ return -1;
+ }
+
+ /* Read MAC address from device */
+ forth_push((unsigned long)mac_prop_name);
+ forth_push(strlen(mac_prop_name));
+ forth_push(phandle);
+ forth_eval("get-property");
+ if (forth_pop())
+ return -1;
+ prop_len = forth_pop();
+ prop_addr = (uint8_t *)forth_pop();
+ memcpy(mac_addr, &prop_addr[prop_len - 6], 6);
+
+ fd_array[fd].type = FILEIO_TYPE_SOCKET;
+
+ return fd;
+}
+
+static inline int is_valid_fd(int fd)
+{
+ return fd >= 0 && fd < FILEIO_MAX &&
+ fd_array[fd].type != FILEIO_TYPE_EMPTY;
+}
+
+int close(int fd)
+{
+ if (!is_valid_fd(fd))
+ return -1;
+
+ fd_array[fd].type = FILEIO_TYPE_EMPTY;
+
+ return 0;
+}
+
+/**
+ * Standard recv function for the libc.
+ *
+ * @param fd socket file descriptor
+ * @param buf pointer to the array where the packet should be stored
+ * @param len maximum length in bytes of the packet
+ * @param flags currently unused, should be 0
+ * @return the number of bytes that have been received successfully
+ */
+int recv(int fd, void *buf, int len, int flags)
+{
+ if (!is_valid_fd(fd) || flags)
+ return -1;
+
+ forth_push((unsigned long)buf);
+ forth_push(len);
+ forth_push(fd_array[fd].read_xt);
+ return forth_eval_pop("EXECUTE");
+}
+
+/**
+ * Standard send function for the libc.
+ *
+ * @param fd socket file descriptor
+ * @param buf pointer to the array with the output packet
+ * @param len length in bytes of the packet
+ * @param flags currently unused, should be 0
+ * @return the number of bytes that have been sent successfully
+ */
+int send(int fd, const void *buf, int len, int flags)
+{
+ if (!is_valid_fd(fd) || flags)
+ return -1;
+
+ forth_push((unsigned long)buf);
+ forth_push(len);
+ forth_push(fd_array[fd].write_xt);
+ return forth_eval_pop("EXECUTE");
+
+}
+
+/**
+ * Standard read function for the libc.
+ *
+ * @param fd file descriptor (should always be 0 or 2)
+ * @param buf pointer to the array with the output characters
+ * @param len number of bytes to be read
+ * @return the number of bytes that have been read successfully
+ */
+ssize_t read(int fd, void *buf, size_t len)
+{
+ char *ptr = (char *)buf;
+ unsigned cnt = 0;
+ char code;
+
+ if (fd == 0 || fd == 2) {
+ while (cnt < len) {
+ code = forth_eval_pop("key? IF key ELSE 0 THEN");
+ if (!code)
+ break;
+ ptr[cnt++] = code;
+ }
+ }
+
+ return cnt;
+}