This list is closed, nobody may subscribe to it.
2004 |
Jan
(53) |
Feb
(78) |
Mar
(34) |
Apr
(26) |
May
(25) |
Jun
(34) |
Jul
(16) |
Aug
(16) |
Sep
(2) |
Oct
(58) |
Nov
(13) |
Dec
(32) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(62) |
Feb
(4) |
Mar
(40) |
Apr
(9) |
May
(13) |
Jun
(26) |
Jul
(32) |
Aug
(24) |
Sep
(18) |
Oct
(18) |
Nov
(14) |
Dec
|
2006 |
Jan
(15) |
Feb
(2) |
Mar
(23) |
Apr
(2) |
May
(2) |
Jun
(13) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2007 |
Jan
(1) |
Feb
(45) |
Mar
|
Apr
(13) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(31) |
Dec
(5) |
2008 |
Jan
(6) |
Feb
(34) |
Mar
(113) |
Apr
(40) |
May
(19) |
Jun
(5) |
Jul
(41) |
Aug
(13) |
Sep
(53) |
Oct
(4) |
Nov
(53) |
Dec
|
2009 |
Jan
(1) |
Feb
(29) |
Mar
(66) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(163) |
Nov
|
Dec
(91) |
From: <rob...@us...> - 2005-01-09 20:36:32
|
Update of /cvsroot/gc-linux/ipl/dolup In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1053/dolup Removed Files: dolup.c dolup.h Log Message: deleted dir dolup. files were already moved to /load --- dolup.c DELETED --- --- dolup.h DELETED --- |
From: <rob...@us...> - 2005-01-09 12:26:54
|
Update of /cvsroot/gc-linux/ipl/include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23177 Added Files: block.h dolup.h fat.h file.h lowmem.h sd.h sram.h Log Message: Forgot to add some moved include files to the repository --- NEW FILE: block.h --- #ifndef __BLOCK_H #define __BLOCK_H typedef struct { int dev; int (*block_read)(int dev, int start, int size, void *buffer); } block_dev_desc_t; #endif --- NEW FILE: dolup.h --- /* * Copyright (c) 2001-2003 Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. * * Author: Adam Dunkels <ad...@si...> * */ #ifndef __DOLUP_H__ #define __DOLUP_H__ void dolup_init(void); #endif /* __HTTPD_H__ */ --- NEW FILE: fat.h --- /* * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg * * 2002-07-28 - rj...@ne... - ported to ppcboot v1.1.6 * 2003-03-10 - kh...@ne... - ported to u-boot * * See file CREDITS for list of people who contributed to this * project. * * 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 program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * */ #ifndef _FAT_H_ #define _FAT_H_ #include <linux/types.h> #include "block.h" #define CONFIG_SUPPORT_VFAT #define SECTOR_SIZE FS_BLOCK_SIZE #define FS_BLOCK_SIZE 512 #if FS_BLOCK_SIZE != SECTOR_SIZE #error FS_BLOCK_SIZE != SECTOR_SIZE - This code needs to be fixed! #endif #define MAX_CLUSTSIZE 65536 #define DIRENTSPERBLOCK (FS_BLOCK_SIZE/sizeof(dir_entry)) #define DIRENTSPERCLUST ((mydata->clust_size*SECTOR_SIZE)/sizeof(dir_entry)) #define FATBUFBLOCKS 6 #define FATBUFSIZE (FS_BLOCK_SIZE*FATBUFBLOCKS) #define FAT12BUFSIZE ((FATBUFSIZE*2)/3) #define FAT16BUFSIZE (FATBUFSIZE/2) #define FAT32BUFSIZE (FATBUFSIZE/4) /* Filesystem identifiers */ #define FAT12_SIGN "FAT12 " #define FAT16_SIGN "FAT16 " #define FAT32_SIGN "FAT32 " #define SIGNLEN 8 /* File attributes */ #define ATTR_RO 1 #define ATTR_HIDDEN 2 #define ATTR_SYS 4 #define ATTR_VOLUME 8 #define ATTR_DIR 16 #define ATTR_ARCH 32 #define ATTR_VFAT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) #define DELETED_FLAG ((char)0xe5) /* Marks deleted files when in name[0] */ #define aRING 0x05 /* Used to represent 'å' in name[0] */ /* Indicates that the entry is the last long entry in a set of long * dir entries */ #define LAST_LONG_ENTRY_MASK 0x40 /* Flags telling whether we should read a file or list a directory */ #define LS_NO 0 #define LS_YES 1 #define LS_DIR 1 #define LS_ROOT 2 #ifdef DEBUG #define FAT_DPRINT(args...) printf(args) #else #define FAT_DPRINT(args...) #endif #define FAT_ERROR(arg) printf(arg) #define ISDIRDELIM(c) ((c) == '/' || (c) == '\\') #define FSTYPE_NONE (-1) #if defined(__linux__) && defined(__KERNEL__) #define FAT2CPU16 le16_to_cpu #define FAT2CPU32 le32_to_cpu #else #if __LITTLE_ENDIAN #define FAT2CPU16(x) (x) #define FAT2CPU32(x) (x) #else #define FAT2CPU16(x) ((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8)) #define FAT2CPU32(x) ((((x) & 0x000000ff) << 24) | \ (((x) & 0x0000ff00) << 8) | \ (((x) & 0x00ff0000) >> 8) | \ (((x) & 0xff000000) >> 24)) #endif #endif #define TOLOWER(c) if((c) >= 'A' && (c) <= 'Z'){(c)+=('a' - 'A');} #define START(dent) (FAT2CPU16((dent)->start) \ + (mydata->fatsize != 32 ? 0 : \ (FAT2CPU16((dent)->starthi) << 16))) typedef struct boot_sector { __u8 ignored[3]; /* Bootstrap code */ char system_id[8]; /* Name of fs */ __u8 sector_size[2]; /* Bytes/sector */ __u8 cluster_size; /* Sectors/cluster */ __u16 reserved; /* Number of reserved sectors */ __u8 fats; /* Number of FATs */ __u8 dir_entries[2]; /* Number of root directory entries */ __u8 sectors[2]; /* Number of sectors */ __u8 media; /* Media code */ __u16 fat_length; /* Sectors/FAT */ __u16 secs_track; /* Sectors/track */ __u16 heads; /* Number of heads */ __u32 hidden; /* Number of hidden sectors */ __u32 total_sect; /* Number of sectors (if sectors == 0) */ /* FAT32 only */ __u32 fat32_length; /* Sectors/FAT */ __u16 flags; /* Bit 8: fat mirroring, low 4: active fat */ __u8 version[2]; /* Filesystem version */ __u32 root_cluster; /* First cluster in root directory */ __u16 info_sector; /* Filesystem info sector */ __u16 backup_boot; /* Backup boot sector */ __u16 reserved2[6]; /* Unused */ } boot_sector; typedef struct volume_info { __u8 drive_number; /* BIOS drive number */ __u8 reserved; /* Unused */ __u8 ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */ __u8 volume_id[4]; /* Volume ID number */ char volume_label[11]; /* Volume label */ char fs_type[8]; /* Typically FAT12, FAT16, or FAT32 */ /* Boot code comes next, all but 2 bytes to fill up sector */ /* Boot sign comes last, 2 bytes */ } volume_info; typedef struct dir_entry { char name[8],ext[3]; /* Name and extension */ __u8 attr; /* Attribute bits */ __u8 lcase; /* Case for base and extension */ __u8 ctime_ms; /* Creation time, milliseconds */ __u16 ctime; /* Creation time */ __u16 cdate; /* Creation date */ __u16 adate; /* Last access date */ __u16 starthi; /* High 16 bits of cluster in FAT32 */ __u16 time,date,start;/* Time, date and first cluster */ __u32 size; /* File size in bytes */ } dir_entry; typedef struct dir_slot { __u8 id; /* Sequence number for slot */ __u8 name0_4[10]; /* First 5 characters in name */ __u8 attr; /* Attribute byte */ __u8 reserved; /* Unused */ __u8 alias_checksum;/* Checksum for 8.3 alias */ __u8 name5_10[12]; /* 6 more characters in name */ __u16 start; /* Unused */ __u8 name11_12[4]; /* Last 2 characters in name */ } dir_slot; /* Private filesystem parameters */ typedef struct { int fatsize; /* Size of FAT in bits */ __u16 fatlength; /* Length of FAT in sectors */ __u16 fat_sect; /* Starting sector of the FAT */ __u16 rootdir_sect; /* Start sector of root directory */ __u16 clust_size; /* Size of clusters in sectors */ short data_begin; /* The sector of the first cluster, can be negative */ __u8 fatbuf[FATBUFSIZE]; /* Current FAT buffer */ int fatbufnum; /* Used by get_fatent, init to -1 */ } fsdata; typedef int (file_detectfs_func)(void); typedef int (file_ls_func)(const char *dir); typedef long (file_read_func)(const char *filename, void *buffer, unsigned long maxsize); struct filesystem { file_detectfs_func *detect; file_ls_func *ls; file_read_func *read; const char name[12]; }; /* FAT tables */ file_detectfs_func file_fat_detectfs; file_ls_func file_fat_ls; file_read_func file_fat_read; /* Currently this doesn't check if the dir exists or is valid... */ int file_cd(const char *path); int file_fat_detectfs(void); int file_fat_ls(const char *dir); long file_fat_read(const char *filename, void *buffer, unsigned long maxsize); const char *file_getfsname(int idx); int fat_register_device(block_dev_desc_t *dev_desc, int pbr_offset); #endif /* _FAT_H_ */ --- NEW FILE: file.h --- #ifndef __file_h #define __file_h long file_read(const char *filename, void *buffer, unsigned long maxsize); #endif --- NEW FILE: lowmem.h --- #ifndef __lowmem_h #define __lowmem_h #define lowmem_current_video_mode *((unsigned long*)0x800000CC) #endif --- NEW FILE: sd.h --- #ifndef _SD_H_ #define _SD_H_ void sd_boot(void); #endif --- NEW FILE: sram.h --- #ifndef __sram_h #define __sram_h void sram_set_videomode(int v); int sram_get_videomode(void); void sram_set_autoboot(int v); int sram_get_autoboot(void); struct ip_addr *sram_get_ip(int w); void sram_load_defaults(void); void read_sram(void); void write_sram(void); #endif |
From: <rob...@us...> - 2005-01-09 11:40:58
|
Update of /cvsroot/gc-linux/ipl/disk In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5953/disk Modified Files: fat.c file.c sd.c Removed Files: block.h fat.h file.h sd.h Log Message: Sorted all source files int / into the following directories: io, lowlevel, loadand ipl Did some cleaning in the source files, but there is still much to be done Index: fat.c =================================================================== RCS file: /cvsroot/gc-linux/ipl/disk/fat.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- fat.c 29 Dec 2004 11:10:33 -0000 1.1.1.1 +++ fat.c 9 Jan 2005 11:40:46 -0000 1.2 @@ -5,6 +5,7 @@ * * 2002-07-28 - rj...@ne... - ported to ppcboot v1.1.6 * 2003-03-10 - kh...@ne... - ported to uboot + * 2004-12-29 - ro...@re... - ported to tmbinc's IPL replacement * * See file CREDITS for list of people who contributed to this * project. @@ -27,7 +28,7 @@ /*#include <common.h> #include <config.h>*/ -#include "disk/fat.h" +#include "fat.h" //#include <asm/byteorder.h> #include <vsprintf.h> #include <linux/string.h> Index: file.c =================================================================== RCS file: /cvsroot/gc-linux/ipl/disk/file.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- file.c 29 Dec 2004 11:10:33 -0000 1.1.1.1 +++ file.c 9 Jan 2005 11:40:46 -0000 1.2 @@ -5,6 +5,7 @@ * * 2002-07-28 - rj...@ne... - ported to ppcboot v1.1.6 * 2003-03-10 - kh...@ne... - ported to uboot + * 2004-12-29 - ro...@re... - ported to tmbinc's IPL replacement * * See file CREDITS for list of people who contributed to this * project. @@ -28,7 +29,7 @@ //#include <common.h> //#include <config.h> //#include <malloc.h> -#include <disk/fat.h> +#include <fat.h> //#include <stat.h> #include <time.h> #include <linux/string.h> Index: sd.c =================================================================== RCS file: /cvsroot/gc-linux/ipl/disk/sd.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- sd.c 29 Dec 2004 11:10:33 -0000 1.1.1.1 +++ sd.c 9 Jan 2005 11:40:46 -0000 1.2 @@ -1,9 +1,12 @@ +//Todo: header and stuff +//Copyright 2004,2005 Rob Reilink + #include "sd.h" #include "exi.h" #include <linux/string.h> -#include "disk/block.h" -#include "disk/fat.h" -#include "disk/file.h" +#include "block.h" +#include "fat.h" +#include "file.h" //Todo: place this in disk.c or something #include <memlayout.h> @@ -204,7 +207,7 @@ unsigned short end_cyl; unsigned long start_lba, size; }; -//Yak. Put this in a file independent of device! +//Todo: Yak. Put this in a file independent of device! int sd_read_parttable(struct partition_s *part) { --- block.h DELETED --- --- fat.h DELETED --- --- file.h DELETED --- --- sd.h DELETED --- |
Update of /cvsroot/gc-linux/ipl/io In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5953/io Added Files: console.c console_font.c console_font_8x8.c dvd.c exi.c network.c pad.c sram.c video.c vsprintf.c Log Message: Sorted all source files int / into the following directories: io, lowlevel, loadand ipl Did some cleaning in the source files, but there is still much to be done --- NEW FILE: console.c --- #include "console.h" #include "exi.h" #include "pad.h" #include "color.h" #include <linux/string.h> static struct console_data_s *default_console; void (*my_puts)(const char *s); void (*my_putstring)(const char *s); void (*my_putchar)(char c); void c_putstring(const char *s) { console_puts(default_console, s); } void c_puts(const char *s) { console_puts(default_console, s); console_putc(default_console, '\n'); } void c_putchar(char c) { console_putc(default_console, c); } #if 0 void s_putc(unsigned char c); void s_putstring(const char *s) { while (*s) { if (*s == '\n') s_putc('\r'); s_putc(*s++); } } void s_puts(const char *s) { s_putstring(s); s_putstring("\n"); } void s_putchar(char c) { s_putc(c); } #endif void puts(const char *s) { if (my_puts) my_puts(s); } void putstring(const char *s) { if (my_putstring) my_putstring(s); } void putchar(char c) { if (my_putchar) my_putchar(c); } int set_color(int background, int foreground) { default_console->foreground = foreground; default_console->background = background; return 0; } void set_position(int x, int y) { default_console->cursor_y = y; default_console->cursor_x = x; } struct console_data_s console; extern unsigned char console_font_8x8[]; extern unsigned char console_font_8x16[]; void console_init(struct console_data_s *con, void *framebuffer, int xres, int yres, int stride) { con->framebuffer = framebuffer; con->xres = xres; con->yres = yres; con->border_left = 0; con->border_top = 0; con->border_right = con->xres; con->border_bottom = con->yres; con->stride = stride; con->cursor_x = con->cursor_y = 0; con->font = console_font_8x16; con->foreground = COLOR_WHITE; con->background = COLOR_BLACK; con->scrolled_lines = 0; int c = con->xres * con->yres / 2; unsigned long *p = (unsigned long*)con->framebuffer; while (c--) *p++ = con->background; default_console = con; my_puts = c_puts; my_putstring = c_putstring; my_putchar = c_putchar; /* my_puts = s_puts; my_putstring = s_putstring; my_putchar = s_putchar; */ } #define FONT_XSIZE 8 #define FONT_YSIZE 16 #define FONT_XFACTOR 1 #define FONT_YFACTOR 1 #define FONT_XGAP 2 #define FONT_YGAP 0 void console_drawc(struct console_data_s *con, int x, int y, unsigned char c) { x >>= 1; int ax, ay; unsigned long *ptr = (unsigned long*)(con->framebuffer + con->stride * y + x * 4); for (ay = 0; ay < FONT_YSIZE; ay++) { #if FONT_XFACTOR == 2 for (ax = 0; ax < 8; ax++) { unsigned long color; if ((con->font[c * FONT_YSIZE + ay] << ax) & 0x80) color = con->foreground; else color = con->background; #if FONT_YFACTOR == 2 // pixel doubling: we write u32 ptr[ay * 2 * con->stride/4 + ax] = color; // line doubling ptr[(ay * 2 +1) * con->stride/4 + ax] = color; #else ptr[ay * con->stride/4 + ax] = color; #endif } #else for (ax = 0; ax < 4; ax ++) { unsigned long color[2]; int bits = (con->font[c * FONT_YSIZE + ay] << (ax*2)); if (bits & 0x80) color[0] = con->foreground; else color[0] = con->background; if (bits & 0x40) color[1] = con->foreground; else color[1] = con->background; ptr[ay * con->stride/4 + ax] = (color[0] & 0xFFFF00FF) | (color[1] & 0x0000FF00); } #endif for (ax = 0; ax < FONT_XGAP/2; ++ax) { ptr[ay * con->stride/4 + ax + 4] = con->background; } } } void console_puts(struct console_data_s *con, const char *string) { while (*string) console_putc(con, *string++); } void console_putc(struct console_data_s *con, char c) { switch (c) { case '\n': con->cursor_y += FONT_YSIZE * FONT_YFACTOR + FONT_YGAP; con->cursor_x = con->border_left; break; case '\r': con->cursor_x = con->border_left; break; default: console_drawc(con, con->cursor_x, con->cursor_y, c); con->cursor_x += FONT_XSIZE * FONT_XFACTOR + FONT_XGAP; if ((con->cursor_x + (FONT_XSIZE * FONT_XFACTOR)) > con->border_right) { con->cursor_y += FONT_YSIZE * FONT_YFACTOR + FONT_YGAP; con->cursor_x = con->border_left; } } if ((con->cursor_y + FONT_YSIZE * FONT_YFACTOR) >= con->border_bottom) { #if 0 if (con->scrolled_lines == con->yres / (FONT_YSIZE * FONT_YFACTOR + FONT_YGAP)) { struct PAD pad; while (1) { PAD_ReadState(&pad, 0); if (pad.Digital.A) break; } while (1) { PAD_ReadState(&pad, 0); if (!pad.Digital.A) break; } con->scrolled_lines = 0; } con->scrolled_lines++; #endif memcpy(con->framebuffer, con->framebuffer + con->stride * (FONT_YSIZE * FONT_YFACTOR + FONT_YGAP), con->stride * con->yres - FONT_YSIZE); int cnt = (con->stride * (FONT_YSIZE * FONT_YFACTOR + FONT_YGAP)) / 4; int a = 0; unsigned long *ptr = con->framebuffer + con->stride * (con->yres - FONT_YSIZE); while (cnt--) *ptr++ = con->background; con->cursor_y -= FONT_YSIZE * FONT_YFACTOR + FONT_YGAP; } } --- NEW FILE: console_font.c --- unsigned char console_font_8x16[] = { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ [...4574 lines suppressed...] 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ }; --- NEW FILE: console_font_8x8.c --- unsigned char console_font_8x8[] = { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 1 0x01 '^A' */ 0x7e, /* 01111110 */ 0x81, /* 10000001 */ 0xa5, /* 10100101 */ 0x81, /* 10000001 */ 0xbd, /* 10111101 */ 0x99, /* 10011001 */ [...2526 lines suppressed...] 0x3c, /* 00111100 */ 0x3c, /* 00111100 */ 0x3c, /* 00111100 */ 0x3c, /* 00111100 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 255 0xff 'ÿ' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ }; --- NEW FILE: dvd.c --- #include <console.h> #include <time.h> #include <cache.h> volatile long *dvd=(volatile long *)0xCC006000; void dvd_reset(void) { *(unsigned long*)0xcc006004 = 2; unsigned long v = *(unsigned long*)0xcc003024; *(unsigned long*)0xcc003024 = (v &~4) | 1; mdelay(1); *(unsigned long*)0xcc003024 = v | 5; } unsigned int dvd_read(void *dst, int len, unsigned int offset) { if ((((int)dst) & 0xC0000000) == 0x80000000) // cached? dcache_inv(dst, len); dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xA8000000; dvd[3] = offset >> 2; dvd[4] = len; dvd[5] = (unsigned long)dst; dvd[6] = len; dvd[7] = 3; // enable reading! while (dvd[7] & 1); if (dvd[0] & 0x4) return 1; return 0; } int dvd_seek(int offset) { dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xAB000000; dvd[3] = offset >> 2; dvd[4] = 0; dvd[7] = 1; while (dvd[7] & 1); if (dvd[0] & 0x4) return 1; return 0; } unsigned int dvd_read_id(void *dst) { if ((((int)dst) & 0xC0000000) == 0x80000000) // cached? dcache_inv(dst, 0x20); dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xA8000040; dvd[3] = 0; dvd[4] = 0x20; dvd[5] = (unsigned long)dst; dvd[6] = 0x20; dvd[7] = 3; // enable reading! while (dvd[7] & 1); if (dvd[0] & 0x4) return 1; return 0; } void dvd_motor_off() { dvd[0] = 0x2E; dvd[1] = 0; dvd[2] = 0xe3000000; dvd[3] = 0; dvd[4] = 0; dvd[5] = 0; dvd[6] = 0; dvd[7] = 1; // enable reading! while (dvd[7] & 1); } unsigned int dvd_init() { dvd_reset(); if (dvd_read_id(0x80000000)) return -1; dcache_inv(0x80000000, 0x20); return 0; } void dvd_set_audio(int enable, int len) { enable = !!enable; dvd[2] = 0xE4000000 | (enable<<16) | len; dvd[7] = 1; while (dvd[7] & 1); } void dvd_set_streaming(void) { int streaming_enable = *(unsigned char*)0x80000008; dvd[1] = dvd[1]; if (!streaming_enable) dvd_set_audio(0, 0); else dvd_set_audio(1, (*(unsigned char*)0x80000009) ? 0 : 0xA); while (dvd[7] & 1); } unsigned int dvd_get_error(void) { dvd[2] = 0xE0000000; dvd[8] = 0; dvd[7] = 1; while (dvd[7] & 1); return dvd[8]; } unsigned int dvd_get_diconfig(void) { return dvd[9]; } const char *dvd_get_error_message(void) { switch (dvd_get_error()>>24) { /* as documented in NinDoc */ case 0x00: return "Ready."; case 0x01: return "Cover is opened."; case 0x02: return "Disk change."; case 0x03: return "No Disk."; case 0x04: return "Motor stop."; case 0x05: return "Disk ID not read."; default: return "unknown"; } } /**************** NPDP STUFF ***************/ /* by Dr.Matrix */ /* Note by tmbinc: I wasn't able to test this stuff, as i don't have a NPDP. But Dr.Matrix usually does things which work, i trust in him! */ unsigned int npdp_getid(unsigned char *dst) { static unsigned char id[256] __attribute__((__aligned__(32))); dcache_inv(id, 0x40); dvd[0] = 0x2E; dvd[1] = 0; memcpy(dvd + 2, "NPDP-ID", 8); dvd[4] = 0x40; dvd[5] = (unsigned long)id; dvd[6] = 0x40; dvd[7] = 3; // enable reading! while (dvd[7] & 1); if (dvd[6]) return 1; memcpy(dst, id, 0x40); return 0; } --- NEW FILE: exi.c --- #include "exi.h" #include <irq.h> #include <console.h> #include "cache.h" static int flags; /* exi_select: enable chip select, set speed */ void exi_select(int channel, int device, int freq) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; long d; cli(flags); // exi_select d = exi[channel * 5]; d &= 0x405; d |= ((1<<device)<<7) | (freq << 4); exi[channel*5] = d; } /* disable chipselect */ void exi_deselect(int channel) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; exi[channel * 5] &= 0x405; sti(flags); } /* dirty way for asynchronous reads */ static void *exi_last_addr; static int exi_last_len; /* mode?Read:Write len bytes to/from channel */ /* when read, data will be written back in exi_sync */ inline void exi_imm(int channel, void *data, int len, int mode, int zero) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; if (mode == EXI_WRITE) exi[channel * 5 + 4] = *(unsigned long*)data; else exi[channel * 5 + 4] = -1; exi[channel * 5 + 3] = ((len-1)<<4)|(mode<<2)|1; if (mode == EXI_READ) { exi_last_addr = data; exi_last_len = len; } else { exi_last_addr = 0; exi_last_len = 0; } } /* Wait until transfer is done, write back data */ void exi_sync(int channel) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; while (exi[channel * 5 + 3] & 1); if (exi_last_addr) { int i; unsigned long d; d = exi[channel * 5 + 4]; for (i=0; i<exi_last_len; ++i) ((unsigned char*)exi_last_addr)[i] = (d >> ((3-i)*8)) & 0xFF; } } /* simple wrapper for transfers > 4bytes */ void exi_imm_ex(int channel, void *data, int len, int mode) { unsigned char *d = (unsigned char*)data; while (len) { int tc = len; if (tc > 4) tc = 4; exi_imm(channel, d, tc, mode, 0); exi_sync(channel); len-=tc; d+=tc; } } void exi_dma_start(int channel, void *data, int len, int mode) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; if (len < 0) { printf("!!! len is %d\n", len); while (1); } exi[channel * 5 + 1] = (unsigned long)data; exi[channel * 5 + 2] = len; exi[channel * 5 + 3] = (mode<<2)|3; } void exi_imm_fast(int channel, void *data, int len, int mode) { unsigned long addr = (unsigned long)data; unsigned char *d = (unsigned char*)data; int addr_misalign = (-addr) & 31; if ((len - addr_misalign) < 32) return exi_imm_ex(channel, data, len, mode); if (addr_misalign) /* fix misalignment with normal transfers */ { exi_imm_ex(channel, data, addr_misalign, mode); len -= addr_misalign; addr += addr_misalign; } int len_align = len & ~31; dcache_flush((void*)addr, len_align); exi_dma_start(channel, (void*)addr, len_align, mode); exi_sync(channel); if (mode == EXI_READ) dcache_inv((void*)addr, len_align); len -= len_align; if (len) exi_imm_ex(channel, (void*)(addr + len_align), len, mode); } static exi_irq_handler_t *exi_handler[3 * 3]; // 3 channels, 3 events static void *exi_handler_context[3 * 3]; static unsigned long exi_enable_mask[3]; void exi_refresh_enable() { int channel; for (channel = 0; channel < 3; ++channel) *(unsigned long*)(0xcc006800 + channel*0x14) |= 0x401; // exi_enable_mask[channel]; } static inline int have_irq(int t) { if (exi_handler[t]) { exi_handler[t](t/3, t%3, exi_handler_context[t]); return 1; } else { printf("unhandled exi irq!\n"); return 0; } } int exi_interrupt_handler(int irq, void *c) { int ch; for (ch = 0; ch < 3; ++ch) { unsigned long v = (*(unsigned long*)(0xcc006800 + ch * 0x14)); // & 0xC0F; v &= v<<1; *(unsigned long*)(0xcc006800 + ch * 0x14) |= v; if (v & 0x800) have_irq(ch * 3 + EXI_EVENT_INSERT); if (v & 8) have_irq(ch * 3 + EXI_EVENT_TC); if (v & 2) have_irq(ch * 3 + EXI_EVENT_IRQ); } return 1; } void exi_init() { *(unsigned long*)(0xcc006800) |= 1<<13; // disable decryption and rom mapping printf("EXI: init interrupts\n"); request_irq(IRQ_EXI, exi_interrupt_handler, 0); *(unsigned long*)(0xcc006814) |= 3<<10; // enable&clear irq for insertion } int exi_request_irq(int channel, int event, exi_irq_handler_t *handler, void *context) { if (exi_handler[channel * 3 + event]) { printf("EXI: irq %d:%d already used!\n", channel, event); return -1; } exi_handler[channel * 3 + event] = handler; exi_handler_context[channel * 3 + event] = context; switch (event) { case EXI_EVENT_TC: *(unsigned long*)(0xcc006800 + channel*0x14) |= 3<<2; // enable&clear irq exi_enable_mask[channel] |= 1 << 2; break; case EXI_EVENT_INSERT: *(unsigned long*)(0xcc006800 + channel*0x14) |= 3<<10; exi_enable_mask[channel] |= 1 << 10; break; case EXI_EVENT_IRQ: *(unsigned long*)(0xcc006800 + channel*0x14) |= 3<<0; exi_enable_mask[channel] |= 1 << 0; break; } return 0; } int exi_free_irq(int channel, int event) { exi_handler[channel * 3 + event] = 0; switch (event) { case EXI_EVENT_TC: *(unsigned long*)(0xcc006800 + channel*0x14) &= ~(3<<2); // enable&clear irq exi_enable_mask[channel] &= ~(1 << 2); break; case EXI_EVENT_INSERT: *(unsigned long*)(0xcc006800 + channel*0x14) &= ~(3<<10); exi_enable_mask[channel] &= ~(1 << 10); break; case EXI_EVENT_IRQ: *(unsigned long*)(0xcc006800 + channel*0x14) &= ~(3<<0); exi_enable_mask[channel] &= ~(1 << 0); break; } return 0; } void exi_read(int channel, void *data, int len) { exi_imm_ex(channel, data, len, EXI_READ); } void exi_write(int channel, const void *data, int len) { exi_imm_ex(channel, data, len, EXI_WRITE); } unsigned long exi_rw(int channel,unsigned long data,int len) { volatile unsigned long *exi = (volatile unsigned long *)0xCC006800; exi[channel * 5 + 4] = data<<(8*(4-len)); exi[channel * 5 + 3] = ((len-1)<<4)|(2<<2)|1; while (exi[channel * 5 + 3] & 1); return exi[channel * 5 + 4]>>(8*(4-len)); } --- NEW FILE: network.c --- #include "time.h" #include "lwip/debug.h" #include "lwip/mem.h" #include "lwip/memp.h" #include "lwip/sys.h" #include "lwip/stats.h" #include "lwip/ip.h" #include "lwip/udp.h" #include "lwip/tcp.h" #include "lwip/arch/gc/include/netif/gcif.h" #include "netif/etharp.h" #include "dolup.h" #include "irq.h" #include "console.h" extern void httpd_start(); struct ip_addr *sram_get_ip(int w); static struct netif netif; static tb_t now, start; void network_init() { struct ip_addr *ipaddr = sram_get_ip(0), *netmask = sram_get_ip(1), *gw = sram_get_ip(2); #ifdef STATS stats_init(); #endif /* STATS */ mem_init(); memp_init(); pbuf_init(); netif_init(); ip_init(); // udp_init(); tcp_init(); etharp_init(); if (!netif_add(&netif, ipaddr, netmask, gw, NULL, gcif_init, ip_input)) { printf("netif_add failed!\n"); return; } netif_set_default(&netif); dolup_init(); httpd_start(); mftb(&start); } void network_poll() { mftb(&now); if (tb_diff_msec(&now, &start) >= 250) { unsigned long flags; mftb(&start); cli(flags); tcp_tmr(); sti(flags); } } --- NEW FILE: pad.c --- #include "pad.h" void pad_init() { *(volatile unsigned long*)0xCC006430 = 0x00000000; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006430 = 0x00f70200; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006480 = 0x00000000; *(volatile unsigned long*)0xCC006434 = 0xc0010301; *(volatile unsigned long*)0xCC006438 = 0x00000000; (void)*(volatile unsigned long*)0xCC006434; *(volatile unsigned long*)0xCC006430 |= 0xF0; // enable all four controller ports *(volatile unsigned long*)0xCC006400 = 0x00400300; *(volatile unsigned long*)0xCC00640C = 0x00400300; *(volatile unsigned long*)0xCC006418 = 0x00400300; *(volatile unsigned long*)0xCC006424 = 0x00400300; udelay(1000); *(volatile unsigned long*)0xCC006430 = 0x00000000; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006430 = 0x00f70200; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006480 = 0x00000000; *(volatile unsigned long*)0xCC006434 = 0xc0010301; *(volatile unsigned long*)0xCC006438 = 0x00000000; (void)*(volatile unsigned long*)0xCC006434; *(volatile unsigned long*)0xCC006430 |= 0xF0; // enable all four controller ports *(volatile unsigned long*)0xCC006400 = 0x00400300; *(volatile unsigned long*)0xCC00640C = 0x00400300; *(volatile unsigned long*)0xCC006418 = 0x00400300; *(volatile unsigned long*)0xCC006424 = 0x00400300; *(volatile unsigned long*)0xCC006430 = 0x000701f0; *(volatile unsigned long*)0xCC006438 = 0x80000000; while (!((*(volatile unsigned long*) 0xCC006438)&0x20000000)); } /* ripped from: Author: Peter (www.console-dev.de) */ void PAD_ReadState(PAD *pPad, u8 PadChannel) { u32 Value32[3]; u8 Value8[2]; s8 ValueS8[2]; //u32 PadChannelAddr = 0xCC006400 + (PadChannel*12); u32 PadChannelAddr = MEM_PAD_CHANNEL(PadChannel); /* added in 0.2 */ PAD_BUTTONS_DIGITAL *pDigital=&pPad->Digital; Value32[0] = *(u32 *)(PadChannelAddr+0); Value32[1] = *(u32 *)(PadChannelAddr+4); Value32[2] = *(u32 *)(PadChannelAddr+8); // digital buttons Value8[0] = (Value32[1] >> 16); Value8[1] = (Value32[1] >> 16) >> 8; // digital buttons pDigital->Left = Value8[0] & 0x01; pDigital->Right = Value8[0] & 0x02; pDigital->Down = Value8[0] & 0x04; pDigital->Up = Value8[0] & 0x08; pDigital->Z = Value8[0] & 0x10; pDigital->L = Value8[0] & 0x20; pDigital->R = Value8[0] & 0x40; pDigital->A = Value8[1] & 0x01; pDigital->B = Value8[1] & 0x02; pDigital->X = Value8[1] & 0x04; pDigital->Y = Value8[1] & 0x08; pDigital->Start = Value8[1] & 0x10; // analog stick ValueS8[0] = ((Value32[1]) & 0xff); ValueS8[1] = ((Value32[1]) & 0xff00) >> 8; pPad->Analog.X = 0x80+ValueS8[1]; pPad->Analog.Y = 0x80-ValueS8[0]; // trigger L and R Value8[0] = ((Value32[2]) & 0xff); Value8[1] = ((Value32[2]) & 0xff00) >> 8; pPad->Trigger.L = Value8[0]; pPad->Trigger.R = Value8[1]; // analoc C stick ValueS8[0] = (Value32[2] >> 16); ValueS8[1] = (Value32[2] >> 16) >> 8; pPad->AnalogC.X = 0x80+ValueS8[1]; pPad->AnalogC.Y = 0x80-ValueS8[0]; } --- NEW FILE: sram.c --- #include "ipl.h" #include "pad.h" #include "lwip/ip_addr.h" #include "lwip/inet.h" void sram_set_videomode(int v) { sram_data[33] = v; } int sram_get_videomode(void) { return sram_data[33]; } void sram_set_autoboot(int v) { sram_data[34] = v; } int sram_get_autoboot(void) { return sram_data[34]; } struct ip_addr *sram_get_ip(int w) { return (struct ip_addr*)(sram_data + 0x24 + w * 4); } void sram_load_defaults(void) { sram_data[32] = '!'; sram_set_autoboot(0); sram_set_videomode(1); IP4_ADDR(sram_get_ip(0), 10,0,0,203); IP4_ADDR(sram_get_ip(1), 255,255,255,0); IP4_ADDR(sram_get_ip(2), 10,0,0,1); } void read_sram(void) { //TODO: this somewhere else struct PAD pad; PAD_ReadState(&pad, 0); if (!pad.Digital.Start) exi_sram_read(sram_data); else memset(sram_data + 32, 0, 32); if (sram_data[32] != '!') sram_load_defaults(); } void write_sram(void) { exi_sram_write(sram_data); } --- NEW FILE: video.c --- #include "video.h" #define MEM_VIDEO_BASE (0xCC002000) #define MEM_VIDEO_BASE_PTR (u32*)MEM_VIDEO_BASE #define R_VIDEO_FRAMEBUFFER_1 *(vu32*)(MEM_VIDEO_BASE+0x1C) #define R_VIDEO_FRAMEBUFFER_2 *(vu32*)(MEM_VIDEO_BASE+0x24) #define R_VIDEO_HALFLINE_1 *(vu16*)(MEM_VIDEO_BASE+0x2C) #define R_VIDEO_HALFLINE_2 *(vu16*)(MEM_VIDEO_BASE+0x2E) #define R_VIDEO_STATUS *(vu16*)(MEM_VIDEO_BASE+0x6C) /* ripped from libogc. */ // VIDEO_640X480_NTSC_YUV16 static const u32 VIDEO_Mode640X480NtscYUV16[32] = { 0x0F060001, 0x476901AD, 0x02EA5140, 0x00030018, 0x00020019, 0x410C410C, 0x40ED40ED, 0x00435A4E, 0x00000000, 0x00435A4E, 0x00000000, 0x00000000, 0x110701AE, 0x10010001, 0x00010001, 0x00010001, 0x00000000, 0x00000000, 0x28500100, 0x1AE771F0, 0x0DB4A574, 0x00C1188E, 0xC4C0CBE2, 0xFCECDECF, 0x13130F08, 0x00080C0F, 0x00FF0000, 0x00000000, 0x02800000, 0x000000FF, 0x00FF00FF, 0x00FF00FF}; // VIDEO_640X480_PAL50_YUV16 static const u32 VIDEO_Mode640X480Pal50YUV16[32] = { 0x11F50101, 0x4B6A01B0, 0x02F85640, 0x00010023, 0x00000024, 0x4D2B4D6D, 0x4D8A4D4C, 0x00435A4E, 0x00000000, 0x00435A4E, 0x00000000, 0x013C0144, 0x113901B1, 0x10010001, 0x00010001, 0x00010001, 0x00000000, 0x00000000, 0x28500100, 0x1AE771F0, 0x0DB4A574, 0x00C1188E, 0xC4C0CBE2, 0xFCECDECF, 0x13130F08, 0x00080C0F, 0x00FF0000, 0x00000000, 0x02800000, 0x000000FF, 0x00FF00FF, 0x00FF00FF}; // VIDEO_640X480_PAL60_YUV16 static const u32 VIDEO_Mode640X480Pal60YUV16[32] = { 0x0F060001, 0x476901AD, 0x02EA5140, 0x00030018, 0x00020019, 0x410C410C, 0x40ED40ED, 0x00435A4E, 0x00000000, 0x00435A4E, 0x00000000, 0x00050176, 0x110701AE, 0x10010001, 0x00010001, 0x00010001, 0x00000000, 0x00000000, 0x28500100, 0x1AE771F0, 0x0DB4A574, 0x00C1188E, 0xC4C0CBE2, 0xFCECDECF, 0x13130F08, 0x00080C0F, 0x00FF0000, 0x00000000, 0x02800000, 0x000000FF, 0x00FF00FF, 0x00FF00FF}; void video_init(u32 VideoMode) { u32 Counter=0; u32 *pSrcAddr=NULL; u32 *pDstAddr=MEM_VIDEO_BASE_PTR; switch(VideoMode) { case VIDEO_640X480_NTSC_YUV16: pSrcAddr = (u32*)VIDEO_Mode640X480NtscYUV16; break; case VIDEO_640X480_PAL50_YUV16: pSrcAddr = (u32*)VIDEO_Mode640X480Pal50YUV16; break; case VIDEO_640X480_PAL60_YUV16: pSrcAddr = (u32*)VIDEO_Mode640X480Pal60YUV16; break; } for(Counter=0; Counter<32; Counter++) { if ((Counter != 7) && (Counter != 9)) pDstAddr[Counter] = pSrcAddr[Counter]; } } void video_set_framebuffer(u32 Which, u32 FrameBufferAddr) { switch(Which) { case VIDEO_FRAMEBUFFER_1: R_VIDEO_FRAMEBUFFER_1 = FrameBufferAddr; break; case VIDEO_FRAMEBUFFER_2: R_VIDEO_FRAMEBUFFER_2 = FrameBufferAddr; break; case VIDEO_FRAMEBUFFER_BOTH: R_VIDEO_FRAMEBUFFER_1 = FrameBufferAddr; R_VIDEO_FRAMEBUFFER_2 = FrameBufferAddr; break; } } void video_wait_vsync(void) { while(R_VIDEO_HALFLINE_1 >= 200); while(R_VIDEO_HALFLINE_1 < 200); } --- NEW FILE: vsprintf.c --- /* * linux/lib/vsprintf.c * * Copyright (C) 1991, 1992 Linus Torvalds */ /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ /* * Wirzenius wrote this portably, Torvalds fucked it up :-) */ #include <stdarg.h> #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include "console.h" unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) { unsigned long result = 0,value; if (*cp == '0') { cp++; if ((*cp == 'x') && isxdigit(cp[1])) { base = 16; cp++; } if (!base) { base = 8; } } if (!base) { base = 10; } while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) ? toupper(*cp) : *cp)-'A'+10) < base) { result = result*base + value; cp++; } if (endp) *endp = (char *)cp; return result; } long simple_strtol(const char *cp,char **endp,unsigned int base) { if(*cp=='-') return -simple_strtoul(cp+1,endp,base); return simple_strtoul(cp,endp,base); } /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') static int skip_atoi(const char **s) { int i=0; while (is_digit(**s)) i = i*10 + *((*s)++) - '0'; return i; } #define ZEROPAD 1 /* pad with zero */ #define SIGN 2 /* unsigned/signed long */ #define PLUS 4 /* show plus */ #define SPACE 8 /* space if plus */ #define LEFT 16 /* left justified */ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ #define do_div(n,base) ({ \ int __res; \ __res = ((unsigned long) n) % (unsigned) base; \ n = ((unsigned long) n) / (unsigned) base; \ __res; }) static char * number(char * str, long num, int base, int size, int precision ,int type) { char c,sign,tmp[66]; const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; int i; if (type & LARGE) digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (type & LEFT) type &= ~ZEROPAD; if (base < 2 || base > 36) return 0; c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { if (num < 0) { sign = '-'; num = -num; size--; } else if (type & PLUS) { sign = '+'; size--; } else if (type & SPACE) { sign = ' '; size--; } } if (type & SPECIAL) { if (base == 16) size -= 2; else if (base == 8) size--; } i = 0; if (num == 0) tmp[i++]='0'; else while (num != 0) tmp[i++] = digits[do_div(num,base)]; if (i > precision) precision = i; size -= precision; if (!(type&(ZEROPAD+LEFT))) while(size-->0) *str++ = ' '; if (sign) *str++ = sign; if (type & SPECIAL) { if (base==8) *str++ = '0'; else if (base==16) { *str++ = '0'; *str++ = digits[33]; } } if (!(type & LEFT)) while (size-- > 0) *str++ = c; while (i < precision--) *str++ = '0'; while (i-- > 0) *str++ = tmp[i]; while (size-- > 0) *str++ = ' '; return str; } /* Forward decl. needed for IP address printing stuff... */ int sprintf(char * buf, const char *fmt, ...); int vsprintf(char *buf, const char *fmt, va_list args) { int len; unsigned long num; int i, base; char * str; const char *s; int flags; /* flags to number() */ int field_width; /* width of output field */ int precision; /* min. # of digits for integers; max number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ for (str=buf ; *fmt ; ++fmt) { if (*fmt != '%') { *str++ = *fmt; continue; } /* process flags */ flags = 0; repeat: ++fmt; /* this also skips first '%' */ switch (*fmt) { case '-': flags |= LEFT; goto repeat; case '+': flags |= PLUS; goto repeat; case ' ': flags |= SPACE; goto repeat; case '#': flags |= SPECIAL; goto repeat; case '0': flags |= ZEROPAD; goto repeat; } /* get field width */ field_width = -1; if (is_digit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ field_width = va_arg(args, int); if (field_width < 0) { field_width = -field_width; flags |= LEFT; } } /* get the precision */ precision = -1; if (*fmt == '.') { ++fmt; if (is_digit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ precision = va_arg(args, int); } if (precision < 0) precision = 0; } /* get the conversion qualifier */ qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { qualifier = *fmt; ++fmt; } /* default base */ base = 10; switch (*fmt) { case 'c': if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' '; *str++ = (unsigned char) va_arg(args, int); while (--field_width > 0) *str++ = ' '; continue; case 's': s = va_arg(args, char *); if (!s) s = "<NULL>"; len = strnlen(s, precision); if (!(flags & LEFT)) while (len < field_width--) *str++ = ' '; for (i = 0; i < len; ++i) *str++ = *s++; while (len < field_width--) *str++ = ' '; continue; case 'p': if (field_width == -1) { field_width = 2*sizeof(void *); flags |= ZEROPAD; } str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); continue; case 'n': if (qualifier == 'l') { long * ip = va_arg(args, long *); *ip = (str - buf); } else { int * ip = va_arg(args, int *); *ip = (str - buf); } continue; case '%': *str++ = '%'; continue; /* integer number formats - set up the flags and "break" */ case 'o': base = 8; break; case 'X': flags |= LARGE; case 'x': base = 16; break; case 'd': case 'i': flags |= SIGN; case 'u': break; default: *str++ = '%'; if (*fmt) *str++ = *fmt; else --fmt; continue; } if (qualifier == 'l') num = va_arg(args, unsigned long); else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); if (flags & SIGN) num = (short) num; } else if (flags & SIGN) num = va_arg(args, int); else num = va_arg(args, unsigned int); str = number(str, num, base, field_width, precision, flags); } *str = '\0'; return str-buf; } int sprintf(char * buf, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i=vsprintf(buf,fmt,args); va_end(args); return i; } int printf( const char *fmt, ...) { va_list args; char buffer[1024]; int i; va_start(args, fmt); i=vsprintf(buffer, fmt,args); va_end(args); putstring (buffer); return i; } |
Update of /cvsroot/gc-linux/ipl/lowlevel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5953/lowlevel Added Files: cache.S crt0.s ctype.c exception.S exceptionc.c irq.c string.c string_asm.S time.c Log Message: Sorted all source files int / into the following directories: io, lowlevel, loadand ipl Did some cleaning in the source files, but there is still much to be done --- NEW FILE: cache.S --- #include <asm.h> .globl dcache_flush dcache_flush: cmplwi r4, 0 # zero or negative size? blelr clrlwi. r5, r3, 27 # check for lower bits set in address beq 1f addi r4, r4, 0x20 1: addi r4, r4, 0x1f srwi r4, r4, 5 mtctr r4 2: dcbst r0, r3 addi r3, r3, 0x20 bdnz 2b blr .globl dcache_inv dcache_inv: cmplwi r4, 0 # zero or negative size? blelr clrlwi. r5, r3, 27 # check for lower bits set in address beq 1f addi r4, r4, 0x20 1: addi r4, r4, 0x1f srwi r4, r4, 5 mtctr r4 2: dcbi r0, r3 addi r3, r3, 0x20 bdnz 2b blr .globl flush_code flush_code: lis r5, 0xFFFF ori r5, r5, 0xFFF1 and r5, r5, r3 subf r3, r5, r3 add r4, r4, r3 1: dcbst r0, r5 sync icbi r0, r5 addic r5, r5, 8 subic. r4, r4, 8 bge 1b isync blr --- NEW FILE: crt0.s --- .text .org 0x0 .globl _start # crt0.s file for the GameCube V1.0 by Costis (co...@gb...)! # # This is start-up code for initializing the GameCube system and hardware # before executing the actual user program code. It clears the GPR's, # initializes the FPR's, initializes the Data, Code, and L2 caches, clears # and initializes SPR's, and disables exceptions (interrupts). # # Note: The next version will have full exception (interrupt) initialization # code. As stated above, this version does not support interrupts, # however, there are no freely available interrupt handling functions # yet. So, even with proper interrupt initialization, it would not # actually be useful with the current open source libraries for the # GameCube. # # Have fun!!! Please e-mail any suggestions or bugs to co...@gb.... # Entry Point _start: bl InitGPRS # Initialize the General Purpose Registers bl InitHardware # Initialize the GameCube Hardware (Floating Point Registers, Caches, etc.) bl SystemInit # Initialize more cache aspects, clear a few SPR's, and disable interrupts. # clear BSS .extern __bss_start, _end lis 3, __bss_start@h ori 3, 3, __bss_start@l li 4, 0 lis 5, _end@h ori 5, 5, _end@l sub 5, 5, 3 bl memset bl main # Branch to the user code! eloop: b eloop # If the main function returns, then just loop endlessly. InitGPRS: # Clear all of the GPR's to 0 li 0,0 li 3,0 li 4,0 li 5,0 li 6,0 li 7,0 li 8,0 li 9,0 li 10,0 li 11,0 li 12,0 li 14,0 li 15,0 li 16,0 li 17,0 li 18,0 li 19,0 li 20,0 li 21,0 li 22,0 li 23,0 li 24,0 li 25,0 li 26,0 li 27,0 li 28,0 li 29,0 li 30,0 li 31,0 # lis 1, 0x8160 # Set the Stack Pointer to the top of main RAM. lis 1, 0x8170 # put the fucking stack pointer somewhere else. subi 1, 1, 0x10 lis 2,0x8000 stw 1,0x34(2) # write sp lis 2,_SDA2_BASE_@h ori 2,2,_SDA2_BASE_@l # Set the Small Data 2 (Read Only) base register. lis 13,_SDA_BASE_@h ori 13,13,_SDA_BASE_@l # Set the Small Data (Read\Write) base register. blr InitHardware: mflr 31 # Store the link register in r31 bl PSInit # Initialize Paired Singles bl FPRInit # Initialize the FPR's bl CacheInit # Initialize the system caches mtlr 31 # Retreive the link register from r31 blr PSInit: mfspr 3, 920 # (HID2) oris 3, 3, 0xA000 mtspr 920, 3 # (HID2) # Set the Instruction Cache invalidation bit in HID0 mfspr 3,1008 ori 3,3,0x0800 mtspr 1008,3 sync # Clear various Special Purpose Registers li 3,0 mtspr 912,3 mtspr 913,3 mtspr 914,3 mtspr 915,3 mtspr 916,3 mtspr 917,3 mtspr 918,3 mtspr 919,3 # Return blr FPRInit: # Enable the Floating Point Registers mfmsr 3 ori 3,3,0x2000 mtmsr 3 # Clear all of the FPR's to 0 lis 3, zfloat@h ori 3, 3, zfloat@l lfd 0, 0(3) fmr 1,0 fmr 2,0 fmr 3,0 fmr 4,0 fmr 5,0 fmr 6,0 fmr 7,0 fmr 8,0 fmr 9,0 fmr 10,0 fmr 11,0 fmr 12,0 fmr 13,0 fmr 14,0 fmr 15,0 fmr 16,0 fmr 17,0 fmr 18,0 fmr 19,0 fmr 20,0 fmr 21,0 fmr 22,0 fmr 23,0 fmr 24,0 fmr 25,0 fmr 26,0 fmr 27,0 fmr 28,0 fmr 29,0 fmr 30,0 fmr 31,0 mtfsf 255,0 # Return blr CacheInit: mflr 0 stw 0, 4(1) stwu 1, -16(1) stw 31, 12(1) stw 30, 8(1) mfspr 3,1008 # (HID0) rlwinm 0, 3, 0, 16, 16 cmplwi 0, 0x0000 # Check if the Instruction Cache has been enabled or not. bne ICEnabled # If not, then enable it. isync mfspr 3, 1008 ori 3, 3, 0x8000 mtspr 1008, 3 ICEnabled: mfspr 3, 1008 # bl PPCMfhid0 rlwinm 0, 3, 0, 17, 17 cmplwi 0, 0x0000 # Check if the Data Cache has been enabled or not. bne DCEnabled # If not, then enable it. sync mfspr 3, 1008 ori 3, 3, 0x4000 mtspr 1008, 3 DCEnabled: mfspr 3, 1017 # (L2CR) clrrwi 0, 3, 31 # Clear all of the bits except 31 cmplwi 0, 0x0000 bne L2GISkip # Skip the L2 Global Cache Invalidation process if it has already been done befor. # Store the current state of the MSR in r30 mfmsr 3 mr 30,3 sync # Enable Instruction and Data Address Translation li 3, 48 mtmsr 3 sync sync # Disable the L2 Global Cache. mfspr 3, 1017 # (L2CR clrlwi 3, 3, 1 mtspr 1017, 3 # (L2CR) sync # Invalidate the L2 Global Cache. bl L2GlobalInvalidate # Restore the previous state of the MSR from r30 mr 3, 30 mtmsr 3 # Enable the L2 Global Cache and disable the L2 Data Only bit and the L2 Global Invalidate Bit. mfspr 3, 1017 # (L2CR) oris 0, 3, 0x8000 rlwinm 3, 0, 0, 11, 9 mtspr 1017, 3 # (L2CR) L2GISkip: # Restore the non-volatile registers to their previous values and return. lwz 0, 20(1) lwz 31, 12(1) lwz 30, 8(1) addi 1, 1, 16 mtlr 0 blr L2GlobalInvalidate: mflr 0 stw 0, 4(1) stwu 1, -16(1) stw 31, 12(1) sync # Disable the L2 Cache. mfspr 3, 1017 # bl PPCMf1017 clrlwi 3, 3, 1 mtspr 1017, 3 # bl PPCMt1017 sync # Initiate the L2 Cache Global Invalidation process. mfspr 3, 1017 # (L2CR) oris 3, 3, 0x0020 mtspr 1017, 3 # (L2CR) # Wait until the L2 Cache Global Invalidation has been completed. L2GICheckComplete: mfspr 3, 1017 # (L2CR) clrlwi 0, 3, 31 cmplwi 0, 0x0000 bne L2GICheckComplete # Clear the L2 Data Only bit and the L2 Global Invalidate Bit. mfspr 3, 1017 # (L2CR) rlwinm 3, 3, 0, 11, 9 mtspr 1017, 3 # (L2CR) # Wait until the L2 Cache Global Invalidation status bit signifies that it is ready. L2GDICheckComplete: mfspr 3, 1017 # (L2CR) clrlwi 0, 3, 31 cmplwi 0, 0x0000 bne L2GDICheckComplete # Restore the non-volatile registers to their previous values and return. lwz 0, 20(1) lwz 31, 12(1) addi 1, 1, 16 mtlr 0 blr SystemInit: mflr 0 stw 0, 4(1) stwu 1, -0x18(1) stw 31, 0x14(1) stw 30, 0x10(1) stw 29, 0xC(1) # Disable interrupts! mfmsr 3 rlwinm 4,3,0,17,15 rlwinm 4,4,0,26,24 mtmsr 4 # Clear various SPR's li 3,0 mtspr 952, 3 mtspr 956, 3 mtspr 953, 3 mtspr 954, 3 mtspr 957, 3 mtspr 958, 3 # Disable Speculative Bus Accesses to non-guarded space from both caches. mfspr 3, 1008 # (HID0) ori 3, 3, 0x0200 mtspr 1008, 3 # Set the Non-IEEE mode in the FPSCR mtfsb1 29 mfspr 3,920 # (HID2) rlwinm 3, 3, 0, 2, 0 mtspr 920,3 # (HID2) # Restore the non-volatile registers to their previous values and return. lwz 0, 0x1C(1) lwz 31, 0x14(1) lwz 30, 0x10(1) lwz 29, 0xC(1) addi 1, 1, 0x18 mtlr 0 blr zfloat: .float 0 .align 4 --- NEW FILE: ctype.c --- /* * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd...@de.... * * See file CREDITS for list of people who contributed to this * project. * * 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 program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ /* * linux/lib/ctype.c * * Copyright (C) 1991, 1992 Linus Torvalds */ #include <linux/ctype.h> unsigned char _ctype[] = { _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ --- NEW FILE: exception.S --- #include <asm.h> .globl exception_start, exception_end, exception_patch #define EXCEPTION_PROLOG \ stw r0,0(r4); \ stw r1,4(r4); \ stw r2,8(r4); \ stmw r6,24(r4); \ mfspr r0,913; \ stw r0,424(r4); \ mfspr r0,914; \ stw r0,428(r4); \ mfspr r0,915; \ stw r0,432(r4); \ mfspr r0,916; \ stw r0,436(r4); \ mfspr r0,917; \ stw r0,440(r4); \ mfspr r0,918; \ stw r0,444(r4); \ mfspr r0,919; \ stw r0,448(r4); \ mfdsisr r5; \ mfdar r6 exception_start: .set sprg0,272 // we store the current context, and transfer the control to the exception handler mtspr sprg0, r4 lwz r4,0xC0(0) // get current context ptr stw r3, 12(r4) // r3 saved. mfspr r3, sprg0 stw r3, 16(r4) // r4 saved. stw r5, 20(r4) lhz r3, 418(r4) ori r3, r3, 0x0002 sth r3, 418(r4) mfcr r3 stw r3,128(r4) mflr r3 stw r3,132(r4) mfctr r3 stw r3,136(r4) mfxer r3 stw r3,140(r4) mfsrr0 r3 stw r3,408(r4) mfsrr1 r3 stw r3,412(r4) mr r5,r3 nop mfmsr r3 ori r3,r3,0x2030 mtsrr1 r3 exception_patch: li r3,0 lwz r4, 0xD4(0) rlwinm. r5,r5,0,30,30 // check if exception is recoverable lis r5, exception_handler_transfer@h ori r5, r5, exception_handler_transfer@l mtsrr0 r5 bne 1f lis r5, exception_handler_default@h ori r5, r5, exception_handler_default@l rfi // return to exception handler 1: clrlslwi r5, r3, 24, 2 // calculate address in exception handling table lwz r5,0x3000(r5) rfi exception_end: exception_handler_transfer: #if 0 lis r3, 0xc0b0 1: stwu r3, 4(r3) b 1b #endif mtlr r5 EXCEPTION_PROLOG mr r14, r4 blrl mr r3, r14 // fallthrough exception_context_load: lwz r0,0(r3) lwz r1,4(r3) lwz r2,8(r3) lhz r4,418(r3) rlwinm. r5,r4,0,30,30 beq 1f rlwinm r4,r4,0,31,29 sth r4,418(r3) lmw r5,20(r3) b 2f 1: lmw r13,52(r3) 2: lwz r4,424(r3) mtspr 913,r4 lwz r4,428(r3) mtspr 914,r4 lwz r4,432(r3) mtspr 915,r4 lwz r4,436(r3) mtspr 916,r4 lwz r4,440(r3) mtspr 917,r4 lwz r4,444(r3) mtspr 918,r4 lwz r4,448(r3) mtspr 919,r4 lwz r4,128(r3) mtcrf 0xff,r4 lwz r4,132(r3) mtlr r4 lwz r4,136(r3) mtctr r4 lwz r4,140(r3) mtxer r4 mfmsr r4 rlwinm r4,r4,0,17,15 rlwinm r4,r4,0,31,29 mtmsr r4 lwz r4,408(r3) mtsrr0 r4 lwz r4,412(r3) mtsrr1 r4 lwz r4,16(r3) lwz r3,12(r3) rfi .global decCount decCount: .long 0 .global exception_handler_decrementer exception_handler_decrementer: lis r3, decCount@h ori r3, r3, decCount@l lwz r5, 0(r3) addi r5, r5, 1 stw r5, 0(r3) // 40.5 MHz lis r3, 0x0269 ori r3, r3, 0xFB20 mtdec r3 blr .global exception_handler_system_call exception_handler_system_call: mfspr r3, 1008 ori r4, r3, 8 mtspr 1008, r4 isync sync mtspr 1008, r3 blr --- NEW FILE: exceptionc.c --- #include <exception.h> #include <console.h> #include <linux/string.h> #include <irq.h> #include <cache.h> #include <color.h> extern char exception_start, exception_end, exception_patch; extern void exception_handler_default(); extern void exception_handler_decrementer(); extern void exception_handler_system_call(); extern void exception_handler_external(); unsigned long exception_location[15] = { 0x00000100, 0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000800, 0x00000900, 0x00000C00, 0x00000D00, 0x00000F00, 0x00001300, 0x00001400, 0x00001700 }; const char *exception_name[15] = { "System Reset", "Machine Check", "DSI", "ISI", "Interrupt", "Alignment", "Program", "Floating Point", "Decrementer", "System Call", "Trace", "Performance", "IABR", "Reserved", "Thermal"}; void exception_init() { int i; for (i = 0; i < 15; ++i) { void * address = (void*)(exception_location[i] | 0x80000000); memcpy(address, &exception_start, &exception_end - &exception_start); // fix the "li" to load the correct exception number *(unsigned long*)(&exception_patch - &exception_start + (int)address) |= i; flush_code(address, &exception_end - &exception_start); exception_set_handler(i, exception_handler_default); // *(long*) address = 0x4c000064; flush_code(address, 0x100); } exception_set_handler(8, exception_handler_decrementer); exception_set_handler(9, exception_handler_system_call); exception_set_handler(4, irq_ext); CONTEXT_CURRENT = 0x80002000; CONTEXT_CURRENT_PHYS = 0x2000; } void exception_close() { int i; for (i = 0; i < 15; ++i) { void * address = (void*)(exception_location[i] | 0x80000000); *(long*) address = 0x4c000064; flush_code(address, 0x100); } mtmsr(mfmsr() & ~0x8000); // EE mtmsr(mfmsr() | 0x2002); // FP, RI } void exception_set_handler(int exception, void (*handler)(int, struct context_s*)) { ((void**)0x80003000)[exception] = handler; } void exception_handler_default(int exception) { struct context_s *c = (struct context_s *)CONTEXT_CURRENT; printf("Exception (%s) occured!\n", exception_name[exception]); printf("GPR00 %08lx GPR08 %08lx GPR16 %08lx GPR24 %08lx\n",c->GPR[0], c->GPR[8], c->GPR[16], c->GPR[24]); printf("GPR01 %08lx GPR09 %08lx GPR17 %08lx GPR25 %08lx\n",c->GPR[1], c->GPR[9], c->GPR[17], c->GPR[25]); printf("GPR02 %08lx GPR10 %08lx GPR18 %08lx GPR26 %08lx\n",c->GPR[2], c->GPR[10], c->GPR[18], c->GPR[26]); printf("GPR03 %08lx GPR11 %08lx GPR19 %08lx GPR27 %08lx\n",c->GPR[3], c->GPR[11], c->GPR[19], c->GPR[27]); printf("GPR04 %08lx GPR12 %08lx GPR20 %08lx GPR28 %08lx\n",c->GPR[4], c->GPR[12], c->GPR[20], c->GPR[28]); printf("GPR05 %08lx GPR13 %08lx GPR21 %08lx GPR29 %08lx\n",c->GPR[5], c->GPR[13], c->GPR[21], c->GPR[29]); printf("GPR06 %08lx GPR14 %08lx GPR22 %08lx GPR30 %08lx\n",c->GPR[6], c->GPR[14], c->GPR[22], c->GPR[30]); printf("GPR07 %08lx GPR15 %08lx GPR23 %08lx GPR31 %08lx\n",c->GPR[7], c->GPR[15], c->GPR[23], c->GPR[31]); printf("LR %08lx SRR0 %08lx %08lx\n", c->LR, c->SRR0, c->SRR1); printf("DAR: %08lx DSISR %08lx\n", mfspr(19), mfspr(18)); if ((exception == 2) || (exception == 7) || (exception == 6)) // DSI { int i; unsigned long *address = (unsigned long*)c->SRR0; printf("CODE DUMP:\n"); for (i=0; i<12; i+=4) printf("%08lx %08lx %08lx %08lx\n", address[i], address[i+1], address[i+2], address[i+3]); } while (1); } --- NEW FILE: irq.c --- #include <irq.h> struct irq_handler_s { irq_handler_proc *handler; void *context; }; static struct irq_handler_s irq_handler[32]; void irq_ext() { int i; unsigned long cause = *(volatile unsigned long*)0xCC003000; cause &= *(volatile unsigned long*)0xCC003004; for (i = 0; i < 32; ++i) if (cause & (0x80000000>>i)) if (irq_handler[i].handler) irq_handler[i].handler(i, irq_handler[i].context); *(volatile unsigned long*)0xCC003000 = cause; } int request_irq(int irq, irq_handler_proc *handler, void *context) { if (irq_handler[irq].handler) return -1; irq_handler[irq].handler = handler; irq_handler[irq].context = context; *(unsigned long*)0xCC003004 |= 0x80000000>>irq; // enable irq return 0; } int free_irq(int irq, void *context) { if (!irq_handler[irq].handler) return -1; if (irq_handler[irq].context != context) return -2; irq_handler[irq].handler = 0; *(unsigned long*)0xCC003004 &= ~(0x80000000>>irq); return 0; } --- NEW FILE: string.c --- /* * linux/lib/string.c * * Copyright (C) 1991, 1992 Linus Torvalds */ /* * stupid library routines.. The optimized versions should generally be found * as inline code in <asm-xx/string.h> * * These are buggy as well.. * * * Fri Jun 25 1999, Ingo Oeser <io...@in...> * - Added strsep() which will replace strtok() soon (because strsep() is * reentrant and should be faster). Use only strsep() in new code, please. */ #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #ifndef __HAVE_ARCH_STRNICMP /** * strnicmp - Case insensitive, length-limited string comparison * @s1: One string * @s2: The other string * @len: the maximum number of characters to compare */ int strnicmp(const char *s1, const char *s2, size_t len) { /* Yes, Virginia, it had better be unsigned */ unsigned char c1, c2; c1 = 0; c2 = 0; if (len) { do { c1 = *s1; c2 = *s2; s1++; s2++; if (!c1) break; if (!c2) break; if (c1 == c2) continue; c1 = tolower(c1); c2 = tolower(c2); if (c1 != c2) break; } while (--len); } return (int)c1 - (int)c2; } #endif char * ___strtok; #ifndef __HAVE_ARCH_STRCPY /** * strcpy - Copy a %NUL terminated string * @dest: Where to copy the string to * @src: Where to copy the string from */ char * strcpy(char * dest,const char *src) { char *tmp = dest; while ((*dest++ = *src++) != '\0') /* nothing */; return tmp; } #endif #ifndef __HAVE_ARCH_STRNCPY /** * strncpy - Copy a length-limited, %NUL-terminated string * @dest: Where to copy the string to * @src: Where to copy the string from * @count: The maximum number of bytes to copy * * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. * However, the result is not %NUL-terminated if the source exceeds * @count bytes. */ char * strncpy(char * dest,const char *src,size_t count) { char *tmp = dest; while (count-- && (*dest++ = *src++) != '\0') /* nothing */; return tmp; } #endif #ifndef __HAVE_ARCH_STRCAT /** * strcat - Append one %NUL-terminated string to another * @dest: The string to be appended to * @src: The string to append to it */ char * strcat(char * dest, const char * src) { char *tmp = dest; while (*dest) dest++; while ((*dest++ = *src++) != '\0') ; return tmp; } #endif #ifndef __HAVE_ARCH_STRNCAT /** * strncat - Append a length-limited, %NUL-terminated string to another * @dest: The string to be appended to * @src: The string to append to it * @count: The maximum numbers of bytes to copy * * Note that in contrast to strncpy, strncat ensures the result is * terminated. */ char * strncat(char *dest, const char *src, size_t count) { char *tmp = dest; if (count) { while (*dest) dest++; while ((*dest++ = *src++)) { if (--count == 0) { *dest = '\0'; break; } } } return tmp; } #endif #ifndef __HAVE_ARCH_STRCMP /** * strcmp - Compare two strings * @cs: One string * @ct: Another string */ int strcmp(const char * cs,const char * ct) { register signed char __res; while (1) { if ((__res = *cs - *ct++) != 0 || !*cs++) break; } return __res; } #endif #ifndef __HAVE_ARCH_STRNCMP /** * strncmp - Compare two length-limited strings * @cs: One string * @ct: Another string * @count: The maximum number of bytes to compare */ int strncmp(const char * cs,const char * ct,size_t count) { register signed char __res = 0; while (count) { if ((__res = *cs - *ct++) != 0 || !*cs++) break; count--; } return __res; } #endif #ifndef __HAVE_ARCH_STRCHR /** * strchr - Find the first occurrence of a character in a string * @s: The string to be searched * @c: The character to search for */ char * strchr(const char * s, int c) { for(; *s != (char) c; ++s) if (*s == '\0') return NULL; return (char *) s; } #endif #ifndef __HAVE_ARCH_STRRCHR /** * strrchr - Find the last occurrence of a character in a string * @s: The string to be searched * @c: The character to search for */ char * strrchr(const char * s, int c) { const char *p = s + strlen(s); do { if (*p == (char)c) return (char *)p; } while (--p >= s); return NULL; } #endif #ifndef __HAVE_ARCH_STRLEN /** * strlen - Find the length of a string * @s: The string to be sized */ size_t strlen(const char * s) { const char *sc; for (sc = s; *sc != '\0'; ++sc) /* nothing */; return sc - s; } #endif #ifndef __HAVE_ARCH_STRNLEN /** * strnlen - Find the length of a length-limited string * @s: The string to be sized * @count: The maximum number of bytes to search */ size_t strnlen(const char * s, size_t count) { const char *sc; for (sc = s; count-- && *sc != '\0'; ++sc) /* nothing */; return sc - s; } #endif #ifndef __HAVE_ARCH_STRSPN /** * strspn - Calculate the length of the initial substring of @s which only * contain letters in @accept * @s: The string to be searched * @accept: The string to search for */ size_t strspn(const char *s, const char *accept) { const char *p; const char *a; size_t count = 0; for (p = s; *p != '\0'; ++p) { for (a = accept; *a != '\0'; ++a) { if (*p == *a) break; } if (*a == '\0') return count; ++count; } return count; } #endif #ifndef __HAVE_ARCH_STRPBRK /** * strpbrk - Find the first occurrence of a set of characters * @cs: The string to be searched * @ct: The characters to search for */ char * strpbrk(const char * cs,const char * ct) { const char *sc1,*sc2; for( sc1 = cs; *sc1 != '\0'; ++sc1) { for( sc2 = ct; *sc2 != '\0'; ++sc2) { if (*sc1 == *sc2) return (char *) sc1; } } return NULL; } #endif #ifndef __HAVE_ARCH_STRTOK /** * strtok - Split a string into tokens * @s: The string to be searched * @ct: The characters to search for * * WARNING: strtok is deprecated, use strsep instead. */ char * strtok(char * s,const char * ct) { char *sbegin, *send; sbegin = s ? s : ___strtok; if (!sbegin) { return NULL; } sbegin += strspn(sbegin,ct); if (*sbegin == '\0') { ___strtok = NULL; return( NULL ); } send = strpbrk( sbegin, ct); if (send && *send != '\0') *send++ = '\0'; ___strtok = send; return (sbegin); } #endif #ifndef __HAVE_ARCH_STRSEP /** * strsep - Split a string into tokens * @s: The string to be searched * @ct: The characters to search for * * strsep() updates @s to point after the token, ready for the next call. * * It returns empty tokens, too, behaving exactly like the libc function * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. * Same semantics, slimmer shape. ;) */ char * strsep(char **s, const char *ct) { char *sbegin = *s, *end; if (sbegin == NULL) return NULL; end = strpbrk(sbegin, ct); if (end) *end++ = '\0'; *s = end; return sbegin; } #endif #ifndef __HAVE_ARCH_MEMSET /** * memset - Fill a region of memory with the given value * @s: Pointer to the start of the area. * @c: The byte to fill the area with * @count: The size of the area. * * Do not use memset() to access IO space, use memset_io() instead. */ void * memset(void * s,int c,size_t count) { char *xs = (char *) s; while (count--) *xs++ = c; return s; } #endif #ifndef __HAVE_ARCH_BCOPY /** * bcopy - Copy one area of memory to another * @src: Where to copy from * @dest: Where to copy to * @count: The size of the area. * * Note that this is the same as memcpy(), with the arguments reversed. * memcpy() is the standard, bcopy() is a legacy BSD function. * * You should not use this function to access IO space, use memcpy_toio() * or memcpy_fromio() instead. */ char * bcopy(const char * src, char * dest, int count) { char *tmp = dest; while (count--) *tmp++ = *src++; return dest; } #endif #ifndef __HAVE_ARCH_MEMCPY /** * memcpy - Copy one area of memory to another * @dest: Where to copy to * @src: Where to copy from * @count: The size of the area. * * You should not use this function to access IO space, use memcpy_toio() * or memcpy_fromio() instead. */ void * memcpy(void * dest,const void *src,size_t count) { char *tmp = (char *) dest, *s = (char *) src; while (count--) *tmp++ = *s++; return dest; } #endif #ifndef __HAVE_ARCH_MEMMOVE /** * memmove - Copy one area of memory to another * @dest: Where to copy to * @src: Where to copy from * @count: The size of the area. * * Unlike memcpy(), memmove() copes with overlapping areas. */ void * memmove(void * dest,const void *src,size_t count) { char *tmp, *s; if (dest <= src) { tmp = (char *) dest; s = (char *) src; while (count--) *tmp++ = *s++; } else { tmp = (char *) dest + count; s = (char *) src + count; while (count--) *--tmp = *--s; } return dest; } #endif #ifndef __HAVE_ARCH_MEMCMP /** * memcmp - Compare two areas of memory * @cs: One area of memory * @ct: Another area of memory * @count: The size of the area. */ int memcmp(const void * cs,const void * ct,size_t count) { const unsigned char *su1, *su2; int res = 0; for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) if ((res = *su1 - *su2) != 0) break; return res; } #endif #ifndef __HAVE_ARCH_MEMSCAN /** * memscan - Find a character in an area of memory. * @addr: The memory area * @c: The byte to search for * @size: The size of the area. * * returns the address of the first occurrence of @c, or 1 byte past * the area if @c is not found */ void * memscan(void * addr, int c, size_t size) { unsigned char * p = (unsigned char *) addr; while (size) { if (*p == c) return (void *) p; p++; size--; } return (void *) p; } #endif #ifndef __HAVE_ARCH_STRSTR /** * strstr - Find the first substring in a %NUL terminated string * @s1: The string to be searched * @s2: The string to search for */ char * strstr(const char * s1,const char * s2) { int l1, l2; l2 = strlen(s2); if (!l2) return (char *) s1; l1 = strlen(s1); while (l1 >= l2) { l1--; if (!memcmp(s1,s2,l2)) return (char *) s1; s1++; } return NULL; } #endif #ifndef __HAVE_ARCH_MEMCHR /** * memchr - Find a character in an area of memory. * @s: The memory area * @c: The byte to search for * @n: The size of the area. * * returns the address of the first occurrence of @c, or %NULL * if @c is not found */ void *memchr(const void *s, int c, size_t n) { const unsigned char *p = s; while (n-- != 0) { if ((unsigned char)c == *p++) { return (void *)(p-1); } } return NULL; } #endif --- NEW FILE: string_asm.S --- /* * String handling functions for PowerPC. * * Copyright (C) 1996 Paul Mackerras. * * 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. */ //#include <linux/config.h> //#include <asm/processor.h> //#include <asm/cache.h> //#include <asm/errno.h> //#include <asm/ppc_asm.h> #include <asm.h> #define COPY_16_BYTES \ lwz r7,4(r4); \ lwz r8,8(r4); \ lwz r9,12(r4); \ lwzu r10,16(r4); \ stw r7,4(r6); \ stw r8,8(r6); \ stw r9,12(r6); \ stwu r10,16(r6) #define COPY_16_BYTES_WITHEX(n) \ 8 ## n ## 0: \ lwz r7,4(r4); \ 8 ## n ## 1: \ lwz r8,8(r4); \ 8 ## n ## 2: \ lwz r9,12(r4); \ 8 ## n ## 3: \ lwzu r10,16(r4); \ 8 ## n ## 4: \ stw r7,4(r6); \ 8 ## n ## 5: \ stw r8,8(r6); \ 8 ## n ## 6: \ stw r9,12(r6); \ 8 ## n ## 7: \ stwu r10,16(r6) #define COPY_16_BYTES_EXCODE(n) \ 9 ## n ## 0: \ addi r5,r5,-(16 * n); \ b 104f; \ 9 ## n ## 1: \ addi r5,r5,-(16 * n); \ b 105f; \ .section __ex_table,"a"; \ .align 2; \ .long 8 ## n ## 0b,9 ## n ## 0b; \ .long 8 ## n ## 1b,9 ## n ## 0b; \ .long 8 ## n ## 2b,9 ## n ## 0b; \ .long 8 ## n ## 3b,9 ## n ## 0b; \ .long 8 ## n ## 4b,9 ## n ## 1b; \ .long 8 ## n ## 5b,9 ## n ## 1b; \ .long 8 ## n ## 6b,9 ## n ## 1b; \ .long 8 ## n ## 7b,9 ## n ## 1b; \ .text .text .globl strcpy strcpy: addi r5,r3,-1 addi r4,r4,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 stbu r0,1(r5) bne 1b blr .globl strncpy strncpy: cmpwi 0,r5,0 beqlr mtctr r5 addi r6,r3,-1 addi r4,r4,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 stbu r0,1(r6) bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ blr .globl strcat strcat: addi r5,r3,-1 addi r4,r4,-1 1: lbzu r0,1(r5) cmpwi 0,r0,0 bne 1b addi r5,r5,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 stbu r0,1(r5) bne 1b blr .globl strcmp strcmp: addi r5,r3,-1 addi r4,r4,-1 1: lbzu r3,1(r5) cmpwi 1,r3,0 lbzu r0,1(r4) subf. r3,r0,r3 beqlr 1 beq 1b blr .globl strlen strlen: addi r4,r3,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 bne 1b subf r3,r3,r4 blr .globl memset memset: rlwimi r4,r4,8,16,23 rlwimi r4,r4,16,0,15 addi r6,r3,-4 cmplwi 0,r5,4 blt 7f stwu r4,4(r6) beqlr andi. r0,r6,3 add r5,r0,r5 subf r6,r0,r6 srwi r0,r5,2 mtctr r0 bdz 6f 1: stwu r4,4(r6) bdnz 1b 6: andi. r5,r5,3 7: cmpwi 0,r5,0 beqlr mtctr r5 addi r6,r6,3 8: stbu r4,1(r6) bdnz 8b blr .globl bcopy bcopy: mr r6,r3 mr r3,r4 mr r4,r6 b memcpy .globl memmove memmove: cmplw 0,r3,r4 bgt backwards_memcpy /* fall through */ .globl memcpy memcpy: srwi. r7,r5,3 addi r6,r3,-4 addi r4,r4,-4 beq 2f /* if less than 8 bytes to do */ andi. r0,r6,3 /* get dest word aligned */ mtctr r7 bne 5f 1: lwz r7,4(r4) lwzu r8,8(r4) stw r7,4(r6) stwu r8,8(r6) bdnz 1b andi. r5,r5,7 2: cmplwi 0,r5,4 blt 3f lwzu r0,4(r4) addi r5,r5,-4 stwu r0,4(r6) 3: cmpwi 0,r5,0 beqlr mtctr r5 addi r4,r4,3 addi r6,r6,3 4: lbzu r0,1(r4) stbu r0,1(r6) bdnz 4b blr 5: subfic r0,r0,4 mtctr r0 6: lbz r7,4(r4) addi r4,r4,1 stb r7,4(r6) addi r6,r6,1 bdnz 6b subf r5,r0,r5 rlwinm. r7,r5,32-3,3,31 beq 2b mtctr r7 b 1b .globl backwards_memcpy backwards_memcpy: rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ add r6,r3,r5 add r4,r4,r5 beq 2f andi. r0,r6,3 mtctr r7 bne 5f 1: lwz r7,-4(r4) lwzu r8,-8(r4) stw r7,-4(r6) stwu r8,-8(r6) bdnz 1b andi. r5,r5,7 2: cmplwi 0,r5,4 blt 3f lwzu r0,-4(r4) subi r5,r5,4 stwu r0,-4(r6) 3: cmpwi 0,r5,0 beqlr mtctr r5 4: lbzu r0,-1(r4) stbu r0,-1(r6) bdnz 4b blr 5: mtctr r0 6: lbzu r7,-1(r4) stbu r7,-1(r6) bdnz 6b subf r5,r0,r5 rlwinm. r7,r5,32-3,3,31 beq 2b mtctr r7 b 1b .globl memcmp memcmp: cmpwi 0,r5,0 ble- 2f mtctr r5 addi r6,r3,-1 addi r4,r4,-1 1: lbzu r3,1(r6) lbzu r0,1(r4) subf. r3,r0,r3 bdnzt 2,1b blr 2: li r3,0 blr .global memchr memchr: cmpwi 0,r5,0 ble- 2f mtctr r5 addi r3,r3,-1 1: lbzu r0,1(r3) cmpw 0,r0,r4 bdnzf 2,1b beqlr 2: li r3,0 blr --- NEW FILE: time.c --- #include "processor.h" #define TB_CLOCK 40500000 unsigned long tb_diff_sec(tb_t *end, tb_t *start) { unsigned long upper, lower; upper = end->u - start->u; if (start->l > end->l) upper--; lower = end->l - start->l; return ((upper*((unsigned long)0x80000000/(TB_CLOCK/2))) + (lower/ TB_CLOCK)); } unsigned long tb_diff_msec(tb_t *end, tb_t *start) { unsigned long upper, lower; upper = end->u - start->u; if (start->l > end->l) upper--; lower = end->l - start->l; return ((upper*((unsigned long)0x80000000/(TB_CLOCK/2000))) + (lower/(TB_CLOCK/1000))); } unsigned long tb_diff_usec(tb_t *end, tb_t *start) { unsigned long upper, lower; upper = end->u - start->u; if (start->l > end->l) upper--; lower = end->l - start->l; return ((upper*((unsigned long)0x80000000/(TB_CLOCK/2000000))) + (lower/(TB_CLOCK/1000000))); } unsigned long tb_diff(tb_t *end, tb_t *start) { unsigned long lower; lower = end->l - start->l; return lower; } void udelay(unsigned int us) { tb_t start, end; mftb(&start); while (1) { mftb(&end); if (tb_diff_usec(&end, &start) >= us) break; } } void mdelay(unsigned int ms) { tb_t start, end; mftb(&start); while (1) { mftb(&end); if (tb_diff_msec(&end, &start) >= ms) break; } } void delay(unsigned int s) { tb_t start, end; mftb(&start); while (1) { mftb(&end); if (tb_diff_sec(&end, &start) >= s) break; } } |
From: <rob...@us...> - 2005-01-09 11:40:56
|
Update of /cvsroot/gc-linux/ipl/load In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5953/load Added Files: dol.c dolup.c elf.c loadapp.c Log Message: Sorted all source files int / into the following directories: io, lowlevel, loadand ipl Did some cleaning in the source files, but there is still much to be done --- NEW FILE: dol.c --- #include <linux/string.h> #include <console.h> #include <processor.h> #include <exception.h> void load_dol(void *dol, int size) { void (*entrypoint)(); if ((*(unsigned long*)dol) > 0x1000) { printf("loading binary file..\n"); memcpy((void*)0x80003100, dol, size); entrypoint = (void(*)())0x80003100; } else { struct dol_s { unsigned long sec_pos[18]; unsigned long sec_address[18]; unsigned long sec_size[18]; unsigned long bss_address, bss_size, entry_point; } *d = (struct dol_s*)dol; int i; for (i=0; i<18; ++i) { if (!d->sec_size[i]) continue; printf("relocating %08lx to %08lx (%ld bytes)\n", d->sec_pos[i], d->sec_address[i], d->sec_size[i]); memcpy((void*)d->sec_address[i], ((unsigned char*)dol)+d->sec_pos[i], d->sec_size[i]); } printf("clearing BSS (at %08lx, %lu bytes...)\n", d->bss_address, d->bss_size); memset((void*)d->bss_address, 0, d->bss_size); entrypoint = (void(*)())d->entry_point; } mtmsr((mfmsr() | 2) & ~0x8000); printf("jumping to %p\n", entrypoint); flush_code(0x80000000, 0x1800000); exception_close(); entrypoint(); printf("returned from entrypoint - should never happen. but happens.\n"); while(1); } --- NEW FILE: dolup.c --- /* * DOL loader over tcp/ip * Receives a DOL on port 4000 and executes it */ #include "lwip/debug.h" #include "lwip/stats.h" #include "lwip/tcp.h" #include <console.h> #include <types.h> #include <processor.h> #include <elf.h> // ELF is read into a fixed buffer //#define FILE_BUFFER ((u8*)0x80800000) #include <memlayout.h> #define TYPE_UNKNOWN 0 #define TYPE_DOL 1 #define TYPE_ELF 2 struct dolup_state { struct dol_s { u32 sec_pos[18]; u32 sec_address[18]; u32 sec_size[18]; u32 bss_address, bss_size, entry_point; u32 dummy[7]; } dolhdr; u32 filepos; u32 filesize; int type; int retries; }; /*-----------------------------------------------------------------------------------*/ static void conn_err(void *arg, err_t err) { struct dolup_state *hs; hs = arg; mem_free(hs); } /*-----------------------------------------------------------------------------------*/ static void close_conn(struct tcp_pcb *pcb, struct dolup_state *hs) { void (*entrypoint)(); printf("DOLUP: connection CLOSE\n"); tcp_arg(pcb, NULL); tcp_sent(pcb, NULL); tcp_recv(pcb, NULL); tcp_close(pcb); entrypoint = NULL; switch (hs->type) { case TYPE_DOL: entrypoint = (void(*)())hs->dolhdr.entry_point; break; case TYPE_ELF: entrypoint = (void(*)(void))load_elf_image((unsigned long)ELF_FILE_BUFFER); break; default: printf("unknown file type\n"); } mem_free(hs); if (entrypoint != NULL) { // clear interrupt mask *(volatile unsigned long*)0xCC003004 = 0; exception_close(); printf("starting execution at %p\n", entrypoint); entrypoint(); } } /*-----------------------------------------------------------------------------------*/ static err_t dolup_poll(void *arg, struct tcp_pcb *pcb) { struct dolup_state *hs; hs = arg; // printf("Polll\n"); if (hs == NULL) { printf("Null, close\n"); tcp_abort(pcb); return ERR_ABRT; } else { ++hs->retries; if (hs->retries == 40) { tcp_abort(pcb); return ERR_ABRT; } // send_data(pcb, hs); } return ERR_OK; } /*-----------------------------------------------------------------------------------*/ #if 0 static err_t dolup_sent(void *arg, struct tcp_pcb *pcb, u16_t len) { return ERR_OK; } #endif /*-----------------------------------------------------------------------------------*/ static err_t dolup_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { struct dolup_state *hs; hs = arg; if (err == ERR_OK && p != NULL) { // Inform TCP that we have taken the data. tcp_recved(pcb, p->tot_len); u8 * data = p->payload; int len = p->tot_len; while (len > 0) { if (hs->filepos < 256) { // copy data into header u8 *header = (u8 *)(&hs->dolhdr); int tmp_len = len; if (hs->filepos + tmp_len > 256) tmp_len = 256 - hs->filepos; memcpy(header+hs->filepos, data, tmp_len); hs->filepos+=tmp_len; if (hs->filepos == 256) { // check for elf if ( valid_elf_image((u32)header) ) { hs->type = TYPE_ELF; hs->filesize = 0; // no decoding memcpy( ELF_FILE_BUFFER, header, 256); } else { int i; // calculate dol size hs->type = TYPE_DOL; hs->filesize = 256; for (i=0; i<18; i++) { u32 sec_end = hs->dolhdr.sec_pos[i] + hs->dolhdr.sec_size[i]; if (sec_end > hs->filesize) { hs->filesize = sec_end; } } } } data+=tmp_len; len-=tmp_len; } else { switch (hs->type) { case TYPE_DOL: { // write dol into memory int i, found=0; for (i=0; i<18 && !found ; i++) { if ((hs->dolhdr.sec_pos[i] <= hs->filepos) && (hs->dolhdr.sec_pos[i]+hs->dolhdr.sec_size[i] > hs->filepos)) { u32 tmp_offset = hs->filepos - hs->dolhdr.sec_pos[i]; u32 tmp_len = len; if ( tmp_offset + tmp_len > hs->dolhdr.sec_size[i] ) { tmp_len = hs->dolhdr.sec_size[i] - tmp_offset; } memcpy((void*)(hs->dolhdr.sec_address[i] + tmp_offset), data, tmp_len); flush_code((void*)(hs->dolhdr.sec_address[i] + tmp_offset), tmp_len); data+=tmp_len; len-=tmp_len; hs->filepos+=tmp_len; found=1; } } if (!found) { // if the filepos was not found in the dol header, advance the file pointer by one byte. there could be some // alignment between sections, for example for DVD reads data++; len--; hs->filepos++; } break; } default: { // copy others into buffer memcpy(ELF_FILE_BUFFER + hs->filepos, data, len); hs->filepos += len; data += len; len = 0; break; } } } } } if (p != NULL) { pbuf_free(p); } if (err == ERR_OK) { if ((hs->filepos >= hs->filesize && hs->filesize > 0) || (hs->type == TYPE_ELF && p == NULL)) { printf("\n"); close_conn(pcb, hs); } else { printf("."); } } return ERR_OK; } /*-----------------------------------------------------------------------------------*/ static err_t dolup_accept(void *arg, struct tcp_pcb *pcb, err_t err) { struct dolup_state *hs; tcp_setprio(pcb, TCP_PRIO_MIN); /* Allocate memory for the structure that holds the state of the connection. */ hs = mem_malloc(sizeof(struct dolup_state)); if (hs == NULL) { printf("dolup_accept: Out of memory\n"); return ERR_MEM; } printf("dolup: accept\n"); hs->filepos = 0; hs->filesize = 0; hs->type = TYPE_UNKNOWN; /* Tell TCP that this is the structure we wish to be passed for our callbacks. */ tcp_arg(pcb, hs); /* Tell TCP that we wish to be informed of incoming data by a call to the dolup_recv() function. */ tcp_recv(pcb, dolup_recv); tcp_err(pcb, conn_err); tcp_poll(pcb, dolup_poll, 4); return ERR_OK; } /*-----------------------------------------------------------------------------------*/ void dolup_init(void) { struct tcp_pcb *pcb; pcb = tcp_new(); tcp_bind(pcb, IP_ADDR_ANY, 4000); pcb = tcp_listen(pcb); tcp_accept(pcb, dolup_accept); } --- NEW FILE: elf.c --- /* * Copyright (c) 2001 William L. Pitts * Modifications (c) 2004 Felix Domke * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */ #include <linux/types.h> #include <elf_abi.h> #include <linux/string.h> #include <console.h> #include <cache.h> #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif /* ====================================================================== * Determine if a valid ELF image exists at the given memory location. * First looks at the ELF header magic field, the makes sure that it is * executable and makes sure that it is for a PowerPC. * ====================================================================== */ int valid_elf_image (unsigned long addr) { Elf32_Ehdr *ehdr; /* Elf header structure pointer */ /* -------------------------------------------------- */ ehdr = (Elf32_Ehdr *) addr; if (!IS_ELF (*ehdr)) { printf ("## No elf image at address 0x%08lx\n", addr); return 0; } if (ehdr->e_type != ET_EXEC) { printf ("## Not a 32-bit elf image at address 0x%08lx\n", addr); return 0; } #if 0 if (ehdr->e_machine != EM_PPC) { printf ("## Not a PowerPC elf image at address 0x%08lx\n", addr); return 0; } #endif return 1; } /* ====================================================================== * A very simple elf loader, assumes the image is valid, returns the * entry point address. * ====================================================================== */ unsigned long load_elf_image (unsigned long addr) { Elf32_Ehdr *ehdr; Elf32_Shdr *shdr; unsigned char *strtab = 0; unsigned char *image; int i; ehdr = (Elf32_Ehdr *) addr; /* Find the section header string table for output info */ shdr = (Elf32_Shdr *) (addr + ehdr->e_shoff + (ehdr->e_shstrndx * sizeof (Elf32_Shdr))); if (shdr->sh_type == SHT_STRTAB) strtab = (unsigned char *) (addr + shdr->sh_offset); /* Load each appropriate section */ for (i = 0; i < ehdr->e_shnum; ++i) { shdr = (Elf32_Shdr *) (addr + ehdr->e_shoff + (i * sizeof (Elf32_Shdr))); if (!(shdr->sh_flags & SHF_ALLOC) || shdr->sh_addr == 0 || shdr->sh_size == 0) { continue; } shdr->sh_addr &= 0x3FFFFFFF; shdr->sh_addr |= 0x80000000; if (strtab) { printf ("%sing %s @ 0x%08lx (%ld bytes)\n", (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", &strtab[shdr->sh_name], (unsigned long) shdr->sh_addr, (long) shdr->sh_size); } if (shdr->sh_type == SHT_NOBITS) { memset ((void *)shdr->sh_addr, 0, shdr->sh_size); } else { image = (unsigned char *) addr + shdr->sh_offset; memcpy ((void *) shdr->sh_addr, (const void *) image, shdr->sh_size); } flush_code ((void*)shdr->sh_addr, shdr->sh_size); } printf("loading elf done!\n"); return (ehdr->e_entry & 0x3FFFFFFF) | 0x80000000; } --- NEW FILE: loadapp.c --- #include <dvd.h> #include <console.h> #include <linux/string.h> #include <pad.h> #include <processor.h> #include <cache.h> #include "lowmem.h" #include "ipl.h" typedef int my_dvd_read(void *, int, int); static char *ccodes[]={"JPN", "USA", "PAL", "???"}; void load_app(my_dvd_read *dvd_read) { char *buffer = (char*)0xC0100000; void (*app_init)(void (*report)(const char *fmt, ...)); int (*app_main)(void **dst, int *size, int *offset); void *(*app_final)(); void (*entrypoint)(); void (*app_entry)(void(**init)(const char *fmt, ...), int (**main)(), void *(**final)()); /* now we initialize the dvdrom. this will read the disc id. */ printf("init dvd..\n"); if (dvd_init()) { printf("dvd init failed (%s)!\n", dvd_get_error_message()); return; } ipl_set_config(2); /* disable modified bios */ /* we need to disable external IRQs */ exception_close(); dvd_set_streaming(); /* we check if we have a fitting video mode selected, otherwise the */ /* game *will* OSFatal because it can't change PAL <-> NTSC. */ /* we ignore the fact that there are different hardwares out there */ /* and hope the user's tvset is able to cope with that. good luck. */ printf("checking countrycode..."); dvd_read(buffer, 0x20, 0x440); int ccode = *(int*)(buffer + 0x18); if (ccode >= 3) ccode = 3; printf(" found %s.\n", ccodes[ccode]); int current_mode = lowmem_current_video_mode & 1; /* 0, 2, 4 are NTSC-styled modes, 1, 3, 5 are PAL-styled modes. */ int required_mode = (ccode == 2) ? 1 : 0; /* pal for PAL, otherwise NTSC */ if (current_mode != required_mode) { printf("adjusting video mode to %s\n", required_mode ? "PAL" : "NTSC"); lowmem_current_video_mode = required_mode; } video_init((*(unsigned long*)0x800000cc) & 1); /* load the apploader-header. */ printf("reading apploader!\n"); memset(buffer, 0, 0x20); printf("dvd_read\n"); dvd_read(buffer, 0x20, 0x2440); printf("apploader date: %s\n", buffer); printf("apploader entry point: %08lx\n", *(unsigned long*)(buffer+0x10)); printf("apploader size: %08lx\n", *(unsigned long*)(buffer+0x14)); /* read the apploader */ dvd_read((void*)0x81200000, ((*(unsigned long*)(buffer+0x14)) + 31) &~31, 0x2460); /* call abbloader entry */ app_entry = *(unsigned long*)(buffer+0x10); app_entry(&app_init, &app_main, &app_final); /* intialize it with our debug printf */ app_init(printf); /* call the apploader until it's done. */ while (1) { void *dst=0; int len=0, offset=0; printf("."); int res = app_main(&dst, &len, &offset); if (!res) break; if (dvd_read(dst, len, offset)) printf("DVD READ ERROR: %s\n", dvd_get_error_message()); flush_code(dst, len); } entrypoint = app_final(); entrypoint(); while (1); } |
From: <rob...@us...> - 2005-01-09 11:40:56
|
Update of /cvsroot/gc-linux/ipl/ipl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5953/ipl Added Files: flash.c ipl.c Log Message: Sorted all source files int / into the following directories: io, lowlevel, loadand ipl Did some cleaning in the source files, but there is still much to be done --- NEW FILE: flash.c --- /* * function to write to flash. Only works with modified IPL "ROM"s. */ #include <ipl.h> #include <vsprintf.h> int chip_erase(void) { rom_write(0xAAA, 0xAA); rom_write(0x555, 0x55); rom_write(0xAAA, 0x80); rom_write(0xAAA, 0xAA); rom_write(0x555, 0x55); rom_write(0xAAA, 0x10); printf("erasing..\n"); while (!(rom_read(0) & 0x80)); return 0; } int erase_sector(int addr) { rom_write(0xAAA, 0xAA); rom_write(0x555, 0x55); rom_write(0xAAA, 0x80); rom_write(0xAAA, 0xAA); rom_write(0x555, 0x55); rom_write(addr, 0x30); printf("\r%08x erase..\n", addr); // while (!(rom_read(addr) & 0x80)) ; while (rom_read(addr) != rom_read(addr)); return 0; } int is_eraseblock(int addr) { if (addr >= 0x10000) return !(addr & 0xFFFF); return ((addr == 0) || (addr == 0x4000) || (addr == 0x6000) || (addr == 0x8000)); } int do_flash(int target, unsigned char *src, int len) { ipl_set_config(0x0); // CFI query rom_write(0xAA, 0x98); printf("CFI data:\n"); int addr; for (addr = 0; addr < 0x100; addr += 0x10) { int i; for (i=0; i<0x10; i += 2) printf("%02x ", rom_read(addr + i)); for (i=0; i<0x10; i += 2) { int v = rom_read(addr + i); printf("%c", v >= 0x20 ? v : '.'); } printf("\n"); } printf("man id:\n"); int i; for (i=0; i<10; ++i) { rom_write(0, 0xF0); rom_write(0xAAA, 0xAA); rom_write(0x555, 0x55); rom_write(0xAAA, 0x90); printf("%02x ", rom_read(i * 2)); } printf("\n"); rom_write(0xAAA, 0xAA); rom_write(0x555, 0x55); rom_write(0xAAA, 0x20); printf("erasing...\n"); for (addr = target; addr < (target + len); ++addr) if (is_eraseblock(addr)) erase_sector(addr); printf("flashing...\n"); while (len) { rom_write(target, 0xA0); rom_write(target, *src); while (rom_read(target) != *src); ++src; ++target; --len; } printf("done!\n"); return 0; } --- NEW FILE: ipl.c --- /* * different stuff to access the IPL chips (including special functions) */ #include <exi.h> #include <time.h> #include <ipl.h> unsigned char sram_data[64] __attribute__((__aligned__(32))); void exi_sram_read(void *data) { unsigned long val; exi_select(0, 1, 3); val = 0x20000100; exi_write(0, &val, 4); exi_read(0, data, 64); exi_deselect(0); } void exi_sram_write(void *data) { unsigned long val; exi_select(0, 1, 3); val = 0xA0000100; exi_write(0, &val, 4); exi_write(0, data, 64); exi_deselect(0); } void exi_ipl_write(unsigned long addr, unsigned long val) { exi_select(0, 1, 3); exi_write(0, &addr, 4); exi_write(0, &val, 4); exi_deselect(0); } unsigned char rom_read(int addr) { addr <<= 6; unsigned long val; exi_select(0, 1, 3); exi_write(0, &addr, 4); exi_read(0, &val, 4); exi_deselect(0); return val >> 24; } void rom_readn(int addr, unsigned char *d, int len) { while (len) { int max = 1024 - (addr & 1023); if (len < max) max = len; addr <<= 6; exi_select(0, 1, 3); exi_write(0, &addr, 4); exi_read(0, d, max); exi_deselect(0); addr += max; len -= max; } } void rom_write(int addr, unsigned char c) { unsigned long val; addr <<= 6; addr |= 0x80000000; val = c << 24; exi_select(0, 1, 3); exi_write(0, &addr, 4); exi_write(0, &val, 4); exi_deselect(0); } void s_putc(unsigned char c) { unsigned long val, addr; addr = 0xA8000000; val = c << 24; exi_select(0, 1, 3); exi_write(0, &addr, 4); exi_write(0, &val, 4); exi_deselect(0); // udelay(1000000/115200*20); mdelay(1); } void ipl_read(void *dst, unsigned long addr, int len) { addr <<= 6; exi_select(0, 1, 3); exi_write(0, &addr, 4); exi_read(0, dst, len); exi_deselect(0); } void ipl_set_config(unsigned char c) { unsigned long val, addr; addr = 0xB0000000; val = c << 24; exi_select(0, 1, 3); exi_write(0, &addr, 4); exi_write(0, &val, 4); exi_deselect(0); } void ipl_boot(int what) { if (what < 0) ipl_set_config(0x2); // boot to original IPL else ipl_set_config(what << 4); // boot with prefix *(unsigned long*)0xcc003024=0; while (1); } //Test for rob's ipl int ipl_rob_test() { //request the dataflash's status. Test it multiple times, to make sure they are //not some randomly read values from some memory exi_select(0,1,4); exi_rw(0,0x40,1); //select dataflash exi_rw(0,0x40,1); //request status int i; for (i=0;i<20;i++) if ((exi_rw(0,-1,1) & 0x3c) != 0x1c) return 0; return 1; } void ipl_rob_read(void *dst, unsigned long addr, int len) { unsigned long page,byte,dfaddr; byte=addr % DATAFLASH_PAGE_SIZE; page=(addr-byte)/DATAFLASH_PAGE_SIZE; dfaddr=(page<<9) | byte; exi_select(0,1,4); exi_rw(0,0x40,1); //select dataflash exi_rw(0,0xE8000000|dfaddr,4); //send page and byte adress exi_rw(0,-1,4); //dummy exi_read(0,dst,len); exi_deselect(0); } |
From: <rob...@us...> - 2005-01-09 11:40:55
|
Update of /cvsroot/gc-linux/ipl/include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5953/include Modified Files: exi.h ipl.h pad.h Log Message: Sorted all source files int / into the following directories: io, lowlevel, loadand ipl Did some cleaning in the source files, but there is still much to be done Index: exi.h =================================================================== RCS file: /cvsroot/gc-linux/ipl/include/exi.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- exi.h 29 Dec 2004 11:10:31 -0000 1.1.1.1 +++ exi.h 9 Jan 2005 11:40:46 -0000 1.2 @@ -14,6 +14,7 @@ void exi_dma_start(int channel, void *data, int len, int mode); void exi_read(int channel, void *data, int len); void exi_write(int channel, const void *data, int len); +unsigned long exi_rw(int channel,unsigned long data,int len); void exi_init(); Index: ipl.h =================================================================== RCS file: /cvsroot/gc-linux/ipl/include/ipl.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- ipl.h 29 Dec 2004 11:10:31 -0000 1.1.1.1 +++ ipl.h 9 Jan 2005 11:40:46 -0000 1.2 @@ -1,6 +1,8 @@ #ifndef __ipl_h #define __ipl_h +#define DATAFLASH_PAGE_SIZE 264 + extern unsigned char sram_data[64]; void exi_sram_read(void *data); @@ -16,4 +18,8 @@ void ipl_set_config(unsigned char c); void ipl_boot(int what); +/* ipl functions for rob's modchip */ +int ipl_rob_test(); +void ipl_rob_read(void *dst, unsigned long addr, int len); + #endif Index: pad.h =================================================================== RCS file: /cvsroot/gc-linux/ipl/include/pad.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- pad.h 29 Dec 2004 11:10:31 -0000 1.1.1.1 +++ pad.h 9 Jan 2005 11:40:46 -0000 1.2 @@ -85,6 +85,7 @@ /*+----------------------------------------------------------------------------------------------+*/ /*+----------------------------------------------------------------------------------------------+*/ /*+----------------------------------------------------------------------------------------------+*/ +void pad_init(); void PAD_ReadState(PAD *pPad, u8 PadChannel); /*+----------------------------------------------------------------------------------------------+*/ |
Update of /cvsroot/gc-linux/ipl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5953 Modified Files: Makefile main.c Removed Files: cache.S console.c console_font.c console_font_8x8.c crt0.s ctype.c dol.c dvd.c elf.c exception.S exceptionc.c exi.c flash.c ipl.c ipl_tmb.h irq.c loadapp.c lowmem.h network.c pad.c string.c string_asm.S time.c video.c vsprintf.c Log Message: Sorted all source files int / into the following directories: io, lowlevel, loadand ipl Did some cleaning in the source files, but there is still much to be done Index: Makefile =================================================================== RCS file: /cvsroot/gc-linux/ipl/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- Makefile 30 Dec 2004 10:21:15 -0000 1.2 +++ Makefile 9 Jan 2005 11:40:45 -0000 1.3 @@ -42,33 +42,49 @@ #-Werror # Files -IPL_OBJS = main.o string_asm.o string.o ctype.o video.o console.o exi.o \ - cache.o vsprintf.o pad.o irq.o console_font.o elf.o dvd.o dol.o \ - network.o loadapp.o exception.o exceptionc.o \ - time.o ipl.o flash.o dolup/dolup.o +MAIN_OBJS = \ + main.o -DISK_OBJS = disk/sd.o disk/fat.o disk/file.o +IO_OBJS = \ + io/video.o io/console.o io/console_font.o io/vsprintf.o \ + io/exi.o io/dvd.o io/network.o io/sram.o + +IPL_OBJS = \ + ipl/ipl.o ipl/flash.o + +LOWLEVEL_OBJS = \ + lowlevel/cache.o lowlevel/exception.o lowlevel/exceptionc.o \ + lowlevel/irq.o lowlevel/string_asm.o lowlevel/string.o \ + lowlevel/ctype.o lowlevel/time.o + +LOAD_OBJS = \ + load/elf.o load/dol.o load/dolup.o load/loadapp.o + +DISK_OBJS = \ + disk/sd.o disk/fat.o disk/file.o io/pad.o LWIP_OBJS = \ - lwip/core/tcp_in.o \ - lwip/core/inet.o lwip/core/mem.o lwip/core/memp.o \ - lwip/core/netif.o lwip/core/pbuf.o lwip/core/raw.o lwip/core/stats.o \ - lwip/core/sys.o lwip/core/tcp.o lwip/core/ipv4/ip_addr.o \ - lwip/core/ipv4/icmp.o lwip/core/ipv4/ip.o lwip/core/ipv4/ip_frag.o \ - lwip/core/tcp_out.o lwip/core/udp.o lwip/netif/etharp.o \ + lwip/core/tcp_in.o \ + lwip/core/inet.o lwip/core/mem.o lwip/core/memp.o \ + lwip/core/netif.o lwip/core/pbuf.o lwip/core/raw.o lwip/core/stats.o \ + lwip/core/sys.o lwip/core/tcp.o lwip/core/ipv4/ip_addr.o \ + lwip/core/ipv4/icmp.o lwip/core/ipv4/ip.o lwip/core/ipv4/ip_frag.o \ + lwip/core/tcp_out.o lwip/core/udp.o lwip/netif/etharp.o \ ./lwip/arch/gc/lib.o ./lwip/arch/gc/netif/gcif.o \ ./lwip/arch/gc/lib_arch.o \ #lwip/core/dhcp.o -HTTPD_OBJS = httpd/vfs.o httpd/httpd.o httpd/flash_put.o +HTTPD_OBJS = \ + httpd/vfs.o httpd/httpd.o httpd/flash_put.o LIBRARIES = # gdbstub/libgdbstub.a # ./lwip/core/dhcp.o -OBJS = crt0.o $(IPL_OBJS) $(LWIP_OBJS) $(HTTPD_OBJS) $(DISK_OBJS) $(LIBRARIES) +OBJS = lowlevel/crt0.o $(MAIN_OBJS) $(IPL_OBJS) $(IO_OBJS) $(LOWLEVEL_OBJS) \ + $(DISK_OBJS) $(LOAD_OBJS) $(LWIP_OBJS) $(HTTPD_OBJS) $(LIBRARIES) # Build rules all: main.dol main_boot.bin @@ -77,13 +93,15 @@ rm -rf $(OBJS) realclean: - find -name *.o | xargs -r rm - find -name *.a | xargs -r rm - find -name *~ | xargs -r rm - find -name *.bin | xargs -r rm - find -name *.dol | xargs -r rm - find -name *.elf | xargs -r rm - + find -name '*.o' | xargs -r rm + find -name '*.a' | xargs -r rm + find -name '*~' | xargs -r rm + find -name '*.bin' | xargs -r rm + find -name '*.dol' | xargs -r rm + find -name '*.elf' | xargs -r rm + find -name '*.map' | xargs -r rm + find -name '*.tmp' | xargs -r rm + .c.o: $(CC) $(CFLAGS) -c -o $@ $*.c @@ -107,8 +125,8 @@ $(OBJCOPY) -O binary $< $@ main.elf: $(OBJS) - $(CC) $(LDFLAGS) -Wl,-n -o $@ -Wl,-Ttext=0x80D00000 $(OBJS) -Wl,-Map -Wl,main.map -# $(CC) $(LDFLAGS) -Wl,-n -o $@ -Wl,-Ttext=0x80003100 $(OBJS) -Wl,-Map -Wl,main.map +# $(CC) $(LDFLAGS) -Wl,-n -o $@ -Wl,-Ttext=0x80D00000 $(OBJS) -Wl,-Map -Wl,main.map + $(CC) $(LDFLAGS) -Wl,-n -o $@ -Wl,-Ttext=0x80003100 $(OBJS) -Wl,-Map -Wl,main.map $(CC) $(LDFLAGS) -Wl,-n -o main_high.elf -Wl,-Ttext=0x817c0000 $(OBJS) -Wl,-Map -Wl,main_high.map main_boot.elf: $(OBJS) Index: main.c =================================================================== RCS file: /cvsroot/gc-linux/ipl/main.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- main.c 29 Dec 2004 11:49:28 -0000 1.2 +++ main.c 9 Jan 2005 11:40:46 -0000 1.3 @@ -8,7 +8,8 @@ #include "video.h" #include "color.h" #include "time.h" -#include "disk/sd.h" +#include "sram.h" +#include "sd.h" #include <linux/string.h> #include <network.h> #include <dvd.h> @@ -29,47 +30,6 @@ void load_app(my_dvd_read *dvd); extern void _start(), _end(); -void pad_init() -{ - *(volatile unsigned long*)0xCC006430 = 0x00000000; - *(volatile unsigned long*)0xCC006438 = 0x80000000; - *(volatile unsigned long*)0xCC006430 = 0x00f70200; - *(volatile unsigned long*)0xCC006438 = 0x80000000; - *(volatile unsigned long*)0xCC006480 = 0x00000000; - *(volatile unsigned long*)0xCC006434 = 0xc0010301; - *(volatile unsigned long*)0xCC006438 = 0x00000000; - - (void)*(volatile unsigned long*)0xCC006434; - - *(volatile unsigned long*)0xCC006430 |= 0xF0; // enable all four controller ports - - *(volatile unsigned long*)0xCC006400 = 0x00400300; - *(volatile unsigned long*)0xCC00640C = 0x00400300; - *(volatile unsigned long*)0xCC006418 = 0x00400300; - *(volatile unsigned long*)0xCC006424 = 0x00400300; - - udelay(1000); - - *(volatile unsigned long*)0xCC006430 = 0x00000000; - *(volatile unsigned long*)0xCC006438 = 0x80000000; - *(volatile unsigned long*)0xCC006430 = 0x00f70200; - *(volatile unsigned long*)0xCC006438 = 0x80000000; - *(volatile unsigned long*)0xCC006480 = 0x00000000; - *(volatile unsigned long*)0xCC006434 = 0xc0010301; - *(volatile unsigned long*)0xCC006438 = 0x00000000; - - (void)*(volatile unsigned long*)0xCC006434; - - *(volatile unsigned long*)0xCC006430 |= 0xF0; // enable all four controller ports - - *(volatile unsigned long*)0xCC006400 = 0x00400300; - *(volatile unsigned long*)0xCC00640C = 0x00400300; - *(volatile unsigned long*)0xCC006418 = 0x00400300; - *(volatile unsigned long*)0xCC006424 = 0x00400300; - *(volatile unsigned long*)0xCC006430 = 0x000701f0; - *(volatile unsigned long*)0xCC006438 = 0x80000000; - while (!((*(volatile unsigned long*) 0xCC006438)&0x20000000)); -} void lowmem_init() { @@ -117,61 +77,6 @@ static struct console_data_s console; -void sram_set_videomode(int v) -{ - sram_data[33] = v; -} - -int sram_get_videomode(void) -{ - return sram_data[33]; -} - -void sram_set_autoboot(int v) -{ - sram_data[34] = v; -} - -int sram_get_autoboot(void) -{ - return sram_data[34]; -} - -struct ip_addr *sram_get_ip(int w) -{ - return (struct ip_addr*)(sram_data + 0x24 + w * 4); -} - -void sram_load_defaults(void) -{ - sram_data[32] = '!'; - - sram_set_autoboot(0); - sram_set_videomode(1); - IP4_ADDR(sram_get_ip(0), 10,0,0,203); - IP4_ADDR(sram_get_ip(1), 255,255,255,0); - IP4_ADDR(sram_get_ip(2), 10,0,0,1); -} - -void read_sram(void) -{ - struct PAD pad; - PAD_ReadState(&pad, 0); - - if (!pad.Digital.Start) - exi_sram_read(sram_data); - else - memset(sram_data + 32, 0, 32); - - if (sram_data[32] != '!') - sram_load_defaults(); -} - -void write_sram(void) -{ - exi_sram_write(sram_data); -} - /* the menu stuff. */ struct menuentry_s; @@ -183,6 +88,7 @@ void menu_boot_game(struct menuentry_s *entry, int event, int data); void menu_boot_auto(struct menuentry_s *entry, int event, int data); void menu_boot_sd(struct menuentry_s *entry, int event, int data); +void menu_debug(struct menuentry_s *entry, int event, int data); #define EVENT_INIT 0 #define EVENT_REDRAW 1 @@ -216,9 +122,21 @@ {"Loader at 1MB", 0, menu_boot_ipl, 8}, {"Autoboot", 0, menu_boot_auto}, {"Boot from SD", 0, menu_boot_sd}, + {"Debug",0,menu_debug}, {0,0,0}, }; +void menu_debug(struct menuentry_s *entry, int event, int data) +{ + unsigned char buffer[256]; + if ((event == EVENT_BUTTON) && (data == BUTTON_A)) { + ipl_rob_read(buffer,0,256); + int i; + for (i=0;i<256;i++) printf("%02x ",buffer[i]); + for(;;); + } +} + void menu_boot_sd(struct menuentry_s *entry, int event, int data) { if ((event == EVENT_BUTTON) && (data == BUTTON_A)) { @@ -393,6 +311,8 @@ lowmem_init(); printf("pad "); pad_init(); + printf("exi "); + exi_init(); printf("sram "); read_sram(); printf("video "); @@ -430,7 +350,6 @@ // printf("--- display offset: %i\n", (s8)sram_data[0x10]); // printf("--- language: %i\n", sram_data[0x12]); - exi_init(); // setup network interface network_init(); @@ -453,6 +372,10 @@ "Y for original IPL\n" "Z for alternative BIOS (at 1MB)\n"); #endif +/* if (ipl_rob_test()) + printf(" Rob's IPL chip found\n"); + else + printf(" Rob's IPL chip not found\n");*/ printf( " - To upload a binary using BBA, just upload it to port 4000.\n" --- cache.S DELETED --- --- console.c DELETED --- --- console_font.c DELETED --- --- console_font_8x8.c DELETED --- --- crt0.s DELETED --- --- ctype.c DELETED --- --- dol.c DELETED --- --- dvd.c DELETED --- --- elf.c DELETED --- --- exception.S DELETED --- --- exceptionc.c DELETED --- --- exi.c DELETED --- --- flash.c DELETED --- --- ipl.c DELETED --- --- ipl_tmb.h DELETED --- --- irq.c DELETED --- --- loadapp.c DELETED --- --- lowmem.h DELETED --- --- network.c DELETED --- --- pad.c DELETED --- --- string.c DELETED --- --- string_asm.S DELETED --- --- time.c DELETED --- --- video.c DELETED --- --- vsprintf.c DELETED --- |
From: <rob...@us...> - 2005-01-09 11:31:57
|
Update of /cvsroot/gc-linux/ipl/lowlevel In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5288/lowlevel Log Message: Directory /cvsroot/gc-linux/ipl/lowlevel added to the repository |
From: <rob...@us...> - 2005-01-09 11:31:57
|
Update of /cvsroot/gc-linux/ipl/load In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5288/load Log Message: Directory /cvsroot/gc-linux/ipl/load added to the repository |
From: <rob...@us...> - 2005-01-09 11:31:57
|
Update of /cvsroot/gc-linux/ipl/ipl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5288/ipl Log Message: Directory /cvsroot/gc-linux/ipl/ipl added to the repository |
From: <rob...@us...> - 2005-01-09 11:31:27
|
Update of /cvsroot/gc-linux/ipl/io In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5195/io Log Message: Directory /cvsroot/gc-linux/ipl/io added to the repository |
From: <pal...@us...> - 2005-01-08 22:46:58
|
Update of /cvsroot/gc-linux/linux/include/linux In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32197/include/linux Modified Files: exi.h Log Message: Initial EXI framework check-in, including BBA changes Index: exi.h =================================================================== RCS file: /cvsroot/gc-linux/linux/include/linux/exi.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- exi.h 19 Oct 2004 22:49:41 -0000 1.6 +++ exi.h 8 Jan 2005 22:46:48 -0000 1.7 @@ -1,9 +1,9 @@ /* * include/linux/exi.h * - * Nintendo GameCube EXpansion Interface definitions - * Copyright (C) 2004 Arthur Othieno <a.o...@bl...> - * Copyright (C) 2004 The GameCube Linux Team + * Nintendo GameCube EXI driver + * Copyright (C) 2004-2005 The GameCube Linux Team + * Copyright (C) 2004,2005 Todd Jeffreys <to...@vo...> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,55 +11,96 @@ * of the License, or (at your option) any later version. * */ -#ifndef __EXI_H -#define __EXI_H -#include <linux/device.h> +#ifndef __exi_bus__ +#define __exi_bus__ -/* while the real framework gets finished, we'll use the lite version */ -#include <../drivers/exi/gcn-exi-lite.h> +#define EXI_DMA_ALIGNMENT 32 +/* ------------------- + exi_sub_command flags + ----------------- */ +#define EXI_CMD_READ (0x00000000) +#define EXI_CMD_WRITE (0x00000005) -struct exi_dev { - unsigned long id; +/* ---------------------- + exi_command flags + --------------------- */ - struct device dev; +#define EXI_DESELECT_UDELAY (0x00000001) + +#include <linux/device.h> +#include <linux/list.h> + +struct exi_command +{ + unsigned int flags; + + void *data; + unsigned int len; + + void *param; + void (*completion_routine)(struct exi_command *cmd); }; -#define to_exi_dev(n) container_of(n, struct exi_dev, dev) +struct exi_command_group +{ + struct list_head list; + + struct exi_device *dev; + + unsigned int flags; + + unsigned int deselect_udelay; + + unsigned int num_commands; + struct exi_command *commands; +}; +extern struct bus_type exi_bus_type; -struct exi_device_id { - unsigned long dev_id; +struct exi_device_id +{ + unsigned int channel; + unsigned int device; + + u32 id; }; -struct exi_driver { - char *name; - struct exi_device_id *id_table; +struct exi_device +{ + struct exi_device_id eid; - int (*probe) (struct exi_dev *dev); - void (*remove) (struct exi_dev *dev); + struct device dev; +}; - struct device_driver driver; +#define to_exi_device(n) container_of(n,struct exi_device,dev) + +struct exi_driver +{ + char *name; + struct exi_device_id eid; + unsigned int frequency; + + int (*probe) (struct exi_device *dev); + void (*remove) (struct exi_device *dev); + + struct device_driver driver; }; -#define to_exi_driver(drv) container_of(drv, struct exi_driver, driver) +typedef int (*exi_irq_handler)(int channel,void *param); +#define to_exi_driver(n) container_of(n,struct exi_driver,driver) -extern struct device exi_bus_dev; -extern struct bus_type exi_bus_type; +void exi_add_command_group(struct exi_command_group *cmd,unsigned int count); -extern int exi_driver_register(struct exi_driver *drv); -extern void exi_driver_unregister(struct exi_driver *drv); +int exi_register_driver(struct exi_driver *drv); +void exi_unregister_driver(struct exi_driver *drv); -static inline void *exi_get_drvdata(struct exi_dev *exi_dev) -{ - return dev_get_drvdata(&exi_dev->dev); -} +int exi_register_irq(int channel_irq,exi_irq_handler func,void *param); +void exi_unregister_irq(int channel_irq); -static inline void exi_set_drvdata(struct exi_dev *exi_dev, void *data) -{ - dev_set_drvdata(&exi_dev->dev, data); -} +#define exi_get_driver_data(exi_device) dev_get_drvdata(&exi_device->dev) +#define exi_set_driver_data(exi_device,data) dev_set_drvdata(&exi_device->dev,data) -#endif /* !__EXI_H */ +#endif |
From: <pal...@us...> - 2005-01-08 22:46:58
|
Update of /cvsroot/gc-linux/linux/drivers/exi In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32197/drivers/exi Modified Files: Makefile Added Files: exi-bus.c exi-hw.c exi_priv.h Log Message: Initial EXI framework check-in, including BBA changes --- NEW FILE: exi-bus.c --- /* * drivers/exi/exi-bus.c * * Nintendo GameCube EXI driver * Copyright (C) 2004-2005 The GameCube Linux Team * Copyright (C) 2004,2005 Todd Jeffreys <to...@vo...> * * 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. * */ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/device.h> #include <linux/exi.h> #include <asm/io.h> #include "exi_priv.h" static int exi_match(struct device *dev,struct device_driver *drv); struct exi_interrupt_handlers irq_handlers[EXI_MAX_CHANNELS]; struct exi_locked_data exi_data[EXI_MAX_CHANNELS]; static struct exi_device exi_devices[EXI_MAX_CHANNELS][EXI_DEVICES_PER_CHANNEL]; static struct device exi_parent[EXI_MAX_CHANNELS] = { { .bus_id = "exi0", }, { .bus_id = "exi1", }, { .bus_id = "exi2", } }; static struct bus_type exi_bus_type = { .match = exi_match, .name = "exi" }; int exi_register_irq(int channel_irq,exi_irq_handler func,void *param) { void* __iomem reg; u32 csr; if (channel_irq < EXI_MAX_CHANNELS) { if (irq_handlers[channel_irq].func) { return -EBUSY; } irq_handlers[channel_irq].param = param; irq_handlers[channel_irq].func = func; /* now setup the hardware */ reg = EXI_CSR(channel_irq); csr = readl(reg); writel(csr | (EXI_CSR_EXIINT | EXI_CSR_EXIINTMASK),reg); return 0; } return -EINVAL; } void exi_unregister_irq(int channel_irq) { void * __iomem reg; u32 csr; if (channel_irq < EXI_MAX_CHANNELS) { irq_handlers[channel_irq].func = NULL; reg = EXI_CSR(channel_irq); csr = readl(reg); writel((csr | EXI_CSR_EXIINT) & ~EXI_CSR_EXIINTMASK,reg); } } static int exi_device_probe(struct device *dev) { struct exi_device *exi_device = to_exi_device(dev); struct exi_driver *exi_driver = to_exi_driver(dev->driver); int err = -ENODEV; if (exi_driver->probe) { err = exi_driver->probe(exi_device); } return err; } static int exi_device_remove(struct device *dev) { struct exi_device *exi_device = to_exi_device(dev); struct exi_driver *exi_driver = to_exi_driver(dev->driver); if (exi_driver->remove) { exi_driver->remove(exi_device); } return 0; } int exi_register_driver(struct exi_driver *driver) { driver->driver.name = driver->name; driver->driver.bus = &exi_bus_type; driver->driver.probe = exi_device_probe; driver->driver.remove = exi_device_remove; return driver_register(&driver->driver); } void exi_unregister_driver(struct exi_driver *driver) { driver_unregister(&driver->driver); } static int exi_match(struct device *dev,struct device_driver *drv) { /* return 1 if the driver can handle the device */ struct exi_device *exi_device = to_exi_device(dev); struct exi_driver *exi_driver = to_exi_driver(drv); if ((exi_device->eid.channel == exi_driver->eid.channel) && (exi_device->eid.device == exi_driver->eid.device) && (exi_device->eid.id == exi_driver->eid.id)) { return 1; } return 0; } static void exi_bus_scan(void) { unsigned int channel; unsigned int device; for (channel=0;channel<EXI_MAX_CHANNELS;++channel) { /* initialize the data per each exi bus */ exi_data[channel].exi_state = EXI_IDLE; exi_data[channel].cur_command = 0; atomic_set(&exi_data[channel].tc_interrupt,0); spin_lock_init(&exi_data[channel].queue_lock); INIT_LIST_HEAD(&exi_data[channel].queue); tasklet_init(&exi_data[channel].tasklet, exi_tasklet, (unsigned long)&exi_data[channel]); /* add the exi devices underneath the parents */ for (device=0;device<EXI_DEVICES_PER_CHANNEL;++device) { exi_devices[channel][device].eid.channel = channel; exi_devices[channel][device].eid.device = device; sprintf(exi_devices[channel][device].dev.bus_id, "dev%u",device); exi_devices[channel][device].dev.parent = &exi_parent[channel]; exi_devices[channel][device].dev.bus = &exi_bus_type; exi_devices[channel][device].dev.platform_data = &exi_data[channel]; /* now ID the device */ exi_devices[channel][device].eid.id = exi_synchronous_id(channel,device); if (exi_devices[channel][device].eid.id != EXI_INVALID_ID) { printk(KERN_INFO "%s:%s: %x\n", exi_parent[channel].bus_id, exi_devices[channel][device].dev.bus_id, exi_devices[channel][device].eid.id); device_register(&exi_devices[channel][device].dev); } } } } void exi_bus_insert(unsigned int channel,unsigned int bInsert) { /* this is all wrong, just skip this function, no hot-plug support for now */ /*u32 device; u32 id; if (bInsert) { for (device=0;device<EXI_DEVICES_PER_CHANNEL;++device) { id = exi_synchronous_id(channel,device); if (id != EXI_INVALID_ID) { device_register(&exi_devices[channel][device].dev); } } } else { device_register(&exi_devices[channel][0].dev); device_register(&exi_devices[channel][1].dev); device_register(&exi_devices[channel][2].dev); }*/ } static int __init exi_init(void) { int i; int r; /* acquire the interrupt */ printk(KERN_INFO "Initializing EXI interface\n"); /* register the bus */ if ((r=bus_register(&exi_bus_type))) { return r; } /* register root devices */ for (i=0;i<EXI_MAX_CHANNELS;++i) { if ((r=device_register(exi_parent+i))) { return r; } } irq_handlers[0].func = NULL; irq_handlers[1].func = NULL; irq_handlers[2].func = NULL; for (r=0;r<EXI_MAX_CHANNELS;++r) { /* wait for all transfers to complete */ while (readl(EXI_CR(r)) & EXI_MR_TSTART) { } /* clear interrupts and reset interrupts */ writel(EXI_CSR_TCINT | EXI_CSR_EXIINT | EXI_CSR_EXTINT | EXI_CSR_EXTINTMASK, EXI_CSR(r)); } /* now enumerate through the bus and add all detected devices */ exi_bus_scan(); return (request_irq(EXI_IRQ,exi_bus_irq_handler,0,"EXI",NULL)); } EXPORT_SYMBOL(exi_register_driver); EXPORT_SYMBOL(exi_unregister_driver); EXPORT_SYMBOL(exi_register_irq); EXPORT_SYMBOL(exi_unregister_irq); EXPORT_SYMBOL(exi_add_command_group); EXPORT_SYMBOL(exi_bus_type); postcore_initcall(exi_init); --- NEW FILE: exi-hw.c --- /* * drivers/exi/exi-hw.c * * Nintendo GameCube EXI driver * Copyright (C) 2004-2005 The GameCube Linux Team * Copyright (C) 2004,2005 Todd Jeffreys <to...@vo...> * * 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. * */ #include <linux/types.h> #include <linux/exi.h> #include <linux/wait.h> #include <linux/delay.h> #include <asm/io.h> #include "exi_priv.h" static inline void exi_select(struct exi_command_group *cmd) { const u32 channel = (cmd->flags >> 16) & 3; const u32 device = (cmd->flags >> 20) & 7; const u32 frequency = (cmd->flags >> 24) & 7; void * __iomem const reg = EXI_CSR(channel); u32 val = readl(reg); val &= (EXI_CSR_EXTINTMASK | EXI_CSR_TCINTMASK | EXI_CSR_EXIINTMASK); val |= (device << 7) | (frequency << 4); writel(val,reg); } static inline void exi_deselect(struct exi_command_group *cmd) { u32 channel = (cmd->flags >> 16) & 3; void * __iomem const reg = EXI_CSR(channel); u32 val; if (cmd->flags & EXI_DESELECT_UDELAY) { udelay(cmd->deselect_udelay); } val = readl(reg) & (EXI_CSR_EXTINTMASK | EXI_CSR_TCINTMASK | EXI_CSR_EXIINTMASK); writel(val,reg); } static void exi_immediate_transfer(struct exi_command *cmd, unsigned int channel) { void * __iomem const imm_reg = EXI_IMM(channel); void * __iomem const cr_reg = EXI_CR(channel); void * __iomem const csr_reg = EXI_CSR(channel); u32 val; void *data = cmd->data; u32 len = cmd->len; /* fast path, 4 bytes at a time */ while (len >= 4) { /* write to register */ if (cmd->flags & EXI_CMD_WRITE) val = *((u32*)data); else val = 0xFFFFFFFF; writel(val,imm_reg); /* go! */ val = EXI_MR_TSTART | EXI_MR_TLEN(4) | (cmd->flags & 7); writel(val,cr_reg); /* wait for completion */ while (readl(cr_reg) & EXI_MR_TSTART) { } /* clear the TCINT now */ writel(readl(csr_reg) | EXI_CSR_TCINT,csr_reg); /* store result on a read */ if (!(cmd->flags & EXI_CMD_WRITE)) { *((u32*)data) = readl(imm_reg); } /* change pointer and length */ data += 4; len -= 4; } /* if we have 1,2,3 remaining bytes */ if (len) { /* write to register */ if (cmd->flags & EXI_CMD_WRITE) { switch (len) { case 1: val = *((u8*)data) << 24; break; case 2: val = *((u16*)data) << 16; break; default: /* this is really 3, we read an entire 4 bytes at a time since there is no penalty for reading the extra byte. EXI hardware will ignore the extra byte anyways. */ val = *((u32*)data); break; } } else { val = 0xFFFFFFFF; } writel(val,imm_reg); /* go */ val = EXI_MR_TSTART | EXI_MR_TLEN(len) | (cmd->flags & 7); writel(val,cr_reg); /* wait for completion */ while (readl(cr_reg) & EXI_MR_TSTART) { } /* clear the TCINT now */ writel(readl(csr_reg) | EXI_CSR_TCINT,csr_reg); /* store result on a read */ if (!(cmd->flags & EXI_CMD_WRITE)) { val = readl(imm_reg); switch (len) { case 1: *((u8*)data) = (u8)(val >> 24); break; case 2: *((u16*)data) = (u16)(val >> 16); break; default: /* this is really a 3 byte read */ *((u16*)data) = (u16)(val >> 16); *((u8*)(data+2)) = (u8)(val >> 8); break; } } } } static void exi_dma_transfer(struct exi_command *subcmd, unsigned int channel) { void * __iomem reg; u32 val; /* flush the cache when writing */ if (subcmd->flags & EXI_CMD_WRITE) { flush_dcache_range((u32)subcmd->data, (u32)subcmd->data + subcmd->len); } /* convert to physical */ val = virt_to_phys(subcmd->data); writel(val,EXI_MAR(channel)); /* write length */ writel(subcmd->len,EXI_LENGTH(channel)); /* clear the IMM area */ writel(0xFFFFFFFF,EXI_IMM(channel)); /* enable the TC interrupt */ reg = EXI_CSR(channel); val = readl(reg) | EXI_CSR_TCINTMASK | EXI_CSR_TCINT; writel(val,reg); /* go! */ val = EXI_MR_TSTART | EXI_MR_DMA | (subcmd->flags & 7); writel(val,EXI_CR(channel)); } static void exi_complete_command(struct exi_locked_data *data, struct exi_command *subcmd) { struct exi_command_group *cmd; unsigned long flags; cmd = (struct exi_command_group*)data->queue.next; /* restore idle flag */ data->exi_state = EXI_IDLE; /* increment the count now */ data->cur_command++; if (data->cur_command >= cmd->num_commands) { /* deselect */ exi_deselect(cmd); /* remove from queue */ spin_lock_irqsave(&data->queue_lock,flags); list_del(&cmd->list); spin_unlock_irqrestore(&data->queue_lock,flags); /* reset pointer */ data->cur_command = 0; } /* call the callback */ if (subcmd->completion_routine) { subcmd->completion_routine(subcmd); } } static void exi_execute_queue(struct exi_locked_data *data) { u32 channel; struct exi_command_group *cmd; struct exi_command *subcmd; /* execute the first command, but do not remove until done */ cmd = (struct exi_command_group*)data->queue.next; channel = (cmd->flags >> 16) & 3; /* is this the first item? We must select it */ if (data->cur_command == 0) { exi_select(cmd); } subcmd = cmd->commands + data->cur_command; /* execute transfer, determine if we can use DMA */ if (((subcmd->len & (EXI_DMA_ALIGNMENT-1)) == 0) && (((u32)subcmd->data & (EXI_DMA_ALIGNMENT-1)) == 0)) { /* set state */ atomic_set(&data->tc_interrupt,0); data->exi_state = EXI_WAITING_FOR_TC; /* do it */ exi_dma_transfer(subcmd,channel); } else { exi_immediate_transfer(subcmd,channel); exi_complete_command(data,subcmd); } } u32 exi_synchronous_id(unsigned int channel,unsigned int device) { struct exi_command_group cmd; struct exi_command sub; u16 write; u32 read; cmd.flags = (channel << 16) | (EXI_DEVICE_0 << device) | EXI_FREQUENCY_3; write = 0; exi_select(&cmd); sub.flags = EXI_CMD_WRITE; sub.data = &write; sub.len = sizeof(write); exi_immediate_transfer(&sub,channel); sub.flags = EXI_CMD_READ; sub.data = &read; sub.len = sizeof(read); exi_immediate_transfer(&sub,channel); exi_deselect(&cmd); return read; } void exi_tasklet(unsigned long param) { unsigned long flags; int empty; struct exi_locked_data *data = (struct exi_locked_data*)param; struct exi_command_group *cmd; struct exi_command *subcmd; while (1) { /* check if the queue has stuff in it */ spin_lock_irqsave(&data->queue_lock,flags); empty = list_empty(&data->queue); spin_unlock_irqrestore(&data->queue_lock,flags); if (empty) { goto exit_tasklet; } /* stuff in queue, process it */ switch (data->exi_state) { case EXI_IDLE: exi_execute_queue(data); break; case EXI_WAITING_FOR_TC: /* no interrupt yet? */ if (!atomic_read(&data->tc_interrupt)) { goto exit_tasklet; } /* finish the operation */ cmd = (struct exi_command_group*)data->queue.next; subcmd = cmd->commands + data->cur_command; /* invalidate the cache on a read */ if (!(subcmd->flags & EXI_CMD_WRITE)) { invalidate_dcache_range((u32)subcmd->data, (u32)subcmd->data + subcmd->len); } /* complete the operation */ atomic_set(&data->tc_interrupt,0); exi_complete_command(data,subcmd); break; } } exit_tasklet: return; } irqreturn_t exi_bus_irq_handler(int irq,void *dev_id,struct pt_regs *regs) { void * __iomem reg; u32 csr; u32 val; int channel; for (channel = 0; channel < EXI_MAX_CHANNELS; channel++) { /* find interrupt cause */ reg = EXI_CSR(channel); csr = readl(reg); val = csr & (EXI_CSR_EXTINT | EXI_CSR_EXIINT | EXI_CSR_TCINT); if (!val) continue; /* ack */ writel(csr,reg); if (csr & EXI_CSR_EXTINT) { /* insert happened */ exi_bus_insert(channel,csr & EXI_CSR_EXT); } if ((csr & (EXI_CSR_TCINT | EXI_CSR_TCINTMASK)) == (EXI_CSR_TCINT | EXI_CSR_TCINTMASK)) { /* there's a weird thing happening, we tend to get these interrupts when the mask is off, so skip them if the mask if off */ /* get the device data based on the channel */ atomic_set(&exi_data[channel].tc_interrupt,1); tasklet_schedule(&exi_data[channel].tasklet); /* disable the TC interrupt */ csr &= ~EXI_CSR_TCINTMASK; csr |= EXI_CSR_TCINT; writel(csr,reg); } if (csr & EXI_CSR_EXIINT) { /* fire the callback associated with the irq */ if (irq_handlers[channel].func) { irq_handlers[channel].func( channel,irq_handlers[channel].param); } } } return IRQ_HANDLED; } void exi_add_command_group(struct exi_command_group *cmd,unsigned int count) { unsigned long flags; unsigned int i; unsigned int freq; struct exi_driver *drv; struct exi_locked_data *data = (struct exi_locked_data*)cmd->dev->dev.platform_data; spin_lock_irqsave(&data->queue_lock,flags); /* add to the queue */ for (i=0;i<count;++i) { /* modify the flags based on the device pull out the frequency from the driver */ drv = to_exi_driver(cmd->dev->dev.driver); freq = drv ? (drv->frequency << 24) : EXI_FREQUENCY_3; cmd->flags &= 0xFFFF; cmd->flags |= (cmd->dev->eid.channel << 16) | (EXI_DEVICE_0 << cmd->dev->eid.device) | freq; /* add to the list */ list_add_tail(&cmd[i].list,&data->queue); } spin_unlock_irqrestore(&data->queue_lock,flags); /* now start the tasklet */ tasklet_schedule(&data->tasklet); } --- NEW FILE: exi_priv.h --- /* * drivers/exi/exi_priv.h * * Nintendo GameCube EXI driver * Copyright (C) 2004-2005 The GameCube Linux Team * Copyright (C) 2004,2005 Todd Jeffreys <to...@vo...> * * 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. * */ #ifndef __exi_priv__ #define __exi_priv__ #include <linux/interrupt.h> #include <linux/list.h> #include <asm/atomic.h> /* Flags for exi_command->flags */ #define EXI_CHANNEL_0 (0x00000000) #define EXI_CHANNEL_1 (0x00010000) #define EXI_CHANNEL_2 (0x00020000) #define EXI_DEVICE_0 (0x00100000) #define EXI_DEVICE_1 (0x00200000) #define EXI_DEVICE_2 (0x00400000) #define EXI_FREQUENCY_0 (0x00000000) #define EXI_FREQUENCY_1 (0x01000000) #define EXI_FREQUENCY_2 (0x02000000) #define EXI_FREQUENCY_3 (0x03000000) #define EXI_FREQUENCY_4 (0x04000000) #define EXI_FREQUENCY_5 (0x05000000) #define _EXI_DEBUG 1 #define EXI_IRQ 4 #define EXI_MAX_CHANNELS 3 #define EXI_DEVICES_PER_CHANNEL 3 #define EXI_INVALID_ID 0xFFFFFFFF #define EXI_READ 0 #define EXI_WRITE 1 #define EXI_CSR_BASE (void* __iomem)0xCC006800 #define EXI_MAR_BASE (void* __iomem)0xCC006804 #define EXI_LENGTH_BASE (void* __iomem)0xCC006808 #define EXI_CR_BASE (void* __iomem)0xCC00680C #define EXI_IMM_DATA_BASE (void* __iomem)0xCC006810 #define EXI_CHANNEL_SPACING 0x14 #define EXI_CSR_EXT (1<<12) #define EXI_CSR_EXTINT (1<<11) #define EXI_CSR_EXTINTMASK (1<<10) #define EXI_CSR_CSMASK (0x7<<7) #define EXI_CSR_CS_0 (0x1<<7) /* Chip Select 001 */ #define EXI_CSR_CS_1 (0x2<<7) /* Chip Select 010 */ #define EXI_CSR_CS_2 (0x4<<7) /* Chip Select 100 */ #define EXI_CSR_CLKMASK (0x7<<4) #define EXI_CSR_CLK_1MHZ (0x0<<4) #define EXI_CSR_CLK_2MHZ (0x1<<4) #define EXI_CSR_CLK_4MHZ (0x2<<4) #define EXI_CSR_CLK_8MHZ (0x3<<4) #define EXI_CSR_CLK_16MHZ (0x4<<4) #define EXI_CSR_CLK_32MHZ (0x5<<4) #define EXI_CSR_TCINT (1<<3) #define EXI_CSR_TCINTMASK (1<<2) #define EXI_CSR_EXIINT (1<<1) #define EXI_CSR_EXIINTMASK (1<<0) #define EXI_MR_TSTART (1<<0) #define EXI_MR_DMA (1<<1) #define EXI_MR_READ (0<<2) #define EXI_MR_WRITE (1<<2) #define EXI_MR_READ_WRITE (2<<2) #define EXI_MR_TLEN(i) ((i-1)<<4) #define EXI_CSR(c) (EXI_CSR_BASE + (c*EXI_CHANNEL_SPACING)) #define EXI_MAR(c) (EXI_MAR_BASE + (c*EXI_CHANNEL_SPACING)) #define EXI_LENGTH(c) (EXI_LENGTH_BASE + (c*EXI_CHANNEL_SPACING)) #define EXI_CR(c) (EXI_CR_BASE + (c*EXI_CHANNEL_SPACING)) #define EXI_IMM(c) (EXI_IMM_DATA_BASE + (c*EXI_CHANNEL_SPACING)) #define EXI0_CSR EXI_CSR(0) #define EXI1_CSR EXI_CSR(1) #define EXI2_CSR EXI_CSR(2) struct exi_locked_data { /* per bus information */ spinlock_t queue_lock; struct list_head queue; unsigned int cur_command; struct tasklet_struct tasklet; enum { EXI_IDLE, EXI_WAITING_FOR_TC } exi_state; atomic_t tc_interrupt; }; struct exi_interrupt_handlers { exi_irq_handler func; void *param; }; extern struct exi_interrupt_handlers irq_handlers[EXI_MAX_CHANNELS]; extern struct exi_locked_data exi_data[EXI_MAX_CHANNELS]; void exi_tasklet(unsigned long param); irqreturn_t exi_bus_irq_handler(int irq,void *dev_id,struct pt_regs *regs); void exi_bus_insert(unsigned int channel,unsigned int bInsert); u32 exi_synchronous_id(unsigned int channel,unsigned int device); #endif Index: Makefile =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/exi/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- Makefile 19 Oct 2004 22:49:40 -0000 1.2 +++ Makefile 8 Jan 2005 22:46:47 -0000 1.3 @@ -2,4 +2,4 @@ # Makefile for the EXI bus core. # -obj-$(CONFIG_EXI) += exi-driver.o gcn-exi-lite.o +obj-$(CONFIG_EXI) += exi-bus.o exi-hw.o |
From: <pal...@us...> - 2005-01-08 22:46:58
|
Update of /cvsroot/gc-linux/linux/sound/ppc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32197/sound/ppc Modified Files: gcn-ai.c Log Message: Initial EXI framework check-in, including BBA changes Index: gcn-ai.c =================================================================== RCS file: /cvsroot/gc-linux/linux/sound/ppc/gcn-ai.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- gcn-ai.c 6 Jan 2005 20:23:21 -0000 1.2 +++ gcn-ai.c 8 Jan 2005 22:46:48 -0000 1.3 @@ -20,7 +20,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/kernel.h> - +#include <asm/io.h> #include <sound/core.h> #include <sound/pcm.h> #define SNDRV_GET_ID @@ -48,7 +48,7 @@ #define DSP_IRQ 6 -#define AUDIO_DSP_CONTROL *(volatile u_int16_t *)(0xCC00500a) +#define AI_DSP_CSR (void __iomem*)0xCC00500A #define AI_CSR_RES (1<<0) #define AI_CSR_PIINT (1<<1) #define AI_CSR_HALT (1<<2) @@ -68,7 +68,7 @@ #define AUDIO_DMA_LENGTH *(volatile u_int16_t *)(0xCC005036) #define AI_DCL_PLAY (1<<15) -#define AUDIO_DMA_LEFT *(volatile u_int16_t *)(0xCC00503a) +#define AUDIO_DMA_LEFT *(volatile u_int16_t *)(0xCC00503A) #define AUDIO_STREAM_STATUS *(volatile u_int32_t *)(0xCC006C00) #define AI_AICR_RATE (1<<6) @@ -252,9 +252,9 @@ static irqreturn_t snd_gcn_interrupt(int irq, void *dev, struct pt_regs *regs) { snd_gcn_t *chip = (snd_gcn_t *) dev; - unsigned short val = AUDIO_DSP_CONTROL; + unsigned long flags; - if (val & AI_CSR_AIDINT) { + if (readw(AI_DSP_CSR) & AI_CSR_AIDINT) { u_int32_t addr; DPRINTK("DSP interrupt! period #%i\n", chip->cur_period); @@ -284,7 +284,10 @@ snd_pcm_period_elapsed(chip->playback_substream); } /* ack AI DMA interrupt */ - AUDIO_DSP_CONTROL |= AI_CSR_AIDINT; + local_irq_save(flags); + writew(readw(AI_DSP_CSR) | AI_CSR_AIDINT,AI_DSP_CSR); + local_irq_restore(flags); + return IRQ_HANDLED; } @@ -334,7 +337,7 @@ { int err; snd_card_t *card; - + unsigned long flags; /* if (!is_gamecube()) return -ENODEV; */ @@ -363,12 +366,11 @@ return -EBUSY; } else { - /* enable AI DMA interrupt */ - AUDIO_DSP_CONTROL |= AI_CSR_AIDINTMASK; - - /* enable any DSP interrupts */ - AUDIO_DSP_CONTROL |= AI_CSR_PIINT; - + /* enable AI DMA and DSP interrupt */ + local_irq_save(flags); + writew(readw(AI_DSP_CSR) | AI_CSR_AIDINTMASK | AI_CSR_PIINT, + AI_DSP_CSR); + local_irq_restore(flags); } #if 0 @@ -409,10 +411,15 @@ static void __exit alsa_card_gcn_exit(void) { + unsigned long flags; DPRINTK("Goodbye, cruel world\n"); StopSample(); - AUDIO_DSP_CONTROL &= ~AI_CSR_AIDINTMASK; + /* disable interrupts */ + local_irq_save(flags); + writew(readw(AI_DSP_CSR) & ~AI_CSR_AIDINTMASK,AI_DSP_CSR); + local_irq_restore(flags); + free_irq(DSP_IRQ, gcn_audio); snd_card_free(gcn_audio->card); } |
From: <pal...@us...> - 2005-01-08 22:46:56
|
Update of /cvsroot/gc-linux/linux/arch/ppc/platforms In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32197/arch/ppc/platforms Modified Files: gamecube.c gcn-dvdcover.c gcn-rtc.c Log Message: Initial EXI framework check-in, including BBA changes Index: gamecube.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/platforms/gamecube.c,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -r1.30 -r1.31 --- gamecube.c 8 Jan 2005 14:09:53 -0000 1.30 +++ gamecube.c 8 Jan 2005 22:46:47 -0000 1.31 @@ -40,7 +40,7 @@ return GCN_MEM_SIZE; } -static void __init gamecube_map_io(void) +static void gamecube_map_io(void) { /* all RAM and more ??? */ io_block_mapping(0xd0000000, 0, 0x02000000, _PAGE_IO); @@ -66,7 +66,7 @@ gamecube_restart(NULL); } -static void __init gamecube_calibrate_decr(void) +static void gamecube_calibrate_decr(void) { int freq, divisor; freq = 162000000; @@ -120,7 +120,7 @@ .end = flipper_end_irq, }; -static void __init gamecube_init_IRQ(void) +static void gamecube_init_IRQ(void) { int i; @@ -146,7 +146,7 @@ return 0; } -static void __init gamecube_setup_arch(void) +static void gamecube_setup_arch(void) { #ifdef CONFIG_GAMECUBE_CONSOLE #if (GCN_XFB_START <= 0x00fffe00) @@ -201,14 +201,14 @@ ppc_md.find_end_of_memory = gamecube_find_end_of_memory; ppc_md.setup_io_mappings = gamecube_map_io; - ppc_md.time_init = gcn_time_init; - ppc_md.set_rtc_time = gcn_set_rtc_time; - ppc_md.get_rtc_time = gcn_get_rtc_time; - #ifdef CONFIG_KEXEC ppc_md.machine_shutdown = gamecube_shutdown; ppc_md.machine_kexec_prepare = gamecube_kexec_prepare; ppc_md.machine_kexec = machine_kexec_simple; #endif /* CONFIG_KEXEC */ + /* no RTC driver, too slow */ + ppc_md.time_init = NULL; + ppc_md.set_rtc_time = NULL; + ppc_md.get_rtc_time = NULL; } Index: gcn-dvdcover.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/platforms/gcn-dvdcover.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- gcn-dvdcover.c 6 Jan 2005 20:04:20 -0000 1.2 +++ gcn-dvdcover.c 8 Jan 2005 22:46:47 -0000 1.3 @@ -16,7 +16,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> -#include <linux/interrupt.h> #include <asm/io.h> @@ -62,44 +61,9 @@ #define di_printk(level, format, arg...) \ printk(level PFX format , ## arg) -typedef enum { - OPENED = 0, - CLOSED, - UNKNOWN, -} gcn_dvdcover_state_t; - -gcn_dvdcover_state_t gcn_dvdcover_state = UNKNOWN; - -/** - * - */ -static irqreturn_t gcn_dvdcover_handler(int this_irq, void *dev_id, - struct pt_regs *regs) -{ - unsigned long reason = readl(DI_DICVR); - - gcn_dvdcover_state = (readl(DI_DICVR) & DI_DICVR_CVR)? - OPENED:CLOSED; - - di_printk(KERN_INFO, "DVD cover was %s.\n", - (gcn_dvdcover_state == OPENED) ? - "opened" : "closed"); - - /* handle only DVD cover interrupts here */ - if (reason & DI_DICVR_CVRINT) { - writel(reason | DI_DICVR_CVRINT, DI_DICVR); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/** - * - */ static int gcn_dvdcover_init(void) { unsigned long outval; - int err; /* clear pending DI interrupts and mask new ones */ /* this prevents an annoying bug while we lack a complete DVD driver */ @@ -111,16 +75,6 @@ writel(DI_CMD_STOP << 24, DI_DICMDBUF0); writel(DI_DICR_TSTART, DI_DICR); - err = request_irq(DVD_IRQ, gcn_dvdcover_handler, 0, - "Nintendo GameCube DVD", 0); - if (err) { - di_printk(KERN_ERR, "request of irq%d failed\n", DVD_IRQ); - return err; - } - - /* enable DVD cover interrupts */ - writel(readl(DI_DICVR) | DI_DICVR_CVRINTMASK, DI_DICVR); - return 0; } @@ -129,7 +83,7 @@ */ static void gcn_dvdcover_exit(void) { - free_irq(DVD_IRQ, 0); + } module_init(gcn_dvdcover_init); Index: gcn-rtc.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/platforms/gcn-rtc.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- gcn-rtc.c 19 Oct 2004 22:58:36 -0000 1.1 +++ gcn-rtc.c 8 Jan 2005 22:46:47 -0000 1.2 @@ -17,10 +17,6 @@ #include <linux/time.h> #include <linux/exi.h> -#ifndef EXI_LITE -#error Sorry, this driver needs currently the gcn-exi-lite framework. -#endif - /* * The EXI functions that we use are guaranteed to work by the gcn-exi-lite * framework even if exi_lite_init() has not been called. @@ -28,12 +24,28 @@ #define RTC_OFFSET 946684800L +static int rtc_probe(struct exi_device *); +static void rtc_remove(struct exi_device *); + static int bias = 0; +static int initialized = 0; +static struct exi_driver rtc_exi_driver = { + .name = "RTC/SRAM", + .eid = { + .channel = 0, + .device = 1, + .id = 0xFFFF1698 + }, + .frequency = 3, + .probe = rtc_probe, + .remove = rtc_remove +}; +#if 0 static void read_sram(unsigned char *abuf) { unsigned long a; - + /* select the SRAM device */ exi_select(0, 1, 3); @@ -87,34 +99,63 @@ /* Deselect the RTC device */ exi_deselect(0); } - +#endif /** * */ -long __init gcn_time_init(void) +unsigned long gcn_get_rtc_time(void) { - char sram[64]; - int *pbias = (int *)&sram[0xC]; - read_sram(sram); - bias = *pbias; + static int i=0; + if (i++ == 0) { + printk(KERN_INFO "Get RTC time\n"); + } + if (initialized) { + //return get_rtc() + bias + RTC_OFFSET; + } return 0; } /** * */ -unsigned long gcn_get_rtc_time(void) +int gcn_set_rtc_time(unsigned long nowtime) { - return get_rtc() + bias + RTC_OFFSET; + printk(KERN_INFO "Set RTC time %lu\n",nowtime); + if (initialized) { + //set_rtc(nowtime - RTC_OFFSET - bias); + return 0; + } + + return 0; +} + +static int rtc_probe(struct exi_device *dev) +{ + /* nothing to probe, hardware is always there */ + initialized = 1; + + return 0; +} + +static void rtc_remove(struct exi_device *dev) +{ + initialized = 0; } /** * */ -int gcn_set_rtc_time(unsigned long nowtime) +long gcn_time_init(void) { - set_rtc(nowtime - RTC_OFFSET - bias); - - return 1; + printk(KERN_INFO "gcn_time_init\n"); + initialized = 0; + return 0; + //return exi_register_driver(&rtc_exi_driver); } + /* +char sram[64]; + int *pbias = (int *)&sram[0xC]; + read_sram(sram); + bias = *pbias; + return 0; */ |
From: <pal...@us...> - 2005-01-08 22:46:56
|
Update of /cvsroot/gc-linux/linux/drivers/net In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32197/drivers/net Modified Files: gcn-bba.c Log Message: Initial EXI framework check-in, including BBA changes Index: gcn-bba.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/net/gcn-bba.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- gcn-bba.c 6 Jan 2005 20:27:54 -0000 1.3 +++ gcn-bba.c 8 Jan 2005 22:46:48 -0000 1.4 @@ -1,9 +1,9 @@ -/** +/* * drivers/net/gcn-bba.c * * Nintendo GameCube Broadband Adapter driver * Copyright (C) 2004-2005 The GameCube Linux Team - * Copyright (C) 2004,2005 Albert Herranz + * Copyright (C) 2004,2005 Albert Herranz,Todd Jeffreys * * Based on previous work by Stefan Esser, Franz Lehner, Costis and tmbinc. * [...1306 lines suppressed...] - - ret = bba_probe(); - - return ret; + return exi_register_driver(&bba_exi_driver); } /** @@ -1076,9 +1349,9 @@ */ static void __exit bba_exit_module(void) { - unregister_netdev(bba_dev); - exi_lite_exit(); + exi_unregister_driver(&bba_exi_driver); } module_init(bba_init_module); module_exit(bba_exit_module); + |
From: <he...@us...> - 2005-01-08 14:10:03
|
Update of /cvsroot/gc-linux/linux/arch/ppc/platforms In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18733 Modified Files: gamecube.c Log Message: Make new kexec hooks static, as pointed by apgo. Index: gamecube.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/platforms/gamecube.c,v retrieving revision 1.29 retrieving revision 1.30 diff -u -d -r1.29 -r1.30 --- gamecube.c 7 Jan 2005 23:34:32 -0000 1.29 +++ gamecube.c 8 Jan 2005 14:09:53 -0000 1.30 @@ -159,12 +159,12 @@ } #ifdef CONFIG_KEXEC -void gamecube_shutdown(void) +static void gamecube_shutdown(void) { /* currently not used */ } -int gamecube_kexec_prepare(struct kimage *image) +static int gamecube_kexec_prepare(struct kimage *image) { int retval = 0; |
From: Albert H. <alb...@ya...> - 2005-01-08 11:38:34
|
--- Arthur Othieno <a.o...@bl...> escribió: > Since these are not referenced outside this file > (yet?), they should > be defined static, no? Think namespace pollution ... Yes, you're right. I'll fix that. Thanks, Albert ______________________________________________ Renovamos el Correo Yahoo!: ¡250 MB GRATIS! Nuevos servicios, más seguridad http://correo.yahoo.es |
From: <a.o...@bl...> - 2005-01-08 10:22:29
|
On Fri, Jan 07, 2005 at 03:34:35PM -0800, he...@us... wrote: > Update of /cvsroot/gc-linux/linux/arch/ppc/platforms > In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14169 > > Modified Files: > gamecube.c > Log Message: > Add kexec ppc hooks. > We still have no kexec on mainline, but will soon. > > > Index: gamecube.c > =================================================================== > RCS file: /cvsroot/gc-linux/linux/arch/ppc/platforms/gamecube.c,v > retrieving revision 1.28 > retrieving revision 1.29 > diff -u -d -r1.28 -r1.29 > --- gamecube.c 6 Jan 2005 19:57:53 -0000 1.28 > +++ gamecube.c 7 Jan 2005 23:34:32 -0000 1.29 > @@ -158,6 +158,20 @@ > #endif > } > > +#ifdef CONFIG_KEXEC > +void gamecube_shutdown(void) > +{ > + /* currently not used */ > +} > + > +int gamecube_kexec_prepare(struct kimage *image) > +{ > + int retval = 0; > + > + return retval; > +} > +#endif /* CONFIG_KEXEC */ > + Since these are not referenced outside this file (yet?), they should be defined static, no? Think namespace pollution ... Arthur |
From: <he...@us...> - 2005-01-08 00:55:43
|
Update of /cvsroot/gc-linux/htdocs/xml/en In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2000 Modified Files: news.xml Log Message: 8 Jan 2005, Latest kernel build updated to 2.6.10 Index: news.xml =================================================================== RCS file: /cvsroot/gc-linux/htdocs/xml/en/news.xml,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -r1.30 -r1.31 --- news.xml 4 Jan 2005 21:37:12 -0000 1.30 +++ news.xml 8 Jan 2005 00:55:32 -0000 1.31 @@ -2,6 +2,11 @@ <?xml-stylesheet href="news.xsl" type="text/xsl"?> <news> <item> + <date>8 January 2005</date> + <title>Latest kernel build updated to 2.6.10</title> + <text>This latest release includes Rob's preliminary read-only support for SD cards. Available at the <a href="docs/download.html">Latest Kernel Build</a> section of the download page.</text> + </item> + <item> <date>3 January 2005</date> <title>SDLOAD</title> <text>by <a href="http://www.gcdev.com/">Costis</a> allows the user to boot code on an unmodified GC within seconds, only with an Action Replay and an SD card. We also have a read-only SD card kernel driver by Rob.</text> |
From: <he...@us...> - 2005-01-07 23:40:24
|
Update of /cvsroot/gc-linux/linux/drivers/misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15050 Modified Files: Kconfig Makefile Added Files: gcn-mi.c gcn-mi.h Log Message: Add Nintendo GameCube Memory Interface driver. Useful to detect weird hardware behaviour and to hard protect some special memory areas, like the kexec preservation area. Change GCN_GQR to GAMECUBE_GQR, like in the rest of Kconfig options. --- NEW FILE: gcn-mi.c --- /* * arch/ppc/platforms/gcn-mi.c * * Nintendo GameCube Memory Interface driver * Copyright (C) 2004-2005 The GameCube Linux Team * Copyright (C) 2004,2005 Albert Herranz * * 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. * */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/spinlock.h> #include <linux/proc_fs.h> #include <asm/io.h> #include "gcn-mi.h" #include "../../arch/ppc/platforms/gamecube.h" #define MI_IRQ 7 #define MI_BASE 0xcc004000 #define MI_SIZE 0x80 #define MI_PROT_REGION0 ((u32 __iomem *)(MI_BASE+0x00)) #define MI_PROT_REGION1 ((u32 __iomem *)(MI_BASE+0x04)) #define MI_PROT_REGION2 ((u32 __iomem *)(MI_BASE+0x08)) #define MI_PROT_REGION3 ((u32 __iomem *)(MI_BASE+0x0c)) #define MI_PROT_TYPE ((u16 __iomem *)(MI_BASE+0x10)) #define MI_IMR ((u16 __iomem *)(MI_BASE+0x1c)) #define MI_ICR ((u16 __iomem *)(MI_BASE+0x1e)) #define MI_0x4020 ((u16 __iomem *)(MI_BASE+0x20)) #define MI_ADDRLO ((u16 __iomem *)(MI_BASE+0x22)) #define MI_ADDRHI ((u16 __iomem *)(MI_BASE+0x24)) #define MI_PAGE_SHIFT 10 #define MI_PAGE_MASK (~((1 << MI_PAGE_SHIFT) - 1)) #define MI_PAGE_SIZE (1UL << MI_PAGE_SHIFT) struct mi_private { struct device *device; int irq; int nr_regions; int regions_bitmap; unsigned long faults[MI_MAX_REGIONS+1]; unsigned long last_address; unsigned long last_address_faults; spinlock_t lock; #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_file; #endif }; static struct mi_private *mi_private; #define DRV_MODULE_NAME "gcn-mi" #define DRV_DESCRIPTION "Nintendo GameCube Memory Interface driver" #define DRV_AUTHOR "Albert Herranz" #define PFX DRV_MODULE_NAME ": " #define mi_printk(level, format, arg...) \ printk(level PFX format , ## arg) /** * */ static int mi_setup_default_regions(void) { int retval = 0; #ifndef MODULE #ifdef CONFIG_KEXEC retval = gcn_mi_region_protect(GCN_PRESERVE_TO, GCN_PRESERVE_TO + PAGE_ALIGN(GCN_PRESERVE_SIZE), MI_PROT_RO); if (retval < 0) { mi_printk(KERN_ERR, "unable to protect" " kexec reserved memory\n"); } #endif /* CONFIG_KEXEC */ #endif /* MODULE */ return retval; } /** * */ static irqreturn_t mi_handler(int this_irq, void *data, struct pt_regs *regs) { struct mi_private *priv = (struct mi_private *)data; unsigned long flags; int region, cause, ack; unsigned long address; spin_lock_irqsave(priv->lock, flags); address = readw(MI_ADDRLO) | (readw(MI_ADDRHI)<<16); ack = 0; cause = readw(MI_ICR); /* a fault was detected in some of the registered regions */ if ( (cause & 0xf) != 0) { for (region = 0; region < MI_MAX_REGIONS; region++) { if ( (cause & (1 << region)) != 0 ) { priv->faults[region]++; mi_printk(KERN_INFO, "bad access on region #%d" " at 0x%lx\n", region, address); } } } /* a fault was detected out of any registered region */ if ( (cause & (1 << 4)) != 0 ) { priv->faults[MI_MAX_REGIONS]++; if (address == priv->last_address) { priv->last_address_faults++; } else { #if 0 if (priv->last_address_faults > 0) { mi_printk(KERN_INFO, "bad access" " at 0x%lx (%lu times)\n", priv->last_address, priv->last_address_faults); } #endif priv->last_address = address; priv->last_address_faults = 1; } } ack |= cause; writew(ack, MI_ICR); /* ack int */ writew(0, MI_0x4020); /* kind of ack */ spin_unlock_irqrestore(priv->lock, flags); return IRQ_HANDLED; } #ifdef CONFIG_PROC_FS /** * */ static int mi_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) { struct mi_private *priv = (struct mi_private *)data; int len; int region; len = sprintf(page, "# <region> <faults>\n"); for (region = 0; region < MI_MAX_REGIONS; region++) { if ( (priv->regions_bitmap & (1<<region)) != 0 ) { len += sprintf(page+len, "%d\t%lu\n", region, priv->faults[region]); } } len += sprintf(page+len, "%s\t%lu\n", "none", priv->faults[MI_MAX_REGIONS]); return len; } #endif /* CONFIG_PROC_FS */ /** * */ static int mi_setup_irq(struct mi_private *priv) { int retval; retval = request_irq(priv->irq, mi_handler, 0, DRV_MODULE_NAME, priv); if (retval) { mi_printk(KERN_ERR, "request of irq%d failed\n", priv->irq); } else { writew((1<<4), MI_IMR); /* do not mask all MI interrupts */ } return retval; } /** * */ static int mi_probe(struct device *device, struct resource *mem, int irq) { struct mi_private *priv; int retval; priv = kmalloc(sizeof(struct mi_private), GFP_KERNEL); if (!priv) { retval = -ENOMEM; goto err; } memset(priv, 0, sizeof(*priv)); /* int region; priv->nr_regions = 0; priv->regions_bitmap = 0; for( region = 0; region < MI_MAX_REGIONS; region++ ) { priv->faults[region] = 0; } priv->last_address_faults = 0; */ priv->device = device; dev_set_drvdata(priv->device, priv); priv->irq = irq; retval = mi_setup_irq(priv); if (retval) goto err_setup_irq; #ifdef CONFIG_PROC_FS struct platform_device *pdev = to_platform_device(device); priv->proc_file = create_proc_read_entry(pdev->dev.bus_id, 0444, NULL, mi_proc_read, priv); priv->proc_file->owner = THIS_MODULE; #endif /* CONFIG_PROC_FS */ mi_private = priv; mi_setup_default_regions(); return 0; err_setup_irq: dev_set_drvdata(priv->device, NULL); kfree(priv); err: return retval; } /** * */ static void mi_shutdown(struct mi_private *priv) { gcn_mi_region_unprotect_all(); } /** * */ static void mi_remove(struct mi_private *priv) { #ifdef CONFIG_PROC_FS struct platform_device *pdev = to_platform_device(priv->device); remove_proc_entry(pdev->dev.bus_id, NULL); #endif /* CONFIG_PROC_FS */ mi_shutdown(priv); /* free interrupt handler */ free_irq(priv->irq, priv); kfree(priv); mi_private = NULL; } /** * */ static int __init mi_drv_probe(struct device *device) { struct platform_device *pdev = to_platform_device(device); struct resource *mem; int irq; irq = platform_get_irq(pdev, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) return -ENODEV; mi_printk(KERN_INFO, "%s\n", DRV_DESCRIPTION); return mi_probe(device, mem, irq); } /** * */ static int mi_drv_remove(struct device *device) { struct mi_private *priv = dev_get_drvdata(device); if (priv) { mi_remove(priv); dev_set_drvdata(device, NULL); } return 0; } /** * */ static void mi_drv_shutdown(struct device *device) { struct mi_private *priv = dev_get_drvdata(device); if (priv) mi_shutdown(priv); } static struct device_driver mi_device_driver = { .name = "mi", .bus = &platform_bus_type, .probe = mi_drv_probe, .remove = mi_drv_remove, .shutdown = mi_drv_shutdown, }; static struct resource mi_resources[] = { [0] = { .start = MI_BASE, .end = MI_BASE + MI_SIZE -1, .flags = IORESOURCE_MEM, }, [1] = { .start = MI_IRQ, .end = MI_IRQ, .flags = IORESOURCE_IRQ, }, }; static struct platform_device mi_device = { .name = "mi", .id = 0, .num_resources = ARRAY_SIZE(mi_resources), .resource = mi_resources, }; /** * */ static int __init mi_init(void) { int retval = 0; retval = driver_register(&mi_device_driver); if (!retval) { retval = platform_device_register(&mi_device); } return retval; } /** * */ static void __exit mi_exit(void) { platform_device_unregister(&mi_device); driver_unregister(&mi_device_driver); } module_init(mi_init); module_exit(mi_exit); /* Exported symbols */ /** * */ int gcn_mi_region_protect(unsigned long physlo, unsigned long physhi, int type) { struct mi_private *priv = mi_private; int region, free_regions; u16 pagelo, pagehi; if (!priv) return -ENODEV; if (type < MI_PROT_NONE || type > MI_PROT_RW) return -EINVAL; if ( (physlo & ~MI_PAGE_MASK) != 0 || (physhi & ~MI_PAGE_MASK) != 0 ) { return -EINVAL; } free_regions = MI_MAX_REGIONS - priv->nr_regions; if (free_regions <= 0) { return -ENOMEM; } for (region = 0; region < MI_MAX_REGIONS; region++) { if ( (priv->regions_bitmap & (1<<region)) == 0 ) break; } if (region >= MI_MAX_REGIONS) return -ENOMEM; priv->regions_bitmap |= (1 << region); priv->nr_regions++; writew((readw(MI_PROT_TYPE) & ~(3 << 2*region))|(type << 2*region), MI_PROT_TYPE); pagelo = physlo >> MI_PAGE_SHIFT; pagehi = (physhi >> MI_PAGE_SHIFT) - 1; writel((pagelo << 16) | pagehi, MI_PROT_REGION0 + 4*region); writew(readw(MI_IMR) | (1 << region), MI_IMR); mi_printk(KERN_INFO, "protected region #%d" " from 0x%0lx to 0x%0lx with 0x%0x\n", region, (unsigned long)(pagelo << MI_PAGE_SHIFT), (unsigned long)(((pagehi+1) << MI_PAGE_SHIFT) - 1), type); return region; } /** * */ int gcn_mi_region_unprotect(int region) { struct mi_private *priv = mi_private; if (!priv) return -ENODEV; if (region < 0 || region > MI_MAX_REGIONS) return -EINVAL; writew(readw(MI_IMR) & ~(1 << region), MI_IMR); writel(0, MI_PROT_REGION0 + 4*region); writew(readw(MI_PROT_TYPE) | (MI_PROT_RW << 2*region), MI_PROT_TYPE); if ( (priv->regions_bitmap & (1<<region)) != 0 ) mi_printk(KERN_INFO, "region #%d unprotected\n", region); priv->regions_bitmap &= ~(1 << region); priv->nr_regions--; return 0; } /** * */ void gcn_mi_region_unprotect_all(void) { int region; writew(0, MI_IMR); for (region = 0; region < MI_MAX_REGIONS; region++) { gcn_mi_region_unprotect(region); } } MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); --- NEW FILE: gcn-mi.h --- /* * arch/ppc/platforms/gcn-mi.h * * Nintendo GameCube Memory Interface driver * Copyright (C) 2004-2005 The GameCube Linux Team * Copyright (C) 2004,2005 Albert Herranz * * 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. * */ #ifndef __GCN_MI_H #define __GCN_MI_H #ifdef CONFIG_GAMECUBE_MI #define MI_MAX_REGIONS 4 #define MI_PROT_NONE 0x00 #define MI_PROT_RO 0x01 #define MI_PROT_WO 0x02 #define MI_PROT_RW 0x03 int gcn_mi_region_protect(unsigned long physlo, unsigned long physhi, int type); int gcn_mi_region_unprotect(int region); void gcn_mi_region_unprotect_all(void); #endif /* CONFIG_GAMECUBE_MI */ #endif /* __GCN_MI_H */ Index: Kconfig =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/misc/Kconfig,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Kconfig 2 Dec 2004 15:52:41 -0000 1.1 +++ Kconfig 7 Jan 2005 23:40:14 -0000 1.2 @@ -4,7 +4,7 @@ menu "Misc devices" -config GCN_GQR +config GAMECUBE_GQR tristate "Device driver for Gamecube Gekko GQR" depends on GAMECUBE default m @@ -14,6 +14,20 @@ psql and psqst instrutions. The registers will appear in /proc/sys/gqr. +config GAMECUBE_MI + tristate "Nintendo GameCube Memory Interface" + depends on GAMECUBE + default n + help + If you say yes to this option, support will be included for the + Memory Interface (MI) of the Nintendo GameCube. + + The MI allows one to setup up to four protected memory regions, + catching invalid accesses to them. The MI catches out of bounds + memory accesses too. + + If in doubt, say N here. + config IBM_ASM tristate "Device driver for IBM RSA service processor" depends on X86 && EXPERIMENTAL Index: Makefile =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/misc/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Makefile 2 Dec 2004 15:55:53 -0000 1.1 +++ Makefile 7 Jan 2005 23:40:14 -0000 1.2 @@ -4,4 +4,5 @@ obj- := misc.o # Dummy rule to force built-in.o to be made obj-$(CONFIG_IBM_ASM) += ibmasm/ -obj-$(CONFIG_GCN_GQR) += gcn-gqr.o +obj-$(CONFIG_GAMECUBE_GQR) += gcn-gqr.o +obj-$(CONFIG_GAMECUBE_MI) += gcn-mi.o |
From: <he...@us...> - 2005-01-07 23:34:42
|
Update of /cvsroot/gc-linux/linux/arch/ppc/platforms In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14169 Modified Files: gamecube.c Log Message: Add kexec ppc hooks. We still have no kexec on mainline, but will soon. Index: gamecube.c =================================================================== RCS file: /cvsroot/gc-linux/linux/arch/ppc/platforms/gamecube.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- gamecube.c 6 Jan 2005 19:57:53 -0000 1.28 +++ gamecube.c 7 Jan 2005 23:34:32 -0000 1.29 @@ -158,6 +158,20 @@ #endif } +#ifdef CONFIG_KEXEC +void gamecube_shutdown(void) +{ + /* currently not used */ +} + +int gamecube_kexec_prepare(struct kimage *image) +{ + int retval = 0; + + return retval; +} +#endif /* CONFIG_KEXEC */ + void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) @@ -190,4 +204,11 @@ ppc_md.time_init = gcn_time_init; ppc_md.set_rtc_time = gcn_set_rtc_time; ppc_md.get_rtc_time = gcn_get_rtc_time; + +#ifdef CONFIG_KEXEC + ppc_md.machine_shutdown = gamecube_shutdown; + ppc_md.machine_kexec_prepare = gamecube_kexec_prepare; + ppc_md.machine_kexec = machine_kexec_simple; +#endif /* CONFIG_KEXEC */ + } |
From: <he...@us...> - 2005-01-06 20:28:33
|
Update of /cvsroot/gc-linux/linux/drivers/video In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2385/drivers/video Modified Files: Makefile Log Message: Cosmetic change. Index: Makefile =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/video/Makefile,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- Makefile 4 Jan 2005 21:39:30 -0000 1.11 +++ Makefile 6 Jan 2005 20:28:24 -0000 1.12 @@ -94,8 +94,8 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_PXA) += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o -obj-$(CONFIG_FB_GAMECUBE) += gcnfb.o gcngx.o cfbfillrect.o cfbcopyarea.o \ - cfbimgblt.o +obj-$(CONFIG_FB_GAMECUBE) += gcnfb.o gcngx.o \ + cfbfillrect.o cfbcopyarea.o cfbimgblt.o # Platform or fallback drivers go here obj-$(CONFIG_FB_VESA) += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o |