From: wdenk Date: Fri, 7 Dec 2001 01:21:34 +0000 (+0000) Subject: * Patch by Denis Peter, 5 Dec 2001 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=6838d0f1f37b261e9b4f0cdccdfe9c36f6dc080e;p=users%2Frw%2Fppcboot.git * Patch by Denis Peter, 5 Dec 2001 - add USB support for 40x - add support for MIP405 board - Move PIP405 into new manufacturer's directory, separate out common stuff - changed scsi_init in file common/board.c to make it common to IDE init - added last_stage_init in common/board.c (#ifdef CONFIG_LAST_STAGE_INIT) for parts which needs working interrupts (ISA Keyboard etc) - replaced "defined(CONFIG_PIP405)" in common/cmd_i2c.c with "defined(CONFIG_I2C405)" which is also defined for MIP405. Other 405 based boards may also change to this define. (CONFIG_W70 CONFIG_CPCI405, CONFIG_AR405, CONFIG_WALNUT405 and CONFIG_ERIC). - add "device_deregister()" in common/devices.c. Used to deregister the USB keyboard. - removed drv_isa_kbd_init() in common/devices.c because it will not work when initializing before setting up the interrupts. - changed type of TimeOut from int to ulong and the sequence how the TimeOut value is calculated (to prevent an overflow for a CPU frequency of 266MHz) in file cpu/ppc4xx/i2c.c. - fix size rounding in disc/part.c --- diff --git a/CHANGELOG b/CHANGELOG index 771578a..7cafdd7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -56,6 +56,33 @@ To do: Modifications for 1.1.2: ====================================================================== +* Patch by Denis Peter, 5 Dec 2001 + - add USB support for 40x + - add support for MIP405 board + - Move PIP405 into new manufacturer's directory, + separate out common stuff + - changed scsi_init in file common/board.c to make it common to IDE + init + - added last_stage_init in common/board.c (#ifdef + CONFIG_LAST_STAGE_INIT) for parts which needs working interrupts + (ISA Keyboard etc) + - replaced "defined(CONFIG_PIP405)" in common/cmd_i2c.c with + "defined(CONFIG_I2C405)" which is also defined for MIP405. Other + 405 based boards may also change to this define. (CONFIG_W70 + CONFIG_CPCI405, CONFIG_AR405, CONFIG_WALNUT405 and CONFIG_ERIC). + - add "device_deregister()" in common/devices.c. Used to + deregister the USB keyboard. + - removed drv_isa_kbd_init() in common/devices.c because it will + not work when initializing before setting up the interrupts. + - changed type of TimeOut from int to ulong and the sequence how + the TimeOut value is calculated (to prevent an overflow for a CPU + frequency of 266MHz) in file cpu/ppc4xx/i2c.c. + - fix size rounding in disc/part.c + +* Fix for broken SanDisk which spuriously set high bit in function ID + CIS tuple + Patch by Peter Desnoyers, 05 Dec 2001 + * Add new 8260 mask revision support * Add support for TTTech C2MON board diff --git a/CREDITS b/CREDITS index 86c6d64..d3e2975 100644 --- a/CREDITS +++ b/CREDITS @@ -99,7 +99,8 @@ D: Port to MPC8260ADS board N: Murray Jensen E: Murray.Jensen@cmst.csiro.au -D: Initial 8260 support; GDB support; Port to Cogent+Hymod boards; Hymod Board Database +D: Initial 8260 support; GDB support +D: Port to Cogent+Hymod boards; Hymod Board Database W: http://www.msa.cmst.csiro.au/ourstaff/MurrayJensen/mjj.html N: Yoo. Jonghoon @@ -132,7 +133,9 @@ D: Support for Embedded Planet RPX Super Board N: Denis Peter E: d.peter@mpl.ch -D: Port to PIP405 board, support for SCSI, floppy, CDROM, CT69000 video, ... +D: Support for 4xx SCSI, floppy, CDROM, CT69000 video, ... +D: Support for PIP405 board +D: Support for MIP405 board N: Bill Pitts E: wlp@mindspring.com diff --git a/MAKEALL b/MAKEALL index 27399d9..6c0b8f6 100755 --- a/MAKEALL +++ b/MAKEALL @@ -36,9 +36,9 @@ LIST_4xx=" \ CANBT CPCI405 \ CPCIISER4 CRAYL1 \ DASA_SIM ERIC \ - OCRTC PIP405 \ - W7OLMC W7OLMG \ - WALNUT405 \ + MIP405 OCRTC \ + PIP405 W7OLMC \ + W7OLMG WALNUT405 \ " ######################################################################### diff --git a/Makefile b/Makefile index e8b10f2..eb80451 100644 --- a/Makefile +++ b/Makefile @@ -459,6 +459,15 @@ ERIC_config:unconfig echo "CPU = ppc4xx" >>config.mk ; \ echo "#include " >config.h +MIP405_config:unconfig + @echo "Configuring for $(@:_config=) Board..." ; \ + cd ./include ; \ + echo "ARCH = ppc" > config.mk ; \ + echo "BOARD = mip405" >>config.mk ; \ + echo "CPU = ppc4xx" >>config.mk ; \ + echo "VENDOR = mpl" >>config.mk ; \ + echo "#include " >config.h + OCRTC_config: unconfig @echo "Configuring for $(@:_config=) Board..." ; \ cd ./include ; \ @@ -474,6 +483,7 @@ PIP405_config:unconfig echo "ARCH = ppc" > config.mk ; \ echo "BOARD = pip405" >>config.mk ; \ echo "CPU = ppc4xx" >>config.mk ; \ + echo "VENDOR = mpl" >>config.mk ; \ echo "#include " >config.h W7OLMC_config \ diff --git a/README b/README index 8c951f8..059a1eb 100644 --- a/README +++ b/README @@ -128,7 +128,9 @@ Directory Hierarchy: - board/lantec Files specific to LANTEC boards - board/lwmon Files specific to LWMON boards - board/mbx8xx Files specific to MBX boards -- board/pip405 Files specific to PIP405 boards +- board/mpl/common Common files for MPL boards +- board/mpl/pip405 Files specific to PIP405 boards +- board/mpl/mip405 Files specific to MIP405 boards - board/RPXlite Files specific to RPXlite boards - board/rpxsuper Files specific to RPXsuper boards @@ -211,18 +213,18 @@ The following options need to be configured: - Board Type: Define exactly one of - CONFIG_ADCIOP, CONFIG_FADS, CONFIG_RPXSUPER, - CONFIG_ADS, CONFIG_FPS850L, CONFIG_SANDPOINT, - CONFIG_BSEIP, CONFIG_HERMES, CONFIG_SBC8260, - CONFIG_COGENT, CONFIG_HYMOD, CONFIG_SM850, - CONFIG_COGENT, CONFIG_IP860, CONFIG_SPD823TS, - CONFIG_CPCI405, CONFIG_IVMS8, CONFIG_SXNI855T, - CONFIG_CU824, CONFIG_MBX, CONFIG_TQM823L, - CONFIG_ERIC, CONFIG_PIP405, CONFIG_TQM8260, - CONFIG_ETX094, CONFIG_RDSPROTO, CONFIG_TQM850L, - CONFIG_EVB64260, CONFIG_RPXCLASSIC, CONFIG_TQM855L, - CONFIG_EVB64260, CONFIG_RPXLITE, CONFIG_TQM860L, - CONFIG_PCU_E, CONFIG_CCM + CONFIG_ADCIOP, CONFIG_FADS, CONFIG_RPXLITE, + CONFIG_ADS, CONFIG_FPS850L, CONFIG_RPXSUPER, + CONFIG_BSEIP, CONFIG_HERMES, CONFIG_SANDPOINT, + CONFIG_CCM, CONFIG_HYMOD, CONFIG_SBC8260, + CONFIG_COGENT, CONFIG_IP860, CONFIG_SM850, + CONFIG_COGENT, CONFIG_IVMS8, CONFIG_SPD823TS, + CONFIG_CPCI405, CONFIG_MBX, CONFIG_SXNI855T, + CONFIG_CU824, CONFIG_MIP405, CONFIG_TQM823L, + CONFIG_ERIC, CONFIG_PCU_E, CONFIG_TQM8260, + CONFIG_ETX094, CONFIG_PIP405, CONFIG_TQM850L, + CONFIG_EVB64260, CONFIG_RDSPROTO, CONFIG_TQM855L, + CONFIG_EVB64260, CONFIG_RPXCLASSIC, CONFIG_TQM860L - CPU Module Type: (if CONFIG_COGENT is defined) Define exactly one of @@ -395,10 +397,11 @@ The following options need to be configured: CFG_CMD_DHCP DHCP support CFG_CMD_BEDBUG Include BedBug Debugger CFG_CMD_ELF bootelf, bootvx - CFG_CMD_FDC Floppy Disk Support - CFG_CMD_SCSI SCSI Support + CFG_CMD_FDC * Floppy Disk Support + CFG_CMD_SCSI * SCSI Support CFG_CMD_SETGETDCR Support for DCR Register access (4xx only) - CFG_CMD_BSP * Board SPecific functions + CFG_CMD_USB * USB support + CFG_CMD_BSP * Board SPecific functions ----------------------------------------------- CFG_CMD_ALL all @@ -465,6 +468,17 @@ The following options need to be configured: maximum numbers of LUNs, SCSI ID's and target devices. +- USB Support: + At the moment only the UHCI host controller is + supported (PIP405, MIP405); define + CONFIG_USB_UHCI to enable it. + define CONFIG_USB_KEYBOARD to enable the USB Keyboard + end define CONFIG_USB_STORAGE to enable the USB + storage devices. + Note: + Supported are USB Keyboards and USB Floppy drives + (TEAC FD-05PUB). + - Keyboard Support: CONFIG_ISA_KEYBOARD diff --git a/board/mpl/common/flash.c b/board/mpl/common/flash.c new file mode 100644 index 0000000..6f2eef6 --- /dev/null +++ b/board/mpl/common/flash.c @@ -0,0 +1,886 @@ +/* + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.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 + */ + +/* + * Modified 4/5/2001 + * Wait for completion of each sector erase command issued + * 4/5/2001 + * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com + */ + +/* + * Modified 3/7/2001 + * - adopted for pip405, Denis Peter, MPL AG Switzerland + * TODO: + * clean-up + */ + +#include +#include +#include +#ifdef CONFIG_PIP405 +#include "../pip405/pip405.h" +#endif +#ifdef CONFIG_MIP405 +#include "../mip405/mip405.h" +#endif + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); +static void flash_get_offsets (ulong base, flash_info_t *info); + +void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt); + + +#ifdef CONFIG_ADCIOP +#define ADDR0 0x0aa9 +#define ADDR1 0x0556 +#define FLASH_WORD_SIZE unsigned char +#endif + +#ifdef CONFIG_CPCI405 +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned short +#endif + +#ifdef CONFIG_PIP405 +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned short +#endif + +#ifdef CONFIG_MIP405 +#define ADDR0 0x5555 +#define ADDR1 0x2aaa +#define FLASH_WORD_SIZE unsigned short +#endif + +#define FALSE 0 +#define TRUE 1 + +/*----------------------------------------------------------------------- + */ + + +unsigned long flash_init (void) +{ + unsigned long size_b0, size_b1; + int i; + unsigned long pbcr; + unsigned long base_b0, base_b1; + unsigned char rc; + + rc=switch_cs(FALSE); /* map Flash High */ + + if(rc) + printf("(MPS Boot) "); + else + printf("(Flash Boot) "); + /* Init: no FLASHes known */ + for (i=0; i= CFG_FLASH_BASE + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + size_b1 = 0 ; + flash_info[0].size = size_b0; + } + + /* 2 banks */ + else + { + size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + + /* Re-do sizing to get full correct info */ + + if (size_b1) + { + mtdcr(ebccfga, pb0cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb0cr); + base_b1 = -size_b1; + pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb1cr = %x\n", pbcr); */ + } + + if (size_b0) + { + mtdcr(ebccfga, pb1cr); + pbcr = mfdcr(ebccfgd); + mtdcr(ebccfga, pb1cr); + base_b0 = base_b1 - size_b0; + pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17); + mtdcr(ebccfgd, pbcr); + /* printf("pb0cr = %x\n", pbcr); */ + } + + size_b0 = flash_get_size((vu_long *)base_b0, &flash_info[0]); + + flash_get_offsets (base_b0, &flash_info[0]); + + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b0+size_b0-CFG_MONITOR_LEN, + base_b0+size_b0-1, + &flash_info[0]); + + if (size_b1) { + /* Re-do sizing to get full correct info */ + size_b1 = flash_get_size((vu_long *)base_b1, &flash_info[1]); + + flash_get_offsets (base_b1, &flash_info[1]); + + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b1+size_b1-CFG_MONITOR_LEN, + base_b1+size_b1-1, + &flash_info[1]); + /* monitor protection OFF by default (one is enough) */ + (void)flash_protect(FLAG_PROTECT_CLEAR, + base_b0+size_b0-CFG_MONITOR_LEN, + base_b0+size_b0-1, + &flash_info[0]); + } else { + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].sector_count = -1; + } + + flash_info[0].size = size_b0; + flash_info[1].size = size_b1; + }/* else 2 banks */ + /* switch_cs(rc); */ /* switch mode back */ + return (size_b0 + size_b1); +} + + +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + return; +} +#if 0 +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + (info->flash_id == FLASH_AM040)){ + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } + else { + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00010000; + } + } + } +} + +#endif +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *flash; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_SST: printf ("SST "); break; + case FLASH_MAN_INTEL: printf ("Intel "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: printf ("AM29F040 (512 Kbit, uniform sector size)\n"); + break; + case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + case FLASH_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n"); + break; + case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n"); + break; + case FLASH_INTEL320T: printf ("TE28F320C3 (32 Mbit, top sector size)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld KB in %d Sectors\n", + info->size >> 10, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + /* + * Check if whole sector is erased + */ + if (i != (info->sector_count-1)) + size = info->start[i+1] - info->start[i]; + else + size = info->start[0] + info->size - info->start[i]; + erased = 1; + flash = (volatile unsigned long *)info->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k=0; kstart[i], + info->protect[i] ? " (RO)" : " " +#else + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + info->protect[i] ? "RO " : " " +#endif + ); + } + printf ("\n"); + +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + FLASH_WORD_SIZE value; + ulong base = (ulong)addr; + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; + + /* Write auto select command: read Manufacturer ID */ + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; + + value = addr2[0]; + /* printf("flash_get_size value: %x\n",value); */ + switch (value) { + case (FLASH_WORD_SIZE)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (FLASH_WORD_SIZE)FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (FLASH_WORD_SIZE)INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + case (FLASH_WORD_SIZE)SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + value = addr2[1]; /* device ID */ + /* printf("Device value %x\n",value); */ + switch (value) { + case (FLASH_WORD_SIZE)AMD_ID_F040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 512 ko */ + break; + case (FLASH_WORD_SIZE)AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ +#if 0 /* enable when device IDs are available */ + case (FLASH_WORD_SIZE)AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (FLASH_WORD_SIZE)AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00400000; + break; /* => 4 MB */ +#endif + case (FLASH_WORD_SIZE)SST_ID_xF800A: + info->flash_id += FLASH_SST800A; + info->sector_count = 16; + info->size = 0x00100000; + break; /* => 1 MB */ + case (FLASH_WORD_SIZE)INTEL_ID_28F320C3T: + info->flash_id += FLASH_INTEL320T; + info->sector_count = 71; + info->size = 0x00400000; + break; /* => 4 MB */ + + + case (FLASH_WORD_SIZE)SST_ID_xF160A: + info->flash_id += FLASH_SST160A; + info->sector_count = 32; + info->size = 0x00200000; + break; /* => 2 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + + /* set up sector start address table */ + if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || + (info->flash_id == FLASH_AM040)){ + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } else { + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00004000; + info->start[2] = base + 0x00006000; + info->start[3] = base + 0x00008000; + for (i = 4; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000) - 0x00030000; + } + else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + if(info->sector_count==71) { + + info->start[i--] = base + info->size - 0x00002000; + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000A000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x0000E000; + for (; i >= 0; i--) + info->start[i] = base + i * 0x000010000; + } + else { + info->start[i--] = base + info->size - 0x00004000; + info->start[i--] = base + info->size - 0x00006000; + info->start[i--] = base + info->size - 0x00008000; + for (; i >= 0; i--) + info->start[i] = base + i * 0x00010000; + } + } + } + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]); + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) + info->protect[i] = 0; + else + info->protect[i] = addr2[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { +#if 0 /* test-only */ +#ifdef CONFIG_ADCIOP + addr2 = (volatile unsigned char *)info->start[0]; + addr2[ADDR0] = 0xAA; + addr2[ADDR1] = 0x55; + addr2[ADDR0] = 0xF0; /* reset bank */ +#else + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ +#endif +#else /* test-only */ + addr2 = (FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ +#endif /* test-only */ + } + return (info->size); +} + +int wait_for_DQ7(flash_info_t *info, int sect) +{ + ulong start, now, last; + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); + + start = get_timer (0); + last = start; + while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return -1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + return 0; +} + +int intel_wait_for_DQ7(flash_info_t *info, int sect) +{ + ulong start, now, last; + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]); + + start = get_timer (0); + last = start; + while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return -1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + addr[0]=(FLASH_WORD_SIZE)0x00500050; + return 0; +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *addr2; + int flag, prot, sect, l_sect; + int i; + + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("Can't erase unknown flash type - aborted\n"); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr2 = (FLASH_WORD_SIZE *)(info->start[sect]); + /* printf("Erasing sector %p\n", addr2); */ /* CLH */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */ + for (i=0; i<50; i++) + udelay(1000); /* wait 1 ms */ + wait_for_DQ7(info, sect); + } + else { + if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ + addr2[0] = (FLASH_WORD_SIZE)0x00600060; /* unlock sector */ + addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* sector erase */ + intel_wait_for_DQ7(info, sect); + addr2[0] = (FLASH_WORD_SIZE)0x00200020; /* sector erase */ + addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* sector erase */ + intel_wait_for_DQ7(info, sect); + } + else { + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080; + addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */ + wait_for_DQ7(info, sect); + } + } + l_sect = sect; + /* + * Wait for each sector to complete, it's more + * reliable. According to AMD Spec, you must + * issue all erase commands within a specified + * timeout. This has been seen to fail, especially + * if printf()s are included (for debug)!! + */ + /* wait_for_DQ7(info, sect); */ + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + +#if 0 + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + wait_for_DQ7(info, l_sect); + +DONE: +#endif + /* reset to read mode */ + addr = (FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + + printf (" done\n"); + return 0; +} + +void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt) +{ + int i; + volatile FLASH_WORD_SIZE *addr2; + long c; + c= (long)cnt; + for(i=info->sector_count-1;i>0;i--) + { + if(addr>=info->start[i]) + break; + } + do { + addr2 = (FLASH_WORD_SIZE *)(info->start[i]); + addr2[0] = (FLASH_WORD_SIZE)0x00600060; /* unlock sector setup */ + addr2[0] = (FLASH_WORD_SIZE)0x00D000D0; /* unlock sector */ + intel_wait_for_DQ7(info, i); + i++; + c-=(info->start[i]-info->start[i-1]); + }while(c>0); + + +} + + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong wp, data; + int rc; + /* int i, l, rc; */ + /* unsigned char sw; */ + ulong *srcp; + + + + if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ + unlock_intel_sectors(info,addr,cnt); + } + wp=addr; + srcp=(ulong *)src; + while (cnt >= 4) { + data=*srcp++; + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + if((wp % 0x10000)==0) + printf("."); /* show Progress */ + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + return -1; +#if 0 + wp = (addr & ~3); /* get lower word aligned address */ + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i=0; i<4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + if((wp % 0x10000)==0) + printf("."); /* show Progress */ + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + rc=write_word(info, wp, data); + return rc; + +#endif +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static FLASH_WORD_SIZE *read_val = (FLASH_WORD_SIZE *)0x200000; + +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]); + volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest; + volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data; + ulong start; + int flag; + int i; + + /* Check if Flash is (sufficiently) erased */ + if ((*((volatile FLASH_WORD_SIZE *)dest) & + (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++) + { + if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ + /* intel style writting */ + dest2[i] = (FLASH_WORD_SIZE)0x00500050; + dest2[i] = (FLASH_WORD_SIZE)0x00400040; + *read_val++ = data2[i]; + dest2[i] = data2[i]; + if (flag) + enable_interrupts(); + /* data polling for D7 */ + start = get_timer (0); + udelay(10); + while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) + { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) + return (1); + } + dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */ + udelay(10); + dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */ + if(dest2[i]!=data2[i]) + printf("Error at %p 0x%04X != 0x%04X\n",&dest2[i],dest2[i],data2[i]); + + } + else { + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0; + dest2[i] = data2[i]; + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != + (data2[i] & (FLASH_WORD_SIZE)0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + } + } + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/mpl/common/isa.c b/board/mpl/common/isa.c new file mode 100644 index 0000000..fff8f88 --- /dev/null +++ b/board/mpl/common/isa.c @@ -0,0 +1,469 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + * + * TODO: clean-up + */ + +#include +#include +#include +#include "isa.h" +#include "pci.h" +#include "kbd.h" +#include "video.h" + +extern int drv_isa_kbd_init (void); + +#undef ISA_DEBUG + +#ifdef ISA_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + + + +/* fdc (logical device 0) */ +const SIO_LOGDEV_TABLE sio_fdc[] = { + {0x60, 3}, /* set IO to FDPort (3F0) */ + {0x61, 0xF0}, /* set IO to FDPort (3F0) */ + {0x70, 06}, /* set IRQ 6 for FDPort */ + {0x74, 02}, /* set DMA 2 for FDPort */ + {0xF0, 0x05}, /* set to PS2 type */ + {0xF1, 0x00}, /* default value */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; +/* paralell port (logical device 3) */ +const SIO_LOGDEV_TABLE sio_pport[] = { + {0x60, 3}, /* set IO to PPort (378) */ + {0x61, 0x78}, /* set IO to PPort (378) */ + {0x70, 07}, /* set IRQ 7 for PPort */ + {0xF1, 00}, /* set PPort to normal */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; +/* paralell port (logical device 3) Floppy assigned to lpt */ +const SIO_LOGDEV_TABLE sio_pport_fdc[] = { + {0x60, 3}, /* set IO to PPort (378) */ + {0x61, 0x78}, /* set IO to PPort (378) */ + {0x70, 07}, /* set IRQ 7 for PPort */ + {0xF1, 02}, /* set PPort to Floppy */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; +/* uart 1 (logical device 4) */ +const SIO_LOGDEV_TABLE sio_com1[] = { + {0x60, 3}, /* set IO to COM1 (3F8) */ + {0x61, 0xF8}, /* set IO to COM1 (3F8) */ + {0x70, 04}, /* set IRQ 4 for COM1 */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; +/* uart 2 (logical device 5) */ +const SIO_LOGDEV_TABLE sio_com2[] = { + {0x60, 2}, /* set IO to COM2 (2F8) */ + {0x61, 0xF8}, /* set IO to COM2 (2F8) */ + {0x70, 03}, /* set IRQ 3 for COM2 */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; + +/* keyboard controller (logical device 7) */ +const SIO_LOGDEV_TABLE sio_keyboard[] = { + {0x70, 1}, /* set IRQ 1 for keyboard */ + {0x72, 12}, /* set IRQ 12 for mouse */ + {0xF0, 0}, /* disable Port92 (this is a PowerPC!!) */ + {0x30, 1}, /* and activate the device */ + {0xFF, 0} /* end of device table */ +}; + + +/******************************************************************************* +* Config SuperIO FDC37C672 +********************************************************************************/ +unsigned char open_cfg_super_IO(int address) +{ + out8(CFG_ISA_IO_BASE_ADDRESS | address,0x55); /* open config */ + out8(CFG_ISA_IO_BASE_ADDRESS | address,0x20); /* set address to DEV ID */ + if(in8(CFG_ISA_IO_BASE_ADDRESS | address | 0x1)==0x40) /* ok Device ID is correct */ + return TRUE; + else + return FALSE; +} + +void close_cfg_super_IO(int address) +{ + out8(CFG_ISA_IO_BASE_ADDRESS | address,0xAA); /* close config */ +} + + +unsigned char read_cfg_super_IO(int address, unsigned char function, unsigned char regaddr) +{ + /* assuming config reg is open */ + out8(CFG_ISA_IO_BASE_ADDRESS | address,0x7); /* points to the function reg */ + out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,function); /* set the function no */ + out8(CFG_ISA_IO_BASE_ADDRESS | address,regaddr); /* sets the address in the function */ + return in8(CFG_ISA_IO_BASE_ADDRESS | address | 1); +} + +void write_cfg_super_IO(int address, unsigned char function, unsigned char regaddr, unsigned char data) +{ + /* assuming config reg is open */ + out8(CFG_ISA_IO_BASE_ADDRESS | address,0x7); /* points to the function reg */ + out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,function); /* set the function no */ + out8(CFG_ISA_IO_BASE_ADDRESS | address,regaddr); /* sets the address in the function */ + out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,data); /* writes the data */ +} + +void isa_write_table(SIO_LOGDEV_TABLE *ldt,unsigned char ldev) +{ + while (ldt->index != 0xFF) { + write_cfg_super_IO(SIO_CFG_PORT, ldev, ldt->index, ldt->val); + ldt++; + } /* endwhile */ +} + +void isa_sio_loadtable(void) +{ + unsigned char *s = getenv("floppy"); + /* setup Floppy device 0*/ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_fdc,0); + /* setup parallel port device 3 */ + if(s && !strncmp(s, "lpt", 3)) { + printf("SIO: Floppy assigned to LPT\n"); + /* floppy is assigned to the LPT */ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_pport_fdc,3); + } + else { + /*printf("Floppy assigned to internal port\n");*/ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_pport,3); + } + /* setup Com1 port device 4 */ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_com1,4); + /* setup Com2 port device 5 */ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_com2,5); + /* setup keyboards device 7 */ + isa_write_table((SIO_LOGDEV_TABLE *)&sio_keyboard,7); +} + + +void isa_sio_setup(void) +{ + if(open_cfg_super_IO(SIO_CFG_PORT)==TRUE) + { + isa_sio_loadtable(); + close_cfg_super_IO(0x3F0); + } +} + + + +/****************************************************************************** + * IRQ Controller + * we use the Vector mode + */ + +struct isa_irq_action { + interrupt_handler_t *handler; + void *arg; + int count; +}; + +static struct isa_irq_action isa_irqs[16]; + + +/* + * This contains the irq mask for both 8259A irq controllers, + */ +static unsigned int cached_irq_mask = 0xffff; + +#define cached_imr1 (unsigned char)cached_irq_mask +#define cached_imr2 (unsigned char)(cached_irq_mask>>8) +#define IMR_1 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_OCW1 +#define IMR_2 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_OCW1 +#define ICW1_1 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_ICW1 +#define ICW1_2 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_ICW1 +#define ICW2_1 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_ICW2 +#define ICW2_2 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_ICW2 +#define ICW3_1 ICW2_1 +#define ICW3_2 ICW2_2 +#define ICW4_1 ICW2_1 +#define ICW4_2 ICW2_2 +#define ISR_1 ICW1_1 +#define ISR_2 ICW1_2 + + +void disable_8259A_irq(unsigned int irq) +{ + unsigned int mask = 1 << irq; + + cached_irq_mask |= mask; + if (irq & 8) + out8(IMR_2,cached_imr2); + else + out8(IMR_1,cached_imr1); +} + +void enable_8259A_irq(unsigned int irq) +{ + unsigned int mask = ~(1 << irq); + + cached_irq_mask &= mask; + if (irq & 8) + out8(IMR_2,cached_imr2); + else + out8(IMR_1,cached_imr1); +} +/* +int i8259A_irq_pending(unsigned int irq) +{ + unsigned int mask = 1<> 8); + spin_unlock_irqrestore(&i8259A_lock, flags); + + return ret; +} +*/ + +/* + * This function assumes to be called rarely. Switching between + * 8259A registers is slow. + */ +int i8259A_irq_real(unsigned int irq) +{ + int value; + int irqmask = 1<> 8); + out8(ISR_2,0x0A); /* back to the IRR register */ + return value; +} + +/* + * Careful! The 8259A is a fragile beast, it pretty + * much _has_ to be done exactly like this (mask it + * first, _then_ send the EOI, and the order of EOI + * to the two 8259s is important! + */ +void mask_and_ack_8259A(unsigned int irq) +{ + unsigned int irqmask = 1 << irq; + unsigned int temp_irqmask = cached_irq_mask; + /* + * Lightweight spurious IRQ detection. We do not want + * to overdo spurious IRQ handling - it's usually a sign + * of hardware problems, so we only do the checks we can + * do without slowing down good hardware unnecesserily. + * + * Note that IRQ7 and IRQ15 (the two spurious IRQs + * usually resulting from the 8259A-1|2 PICs) occur + * even if the IRQ is masked in the 8259A. Thus we + * can check spurious 8259A IRQs without doing the + * quite slow i8259A_irq_real() call for every IRQ. + * This does not cover 100% of spurious interrupts, + * but should be enough to warn the user that there + * is something bad going on ... + */ + if (temp_irqmask & irqmask) + goto spurious_8259A_irq; + temp_irqmask |= irqmask; + +handle_real_irq: + if (irq & 8) { + in8(IMR_2); /* DUMMY - (do we need this?) */ + out8(IMR_2,(unsigned char)(temp_irqmask>>8)); + out8(ISR_2,0x60+(irq&7));/* 'Specific EOI' to slave */ + out8(ISR_1,0x62); /* 'Specific EOI' to master-IRQ2 */ + out8(IMR_2,cached_imr2); /* turn it on again */ + } else { + in8(IMR_1); /* DUMMY - (do we need this?) */ + out8(IMR_1,(unsigned char)temp_irqmask); + out8(ISR_1,0x60+irq); /* 'Specific EOI' to master */ + out8(IMR_1,cached_imr1); /* turn it on again */ + } + + return; + +spurious_8259A_irq: + /* + * this is the slow path - should happen rarely. + */ + if (i8259A_irq_real(irq)) + /* + * oops, the IRQ _is_ in service according to the + * 8259A - not spurious, go handle it. + */ + goto handle_real_irq; + + { + static int spurious_irq_mask; + /* + * At this point we can be sure the IRQ is spurious, + * lets ACK and report it. [once per IRQ] + */ + if (!(spurious_irq_mask & irqmask)) { + PRINTF("spurious 8259A interrupt: IRQ%d.\n", irq); + spurious_irq_mask |= irqmask; + } + /* irq_err_count++; */ + /* + * Theoretically we do not have to handle this IRQ, + * but in Linux this does not cause problems and is + * simpler for us. + */ + goto handle_real_irq; + } +} + +void init_8259A(void) +{ + out8(IMR_1,0xff); /* mask all of 8259A-1 */ + out8(IMR_2,0xff); /* mask all of 8259A-2 */ + + out8(ICW1_1,0x11); /* ICW1: select 8259A-1 init */ + out8(ICW2_1,0x20 + 0); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ + out8(ICW3_1,0x04); /* 8259A-1 (the master) has a slave on IR2 */ + out8(ICW4_1,0x01); /* master expects normal EOI */ + out8(ICW1_2,0x11); /* ICW2: select 8259A-2 init */ + out8(ICW2_2,0x20 + 8); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ + out8(ICW3_2,0x02); /* 8259A-2 is a slave on master's IR2 */ + out8(ICW4_2,0x01); /* (slave's support for AEOI in flat mode + is to be investigated) */ + udelay(10000); /* wait for 8259A to initialize */ + out8(IMR_1,cached_imr1); /* restore master IRQ mask */ + udelay(10000); /* wait for 8259A to initialize */ + out8(IMR_2,cached_imr2); /* restore slave IRQ mask */ +} + + +#define PCI_INT_ACK_ADDR 0xEED00000 + +int handle_isa_int(void) +{ + unsigned long irqack; + unsigned char isr1,isr2,irq; + /* first we acknokledge the int via the PCI bus */ + irqack=in32(PCI_INT_ACK_ADDR); + /* now we get the ISRs */ + isr2=in8(ISR_2); + isr1=in8(ISR_1); + irq=(unsigned char)irqack; + if((irq==7)&&((isr1&0x80)==0)) { + PRINTF("IRQ7 detected but not in ISR\n"); + } + else { + /* we should handle cascaded interrupts here also */ + /* printf("ISA Irq %d\n",irq); */ + isa_irqs[irq].count++; + if (isa_irqs[irq].handler != NULL) + (*isa_irqs[irq].handler)(isa_irqs[irq].arg); /* call isr */ + else + { + PRINTF ("bogus interrupt vector 0x%x\n", irq); + } + } + /* issue EOI instruction to clear the IRQ */ + mask_and_ack_8259A(irq); + return 0; +} + + + +/****************************************************************** + * Install and free an ISA interrupt handler. + */ + +void isa_irq_install_handler(int vec, interrupt_handler_t *handler, void *arg) +{ + if (isa_irqs[vec].handler != NULL) { + printf ("ISA Interrupt vector %d: handler 0x%x replacing 0x%x\n", + vec, (uint)handler, (uint)isa_irqs[vec].handler); + } + isa_irqs[vec].handler = handler; + isa_irqs[vec].arg = arg; + enable_8259A_irq(vec); + PRINTF ("Install ISA IRQ %d ==> %p, @ %p mask=%04x\n", vec, handler, &isa_irqs[vec].handler,cached_irq_mask); + +} + +void isa_irq_free_handler(int vec) +{ + disable_8259A_irq(vec); + isa_irqs[vec].handler = NULL; + isa_irqs[vec].arg = NULL; + printf ("Free ISA IRQ %d mask=%04x\n", vec, cached_irq_mask); + +} + +/****************************************************************************/ +void isa_init_irq_contr(void) +{ + int i; + /* disable all Interrupts */ + /* first write icws controller 1 */ + for(i=0;i<16;i++) + { + isa_irqs[i].handler=NULL; + isa_irqs[i].arg=NULL; + isa_irqs[i].count=0; + } + init_8259A(); + out8(IMR_2,0xFF); +} + + +/****************************************************************** + * Init the ISA bus and devices. + */ + + +int isa_init(void) +{ + isa_sio_setup(); + drv_isa_kbd_init(); + return 0; +} + + + diff --git a/board/mpl/common/isa.h b/board/mpl/common/isa.h new file mode 100644 index 0000000..1b775fb --- /dev/null +++ b/board/mpl/common/isa.h @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 _PIP405_ISA_H_ +#define _PIP405_ISA_H_ +/* Super IO */ +#define SIO_CFG_PORT 0x3F0 /* Config Port Address */ + + + +/* table fore SIO initialization */ +typedef struct { + const uchar index; + const uchar val; +} SIO_LOGDEV_TABLE; + +typedef struct { + const uchar ldev; + const SIO_LOGDEV_TABLE *ldev_table; +} SIO_TABLE; + + + + +unsigned char open_cfg_super_IO(int address); +unsigned char read_cfg_super_IO(int address, unsigned char function, unsigned char regaddr); +void write_cfg_super_IO(int address, unsigned char function, unsigned char regaddr, unsigned char data); +void close_cfg_super_IO(int address); +void isa_sio_setup(void); +void isa_sio_setup(void); +void isa_irq_install_handler(int vec, interrupt_handler_t *handler, void *arg); +void isa_irq_free_handler(int vec); +int handle_isa_int(void); + + +#endif diff --git a/board/mpl/common/kbd.c b/board/mpl/common/kbd.c new file mode 100644 index 0000000..d5949fa --- /dev/null +++ b/board/mpl/common/kbd.c @@ -0,0 +1,655 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * + * Source partly derived from: + * linux/drivers/char/pc_keyb.c + * + * + */ +#include +#include +#include +#include "isa.h" +#include "kbd.h" + + +unsigned char kbd_read_status(void); +unsigned char kbd_read_input(void); +void kbd_send_data(unsigned char data); +void disable_8259A_irq(unsigned int irq); +void enable_8259A_irq(unsigned int irq); + +/* used only by send_data - set by keyboard_interrupt */ + + +#undef KBG_DEBUG + +#ifdef KBG_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +#define KBD_STAT_KOBF 0x01 +#define KBD_STAT_IBF 0x02 +#define KBD_STAT_SYS 0x04 +#define KBD_STAT_CD 0x08 +#define KBD_STAT_LOCK 0x10 +#define KBD_STAT_MOBF 0x20 +#define KBD_STAT_TI_OUT 0x40 +#define KBD_STAT_PARERR 0x80 + +#define KBD_INIT_TIMEOUT 1000 /* Timeout in ms for initializing the keyboard */ +#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ +#define KBD_TIMEOUT 2000 /* Timeout in ms for keyboard command acknowledge */ +/* + * Keyboard Controller Commands + */ + +#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ +#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ +#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ +#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ +#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ +#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ +#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ +#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ +#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ +#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ +#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if + initiated by the auxiliary device */ +#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ + +/* + * Keyboard Commands + */ + +#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ +#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ +#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ +#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */ +#define KBD_CMD_RESET 0xFF /* Reset */ + +/* + * Keyboard Replies + */ + +#define KBD_REPLY_POR 0xAA /* Power on reset */ +#define KBD_REPLY_ACK 0xFA /* Command ACK */ +#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ + +/* + * Status Register Bits + */ + +#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ +#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ +#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ +#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ +#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ +#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ +#define KBD_STAT_PERR 0x80 /* Parity error */ + +#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF) + +/* + * Controller Mode Register Bits + */ + +#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ +#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ +#define KBD_MODE_SYS 0x04 /* The system flag (?) */ +#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ +#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ +#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ +#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ +#define KBD_MODE_RFU 0x80 + + +#define KDB_DATA_PORT 0x60 +#define KDB_COMMAND_PORT 0x64 + +#define LED_SCR 0x01 /* scroll lock led */ +#define LED_CAP 0x04 /* caps lock led */ +#define LED_NUM 0x02 /* num lock led */ + +#define KBD_BUFFER_LEN 0x20 /* size of the keyboardbuffer */ + + + + +static volatile char kbd_buffer[KBD_BUFFER_LEN]; +static volatile int in_pointer = 0; +static volatile int out_pointer = 0; + + +static unsigned char num_lock = 0; +static unsigned char caps_lock = 0; +static unsigned char scroll_lock = 0; +static unsigned char shift = 0; +static unsigned char ctrl = 0; +static unsigned char alt = 0; +static unsigned char e0 = 0; +static unsigned char leds = 0; + +#define DEVNAME "kbd" + +/* Simple translation table for the keys */ + +static unsigned char kbd_plain_xlate[] = { + 0xff,0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t', /* 0x00 - 0x0f */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',0xff, 'a', 's', /* 0x10 - 0x1f */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',0xff,'\\', 'z', 'x', 'c', 'v', /* 0x20 - 0x2f */ + 'b', 'n', 'm', ',', '.', '/',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */ + 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */ + '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */ + '\r',0xff,0xff + }; + +static unsigned char kbd_shift_xlate[] = { + 0xff,0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t', /* 0x00 - 0x0f */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',0xff, 'A', 'S', /* 0x10 - 0x1f */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',0xff, '|', 'Z', 'X', 'C', 'V', /* 0x20 - 0x2f */ + 'B', 'N', 'M', '<', '>', '?',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */ + 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */ + '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */ + '\r',0xff,0xff + }; + +static unsigned char kbd_ctrl_xlate[] = { + 0xff,0x1b, '1',0x00, '3', '4', '5',0x1E, '7', '8', '9', '0',0x1F, '=','\b','\t', /* 0x00 - 0x0f */ + 0x11,0x17,0x05,0x12,0x14,0x18,0x15,0x09,0x0f,0x10,0x1b,0x1d,'\n',0xff,0x01,0x13, /* 0x10 - 0x1f */ + 0x04,0x06,0x08,0x09,0x0a,0x0b,0x0c, ';','\'', '~',0x00,0x1c,0x1a,0x18,0x03,0x16, /* 0x20 - 0x2f */ + 0x02,0x0e,0x0d, '<', '>', '?',0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */ + 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */ + '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */ + '\r',0xff,0xff + }; + +/****************************************************************** + * Init + ******************************************************************/ +int isa_kbd_init(void) +{ + char* result; + result=kbd_initialize(); + if(result==NULL) { + PRINTF("AT Keyboard initialized\n"); + irq_install_handler(25, (interrupt_handler_t *)handle_isa_int, NULL); + isa_irq_install_handler(KBD_INTERRUPT, (interrupt_handler_t *)kbd_interrupt, NULL); + return (1); + } + else { + printf("%s\n",result); + return (-1); + } +} + +#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE +extern int overwrite_console (void); +#else +int overwrite_console (void) +{ + return (0); +} +#endif + +int drv_isa_kbd_init (void) +{ + int error; + device_t kbddev ; + char *stdinname = getenv ("stdin"); + + if(isa_kbd_init()==-1) + return -1; + memset (&kbddev, 0, sizeof(kbddev)); + strcpy(kbddev.name, DEVNAME); + kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + kbddev.putc = NULL ; + kbddev.puts = NULL ; + kbddev.getc = kbd_getc ; + kbddev.tstc = kbd_testc ; + + error = device_register (&kbddev); + if(error==0) { + /* check if this is the standard input device */ + if(strcmp(stdinname,DEVNAME)==0) { + /* reassign the console */ + if(overwrite_console()) { + return 1; + } + error=console_assign(stdin,DEVNAME); + if(error==0) + return 1; + else + return error; + } + return 1; + } + return error; +} + +/****************************************************************** + * Queue handling + ******************************************************************/ +/* puts character in the queue and sets up the in and out pointer */ +void kbd_put_queue(char data) +{ + if((in_pointer+1)==KBD_BUFFER_LEN) { + if(out_pointer==0) { + return; /* buffer full */ + } else{ + in_pointer=0; + } + } else { + if((in_pointer+1)==out_pointer) + return; /* buffer full */ + in_pointer++; + } + kbd_buffer[in_pointer]=data; + return; +} + +/* test if a character is in the queue */ +int kbd_testc(void) +{ + if(in_pointer==out_pointer) + return(0); /* no data */ + else + return(1); +} +/* gets the character from the queue */ +int kbd_getc(void) +{ + char c; + while(in_pointer==out_pointer); + if((out_pointer+1)==KBD_BUFFER_LEN) + out_pointer=0; + else + out_pointer++; + c=kbd_buffer[out_pointer]; + return (int)c; + +} + + +/* set LEDs */ + +void kbd_set_leds(void) +{ + if(caps_lock==0) + leds&=~LED_CAP; /* switch caps_lock off */ + else + leds|=LED_CAP; /* switch on LED */ + if(num_lock==0) + leds&=~LED_NUM; /* switch LED off */ + else + leds|=LED_NUM; /* switch on LED */ + if(scroll_lock==0) + leds&=~LED_SCR; /* switch LED off */ + else + leds|=LED_SCR; /* switch on LED */ + kbd_send_data(KBD_CMD_SET_LEDS); + kbd_send_data(leds); +} + + +void handle_keyboard_event(unsigned char scancode) +{ + unsigned char keycode; + + /* Convert scancode to keycode */ + PRINTF("scancode %x\n",scancode); + if(scancode==0xe0) { + e0=1; /* special charakters */ + return; + } + if(e0==1) { + e0=0; /* delete flag */ + if(!( ((scancode&0x7F)==0x38)|| /* the right ctrl key */ + ((scancode&0x7F)==0x1D)|| /* the right alt key */ + ((scancode&0x7F)==0x35)|| /* the right '/' key */ + ((scancode&0x7F)==0x1C) )) /* the right enter key */ + /* we swallow unknown e0 codes */ + return; + } + /* special cntrl keys */ + switch(scancode) + { + case 0x2A: + case 0x36: /* shift pressed */ + shift=1; + return; /* do nothing else */ + case 0xAA: + case 0xB6: /* shift released */ + shift=0; + return; /* do nothing else */ + case 0x38: /* alt pressed */ + alt=1; + return; /* do nothing else */ + case 0xB8: /* alt released */ + alt=0; + return; /* do nothing else */ + case 0x1d: /* ctrl pressed */ + ctrl=1; + return; /* do nothing else */ + case 0x9d: /* ctrl released */ + ctrl=0; + return; /* do nothing else */ + case 0x46: /* scrollock pressed */ + scroll_lock=~scroll_lock; + kbd_set_leds(); + return; /* do nothing else */ + case 0x3A: /* capslock pressed */ + caps_lock=~caps_lock; + kbd_set_leds(); + return; + case 0x45: /* numlock pressed */ + num_lock=~num_lock; + kbd_set_leds(); + return; + case 0xC6: /* scroll lock released */ + case 0xC5: /* num lock released */ + case 0xBA: /* caps lock released */ + return; /* just swallow */ + } + if((scancode&0x80)==0x80) /* key released */ + return; + /* now, decide which table we need */ + if(scancode > (sizeof(kbd_plain_xlate)/sizeof(kbd_plain_xlate[0]))) { /* scancode not in list */ + PRINTF("unkown scancode %X\n",scancode); + return; /* swallow it */ + } + /* setup plain code first */ + keycode=kbd_plain_xlate[scancode]; + if(caps_lock==1) { /* caps_lock is pressed, overwrite plain code */ + if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */ + PRINTF("unkown caps-locked scancode %X\n",scancode); + return; /* swallow it */ + } + keycode=kbd_shift_xlate[scancode]; + if(keycode<'A') { /* we only want the alphas capital */ + keycode=kbd_plain_xlate[scancode]; + } + } + if(shift==1) { /* shift overwrites caps_lock */ + if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */ + PRINTF("unkown shifted scancode %X\n",scancode); + return; /* swallow it */ + } + keycode=kbd_shift_xlate[scancode]; + } + if(ctrl==1) { /* ctrl overwrites caps_lock and shift */ + if(scancode > (sizeof(kbd_ctrl_xlate)/sizeof(kbd_ctrl_xlate[0]))) { /* scancode not in list */ + PRINTF("unkown ctrl scancode %X\n",scancode); + return; /* swallow it */ + } + keycode=kbd_ctrl_xlate[scancode]; + } + /* check if valid keycode */ + if(keycode==0xff) { + PRINTF("unkown scancode %X\n",scancode); + return; /* swallow unknown codes */ + } + + kbd_put_queue(keycode); + PRINTF("%x\n",keycode); +} + +/* + * This reads the keyboard status port, and does the + * appropriate action. + * + */ +unsigned char handle_kbd_event(void) +{ + unsigned char status = kbd_read_status(); + unsigned int work = 10000; + + while ((--work > 0) && (status & KBD_STAT_OBF)) { + unsigned char scancode; + + scancode = kbd_read_input(); + + /* Error bytes must be ignored to make the + Synaptics touchpads compaq use work */ + /* Ignore error bytes */ + if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR))) + { + if (status & KBD_STAT_MOUSE_OBF) + ; /* not supported: handle_mouse_event(scancode); */ + else + handle_keyboard_event(scancode); + } + status = kbd_read_status(); + } + if (!work) + PRINTF("pc_keyb: controller jammed (0x%02X).\n", status); + return status; +} + + + +/****************************************************************************** + * Lowlevel Part of keyboard section + */ +unsigned char kbd_read_status(void) +{ + return(in8(CFG_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT)); +} + +unsigned char kbd_read_input(void) +{ + return(in8(CFG_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT)); +} + +void kbd_write_command(unsigned char cmd) +{ + out8(CFG_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT,cmd); +} + +void kbd_write_output(unsigned char data) +{ + out8(CFG_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT, data); +} + +int kbd_read_data(void) +{ + int val; + unsigned char status; + + val=-1; + status = kbd_read_status(); + if (status & KBD_STAT_OBF) { + val = kbd_read_input(); + if (status & (KBD_STAT_GTO | KBD_STAT_PERR)) + val = -2; + } + return val; +} + +int kbd_wait_for_input(void) +{ + unsigned long timeout; + int val; + + timeout = KBD_TIMEOUT; + val=kbd_read_data(); + while(val < 0) + { + if(timeout--==0) + return -1; + udelay(1000); + val=kbd_read_data(); + } + return val; +} + + +int kb_wait(void) +{ + unsigned long timeout = KBC_TIMEOUT * 10; + + do { + unsigned char status = handle_kbd_event(); + if (!(status & KBD_STAT_IBF)) + return 0; /* ok */ + udelay(1000); + timeout--; + } while (timeout); + return 1; +} + +void kbd_write_command_w(int data) +{ + if(kb_wait()) + PRINTF("timeout in kbd_write_command_w\n"); + kbd_write_command(data); +} + +void kbd_write_output_w(int data) +{ + if(kb_wait()) + PRINTF("timeout in kbd_write_output_w\n"); + kbd_write_output(data); +} + +void kbd_send_data(unsigned char data) +{ + unsigned char status; + disable_8259A_irq(1); /* disable interrupt */ + kbd_write_output_w(data); + status = kbd_wait_for_input(); + if (status == KBD_REPLY_ACK) + enable_8259A_irq(1); /* enable interrupt */ +} + + +char * kbd_initialize(void) +{ + int status; + + in_pointer = 0; /* delete in Buffer */ + out_pointer = 0; + /* + * Test the keyboard interface. + * This seems to be the only way to get it going. + * If the test is successful a x55 is placed in the input buffer. + */ + kbd_write_command_w(KBD_CCMD_SELF_TEST); + if (kbd_wait_for_input() != 0x55) + return "Kbd: failed self test"; + /* + * Perform a keyboard interface test. This causes the controller + * to test the keyboard clock and data lines. The results of the + * test are placed in the input buffer. + */ + kbd_write_command_w(KBD_CCMD_KBD_TEST); + if (kbd_wait_for_input() != 0x00) + return "Kbd: interface failed self test"; + /* + * Enable the keyboard by allowing the keyboard clock to run. + */ + kbd_write_command_w(KBD_CCMD_KBD_ENABLE); + status = kbd_wait_for_input(); + /* + * Reset keyboard. If the read times out + * then the assumption is that no keyboard is + * plugged into the machine. + * This defaults the keyboard to scan-code set 2. + * + * Set up to try again if the keyboard asks for RESEND. + */ + do { + kbd_write_output_w(KBD_CMD_RESET); + status = kbd_wait_for_input(); + if (status == KBD_REPLY_ACK) + break; + if (status != KBD_REPLY_RESEND) + { + PRINTF("status: %X\n",status); + return "Kbd: reset failed, no ACK"; + } + } while (1); + if (kbd_wait_for_input() != KBD_REPLY_POR) + return "Kbd: reset failed, no POR"; + + /* + * Set keyboard controller mode. During this, the keyboard should be + * in the disabled state. + * + * Set up to try again if the keyboard asks for RESEND. + */ + do { + kbd_write_output_w(KBD_CMD_DISABLE); + status = kbd_wait_for_input(); + if (status == KBD_REPLY_ACK) + break; + if (status != KBD_REPLY_RESEND) + return "Kbd: disable keyboard: no ACK"; + } while (1); + + kbd_write_command_w(KBD_CCMD_WRITE_MODE); + kbd_write_output_w(KBD_MODE_KBD_INT + | KBD_MODE_SYS + | KBD_MODE_DISABLE_MOUSE + | KBD_MODE_KCC); + + /* ibm powerpc portables need this to use scan-code set 1 -- Cort */ + kbd_write_command_w(KBD_CCMD_READ_MODE); + if (!(kbd_wait_for_input() & KBD_MODE_KCC)) { + /* + * If the controller does not support conversion, + * Set the keyboard to scan-code set 1. + */ + kbd_write_output_w(0xF0); + kbd_wait_for_input(); + kbd_write_output_w(0x01); + kbd_wait_for_input(); + } + kbd_write_output_w(KBD_CMD_ENABLE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Kbd: enable keyboard: no ACK"; + + /* + * Finally, set the typematic rate to maximum. + */ + kbd_write_output_w(KBD_CMD_SET_RATE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Kbd: Set rate: no ACK"; + kbd_write_output_w(0x00); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Kbd: Set rate: no ACK"; + return NULL; +} + +void kbd_interrupt(void) +{ + handle_kbd_event(); +} + + + +/* eof */ + diff --git a/board/mpl/common/kbd.h b/board/mpl/common/kbd.h new file mode 100644 index 0000000..e2cdf37 --- /dev/null +++ b/board/mpl/common/kbd.h @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 _KBD_H_ +#define _KBD_H_ + +extern int kbd_testc(void); +extern int kbd_getc(void); +extern void kbd_interrupt(void); +extern char *kbd_initialize(void); + +unsigned char kbd_is_init(void); +#define KBD_INTERRUPT 1 +#endif diff --git a/board/mpl/common/memtst.c b/board/mpl/common/memtst.c new file mode 100644 index 0000000..e573c94 --- /dev/null +++ b/board/mpl/common/memtst.c @@ -0,0 +1,522 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + */ + +/* NOT Used yet... + add following code to PIP405.c : +int testdram (unsigned long ramsize) +{ + unsigned char s[32]; + int i; + i=getenv_r("testmem",s,32); + if (i!=0) { + i=(int)simple_strtoul(s,NULL,10); + if((i>0)&&(i<0xf)) { + printf("testing "); + i=mem_test(0,ramsize,i); + if(i>0) + printf("ERROR "); + else + printf("Ok "); + } + } + return(1); +} +*/ + + +#include +#include +#include <405gp_i2c.h> + +#define FALSE 0 +#define TRUE 1 + +#define TEST_QUIET 8 +#define TEST_SHOW_PROG 4 +#define TEST_SHOW_ERR 2 +#define TEST_SHOW_ALL 1 + +#define TESTPAT1 0xAA55AA55 +#define TESTPAT2 0x55AA55AA +#define TEST_PASSED 0 +#define TEST_FAILED 1 +#define MEGABYTE (1024*1024) + + + + + +typedef struct { + volatile unsigned long pat1; + volatile unsigned long pat2; +} RAM_MEMTEST_PATTERN2; + +typedef struct { + volatile unsigned long addr; +} RAM_MEMTEST_ADDRLINE; + +static __inline unsigned long Swap_32(unsigned long val) +{ + return(((val << 16) & 0xFFFF0000) | ((val >> 16) & 0x0000FFFF)); +} + +void testm_puts(int quiet, char *buf) +{ + if((quiet&TEST_SHOW_ALL)==TEST_SHOW_ALL) + puts(buf); +} + + +void Write_Error(int mode, unsigned long addr, unsigned long expected, unsigned long actual) +{ + + char dispbuf[64]; + sprintf(dispbuf,"\n ERROR @ 0x%08lX: (exp: 0x%08lX act: 0x%08lX) ",addr,expected,actual); + testm_puts(((mode & TEST_SHOW_ERR)==TEST_SHOW_ERR) ? TEST_SHOW_ALL : mode,dispbuf); +} + + +/* + * fills the memblock of bytes from with pat1 and pat2 + */ + + +void RAM_MemTest_WritePattern2(unsigned long startaddr, unsigned long size, + unsigned long pat1, unsigned long pat2) +{ + RAM_MEMTEST_PATTERN2 *p, *pe; + + p = (RAM_MEMTEST_PATTERN2 *)startaddr; + pe = (RAM_MEMTEST_PATTERN2 *)(startaddr + size); + + while (p < pe) { + p->pat1 = pat1; + p->pat2 = pat2; + p++; + } /* endwhile */ +} + +/* + * checks the memblock of bytes from with pat1 and pat2 + * returns the address of the first error or NULL if all is well + */ + +void * RAM_MemTest_CheckPattern2(int mode,unsigned long startaddr, unsigned long size, + unsigned long pat1, unsigned long pat2) +{ + RAM_MEMTEST_PATTERN2 *p, *pe; + unsigned long actual1, actual2; + + p = (RAM_MEMTEST_PATTERN2 *)startaddr; + pe = (RAM_MEMTEST_PATTERN2 *)(startaddr + size); + + while (p < pe) { + actual1 = p->pat1; actual2 = p->pat2; + + if (actual1 != pat1) { + Write_Error(mode,(unsigned long)&(p->pat1), pat1, actual1); + return((void *)&(p->pat1)); + } /* endif */ + + if (actual2 != pat2) { + Write_Error(mode,(unsigned long)&(p->pat2), pat2, actual2); + return((void *)&(p->pat2)); + } /* endif */ + + p++; + } /* endwhile */ + + return(NULL); +} + +/* + * fills the memblock of bytes from with the address + */ + +void RAM_MemTest_WriteAddrLine(unsigned long startaddr, unsigned long size, int swapped) +{ + RAM_MEMTEST_ADDRLINE *p, *pe; + + p = (RAM_MEMTEST_ADDRLINE *)startaddr; + pe = (RAM_MEMTEST_ADDRLINE *)(startaddr + size); + + if (!swapped) { + while (p < pe) { + p->addr = (unsigned long)p; + p++; + } /* endwhile */ + } else { + while (p < pe) { + p->addr = Swap_32((unsigned long)p); + p++; + } /* endwhile */ + } /* endif */ +} + +/* + * checks the memblock of bytes from + * returns the address of the error or NULL if all is well + */ + +void * RAM_MemTest_CheckAddrLine(int mode,unsigned long startaddr, unsigned long size, int swapped) +{ + RAM_MEMTEST_ADDRLINE *p, *pe; + unsigned long actual, expected; + + p = (RAM_MEMTEST_ADDRLINE *)startaddr; + pe = (RAM_MEMTEST_ADDRLINE *)(startaddr + size); + + if (!swapped) { + while (p < pe) { + actual = p->addr; + expected = (unsigned long)p; + if (actual != expected) { + Write_Error(mode,(unsigned long)&(p->addr), expected, actual); + return((void *)&(p->addr)); + } /* endif */ + p++; + } /* endwhile */ + } + else { + while (p < pe) { + actual = p->addr; + expected = Swap_32((unsigned long)p); + if (actual != expected) { + Write_Error(mode,(unsigned long)&(p->addr), expected, actual); + return((void *)&(p->addr)); + } /* endif */ + p++; + } /* endwhile */ + } /* endif */ + + return(NULL); +} + +/* + * checks the memblock of bytes from + * returns the address of the error or NULL if all is well + */ + +void * RAM_MemTest_CheckAddrLineReverse(int mode,unsigned long startaddr, + unsigned long size, int swapped) +{ + RAM_MEMTEST_ADDRLINE *p, *pe; + unsigned long actual, expected; + + p = (RAM_MEMTEST_ADDRLINE *)(startaddr + size - sizeof(p->addr)); + pe = (RAM_MEMTEST_ADDRLINE *)startaddr; + + if (!swapped) { + while (p > pe) { + actual = p->addr; + expected = (unsigned long)p; + if (actual != expected) { + Write_Error(mode,(unsigned long)&(p->addr), expected, actual); + return((void *)&(p->addr)); + } /* endif */ + p--; + } /* endwhile */ + } else { + while (p > pe) { + actual = p->addr; + expected = Swap_32((unsigned long)p); + if (actual != expected) { + Write_Error(mode,(unsigned long)&(p->addr), expected, actual); + return((void *)&(p->addr)); + } /* endif */ + p--; + } /* endwhile */ + } /* endif */ + + return(NULL); +} + +/* + * fills the memblock of bytes from with walking bit pattern + */ + +void RAM_MemTest_WriteWalkBit(unsigned long startaddr, unsigned long size) +{ + volatile unsigned long *p, *pe; + unsigned long i; + + p = (unsigned long *)startaddr; + pe = (unsigned long *)(startaddr + size); + i = 0; + + while (p < pe) { + *p = 1UL << i; + i = (i + 1 + (((unsigned long)p) >> 7)) % 32; + p++; + } /* endwhile */ +} + +/* + * checks the memblock of bytes from + * returns the address of the error or NULL if all is well + */ + +void * RAM_MemTest_CheckWalkBit(int mode,unsigned long startaddr, unsigned long size) +{ + volatile unsigned long *p, *pe; + unsigned long actual, expected; + unsigned long i; + + p = (unsigned long *)startaddr; + pe = (unsigned long *)(startaddr + size); + i = 0; + + while (p < pe) { + actual = *p; + expected = (1UL << i); + if (actual != expected) { + Write_Error(mode,(unsigned long)p, expected, actual); + return((void *)p); + } /* endif */ + i = (i + 1 + (((unsigned long)p) >> 7)) % 32; + p++; + } /* endwhile */ + + return(NULL); +} + +/* + * fills the memblock of bytes from with "random" pattern + */ + +void RAM_MemTest_WriteRandomPattern(unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + unsigned long i, p; + + p = *pat; + + for (i = 0; i < (size / 4); i++) { + *(unsigned long *)(startaddr + i*4) = p; + if ((p % 2) > 0) { + p ^= i; + p >>= 1; + p |= 0x80000000; + } else { + p ^= ~i; + p >>= 1; + } /* endif */ + } /* endfor */ + *pat = p; +} + +/* + * checks the memblock of bytes from + * returns the address of the error or NULL if all is well + */ + +void * RAM_MemTest_CheckRandomPattern(int mode,unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + void *perr = NULL; + unsigned long i, p, p1; + + p = *pat; + + for (i = 0; i < (size / 4); i++) { + p1 = *(unsigned long *)(startaddr + i*4); + if ( p1 != p) { + if (perr == NULL) { + Write_Error(mode,startaddr + i*4, p, p1); + perr = (void *)(startaddr + i*4); + } /* endif */ + } /* endif */ + + if ((p % 2) > 0) { + p ^= i; + p >>= 1; + p |= 0x80000000; + } else { + p ^= ~i; + p >>= 1; + } /* endif */ + } /* endfor */ + + *pat = p; + return(perr); +} + + +void RAM_MemTest_WriteData1(unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + RAM_MemTest_WritePattern2(startaddr, size, TESTPAT1, TESTPAT2); +} + +void * RAM_MemTest_CheckData1(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + return (RAM_MemTest_CheckPattern2(mode, startaddr, size, TESTPAT1, TESTPAT2)); +} + +void RAM_MemTest_WriteData2(unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + RAM_MemTest_WritePattern2(startaddr, size, TESTPAT2, TESTPAT1); +} + +void * RAM_MemTest_CheckData2(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + return (RAM_MemTest_CheckPattern2(mode, startaddr, size, TESTPAT2, TESTPAT1)); +} + +void RAM_MemTest_WriteAddr1(unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + RAM_MemTest_WriteAddrLine(startaddr, size, FALSE); +} + +void * RAM_MemTest_Check1Addr1(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + return(RAM_MemTest_CheckAddrLine(mode,startaddr,size, FALSE)); +} + +void * RAM_MemTest_Check2Addr1(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + return(RAM_MemTest_CheckAddrLineReverse(mode,startaddr,size, FALSE)); +} + +void RAM_MemTest_WriteAddr2(unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + RAM_MemTest_WriteAddrLine(startaddr, size, TRUE); +} + +void * RAM_MemTest_Check1Addr2(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + return(RAM_MemTest_CheckAddrLine(mode,startaddr,size, TRUE)); +} + +void * RAM_MemTest_Check2Addr2(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat) +{ + return(RAM_MemTest_CheckAddrLineReverse(mode,startaddr,size, TRUE)); +} + + + +typedef struct { + void (*test_write)(unsigned long startaddr, unsigned long size, unsigned long *pat); + char *test_write_desc; + void * (*test_check1)(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat); + void * (*test_check2)(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat); +} RAM_MEMTEST_FUNC; + + +#define TEST_STAGES 5 +const RAM_MEMTEST_FUNC test_stage[TEST_STAGES] = { + {RAM_MemTest_WriteData1, "data test 1...\n", RAM_MemTest_CheckData1, NULL}, + {RAM_MemTest_WriteData2, "data test 2...\n", RAM_MemTest_CheckData2, NULL}, + {RAM_MemTest_WriteAddr1, "address line test...\n", RAM_MemTest_Check1Addr1, RAM_MemTest_Check2Addr1}, + {RAM_MemTest_WriteAddr2, "address line test (swapped)...\n", RAM_MemTest_Check1Addr2, RAM_MemTest_Check2Addr2}, + {RAM_MemTest_WriteRandomPattern, "random data test...\n", RAM_MemTest_CheckRandomPattern, NULL} +}; + + + +int mem_test(unsigned long start, unsigned long ramsize, int quiet) +{ + unsigned long errors,stage; + unsigned long startaddr, size, i; + const unsigned long blocksize = 0x80000; /* check in 512KB blocks */ + unsigned long *perr; + unsigned long rdatapat; + char dispbuf[80]; + int status = TEST_PASSED; + int prog=0; + + errors = 0; + startaddr = start; + size = ramsize; + if((quiet&TEST_SHOW_PROG)==TEST_SHOW_PROG) { + prog++; + printf("."); + } + sprintf(dispbuf,"\n\nMemory Test: addr = 0x%lx size = 0x%lx\n",startaddr,size); + testm_puts(quiet,dispbuf); + for(stage=0;stage0) + printf("\b \b"); + } + + if (status == TEST_FAILED) + errors++; + + return(errors); +} + + diff --git a/board/mpl/common/pci.c b/board/mpl/common/pci.c new file mode 100644 index 0000000..579f3fd --- /dev/null +++ b/board/mpl/common/pci.c @@ -0,0 +1,1411 @@ +/*-----------------------------------------------------------------------------+ +| +| This source code has been made available to you by IBM on an AS-IS +| basis. Anyone receiving this source is licensed under IBM +| copyrights to use it in any way he or she deems fit, including +| copying it, modifying it, compiling it, and redistributing it either +| with or without modifications. No license under IBM patents or +| patent applications is to be implied by the copyright license. +| +| Any user of this software should understand that IBM cannot provide +| technical support for this software and will not be responsible for +| any consequences resulting from the use of this software. +| +| Any person who transfers this source code or any derivative work +| must include the IBM copyright notice, this paragraph, and the +| preceding two paragraphs in the transferred software. +| +| COPYRIGHT I B M CORPORATION 1995 +| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M ++-----------------------------------------------------------------------------*/ +/* + * Adapted for PIP405 03.07.01 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * TODO: Clean-up + */ + +#include +#include +#include +#include "pci.h" +#include +#include "isa.h" + + +void pciinfo(int bus_no); +#ifdef CONFIG_405GP + +#ifdef CONFIG_PCI + +#undef PCI_DEBUG + +/*------------------------------------------------------------------------ +| These are the lowest addresses allowed for PCI configuration. +| They correspond to lowest available I/O and Memory addresses. +| In the case where where multiple PMM regs are being used to map +| different PLB to PCI regions, each region should have it's own +| minimum address. ++-----------------------------------------------------------------------*/ +unsigned long LowestMemAddr1 = MIN_PCI_MEMADDR1; +unsigned long LowestMemAddr2 = MIN_PCI_MEMADDR2; +unsigned long LowestIOAddr = MIN_PCI_PCI_IOADDR1; + +unsigned long MaxBusNum = 0; + + + +/*-----------------------------------------------------------------------------+ +| pci_init. Initializes the 405GP PCI Configuration regs. ++-----------------------------------------------------------------------------*/ +void pci_init(bd_t *dummy) +{ + unsigned short temp_short; + +#ifdef CONFIG_PCI_HOST + /*--------------------------------------------------------------------------+ + | 405GP PCI Master configuration. + | Map one 512 MB range of PLB/processor addresses to PCI memory space. + | PLB address 0x80000000-0x9FFFFFFF ==> PCI address 0x80000000-0x9FFFFFFF + | Use byte reversed out routines to handle endianess. + +--------------------------------------------------------------------------*/ + out32r(PMM0MA, 0x00000000); /* ensure disabled b4 setting PMM0LA */ + out32r(PMM0LA, PCI_M0_LOCAL_ADDR); + out32r(PMM0PCILA, PCI_M0_PCI_LOW_ADDR); + out32r(PMM0PCIHA, PCI_M0_PCI_HIGH_ADDR); + out32r(PMM0MA, PCI_M0_MASK_ATTRIB); /* no prefetching, and enable region */ + /*--------------------------------------------------------------------------+ + | Map one 512 MB range of PLB/processor addresses to PCI memory space. + | PLB address 0xA0000000-0xBFFFFFFF ==> PCI address 0x00000000-0x1FFFFFFF + | Use byte reversed out routines to handle endianess. + | This space is for the VGA card. + +--------------------------------------------------------------------------*/ + out32r(PMM1MA, 0x00000000); /* ensure disabled b4 setting PMM1LA */ + out32r(PMM1LA, PCI_M1_LOCAL_ADDR); + out32r(PMM1PCILA, PCI_M1_PCI_LOW_ADDR); + out32r(PMM1PCIHA, PCI_M1_PCI_HIGH_ADDR); + out32r(PMM1MA, PCI_M1_MASK_ATTRIB); /* no prefetching, and enable region */ + /*--------------------------------------------------------------------------+ + | PMM2 is not used. Initialize them to zero. + +--------------------------------------------------------------------------*/ + out32r(PMM2MA, 0x00000000); /* ensure disabled b4 setting PMM2LA */ + out32r(PMM2LA, PCI_M2_LOCAL_ADDR); + out32r(PMM2PCILA, PCI_M2_PCI_LOW_ADDR); + out32r(PMM2PCIHA, PCI_M2_PCI_HIGH_ADDR); + out32r(PMM2MA, PCI_M2_MASK_ATTRIB); /* not enabled */ +#endif + + /*--------------------------------------------------------------------------+ + | 405GP PCI Target configuration. (PTM1) + | Note: PTM1MS is hardwire enabled but we set the enable bit anyway. + +--------------------------------------------------------------------------*/ + out32r(PTM1LA, CFG_PCI_PTM1LA); /* insert address */ + out32r(PTM1MS, CFG_PCI_PTM1MS); /* insert size, enable bit is 1 */ + + /*--------------------------------------------------------------------------+ + | 405GP PCI Target configuration. (PTM2) + +--------------------------------------------------------------------------*/ + out32r(PTM2LA, CFG_PCI_PTM2LA); /* insert address */ + if (CFG_PCI_PTM2MS == 0) + { + out32r(PTM2MS, 0x00000001); /* set enable bit */ + PCI_Write_CFG_Reg(PCIDEVID_405GP, PCIBASEADDR2, 0x00000000, 4); + out32r(PTM2MS, 0x00000000); /* disable */ + } + else + out32r(PTM2MS, CFG_PCI_PTM2MS); /* insert size, enable bit is 1 */ + + /* + * Insert Subsystem Vendor and Device ID + */ + PCI_Write_CFG_Reg(PCIDEVID_405GP, PCISSVENDORID, CFG_PCI_SUBSYS_VENDORID, 2); + PCI_Write_CFG_Reg(PCIDEVID_405GP, PCISSDEVICEID, CFG_PCI_SUBSYS_DEVICEID, 2); + +#ifdef CONFIG_PCI_HOST + /*--------------------------------------------------------------------------+ + | Write the 405GP PCI Configuration regs. + | Enable 405GP to be a master on the PCI bus (PMM). + | Enable 405GP to act as a PCI memory target (PTM). + +--------------------------------------------------------------------------*/ + temp_short = PCI_Read_CFG_Reg(PCIDEVID_405GP, PCICMD, 2); + PCI_Write_CFG_Reg(PCIDEVID_405GP, PCICMD, temp_short | BM_EN | MEM_EN, 2); +#endif + + + /* + * Set HCE bit (Host Configuration Enabled) + */ + temp_short = PCI_Read_CFG_Reg(PCIDEVID_405GP, PCIBRDGOPT2, 2); + PCI_Write_CFG_Reg(PCIDEVID_405GP, PCIBRDGOPT2,(temp_short | 0x0001), 2); + +#ifdef CONFIG_PCI_PNP + /*--------------------------------------------------------------------------+ + | Scan the PCI bus and configure devices found. + +--------------------------------------------------------------------------*/ + PCI_Scan(0); +#endif /* CONFIG_PCI_PNP */ + +} + +/*-----------------------------------------------------------------------------+ +| Subroutine: PCI_Read_CFG_Reg +| Description: Read a PCI configuration register +| Inputs: +| BusDevFunc PCI Bus+Device+Function number +| Reg Configuration register number +| Width Number of bytes to read (1, 2, or 4) +| Return value: +| (unsigned int) Value of the configuration register read. +| For reads shorter than 4 bytes, return value +| is LSB-justified ++-----------------------------------------------------------------------------*/ +unsigned long PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width) +{ + unsigned int RegAddr; + + /*--------------------------------------------------------------------------+ + | bit 31 must be 1 and bits 1:0 must be 0 (note Little Endian bit notation) + +--------------------------------------------------------------------------*/ + RegAddr = 0x80000000 | ((Reg|BusDevFunc) & 0xFFFFFFFC); + + /*--------------------------------------------------------------------------+ + | Write reg to PCI Config Address + +--------------------------------------------------------------------------*/ + out32r(PCICFGADR, RegAddr); + + /*--------------------------------------------------------------------------+ + | Read reg value from PCI Config Data + +--------------------------------------------------------------------------*/ + switch (Width) + { + case 1: return ((unsigned int) in8(PCICFGDATA | (Reg & 0x3))); + case 2: return ((unsigned int) in16r(PCICFGDATA | (Reg & 0x3))); + case 4: return (in32r(PCICFGDATA | (Reg & 0x3))); + } + + return 0; /* not reached: just to satisfy the compiler */ +} + +/*-----------------------------------------------------------------------------+ +| Subroutine: PCI_Write_CFG_Reg +| Description: Write a PCI configuration register. +| Inputs: +| BusDevFunc PCI Bus+Device+Function number +| Reg Configuration register number +| Value Configuration register value +| Width Number of bytes to write (1, 2, or 4) +| Return value: +| 0 Successful +| Updated for pass2 errata #6. Need to disable interrupts and clear the +| PCICFGADR reg after writing the PCICFGDATA reg. ++-----------------------------------------------------------------------------*/ +int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned long Value, int Width) +{ + unsigned int RegAddr; + unsigned int msr; + + /*--------------------------------------------------------------------------+ + | Ensure interrupts disabled for pass2 errata #6. + +--------------------------------------------------------------------------*/ + msr = mfmsr(); + mtmsr(msr & ~(MSR_EE|MSR_CE)); + + /*--------------------------------------------------------------------------+ + | bit 31 must be 1 and bits 1:0 must be 0 (note Little Endian bit notation) + +--------------------------------------------------------------------------*/ + RegAddr = 0x80000000 | ((Reg|BusDevFunc) & 0xFFFFFFFC); + /*--------------------------------------------------------------------------+ + | Write reg to PCI Config Address + +--------------------------------------------------------------------------*/ + out32r(PCICFGADR, RegAddr); + + /*--------------------------------------------------------------------------+ + | Write reg value to PCI Config Data + +--------------------------------------------------------------------------*/ + switch (Width) + { + case 1: out8(PCICFGDATA | (Reg & 0x3), (unsigned char)(Value & 0xFF)); + break; + case 2: out16r(PCICFGDATA | (Reg & 0x3),(unsigned short)(Value & 0xFFFF)); + break; + case 4: out32r(PCICFGDATA | (Reg & 0x3), Value); + break; + } + + /*--------------------------------------------------------------------------+ + | Write PCI Config Address after writing PCICFGDATA for pass2 errata #6. + +--------------------------------------------------------------------------*/ + out32r(PCICFGADR, 0x00000000); + + /*--------------------------------------------------------------------------+ + | Restore msr (for pass2 errata #6). + +--------------------------------------------------------------------------*/ + mtmsr(msr); + + return (0); +} + +#include "pci_parts.h" + +/* + * Returns the pointer to the func config table, or NULL, if it not available + * if the revision is ff in the table, it will not be chcked + */ + +PCI_DEV_CFG_TABLE *PCI_Get_Func_Table(unsigned short vend_id,unsigned short dev_id,unsigned char revision,unsigned char func) +{ + int i; + i=0; + while(pcidevtbl[i].vendorID!=0xffff) { + if((pcidevtbl[i].vendorID == vend_id) && + (pcidevtbl[i].deviceID == dev_id) && + (pcidevtbl[i].func == func) && + ((pcidevtbl[i].revision == 0xff) || (pcidevtbl[i].revision == revision))) { +#ifdef PCI_DEBUG + printf("Table found for 0x%04X 0x%04X\n",vend_id,dev_id); +#endif + return &pcidevtbl[i]; + } + i++; /* proceed all entries */ + } +#ifdef PCI_DEBUG + printf("No Table found for 0x%04X 0x%04X\n",vend_id,dev_id); +#endif + return NULL; +} + + +/*----------------------------------------------------------------------- +| +| Subroutine: PCI_Scan +| +| Prototype: void PCI_Scan(int BusNum) +| +| Description: Scan through all 16 allowable PCI IDs and configure +| those for which the vendor ID indicates there is a +| device present. +| +| Inputs: +| BusNum Bus number where scanning begins +| +| Return value: +| None +| ++----------------------------------------------------------------------*/ +void PCI_Scan(int bus_no) +{ + int device_no,i; + int BusDevFunc; + unsigned short vend_id,dev_id; + unsigned char revision,func,header; + PCI_DEV_CFG_TABLE *pci_dev_table=NULL; + /*--------------------------------------------------------------------------+ + | Start with device 1, the 405GP is device 0. MCG 01/04/99 + +--------------------------------------------------------------------------*/ + /* init all known (on Board devices) first */ + for (device_no = 1; device_no < MAX_PCI_DEVICES; device_no++) + { + BusDevFunc = (bus_no << 16) | (device_no << 11); + if((unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2) != 0xffff) { + header = (unsigned char)PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1); + for(func=0;funcfcntable[i].width!=0) { + PCI_Write_CFG_Reg(BusDevFunc,pci_dev_table->fcntable[i].index, + pci_dev_table->fcntable[i].val,pci_dev_table->fcntable[i].width); + #ifdef PCI_DEBUG + printf(" Reg 0x%02X Value 0x%08lX Width %02d written\n",pci_dev_table->fcntable[i].index, + pci_dev_table->fcntable[i].val,pci_dev_table->fcntable[i].width); + #endif + i++; + } + if((header & 0x80)==0) + break; /* no more functions */ + } /* next function */ + } /* if device available */ + } /* all devices */ +#if 0 + /*************************************************************************** + * Since the IO and Memory Area of the ISA Bridge is not relocable, config it + * first. + ****************************************************************************/ + isabridgeDev=0; + for (Device = 1; Device < MAX_PCI_DEVICES; Device++) + { + BusDevFunc = (BusNum << 16) | (Device << 11); + + if (PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2) != 0xFFFF) + { + if(PCI_Read_CFG_Reg(BusDevFunc, PCICLASSCODE,2) == 0x0601) + { + isabridgeDev=Device; + PCI_Config_ISABridge(BusDevFunc); + break; /* do not scan further */ + } + } + } + + for (Device = 1; Device < MAX_PCI_DEVICES; Device++) + { + if(Device==isabridgeDev) + continue; /* skip ISA Bridge */ + + BusDevFunc = (BusNum << 16) | (Device << 11); + + if (PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2) != 0xFFFF) + { +#ifdef PCI_DEBUG + printf("Device %d is present\n",Device); +#endif + switch( PCI_Read_CFG_Reg(BusDevFunc, PCICLASSCODE, 2) ) + { + case 0x0604: /* PCI-PCI Bridge */ +#ifdef PCI_DEBUG + printf("Device %d is PCI Bridge\n",Device); +#endif + PCI_Config_Device(BusDevFunc, 2); + PCI_Config_Bridge(BusDevFunc); + break; + case 0x0100: /* PCI-PCI Bridge */ +#ifdef PCI_DEBUG + printf("Device %d is SCSI Controller\n",Device); +#endif + PCI_Config_SCSI_contrl(BusDevFunc); + break; + + case 0x0300: /* VGA Display controller */ + case 0x0001: /* VGA Display controller (pre PCI rev 2.0)*/ +#ifdef PCI_DEBUG + printf("Device %d is VGA\n",Device); +#endif + PCI_Config_VGA_contrl(BusDevFunc); + break; + + default: +#ifdef PCI_DEBUG + printf("Device %d is a 0x%04X\n",Device,PCI_Read_CFG_Reg(BusDevFunc, PCICLASSCODE, 2)); +#endif +/* PCI_Config_Device(BusDevFunc, 6); */ + } + } + else + { +#ifdef DEBUG + printf("Device %d not present\n",Device); +#endif + } + } +#endif + +} + + +/*----------------------------------------------------------------------- +| Subroutine: PCI_Config_Device +| +| Description: Configure a PCI device by examining its I/O and memory +| address space needs and allocating address space to it by +| programming the address decoders in the Base Address Registers. +| +| Inputs: +| BusDevFunc Bus+Device+Function number +| NumBaseAddr Number of base address registers to +| configure +| Return value: +| None ++----------------------------------------------------------------------*/ +void PCI_Config_Device(int BusDevFunc, int NumBaseAddr) +{ + int AddrSlot, i; + unsigned long AddrDesc, AddrProg, Min_Gnt_Val, int_line; + + for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++) + { + PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 0xFFFFFFFF,4); + + AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 4); + + if (AddrDesc == 0) /* unimplemented, stop looking */ + continue; /* 01/04/99 MCG */ + +#ifdef PCI_DEBUG + printf("Read Base Addr Reg %d = 0x%08lx\n",AddrSlot,AddrDesc); +#endif + + if ((AddrDesc & 1) == 0) /* Memory */ + { + AddrDesc &= 0xFFFFFFF0; + + for (i = 0; (AddrDesc & 1) != 1; i++) + AddrDesc = AddrDesc >> 1; + + AddrDesc = 1 << i; + + if ((unsigned long)AddrDesc < 4096) + AddrDesc = 4096; +#ifdef PCI_DEBUG + printf(" PCI Memory space = 0x%lx bytes \n",AddrDesc); +#endif + for (AddrProg = MIN_PCI_MEMADDR1; AddrProg < LowestMemAddr1; AddrProg += AddrDesc); + + PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4); + LowestMemAddr1 = AddrProg + AddrDesc; + } + else /* I/O */ + { + AddrDesc &= 0xFFFFFFFC; + + for (i = 0; (AddrDesc & 1) != 1; i++) + AddrDesc = AddrDesc >> 1; + + AddrDesc = 1 << i; +#ifdef PCI_DEBUG + printf(" PCI I/O space = 0x%lx bytes \n",AddrDesc); +#endif + for (AddrProg = MIN_PCI_PCI_IOADDR2; AddrProg < LowestIOAddr; AddrProg += AddrDesc); + + PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4); + LowestIOAddr = AddrProg + AddrDesc; + } + + } + + Min_Gnt_Val = 0x80; + PCI_Write_CFG_Reg(BusDevFunc, PCILATENCYTIM, Min_Gnt_Val, 1); + + /* + * Write pci interrupt line register (cpci405 specific) + */ + switch ((BusDevFunc >> 11) & 0x03) + { + case 0: + int_line = 27 + 2; + break; + case 1: + int_line = 27 + 3; + break; + case 2: + int_line = 27 + 0; + break; + case 3: + int_line = 27 + 1; + break; + } + PCI_Write_CFG_Reg(BusDevFunc, PCIINTLINE, int_line, 1); + + /* + * Enable i/o space, memory space and master on this device + */ + PCI_Write_CFG_Reg(BusDevFunc, PCICMD, 7, 2); + +} + +/*----------------------------------------------------------------------- +| Subroutine: PCI_Config_VGA_Device +| +| Description: Configure a PCI VGA device by examining its I/O and memory +| address space needs and allocating address space to it by +| programming the address decoders in the Base Address Registers. +| +| Inputs: +| BusDevFunc Bus+Device+Function number +| NumBaseAddr Number of base address registers to +| configure +| Return value: +| None ++----------------------------------------------------------------------*/ +void PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr) +{ + int AddrSlot, i; + unsigned long AddrDesc, AddrProg, Min_Gnt_Val; + + for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++) + { + PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 0xFFFFFFFF,4); + + AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 4); + + if (AddrDesc == 0) /* unimplemented, stop looking */ + continue; /* 01/04/99 MCG */ + +#ifdef PCI_DEBUG + printf("VGA Device Read Base Addr Reg %d = 0x%08lx\n",AddrSlot,AddrDesc); +#endif + + if ((AddrDesc & 1) == 0) /* Memory */ + { + AddrDesc &= 0xFFFFFFF0; + + for (i = 0; (AddrDesc & 1) != 1; i++) + AddrDesc = AddrDesc >> 1; + + AddrDesc = 1 << i; + + if ((unsigned long)AddrDesc < 4096) + AddrDesc = 4096; +#ifdef PCI_DEBUG + printf(" PCI Memory space = 0x%lx bytes \n",AddrDesc); +#endif + for (AddrProg = MIN_PCI_MEMADDR2; AddrProg < LowestMemAddr2; AddrProg += AddrDesc); + + PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4); + LowestMemAddr2 = AddrProg + AddrDesc; + } + else /* I/O */ + { + AddrDesc &= 0xFFFFFFFC; + + for (i = 0; (AddrDesc & 1) != 1; i++) + AddrDesc = AddrDesc >> 1; + + AddrDesc = 1 << i; +#ifdef PCI_DEBUG + printf(" PCI I/O space = 0x%lx bytes \n",AddrDesc); +#endif + for (AddrProg = MIN_PCI_PCI_IOADDR2; AddrProg < LowestIOAddr; AddrProg ++= AddrDesc); + + PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4); + LowestIOAddr = AddrProg + AddrDesc; + } + + } + + Min_Gnt_Val = 0x80; + PCI_Write_CFG_Reg(BusDevFunc, PCILATENCYTIM, Min_Gnt_Val, 1); +} + +/*----------------------------------------------------------------------- +| +| Subroutine: PCI_Config_Bridge +| +| Prototype: void PCI_Config_Bridge(int BusDevFunc) +| +| Description: Configure a PCI-PCI bridge +| +| Inputs: +| BusDevFunc Bus+Device+Function number +| +| Return value: +| None +| ++----------------------------------------------------------------------*/ +void PCI_Config_Bridge(int BusDevFunc) +{ + int SecondaryBus; + int PrimaryBus; + int CommandReg_Val; + int InitialLowestIOAddr, InitialLowestMemAddr; + int IOBase, MemBase; + int IOLimit, MemLimit; + + InitialLowestIOAddr = LowestIOAddr; + InitialLowestMemAddr = LowestMemAddr1; + + CommandReg_Val = (unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCICMD, 2); + + /* Configure bridge's base address registers */ + + PCI_Config_Device(BusDevFunc, 2); + + if ( LowestIOAddr > InitialLowestIOAddr ) /* bridge uses IO space? */ + CommandReg_Val |= 0x01; /* enable I/O Space */ + + if ( LowestMemAddr1 > InitialLowestMemAddr ) /* bridge uses memory space? */ + CommandReg_Val |= 0x02; /* enable Memory Space */ + + PrimaryBus = (BusDevFunc >> 16) & 0xFF; + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_PRIMARYBUS, PrimaryBus, 1); + + SecondaryBus = ++MaxBusNum; + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SECONDARYBUS, SecondaryBus, 1); + + /* Start with max. possible value for subordinate bus number */ + /* Later, after any additional child busses are found, we'll update this */ + + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, 0xFF, 1); + + /* IO Base must be on 4Kb boundary. Adjust if needed */ + + if ((LowestIOAddr % 4096) != 0) + LowestIOAddr += 4096 - (LowestIOAddr % 4096); + + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOBASE, (LowestIOAddr>>8) & 0xF0, 1); + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOBASEUPPER16, (LowestIOAddr>>16) & 0xFFFF, 2); + + IOBase = LowestIOAddr; + + /* Mem Base must be on 1 MB boundary. adjust if needed */ + if ((LowestMemAddr1 % 0x100000) != 0) + LowestMemAddr1 += 0x100000 - (LowestMemAddr1 % 0x100000); + + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_MEMBASE, (LowestMemAddr1>>16) & 0xFFF0, 2); + MemBase = LowestMemAddr1; + + PCI_Scan(SecondaryBus); + + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, MaxBusNum, 1); + + IOLimit = LowestIOAddr; + if (LowestIOAddr > IOBase) /* IO space used on secondary bus? */ + { + CommandReg_Val |= 0x01; /* enable IO Space */ + IOLimit--; /* IOLimit is highest used address */ + } + + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOLIMIT, ((IOLimit)>>8) & 0xF0, 1); + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOLIMITUPPER16, ((IOLimit)>>16) & 0xFFFF, 2); + + /* IOLIMIT is the starting address of a 4K block forwarded by the bridge. */ + /* Round LowestIOAddr up to the next 4K boundary if IO space is enabled. */ + + if ((CommandReg_Val & 0x01) == 0x01) + LowestIOAddr = (IOLimit | 0xFFF) + 1; + + MemLimit = LowestMemAddr1; + if ( LowestMemAddr1 > MemBase ) /* mem. space is used on secondary bus? */ + { + CommandReg_Val |= 0x02; /* enable Memory Space */ + MemLimit--; /* MemLimit is highest used address */ + } + + PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_MEMLIMIT, ((MemLimit)>>16) & 0xFFF0, 2); + + /* MEMLIMIT is the starting address of a 1M block forwarded by the bridge. */ + /* Round LowestMemAddr up to the next 1M boundary if Memory space is enabled. */ + + if ( (CommandReg_Val & 0x02) == 0x02 ) + LowestMemAddr1 = (MemLimit | 0xFFFFF) + 1; + + /* Enable Bus Master on secondary bus */ + CommandReg_Val |= 0x04; + + PCI_Write_CFG_Reg(BusDevFunc, PCICMD, CommandReg_Val, 2); + +} + +/*----------------------------------------------------------------------- +| Subroutine: PCI_Find_Device +| +| Prototype: int PCI_Find_Device(hword VendorID, hword DeviceID); +| +| Description: +| Locate a PCI device by vendor and device number +| +| Inputs: +| VendorID Value of the device's Vendor ID field +| DeviceID Value of the device's Device ID field +| +| Return value: +| < 0 Device not found +| (int) PCI Bus+Device+Function number ++----------------------------------------------------------------------*/ +int PCI_Find_Device(unsigned short VendorID, unsigned short DeviceID) +{ + int Device; + int BusDevFunc; + int BusNum; + int Funct; + + for (BusNum = MaxBusNum; BusNum >= 0; BusNum--) + for (Device = 0; Device < MAX_PCI_DEVICES; Device++) + { + for(Funct=0;FunctheaderType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1); + + if (pD->headerType & 0x01) /* PCI-to-PCI bridge */ + { + pB->vendorId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2); + pB->deviceId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2); + pB->command = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2); + pB->status = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_STATUS, 2); + pB->revisionId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1); + pB->progIf = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PROGRAMMING_IF, 1); + pB->subClass = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBCLASS, 1); + pB->classCode = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CLASS, 1); + pB->cacheLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CACHE_LINE_SIZE, 1); + pB->latency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, 1); + pB->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1); + pB->bist = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BIST, 1); + pB->base0 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_0, 4); + pB->base1 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_1, 4); + pB->priBus = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRIMARY_BUS, 1); + pB->secBus = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SECONDARY_BUS, 1); + pB->subBus = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBORDINATE_BUS, 1); + pB->secLatency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SEC_LATENCY, 1); + pB->ioBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_BASE, 1); + pB->ioLimit = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_LIMIT, 1); + pB->secStatus = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SEC_STATUS, 2); + pB->memBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MEM_BASE, 2); + pB->memLimit = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MEM_LIMIT, 2); + pB->preBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_BASE, 2); + pB->preLimit = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_LIMIT, 2); + pB->preBaseUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_BASE_U, 4); + pB->preLimitUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_LIMIT_U, 4); + pB->ioBaseUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_BASE_U, 2); + pB->ioLimitUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_LIMIT_U, 2); + pB->romBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_ROM_BASE, 4); + pB->intLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRG_INT_LINE, 1); + pB->intPin = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRG_INT_PIN, 1); + pB->control = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRIDGE_CONTROL, 2); + pciBheaderPrint(pB); + } + else /* PCI device */ + { + pD->vendorId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2); + pD->deviceId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2); + pD->command = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2); + pD->status = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_STATUS, 1); + pD->revisionId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1); + pD->progIf = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PROGRAMMING_IF, 1); + pD->subClass = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBCLASS, 1); + pD->classCode = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CLASS, 1); + pD->cacheLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CACHE_LINE_SIZE, 1); + pD->latency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, 1); + pD->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1); + pD->bist = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BIST, 1); + pD->base0 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_0, 4); + pD->base1 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_1, 4); + pD->base2 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_2, 4); + pD->base3 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_3, 4); + pD->base4 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_4, 4); + pD->base5 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_5, 4); + pD->cis = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CIS, 4); + pD->subVendorId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_VENDER_ID, 2); + pD->subSystemId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_SYSTEM_ID, 2); + pD->romBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 4); + pD->intLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_LINE, 1); + pD->intPin = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_PIN, 1); + pD->minGrant = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MIN_GRANT, 1); + pD->maxLatency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MAX_LATENCY, 1); + pciDheaderPrint(pD); + } +} + +/******************************************************************************* +* +* pciDheaderPrint - print a PCI device header +* +* This routine prints a PCI device header. +* +*/ +void +pciDheaderPrint(PCI_HEADER_DEVICE * pD) +{ + printf (" vendor ID = 0x%.4x\n", (ushort)pD->vendorId); + printf (" device ID = 0x%.4x\n", (ushort)pD->deviceId); + printf (" command register = 0x%.4x\n", (ushort)pD->command); + printf (" status register = 0x%.4x\n", (ushort)pD->status); + printf (" revision ID = 0x%.2x\n", (uchar)pD->revisionId); + printf (" class code = 0x%.2x\n", (uchar)pD->classCode); + printf (" sub class code = 0x%.2x\n", (uchar)pD->subClass); + printf (" programming interface = 0x%.2x\n", (uchar)pD->progIf); + printf (" cache line = 0x%.2x\n", (uchar)pD->cacheLine); + printf (" latency time = 0x%.2x\n", (uchar)pD->latency); + printf (" header type = 0x%.2x\n", (uchar)pD->headerType); + printf (" BIST = 0x%.2x\n", (uchar)pD->bist); + printf (" base address 0 = 0x%.8x\n", pD->base0); + printf (" base address 1 = 0x%.8x\n", pD->base1); + printf (" base address 2 = 0x%.8x\n", pD->base2); + printf (" base address 3 = 0x%.8x\n", pD->base3); + printf (" base address 4 = 0x%.8x\n", pD->base4); + printf (" base address 5 = 0x%.8x\n", pD->base5); + printf (" cardBus CIS pointer = 0x%.8x\n", pD->cis); + printf (" sub system vendor ID = 0x%.4x\n", (ushort)pD->subVendorId); + printf (" sub system ID = 0x%.4x\n", (ushort)pD->subSystemId); + printf (" expansion ROM base address = 0x%.8x\n", pD->romBase); + printf (" interrupt line = 0x%.2x\n", (uchar)pD->intLine); + printf (" interrupt pin = 0x%.2x\n", (uchar)pD->intPin); + printf (" min Grant = 0x%.2x\n", (uchar)pD->minGrant); + printf (" max Latency = 0x%.2x\n", (uchar)pD->maxLatency); +} + +/******************************************************************************* +* +* pciBheaderPrint - print a PCI-to-PCI bridge header +* +* This routine prints a PCI-to-PCI bridge header. +* +*/ +void +pciBheaderPrint(PCI_HEADER_BRIDGE * pB) +{ + printf (" vendor ID = 0x%.4x\n", (ushort)pB->vendorId); + printf (" device ID = 0x%.4x\n", (ushort)pB->deviceId); + printf (" command register = 0x%.4x\n", (ushort)pB->command); + printf (" status register = 0x%.4x\n", (ushort)pB->status); + printf (" revision ID = 0x%.2x\n", (uchar)pB->revisionId); + printf (" class code = 0x%.2x\n", (uchar)pB->classCode); + printf (" sub class code = 0x%.2x\n", (uchar)pB->subClass); + printf (" programming interface = 0x%.2x\n", (uchar)pB->progIf); + printf (" cache line = 0x%.2x\n", (uchar)pB->cacheLine); + printf (" latency time = 0x%.2x\n", (uchar)pB->latency); + printf (" header type = 0x%.2x\n", (uchar)pB->headerType); + printf (" BIST = 0x%.2x\n", (uchar)pB->bist); + printf (" base address 0 = 0x%.8x\n", pB->base0); + printf (" base address 1 = 0x%.8x\n", pB->base1); + printf (" primary bus number = 0x%.2x\n", (uchar)pB->priBus); + printf (" secondary bus number = 0x%.2x\n", (uchar)pB->secBus); + printf (" subordinate bus number = 0x%.2x\n", (uchar)pB->subBus); + printf (" secondary latency timer = 0x%.2x\n", (uchar)pB->secLatency); + printf (" IO base = 0x%.2x\n", (uchar)pB->ioBase); + printf (" IO limit = 0x%.2x\n", (uchar)pB->ioLimit); + printf (" secondary status = 0x%.4x\n", (ushort)pB->secStatus); + printf (" memory base = 0x%.4x\n", (ushort)pB->memBase); + printf (" memory limit = 0x%.4x\n", (ushort)pB->memLimit); + printf (" prefetch memory base = 0x%.4x\n", (ushort)pB->preBase); + printf (" prefetch memory limit = 0x%.4x\n", (ushort)pB->preLimit); + printf (" prefetch memory base upper = 0x%.8x\n", pB->preBaseUpper); + printf (" prefetch memory limit upper = 0x%.8x\n", pB->preLimitUpper); + printf (" IO base upper 16 bits = 0x%.4x\n", (ushort)pB->ioBaseUpper); + printf (" IO limit upper 16 bits = 0x%.4x\n", (ushort)pB->ioLimitUpper); + printf (" expansion ROM base address = 0x%.8x\n", pB->romBase); + printf (" interrupt line = 0x%.2x\n", (uchar)pB->intLine); + printf (" interrupt pin = 0x%.2x\n", (uchar)pB->intPin); + printf (" bridge control = 0x%.4x\n", (ushort)pB->control); +} + + + + +/******************************************************************************* +* +* pciGetHeader0 - gets the header of the specified PCI device +* +* only header 0 . +* +*/ + +int pciGetHeader0(PCI_HEADER_DEVICE * pD,int BusDevFunc) +{ + pD->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1); + + if ((pD->headerType&0x7F)!=0) /* Not a Header 0 type */ + return FALSE; + else /* PCI device */ + { + pD->vendorId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2); + pD->deviceId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2); + pD->command = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2); + pD->status = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_STATUS, 1); + pD->revisionId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1); + pD->progIf = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PROGRAMMING_IF, 1); + pD->subClass = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBCLASS, 1); + pD->classCode = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CLASS, 1); + pD->cacheLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CACHE_LINE_SIZE, 1); + pD->latency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, 1); + pD->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1); + pD->bist = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BIST, 1); + pD->base0 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_0, 4); + pD->base1 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_1, 4); + pD->base2 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_2, 4); + pD->base3 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_3, 4); + pD->base4 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_4, 4); + pD->base5 = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_5, 4); + pD->cis = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CIS, 4); + pD->subVendorId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_VENDER_ID, 2); + pD->subSystemId = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_SYSTEM_ID, 2); + pD->romBase = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 4); + pD->intLine = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_LINE, 1); + pD->intPin = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_PIN, 1); + pD->minGrant = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MIN_GRANT, 1); + pD->maxLatency = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MAX_LATENCY, 1); + } + return TRUE; +} + +/******************************************************************************* +* +* pciGetResource - gets the Resource information of the specified PCI device +* +* +* +*/ +int pciGetResource(PCI_RESOURCE_DESC * pR) +{ + PCI_HEADER_DEVICE headerDevice; + int basereg, i; + unsigned long AddrDesc; + + + if(pciGetHeader0(&headerDevice,pR->BusDevFunc)==FALSE) + return FALSE; /* no header 0 type */ + /* fill in read only fields */ + pR->vendorId = headerDevice.vendorId; + pR->deviceId = headerDevice.deviceId; + pR->revisionId = headerDevice.revisionId; + pR->classCode = headerDevice.classCode; + pR->subClass = headerDevice.subClass; + pR->progIf = headerDevice.progIf; + pR->intLine = headerDevice.intLine; + pR->intPin = headerDevice.intPin; + pR->headerType = headerDevice.headerType; + pR->pciInt = 0; /* no Interrupt as default */ + /* calculate the PCI Interrupt if any.. */ + if(pR->intPin!=0) + { + /* interrupts are routed as follows: + - Device 6, INTA# = INTA# + - Device 7, INTA# = INTB# + - Device 8, INTA# = INTC# + - Device 9, INTA# = INTD# + - Device A, INTA# = INTA# + - Device 0 must be INTA# = INTC# */ + i=(pR->BusDevFunc >> 11) & 0x1F; /* max 32 devices (Bus nr not yet implemented) */ + i=i%4; /* dev0 and INTA# = INTC# */ + i+=1; /* Adjust it (first step) */ + i+=pR->intPin; + pR->pciInt=(char)((i%4)+1); /* 2nd step */ + } + /* try to get memory or io descriptions */ + for (basereg = 0; basereg < MAX_PCI_BASE_REG; basereg++) + { + pR->size[basereg]=0; /* delete size */ + pR->attr[basereg]=DESC_IS_NOT_VALID; + PCI_Write_CFG_Reg(pR->BusDevFunc, PCIBASEADDR0 + (4*basereg), 0xFFFFFFFF,4); + AddrDesc = PCI_Read_CFG_Reg(pR->BusDevFunc, PCIBASEADDR0 + (4*basereg), 4); + if (AddrDesc == 0) /* unimplemented, stop looking */ + continue; + if ((AddrDesc&0x3)==0x1) /* is IO */ + { + pR->attr[basereg]=DESC_IS_IO; + /* determine size, all bytes which are don't care are 0 */ + AddrDesc&=0xFFFFFFFC; /* delete Atributes */ + AddrDesc=~AddrDesc; + AddrDesc&=0x0000FFFF; /* Mask unused bits */ + pR->size[basereg]=AddrDesc+1; /* size */ + } + else + { + pR->attr[basereg]=DESC_IS_MEM; + switch((AddrDesc&0x6)>>1) + { + case 0x1: + pR->attr[basereg]|=DESC_IS_LOWMEM; /* locate it below 1M */ + break; + case 0x2: + pR->attr[basereg]|=DESC_IS_64BIT; /* dual Address.. increment base reg later */ + break; + case 0x3: + pR->attr[basereg]=DESC_IS_NOT_VALID; /* Error */ + break; + } /* case */ + if((AddrDesc&0x8)==0x8) /* is prefetchable */ + pR->attr[basereg]|=DESC_IS_PREFETCH; + /* 64Bit addressing not implemented */ + if((pR->attr[basereg]&DESC_IS_64BIT)==DESC_IS_64BIT) + { + basereg++; + if(baseregsize[basereg]=0; /* delete size */ + pR->attr[basereg]=DESC_IS_NOT_VALID; + } + continue; + } /* if DESC_IS_64BIT */ + /* determine size */ + AddrDesc&=0xFFFFFFF0;/* delete attributes */ + AddrDesc=~AddrDesc; + pR->size[basereg]=AddrDesc+1; /* size */ + } /* else */ + } /* for basereg */ + return TRUE; +} + +#if 0 +/************************************************************************************* +* pcishowrees +*/ +void pciShowRes(PCI_RESOURCE_DESC *pD) +{ + int i, match; + printf("%02d:%02d:%02d ",(char)(pD->BusDevFunc>>16)&0xFF, + (char)(pD->BusDevFunc>>11)&0x1F,(char)(pD->BusDevFunc>>8)&0x3); + + /* search memory desc */ + match=0; + for(i=0;iattr[i]&DESC_IS_IO)==DESC_IS_IO) + { + printf("%4lX ",pD->size[i]); + match=1; + } + } + if(match==0) + printf(" "); + match=0; + for(i=0;iattr[i]&DESC_IS_MEM)==DESC_IS_MEM) + { + printf("%8lX ",pD->size[i]); + match=1; + } + } + if(match==0) + printf(" "); + if(pD->intPin==0) + printf(" "); + else + printf("INT%c# ",(pD->pciInt + 'A')-1); + switch (pD->classCode) + { + case 0x00: + switch(pD->subClass) + { + case 0: printf("not VGA"); break; + case 1: printf("VGA"); break; + default: printf("unknown"); break; + } + printf("Pre Class: "); + break; + case 0x01: + switch(pD->subClass) + { + case 0x00: printf("SCSI "); break; + case 0x01: printf("IDE "); break; + case 0x02: printf("Floppy "); break; + case 0x03: printf("IPI "); break; + case 0x04: printf("RAID "); break; + case 0x88: printf("other "); break; + default: printf("unknown "); break; + } + printf("Mass Storage "); + break; + case 0x02: + switch(pD->subClass) + { + case 0x00: printf("Ethernet"); break; + case 0x01: printf("Token Ring"); break; + case 0x02: printf("FDDI"); break; + case 0x03: printf("ATM"); break; + case 0x80: printf("other"); break; + default: printf("unknown"); break; + } + printf(" Network Controller "); + break; + case 0x03: + switch(pD->subClass) + { + case 0x00: printf("%s",((pD->progIf&0x1)==0x1)? "8514 comp":"VGA"); break; + case 0x01: printf("XGA"); break; + case 0x80: printf("other"); break; + default: printf("unknown"); break; + } + printf(" Display Cont. "); + break; + case 0x04: + switch(pD->subClass) + { + case 0x00: printf("Video"); break; + case 0x01: printf("Audio"); break; + case 0x80: printf("other"); break; + default: printf("unknown"); break; + } + printf(" Multimedia Device "); + break; + case 0x05: + switch(pD->subClass) + { + case 0x00: printf("RAM"); break; + case 0x01: printf("Flash"); break; + case 0x80: printf("other"); break; + default: printf("unknown"); break; + } + printf(" Memory Device "); + break; + case 0x06: + switch(pD->subClass) + { + case 0x00: printf("HostBridge"); break; + case 0x01: printf("ISA"); break; + case 0x02: printf("EISA"); break; + case 0x03: printf("MCA"); break; + case 0x04: printf("PCI-PCI"); break; + case 0x05: printf("PCMCIA"); break; + case 0x06: printf("NuBus"); break; + case 0x07: printf("CardBus"); break; + case 0x80: printf("other"); break; + default: printf("unknown"); break; + } + printf(" Bridge "); + break; + case 0x07: + switch(pD->subClass) + { + case 0x00: + switch(pD->progIf) + { + case 0: printf("Generic XT Serial Controller ");break; + case 1: printf("16450 Serial Controller ");break; + case 2: printf("16550 Serial Controller ");break; + default: printf("unknown Serial Controller ");break; + } + break; + case 0x01: + switch(pD->progIf) + { + case 0: printf("Paralell Port ");break; + case 1: printf("Bidirectional Paralell Port ");break; + case 2: printf("ECP 1.X Paralell Port ");break; + default: printf("unknown Paralall Port ");break; + } + break; + case 0x80: printf("other Simple Communications Controller "); break; + default: printf("unknown Simple Communications Controller "); break; + } + break; + case 0x08: + switch(pD->subClass) + { + case 0x00: + switch(pD->progIf) + { + case 0: printf("Generic 8259 PIC ");break; + case 1: printf("ISA PIC ");break; + case 2: printf("EISA PIC ");break; + default: printf("unknown PIC ");break; + } + break; + case 0x01: + switch(pD->progIf) + { + case 0: printf("Generic 8237 DMA ");break; + case 1: printf("ISA DMA ");break; + case 2: printf("EISA DMA ");break; + default: printf("unknown DMA ");break; + } + break; + case 0x02: + switch(pD->progIf) + { + case 0: printf("Generic 8254 Timer ");break; + case 1: printf("ISA Timer ");break; + case 2: printf("EISA Timer ");break; + default: printf("unknown Timer ");break; + } + break; + case 0x03: + switch(pD->progIf) + { + case 0: printf("Generic RTC ");break; + case 1: printf("ISA RTC ");break; + default: printf("unknown RTC ");break; + } + break; + case 0x80: printf("other Generic System Peripherals "); break; + default: printf("unknown Generic System Peripherals "); break; + } + break; + case 0x09: + switch(pD->subClass) + { + case 0x00: printf("Keyboard Controller "); break; + case 0x01: printf("Digitizer "); break; + case 0x02: printf("Mouse "); break; + case 0x80: printf("other Input Device "); break; + default: printf("unknown Input Device "); break; + } + break; + case 0x0A: + switch(pD->subClass) + { + case 0x00: printf("Generic Docking Station "); break; + case 0x80: printf("other Docking Device "); break; + default: printf("unknown Docking Device "); break; + } + break; + case 0x0B: + switch(pD->subClass) + { + case 0x00: printf("386 "); break; + case 0x01: printf("486 "); break; + case 0x02: printf("Pentium "); break; + case 0x10: printf("Alpha "); break; + case 0x20: printf("PowerPC "); break; + case 0x40: printf("Co-"); break; + default: printf("unknown "); break; + } + printf("Processor "); + break; + case 0x0C: + switch(pD->subClass) + { + case 0x00: printf("FireWire "); break; + case 0x01: printf("ACCESS.bus "); break; + case 0x02: printf("SSA "); break; + case 0x03: printf("USB "); break; + case 0x04: printf("Fibre Channel "); break; + default: printf("unknown Serial Bus "); break; + } + break; + } /* Switch */ + printf("\n"); +} + +#endif + +#if 0 +/************************************************************************************** +* pciScanforDevices +*/ + +void pciScanForDevices(int BusNum) +{ + + PCI_RESOURCE_DESC resourcedesc; + int Device,Function,BusDevFunc; + unsigned short vendor_id,vendor_id2; + + printf("PCI IO Memory IRQ Device\n"); + /* 00:00:00 1234 12345678 INTA# DD */ + for (Device = 1; Device < MAX_PCI_DEVICES; Device++) + { + BusDevFunc = (BusNum << 16) | (Device << 11); /* scan only function 0 */ + vendor_id = PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2); + if (vendor_id != 0xFFFF) + { + + for(Function=0;Function PCI address 0x80000000-0x9FFFFFFF + * Use byte reversed out routines to handle endianess. + ***********************************************************************/ +#define PCI_M0_LOCAL_ADDR 0x80000000 +#define PCI_M0_PCI_LOW_ADDR 0x80000000 +#define PCI_M0_PCI_HIGH_ADDR 0x00000000 +#define PCI_M0_MASK_ATTRIB 0xE0000001 /* no prefetching, and enable region */ +/************************************************************************** + * Map one 512 MB range of PLB/processor addresses to PCI memory space. + * PLB address 0xA0000000-0xBFFFFFFF ==> PCI address 0x00000000-0x1FFFFFFF + * This space is for the VGA card. + **************************************************************************/ +#define PCI_M1_LOCAL_ADDR 0xA0000000 +#define PCI_M1_PCI_LOW_ADDR 0x00000000 +#define PCI_M1_PCI_HIGH_ADDR 0x00000000 +#define PCI_M1_MASK_ATTRIB 0xE0000001 /* no prefetching, and enable region */ +/*************************************************************************** + * PMM2 is not used. Initialize them to zero. + *****************************************************************************/ +#define PCI_M2_LOCAL_ADDR 0x00000000 +#define PCI_M2_PCI_LOW_ADDR 0x00000000 +#define PCI_M2_PCI_HIGH_ADDR 0x00000000 +#define PCI_M2_MASK_ATTRIB 0x00000000 /* not enabled */ + +typedef struct pciHeaderDevice +{ + short vendorId; /* vendor ID */ + short deviceId; /* device ID */ + short command; /* command register */ + short status; /* status register */ + char revisionId; /* revision ID */ + char classCode; /* class code */ + char subClass; /* sub class code */ + char progIf; /* programming interface */ + char cacheLine; /* cache line */ + char latency; /* latency time */ + char headerType; /* header type */ + char bist; /* BIST */ + int base0; /* base address 0 */ + int base1; /* base address 1 */ + int base2; /* base address 2 */ + int base3; /* base address 3 */ + int base4; /* base address 4 */ + int base5; /* base address 5 */ + int cis; /* cardBus CIS pointer */ + short subVendorId; /* sub system vendor ID */ + short subSystemId; /* sub system ID */ + int romBase; /* expansion ROM base address */ + int reserved0; /* reserved */ + int reserved1; /* reserved */ + char intLine; /* interrupt line */ + char intPin; /* interrupt pin */ + char minGrant; /* min Grant */ + char maxLatency; /* max Latency */ +} PCI_HEADER_DEVICE; + +typedef struct pciHeaderBridge +{ + short vendorId; /* vendor ID */ + short deviceId; /* device ID */ + short command; /* command register */ + short status; /* status register */ + char revisionId; /* revision ID */ + char classCode; /* class code */ + char subClass; /* sub class code */ + char progIf; /* programming interface */ + char cacheLine; /* cache line */ + char latency; /* latency time */ + char headerType; /* header type */ + char bist; /* BIST */ + int base0; /* base address 0 */ + int base1; /* base address 1 */ + char priBus; /* primary bus number */ + char secBus; /* secondary bus number */ + char subBus; /* subordinate bus number */ + char secLatency; /* secondary latency timer */ + char ioBase; /* IO base */ + char ioLimit; /* IO limit */ + short secStatus; /* secondary status */ + short memBase; /* memory base */ + short memLimit; /* memory limit */ + short preBase; /* prefetchable memory base */ + short preLimit; /* prefetchable memory limit */ + int preBaseUpper; /* prefetchable memory base upper 32 bits */ + int preLimitUpper; /* prefetchable memory base upper 32 bits */ + short ioBaseUpper; /* IO base upper 16 bits */ + short ioLimitUpper; /* IO limit upper 16 bits */ + int reserved; /* reserved */ + int romBase; /* expansion ROM base address */ + char intLine; /* interrupt line */ + char intPin; /* interrupt pin */ + short control; /* bridge control */ + } PCI_HEADER_BRIDGE; + + +typedef struct pciRecourceDesc +{ + unsigned long BusDevFunc; /* location of the device */ + short vendorId; /* vendor ID */ + short deviceId; /* device ID */ + char revisionId; /* revision ID */ + char classCode; /* class code */ + char subClass; /* sub class code */ + char progIf; /* programming interface */ + char headerType; /* header type */ + unsigned long size[MAX_PCI_BASE_REG]; /* memory sizes */ + char attr[MAX_PCI_BASE_REG]; /* memory attributes */ + char intLine; /* interrupt line */ + char intPin; /* interrupt pin */ + char pciInt; /* Pci Interrupt Line ( 0 = no, 1 = A...)*/ +} PCI_RESOURCE_DESC; + + +/* table for PCI Initialization */ + +typedef struct { + const int index; + const unsigned long val; + const int with; +} PCI_CFG_TABLE; + + +typedef struct { + int index; /* address */ + unsigned long val; /* value */ + int width; /* data size */ +}PCI_FCN_CFG_TABLE; + +typedef struct { + unsigned short vendorID; /* Vendor ID */ + unsigned short deviceID; /* Device ID */ + unsigned char revision; /* Device ID */ + unsigned char func; /* Function number */ + PCI_FCN_CFG_TABLE fcntable[10]; +}PCI_DEV_CFG_TABLE; + + +unsigned long PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width); +int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned long Value, int Width); +void PCI_Scan(int BusNum); +void PCI_Config_Device(int BusDevFunc, int NumBaseAddr); +void PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr); +void PCI_Config_Bridge(int BusDevFunc); +void PCI_Dump_Device(int BusDevFunc); +int PCI_Find_Device(unsigned short VendorID, unsigned short DeviceID); +void pciHeaderShow(int BusDevFunc); +void pciDheaderPrint(PCI_HEADER_DEVICE * pD); +void pciBheaderPrint(PCI_HEADER_BRIDGE * pB); +void PCI_Config_ISABridge(int BusDevFunc); +void PCI_Config_VGA_contrl(int BusDevFunc); + +void pciScanForDevices(int BusNum); +void pciShowRes(PCI_RESOURCE_DESC *pd); +int pciGetResource(PCI_RESOURCE_DESC * pR); +int pciGetHeader0(PCI_HEADER_DEVICE * pD,int BusDevFunc); + +/*************************************************************************** +* Defines PIIX4 Config Registers +****************************************************************************/ + +/* Function 0 ISA Bridge */ +#define PCI_CFG_PIIX4_IORT 0x4C /* 8 bit ISA Recovery Timer Reg (default 0x4D) */ +#define PCI_CFG_PIIX4_XBCS 0x4E /* 16 bit XBus Chip select reg (default 0x0003) */ +#define PCI_CFG_PIIX4_PIRQC 0x60 /* PCI IRQ Route Register 4 x 8bit (default )*/ +#define PCI_CFG_PIIX4_SERIRQ 0x64 +#define PCI_CFG_PIIX4_TOM 0x69 +#define PCI_CFG_PIIX4_MSTAT 0x6A +#define PCI_CFG_PIIX4_MBDMA 0x76 +#define PCI_CFG_PIIX4_APICBS 0x80 +#define PCI_CFG_PIIX4_DLC 0x82 +#define PCI_CFG_PIIX4_PDMACFG 0x90 +#define PCI_CFG_PIIX4_DDMABS 0x92 +#define PCI_CFG_PIIX4_GENCFG 0xB0 +#define PCI_CFG_PIIX4_RTCCFG 0xCB + +/* IO Addresses */ +#define PIIX4_ISA_DMA1_CH0BA 0x00 +#define PIIX4_ISA_DMA1_CH0CA 0x01 +#define PIIX4_ISA_DMA1_CH1BA 0x02 +#define PIIX4_ISA_DMA1_CH1CA 0x03 +#define PIIX4_ISA_DMA1_CH2BA 0x04 +#define PIIX4_ISA_DMA1_CH2CA 0x05 +#define PIIX4_ISA_DMA1_CH3BA 0x06 +#define PIIX4_ISA_DMA1_CH3CA 0x07 +#define PIIX4_ISA_DMA1_CMDST 0x08 +#define PIIX4_ISA_DMA1_REQ 0x09 +#define PIIX4_ISA_DMA1_WSBM 0x0A +#define PIIX4_ISA_DMA1_CH_MOD 0x0B +#define PIIX4_ISA_DMA1_CLR_PT 0x0C +#define PIIX4_ISA_DMA1_M_CLR 0x0D +#define PIIX4_ISA_DMA1_CLR_M 0x0E +#define PIIX4_ISA_DMA1_RWAMB 0x0F + +#define PIIX4_ISA_DMA2_CH0BA 0xC0 +#define PIIX4_ISA_DMA2_CH0CA 0xC1 +#define PIIX4_ISA_DMA2_CH1BA 0xC2 +#define PIIX4_ISA_DMA2_CH1CA 0xC3 +#define PIIX4_ISA_DMA2_CH2BA 0xC4 +#define PIIX4_ISA_DMA2_CH2CA 0xC5 +#define PIIX4_ISA_DMA2_CH3BA 0xC6 +#define PIIX4_ISA_DMA2_CH3CA 0xC7 +#define PIIX4_ISA_DMA2_CMDST 0xD0 +#define PIIX4_ISA_DMA2_REQ 0xD2 +#define PIIX4_ISA_DMA2_WSBM 0xD4 +#define PIIX4_ISA_DMA2_CH_MOD 0xD6 +#define PIIX4_ISA_DMA2_CLR_PT 0xD8 +#define PIIX4_ISA_DMA2_M_CLR 0xDA +#define PIIX4_ISA_DMA2_CLR_M 0xDC +#define PIIX4_ISA_DMA2_RWAMB 0xDE + +#define PIIX4_ISA_INT1_ICW1 0x20 +#define PIIX4_ISA_INT1_OCW2 0x20 +#define PIIX4_ISA_INT1_OCW3 0x20 +#define PIIX4_ISA_INT1_ICW2 0x21 +#define PIIX4_ISA_INT1_ICW3 0x21 +#define PIIX4_ISA_INT1_ICW4 0x21 +#define PIIX4_ISA_INT1_OCW1 0x21 + +#define PIIX4_ISA_INT1_ELCR 0x4D0 + +#define PIIX4_ISA_INT2_ICW1 0xA0 +#define PIIX4_ISA_INT2_OCW2 0xA0 +#define PIIX4_ISA_INT2_OCW3 0xA0 +#define PIIX4_ISA_INT2_ICW2 0xA1 +#define PIIX4_ISA_INT2_ICW3 0xA1 +#define PIIX4_ISA_INT2_ICW4 0xA1 +#define PIIX4_ISA_INT2_OCW1 0xA1 +#define PIIX4_ISA_INT2_IMR 0xA1 /* read only */ + +#define PIIX4_ISA_INT2_ELCR 0x4D1 + +#define PIIX4_ISA_TMR0_CNT_ST 0x40 +#define PIIX4_ISA_TMR1_CNT_ST 0x41 +#define PIIX4_ISA_TMR2_CNT_ST 0x42 +#define PIIX4_ISA_TMR_TCW 0x43 + +#define PIIX4_ISA_RST_XBUS 0x60 + +#define PIIX4_ISA_NMI_CNT_ST 0x61 +#define PIIX4_ISA_NMI_ENABLE 0x70 + +#define PIIX4_ISA_RTC_INDEX 0x70 +#define PIIX4_ISA_RTC_DATA 0x71 +#define PIIX4_ISA_RTCEXT_IND 0x70 +#define PIIX4_ISA_RTCEXT_DATA 0x71 + +#define PIIX4_ISA_DMA1_CH2LPG 0x81 +#define PIIX4_ISA_DMA1_CH3LPG 0x82 +#define PIIX4_ISA_DMA1_CH1LPG 0x83 +#define PIIX4_ISA_DMA1_CH0LPG 0x87 +#define PIIX4_ISA_DMA2_CH2LPG 0x89 +#define PIIX4_ISA_DMA2_CH3LPG 0x8A +#define PIIX4_ISA_DMA2_CH1LPG 0x8B +#define PIIX4_ISA_DMA2_LPGRFR 0x8F + +#define PIIX4_ISA_PORT_92 0x92 + +#define PIIX4_ISA_APM_CONTRL 0xB2 +#define PIIX4_ISA_APM_STATUS 0xB3 + +#define PIIX4_ISA_COCPU_ERROR 0xF0 + +/* Function 1 IDE Controller */ +#define PCI_CFG_PIIX4_BMIBA 0x20 +#define PCI_CFG_PIIX4_IDETIM 0x40 +#define PCI_CFG_PIIX4_SIDETIM 0x44 +#define PCI_CFG_PIIX4_UDMACTL 0x48 +#define PCI_CFG_PIIX4_UDMATIM 0x4A + +/* Function 2 USB Controller */ +#define PCI_CFG_PIIX4_SBRNUM 0x60 +#define PCI_CFG_PIIX4_LEGSUP 0xC0 + +/* Function 3 Power Management */ +#define PCI_CFG_PIIX4_PMAB 0x40 +#define PCI_CFG_PIIX4_CNTA 0x44 +#define PCI_CFG_PIIX4_CNTB 0x48 +#define PCI_CFG_PIIX4_GPICTL 0x4C +#define PCI_CFG_PIIX4_DEVRESD 0x50 +#define PCI_CFG_PIIX4_DEVACTA 0x54 +#define PCI_CFG_PIIX4_DEVACTB 0x58 +#define PCI_CFG_PIIX4_DEVRESA 0x5C +#define PCI_CFG_PIIX4_DEVRESB 0x60 +#define PCI_CFG_PIIX4_DEVRESC 0x64 +#define PCI_CFG_PIIX4_DEVRESE 0x68 +#define PCI_CFG_PIIX4_DEVRESF 0x6C +#define PCI_CFG_PIIX4_DEVRESG 0x70 +#define PCI_CFG_PIIX4_DEVRESH 0x74 +#define PCI_CFG_PIIX4_DEVRESI 0x78 + + +#endif diff --git a/board/mpl/common/pci_parts.h b/board/mpl/common/pci_parts.h new file mode 100644 index 0000000..2be4141 --- /dev/null +++ b/board/mpl/common/pci_parts.h @@ -0,0 +1,131 @@ + /* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 _PCI_PARTS_H_ +#define _PCI_PARTS_H_ + + +/* Board specific file containing: + * - PCI Memory Mapping + * - PCI IO Mapping + * - PCI Interrupt Mapping + */ + +/* PIP405 PCI INT Routing: + * IRQ0 VECTOR + * PIXX4 IDSEL = AD16 INTA# 28 (Function 2 USB is INTD# = 31) + * VGA IDSEL = AD17 INTB# 29 + * SCSI IDSEL = AD18 INTC# 30 + * PC104 IDSEL0 = AD20 INTA# 28 + * PC104 IDSEL1 = AD21 INTB# 29 + * PC104 IDSEL2 = AD22 INTC# 30 + * PC104 IDSEL3 = AD23 INTD# 31 + * + * busdevfunc = EXXX XXXX BBBB BBBB DDDD DFFF RRRR RR00 + * ^ ^ ^ ^ ^ + * 31 23 15 10 7 + * E = Enabled + * B = Bussnumber + * D = Devicenumber (Device0 = AD10) + * F = Functionnumber + * R = Registernumber + * + * Device = (busdevfunc>>11) + 10 + * Vector = devicenumber % 4 + 28 + * + */ +#define PCI_DEV_NUMBER(x) (((x>>11) & 0x1f) + 10) +#define PCI_IRQ_VECTOR(x) (PCI_DEV_NUMBER(x) % 4) + 28 + + +/* PCI Device List for PIP405 */ + +/* Mapping: + * +-------------+------------+------------+--------------------------------+ + * ¦ PCI MemAddr | PCI IOAddr | Local Addr | Device / Function | + * +-------------+------------+------------+--------------------------------+ + * | 0x00000000 | | 0xA0000000 | ISA Memory (hard wired) | + * | 0x00FFFFFF | | 0xA0FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + * | | 0x00000000 | 0xE8000000 | ISA IO (hard wired) | + * | | 0x0000FFFF | 0xE800FFFF | | + * +-------------+------------+------------+--------------------------------+ + * | 0x80000000 | | 0x80000000 | VGA Controller Memory | + * | 0x80FFFFFF | | 0x80FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + * | 0x81000000 | | 0x81000000 | SCSI Controller Memory | + * | 0x81FFFFFF | | 0x81FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + */ + +static PCI_DEV_CFG_TABLE pcidevtbl[]={ +/* PIIX4 ISA Bridge Function 0 */ +{0x8086,0x7110, 0xff,0, { + {PCI_CFG_PIIX4_SERIRQ, 0xD0, 1},/* enable Continous SERIRQ Pin */ + {PCI_CFG_PIIX4_GENCFG, 0x00010000, 4},/* enable SERIRQs */ + {PCI_CFG_PIIX4_XBCS, 0x0080, 2}, /* disable all peri CS */ + {PCI_CFG_PIIX4_RTCCFG, 0x21, 1}, /* enable RTC */ + {0xFFFF, 0,0}} /* end of device table */ +}, +/* PIIX4 IDE Controller Function 1 */ +{0x8086,0x7111,0xff,1,{ + {PCI_CFG_COMMAND, 0x0001, 2},/* enable IO access */ + {PCI_CFG_PIIX4_IDETIM, 0x80008000, 4},/* enable Both IDE channels */ + {0xFFFF, 0,0}} /* end of device table */ +}, +/* PIIX4 USB Controller Function 2 */ +{0x8086,0x7112,0xff,2,{ + {PCI_CFG_DEV_INT_LINE, 31, 1},/* Int vector = 31 */ + {PCI_CFG_BASE_ADDRESS_4, 0x0000E001, 4},/* Set IO Address to 0xe000 to 0xe01F */ + {PCI_CFG_LATENCY_TIMER, 0x80, 1},/* Latency Timer 0x80 */ + {0xC0, 0x2000, 2}, /* Legacy support */ + {PCI_CFG_COMMAND, 0x0005, 2},/* enable IO access and Master */ + {0xFFFF, 0,0}} /* end of device table */ +}, +/* VGA Controller ct69000 (logical device 0) */ +{0x102C,0x00C0,0xff,0,{ + {PCI_CFG_BASE_ADDRESS_0, 0x80000000, 4},/* Frame buffer access */ + {PCI_CFG_EXPANSION_ROM, 0x00000000, 4},/* disable ROM */ + {PCI_CFG_DEV_INT_LINE, 29, 1},/* Int vector = 29 */ + {PCI_CFG_COMMAND, 0x0003, 2},/* enable IO access */ + {0xFFFF, 0,0}} /* end of device table */ +}, +/* Symbois 810 function 0 */ +{0x1000,0x0001,0xff,0,{ + {PCI_CFG_BASE_ADDRESS_0, 0x00001001, 4},/* IO Base address */ + {PCI_CFG_BASE_ADDRESS_1, 0x81000000, 4},/* Memory Base address */ + {PCI_CFG_DEV_INT_LINE, 30, 1},/* Int vector = 30 */ + {PCI_CFG_COMMAND, 0x0006, 2},/* enable Memory access and busmaster */ + {0xFFFF, 0,0}} /* end of device table */ +}, +/* Terminator */ +{0xffff,0xffff,0xff,0xff,{ + {0xFFFF, 0,0}} /* end of device table */ +} +}; +#endif /* _PCI_PARTS_H_ */ + + + + + diff --git a/board/mpl/common/sym53c8xx.c b/board/mpl/common/sym53c8xx.c new file mode 100644 index 0000000..77eb0e0 --- /dev/null +++ b/board/mpl/common/sym53c8xx.c @@ -0,0 +1,751 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch. + * + * 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 + * partly derived from + * linux/drivers/scsi/sym53c8xx.c + * + */ + +/* + * SCSI support based on the chip sym53C810. + */ + +#include +#include +#include +#include "pci.h" +#include +#include "sym53c8xx_defs.h" +#include + +#undef SYM53C8XX_DEBUG + +#ifdef SYM53C8XX_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX) + + +#undef SCSI_SINGLE_STEP +/* + * Single Step is only used for debug purposes + */ +#ifdef SCSI_SINGLE_STEP +static unsigned long start_script_select; +static unsigned long start_script_msgout; +static unsigned long start_script_msgin; +static unsigned long start_script_msg_ext; +static unsigned long start_script_cmd; +static unsigned long start_script_data_in; +static unsigned long start_script_data_out; +static unsigned long start_script_status; +static unsigned long start_script_complete; +static unsigned long start_script_error; +static unsigned long start_script_reselection; +static unsigned int len_script_select; +static unsigned int len_script_msgout; +static unsigned int len_script_msgin; +static unsigned int len_script_msg_ext; +static unsigned int len_script_cmd; +static unsigned int len_script_data_in; +static unsigned int len_script_data_out; +static unsigned int len_script_status; +static unsigned int len_script_complete; +static unsigned int len_script_error; +static unsigned int len_script_reselection; +#endif + + +static unsigned short scsi_int_mask; /* shadow register for SCSI related interrupts */ +static unsigned char script_int_mask; /* shadow register for SCRIPT related interrupts */ +static unsigned long script_select[8]; /* script for selection */ +static unsigned long script_msgout[8]; /* script for message out phase (NOT USED) */ +static unsigned long script_msgin[14]; /* script for message in phase */ +static unsigned long script_msg_ext[32]; /* script for message in phase when more than 1 byte message */ +static unsigned long script_cmd[18]; /* script for command phase */ +static unsigned long script_data_in[8]; /* script for data in phase */ +static unsigned long script_data_out[8]; /* script for data out phase */ +static unsigned long script_status[6]; /* script for status phase */ +static unsigned long script_complete[10]; /* script for complete */ +static unsigned long script_reselection[4]; /* script for reselection (NOT USED) */ +static unsigned long script_error[2]; /* script for error handling */ + +static unsigned long int_stat[3]; /* interrupt status */ +static unsigned long scsi_mem_addr; /* base memory address =SCSI_MEM_ADDRESS; */ + + +#define SCSI_MAX_RETRY 3 /* number of retries in scsi_issue() */ + +#define SCSI_MAX_RETRY_NOT_READY 10 /* number of retries when device is not ready */ +#define SCSI_NOT_READY_TIME_OUT 500 /* timeout per retry when not ready */ + +/********************************************************************************* + * forward declerations + */ + +void scsi_chip_init(void); +void handle_scsi_int(void); + + +/******************************************************************************** + * reports SCSI errors to the user + */ +void scsi_print_error(ccb *pccb) +{ + int i; + printf("SCSI Error: Target %d LUN %d Command %02X\n",pccb->target, pccb->lun, pccb->cmd[0]); + printf(" CCB: "); + for(i=0;icmdlen;i++) + printf("%02X ",pccb->cmd[i]); + printf("(len=%d)\n",pccb->cmdlen); + printf(" Cntrl: "); + switch(pccb->contr_stat) { + case SIR_COMPLETE: printf("Complete (no Error)\n"); break; + case SIR_SEL_ATN_NO_MSG_OUT: printf("Selected with ATN no MSG out phase\n"); break; + case SIR_CMD_OUT_ILL_PH: printf("Command out illegal phase\n"); break; + case SIR_MSG_RECEIVED: printf("MSG received Error\n"); break; + case SIR_DATA_IN_ERR: printf("Data in Error\n"); break; + case SIR_DATA_OUT_ERR: printf("Data out Error\n"); break; + case SIR_SCRIPT_ERROR: printf("Script Error\n"); break; + case SIR_MSG_OUT_NO_CMD: printf("MSG out no Command phase\n"); break; + case SIR_MSG_OVER7: printf("MSG in over 7 bytes\n"); break; + case INT_ON_FY: printf("Interrupt on fly\n"); break; + case SCSI_SEL_TIME_OUT: printf("SCSI Selection Timeout\n"); break; + case SCSI_HNS_TIME_OUT: printf("SCSI Handshake Timeout\n"); break; + case SCSI_MA_TIME_OUT: printf("SCSI Phase Error\n"); break; + case SCSI_UNEXP_DIS: printf("SCSI unexpected disconnect\n"); break; + default: printf("unknown status %lx\n",pccb->contr_stat); break; + } + printf(" Sense: SK %x (",pccb->sense_buf[2]&0x0f); + switch(pccb->sense_buf[2]&0xf) { + case SENSE_NO_SENSE: printf("No Sense)"); break; + case SENSE_RECOVERED_ERROR: printf("Recovered Error)"); break; + case SENSE_NOT_READY: printf("Not Ready)"); break; + case SENSE_MEDIUM_ERROR: printf("Medium Error)"); break; + case SENSE_HARDWARE_ERROR: printf("Hardware Error)"); break; + case SENSE_ILLEGAL_REQUEST: printf("Illegal request)"); break; + case SENSE_UNIT_ATTENTION: printf("Unit Attention)"); break; + case SENSE_DATA_PROTECT: printf("Data Protect)"); break; + case SENSE_BLANK_CHECK: printf("Blank check)"); break; + case SENSE_VENDOR_SPECIFIC: printf("Vendor specific)"); break; + case SENSE_COPY_ABORTED: printf("Copy aborted)"); break; + case SENSE_ABORTED_COMMAND: printf("Aborted Command)"); break; + case SENSE_VOLUME_OVERFLOW: printf("Volume overflow)"); break; + case SENSE_MISCOMPARE: printf("Misscompare\n"); break; + default: printf("Illegal Sensecode\n"); break; + } + printf(" ASC %x ASCQ %x\n",pccb->sense_buf[12],pccb->sense_buf[13]); + printf(" Status: "); + switch(pccb->status) { + case S_GOOD : printf("Good\n"); break; + case S_CHECK_COND: printf("Check condition\n"); break; + case S_COND_MET: printf("Condition Met\n"); break; + case S_BUSY: printf("Busy\n"); break; + case S_INT: printf("Intermediate\n"); break; + case S_INT_COND_MET: printf("Intermediate condition met\n"); break; + case S_CONFLICT: printf("Reservation conflict\n"); break; + case S_TERMINATED: printf("Command terminated\n"); break; + case S_QUEUE_FULL: printf("Task set full\n"); break; + default: printf("unknown: %02X\n",pccb->status); break; + } + +} + + + +/****************************************************************************** + * sets-up the SCSI controller + * the base memory address is retrived via the PCI_Read_CFG_Reg + */ +void scsi_low_level_init(int busdevfunc) +{ + unsigned long addr; + unsigned char vec; + vec=PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_DEV_INT_LINE, 1); + addr=PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_BASE_ADDRESS_1, 4); + scsi_mem_addr=addr; + scsi_chip_init(); + scsi_bus_reset(); + irq_install_handler(vec, (interrupt_handler_t *)handle_scsi_int, NULL); +} + + +/************************************************************************************ + * Low level Part of SCSI Driver + */ + +/* + * big-endian -> little endian conversion for the script + */ +unsigned long swap_script(unsigned long val) +{ + unsigned long tmp; + tmp = ((val>>24)&0xff) | ((val>>8)&0xff00) | ((val<<8)&0xff0000) | ((val<<24)&0xff000000); + return tmp; +} + + +void scsi_write_byte(ulong offset,unsigned char val) +{ + out8(scsi_mem_addr+offset,val); +} + + +unsigned char scsi_read_byte(ulong offset) +{ + return(in8(scsi_mem_addr+offset)); +} + + +/******************************************************************************** + * interrupt handler + */ +void handle_scsi_int(void) +{ + unsigned char stat,stat1,stat2; + unsigned short sstat; + int i; +#ifdef SCSI_SINGLE_STEP + unsigned long tt; +#endif + stat=scsi_read_byte(ISTAT); + if((stat & DIP)==DIP) { /* DMA Interrupt pending */ + stat1=scsi_read_byte(DSTAT); +#ifdef SCSI_SINGLE_STEP + if((stat1 & SSI)==SSI) + { + tt=in32r(scsi_mem_addr+DSP); + if(((tt)>=start_script_select) && ((tt)<=start_script_select+len_script_select)) { + printf("select %d\n",(tt-start_script_select)>>2); + goto end_single; + } + if(((tt)>=start_script_msgout) && ((tt)<=start_script_msgout+len_script_msgout)) { + printf("msgout %d\n",(tt-start_script_msgout)>>2); + goto end_single; + } + if(((tt)>=start_script_msgin) && ((tt)<=start_script_msgin+len_script_msgin)) { + printf("msgin %d\n",(tt-start_script_msgin)>>2); + goto end_single; + } + if(((tt)>=start_script_msg_ext) && ((tt)<=start_script_msg_ext+len_script_msg_ext)) { + printf("msgin_ext %d\n",(tt-start_script_msg_ext)>>2); + goto end_single; + } + if(((tt)>=start_script_cmd) && ((tt)<=start_script_cmd+len_script_cmd)) { + printf("cmd %d\n",(tt-start_script_cmd)>>2); + goto end_single; + } + if(((tt)>=start_script_data_in) && ((tt)<=start_script_data_in+len_script_data_in)) { + printf("data_in %d\n",(tt-start_script_data_in)>>2); + goto end_single; + } + if(((tt)>=start_script_data_out) && ((tt)<=start_script_data_out+len_script_data_out)) { + printf("data_out %d\n",(tt-start_script_data_out)>>2); + goto end_single; + } + if(((tt)>=start_script_status) && ((tt)<=start_script_status+len_script_status)) { + printf("status %d\n",(tt-start_script_status)>>2); + goto end_single; + } + if(((tt)>=start_script_complete) && ((tt)<=start_script_complete+len_script_complete)) { + printf("complete %d\n",(tt-start_script_complete)>>2); + goto end_single; + } + if(((tt)>=start_script_error) && ((tt)<=start_script_error+len_script_error)) { + printf("error %d\n",(tt-start_script_error)>>2); + goto end_single; + } + if(((tt)>=start_script_reselection) && ((tt)<=start_script_reselection+len_script_reselection)) { + printf("reselection %d\n",(tt-start_script_reselection)>>2); + goto end_single; + } + printf("sc: %lx\n",tt); +end_single: + stat2=scsi_read_byte(DCNTL); + stat2|=STD; + scsi_write_byte(DCNTL,stat2); + } +#endif + if((stat1 & SIR)==SIR) /* script interrupt */ + { + int_stat[0]=in32(scsi_mem_addr+DSPS); + } + if((stat1&DFE)==0) { /* fifo not epmty */ + scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */ + stat2=scsi_read_byte(STEST3); + scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */ + } + } + if((stat & SIP)==SIP) { /* scsi interrupt */ + sstat = (unsigned short)scsi_read_byte(SIST+1); + sstat <<=8; + sstat |= (unsigned short)scsi_read_byte(SIST); + for(i=0;i<3;i++) { + if(int_stat[i]==0) + break; /* found an empty int status */ + } + int_stat[i]=SCSI_INT_STATE | sstat; + stat1=scsi_read_byte(DSTAT); + if((stat1&DFE)==0) { /* fifo not epmty */ + scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */ + stat2=scsi_read_byte(STEST3); + scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */ + } + } + if((stat & INTF)==INTF) { /* interrupt on Fly */ + scsi_write_byte(ISTAT,stat); /* clear it */ + for(i=0;i<3;i++) { + if(int_stat[i]==0) + break; /* found an empty int status */ + } + int_stat[i]=INT_ON_FY; + } +} + + +void scsi_bus_reset(void) +{ + unsigned char t; + int i; + t=scsi_read_byte(SCNTL1); + scsi_write_byte(SCNTL1,(t | CRST)); + udelay(50); + scsi_write_byte(SCNTL1,t); + for(i=0;i<2000;i++) + udelay(1000); /* 2sec to give the devices time to spin up */ + scsi_chip_init(); /* reinit the chip ...*/ + +} + +void scsi_int_enable(void) +{ + scsi_write_byte(SIEN,(unsigned char)scsi_int_mask); + scsi_write_byte(SIEN+1,(unsigned char)(scsi_int_mask>>8)); + scsi_write_byte(DIEN,script_int_mask); +} + +void scsi_write_dsp(unsigned long start) +{ + unsigned long val; +#ifdef SCSI_SINGLE_STEP + unsigned char t; +#endif + val = start; + out32r(scsi_mem_addr + DSP,start); +#ifdef SCSI_SINGLE_STEP + t=scsi_read_byte(DCNTL); + t|=STD; + scsi_write_byte(DCNTL,t); +#endif +} + +/* only used for debug purposes */ +void scsi_print_script(void) +{ + printf("script_select @ 0x%08lX\n",(unsigned long)&script_select[0]); + printf("script_msgout @ 0x%08lX\n",(unsigned long)&script_msgout[0]); + printf("script_msgin @ 0x%08lX\n",(unsigned long)&script_msgin[0]); + printf("script_msgext @ 0x%08lX\n",(unsigned long)&script_msg_ext[0]); + printf("script_cmd @ 0x%08lX\n",(unsigned long)&script_cmd[0]); + printf("script_data_in @ 0x%08lX\n",(unsigned long)&script_data_in[0]); + printf("script_data_out @ 0x%08lX\n",(unsigned long)&script_data_out[0]); + printf("script_status @ 0x%08lX\n",(unsigned long)&script_status[0]); + printf("script_complete @ 0x%08lX\n",(unsigned long)&script_complete[0]); + printf("script_error @ 0x%08lX\n",(unsigned long)&script_error[0]); +} + + + +void scsi_set_script(ccb *pccb) +{ + int i; + i=0; + script_select[i++]=swap_script(SCR_REG_REG(GPREG, SCR_AND, 0xfe)); + script_select[i++]=0; /* LED ON */ + script_select[i++]=swap_script(SCR_CLR(SCR_TRG)); /* select initiator mode */ + script_select[i++]=0; + /* script_select[i++]=swap_script(SCR_SEL_ABS_ATN | pccb->target << 16); */ + script_select[i++]=swap_script(SCR_SEL_ABS | pccb->target << 16); + script_select[i++]=swap_script((unsigned long)&script_cmd[0x04]); /* error handling */ + script_select[i++]=swap_script(SCR_JUMP); /* next section */ + /* script_select[i++]=swap_script((unsigned long)&script_msgout[0]); */ /* message out */ + script_select[i++]=swap_script((unsigned long)&script_cmd[0]); /* command out */ + +#ifdef SCSI_SINGLE_STEP + start_script_select=(unsigned long)&script_select[0]; + len_script_select=i*4; +#endif + + i=0; + script_msgout[i++]=swap_script(SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT))); + script_msgout[i++]=SIR_SEL_ATN_NO_MSG_OUT; + script_msgout[i++]=swap_script( SCR_MOVE_ABS(1) ^ SCR_MSG_OUT); + script_msgout[i++]=swap_script((unsigned long)&pccb->msgout[0]); + script_msgout[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_COMMAND))); /* if Command phase */ + script_msgout[i++]=swap_script((unsigned long)&script_cmd[0]); /* switch to command */ + script_msgout[i++]=swap_script(SCR_INT); /* interrupt if not */ + script_msgout[i++]=SIR_MSG_OUT_NO_CMD; + +#ifdef SCSI_SINGLE_STEP + start_script_msgout=(unsigned long)&script_msgout[0]; + len_script_msgout=i*4; +#endif + i=0; + script_cmd[i++]=swap_script(SCR_MOVE_ABS(pccb->cmdlen) ^ SCR_COMMAND); + script_cmd[i++]=swap_script((unsigned long)&pccb->cmd[0]); + script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN))); /* message in ? */ + script_cmd[i++]=swap_script((unsigned long)&script_msgin[0]); + script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT))); /* data out ? */ + script_cmd[i++]=swap_script((unsigned long)&script_data_out[0]); + script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN))); /* data in ? */ + script_cmd[i++]=swap_script((unsigned long)&script_data_in[0]); + script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_STATUS))); /* status ? */ + script_cmd[i++]=swap_script((unsigned long)&script_status[0]); + script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND))); /* command ? */ + script_cmd[i++]=swap_script((unsigned long)&script_cmd[0]); + script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT))); /* message out ? */ + script_cmd[i++]=swap_script((unsigned long)&script_msgout[0]); + script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN))); /* just for error handling message in ? */ + script_cmd[i++]=swap_script((unsigned long)&script_msgin[0]); + script_cmd[i++]=swap_script(SCR_INT); /* interrupt if not */ + script_cmd[i++]=SIR_CMD_OUT_ILL_PH; +#ifdef SCSI_SINGLE_STEP + start_script_cmd=(unsigned long)&script_cmd[0]; + len_script_cmd=i*4; +#endif + i=0; + script_data_out[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_OUT); /* move */ + script_data_out[i++]=swap_script((unsigned long)pccb->pdata); /* pointer to buffer */ + script_data_out[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS))); + script_data_out[i++]=swap_script((unsigned long)&script_status[0]); + script_data_out[i++]=swap_script(SCR_INT); + script_data_out[i++]=SIR_DATA_OUT_ERR; + +#ifdef SCSI_SINGLE_STEP + start_script_data_out=(unsigned long)&script_data_out[0]; + len_script_data_out=i*4; +#endif + i=0; + script_data_in[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_IN); /* move */ + script_data_in[i++]=swap_script((unsigned long)pccb->pdata); /* pointer to buffer */ + script_data_in[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS))); + script_data_in[i++]=swap_script((unsigned long)&script_status[0]); + script_data_in[i++]=swap_script(SCR_INT); + script_data_in[i++]=SIR_DATA_IN_ERR; +#ifdef SCSI_SINGLE_STEP + start_script_data_in=(unsigned long)&script_data_in[0]; + len_script_data_in=i*4; +#endif + i=0; + script_msgin[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); + script_msgin[i++]=swap_script((unsigned long)&pccb->msgin[0]); + script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE))); + script_msgin[i++]=swap_script((unsigned long)&script_complete[0]); + script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT))); + script_msgin[i++]=swap_script((unsigned long)&script_complete[0]); + script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP))); + script_msgin[i++]=swap_script((unsigned long)&script_complete[0]); + script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP))); + script_msgin[i++]=swap_script((unsigned long)&script_complete[0]); + script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED))); + script_msgin[i++]=swap_script((unsigned long)&script_msg_ext[0]); + script_msgin[i++]=swap_script(SCR_INT); + script_msgin[i++]=SIR_MSG_RECEIVED; +#ifdef SCSI_SINGLE_STEP + start_script_msgin=(unsigned long)&script_msgin[0]; + len_script_msgin=i*4; +#endif + i=0; + script_msg_ext[i++]=swap_script(SCR_CLR (SCR_ACK)); /* clear ACK */ + script_msg_ext[i++]=0; + script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* assuming this is the msg length */ + script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[1]); + script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); + script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */ + script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ + script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[2]); + script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); + script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */ + script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ + script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[3]); + script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); + script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */ + script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ + script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[4]); + script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); + script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */ + script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ + script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[5]); + script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); + script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */ + script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ + script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[6]); + script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); + script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */ + script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */ + script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[7]); + script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); + script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */ + script_msg_ext[i++]=swap_script(SCR_INT); + script_msg_ext[i++]=SIR_MSG_OVER7; +#ifdef SCSI_SINGLE_STEP + start_script_msg_ext=(unsigned long)&script_msg_ext[0]; + len_script_msg_ext=i*4; +#endif + i=0; + script_status[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_STATUS); + script_status[i++]=swap_script((unsigned long)&pccb->status); + script_status[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN))); + script_status[i++]=swap_script((unsigned long)&script_msgin[0]); + script_status[i++]=swap_script(SCR_INT); + script_status[i++]=SIR_STATUS_ILL_PH; +#ifdef SCSI_SINGLE_STEP + start_script_status=(unsigned long)&script_status[0]; + len_script_status=i*4; +#endif + i=0; + script_complete[i++]=swap_script(SCR_REG_REG (SCNTL2, SCR_AND, 0x7f)); + script_complete[i++]=0; + script_complete[i++]=swap_script(SCR_CLR (SCR_ACK|SCR_ATN)); + script_complete[i++]=0; + script_complete[i++]=swap_script(SCR_WAIT_DISC); + script_complete[i++]=0; + script_complete[i++]=swap_script(SCR_REG_REG(GPREG, SCR_OR, 0x01)); + script_complete[i++]=0; /* LED OFF */ + script_complete[i++]=swap_script(SCR_INT); + script_complete[i++]=SIR_COMPLETE; +#ifdef SCSI_SINGLE_STEP + start_script_complete=(unsigned long)&script_complete[0]; + len_script_complete=i*4; +#endif + i=0; + script_error[i++]=swap_script(SCR_INT); /* interrupt if error */ + script_error[i++]=SIR_SCRIPT_ERROR; +#ifdef SCSI_SINGLE_STEP + start_script_error=(unsigned long)&script_error[0]; + len_script_error=i*4; +#endif + i=0; + script_reselection[i++]=swap_script(SCR_CLR (SCR_TRG)); /* target status */ + script_reselection[i++]=0; + script_reselection[i++]=swap_script(SCR_WAIT_RESEL); + script_reselection[i++]=swap_script((unsigned long)&script_select[0]); /* len = 4 */ +#ifdef SCSI_SINGLE_STEP + start_script_reselection=(unsigned long)&script_reselection[0]; + len_script_reselection=i*4; +#endif +} + + + +void scsi_issue(ccb *pccb) +{ + int i; + unsigned short sstat; + int retrycnt; /* retry counter */ + for(i=0;i<3;i++) + int_stat[i]=0; /* delete all int status */ + /* struct pccb must be set-up correctly */ + retrycnt=0; + PRINTF("ID %d issue cmd %02X\n",pccb->target,pccb->cmd[0]); + pccb->trans_bytes=0; /* no bytes transfered yet */ + scsi_set_script(pccb); /* fill in SCRIPT */ + scsi_int_mask=STO | UDC | MA; /* Interrupts which are enabled */ + script_int_mask=0xff; /* enable all Ints */ + scsi_int_enable(); + scsi_write_dsp((unsigned long)&script_select[0]); /* start script */ + /* now we have to wait for IRQs */ +retry: + while(int_stat[0]==0); + if(int_stat[0]==SIR_COMPLETE) { + if(pccb->msgin[0]==M_DISCONNECT) { + PRINTF("Wait for reselection\n"); + for(i=0;i<3;i++) + int_stat[i]=0; /* delete all int status */ + scsi_write_dsp((unsigned long)&script_reselection[0]); /* start reselection script */ + goto retry; + } + pccb->contr_stat=SIR_COMPLETE; + return; + } + if((int_stat[0] & SCSI_INT_STATE)==SCSI_INT_STATE) { /* scsi interrupt */ + sstat=(unsigned short)int_stat[0]; + if((sstat & STO)==STO) { /* selection timeout */ + pccb->contr_stat=SCSI_SEL_TIME_OUT; + scsi_write_byte(GPREG,0x01); + PRINTF("ID: %X Selection Timeout\n",pccb->target); + return; + } + if((sstat & UDC)==UDC) { /* unexpected disconnect */ + pccb->contr_stat=SCSI_UNEXP_DIS; + scsi_write_byte(GPREG,0x01); + PRINTF("ID: %X Unexpected Disconnect\n",pccb->target); + return; + } + if((sstat & RSL)==RSL) { /* reselection */ + pccb->contr_stat=SCSI_UNEXP_DIS; + scsi_write_byte(GPREG,0x01); + PRINTF("ID: %X Unexpected Disconnect\n",pccb->target); + return; + } + if(((sstat & MA)==MA)||((sstat & HTH)==HTH)) { /* phase missmatch */ + if(retrycnttrans_bytes=pccb->datalen - + ((unsigned long)scsi_read_byte(DBC) | + ((unsigned long)scsi_read_byte(DBC+1)<<8) | + ((unsigned long)scsi_read_byte(DBC+2)<<16)); + for(i=0;i<3;i++) + int_stat[i]=0; /* delete all int status */ + retrycnt++; + PRINTF("ID: %X Phase Missmatch Retry %d Phase %02X transfered %lx\n", + pccb->target,retrycnt,scsi_read_byte(SBCL),pccb->trans_bytes); + scsi_write_dsp((unsigned long)&script_cmd[4]); /* start retry script */ + goto retry; + } + if((sstat & MA)==MA) + pccb->contr_stat=SCSI_MA_TIME_OUT; + else + pccb->contr_stat=SCSI_HNS_TIME_OUT; + PRINTF("Phase Missmatch stat %lx\n",pccb->contr_stat); + return; + } /* no phase int */ + PRINTF("SCSI INT %lX\n",int_stat[0]); + pccb->contr_stat=int_stat[0]; + return; + } /* end scsi int */ + PRINTF("SCRIPT INT %lX phase %02X\n",int_stat[0],scsi_read_byte(SBCL)); + pccb->contr_stat=int_stat[0]; + return; +} + +int scsi_exec(ccb *pccb) +{ + unsigned char tmpcmd[16],tmpstat; + int i,retrycnt,t; + unsigned long transbytes,datalen; + unsigned char *tmpptr; + retrycnt=0; +retry: + scsi_issue(pccb); + if(pccb->contr_stat!=SIR_COMPLETE) + return FALSE; + if(pccb->status==S_GOOD) + return TRUE; + if(pccb->status==S_CHECK_COND) { /* check condition */ + for(i=0;i<16;i++) + tmpcmd[i]=pccb->cmd[i]; + pccb->cmd[0]=SCSI_REQ_SENSE; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=0; + pccb->cmd[3]=0; + pccb->cmd[4]=14; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; + transbytes=pccb->trans_bytes; + tmpptr=pccb->pdata; + pccb->pdata=&pccb->sense_buf[0]; + datalen=pccb->datalen; + pccb->datalen=14; + tmpstat=pccb->status; + scsi_issue(pccb); + for(i=0;i<16;i++) + pccb->cmd[i]=tmpcmd[i]; + pccb->trans_bytes=transbytes; + pccb->pdata=tmpptr; + pccb->datalen=datalen; + pccb->status=tmpstat; + PRINTF("Request_sense sense key %x ASC %x ASCQ %x\n",pccb->sense_buf[2]&0x0f, + pccb->sense_buf[12],pccb->sense_buf[13]); + switch(pccb->sense_buf[2]&0xf) { + case SENSE_NO_SENSE: + case SENSE_RECOVERED_ERROR: + /* seems to be ok */ + return TRUE; + break; + case SENSE_NOT_READY: + if((pccb->sense_buf[12]!=0x04)||(pccb->sense_buf[13]!=0x01)) { + /* if device is not in process of becoming ready */ + return FALSE; + break; + } /* else fall through */ + case SENSE_UNIT_ATTENTION: + if(retrycnttarget,retrycnt); + for(t=0;ttarget,retrycnt); + return FALSE; + default: + return FALSE; + } + } + PRINTF("Status = %X\n",pccb->status); + return FALSE; +} + + + + +void scsi_chip_init(void) +{ + /* first we issue a soft reset */ + scsi_write_byte(ISTAT,SRST); + udelay(1000); + scsi_write_byte(ISTAT,0); + /* setup chip */ + scsi_write_byte(SCNTL0,0xC0); /* full arbitration no start, no message, parity disabled, master */ + scsi_write_byte(SCNTL1,0x00); + scsi_write_byte(SCNTL2,0x00); + scsi_write_byte(SCNTL3,0x13); /* synchronous clock 40/4=10MHz, asynchronous 40MHz */ + scsi_write_byte(SCID,0x47); /* ID=7, enable reselection */ + scsi_write_byte(SXFER,0x00); /* synchronous transfer period 10MHz, asynchronous */ + scsi_write_byte(SDID,0x00); /* targed SCSI ID = 0 */ + scsi_int_mask=0x0000; /* no Interrupt is enabled */ + script_int_mask=0x00; + scsi_int_enable(); + scsi_write_byte(GPREG,0x01); /* GPIO0 is LED (off) */ + scsi_write_byte(GPCNTL,0x0E); /* GPIO0 is Output */ + scsi_write_byte(STIME0,0x08); /* handshake timer disabled, selection timeout 512msec */ + scsi_write_byte(RESPID,0x80); /* repond only to the own ID (reselection) */ + scsi_write_byte(STEST1,0x00); /* not isolated, SCLK is used */ + scsi_write_byte(STEST2,0x00); /* no Lowlevel Mode? */ + scsi_write_byte(STEST3,0x80); /* enable tolerANT */ + scsi_write_byte(CTEST3,0x04); /* clear FIFO */ + scsi_write_byte(CTEST4,0x00); + scsi_write_byte(CTEST5,0x00); +#ifdef SCSI_SINGLE_STEP + scsi_write_byte(DCNTL,IRQM | SSM); + scsi_write_byte(DMODE,MAN); +#else + scsi_write_byte(DCNTL,IRQM); + scsi_write_byte(DMODE,0x00); +#endif +} +#endif /* (CONFIG_COMMANDS & CFG_CMD_SCSI) */ + + diff --git a/board/mpl/common/sym53c8xx_defs.h b/board/mpl/common/sym53c8xx_defs.h new file mode 100644 index 0000000..d1bc3cf --- /dev/null +++ b/board/mpl/common/sym53c8xx_defs.h @@ -0,0 +1,582 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + * + * Most of these definitions are derived from + * linux/drivers/scsi/sym53c8xx_defs.h + * + */ + +#ifndef _SYM53C8XX_DEFS_H +#define _SYM53C8XX_DEFS_H + + +#define SCNTL0 0x00 /* full arb., ena parity, par->ATN */ + +#define SCNTL1 0x01 /* no reset */ + #define ISCON 0x10 /* connected to scsi */ + #define CRST 0x08 /* force reset */ + #define IARB 0x02 /* immediate arbitration */ + +#define SCNTL2 0x02 /* no disconnect expected */ + #define SDU 0x80 /* cmd: disconnect will raise error */ + #define CHM 0x40 /* sta: chained mode */ + #define WSS 0x08 /* sta: wide scsi send [W]*/ + #define WSR 0x01 /* sta: wide scsi received [W]*/ + +#define SCNTL3 0x03 /* cnf system clock dependent */ + #define EWS 0x08 /* cmd: enable wide scsi [W]*/ + #define ULTRA 0x80 /* cmd: ULTRA enable */ + /* bits 0-2, 7 rsvd for C1010 */ + +#define SCID 0x04 /* cnf host adapter scsi address */ + #define RRE 0x40 /* r/w:e enable response to resel. */ + #define SRE 0x20 /* r/w:e enable response to select */ + +#define SXFER 0x05 /* ### Sync speed and count */ + /* bits 6-7 rsvd for C1010 */ + +#define SDID 0x06 /* ### Destination-ID */ + +#define GPREG 0x07 /* ??? IO-Pins */ + +#define SFBR 0x08 /* ### First byte in phase */ + +#define SOCL 0x09 + #define CREQ 0x80 /* r/w: SCSI-REQ */ + #define CACK 0x40 /* r/w: SCSI-ACK */ + #define CBSY 0x20 /* r/w: SCSI-BSY */ + #define CSEL 0x10 /* r/w: SCSI-SEL */ + #define CATN 0x08 /* r/w: SCSI-ATN */ + #define CMSG 0x04 /* r/w: SCSI-MSG */ + #define CC_D 0x02 /* r/w: SCSI-C_D */ + #define CI_O 0x01 /* r/w: SCSI-I_O */ + +#define SSID 0x0a + +#define SBCL 0x0b + +#define DSTAT 0x0c + #define DFE 0x80 /* sta: dma fifo empty */ + #define MDPE 0x40 /* int: master data parity error */ + #define BF 0x20 /* int: script: bus fault */ + #define ABRT 0x10 /* int: script: command aborted */ + #define SSI 0x08 /* int: script: single step */ + #define SIR 0x04 /* int: script: interrupt instruct. */ + #define IID 0x01 /* int: script: illegal instruct. */ + +#define SSTAT0 0x0d + #define ILF 0x80 /* sta: data in SIDL register lsb */ + #define ORF 0x40 /* sta: data in SODR register lsb */ + #define OLF 0x20 /* sta: data in SODL register lsb */ + #define AIP 0x10 /* sta: arbitration in progress */ + #define LOA 0x08 /* sta: arbitration lost */ + #define WOA 0x04 /* sta: arbitration won */ + #define IRST 0x02 /* sta: scsi reset signal */ + #define SDP 0x01 /* sta: scsi parity signal */ + +#define SSTAT1 0x0e + #define FF3210 0xf0 /* sta: bytes in the scsi fifo */ + +#define SSTAT2 0x0f + #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/ + #define ORF1 0x40 /* sta: data in SODR register msb[W]*/ + #define OLF1 0x20 /* sta: data in SODL register msb[W]*/ + #define DM 0x04 /* sta: DIFFSENS mismatch (895/6 only) */ + #define LDSC 0x02 /* sta: disconnect & reconnect */ + +#define DSA 0x10 /* --> Base page */ +#define DSA1 0x11 +#define DSA2 0x12 +#define DSA3 0x13 + +#define ISTAT 0x14 /* --> Main Command and status */ + #define CABRT 0x80 /* cmd: abort current operation */ + #define SRST 0x40 /* mod: reset chip */ + #define SIGP 0x20 /* r/w: message from host to ncr */ + #define SEM 0x10 /* r/w: message between host + ncr */ + #define CON 0x08 /* sta: connected to scsi */ + #define INTF 0x04 /* sta: int on the fly (reset by wr)*/ + #define SIP 0x02 /* sta: scsi-interrupt */ + #define DIP 0x01 /* sta: host/script interrupt */ + + +#define CTEST0 0x18 +#define CTEST1 0x19 +#define CTEST2 0x1a + #define CSIGP 0x40 + /* bits 0-2,7 rsvd for C1010 */ + +#define CTEST3 0x1b + #define FLF 0x08 /* cmd: flush dma fifo */ + #define CLF 0x04 /* cmd: clear dma fifo */ + #define FM 0x02 /* mod: fetch pin mode */ + #define WRIE 0x01 /* mod: write and invalidate enable */ + /* bits 4-7 rsvd for C1010 */ + +#define DFIFO 0x20 +#define CTEST4 0x21 + #define BDIS 0x80 /* mod: burst disable */ + #define MPEE 0x08 /* mod: master parity error enable */ + +#define CTEST5 0x22 + #define DFS 0x20 /* mod: dma fifo size */ + /* bits 0-1, 3-7 rsvd for C1010 */ +#define CTEST6 0x23 + +#define DBC 0x24 /* ### Byte count and command */ +#define DNAD 0x28 /* ### Next command register */ +#define DSP 0x2c /* --> Script Pointer */ +#define DSPS 0x30 /* --> Script pointer save/opcode#2 */ + +#define SCRATCHA 0x34 /* Temporary register a */ +#define SCRATCHA1 0x35 +#define SCRATCHA2 0x36 +#define SCRATCHA3 0x37 + +#define DMODE 0x38 + #define BL_2 0x80 /* mod: burst length shift value +2 */ + #define BL_1 0x40 /* mod: burst length shift value +1 */ + #define ERL 0x08 /* mod: enable read line */ + #define ERMP 0x04 /* mod: enable read multiple */ + #define BOF 0x02 /* mod: burst op code fetch */ + #define MAN 0x01 /* mod: manual start */ + +#define DIEN 0x39 +#define SBR 0x3a + +#define DCNTL 0x3b /* --> Script execution control */ + #define CLSE 0x80 /* mod: cache line size enable */ + #define PFF 0x40 /* cmd: pre-fetch flush */ + #define PFEN 0x20 /* mod: pre-fetch enable */ + #define SSM 0x10 /* mod: single step mode */ + #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */ + #define STD 0x04 /* cmd: start dma mode */ + #define IRQD 0x02 /* mod: irq disable */ + #define NOCOM 0x01 /* cmd: protect sfbr while reselect */ + /* bits 0-1 rsvd for C1010 */ + +#define ADDER 0x3c + +#define SIEN 0x40 /* -->: interrupt enable */ +#define SIST 0x42 /* <--: interrupt status */ + #define SBMC 0x1000/* sta: SCSI Bus Mode Change (895/6 only) */ + #define STO 0x0400/* sta: timeout (select) */ + #define GEN 0x0200/* sta: timeout (general) */ + #define HTH 0x0100/* sta: timeout (handshake) */ + #define MA 0x80 /* sta: phase mismatch */ + #define CMP 0x40 /* sta: arbitration complete */ + #define SEL 0x20 /* sta: selected by another device */ + #define RSL 0x10 /* sta: reselected by another device*/ + #define SGE 0x08 /* sta: gross error (over/underflow)*/ + #define UDC 0x04 /* sta: unexpected disconnect */ + #define RST 0x02 /* sta: scsi bus reset detected */ + #define PAR 0x01 /* sta: scsi parity error */ + +#define SLPAR 0x44 +#define SWIDE 0x45 +#define MACNTL 0x46 +#define GPCNTL 0x47 +#define STIME0 0x48 /* cmd: timeout for select&handshake*/ +#define STIME1 0x49 /* cmd: timeout user defined */ +#define RESPID 0x4a /* sta: Reselect-IDs */ + +#define STEST0 0x4c + +#define STEST1 0x4d + #define SCLK 0x80 /* Use the PCI clock as SCSI clock */ + #define DBLEN 0x08 /* clock doubler running */ + #define DBLSEL 0x04 /* clock doubler selected */ + + +#define STEST2 0x4e + #define ROF 0x40 /* reset scsi offset (after gross error!) */ + #define EXT 0x02 /* extended filtering */ + +#define STEST3 0x4f + #define TE 0x80 /* c: tolerAnt enable */ + #define HSC 0x20 /* c: Halt SCSI Clock */ + #define CSF 0x02 /* c: clear scsi fifo */ + +#define SIDL 0x50 /* Lowlevel: latched from scsi data */ +#define STEST4 0x52 + #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */ + #define SMODE_HVD 0x40 /* High Voltage Differential */ + #define SMODE_SE 0x80 /* Single Ended */ + #define SMODE_LVD 0xc0 /* Low Voltage Differential */ + #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */ + /* bits 0-5 rsvd for C1010 */ + +#define SODL 0x54 /* Lowlevel: data out to scsi data */ + +#define SBDL 0x58 /* Lowlevel: data from scsi data */ + + + + +/*----------------------------------------------------------- +** +** Utility macros for the script. +** +**----------------------------------------------------------- +*/ + +#define REG(r) (r) + +/*----------------------------------------------------------- +** +** SCSI phases +** +** DT phases illegal for ncr driver. +** +**----------------------------------------------------------- +*/ + +#define SCR_DATA_OUT 0x00000000 +#define SCR_DATA_IN 0x01000000 +#define SCR_COMMAND 0x02000000 +#define SCR_STATUS 0x03000000 +#define SCR_DT_DATA_OUT 0x04000000 +#define SCR_DT_DATA_IN 0x05000000 +#define SCR_MSG_OUT 0x06000000 +#define SCR_MSG_IN 0x07000000 + +#define SCR_ILG_OUT 0x04000000 +#define SCR_ILG_IN 0x05000000 + +/*----------------------------------------------------------- +** +** Data transfer via SCSI. +** +**----------------------------------------------------------- +** +** MOVE_ABS (LEN) +** <> +** +** MOVE_IND (LEN) +** <> +** +** MOVE_TBL +** <> +** +**----------------------------------------------------------- +*/ + +#define OPC_MOVE 0x08000000 + +#define SCR_MOVE_ABS(l) ((0x00000000 | OPC_MOVE) | (l)) +#define SCR_MOVE_IND(l) ((0x20000000 | OPC_MOVE) | (l)) +#define SCR_MOVE_TBL (0x10000000 | OPC_MOVE) + +#define SCR_CHMOV_ABS(l) ((0x00000000) | (l)) +#define SCR_CHMOV_IND(l) ((0x20000000) | (l)) +#define SCR_CHMOV_TBL (0x10000000) + + +/*----------------------------------------------------------- +** +** Selection +** +**----------------------------------------------------------- +** +** SEL_ABS | SCR_ID (0..15) [ | REL_JMP] +** <> +** +** SEL_TBL | << dnad_offset>> [ | REL_JMP] +** <> +** +**----------------------------------------------------------- +*/ + +#define SCR_SEL_ABS 0x40000000 +#define SCR_SEL_ABS_ATN 0x41000000 +#define SCR_SEL_TBL 0x42000000 +#define SCR_SEL_TBL_ATN 0x43000000 + + +#define SCR_JMP_REL 0x04000000 +#define SCR_ID(id) (((unsigned long)(id)) << 16) + +/*----------------------------------------------------------- +** +** Waiting for Disconnect or Reselect +** +**----------------------------------------------------------- +** +** WAIT_DISC +** dummy: <> +** +** WAIT_RESEL +** <> +** +**----------------------------------------------------------- +*/ + +#define SCR_WAIT_DISC 0x48000000 +#define SCR_WAIT_RESEL 0x50000000 + +/*----------------------------------------------------------- +** +** Bit Set / Reset +** +**----------------------------------------------------------- +** +** SET (flags {|.. }) +** +** CLR (flags {|.. }) +** +**----------------------------------------------------------- +*/ + +#define SCR_SET(f) (0x58000000 | (f)) +#define SCR_CLR(f) (0x60000000 | (f)) + +#define SCR_CARRY 0x00000400 +#define SCR_TRG 0x00000200 +#define SCR_ACK 0x00000040 +#define SCR_ATN 0x00000008 + + + + +/*----------------------------------------------------------- +** +** Memory to memory move +** +**----------------------------------------------------------- +** +** COPY (bytecount) +** << source_address >> +** << destination_address >> +** +** SCR_COPY sets the NO FLUSH option by default. +** SCR_COPY_F does not set this option. +** +** For chips which do not support this option, +** ncr_copy_and_bind() will remove this bit. +**----------------------------------------------------------- +*/ + +#define SCR_NO_FLUSH 0x01000000 + +#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n)) +#define SCR_COPY_F(n) (0xc0000000 | (n)) + +/*----------------------------------------------------------- +** +** Register move and binary operations +** +**----------------------------------------------------------- +** +** SFBR_REG (reg, op, data) reg = SFBR op data +** << 0 >> +** +** REG_SFBR (reg, op, data) SFBR = reg op data +** << 0 >> +** +** REG_REG (reg, op, data) reg = reg op data +** << 0 >> +** +**----------------------------------------------------------- +** On 810A, 860, 825A, 875, 895 and 896 chips the content +** of SFBR register can be used as data (SCR_SFBR_DATA). +** The 896 has additionnal IO registers starting at +** offset 0x80. Bit 7 of register offset is stored in +** bit 7 of the SCRIPTS instruction first DWORD. +**----------------------------------------------------------- +*/ + +#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul)) /* + ((ofs) & 0x80)) */ + +#define SCR_SFBR_REG(reg,op,data) \ + (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul)) + +#define SCR_REG_SFBR(reg,op,data) \ + (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul)) + +#define SCR_REG_REG(reg,op,data) \ + (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul)) + + +#define SCR_LOAD 0x00000000 +#define SCR_SHL 0x01000000 +#define SCR_OR 0x02000000 +#define SCR_XOR 0x03000000 +#define SCR_AND 0x04000000 +#define SCR_SHR 0x05000000 +#define SCR_ADD 0x06000000 +#define SCR_ADDC 0x07000000 + +#define SCR_SFBR_DATA (0x00800000>>8ul) /* Use SFBR as data */ + +/*----------------------------------------------------------- +** +** FROM_REG (reg) SFBR = reg +** << 0 >> +** +** TO_REG (reg) reg = SFBR +** << 0 >> +** +** LOAD_REG (reg, data) reg = +** << 0 >> +** +** LOAD_SFBR(data) SFBR = +** << 0 >> +** +**----------------------------------------------------------- +*/ + +#define SCR_FROM_REG(reg) \ + SCR_REG_SFBR(reg,SCR_OR,0) + +#define SCR_TO_REG(reg) \ + SCR_SFBR_REG(reg,SCR_OR,0) + +#define SCR_LOAD_REG(reg,data) \ + SCR_REG_REG(reg,SCR_LOAD,data) + +#define SCR_LOAD_SFBR(data) \ + (SCR_REG_SFBR (gpreg, SCR_LOAD, data)) + +/*----------------------------------------------------------- +** +** LOAD from memory to register. +** STORE from register to memory. +** +** Only supported by 810A, 860, 825A, 875, 895 and 896. +** +**----------------------------------------------------------- +** +** LOAD_ABS (LEN) +** <> +** +** LOAD_REL (LEN) (DSA relative) +** <> +** +**----------------------------------------------------------- +*/ + +#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul) +#define SCR_NO_FLUSH2 0x02000000 +#define SCR_DSA_REL2 0x10000000 + +#define SCR_LOAD_R(reg, how, n) \ + (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n)) + +#define SCR_STORE_R(reg, how, n) \ + (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n)) + +#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n) +#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n) +#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n) +#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n) + +#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n) +#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n) +#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n) +#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n) + + +/*----------------------------------------------------------- +** +** Waiting for Disconnect or Reselect +** +**----------------------------------------------------------- +** +** JUMP [ | IFTRUE/IFFALSE ( ... ) ] +** <
> +** +** JUMPR [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** CALL [ | IFTRUE/IFFALSE ( ... ) ] +** <
> +** +** CALLR [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** RETURN [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** INT [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** Conditions: +** WHEN (phase) +** IF (phase) +** CARRYSET +** DATA (data, mask) +** +**----------------------------------------------------------- +*/ + +#define SCR_NO_OP 0x80000000 +#define SCR_JUMP 0x80080000 +#define SCR_JUMP64 0x80480000 +#define SCR_JUMPR 0x80880000 +#define SCR_CALL 0x88080000 +#define SCR_CALLR 0x88880000 +#define SCR_RETURN 0x90080000 +#define SCR_INT 0x98080000 +#define SCR_INT_FLY 0x98180000 + +#define IFFALSE(arg) (0x00080000 | (arg)) +#define IFTRUE(arg) (0x00000000 | (arg)) + +#define WHEN(phase) (0x00030000 | (phase)) +#define IF(phase) (0x00020000 | (phase)) + +#define DATA(D) (0x00040000 | ((D) & 0xff)) +#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff)) + +#define CARRYSET (0x00200000) + + + +#define SIR_COMPLETE 0x10000000 +/* script errors */ +#define SIR_SEL_ATN_NO_MSG_OUT 0x00000001 +#define SIR_CMD_OUT_ILL_PH 0x00000002 +#define SIR_STATUS_ILL_PH 0x00000003 +#define SIR_MSG_RECEIVED 0x00000004 +#define SIR_DATA_IN_ERR 0x00000005 +#define SIR_DATA_OUT_ERR 0x00000006 +#define SIR_SCRIPT_ERROR 0x00000007 +#define SIR_MSG_OUT_NO_CMD 0x00000008 +#define SIR_MSG_OVER7 0x00000009 +/* Fly interrupt */ +#define INT_ON_FY 0x00000080 +/* Hardware errors are defined in scsi.h */ + +#define SCSI_IDENTIFY 0xC0 + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#endif diff --git a/board/mpl/common/usb_uhci.c b/board/mpl/common/usb_uhci.c new file mode 100644 index 0000000..8f01ddb --- /dev/null +++ b/board/mpl/common/usb_uhci.c @@ -0,0 +1,1153 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + * Note: Part of this code has been derived from linux + * + */ + +/********************************************************************** + * How it works: + * ------------- + * The framelist / Transfer descriptor / Queue Heads are similar like + * in the linux usb_uhci.c. + * + * During initialization, the following skeleton is allocated in init_skel: + * + * framespecific | common chain + * + * framelist[] + * [ 0 ]-----> TD ---------\ + * [ 1 ]-----> TD ----------> TD ------> QH -------> QH -------> QH ---> NULL + * ... TD ---------/ + * [1023]-----> TD --------/ + * + * ^^ ^^ ^^ ^^ ^^ + * 7 TDs for 1 TD for Start of Start of End Chain + * INT (2-128ms) 1ms-INT CTRL Chain BULK Chain + * + * + * Since this is a bootloader, the isochronous transfer descriptor have been removed. + * + * Interrupt Transfers. + * -------------------- + * For Interupt transfers USB_MAX_TEMP_INT_TD Transfer descriptor are available. They + * will be inserted after the appropriate (depending the interval setting) skeleton TD. + * If an interrupt has been detected the dev->irqhandler is called. The status and number + * of transfered bytes is stored in dev->irq_status resp. dev->irq_act_len. If the + * dev->irqhandler returns 0, the interrupt TD is removed and disabled. If an 1 is returned, + * the interrupt TD will be reactivated. + * + * Control Transfers + * ----------------- + * Control Transfers are issued by filling the tmp_td with the appropriate data and connect + * them to the qh_cntrl queue header. Before other control/bulk transfers can be issued, + * the programm has to wait for completion. This does not allows asynchronous data transfer. + * + * Bulk Transfers + * -------------- + * Bulk Transfers are issued by filling the tmp_td with the appropriate data and connect + * them to the qh_bulk queue header. Before other control/bulk transfers can be issued, + * the programm has to wait for completion. This does not allows asynchronous data transfer. + * + * + */ + +#include + +#ifdef CONFIG_4xx +#include <405gp_pci.h> +#endif +#ifdef CONFIG_USB_UHCI + +#include +#include "usb_uhci.h" + +#define USB_MAX_TEMP_TD 128 /* number of temporary TDs for bulk and control transfers */ +#define USB_MAX_TEMP_INT_TD 32 /* number of temporary TDs for Interrupt transfers */ + + +#undef USB_UHCI_DEBUG + +#ifdef USB_UHCI_DEBUG +#define USB_UHCI_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define USB_UHCI_PRINTF(fmt,args...) +#endif + + +static int irqvec = -1; /* irq vector, if -1 uhci is stopped / reseted */ +unsigned long usb_base_addr; /* base address */ + +static uhci_td_t td_int[8]; /* Interrupt Transfer descriptors */ +static uhci_qh_t qh_cntrl; /* control Queue Head */ +static uhci_qh_t qh_bulk; /* bulk Queue Head */ +static uhci_qh_t qh_end; /* end Queue Head */ +static uhci_td_t td_last; /* last TD (linked with end chain) */ + +/* temporary tds */ +static uhci_td_t tmp_td[USB_MAX_TEMP_TD]; /* temporary bulk/control td's */ +static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD]; /* temporary interrupt td's */ + +static unsigned long framelist[1024] __attribute__ ((aligned (0x1000))); /* frame list */ + +static struct virt_root_hub rh; /* struct for root hub */ + +/********************************************************************** + * some forward decleration + */ +int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len,struct devrequest *setup); + +/* fill a td with the approproiate data. Link, status, info and buffer + * are used by the USB controller itselfes, dev is used to identify the + * "connected" device + */ +void usb_fill_td(uhci_td_t* td,unsigned long link,unsigned long status, + unsigned long info, unsigned long buffer, unsigned long dev) +{ + td->link=swap_32(link); + td->status=swap_32(status); + td->info=swap_32(info); + td->buffer=swap_32(buffer); + td->dev_ptr=dev; +} + +/* fill a qh with the approproiate data. Head and element are used by the USB controller + * itselfes. As soon as a valid dev_ptr is filled, a td chain is connected to the qh. + * Please note, that after completion of the td chain, the entry element is removed / + * marked invalid by the USB controller. + */ +void usb_fill_qh(uhci_qh_t* qh,unsigned long head,unsigned long element) +{ + qh->head=swap_32(head); + qh->element=swap_32(element); + qh->dev_ptr=0L; +} + +/* get the status of a td->status + */ +unsigned long usb_uhci_td_stat(unsigned long status) +{ + unsigned long result=0; + result |= (status & TD_CTRL_NAK) ? USB_ST_NAK_REC : 0; + result |= (status & TD_CTRL_STALLED) ? USB_ST_STALLED : 0; + result |= (status & TD_CTRL_DBUFERR) ? USB_ST_BUF_ERR : 0; + result |= (status & TD_CTRL_BABBLE) ? USB_ST_BABBLE_DET : 0; + result |= (status & TD_CTRL_CRCTIMEO) ? USB_ST_CRC_ERR : 0; + result |= (status & TD_CTRL_BITSTUFF) ? USB_ST_BIT_ERR : 0; + result |= (status & TD_CTRL_ACTIVE) ? USB_ST_NOT_PROC : 0; + return result; +} + +/* get the status and the transfered len of a td chain. + * called from the completion handler + */ +int usb_get_td_status(uhci_td_t *td,struct usb_device *dev) +{ + unsigned long temp,info; + unsigned long stat; + uhci_td_t *mytd=td; + + if(dev->devnum==rh.devnum) + return 0; + dev->act_len=0; + stat=0; + do { + temp=swap_32((unsigned long)mytd->status); + stat=usb_uhci_td_stat(temp); + info=swap_32((unsigned long)mytd->info); + if(((info & 0xff)!= USB_PID_SETUP) && + (((info >> 21) & 0x7ff)!= 0x7ff) && + (temp & 0x7FF)!=0x7ff) + { /* if not setup and not null data pack */ + dev->act_len+=(temp & 0x7FF) + 1; /* the transfered len is act_len + 1 */ + } + if(stat) { /* status no ok */ + dev->status=stat; + return -1; + } + temp=swap_32((unsigned long)mytd->link); + mytd=(uhci_td_t *)(temp & 0xfffffff0); + }while((temp & 0x1)==0); /* process all TDs */ + dev->status=stat; + return 0; /* Ok */ +} + + +/*------------------------------------------------------------------- + * LOW LEVEL STUFF + * assembles QHs und TDs for control, bulk and iso + *-------------------------------------------------------------------*/ + +/* Submits a control message. That is a Setup, Data and Status transfer. + * Routine does not wait for completion. + */ +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len,struct devrequest *setup) +{ + unsigned long destination, status; + int maxsze = usb_maxpacket(dev, pipe); + unsigned long dataptr; + int len; + int pktsze; + int i=0; + + if (!maxsze) { + USB_UHCI_PRINTF("uhci_submit_control_urb: pipesize for pipe %lx is zero\n", pipe); + return -1; + } + if(((pipe>>8)&0x7f)==rh.devnum) { + /* this is the root hub -> redirect it */ + return uhci_submit_rh_msg(dev,pipe,buffer,transfer_len,setup); + } + USB_UHCI_PRINTF("uhci_submit_control start len %x, maxsize %x\n",transfer_len,maxsze); + /* The "pipe" thing contains the destination in bits 8--18 */ + destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; /* Setup stage */ + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27); + /* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD); */ + /* Build the TD for the control request, try forever, 8 bytes of data */ + usb_fill_td(&tmp_td[i],UHCI_PTR_TERM ,status, destination | (7 << 21),(unsigned long)setup,(unsigned long)dev); +#if 0 + { + char *sp=(char *)setup; + printf("SETUP to pipe %lx: %x %x %x %x %x %x %x %x\n", pipe, + sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]); + } +#endif + dataptr = (unsigned long)buffer; + len=transfer_len; + + /* If direction is "send", change the frame from SETUP (0x2D) + to OUT (0xE1). Else change it from SETUP to IN (0x69). */ + destination = (pipe & PIPE_DEVEP_MASK) | ((pipe & USB_DIR_IN)==0 ? USB_PID_OUT : USB_PID_IN); + while (len > 0) { + /* data stage */ + pktsze = len; + i++; + if (pktsze > maxsze) + pktsze = maxsze; + destination ^= 1 << TD_TOKEN_TOGGLE; /* toggle DATA0/1 */ + usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, destination | ((pktsze - 1) << 21),dataptr,(unsigned long)dev); /* Status, pktsze bytes of data */ + tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]); + + dataptr += pktsze; + len -= pktsze; + } + + /* Build the final TD for control status */ + /* It's only IN if the pipe is out AND we aren't expecting data */ + + destination &= ~UHCI_PID; + if (((pipe & USB_DIR_IN)==0) || (transfer_len == 0)) + destination |= USB_PID_IN; + else + destination |= USB_PID_OUT; + destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ + i++; + status &=~TD_CTRL_SPD; + /* no limit on errors on final packet , 0 bytes of data */ + usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21),0,(unsigned long)dev); + tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]); /* queue status td */ + /* usb_show_td(i+1);*/ + USB_UHCI_PRINTF("uhci_submit_control end (%d tmp_tds used)\n",i); + /* first mark the control QH element terminated */ + qh_cntrl.element=0xffffffffL; + /* set qh active */ + qh_cntrl.dev_ptr=(unsigned long)dev; + /* fill in tmp_td_chain */ + qh_cntrl.element=swap_32((unsigned long)&tmp_td[0]); + return 0; +} + +/*------------------------------------------------------------------- + * Prepare TDs for bulk transfers. + */ +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len) +{ + unsigned long destination, status,info; + unsigned long dataptr; + int maxsze = usb_maxpacket(dev, pipe); + int len; + int i=0; + + if(transfer_len < 0) { + printf("Negative transfer length in submit_bulk\n"); + return -1; + } + if (!maxsze) + return -1; + /* The "pipe" thing contains the destination in bits 8--18. */ + destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27); + /* ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); */ + /* Build the TDs for the bulk request */ + len = transfer_len; + dataptr = (unsigned long)buffer; + do { + int pktsze = len; + if (pktsze > maxsze) + pktsze = maxsze; + /* pktsze bytes of data */ + info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) | + (usb_gettoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); + + if((len-pktsze)==0) + status |= TD_CTRL_IOC; /* last one generates INT */ + + usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, info,dataptr,(unsigned long)dev); /* Status, pktsze bytes of data */ + if(i>0) + tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]); + i++; + dataptr += pktsze; + len -= pktsze; + usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); + } while (len > 0); + /* first mark the bulk QH element terminated */ + qh_bulk.element=0xffffffffL; + /* set qh active */ + qh_bulk.dev_ptr=(unsigned long)dev; + /* fill in tmp_td_chain */ + qh_bulk.element=swap_32((unsigned long)&tmp_td[0]); + return 0; +} + + +/* search a free interrupt td + */ +uhci_td_t *uhci_alloc_int_td(void) +{ + int i; + for(i=0;i free TD */ + return &tmp_int_td[i]; + } + return NULL; +} + +#if 0 +void uhci_show_temp_int_td(void) +{ + int i; + for(i=0;i free TD */ + printf("temp_td %d is assigned to dev %lx\n",i,tmp_int_td[i].dev_ptr); + } + printf("all others temp_tds are free\n"); +} +#endif +/*------------------------------------------------------------------- + * submits USB interrupt (ie. polling ;-) + */ +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len, int interval) +{ + int nint, n; + unsigned long status, destination; + unsigned long info,tmp; + uhci_td_t *mytd; + if (interval < 0 || interval >= 256) + return -1; + + if (interval == 0) + nint = 0; + else { + for (nint = 0, n = 1; nint <= 8; nint++, n += n) /* round interval down to 2^n */ + { + if(interval < n) { + interval = n / 2; + break; + } + } + nint--; + } + + USB_UHCI_PRINTF("Rounded interval to %i, chain %i\n", interval, nint); + mytd=uhci_alloc_int_td(); + if(mytd==NULL) { + printf("No free INT TDs found\n"); + return -1; + } + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27); +/* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); +*/ + + destination =(pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe) | (((transfer_len - 1) & 0x7ff) << 21); + + info = destination | (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE); + tmp = swap_32(td_int[nint].link); + usb_fill_td(mytd,tmp,status, info,(unsigned long)buffer,(unsigned long)dev); + /* Link it */ + tmp = swap_32((unsigned long)mytd); + td_int[nint].link=tmp; + + usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); + + return 0; +} + +/********************************************************************** + * Low Level functions + */ + + +void reset_hc(void) +{ + + /* Global reset for 100ms */ + out16r( usb_base_addr + USBPORTSC1,0x0204); + out16r( usb_base_addr + USBPORTSC2,0x0204); + out16r( usb_base_addr + USBCMD,USBCMD_GRESET | USBCMD_RS); + /* Turn off all interrupts */ + out16r(usb_base_addr + USBINTR,0); + wait_ms(50); + out16r( usb_base_addr + USBCMD,0); + wait_ms(10); +} + +void start_hc(void) +{ + int timeout = 1000; + + while(in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) { + if (!--timeout) { + printf("USBCMD_HCRESET timed out!\n"); + break; + } + } + /* Turn on all interrupts */ + out16r(usb_base_addr + USBINTR,USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP); + /* Start at frame 0 */ + out16r(usb_base_addr + USBFRNUM,0); + /* set Framebuffer base address */ + out32r(usb_base_addr+USBFLBASEADD,(unsigned long)&framelist); + /* Run and mark it configured with a 64-byte max packet */ + out16r(usb_base_addr + USBCMD,USBCMD_RS | USBCMD_CF | USBCMD_MAXP); +} + +/* Initialize the skeleton + */ +void usb_init_skel(void) +{ + unsigned long temp; + int n; + + for(n=0;nstatus & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */ + qh_cntrl.dev_ptr=0; + } + } + /* now process the bulk */ + if(qh_bulk.dev_ptr!=0) /* it's a device assigned check if this caused IRQ */ + { + dev=(struct usb_device *)qh_bulk.dev_ptr; + usb_get_td_status(&tmp_td[0],dev); /* update status */ + if(!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */ + qh_bulk.dev_ptr=0; + } + } +} + +/* check the interrupt chain, ubdate the status of the appropriate device, + * call the appropriate irqhandler and reactivate the TD if the irqhandler + * returns with 1 + */ +void usb_check_int_chain(void) +{ + int i,res; + unsigned long link,status; + struct usb_device *dev; + uhci_td_t *td,*prevtd; + + for(i=0;i<8;i++) { + prevtd=&td_int[i]; /* the first previous td is the skeleton td */ + link=swap_32(td_int[i].link) & 0xfffffff0; /* next in chain */ + td=(uhci_td_t *)link; /* assign it */ + /* all interrupt TDs are finally linked to the td_int[0]. + * so we process all until we find the td_int[0]. + * if int0 chain points to a QH, we're also done + */ + while(((i>0) && (link != (unsigned long)&td_int[0])) || + ((i==0) && !(swap_32(td->link) & UHCI_PTR_QH))) + { + /* check if a device is assigned with this td */ + status=swap_32(td->status); + if((td->dev_ptr!=0L) && !(status & TD_CTRL_ACTIVE)) { + /* td is not active and a device is assigned -> call irqhandler */ + dev=(struct usb_device *)td->dev_ptr; + dev->irq_act_len=((status & 0x7FF)==0x7FF) ? 0 : (status & 0x7FF) + 1; /* transfered length */ + dev->irq_status=usb_uhci_td_stat(status); /* get status */ + res=dev->irq_handle(dev); /* call irqhandler */ + if(res==1) { + /* reactivate */ + status|=TD_CTRL_ACTIVE; + td->status=swap_32(status); + prevtd=td; /* previous td = this td */ + } + else { + prevtd->link=td->link; /* link previous td directly to the nex td -> unlinked */ + /* remove device pointer */ + td->dev_ptr=0L; + } + } /* if we call the irq handler */ + link=swap_32(td->link) & 0xfffffff0; /* next in chain */ + td=(uhci_td_t *)link; /* assign it */ + } /* process all td in this int chain */ + } /* next interrupt chain */ +} + + +/* usb interrupt service routine. + */ +void handle_usb_interrupt(void) +{ + unsigned short status; + + /* + * Read the interrupt status, and write it back to clear the + * interrupt cause + */ + + status = in16r(usb_base_addr + USBSTS); + + if (!status) /* shared interrupt, not mine */ + return; + if (status != 1) { + /* remove host controller halted state */ + if ((status&0x20) && ((in16r(usb_base_addr+USBCMD) && USBCMD_RS)==0)) { + out16r(usb_base_addr + USBCMD, USBCMD_RS | in16r(usb_base_addr + USBCMD)); + } + } + usb_check_int_chain(); /* call interrupt handlers for int tds */ + usb_check_skel(); /* call completion handler for common transfer routines */ + out16r(usb_base_addr+USBSTS,status); +} + + +/* init uhci + */ +int usb_lowlevel_init(void) +{ + unsigned long temp; + int busdevfunc; + + busdevfunc=PCI_Find_Device(USB_UHCI_VEND_ID,USB_UHCI_DEV_ID); /* get PCI Device ID */ + if(busdevfunc==-1) { + printf("Error USB UHCI (%04X,%04X) not found\n",USB_UHCI_VEND_ID,USB_UHCI_DEV_ID); + return -1; + } + irqvec=PCI_Read_CFG_Reg(busdevfunc,PCI_CFG_DEV_INT_LINE,1); + irq_free_handler(irqvec); + USB_UHCI_PRINTF("Interrupt Line = %d, is %d\n",irqvec); + temp=PCI_Read_CFG_Reg(busdevfunc,PCI_CFG_DEV_INT_PIN,1); + USB_UHCI_PRINTF("Interrupt Pin = %ld\n",temp); + usb_base_addr=PCI_Read_CFG_Reg(busdevfunc,PCI_CFG_BASE_ADDRESS_4,4); + USB_UHCI_PRINTF("IO Base Address = 0x%lx\n",usb_base_addr); + usb_base_addr&=0xFFFFFFF0; + usb_base_addr+=CFG_ISA_IO_BASE_ADDRESS; + rh.devnum = 0; + usb_init_skel(); + reset_hc(); + start_hc(); + irq_install_handler(irqvec, (interrupt_handler_t *)handle_usb_interrupt, NULL); + return 0; +} + +/* stop uhci + */ +int usb_lowlevel_stop(void) +{ + if(irqvec==-1) + return 1; + irq_free_handler(irqvec); + reset_hc(); + irqvec=-1; + return 0; +} + +/******************************************************************************************* + * Virtual Root Hub + * Since the uhci does not have a real HUB, we simulate one ;-) + */ +#undef USB_RH_DEBUG + +#ifdef USB_RH_DEBUG +#define USB_RH_PRINTF(fmt,args...) printf (fmt ,##args) +static void usb_display_wValue(unsigned short wValue,unsigned short wIndex); +static void usb_display_Req(unsigned short req); +#else +#define USB_RH_PRINTF(fmt,args...) +static void usb_display_wValue(unsigned short wValue,unsigned short wIndex) {} +static void usb_display_Req(unsigned short req) {} +#endif + +static unsigned char root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, /* __u16 bcdUSB; v1.0 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x01, /* __u8 iManufacturer; */ + 0x00, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static unsigned char root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + + +static unsigned char root_hub_hub_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x29, /* __u8 bDescriptorType; Hub-descriptor */ + 0x02, /* __u8 bNbrPorts; */ + 0x00, /* __u16 wHubCharacteristics; */ + 0x00, + 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ + 0x00, /* __u8 bHubContrCurrent; 0 mA */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ +}; + +static unsigned char root_hub_str_index0[] = +{ + 0x04, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 0x09, /* __u8 lang ID */ + 0x04, /* __u8 lang ID */ +}; + +static unsigned char root_hub_str_index1[] = +{ + 28, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 'U', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'C', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'I', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'R', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'u', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'b', /* __u8 Unicode */ + 0, /* __u8 Unicode */ +}; + + +/* + * Root Hub Control Pipe (interrupt Pipes are not supported) + */ + + +int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len,struct devrequest *cmd) +{ + void *data = buffer; + int leni = transfer_len; + int len = 0; + int status = 0; + int stat = 0; + int i; + + unsigned short cstatus; + + unsigned short bmRType_bReq; + unsigned short wValue; + unsigned short wIndex; + unsigned short wLength; + + if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + printf("Root-Hub submit IRQ: NOT implemented\n"); +#if 0 + uhci->rh.urb = urb; + uhci->rh.send = 1; + uhci->rh.interval = urb->interval; + rh_init_int_timer (urb); +#endif + return 0; + } + bmRType_bReq = cmd->requesttype | cmd->request << 8; + wValue = swap_16(cmd->value); + wIndex = swap_16(cmd->index); + wLength = swap_16(cmd->length); + usb_display_Req(bmRType_bReq); + for (i = 0; i < 8; i++) + rh.c_p_r[i] = 0; + USB_RH_PRINTF("Root-Hub: adr: %2x cmd(%1x): %02x%02x %04x %04x %04x\n", + dev->devnum, 8, cmd->requesttype,cmd->request, wValue, wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(unsigned short *) data = swap_16(1); + len=2; + break; + case RH_GET_STATUS | RH_INTERFACE: + *(unsigned short *) data = swap_16(0); + len=2; + break; + case RH_GET_STATUS | RH_ENDPOINT: + *(unsigned short *) data = swap_16(0); + len=2; + break; + case RH_GET_STATUS | RH_CLASS: + *(unsigned long *) data = swap_32(0); + len=4; + break; /* hub power ** */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + + status = in16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1)); + cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | + ((status & USBPORTSC_PEC) >> (3 - 1)) | + (rh.c_p_r[wIndex - 1] << (0 + 4)); + status = (status & USBPORTSC_CCS) | + ((status & USBPORTSC_PE) >> (2 - 1)) | + ((status & USBPORTSC_SUSP) >> (12 - 2)) | + ((status & USBPORTSC_PR) >> (9 - 4)) | + (1 << 8) | /* power on ** */ + ((status & USBPORTSC_LSDA) << (-8 + 9)); + + *(unsigned short *) data = swap_16(status); + *(unsigned short *) (data + 2) = swap_16(cstatus); + len=4; + break; + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): + len=0; + break; + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case (RH_C_HUB_OVER_CURRENT): + len=0; /* hub power over current ** */ + break; + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + usb_display_wValue(wValue,wIndex); + switch (wValue) { + case (RH_PORT_ENABLE): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) & ~USBPORTSC_PE; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_PORT_SUSPEND): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) & ~USBPORTSC_SUSP; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_PORT_POWER): + len=0; /* port power ** */ + break; + case (RH_C_PORT_CONNECTION): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_CSC; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_C_PORT_ENABLE): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_PEC; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_C_PORT_SUSPEND): +/*** WR_RH_PORTSTAT(RH_PS_PSSC); */ + len=0; + break; + case (RH_C_PORT_OVER_CURRENT): + len=0; + break; + case (RH_C_PORT_RESET): + rh.c_p_r[wIndex - 1] = 0; + len=0; + break; + } + break; + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + usb_display_wValue(wValue,wIndex); + switch (wValue) { + case (RH_PORT_SUSPEND): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_SUSP; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_PORT_RESET): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_PR; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + wait_ms(10); + status = (status & 0xfff5) & ~USBPORTSC_PR; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + udelay(10); + status = (status & 0xfff5) | USBPORTSC_PE; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + wait_ms(10); + status = (status & 0xfff5) | 0xa; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + case (RH_PORT_POWER): + len=0; /* port power ** */ + break; + case (RH_PORT_ENABLE): + status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); + status = (status & 0xfff5) | USBPORTSC_PE; + out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status); + len=0; + break; + } + break; + + case RH_SET_ADDRESS: + rh.devnum = wValue; + len=0; + break; + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + i=sizeof(root_hub_config_des); + status=i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_dev_des, len); + break; + case (0x02): /* configuration descriptor */ + i=sizeof(root_hub_config_des); + status=i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_config_des, len); + break; + case (0x03): /*string descriptors */ + if(wValue==0x0300) { + i=sizeof(root_hub_str_index0); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_str_index0, len); + break; + } + if(wValue==0x0301) { + i=sizeof(root_hub_str_index1); + status = i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_str_index1, len); + break; + } + stat = USB_ST_STALLED; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + root_hub_hub_des[2] = 2; + i=sizeof(root_hub_hub_des); + status= i > wLength ? wLength : i; + len = leni > status ? status : leni; + memcpy (data, root_hub_hub_des, len); + break; + case RH_GET_CONFIGURATION: + *(unsigned char *) data = 0x01; + len = 1; + break; + case RH_SET_CONFIGURATION: + len=0; + break; + default: + stat = USB_ST_STALLED; + } + USB_RH_PRINTF("Root-Hub stat %lx port1: %x port2: %x\n\n",stat, + in16r(usb_base_addr + USBPORTSC1), in16r(usb_base_addr + USBPORTSC2)); + dev->act_len=len; + dev->status=stat; + return stat; + +} + +/******************************************************************************** + * Some Debug Routines + */ + +#ifdef USB_RH_DEBUG + +static void usb_display_Req(unsigned short req) +{ + USB_RH_PRINTF("- Root-Hub Request: "); + switch (req) { + case RH_GET_STATUS: + USB_RH_PRINTF("Get Status "); + break; + case RH_GET_STATUS | RH_INTERFACE: + USB_RH_PRINTF("Get Status Interface "); + break; + case RH_GET_STATUS | RH_ENDPOINT: + USB_RH_PRINTF("Get Status Endpoint "); + break; + case RH_GET_STATUS | RH_CLASS: + USB_RH_PRINTF("Get Status Class"); + break; /* hub power ** */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Get Status Class Others"); + break; + case RH_CLEAR_FEATURE | RH_ENDPOINT: + USB_RH_PRINTF("Clear Feature Endpoint "); + break; + case RH_CLEAR_FEATURE | RH_CLASS: + USB_RH_PRINTF("Clear Feature Class "); + break; + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Clear Feature Other Class "); + break; + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + USB_RH_PRINTF("Set Feature Other Class "); + break; + case RH_SET_ADDRESS: + USB_RH_PRINTF("Set Address "); + break; + case RH_GET_DESCRIPTOR: + USB_RH_PRINTF("Get Descriptor "); + break; + case RH_GET_DESCRIPTOR | RH_CLASS: + USB_RH_PRINTF("Get Descriptor Class "); + break; + case RH_GET_CONFIGURATION: + USB_RH_PRINTF("Get Configuration "); + break; + case RH_SET_CONFIGURATION: + USB_RH_PRINTF("Get Configuration "); + break; + default: + USB_RH_PRINTF("****UNKNOWN**** 0x%04X ",req); + } + USB_RH_PRINTF("\n"); + +} + +static void usb_display_wValue(unsigned short wValue,unsigned short wIndex) +{ + switch (wValue) { + case (RH_PORT_ENABLE): + USB_RH_PRINTF("Root-Hub: Enable Port %d\n",wIndex); + break; + case (RH_PORT_SUSPEND): + USB_RH_PRINTF("Root-Hub: Suspend Port %d\n",wIndex); + break; + case (RH_PORT_POWER): + USB_RH_PRINTF("Root-Hub: Port Power %d\n",wIndex); + break; + case (RH_C_PORT_CONNECTION): + USB_RH_PRINTF("Root-Hub: C Port Connection Port %d\n",wIndex); + break; + case (RH_C_PORT_ENABLE): + USB_RH_PRINTF("Root-Hub: C Port Enable Port %d\n",wIndex); + break; + case (RH_C_PORT_SUSPEND): + USB_RH_PRINTF("Root-Hub: C Port Suspend Port %d\n",wIndex); + break; + case (RH_C_PORT_OVER_CURRENT): + USB_RH_PRINTF("Root-Hub: C Port Over Current Port %d\n",wIndex); + break; + case (RH_C_PORT_RESET): + USB_RH_PRINTF("Root-Hub: C Port reset Port %d\n",wIndex); + break; + default: + USB_RH_PRINTF("Root-Hub: unknown %x %x\n",wValue,wIndex); + break; + } +} + +#endif + + + +#ifdef USB_UHCI_DEBUG + +static int usb_display_td(uhci_td_t *td) +{ + unsigned long tmp; + int valid; + + printf("TD at %p:\n",td); + + tmp=swap_32(td->link); + printf("Link points to 0x%08lX, %s first, %s, %s\n",tmp&0xfffffff0, + ((tmp & 0x4)==0x4) ? "Depth" : "Breath", + ((tmp & 0x2)==0x2) ? "QH" : "TD", + ((tmp & 0x1)==0x1) ? "invalid" : "valid"); + valid=((tmp & 0x1)==0x0); + tmp=swap_32(td->status); + printf(" %s %ld Errors %s %s %s \n %s %s %s %s %s %s\n Len 0x%lX\n", + (((tmp>>29)&0x1)==0x1) ? "SPD Enable" : "SPD Disable", + ((tmp>>28)&0x3), + (((tmp>>26)&0x1)==0x1) ? "Low Speed" : "Full Speed", + (((tmp>>25)&0x1)==0x1) ? "ISO " : "", + (((tmp>>24)&0x1)==0x1) ? "IOC " : "", + (((tmp>>23)&0x1)==0x1) ? "Active " : "Inactive ", + (((tmp>>22)&0x1)==0x1) ? "Stalled" : "", + (((tmp>>21)&0x1)==0x1) ? "Data Buffer Error" : "", + (((tmp>>20)&0x1)==0x1) ? "Babble" : "", + (((tmp>>19)&0x1)==0x1) ? "NAK" : "", + (((tmp>>18)&0x1)==0x1) ? "Bitstuff Error" : "", + (tmp&0x7ff)); + tmp=swap_32(td->info); + printf(" MaxLen 0x%lX\n",((tmp>>21)&0x7FF)); + printf(" %s Endpoint 0x%lX Dev Addr 0x%lX PID 0x%lX\n",((tmp>>19)&0x1)==0x1 ? "TOGGLE" : "", + ((tmp>>15)&0xF),((tmp>>8)&0x7F),tmp&0xFF); + tmp=swap_32(td->buffer); + printf(" Buffer 0x%08lX\n",tmp); + printf(" DEV %08lX\n",td->dev_ptr); + return valid; +} + + +void usb_show_td(int max) +{ + int i; + if(max>0) { + for(i=0;i: */ +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ +#define TD_CTRL_ACTLEN_MASK 0x7ff /* actual length, encoded as n - 1 */ + +#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) + +#define TD_TOKEN_TOGGLE 19 + +/* ------------------------------------------------------------------------------------ + Virtual Root HUB + ------------------------------------------------------------------------------------ */ +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +/* Our Vendor Specific feature */ +#define RH_REMOVE_EP 0x00 + + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + + +/* Transfer descriptor structure */ +typedef struct { + unsigned long link; /* next td/qh (LE)*/ + unsigned long status; /* status of the td */ + unsigned long info; /* Max Lenght / Endpoint / device address and PID */ + unsigned long buffer; /* pointer to data buffer (LE) */ + unsigned long dev_ptr; /* pointer to the assigned device (BE) */ + unsigned long res[3]; /* reserved (TDs must be 8Byte aligned) */ +} uhci_td_t, *puhci_td_t; + +/* Queue Header structure */ +typedef struct { + unsigned long head; /* Next QH (LE)*/ + unsigned long element; /* Queue element pointer (LE) */ + unsigned long res[5]; /* reserved */ + unsigned long dev_ptr; /* if 0 no tds have been assigned to this qh */ +} uhci_qh_t, *puhci_qh_t; + +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + int numports; /* number of ports */ + int c_p_r[8]; /* C_PORT_RESET */ +}; + + +#endif /* _USB_UHCI_H_ */ + + diff --git a/board/mpl/common/vga_table.h b/board/mpl/common/vga_table.h new file mode 100644 index 0000000..d1cf5a6 --- /dev/null +++ b/board/mpl/common/vga_table.h @@ -0,0 +1,5115 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG, d.peter@mpl.ch. + * + * 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 + * + * Note: Parts of these software are imported from + * - UBL, The Universal Talkware Boot Loader + * Copyright (C) 2000 Universal Talkware Inc. + * - Linux + * + * File: vga_table.c + * + * contains all tables (include fonts) for the vga controller. + * + **********************************************/ +#ifndef _VGA_TABLE_H +#define _VGA_TABLE_H + +/* table for VGA Initialization */ +typedef struct { + const unsigned char reg; + const unsigned char val; +} VIDEO_CFG_TABLE; + +/* Attribute table */ +static VIDEO_CFG_TABLE attr[] = { + { 0x00, 0x00 }, /* black */ + { 0x01, 0x01 }, /* blue */ + { 0x02, 0x02 }, /* green */ + { 0x03, 0x03 }, /* cyan */ + { 0x04, 0x04 }, /* red */ + { 0x05, 0x05 }, /* magenta */ + { 0x06, 0x14 }, /* brown */ + { 0x07, 0x07 }, /* white */ + { 0x08, 0x38 }, /* dark gray */ + { 0x09, 0x39 }, /* light blue */ + { 0x0A, 0x3A }, /* light green */ + { 0x0B, 0x3B }, /* light Cyan */ + { 0x0C, 0x3C }, /* light red */ + { 0x0D, 0x3D }, /* light magenta */ + { 0x0E, 0x3E }, /* yellow */ + { 0x0F, 0x3F }, /* intense white */ + { 0x10, 0x0C }, /* mode control */ + { 0x11, 0x00 }, /* overscan color */ + { 0x12, 0x0f }, /* color plane enable */ + { 0x13, 0x08 }, /* horizontal Pel Panning */ + { 0x14, 0x00 }, /* color select */ + { 0xFF, 0xFF} /* end of table */ +}; + +/* Values for VGA 80 x 25 Text mode */ +static VIDEO_CFG_TABLE crtc[] = { + {0x00,0x5F}, /* horizontal total */ + {0x01,0x4F}, /* horizontal displayed */ + {0x02,0x50}, /* horizontal blank start */ + {0x03,0x82}, /* horizontal blank end MIP520 BIOS*/ + {0x04,0x55}, /* horizontal synch pos MIP520 */ + {0x05,0x9F}, /* horizontal synch width BIOS Source */ + {0x06,0xBF}, /* vertical total BIOS MIP520*/ + {0x07,0x1F}, /* overflow */ + {0x08,0x00}, /* prescan */ + {0x09,0x4F}, /* maximum scanline */ + {0x0A,0x0D}, /* cursor start */ + {0x0B,0x0E}, /* cursor end */ + {0x0C,0x00}, /* start address high byte */ + {0x0D,0x00}, /* start address low byte */ + {0x0E,0x07}, /* cursor location high byte */ + {0x0F,0x80}, /* cursor location low byte */ + {0x10,0x9C}, /* vertical synch start BIOS MIP520*/ + {0x11,0x8E}, /* vertical synch end */ + {0x12,0x8F}, /* vertical display enable end BIOS MIP520 */ + {0x13,0x28}, /* offset */ + {0x14,0x1F}, /* underline row */ + {0x15,0x96}, /* verical blank start */ + {0x16,0xB9}, /* verical blank end */ + {0x17,0xA3}, /* crt Mode Control */ + {0x18,0xFF}, /* line compare */ + /* added for 69000 */ + {0x22,0x20}, /* Memory Latch */ + {0x30,0x00}, /* ext. total vertical register */ + {0x31,0x00}, /* ext. vertical display end */ + {0x32,0x00}, /* ext. vertical synch */ + {0x33,0x00}, /* ext. vertical blanking start */ + {0x38,0x00}, /* ext. total horizontal register */ + {0x3C,0x00}, /* ext. horizontal blanking end */ + {0x40,0x00}, /* ext. start address */ + {0x41,0x00}, /* ext. offset */ + {0x70,0x4F}, /* interlace control register */ + {0x71,0x00}, /* NTSC/PAL Video Output Control */ + {0x72,0x00}, /* NTSC/PAL horizontal serration 1 start */ + {0x73,0x00}, /* NTSC/PAL horizontal serration 2 start */ + {0x74,0x00}, /* NTSC/PAL horizontal pulse width */ + {0x75,0x00}, /* NTSC/PAL filtering burst read length */ + {0x76,0x00}, /* NTSC/PAL filtering burst read quantity */ + {0x77,0x00}, /* NTSC/PAL Filtering Control */ + {0x78,0x00}, /* NTSC/PAL Vertical reduction */ + {0x79,0x00}, /* NTSC/PAL horizontal total fine adjust */ + {0xFF,0xFF} /* end of table */ +}; + +static VIDEO_CFG_TABLE grmr[] = { + {0x00,0x00}, /* all planes are reset */ + {0x01,0x00}, /* no special altering of plane */ + {0x02,0x00}, /* color compare */ + {0x03,0x00}, /* data rotate */ + {0x04,0x00}, /* read plane 0 */ + {0x05,0x10}, /* Mode */ + {0x06,0x0E}, /* misc */ + {0x07,0x00}, /* Color */ + {0x08,0xFF}, /* Bitmask */ + {0xFF,0xFF} /* end of table */ +}; + + +static VIDEO_CFG_TABLE seq[] = { + {0x00,0x03}, /* release the resets */ + {0x01,0x00}, /* clocking mode */ + {0x02,0x03}, /* enable plane 0,1 access */ + {0x03,0x00}, /* character map */ + {0x04,0x02}, /* Memory mode */ + {0x07,0x00}, /* Reset Counter */ + {0xFF,0xFF} /* end of table */ +}; + +static VIDEO_CFG_TABLE xreg[] = { + + { 0x0A, 0x00 }, /* Frame Buffer Mapping */ + { 0x0B, 0x01 }, /* PCI Write Burst support */ + { 0x0E, 0x00 }, /* Frame buffer Page select */ + { 0x20, 0x00 }, /* BitBLT Configuration */ + /* { 0x40, 0x03 }, */ /* Memory Access Control */ + { 0x40, 0x00 }, /* Memory Access Control */ + { 0x60, 0x00 }, /* Video Pin Control */ + { 0x61, 0x00 }, /* DPMS Synch control */ + { 0x62, 0x00 }, /* GPIO Pin Control */ + { 0x63, 0xBD }, /* GPIO Pin Data*/ + { 0x67, 0x00 }, /* Pin Tri-State */ + { 0x80, 0x00 }, /* Pixel Pipeline Config 0 register */ + { 0x81, 0x00 }, /* Pixel Pipeline Config 1 register */ + { 0x82, 0x00 }, /* Pixel Pipeline Config 2 register */ + { 0xA0, 0x00 }, /* Cursor 1 Control Reg */ + { 0xA1, 0x00 }, /* Cursor 1 Vertical Extension Reg */ + { 0xA2, 0x00 }, /* Cursor 1 Base Address Low */ + { 0xA3, 0x00 }, /* Cursor 1 Base Address High */ + { 0xA4, 0x00 }, /* Cursor 1 X-Position Low */ + { 0xA5, 0x00 }, /* Cursor 1 X-Position High */ + { 0xA6, 0x00 }, /* Cursor 1 Y-Position Low */ + { 0xA7, 0x00 }, /* Cursor 1 Y-Position High */ + { 0xA8, 0x00 }, /* Cursor 2 Control Reg */ + { 0xA9, 0x00 }, /* Cursor 2 Vertical Extension Reg */ + { 0xAA, 0x00 }, /* Cursor 2 Base Address Low */ + { 0xAB, 0x00 }, /* Cursor 2 Base Address High */ + { 0xAC, 0x00 }, /* Cursor 2 X-Position Low */ + { 0xAD, 0x00 }, /* Cursor 2 X-Position High */ + { 0xAE, 0x00 }, /* Cursor 2 Y-Position Low */ + { 0xAF, 0x00 }, /* Cursor 2 Y-Position High */ + { 0xC0, 0x7D }, /* Dot Clock 0 VCO M-Divisor */ + { 0xC1, 0x07 }, /* Dot Clock 0 VCO N-Divisor */ + { 0xC3, 0x34 }, /* Dot Clock 0 Divisor select */ + { 0xC4, 0x55 }, /* Dot Clock 1 VCO M-Divisor */ + { 0xC5, 0x09 }, /* Dot Clock 1 VCO N-Divisor */ + { 0xC7, 0x24 }, /* Dot Clock 1 Divisor select */ + { 0xC8, 0x7D }, /* Dot Clock 2 VCO M-Divisor */ + { 0xC9, 0x07 }, /* Dot Clock 2 VCO N-Divisor */ + { 0xCB, 0x34 }, /* Dot Clock 2 Divisor select */ + { 0xCC, 0x38 }, /* Memory Clock 0 VCO M-Divisor */ + { 0xCD, 0x03 }, /* Memory Clock 0 VCO N-Divisor */ + { 0xCE, 0x90 }, /* Memory Clock 0 Divisor select */ + { 0xCF, 0x06 }, /* Clock Config */ + { 0xD0, 0x0F }, /* Power Down */ + { 0xD1, 0x01 }, /* Power Down BitBLT */ + /* { 0xD2, 0x0F }, */ /* 2KHz Counter Power Down */ + { 0xFF, 0xFF} /* end of table */ +}; +/* Clock Config: + * If Loop Divisor = 1 + * Fvco = (Fref * M/N) + * Fout = Fvco / Post Divisor + * Dot Clk0: + * --------- + * M = (M Div + 2) = 127 + * N = (N Div + 2) = 9 + * Post Divisor = 8 + * Loop Divisor = 1 + * Fref = 14.31818MHz => Fvco 202.045MHz => Dot Clock 0 = 25.25MHz + * + * Dot Clk1: + * --------- + * M = (M Div + 2) = 57 + * N = (N Div + 2) = 11 + * Post Divisor = 4 + * Loop Divisor = 1 + * Fref = 14.31818MHz => Fvco 113.24MHz => Dot Clock 1 = 28.31MHz + * + * Dot Clk2: + * --------- + * M = (M Div + 2) = 127 + * N = (N Div + 2) = 9 + * Post Divisor = 8 + * Loop Divisor = 1 + * Fref = 14.31818MHz => Fvco 202.045MHz => Dot Clock 2 = 25.25MHz + * + * Memory Clk: + * ----------- + * M = (M Div + 2) = 58 + * N = (N Div + 2) = 5 + * Post Divisor = 2 + * Fref = 14.31818MHz => Fvco 166MHz => Dot Clock 1 = 83MHz + * + */ + + + +/* DAC datas */ +static unsigned char dac[][3] = { + {0x00, 0x00, 0x00}, /* Index 0 (00) */ + {0x00, 0x00, 0x2A}, /* Index 1 (01) */ + {0x00, 0x2A, 0x00}, /* Index 2 (02) */ + {0x00, 0x2A, 0x2A}, /* Index 3 (03) */ + {0x2A, 0x00, 0x00}, /* Index 4 (04) */ + {0x2A, 0x00, 0x2A}, /* Index 5 (05) */ + {0x2A, 0x2A, 0x00}, /* Index 6 (06) */ + {0x2A, 0x2A, 0x2A}, /* Index 7 (07) */ + {0x00, 0x00, 0x15}, /* Index 8 (08) */ + {0x00, 0x00, 0x3F}, /* Index 9 (09) */ + {0x00, 0x2A, 0x15}, /* Index 10 (0A) */ + {0x00, 0x2A, 0x3F}, /* Index 11 (0B) */ + {0x2A, 0x00, 0x15}, /* Index 12 (0C) */ + {0x2A, 0x00, 0x3F}, /* Index 13 (0D) */ + {0x2A, 0x2A, 0x15}, /* Index 14 (0E) */ + {0x2A, 0x2A, 0x3F}, /* Index 15 (0F) */ + {0x00, 0x15, 0x00}, /* Index 16 (10) */ + {0x00, 0x15, 0x2A}, /* Index 17 (11) */ + {0x00, 0x3F, 0x00}, /* Index 18 (12) */ + {0x00, 0x3F, 0x2A}, /* Index 19 (13) */ + {0x2A, 0x15, 0x00}, /* Index 20 (14) */ + {0x2A, 0x15, 0x2A}, /* Index 21 (15) */ + {0x2A, 0x3F, 0x00}, /* Index 22 (16) */ + {0x2A, 0x3F, 0x2A}, /* Index 23 (17) */ + {0x00, 0x15, 0x15}, /* Index 24 (18) */ + {0x00, 0x15, 0x3F}, /* Index 25 (19) */ + {0x00, 0x3F, 0x15}, /* Index 26 (1A) */ + {0x00, 0x3F, 0x3F}, /* Index 27 (1B) */ + {0x2A, 0x15, 0x15}, /* Index 28 (1C) */ + {0x2A, 0x15, 0x3F}, /* Index 29 (1D) */ + {0x2A, 0x3F, 0x15}, /* Index 30 (1E) */ + {0x2A, 0x3F, 0x3F}, /* Index 31 (1F) */ + {0x15, 0x00, 0x00}, /* Index 32 (20) */ + {0x15, 0x00, 0x2A}, /* Index 33 (21) */ + {0x15, 0x2A, 0x00}, /* Index 34 (22) */ + {0x15, 0x2A, 0x2A}, /* Index 35 (23) */ + {0x3F, 0x00, 0x00}, /* Index 36 (24) */ + {0x3F, 0x00, 0x2A}, /* Index 37 (25) */ + {0x3F, 0x2A, 0x00}, /* Index 38 (26) */ + {0x3F, 0x2A, 0x2A}, /* Index 39 (27) */ + {0x15, 0x00, 0x15}, /* Index 40 (28) */ + {0x15, 0x00, 0x3F}, /* Index 41 (29) */ + {0x15, 0x2A, 0x15}, /* Index 42 (2A) */ + {0x15, 0x2A, 0x3F}, /* Index 43 (2B) */ + {0x3F, 0x00, 0x15}, /* Index 44 (2C) */ + {0x3F, 0x00, 0x3F}, /* Index 45 (2D) */ + {0x3F, 0x2A, 0x15}, /* Index 46 (2E) */ + {0x3F, 0x2A, 0x3F}, /* Index 47 (2F) */ + {0x15, 0x15, 0x00}, /* Index 48 (30) */ + {0x15, 0x15, 0x2A}, /* Index 49 (31) */ + {0x15, 0x3F, 0x00}, /* Index 50 (32) */ + {0x15, 0x3F, 0x2A}, /* Index 51 (33) */ + {0x3F, 0x15, 0x00}, /* Index 52 (34) */ + {0x3F, 0x15, 0x2A}, /* Index 53 (35) */ + {0x3F, 0x3F, 0x00}, /* Index 54 (36) */ + {0x3F, 0x3F, 0x2A}, /* Index 55 (37) */ + {0x15, 0x15, 0x15}, /* Index 56 (38) */ + {0x15, 0x15, 0x3F}, /* Index 57 (39) */ + {0x15, 0x3F, 0x15}, /* Index 58 (3A) */ + {0x15, 0x3F, 0x3F}, /* Index 59 (3B) */ + {0x3F, 0x15, 0x15}, /* Index 60 (3C) */ + {0x3F, 0x15, 0x3F}, /* Index 61 (3D) */ + {0x3F, 0x3F, 0x15}, /* Index 62 (3E) */ + {0x3F, 0x3F, 0x3F}, /* Index 63 (3F) */ + {0x16, 0x1E, 0x17}, /* Index 64 (40) */ + {0x27, 0x2F, 0x00}, /* Index 65 (41) */ + {0x1E, 0x20, 0x18}, /* Index 66 (42) */ + {0x30, 0x04, 0x06}, /* Index 67 (43) */ + {0x08, 0x05, 0x12}, /* Index 68 (44) */ + {0x30, 0x0A, 0x31}, /* Index 69 (45) */ + {0x08, 0x16, 0x07}, /* Index 70 (46) */ + {0x1B, 0x33, 0x21}, /* Index 71 (47) */ + {0x02, 0x2C, 0x16}, /* Index 72 (48) */ + {0x3D, 0x1C, 0x11}, /* Index 73 (49) */ + {0x07, 0x22, 0x33}, /* Index 74 (4A) */ + {0x1D, 0x2B, 0x0A}, /* Index 75 (4B) */ + {0x1A, 0x15, 0x16}, /* Index 76 (4C) */ + {0x15, 0x26, 0x24}, /* Index 77 (4D) */ + {0x05, 0x2B, 0x1E}, /* Index 78 (4E) */ + {0x11, 0x18, 0x01}, /* Index 79 (4F) */ + {0x3A, 0x2C, 0x27}, /* Index 80 (50) */ + {0x25, 0x23, 0x00}, /* Index 81 (51) */ + {0x2A, 0x16, 0x2A}, /* Index 82 (52) */ + {0x18, 0x19, 0x17}, /* Index 83 (53) */ + {0x0B, 0x0F, 0x06}, /* Index 84 (54) */ + {0x00, 0x34, 0x08}, /* Index 85 (55) */ + {0x00, 0x19, 0x12}, /* Index 86 (56) */ + {0x01, 0x06, 0x3B}, /* Index 87 (57) */ + {0x29, 0x0E, 0x25}, /* Index 88 (58) */ + {0x20, 0x10, 0x28}, /* Index 89 (59) */ + {0x02, 0x37, 0x24}, /* Index 90 (5A) */ + {0x08, 0x2A, 0x2E}, /* Index 91 (5B) */ + {0x26, 0x2A, 0x22}, /* Index 92 (5C) */ + {0x0C, 0x0C, 0x2A}, /* Index 93 (5D) */ + {0x28, 0x07, 0x02}, /* Index 94 (5E) */ + {0x34, 0x05, 0x2B}, /* Index 95 (5F) */ + {0x0C, 0x31, 0x33}, /* Index 96 (60) */ + {0x22, 0x08, 0x30}, /* Index 97 (61) */ + {0x00, 0x25, 0x01}, /* Index 98 (62) */ + {0x06, 0x15, 0x01}, /* Index 99 (63) */ + {0x0D, 0x2A, 0x0A}, /* Index 100 (64) */ + {0x08, 0x25, 0x16}, /* Index 101 (65) */ + {0x2A, 0x0A, 0x01}, /* Index 102 (66) */ + {0x08, 0x3B, 0x28}, /* Index 103 (67) */ + {0x00, 0x09, 0x04}, /* Index 104 (68) */ + {0x16, 0x0F, 0x05}, /* Index 105 (69) */ + {0x02, 0x2F, 0x1D}, /* Index 106 (6A) */ + {0x06, 0x3E, 0x02}, /* Index 107 (6B) */ + {0x09, 0x30, 0x07}, /* Index 108 (6C) */ + {0x34, 0x03, 0x06}, /* Index 109 (6D) */ + {0x00, 0x15, 0x2A}, /* Index 110 (6E) */ + {0x39, 0x23, 0x20}, /* Index 111 (6F) */ + {0x2A, 0x32, 0x0C}, /* Index 112 (70) */ + {0x09, 0x31, 0x26}, /* Index 113 (71) */ + {0x27, 0x23, 0x28}, /* Index 114 (72) */ + {0x20, 0x13, 0x0C}, /* Index 115 (73) */ + {0x2C, 0x1E, 0x26}, /* Index 116 (74) */ + {0x20, 0x2F, 0x05}, /* Index 117 (75) */ + {0x22, 0x1B, 0x22}, /* Index 118 (76) */ + {0x09, 0x1C, 0x06}, /* Index 119 (77) */ + {0x16, 0x38, 0x0E}, /* Index 120 (78) */ + {0x22, 0x16, 0x20}, /* Index 121 (79) */ + {0x10, 0x17, 0x25}, /* Index 122 (7A) */ + {0x04, 0x32, 0x22}, /* Index 123 (7B) */ + {0x20, 0x00, 0x37}, /* Index 124 (7C) */ + {0x21, 0x15, 0x1A}, /* Index 125 (7D) */ + {0x01, 0x04, 0x20}, /* Index 126 (7E) */ + {0x02, 0x0C, 0x1E}, /* Index 127 (7F) */ + {0x15, 0x15, 0x29}, /* Index 128 (80) */ + {0x24, 0x3B, 0x00}, /* Index 129 (81) */ + {0x24, 0x28, 0x01}, /* Index 130 (82) */ + {0x20, 0x19, 0x07}, /* Index 131 (83) */ + {0x1A, 0x13, 0x02}, /* Index 132 (84) */ + {0x04, 0x24, 0x1F}, /* Index 133 (85) */ + {0x32, 0x30, 0x08}, /* Index 134 (86) */ + {0x23, 0x12, 0x0B}, /* Index 135 (87) */ + {0x21, 0x38, 0x00}, /* Index 136 (88) */ + {0x04, 0x13, 0x09}, /* Index 137 (89) */ + {0x06, 0x3E, 0x14}, /* Index 138 (8A) */ + {0x23, 0x22, 0x2D}, /* Index 139 (8B) */ + {0x3D, 0x35, 0x30}, /* Index 140 (8C) */ + {0x24, 0x38, 0x05}, /* Index 141 (8D) */ + {0x18, 0x01, 0x26}, /* Index 142 (8E) */ + {0x27, 0x11, 0x38}, /* Index 143 (8F) */ + {0x08, 0x1A, 0x08}, /* Index 144 (90) */ + {0x00, 0x1A, 0x07}, /* Index 145 (91) */ + {0x16, 0x0C, 0x30}, /* Index 146 (92) */ + {0x1B, 0x0A, 0x0B}, /* Index 147 (93) */ + {0x01, 0x0C, 0x09}, /* Index 148 (94) */ + {0x00, 0x33, 0x03}, /* Index 149 (95) */ + {0x13, 0x0A, 0x06}, /* Index 150 (96) */ + {0x22, 0x19, 0x23}, /* Index 151 (97) */ + {0x07, 0x30, 0x39}, /* Index 152 (98) */ + {0x20, 0x07, 0x0D}, /* Index 153 (99) */ + {0x39, 0x18, 0x20}, /* Index 154 (9A) */ + {0x32, 0x31, 0x29}, /* Index 155 (9B) */ + {0x28, 0x3F, 0x02}, /* Index 156 (9C) */ + {0x02, 0x15, 0x3E}, /* Index 157 (9D) */ + {0x27, 0x33, 0x0E}, /* Index 158 (9E) */ + {0x39, 0x2E, 0x1D}, /* Index 159 (9F) */ + {0x1E, 0x38, 0x10}, /* Index 160 (A0) */ + {0x01, 0x33, 0x19}, /* Index 161 (A1) */ + {0x2B, 0x20, 0x0B}, /* Index 162 (A2) */ + {0x29, 0x0B, 0x23}, /* Index 163 (A3) */ + {0x25, 0x04, 0x19}, /* Index 164 (A4) */ + {0x34, 0x36, 0x08}, /* Index 165 (A5) */ + {0x17, 0x1D, 0x01}, /* Index 166 (A6) */ + {0x0A, 0x29, 0x10}, /* Index 167 (A7) */ + {0x14, 0x1C, 0x2B}, /* Index 168 (A8) */ + {0x02, 0x2C, 0x13}, /* Index 169 (A9) */ + {0x14, 0x16, 0x3A}, /* Index 170 (AA) */ + {0x2B, 0x22, 0x28}, /* Index 171 (AB) */ + {0x2E, 0x0A, 0x22}, /* Index 172 (AC) */ + {0x00, 0x20, 0x28}, /* Index 173 (AD) */ + {0x08, 0x22, 0x2D}, /* Index 174 (AE) */ + {0x2C, 0x17, 0x1D}, /* Index 175 (AF) */ + {0x02, 0x0D, 0x20}, /* Index 176 (B0) */ + {0x00, 0x18, 0x2C}, /* Index 177 (B1) */ + {0x19, 0x19, 0x3C}, /* Index 178 (B2) */ + {0x20, 0x32, 0x10}, /* Index 179 (B3) */ + {0x38, 0x1C, 0x21}, /* Index 180 (B4) */ + {0x36, 0x10, 0x00}, /* Index 181 (B5) */ + {0x20, 0x08, 0x19}, /* Index 182 (B6) */ + {0x09, 0x12, 0x01}, /* Index 183 (B7) */ + {0x1D, 0x39, 0x03}, /* Index 184 (B8) */ + {0x20, 0x28, 0x11}, /* Index 185 (B9) */ + {0x35, 0x17, 0x01}, /* Index 186 (BA) */ + {0x0C, 0x02, 0x08}, /* Index 187 (BB) */ + {0x39, 0x0D, 0x10}, /* Index 188 (BC) */ + {0x38, 0x21, 0x16}, /* Index 189 (BD) */ + {0x29, 0x3E, 0x14}, /* Index 190 (BE) */ + {0x0A, 0x1C, 0x28}, /* Index 191 (BF) */ + {0x2F, 0x03, 0x08}, /* Index 192 (C0) */ + {0x02, 0x18, 0x39}, /* Index 193 (C1) */ + {0x0F, 0x31, 0x1E}, /* Index 194 (C2) */ + {0x24, 0x0C, 0x03}, /* Index 195 (C3) */ + {0x04, 0x1A, 0x04}, /* Index 196 (C4) */ + {0x30, 0x33, 0x04}, /* Index 197 (C5) */ + {0x2C, 0x18, 0x36}, /* Index 198 (C6) */ + {0x18, 0x2F, 0x09}, /* Index 199 (C7) */ + {0x03, 0x04, 0x03}, /* Index 200 (C8) */ + {0x22, 0x05, 0x10}, /* Index 201 (C9) */ + {0x03, 0x24, 0x0A}, /* Index 202 (CA) */ + {0x00, 0x1E, 0x1A}, /* Index 203 (CB) */ + {0x00, 0x0A, 0x11}, /* Index 204 (CC) */ + {0x0E, 0x1F, 0x09}, /* Index 205 (CD) */ + {0x1B, 0x3A, 0x3B}, /* Index 206 (CE) */ + {0x22, 0x39, 0x36}, /* Index 207 (CF) */ + {0x22, 0x10, 0x23}, /* Index 208 (D0) */ + {0x31, 0x14, 0x2B}, /* Index 209 (D1) */ + {0x0C, 0x33, 0x35}, /* Index 210 (D2) */ + {0x27, 0x3E, 0x10}, /* Index 211 (D3) */ + {0x10, 0x04, 0x30}, /* Index 212 (D4) */ + {0x05, 0x21, 0x0A}, /* Index 213 (D5) */ + {0x09, 0x11, 0x24}, /* Index 214 (D6) */ + {0x02, 0x2B, 0x00}, /* Index 215 (D7) */ + {0x02, 0x05, 0x15}, /* Index 216 (D8) */ + {0x11, 0x32, 0x1A}, /* Index 217 (D9) */ + {0x2E, 0x1B, 0x08}, /* Index 218 (DA) */ + {0x0D, 0x2F, 0x11}, /* Index 219 (DB) */ + {0x03, 0x30, 0x28}, /* Index 220 (DC) */ + {0x15, 0x38, 0x0A}, /* Index 221 (DD) */ + {0x07, 0x00, 0x00}, /* Index 222 (DE) */ + {0x1D, 0x1C, 0x20}, /* Index 223 (DF) */ + {0x35, 0x11, 0x35}, /* Index 224 (E0) */ + {0x24, 0x29, 0x03}, /* Index 225 (E1) */ + {0x22, 0x37, 0x39}, /* Index 226 (E2) */ + {0x11, 0x1B, 0x10}, /* Index 227 (E3) */ + {0x2D, 0x18, 0x00}, /* Index 228 (E4) */ + {0x20, 0x2F, 0x10}, /* Index 229 (E5) */ + {0x21, 0x26, 0x32}, /* Index 230 (E6) */ + {0x24, 0x10, 0x3D}, /* Index 231 (E7) */ + {0x27, 0x0E, 0x03}, /* Index 232 (E8) */ + {0x31, 0x1F, 0x11}, /* Index 233 (E9) */ + {0x16, 0x0D, 0x02}, /* Index 234 (EA) */ + {0x24, 0x12, 0x16}, /* Index 235 (EB) */ + {0x0F, 0x27, 0x18}, /* Index 236 (EC) */ + {0x10, 0x0E, 0x20}, /* Index 237 (ED) */ + {0x12, 0x0C, 0x0D}, /* Index 238 (EE) */ + {0x14, 0x38, 0x0B}, /* Index 239 (EF) */ + {0x23, 0x0C, 0x09}, /* Index 240 (F0) */ + {0x13, 0x21, 0x0E}, /* Index 241 (F1) */ + {0x2C, 0x05, 0x2C}, /* Index 242 (F2) */ + {0x08, 0x29, 0x01}, /* Index 243 (F3) */ + {0x36, 0x0A, 0x13}, /* Index 244 (F4) */ + {0x08, 0x2D, 0x26}, /* Index 245 (F5) */ + {0x23, 0x30, 0x3E}, /* Index 246 (F6) */ + {0x33, 0x00, 0x04}, /* Index 247 (F7) */ + {0x25, 0x1E, 0x3A}, /* Index 248 (F8) */ + {0x11, 0x2C, 0x26}, /* Index 249 (F9) */ + {0x20, 0x32, 0x27}, /* Index 250 (FA) */ + {0x23, 0x21, 0x13}, /* Index 251 (FB) */ + {0x22, 0x23, 0x1F}, /* Index 252 (FC) */ + {0x31, 0x08, 0x0A}, /* Index 253 (FD) */ + {0x00, 0x01, 0x09}, /* Index 254 (FE) */ + {0x17, 0x07, 0x38} /* Index 255 (FF) */ +}; + + +/*********************************************** + * 8x16 Font + * + * copied from file + * drivers/video/font_8x16.c (LINUX) + **********************************************/ +/**********************************************/ +/* */ +/* Font file generated by cpi2fnt */ +/* */ +/**********************************************/ + +#define FONTDATAMAX 4096 + +unsigned char fontdata_8x16[FONTDATAMAX] = { + + /* 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 */ + + /* 1 0x01 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x81, /* 10000001 */ + 0xa5, /* 10100101 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xdb, /* 11011011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x1a, /* 00011010 */ + 0x32, /* 00110010 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe7, /* 11100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^P' */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0xf0, /* 11110000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0e, /* 00001110 */ + 0x1e, /* 00011110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00101000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x28, /* 00101000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 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 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x86, /* 10000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x78, /* 01111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xdc, /* 11011100 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xde, /* 11011110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xde, /* 11011110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0xee, /* 11101110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0x70, /* 01110000 */ + 0x38, /* 00111000 */ + 0x1c, /* 00011100 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 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 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x36, /* 00110110 */ + 0x32, /* 00110010 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 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 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 '' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 '' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a '' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c '' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e '' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x6e, /* 01101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 '' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a '' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c '' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xe6, /* 11100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e '' */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xf8, /* 11111000 */ + 0xc4, /* 11000100 */ + 0xcc, /* 11001100 */ + 0xde, /* 11011110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f '' */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 ' ' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '¡' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '¢' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '£' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '¤' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '¥' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '¦' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '§' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '¨' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '©' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa 'ª' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '«' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xdc, /* 11011100 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '¬' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xce, /* 11001110 */ + 0x9a, /* 10011010 */ + 0x3f, /* 00111111 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '­' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '®' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '¯' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '°' */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + + /* 177 0xb1 '±' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '²' */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + + /* 179 0xb3 '³' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '´' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 'µ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '¶' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '·' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '¸' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '¹' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba 'º' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '»' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '¼' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '½' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '¾' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '¿' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 'À' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 'Á' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 'Â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 'Ã' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 'Ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 'Å' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 'Æ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 'Ç' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 'È' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 'É' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca 'Ê' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb 'Ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc 'Ì' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd 'Í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce 'Î' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf 'Ï' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 'Ð' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 'Ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 'Ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 'Ó' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 'Ô' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 'Õ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 'Ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '×' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 'Ø' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 'Ù' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda 'Ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb 'Û' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc 'Ü' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd 'Ý' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde 'Þ' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf 'ß' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 'à' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 'á' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 'â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 'ã' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 'ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 'å' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 'æ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 'ç' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 'è' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 'é' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea 'ê' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb 'ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec 'ì' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed 'í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x03, /* 00000011 */ + 0x06, /* 00000110 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xf3, /* 11110011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee 'î' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef 'ï' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 'ð' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 'ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 'ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 'ó' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 'ô' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 'õ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 'ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '÷' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 'ø' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 'ù' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa 'ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb 'û' */ + 0x00, /* 00000000 */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc 'ü' */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd 'ý' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe 'þ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff 'ÿ' */ + 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 */ + +}; + +#endif /* #ifndef _VGA_TABLE_H */ diff --git a/board/mpl/common/video.c b/board/mpl/common/video.c new file mode 100644 index 0000000..71cd1fb --- /dev/null +++ b/board/mpl/common/video.c @@ -0,0 +1,756 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + * Note: Parts of these software are imported from + * - UBL, The Universal Talkware Boot Loader + * Copyright (C) 2000 Universal Talkware Inc. + * - Linux + * + * + */ + +#include +#include +#include +#include +#include "video.h" +#ifdef CONFIG_4xx +#include <405gp_pci.h> +#endif +#include "vga_table.h" + + +#ifdef CONFIG_VIDEO_CT69000 +#define VIDEO_VEND_ID 0x102C +#define VIDEO_DEV_ID 0x00C0 +#else +#error CONFIG_VIDEO_CT69000 must be defined +#endif + +/* + * Routine for resent board info to video + * resides in pip405.c + */ +extern void video_write_board_info(void); + +#undef VGA_DEBUG + +#ifdef VGA_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +#define VGA_MAXROWS 25 +#define VGA_MAXCOLS 80 + +#define CRTC_CURSH 14 /* cursor high pos */ +#define CRTC_CURSL 15 /* cursor low pos */ + +/* description of the hardware layout */ + +#define ATTRI_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3c0 /* Index and Data write port of the attribute Registers */ +#define ATTRI_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3c1 /* Data port of the attribute Registers */ +#define STATUS_REG0 CFG_ISA_IO_BASE_ADDRESS | 0x3c2 /* Status Register 0 (read only) */ +#define MSR_REG_W CFG_ISA_IO_BASE_ADDRESS | 0x3c2 /* Misc. Output Register (write only) */ +#define SEQ_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3c4 /* Index port of the Sequencer Controller */ +#define SEQ_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3c5 /* Data port of the Sequencer Controller */ +#define COL_PAL_MASK CFG_ISA_IO_BASE_ADDRESS | 0x3c6 /* Color Palette Mask */ +#define COL_PAL_STAT CFG_ISA_IO_BASE_ADDRESS | 0x3c7 /* Color Palette Status (read only) */ +#define COL_PAL_IND_R CFG_ISA_IO_BASE_ADDRESS | 0x3c7 /* Color Palette Read Mode Index (write only) */ +#define COL_PAL_IND_W CFG_ISA_IO_BASE_ADDRESS | 0x3c8 /* Color Palette Write Mode Index */ +#define COL_PAL_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3c9 /* Color Palette Data Port */ +#define FCR_REG_R CFG_ISA_IO_BASE_ADDRESS | 0x3ca /* Feature Control Register (read only) */ +#define MSR_REG_R CFG_ISA_IO_BASE_ADDRESS | 0x3cc /* Misc. Output Register (read only) */ +#define GR_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3ce /* Index port of the Graphic Controller Registers */ +#define GR_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3cf /* Data port of the Graphic Controller Registers */ +#define FP_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3d0 /* Index port of the Flat panel Registers */ +#define FP_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3d1 /* Data port of the Flat panel Registers */ +#define MR_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3d2 /* Index Port of the Multimedia Extension */ +#define MR_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3d3 /* Data Port of the Multimedia Extension */ +#define CRT_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3d4 /* Index port of the CRT Controller */ +#define CRT_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3d5 /* Data port of the CRT Controller */ +#define XREG_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3d6 /* Extended Register index */ +#define XREG_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3d7 /* Extended Register data */ +#define STATUS_REG1 CFG_ISA_IO_BASE_ADDRESS | 0x3da /* Input Status Register 1 (read only) */ +#define FCR_REG_W CFG_ISA_IO_BASE_ADDRESS | 0x3da /* Feature Control Register (write only) */ + + +static unsigned char * video_fb; /* Frame buffer */ + +/* current hardware state */ + +static int video_row; +static int video_col; +static unsigned char video_attr; + +static unsigned long font_base_addr; +/********************************************************************** + * some forward declerations... + */ +int video_init(int busdevfunc); +void vga_set_attrib(void); +void vga_set_crt(void); +void vga_set_dac(void); +void vga_set_gr(void); +void vga_set_seq(void); +void vga_set_xreg(void); +void vga_write_sr(unsigned char reg,unsigned char val); +void vga_write_gr(unsigned char reg,unsigned char val); +void vga_write_cr(unsigned char reg,unsigned char val); +void vga_set_font(void); + +/*************************************************************************** + * Init VGA Device + */ + +int drv_video_init(void) +{ + int error, devices = 1 ; + device_t vgadev ; + int busdevfunc; + + busdevfunc=PCI_Find_Device(VIDEO_VEND_ID,VIDEO_DEV_ID); /* get PCI Device ID */ + if(busdevfunc==-1) { + printf("Error VGA Controller (%04X,%04X) not found\n",VIDEO_VEND_ID,VIDEO_DEV_ID); + return -1; + } + video_init(busdevfunc); + video_write_board_info(); + memset (&vgadev, 0, sizeof(vgadev)); + + strcpy(vgadev.name, "vga"); + vgadev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM; + vgadev.putc = video_putc; + vgadev.puts = video_puts; + vgadev.getc = NULL; + vgadev.tstc = NULL; + + error = device_register (&vgadev); + + return (error == 0) ? devices : error ; +} + + +/*********************************************************** + * VGA Initializing + */ + +int video_init(int busdevfunc) +{ + font_base_addr = PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_BASE_ADDRESS_0, 4); + + video_fb = (char*)font_base_addr; /* we look into the big linaer memory area */ + + /* set the extended Registers */ + vga_set_xreg(); + + /* set IO Addresses to 0x3Dx (color mode ) */ + out8(MSR_REG_W,0x01); + + /* Feature Control Register: + Bits 7-4 Reserved = 0 + Bit 3 Vertical Sync select = 1 = Enabled + Bits 2-0 Reserved = 010 = as read from memory. + */ + out8(FCR_REG_W,0x02); + + + /* Miscelaneous output Register: + Bits 7-6 (num lines) = 01 = VGA 400 lines, + Bit 5 (Odd/Even Page) = 1 = Sleect high page of memory, + Bit 4 reserved = 0, + Bits 3-2 (Clocl Select) = 01 = 28.322Mhz + Bit 1 = Display Ram Enable = 1 = Enable processor access. + Bit 0 = Io Address Select = 1 = Color Graphics Enulation. + */ + out8(MSR_REG_W,0x67); + /* set the palette */ + vga_set_dac(); + /* set the attributes (before we bring up the engine + then we dont have to wait for refresh). + */ + vga_set_attrib(); + + /* set the crontroller register. */ + vga_set_crt(); + + vga_write_sr(0x00,0x01); /* synchronous reset */ + vga_write_sr(0x01,0x00); /* clocking mode */ + vga_write_sr(0x02,0x03); /* write to map 0, 1 */ + vga_write_sr(0x03,0x00); /* select character map 0 */ + vga_write_sr(0x04,0x03); /* even-odd addressing */ + vga_write_sr(0x00,0x03); /* clear synchronous reset */ + + vga_set_seq(); /* Set the extended sr's. */ + + vga_set_gr(); /* Set the graphic registers. */ + + /* load the font */ + vga_set_font(); + + /* initialize the rol/col counts and the text attribute. */ + video_row=0; + video_col=0; + video_attr = VGA_ATTR_CLR_WHT; + + /* Clear the video ram */ + video_clear(); + + return 1; +} + +void vga_set_font(void) +{ + int i,j; + char *fontmap; + fontmap = (char *)font_base_addr; + + vga_write_sr(0x00,0x01); /* synchronous reset */ + vga_write_sr(0x04,0x06); /* sequential addressing */ + vga_write_sr(0x02,0x04); /* write to map 2 */ + vga_write_sr(0x00,0x03); /* clear synchronous reset */ + + vga_write_gr(0x04,0x02); /* select map 2 */ + vga_write_gr(0x05,0x00); /* disable odd-even addressing */ + vga_write_gr(0x06,0x00); /* map start at 0xa0000 */ + + for(i=0;i<0x100;i++) { + for(j=0;j<0x10;j++) { + *((char *)fontmap+i*32+j)=(char)fontdata_8x16[i*16+j]; + } + } + vga_write_sr(0x00,0x01); /* synchronous reset */ + vga_write_sr(0x02,0x03); /* write to map 0 and 1 */ + vga_write_sr(0x04,0x03); /* odd-even addressing */ + vga_write_sr(0x03,0x00); /* Character map 0 & 1 */ + vga_write_sr(0x00,0x03); /* clear synchronous reset */ + + vga_write_gr(0x04,0x00); /* select map 0 for CPU */ + vga_write_gr(0x05,0x10); /* enable odd-even addressing */ + vga_write_gr(0x06,0x0E); /* map start at 0xb8000 */ +} + + +/* since we are BIG endian, swap attributes and char */ +unsigned short vga_swap_short(unsigned short val) +{ + unsigned short swapped; + swapped = ((val & 0xff)<<8) | ((val & 0xff00)>>8); + return swapped; +} + +/**************************************************** + * Routines usable Outside world + */ + +/* scolls the text up row rows */ +void video_scroll(int row) +{ + unsigned short clear = ((unsigned short)video_attr << 8) | (' '); + unsigned short* addr16 = &((unsigned short *)video_fb)[(VGA_MAXROWS-row)*VGA_MAXCOLS]; + int i; + + clear=vga_swap_short(clear); + memcpy(video_fb, video_fb+row*(VGA_MAXCOLS*2), (VGA_MAXROWS-row)*(VGA_MAXCOLS*2)); + for (i = 0 ; i < row * VGA_MAXCOLS ; i++) + addr16[i] = clear; + video_row-=row; + video_col=0; +} + + +unsigned long video_cursor(int col, int row) +{ + unsigned short off = row * VGA_MAXCOLS + col ; + unsigned long saved = (video_col << 16) | (video_row & 0xFFFF); + video_col = col; + video_row = row; + + vga_write_cr(CRTC_CURSH,(unsigned char)((off & 0xff00)>>8)); /* Cursor pos. high */ + vga_write_cr(CRTC_CURSL,(unsigned char)(off & 0xff)); /* Cursor pos. low */ + return saved; +} + +void video_set_lxy(unsigned long lxy) +{ + int col = (lxy >> 16) & 0xFFFF; + int row = lxy & 0xFFFF; + video_cursor(col,row); +} + +unsigned long video_get_lxy(void) +{ + return (video_col << 16) | (video_row & 0xFFFF); +} + +void video_clear(void) +{ + int i; + unsigned short clear = ((unsigned short)video_attr << 8) | (' '); + unsigned short * addr16 = (unsigned short * )video_fb; + clear=vga_swap_short(clear); + video_row = video_col = 0; + for (i = 0 ; i < 2000 ; i++) { + addr16[i] = clear; + } +} + +void video_copy(unsigned short *buffer) +{ + int i; + unsigned short * addr16 = (unsigned short * )video_fb; + for (i = 0 ; i < 2000 ; i++) { + buffer[i] = addr16[i]; + } +} + +void video_write(unsigned short *buffer) +{ + int i; + unsigned short * addr16 = (unsigned short *)video_fb; + for (i = 0 ; i < 2000 ; i++) { + addr16[i] = buffer[i]; + } +} + +void video_putc(char ch) +{ + char* addr; +#if 0 + char buf[48]; + char buf1[16]; + static int i=0; + + sprintf(buf1,"%02X ",ch); + serial_puts(buf1); + buf[i++]=((ch>=0x20)&&(ch<=0x7f)) ? ch : '.'; + if(i>=16) { + buf[i++]='\n'; + buf[i]='\0'; + i=0; + serial_puts(" "); + serial_puts(buf); + } +#endif + switch (ch) { + case '\n': + video_col=0; + video_row++; + break; + case '\r': + video_col=0; + break; + case '\t': + video_col += 8 - video_col % 8; + break; + case '\a': +/* beep(); */ + break; + case '\b': + if(video_col) + video_col--; + else + return; + break; + default: + addr = video_fb + 2 * video_row * 80 + 2 * video_col; + + *((char *)addr+1) = (char) video_attr; + *((char *)addr) = (char) ch; + video_col++; + if (video_col > (VGA_MAXCOLS-1)) { + video_row++; + video_col=0; + } + } + + /* If we're on the bottom of the secreen, wrap one row */ + if (video_row > (VGA_MAXROWS-1)) + video_scroll(1); + video_cursor(video_col, video_row); +} + + +unsigned char video_set_attr(unsigned char attr) +{ + unsigned char saved_attr = video_attr; + video_attr = attr; + return saved_attr; +} + +unsigned char video_set_attr_xy(unsigned char attr, int x, int y) +{ + unsigned char *addr = video_fb + (x * 80 + y) * 2 + 1; + unsigned char saved_attr = *addr; + *addr = attr; + return saved_attr; +} + +/* put char at xy */ +void video_putc_xy(char ch, int x, int y) +{ + video_col = x; + video_row = y; + video_putc(ch); +} + +/* put char at xy relative to the position */ +void video_putc_rxy(char ch, int x, int y) +{ + video_col += x; + video_row += y; + video_putc(ch); +} + +/* put char with attribute at xy */ +void video_putc_axy(char ch, char attr, int x, int y) +{ + unsigned char saved_attr = video_set_attr(attr); + video_col = x; + video_row = y; + video_putc(ch); + video_set_attr(saved_attr); +} + +void video_puts(const char *s) +{ + while(*s) { + video_putc(*s); + s++; + } +} + +void video_puts_a(const char *s, char attr) +{ + unsigned char saved_attr = video_set_attr(attr); + video_puts(s); + video_set_attr(saved_attr); +} + +void video_puts_xy(const char *s, int x, int y) +{ + video_cursor(x,y); + video_puts(s); +} + +void video_puts_axy(const char *s, char attr, int x, int y) +{ + unsigned char saved_attr = video_set_attr(attr); + video_puts_xy(s, x, y); + video_set_attr(saved_attr); +} + +void video_wipe_ca_area(unsigned char ch, char attr, int x, int y, int w, int h) +{ + int r, c; + /* better to do this as word writes */ + unsigned short * addr16 = (unsigned short *)video_fb + (y * 80 + x); + unsigned short charattr = (unsigned short)ch << 8 | attr; + charattr=vga_swap_short(charattr); + for (r = 0 ; r < h ; r++, addr16 += 80) { + for (c = 0 ; c < w ; c++) { + addr16[c] = charattr; + } + } +} + +void video_wipe_a_area(unsigned char attr, int x, int y, int w, int h) +{ + int r, c; + /* better to do this as word writes */ + unsigned short * addr16 = (unsigned short *)video_fb + (y * 80 + x); + for (r = 0 ; r < h ; r++, addr16 += 80) { + for (c = 0 ; c < w ; c++) { + ((char*)addr16)[c*2+1] = attr; + } + } +} + +void video_wipe_c_area(unsigned char ch, int x, int y, int w, int h) +{ + int r, c; + /* better to do this as word writes */ + unsigned short * addr16 = (unsigned short *)video_fb + (y * 80 + x); + for (r = 0 ; r < h ; r++, addr16 += 80) { + for (c = 0 ; c < w ; c++) { + ((char*)addr16)[c*2] = ch; + } + } +} + + +/* +tl t tr +l l +bl b br +*/ +typedef struct { + unsigned char tl; /* top left corner */ + unsigned char t; /* top edge */ + unsigned char tr; /* top right corner */ + unsigned char l; /* left edge */ + unsigned char r; /* right edge */ + unsigned char bl; /* bottom left corner */ + unsigned char b; /* bottom edge */ + unsigned char br; /* bottom right corner */ +} box_chars_t; + +box_chars_t sbox_chars = { + 0xDA, 0xC4, 0xBF, + 0xB3, 0xB3, + 0xC0, 0xC4, 0xD9 +}; + +box_chars_t dbox_chars = { + 0xC9, 0xCD, 0xBB, + 0xBA, 0xBA, + 0xC8, 0xCD, 0xBC +}; + +static char cmap[] = "0123456789ABCDEF"; +void video_putchex(char c) +{ + video_putc(cmap[(c >> 4 ) & 0xF]); + video_putc(cmap[c & 0xF]); +} + +void video_putchexl(char c) +{ + video_putc(cmap[c & 0xF]); +} + +void video_putchexh(char c) +{ + video_putc(cmap[(c >> 4) & 0xF]); +} + +#define VGA_CELL_CA(a,c) (((unsigned short)c<<8)|a) /* for BIG endians */ + +void video_gbox_area(box_chars_t *box_chars_p, int x, int y, int w, int h) +{ + int r, c; + /* better to do this as word writes */ + unsigned short* addr16 = (unsigned short *)video_fb + (y * VGA_MAXCOLS + x); + for (r = 0 ; r < h ; r++, addr16 += VGA_MAXCOLS) { + if (r == 0) { + addr16[0] = VGA_CELL_CA(video_attr, box_chars_p->tl); + addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->tr); + for (c = 1 ; c < w - 1 ; c++) + addr16[c] = VGA_CELL_CA(video_attr, box_chars_p->t); + } else if (r == h - 1) { + addr16[0] = VGA_CELL_CA(video_attr, box_chars_p->bl); + addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->br); + for (c = 1 ; c < w - 1 ; c++) + addr16[c] = VGA_CELL_CA(video_attr, box_chars_p->b); + } else { + addr16[0] = VGA_CELL_CA(video_attr, box_chars_p->l); + addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->r); + } + } +} + +/* Writes a box on the screen */ +void video_box_area(int x, int y, int w, int h) { + video_gbox_area(&sbox_chars, x, y, w, h); +} +/*writes a box with double lines on the screen */ +void video_dbox_area(int x, int y, int w, int h) { + video_gbox_area(&dbox_chars, x, y, w, h); +} + +/* routines to set the VGA registers */ + +/* set attributes */ +void vga_set_attrib(void) +{ + int i; + unsigned char status; + + status=in8(STATUS_REG1); + i=0; + + while(attr[i].reg!=0xFF) { + out8(ATTRI_INDEX,attr[i].reg); + out8(ATTRI_INDEX,attr[i].val); /* Attribute uses index for index and data */ + i++; + } + out8(ATTRI_INDEX,0x20); /* unblank the screen */ +} + +/* set CRT Controller Registers */ +void vga_set_crt(void) +{ + int i; + i=0; + while(crtc[i].reg!=0xFF) { + out8(CRT_INDEX,crtc[i].reg); + out8(CRT_DATA,crtc[i].val); + i++; + } +} +/* Set Palette Registers (DAC) */ +void vga_set_dac(void) +{ + int i; + for(i=0;i<256;i++) { + out8(COL_PAL_IND_W,(unsigned char)i); + out8(COL_PAL_DATA,dac[i][0]); /* red */ + out8(COL_PAL_DATA,dac[i][1]); /* green */ + out8(COL_PAL_DATA,dac[i][2]); /* blue */ + } + out8(COL_PAL_MASK,0xff); /* set mask */ +} +/* set Graphic Controller Register */ +void vga_set_gr(void) +{ + int i; + i=0; + while(grmr[i].reg!=0xFF) { + out8(GR_INDEX,grmr[i].reg); + out8(GR_DATA,grmr[i].val); + i++; + } +} + +/* Set Sequencer Registers */ +void vga_set_seq(void) +{ + int i; + i=0; + while(seq[i].reg!=0xFF) { + out8(SEQ_INDEX,seq[i].reg); + out8(SEQ_DATA,seq[i].val); + i++; + } +} + + +/* Set Extension Registers */ +void vga_set_xreg(void) +{ + int i; + i=0; + while(xreg[i].reg!=0xFF) { + out8(XREG_INDEX,xreg[i].reg); + out8(XREG_DATA,xreg[i].val); + i++; + } +} + +/************************************************************ + * some helping routines + */ + +void vga_write_sr(unsigned char reg,unsigned char val) +{ + out8(SEQ_INDEX,reg); + out8(SEQ_DATA,val); +} + + +void vga_write_gr(unsigned char reg,unsigned char val) +{ + out8(GR_INDEX,reg); + out8(GR_DATA,val); +} + +void vga_write_cr(unsigned char reg,unsigned char val) +{ + out8(CRT_INDEX,reg); + out8(CRT_DATA,val); +} + + +#if 0 +void video_dump_reg(void) +{ + /* first dump attributes */ + int i; + unsigned char status; + + + printf("Extended Regs:\n"); + i=0; + while(xreg[i].reg!=0xFF) { + out8(XREG_INDEX,xreg[i].reg); + status=in8(XREG_DATA); + printf("XR%02X is %02X, should be %02X\n",xreg[i].reg,status,xreg[i].val); + i++; + } + printf("Sequencer Regs:\n"); + i=0; + while(seq[i].reg!=0xFF) { + out8(SEQ_INDEX,seq[i].reg); + status=in8(SEQ_DATA); + printf("SR%02X is %02X, should be %02X\n",seq[i].reg,status,seq[i].val); + i++; + } + printf("Graphic Regs:\n"); + i=0; + while(grmr[i].reg!=0xFF) { + out8(GR_INDEX,grmr[i].reg); + status=in8(GR_DATA); + printf("GR%02X is %02X, should be %02X\n",grmr[i].reg,status,grmr[i].val); + i++; + } + printf("CRT Regs:\n"); + i=0; + while(crtc[i].reg!=0xFF) { + out8(CRT_INDEX,crtc[i].reg); + status=in8(CRT_DATA); + printf("CR%02X is %02X, should be %02X\n",crtc[i].reg,status,crtc[i].val); + i++; + } + printf("Attributes:\n"); + status=in8(STATUS_REG1); + i=0; + while(attr[i].reg!=0xFF) { + out8(ATTRI_INDEX,attr[i].reg); + status=in8(ATTRI_DATA); + out8(ATTRI_INDEX,attr[i].val); /* Attribute uses index for index and data */ + printf("AR%02X is %02X, should be %02X\n",attr[i].reg,status,attr[i].val); + i++; + } +} +#endif + + + + + + + + + + + + + + + + + + + + + diff --git a/board/mpl/common/video.h b/board/mpl/common/video.h new file mode 100644 index 0000000..3c6f513 --- /dev/null +++ b/board/mpl/common/video.h @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 _VIDEO_H +#define _VIDEO_H + +int video_init(int busdevfunc); +void video_clear(void); +void video_putc(char ch); +void video_puts(const char *s); +void video_puts_a(const char *s, char attr); +unsigned char video_set_attr(unsigned char attr); + +void video_box_area(int x, int y, int w, int h); +void video_dbox_area(int x, int y, int w, int h); +void video_wipe_c_area(unsigned char ch, int x, int y, int w, int h); + +void video_wipe_a_area(unsigned char attr, int x, int y, int w, int h); +void video_wipe_ca_area(unsigned char ch, char attr, int x, int y, int w, int h); +void video_puts_axy(const char *s, char attr, int x, int y); +void video_putc_rxy(char ch, int x, int y); +void video_putc_xy(char ch, int x, int y); +unsigned char video_set_attr_xy(unsigned char attr, int x, int y); +void video_copy(unsigned short *buffer); +void video_write(unsigned short *buffer); + +#define VGA_ATTR_CLR_RED 0x4 +#define VGA_ATTR_CLR_GRN 0x2 +#define VGA_ATTR_CLR_BLU 0x1 +#define VGA_ATTR_CLR_YEL (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN) +#define VGA_ATTR_CLR_CYN (VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU) +#define VGA_ATTR_CLR_MAG (VGA_ATTR_CLR_BLU | VGA_ATTR_CLR_RED) +#define VGA_ATTR_CLR_BLK 0 +#define VGA_ATTR_CLR_WHT (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU) + +#define VGA_ATTR_BNK 0x80 +#define VGA_ATTR_ITN 0x08 + +#define VGA_ATTR_BG_MSK 0x70 +#define VGA_ATTR_FG_MSK 0x07 + +#define VGA_ATTR_BG_GET(v) (((v) & VGA_ATTR_BG_MSK)>>4) +#define VGA_ATTR_BG_SET(v, c) (((c) & VGA_ATTR_FG_MSK)<<4) | (v & ~VGA_ATTR_BG_MSK)) + +#define VGA_ATTR_FG_GET(v) ((v) & VGA_ATTR_FG_MSK) +#define VGA_ATTR_FG_SET(v, c) ((c) & VGA_ATTR_FG_MSK) | (v & ~VGA_ATTR_FG_MSK)) + +#define VGA_ATTR_FG_BG_SET(v, b, f) (VGA_ATTR_BG_SET(v, b) | VGA_ATTR_FG_SET(v, cf)) + +#define VGA_ATTR_INVERT(A) ((((A)&0x7)<<4)|(((A)&0x70)>>4) |((A)&0x88)) + +#endif diff --git a/board/mpl/mip405/Makefile b/board/mpl/mip405/Makefile new file mode 100644 index 0000000..bcb1da5 --- /dev/null +++ b/board/mpl/mip405/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000, 2001 +# Wolfgang Denk, DENX Software Engineering, wd@denx.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 +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o ../common/flash.o cmd_mip405.o ../common/pci.o ../common/usb_uhci.o ../common/memtst.o +SOBJS = init.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/mpl/mip405/cmd_mip405.c b/board/mpl/mip405/cmd_mip405.c new file mode 100644 index 0000000..3829a24 --- /dev/null +++ b/board/mpl/mip405/cmd_mip405.c @@ -0,0 +1,214 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * hacked for PIP405 + */ + +#include +#include +#include "mip405.h" +#include +#include "../common/isa.h" +#include "../common/video.h" +#include + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width); +unsigned int PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width); +extern void print_mip405_info(void); + + + + + +#define TRUE 1 +#define FALSE 0 + +#define IMAGE_SIZE 0x80000 + +image_header_t header; + + + +int mip405_prg(unsigned long src,unsigned long size) +{ + unsigned long start; + flash_info_t *info; + int i,rc; + unsigned long *magic = (unsigned long *)src; + + info = &flash_info[0]; + start = 0 - size; + for(i=info->sector_count-1;i>0;i--) + { + info->protect[i] = 0; /* unprotect this sector */ + if(start>=info->start[i]) + break; + } + /* set-up flash location */ + /* now erase flash */ + if(magic[0]!=IH_MAGIC) { + printf("Bad Magic number\n"); + return -1; + } + printf("Start erasing at %lx (sector %d) (start %lx)\n", + start,i,info->start[i]); + flash_erase (info, i, info->sector_count-1); + printf("flash erased, programming from 0x%lx 0x%lx Bytes\n",src,size); + switch (rc = flash_write ((uchar *)src, start, size)) + { + case 0: printf ("programming done\n"); return 0; + case 1: printf ("Timeout writing to Flash\n"); return 1; + case 2: printf ("Flash not Erased\n"); return 1; + case 4: printf ("Can't write to protected Flash sectors\n"); return 1; + case 8: printf ("Outside available Flash\n"); return 1; + default: printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc); return 1; + } + return 1; +} + + +int mip405_prg_image(unsigned long load_addr) +{ + unsigned long data,len,checksum; + image_header_t *hdr=&header; + /* Copy header so we can blank CRC field for re-calculation */ + memcpy (&header, (char *)load_addr, sizeof(image_header_t)); + + if (hdr->ih_magic != IH_MAGIC) { + printf ("Bad Magic Number\n"); + return 1; + } + if (hdr->ih_os != IH_OS_PPCBOOT) { + printf ("No PPCBOOT Image\n"); + return 1; + } + if (hdr->ih_type != IH_TYPE_FIRMWARE) { + printf ("No Firmware Image\n"); + return 1; + } + data = (ulong)&header; + len = sizeof(image_header_t); + checksum = hdr->ih_hcrc; + hdr->ih_hcrc = 0; + if (crc32 (0, (char *)data, len) != checksum) { + printf ("Bad Header Checksum\n"); + return 1; + } + data = load_addr + sizeof(image_header_t); + len = hdr->ih_size; + printf (" Verifying Checksum ... "); + if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) { + printf ("Bad Data CRC\n"); + return 1; + } + printf ("OK\n"); + return(mip405_prg(data,len)); +} + + +/* ------------------------------------------------------------------------- */ + +int do_mip405(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + + ulong size,src,device,load_addr; + int result; + backup_t back; + src = MULTI_PURPOSE_SOCKET_ADDR; + size = IMAGE_SIZE; + + if (strcmp(argv[1], "flash") == 0) + { + if (strcmp(argv[2], "mem") == 0) { + if(argc==4) { + load_addr=simple_strtoul(argv[3], NULL, 16); + } + else { + load_addr=CFG_LOAD_ADDR; + } + printf ("\nupdating bootloader image from memory at %lX\n",load_addr); + result=mip405_prg_image(load_addr); + return result; + } + if (strcmp(argv[2], "mps") == 0) { + printf ("\nupdating bootloader image from MSP\n"); + result=mip405_prg(src,size); + return result; + } + + } + if (strcmp(argv[1], "mem") == 0) + { + result=0; + if(argc==3) + { + result = (int)simple_strtol(argv[2], NULL, 16); + } + src=(unsigned long)&result; + src-=CFG_MEMTEST_START; + src-=(100*1024); /* - 100k */ + src&=0xfff00000; + size=0; + do { + size++; + printf("Pass %ld\n",size); + mem_test(CFG_MEMTEST_START,src,1); + if(ctrlc()) + break; + if(result>0) + result--; + + }while(result); + return 0; + } + if (strcmp(argv[1], "info") == 0) + { + print_mip405_info(); + return 0; + } + if (strcmp(argv[1], "led") == 0) + { + device = (ulong)simple_strtoul(argv[2], NULL, 10); + user_led0((device==1)); + return 0; + } + if (strcmp(argv[1], "getback") == 0) { + get_backup_values(&back); + back.signature[3]=0; + back.serial_name[16]=0; + back.eth_addr[20]=0; + printf("GetBackUp: signature: %s\n",back.signature); + printf(" serial#: %s\n",back.serial_name); + printf(" ethaddr: %s\n",back.eth_addr); + return 0; + } + if (strcmp(argv[1], "setback") == 0) { + set_backup_values(1); + return 0; + } + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +/* ------------------------------------------------------------------------- */ diff --git a/board/mpl/mip405/config.mk b/board/mpl/mip405/config.mk new file mode 100644 index 0000000..0f8d153 --- /dev/null +++ b/board/mpl/mip405/config.mk @@ -0,0 +1,29 @@ +# +# (C) Copyright 2000, 2001 +# Wolfgang Denk, DENX Software Engineering, wd@denx.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 +# + +# +# esd ADCIOP boards +# + +#TEXT_BASE = 0xFFFE0000 +TEXT_BASE = 0xFFF80000 diff --git a/board/mpl/mip405/init.S b/board/mpl/mip405/init.S new file mode 100644 index 0000000..fbefef0 --- /dev/null +++ b/board/mpl/mip405/init.S @@ -0,0 +1,224 @@ +/*------------------------------------------------------------------------------+ + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + *-------------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Function: ext_bus_cntlr_init + * Description: Initializes the External Bus Controller for the external + * peripherals. IMPORTANT: For pass1 this code must run from + * cache since you can not reliably change a peripheral banks + * timing register (pbxap) while running code from that bank. + * For ex., since we are running from ROM on bank 0, we can NOT + * execute the code that modifies bank 0 timings from ROM, so + * we run it from cache. + * Bank 0 - Flash or Multi Purpose Socket + * Bank 1 - Multi Purpose Socket or Flash (set in C-Code) + * Bank 2 - UART 1 (set in C-Code) + * Bank 3 - UART 2 (set in C-Code) + * Bank 4 - not used + * Bank 5 - not used + * Bank 6 - not used + * Bank 7 - PLD Register + *-----------------------------------------------------------------------------*/ +#include + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include "config_MIP405.h" +#include +#include + +#include +#include +#include "mip405.h" + + + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: + mflr r4 /* save link register */ + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + mtlr r4 /* restore link register */ + addi r4,0,14 /* set ctr to 14; used to prefetch */ + mtctr r4 /* 14 cache lines to fit this function */ + /* in cache (gives us 8x14=112 instrctns) */ +..ebcloop: + icbt r0,r3 /* prefetch cache line for addr in r3 */ + addi r3,r3,32 /* move to next cache line */ + bdnz ..ebcloop /* continue for 14 cache lines */ + + /*------------------------------------------------------------------- + * Delay to ensure all accesses to ROM are complete before changing + * bank 0 timings. + *------------------------------------------------------------------- */ + addis r3,0,0x0 + ori r3,r3,0xA000 + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + + /*----------------------------------------------------------------------- + * decide boot up mode + *----------------------------------------------------------------------- */ + addi r4,0,pb0cr + mtdcr ebccfga,r4 + mfdcr r4,ebccfgd + + andi. r0, r4, 0x2000 /* mask out irrelevant bits */ + beq 0f /* jump if 8 bit bus width */ + + /* setup 16 bit things (Flash Boot) + *----------------------------------------------------------------------- + * Memory Bank 0 (16 Bit Flash) initialization + *---------------------------------------------------------------------- */ + + addi r4,0,pb0ap + mtdcr ebccfga,r4 +// addis r4,0,0xFF8F +// ori r4,r4,0xFE80 +// addis r4,0,0x9B01 +// ori r4,r4,0x5480 + addis r4,0,(FLASH_AP_B)@h + ori r4,r4,(FLASH_AP_B)@l + mtdcr ebccfgd,r4 + + addi r4,0,pb0cr + mtdcr ebccfga,r4 + /* BS=0x010(4MB),BU=0x3(R/W), */ +// addis r4,0,((FLASH_BASE0_PRELIM & 0xFFF00000) | 0x00050000)@h +// ori r4,r4,0xA000 /* BW=0x01(16 bits) */ + addis r4,0,(FLASH_CR_B)@h + ori r4,r4,(FLASH_CR_B)@l + mtdcr ebccfgd,r4 + b 1f + +0: + + /* 8Bit boot mode: */ + /*----------------------------------------------------------------------- + * Memory Bank 0 Multi Purpose Socket initialization + *----------------------------------------------------------------------- */ + /* 0x7F8FFE80 slowest boot */ + addi r4,0,pb0ap + mtdcr ebccfga,r4 +#if 0 + addis r4,0,0x9B01 + ori r4,r4,0x5480 +#else + addis r4,0,(MPS_AP_B)@h + ori r4,r4,(MPS_AP_B)@l +#endif + mtdcr ebccfgd,r4 + + addi r4,0,pb0cr + mtdcr ebccfga,r4 + /* BS=0x010(4MB),BU=0x3(R/W), */ +// addis r4,0,((FLASH_BASE0_PRELIM & 0xFFF00000) | 0x00050000)@h +// ori r4,r4,0x8000 /* BW=0x0( 8 bits) */ + + addis r4,0,(MPS_CR_B)@h + ori r4,r4,(MPS_CR_B)@l + + mtdcr ebccfgd,r4 + + +1: + /*----------------------------------------------------------------------- + * Memory Bank 2-3-4-5-6 (not used) initialization + *-----------------------------------------------------------------------*/ + addi r4,0,pb1cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb2cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb3cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb4cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb5cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb6cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb7cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + nop /* pass2 DCR errata #8 */ + blr + +/*----------------------------------------------------------------------------- + * Function: sdram_init + * Description: Configures the internal SRAM memory. and setup the + * Stackpointer in it. + *----------------------------------------------------------------------------- */ + .globl sdram_init + +sdram_init: + + /*------------------------------------------------------------------- + * init OnChip Memory for a temporary stack + *------------------------------------------------------------------- */ + + lis r0, 0x7FFF + ori r0, r0, 0xFFFF + mfdcr r3, ocmiscntl /* get instr-side IRAM config */ + mfdcr r4, ocmdscntl /* get data-side IRAM config */ + and r3, r3, r0 /* disable data-side IRAM */ + and r4, r4, r0 /* disable data-side IRAM */ + mtdcr ocmiscntl, r3 /* set instr-side IRAM config */ + mtdcr ocmdscntl, r4 /* set data-side IRAM config */ + isync + lis r0, OCM_DATA_ADDR@h/* IRAM is mapped here */ + mtdcr ocmdsarc, r0 /* set data-side IRAM address */ + oris r4, r4, 0xC000 /* enable data-side IRAM */ + mtdcr ocmdscntl, r4 /* set data-side IRAM config */ + isync + + mfdcr r3, ocmdsarc /* set temp stackpointer (needed by CONS_Init) */ + andis. r3, r3, 0xFC00 + addi r1, r3, 0x1000-16 + + blr + diff --git a/board/mpl/mip405/mip405.c b/board/mpl/mip405/mip405.c new file mode 100644 index 0000000..0e4dcb2 --- /dev/null +++ b/board/mpl/mip405/mip405.c @@ -0,0 +1,988 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * + * TODO: clean-up + */ + +/* + * How do I program the SDRAM Timing Register (SDRAM0_TR) for a specific SDRAM or DIMM? + * + * As an example, consider a case where PC133 memory with CAS Latency equal to 2 is being + * used with a 200MHz 405GP. For a typical 128Mb, PC133 SDRAM, the relevant minimum + * parameters from the datasheet are: + * Tclk = 7.5ns (CL = 2) + * Trp = 15ns + * Trc = 60ns + * Trcd = 15ns + * Trfc = 66ns + * + * If we are operating the 405GP with the MemClk output frequency set to 100 MHZ, the clock + * period is 10ns and the parameters needed for the Timing Register are: + * CASL = CL = 2 clock cycles + * PTA = Trp = 15ns / 10ns = 2 clock cycles + * CTP = Trc - Trcd - Trp = (60ns - 15ns - 15ns) / 10ns= 3 clock cycles + * LDF = 2 clock cycles (but can be extended to meet board-level timing) + * RFTA = Trfc = 66ns / 10ns= 7 clock cycles + * RCD = Trcd = 15ns / 10ns= 2 clock cycles + * + * The actual bit settings in the register would be: + * + * CASL = 0b01 + * PTA = 0b01 + * CTP = 0b10 + * LDF = 0b01 + * RFTA = 0b011 + * RCD = 0b01 + * + * If Trfc is not specified in the datasheet for PC100 or PC133 memory, set RFTA = Trc + * instead. Figure 24 in the PC SDRAM Specification Rev. 1.7 shows refresh to active delay + * defined as Trc rather than Trfc. + * When using DIMM modules, most but not all of the required timing parameters can be read + * from the Serial Presence Detect (SPD) EEPROM on the module. Specifically, Trc and Trfc + * are not available from the EEPROM + */ + +#include +#include "mip405.h" +#include +#include <405gp_i2c.h> +#include +#include + +extern block_dev_desc_t * scsi_get_dev(int dev); +extern block_dev_desc_t * ide_get_dev(int dev); + +#undef SDRAM_DEBUG + +#define FALSE 0 +#define TRUE 1 + +/* stdlib.h causes some compatibility problems; should fixe these! -- wd */ +#ifndef __ldiv_t_defined +typedef struct { + long int quot; /* Quotient */ + long int rem; /* Remainder */ +} ldiv_t; +extern ldiv_t ldiv (long int __numer, long int __denom); +# define __ldiv_t_defined 1 +#endif + + +#define PLD_PART_REG PER_PLD_ADDR + 0 +#define PLD_VERS_REG PER_PLD_ADDR + 1 +#define PLD_BOARD_CFG_REG PER_PLD_ADDR + 2 +#define PLD_IRQ_REG PER_PLD_ADDR + 3 +#define PLD_COM_MODE_REG PER_PLD_ADDR + 4 +#define PLD_EXT_CONF_REG PER_PLD_ADDR + 5 + +#define MEGA_BYTE (1024*1024) + +typedef struct { + unsigned char boardtype; /* Board revision and Population Options */ + unsigned char cal; /* cas Latency (will be programmend as cal-1) */ + unsigned char trp; /* datain27 in clocks */ + unsigned char trcd; /* datain29 in clocks */ + unsigned char tras; /* datain30 in clocks */ + unsigned char tctp; /* tras - trcd in clocks */ + unsigned char am; /* Address Mod (will be programmed as am-1) */ + unsigned char sz; /* log binary => Size = (4MByte<>4; + cc&=0xf; + if(cc>9) + serial_putc(cc+55); + else + serial_putc(cc+48); + cc=i&0xf; + if(cc>9) + serial_putc(cc+55); + else + serial_putc(cc+48); +} + +void write_4hex(unsigned long val) +{ + write_hex((unsigned char)(val>>24)); + write_hex((unsigned char)(val>>16)); + write_hex((unsigned char)(val>>8)); + write_hex((unsigned char)val); +} + +#endif + + +int init_sdram (void) +{ + unsigned long tmp, baseaddr; + unsigned short i; + unsigned char trp_clocks, trcd_clocks, tras_clocks, trc_clocks,tctp_clocks; + unsigned char cal_val; + unsigned char bc; + unsigned long pbcr,sdram_tim,sdram_bank; + unsigned long *p; + + + + serial_init(get_gclk_freq(),9600); + serial_puts("\nInitializing SDRAM, Please stand by"); + mtdcr(ebccfga, pb0cr); /* get cs0 config reg */ + pbcr = mfdcr(ebccfgd); + if((pbcr&0x00002000)==0) { + /* MPS Boot, set up the flash */ + mtdcr(ebccfga, pb1ap); + mtdcr(ebccfgd, FLASH_AP); + mtdcr(ebccfga, pb1cr); + mtdcr(ebccfgd, FLASH_CR); + } + else { + /* Flash boot, set up the MPS */ + mtdcr(ebccfga, pb1ap); + mtdcr(ebccfgd, MPS_AP); + mtdcr(ebccfga, pb1cr); + mtdcr(ebccfgd, MPS_CR); + } + /* set up UART0 (CS2) and UART1 (CS3) */ + mtdcr(ebccfga, pb2ap); + mtdcr(ebccfgd, UART0_AP); + mtdcr(ebccfga, pb2cr); + mtdcr(ebccfgd, UART0_CR); + mtdcr(ebccfga, pb3ap); + mtdcr(ebccfgd, UART1_AP); + mtdcr(ebccfga, pb3cr); + mtdcr(ebccfgd, UART1_CR); + + /* set up the pld */ + mtdcr(ebccfga, pb7ap); + mtdcr(ebccfgd, PLD_AP); + mtdcr(ebccfga, pb7cr); + mtdcr(ebccfgd, PLD_CR); + /* set up the board rev reg */ + mtdcr(ebccfga, pb5ap); + mtdcr(ebccfgd, BOARD_AP); + mtdcr(ebccfga, pb5cr); + mtdcr(ebccfgd, BOARD_CR); + + +#ifdef SDRAM_DEBUG + out8(PER_BOARD_ADDR,0); + bc=in8(PER_BOARD_ADDR); + serial_puts("\nBoard Rev: "); + write_hex(bc); + serial_puts(" (PLD="); + bc=in8(PLD_BOARD_CFG_REG); + write_hex(bc); + serial_puts(")\n"); +#endif + bc=get_board_revcfg(); +#ifdef SDRAM_DEBUG + serial_puts("\nstart SDRAM Setup\n"); + serial_puts("\nBoard Rev: "); + write_hex(bc); + serial_puts("\n"); +#endif + i=0; + baseaddr=CFG_SDRAM_BASE; + while(sdram_table[i].sz!=0xff) { + if(sdram_table[i].boardtype==bc) + break; + i++; + } + if(sdram_table[i].boardtype!=bc) + SDRAM_err("No SDRAM table found for this board!!!\n"); +#ifdef SDRAM_DEBUG + serial_puts(" found table "); + write_hex(i); + serial_puts(" \n"); +#endif + cal_val = sdram_table[i].cal-1; /* Cas Latency */ + trp_clocks = sdram_table[i].trp; /* 20ns / 7.5 ns datain[27] */ + trcd_clocks = sdram_table[i].trcd; /* 20ns /7.5 ns (datain[29]) */ + tras_clocks = sdram_table[i].tras; /* 44ns /7.5 ns (datain[30]) */ + /* ctp = ((trp + tras) - trp - trcd) => tras - trcd */ + tctp_clocks = sdram_table[i].tctp; /* 44 - 20ns = 24ns */ + /* trc_clocks is sum of trp_clocks + tras_clocks */ + trc_clocks = trp_clocks + tras_clocks; + /* get SDRAM timing register */ + mtdcr(memcfga,mem_sdtr1); + sdram_tim = mfdcr(memcfgd) & ~0x018FC01F; + /* insert CASL value */ + sdram_tim |= ((unsigned long)(cal_val)) << 23; + /* insert PTA value */ + sdram_tim |= ((unsigned long)(trp_clocks - 1)) << 18; + /* insert CTP value */ + sdram_tim |= ((unsigned long)(trc_clocks - trp_clocks - trcd_clocks)) << 16; + /* insert LDF (always 01) */ + sdram_tim |= ((unsigned long)0x01) << 14; + /* insert RFTA value */ + sdram_tim |= ((unsigned long)(trc_clocks - 4)) << 2; + /* insert RCD value */ + sdram_tim |= ((unsigned long)(trcd_clocks - 1)) << 0; + + tmp = ((unsigned long)(sdram_table[i].am-1) << 13); /* AM = 3 */ + /* insert SZ value; */ + tmp |= ((unsigned long)sdram_table[i].sz << 17); + /* get SDRAM bank 0 register */ + mtdcr(memcfga,mem_mb0cf); + sdram_bank = mfdcr(memcfgd) & ~0xFFCEE001; + sdram_bank |= (baseaddr | tmp | 0x01); + +#ifdef SDRAM_DEBUG + serial_puts("sdtr: "); + write_4hex(sdram_tim); + serial_puts("\n"); +#endif + + /* write SDRAM timing register */ + mtdcr(memcfga,mem_sdtr1); + mtdcr(memcfgd,sdram_tim); + +#ifdef SDRAM_DEBUG + serial_puts("mb0cf: "); + write_4hex(sdram_bank); + serial_puts("\n"); +#endif + + /* write SDRAM bank 0 register */ + mtdcr(memcfga,mem_mb0cf); + mtdcr(memcfgd,sdram_bank); + + if(get_bus_freq(tmp)>110000000) { /* > 110MHz */ + /* get SDRAM refresh interval register */ + mtdcr(memcfga,mem_rtr); + tmp = mfdcr(memcfgd) & ~0x3FF80000; + tmp |= 0x07F00000; + } + else { + /* get SDRAM refresh interval register */ + mtdcr(memcfga,mem_rtr); + tmp = mfdcr(memcfgd) & ~0x3FF80000; + tmp |= 0x05F00000; + } + /* write SDRAM refresh interval register */ + mtdcr(memcfga,mem_rtr); + mtdcr(memcfgd,tmp); + /* enable ECC if used */ +#if 1 + if(sdram_table[i].ecc) { + /* disable checking for all banks */ +#ifdef SDRAM_DEBUG + serial_puts("disable ECC.. "); +#endif + mtdcr(memcfga,mem_ecccf); + tmp=mfdcr(memcfgd); + tmp&=0xff0fffff; /* disable all banks */ + mtdcr(memcfga,mem_ecccf); + /* set up SDRAM Controller with ECC enabled */ +#ifdef SDRAM_DEBUG + serial_puts("setup SDRAM Controller.. "); +#endif + mtdcr(memcfgd,tmp); + mtdcr(memcfga,mem_mcopt1); + tmp = (mfdcr(memcfgd) & ~0xFFE00000) | 0x90800000; + mtdcr(memcfga,mem_mcopt1); + mtdcr(memcfgd,tmp); + udelay(600); +#ifdef SDRAM_DEBUG + serial_puts("fill the memory..\n"); +#endif + serial_puts("."); + /* now, fill all the memory */ + tmp=((4*MEGA_BYTE)<>=1; + } + rc++; + i=getenv_r("serial#",s,32); + if ((i==0) || strncmp(s, "MIP405", 6)) { + get_backup_values(b); + if(strncmp(b->signature,"MPL\0",4)!=0) { + printf("### No HW ID - assuming MIP405"); + printf("-%d Rev %c",rc, 'A'+((bc>>4)&0xf)); + } + else { + b->serial_name[6]=0; + printf("%s-%d Rev %c SN: %s",b->serial_name,rc, 'A'+((bc>>4)&0xf),&b->serial_name[7]); + } + } + else { + s[6]=0; + printf("%s-%d Rev %c SN: %s",s,rc, 'A'+((bc>>4)&0xf),&s[7]); + } + bc=in8(PLD_EXT_CONF_REG); + printf(" Boot Config: 0x%x\n",bc); + return (0); +} + + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +/* + initdram(int board_type) reads EEPROM via I2c. EEPROM contains all of + the necessary info for SDRAM controller configuration +*/ +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +int testdram (unsigned long ramsize); + +long int initdram (int board_type) +{ + + unsigned long bank_reg[4],tmp,bank_size; + int i,ds; + unsigned long TotalSize; + ds=0; + /* since the DRAM controller is allready set up, calculate the size with the + bank registers */ + mtdcr(memcfga,mem_mb0cf); + bank_reg[0] = mfdcr(memcfgd); + mtdcr(memcfga,mem_mb1cf); + bank_reg[1] = mfdcr(memcfgd); + mtdcr(memcfga,mem_mb2cf); + bank_reg[2] = mfdcr(memcfgd); + mtdcr(memcfga,mem_mb3cf); + bank_reg[3] = mfdcr(memcfgd); + TotalSize=0; + for(i=0;i<4;i++) + { + if((bank_reg[i]&0x1)==0x1) + { + tmp=(bank_reg[i]>>17)&0x7; + bank_size=4<>=4; + bc &= 0x0f; + sprintf(buf,"bootcmd%d",bc); + s = getenv(buf); + if(s) { + sprintf(buf,"%s",s); + setenv("bootcmd",buf); + } + sprintf(buf,"bootargs%d",bc); + s = getenv(buf); + if(s) { + sprintf(buf,"%s",s); + setenv("bootargs",buf); + } +#endif + /* it is time to swap the flash permanently to the flash area */ + switch_cs(FALSE); +} + + + +void set_init_backup(void) +{ + unsigned char *s; + char buf[32]; + backup_t back; + + s=getenv("serial#"); + if(!s) { + get_backup_values(&back); + if(strncmp(back.signature,"MPL\0",4)==0) { + sprintf(buf,"%s",back.serial_name); + setenv("serial#",buf); + sprintf(buf,"%s",back.eth_addr); + setenv("ethaddr",buf); + printf("INFO: serial# and ethaddr recovered, use saveenv\n"); + } + } + else { + /* check if back up is set */ + get_backup_values(&back); + if(strncmp(back.signature,"MPL\0",4)!=0) { + set_backup_values(0); + } + } +} + +extern device_t *stdio_devices[]; +extern char *stdio_names[]; + +void show_stdio_dev(void) +{ + /* Print informations */ + printf ("In: "); + if (stdio_devices[stdin] == NULL) { + printf ("No input devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdin]->name); + } + + printf ("Out: "); + if (stdio_devices[stdout] == NULL) { + printf ("No output devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdout]->name); + } + + printf ("Err: "); + if (stdio_devices[stderr] == NULL) { + printf ("No error devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stderr]->name); + } +} + + + +int last_stage_init(void) +{ + set_init_backup(); + if(miiphy_write(0x1, 0x14, 0x2402) != 0) { + printf("Error writing to the PHY\n"); + } + show_stdio_dev(); + return 0; +} + +/*************************************************************************** + * some helping routines + */ + +int overwrite_console(void) +{ + return(in8(PLD_EXT_CONF_REG) & 0x1); /* return TRUE if console should be overwritten */ +} + + +/************************************************************************ +* Print MIP405 Info +************************************************************************/ +void print_mip405_info(void) +{ + unsigned char part,vers,cfg,irq_reg,com_mode,ext; + + part=in8(PLD_PART_REG); + vers=in8(PLD_VERS_REG); + cfg=in8(PLD_BOARD_CFG_REG); + irq_reg=in8(PLD_IRQ_REG); + com_mode=in8(PLD_COM_MODE_REG); + ext=in8(PLD_EXT_CONF_REG); + + printf("PLD Part %d version %d\n",part,vers); + printf("Board Revision %c\n",((cfg>>4)&0xf)+'A'); + printf("Population Options %d %d %d %d\n",(cfg)&0x1,(cfg>>1)&0x1,(cfg>>2)&0x1,(cfg>>3)&0x1); + printf("User LED %s\n",(com_mode & 0x4) ? "on" : "off"); + printf("UART Clocks %d\n",(com_mode>>4)&0x3); + printf("User Config Switch %d %d %d %d %d %d %d %d\n", + (ext)&0x1,(ext>>1)&0x1,(ext>>2)&0x1,(ext>>3)&0x1,(ext>>4)&0x1,(ext>>5)&0x1,(ext>>6)&0x1,(ext>>7)&0x1); + printf("SER1 uses handshakes %s\n",(ext & 0x80) ? "DTR/DSR" : "RTS/CTS"); + printf("IDE Reset %s\n",(ext & 0x01) ? "asserted" : "not asserted"); + printf("IRQs:\n"); + printf(" PIIX INTR: %s\n",(irq_reg & 0x80) ? "inactive" : "active"); + printf(" UART0 IRQ: %s\n",(irq_reg & 0x40) ? "inactive" : "active"); + printf(" UART1 IRQ: %s\n",(irq_reg & 0x20) ? "inactive" : "active"); + printf(" PIIX SMI: %s\n",(irq_reg & 0x10) ? "inactive" : "active"); + printf(" PIIX INIT: %s\n",(irq_reg & 0x8) ? "inactive" : "active"); + printf(" PIIX NMI: %s\n",(irq_reg & 0x4) ? "inactive" : "active"); +} + + +/****************************************************** + * Routines to display the Board information + * to the screen (since the VGA will be initialized as last, + * we must resend the infos) + */ +#ifdef CONFIG_VIDEO +void video_put_dev_string(block_dev_desc_t *dev_desc) +{ + char buf[80]; + ldiv_t mb; + unsigned long lba512; /* number of blocks if 512bytes block size */ + + if(dev_desc->type!=DEV_TYPE_UNKNOWN) { + if(dev_desc->if_type==IF_TYPE_SCSI) + sprintf(buf,"SCSI %d: (%d:%d) ",dev_desc->dev,dev_desc->target,dev_desc->lun); + else + sprintf(buf,"IDE %d: ",dev_desc->dev); + video_puts(buf); + switch(dev_desc->type & 0x1F) { + case DEV_TYPE_HARDDISK: video_puts("Hard Disk"); break; + case DEV_TYPE_CDROM: video_puts("CD ROM"); break; + case DEV_TYPE_OPDISK: video_puts("Optical Device"); break; + case DEV_TYPE_TAPE: video_puts("Tape"); break; + default: video_puts("unknown"); break; + } + video_puts(" "); + video_puts(dev_desc->vendor); + video_puts(" "); + if(dev_desc->if_type!=IF_TYPE_IDE) + video_puts(dev_desc->product); + + if((dev_desc->lba * dev_desc->blksz)>0L) { + lba512=dev_desc->lba * (dev_desc->blksz/512); + mb = ldiv(lba512, 2048); /* (1024 *1024 / 512 MB */ + /* round to 1 digit */ + mb.rem *= 10 * 512; + mb.rem += 512 * 1024; + mb.rem /= 1024 * 1024; + sprintf (buf," %ld x %ld Bytes = %ld.%ld MB\n",dev_desc->lba,dev_desc->blksz,mb.quot, mb.rem); + } + else { + sprintf (buf," Capacity: not available\n"); + } + video_puts(buf); + } +} + +void video_write_board_info(void) +{ + extern char version_string[]; + unsigned long pvr = get_pvr(); + char buf[32],tmpbuf[80]; + PPC405_SYS_INFO sys_info; + init_data_t *idata = (init_data_t *)(CFG_INIT_RAM_ADDR + CFG_INIT_DATA_OFFSET); + unsigned char *s = getenv("serial#"); + unsigned char *e; + unsigned char bc; + block_dev_desc_t *dev_desc; + int i; + + /* first write PPCBOOT Info */ + video_puts("\n"); + video_puts(version_string); + video_puts("\n\n"); + /* then CPU and board infos */ + get_sys_info(&sys_info); + video_puts("CPU: IBM PowerPC 405GP Rev. "); + switch (pvr) { + case PVR_405GP_RB: video_putc('B'); break; + case PVR_405GP_RC: video_putc('C'); break; + case PVR_405GP_RD: video_putc('D'); break; + case PVR_405GP_RE: video_putc('E'); break; + default: video_puts("unknown"); break; + } + sprintf(tmpbuf," at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf,idata->cpu_clk), + sys_info.freqPLB / 1000000, + sys_info.freqPLB / sys_info.pllOpbDiv / 1000000, + sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000); + video_puts(tmpbuf); + if (mfdcr(strap) & PSR_PCI_ASYNC_EN) + video_puts(" PCI async ext clock used, "); + else { + sprintf(buf," PCI sync clock at %lu MHz, ", sys_info.freqPLB / sys_info.pllPciDiv / 1000000); + video_puts(buf); + } + if (mfdcr(strap) & PSR_PCI_ARBIT_EN) + video_puts("internal PCI arbiter enabled\n"); + else + video_puts("external PCI arbiter enabled\n"); + video_puts(" 16 kB I-Cache 8 kB D-Cache\n"); + /* now some board infos */ + video_puts("Board: "); + if (!s || strncmp(s, "PIP405", 6)) { + bc=video_set_attr(VGA_ATTR_CLR_RED | VGA_ATTR_ITN); + video_puts("### No HW ID - assuming PIP405"); + } + else { + bc=video_set_attr(VGA_ATTR_CLR_GRN); + for (e=s; *e; ++e) { + if (*e == ' ') + break; + } + for ( ; sbi_memsize/0x100000); + video_puts(buf); + /* flash size: */ + video_puts("FLASH: "); + if(switch_cs(0)==0) { + bc=video_set_attr(VGA_ATTR_CLR_GRN); + video_puts("(Flash boot)"); + video_set_attr(bc); + } + else { + switch_cs(1); /* back to boot mode */ + bc=video_set_attr(VGA_ATTR_CLR_RED | VGA_ATTR_ITN); + video_puts("(Multi Purpose Socket boot)"); + video_set_attr(bc); + } + sprintf(buf," %lu MBytes\n",bd_ptr->bi_flashsize/0x100000); + video_puts(buf); + /* revisions */ + video_puts("Rev: "); + sprintf(tmpbuf,"PCB Rev: %c PLD%d Rev %d PLD%d Rev %d\n\n",(in8(PLD_BOARD_CFG_REG)&0xf)+'A', + in8(PLD_PART_REG)&0xf,in8(PLD_VERS_REG)&0xf, + (in8(PLD_PART_REG)>>4)&0xf,(in8(PLD_VERS_REG)>>4)&0xf); + video_puts(tmpbuf); + for(i=0;i>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/mpl/pip405/Makefile b/board/mpl/pip405/Makefile new file mode 100644 index 0000000..802ab60 --- /dev/null +++ b/board/mpl/pip405/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000, 2001 +# Wolfgang Denk, DENX Software Engineering, wd@denx.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 +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o ../common/flash.o cmd_pip405.o ../common/pci.o ../common/isa.o ../common/kbd.o ../common/video.o ../common/sym53c8xx.o ../common/usb_uhci.o ../common/memtst.o +SOBJS = init.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/mpl/pip405/cmd_pip405.c b/board/mpl/pip405/cmd_pip405.c new file mode 100644 index 0000000..e4f5e0b --- /dev/null +++ b/board/mpl/pip405/cmd_pip405.c @@ -0,0 +1,245 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * hacked for PIP405 + */ + +#include +#include +#include "pip405.h" +#include +#include "../common/isa.h" +#include "../common/video.h" +#include + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width); +unsigned int PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width); + + + + + +#define TRUE 1 +#define FALSE 0 + +#define IMAGE_SIZE 0x80000 + +image_header_t header; + + + +int pip405_prg(unsigned long src,unsigned long size) +{ + unsigned long start; + flash_info_t *info; + int i,rc; + unsigned long *magic = (unsigned long *)src; + + info = &flash_info[0]; + start = 0 - size; + for(i=info->sector_count-1;i>0;i--) + { + info->protect[i] = 0; /* unprotect this sector */ + if(start>=info->start[i]) + break; + } + /* set-up flash location */ + rc=switch_cs(FALSE); + /* now erase flash */ + if(magic[0]!=IH_MAGIC) { + printf("Bad Magic number\n"); + switch_cs(rc); + return -1; + } + printf("Start erasing at %lx (sector %d) (start %lx)\n", + start,i,info->start[i]); + flash_erase (info, i, info->sector_count-1); + printf("flash erased, programming 0x%lx Bytes\n",size); + switch (rc = flash_write ((uchar *)src, start, size)) + { + case 0: printf ("programming done\n"); return 0; + case 1: printf ("Timeout writing to Flash\n"); return 1; + case 2: printf ("Flash not Erased\n"); return 1; + case 4: printf ("Can't write to protected Flash sectors\n"); return 1; + case 8: printf ("Outside available Flash\n"); return 1; + default: printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc); return 1; + } + return 1; +} + +int pip405_prg_image(unsigned long load_addr) +{ + unsigned long data,len,checksum; + image_header_t *hdr=&header; + /* Copy header so we can blank CRC field for re-calculation */ + memcpy (&header, (char *)load_addr, sizeof(image_header_t)); + + if (hdr->ih_magic != IH_MAGIC) { + printf ("Bad Magic Number\n"); + return 1; + } + if (hdr->ih_os != IH_OS_PPCBOOT) { + printf ("No PPCBOOT Image\n"); + return 1; + } + if (hdr->ih_type != IH_TYPE_FIRMWARE) { + printf ("No Firmware Image\n"); + return 1; + } + data = (ulong)&header; + len = sizeof(image_header_t); + checksum = hdr->ih_hcrc; + hdr->ih_hcrc = 0; + if (crc32 (0, (char *)data, len) != checksum) { + printf ("Bad Header Checksum\n"); + return 1; + } + data = load_addr + sizeof(image_header_t); + len = hdr->ih_size; + printf (" Verifying Checksum ... "); + if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) { + printf ("Bad Data CRC\n"); + return 1; + } + printf ("OK\n"); + return(pip405_prg(data,len)); +} + + +/* ------------------------------------------------------------------------- */ + +int do_pip405(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + + ulong size,src,device,function,load_addr; + unsigned char i2c[3]; + int result; + backup_t back; + src = MULTI_PURPOSE_SOCKET_ADDR; + size = IMAGE_SIZE; + + if (strcmp(argv[1], "flash") == 0) + { + if (strcmp(argv[2], "floppy") == 0) { + char *local_args[3]; + extern int do_fdcboot (cmd_tbl_t *, bd_t *, int, int, char *[]); + printf ("\nupdating bootloader image from floppy\n"); + local_args[0] = argv[0]; + if(argc==4) { + local_args[1] = argv[3]; + local_args[2] = NULL; + load_addr=simple_strtoul(argv[3], NULL, 16); + result=do_fdcboot(cmdtp, bd, 0, 2, local_args); + } + else { + local_args[1] = NULL; + load_addr=CFG_LOAD_ADDR; + result=do_fdcboot(cmdtp, bd, 0, 1, local_args); + } + result=pip405_prg_image(load_addr); + return result; + } + if (strcmp(argv[2], "mem") == 0) { + if(argc==4) { + load_addr=simple_strtoul(argv[3], NULL, 16); + } + else { + load_addr=CFG_LOAD_ADDR; + } + printf ("\nupdating bootloader image from memory at %lX\n",load_addr); + result=pip405_prg_image(load_addr); + return result; + } + if (strcmp(argv[2], "mps") == 0) { + printf ("\nupdating bootloader image from MSP\n"); + result=pip405_prg(src,size); + return result; + } + } + if (strcmp(argv[1], "getback") == 0) { + get_backup_values(&back); + back.signature[3]=0; + back.serial_name[16]=0; + back.eth_addr[20]=0; + printf("GetBackUp: signature: %s\n",back.signature); + printf(" serial#: %s\n",back.serial_name); + printf(" ethaddr: %s\n",back.eth_addr); + return 0; + } + if (strcmp(argv[1], "setback") == 0) { + set_backup_values(1); + return 0; + } + if (strcmp(argv[1], "mem") == 0) + { + result=0; + if(argc==3) + { + result = (int)simple_strtol(argv[2], NULL, 16); + } + src=(unsigned long)&result; + src-=CFG_MEMTEST_START; + src-=(100*1024); /* - 100k */ + src&=0xfff00000; + size=0; + do { + size++; + printf("Pass %ld\n",size); + mem_test(CFG_MEMTEST_START,src,1); + if(ctrlc()) + break; + if(result>0) + result--; + + }while(result); + return 0; + } + if (strcmp(argv[1], "info") == 0) + { + print_pip405_info(); + return 0; + } + if (strcmp(argv[1], "i2c") == 0) + { + i2c[0]=CFG_I2C_EEPROM_ADDR; + i2c[1]=0; + i2c[2]=0; + i2c_read(&i2c[0],3,(unsigned char *)CFG_LOAD_ADDR,512); + return 0; + } + if (strcmp(argv[1], "led") == 0) + { + device = (ulong)simple_strtoul(argv[2], NULL, 10); + function = (ulong)simple_strtoul(argv[3], NULL, 10); + if(device==0) + user_led0((function==1)); + else + user_led1((function==1)); + return 0; + } + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +/* ------------------------------------------------------------------------- */ diff --git a/board/mpl/pip405/config.mk b/board/mpl/pip405/config.mk new file mode 100644 index 0000000..0f8d153 --- /dev/null +++ b/board/mpl/pip405/config.mk @@ -0,0 +1,29 @@ +# +# (C) Copyright 2000, 2001 +# Wolfgang Denk, DENX Software Engineering, wd@denx.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 +# + +# +# esd ADCIOP boards +# + +#TEXT_BASE = 0xFFFE0000 +TEXT_BASE = 0xFFF80000 diff --git a/board/mpl/pip405/init.S b/board/mpl/pip405/init.S new file mode 100644 index 0000000..1723d54 --- /dev/null +++ b/board/mpl/pip405/init.S @@ -0,0 +1,242 @@ +/*------------------------------------------------------------------------------+ + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + *-------------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Function: ext_bus_cntlr_init + * Description: Initializes the External Bus Controller for the external + * peripherals. IMPORTANT: For pass1 this code must run from + * cache since you can not reliably change a peripheral banks + * timing register (pbxap) while running code from that bank. + * For ex., since we are running from ROM on bank 0, we can NOT + * execute the code that modifies bank 0 timings from ROM, so + * we run it from cache. + * Bank 0 - Flash or Multi Purpose Socket + * Bank 1 - Multi Purpose Socket or Flash + * Bank 2 - not used + * Bank 3 - not used + * Bank 4 - not used + * Bank 5 - not used + * Bank 6 - used to switch on the 12V for the Multipurpose socket + * Bank 7 - Config Register + *-----------------------------------------------------------------------------*/ +#include + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include "config_PIP405.h" +#include +#include + +#include +#include + + + .globl ext_bus_cntlr_init +ext_bus_cntlr_init: + mflr r4 /* save link register */ + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + mtlr r4 /* restore link register */ + addi r4,0,14 /* set ctr to 14; used to prefetch */ + mtctr r4 /* 14 cache lines to fit this function */ + /* in cache (gives us 8x14=112 instrctns) */ +..ebcloop: + icbt r0,r3 /* prefetch cache line for addr in r3 */ + addi r3,r3,32 /* move to next cache line */ + bdnz ..ebcloop /* continue for 14 cache lines */ + + /*------------------------------------------------------------------- + * Delay to ensure all accesses to ROM are complete before changing + * bank 0 timings. + *------------------------------------------------------------------- */ + addis r3,0,0x0 + ori r3,r3,0xA000 + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + + /*----------------------------------------------------------------------- + * decide boot up mode + *----------------------------------------------------------------------- */ + addi r4,0,pb0cr + mtdcr ebccfga,r4 + mfdcr r4,ebccfgd + + andi. r0, r4, 0x2000 /* mask out irrelevant bits */ + beq 0f /* jump if 8 bit bus width */ + + /* setup 16 bit things + *----------------------------------------------------------------------- + * Memory Bank 0 (16 Bit Flash) initialization + *---------------------------------------------------------------------- */ + + addi r4,0,pb0ap + mtdcr ebccfga,r4 + addis r4,0,0x9B01 + ori r4,r4,0x5480 + mtdcr ebccfgd,r4 + + addi r4,0,pb0cr + mtdcr ebccfga,r4 + /* BS=0x011(8MB),BU=0x3(R/W), */ + addis r4,0,((FLASH_BASE0_PRELIM & 0xFFF00000) | 0x00050000)@h + ori r4,r4,0xA000 /* BW=0x01(16 bits) */ + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- + * Memory Bank 1 (Multi Purpose Socket) initialization + *----------------------------------------------------------------------*/ + addi r4,0,pb1ap + mtdcr ebccfga,r4 + addis r4,0,0x0281 + ori r4,r4,0x5480 + mtdcr ebccfgd,r4 + + addi r4,0,pb1cr + mtdcr ebccfga,r4 + /* BS=0x011(8MB),BU=0x3(R/W), */ + addis r4,0,((MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000) | 0x00050000)@h + ori r4,r4,0x8000 /* BW=0x0( 8 bits) */ + mtdcr ebccfgd,r4 + b 1f + +0: + /* 8Bit boot mode: */ + /*----------------------------------------------------------------------- + * Memory Bank 0 Multi Purpose Socket initialization + *----------------------------------------------------------------------- */ + + addi r4,0,pb0ap + mtdcr ebccfga,r4 + addis r4,0,0x9B01 + ori r4,r4,0x5480 + mtdcr ebccfgd,r4 + + addi r4,0,pb0cr + mtdcr ebccfga,r4 + /* BS=0x011(4MB),BU=0x3(R/W), */ + addis r4,0,((FLASH_BASE0_PRELIM & 0xFFF00000) | 0x00050000)@h + ori r4,r4,0x8000 /* BW=0x0( 8 bits) */ + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- + * Memory Bank 1 (Flash) initialization + *-----------------------------------------------------------------------*/ + addi r4,0,pb1ap + mtdcr ebccfga,r4 + addis r4,0,0x0281 + ori r4,r4,0x5480 + mtdcr ebccfgd,r4 + + addi r4,0,pb1cr + mtdcr ebccfga,r4 + /* BS=0x011(8MB),BU=0x3(R/W), */ + addis r4,0,((MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000) | 0x00050000)@h + ori r4,r4,0xA000 /* BW=0x0( 8 bits) */ + mtdcr ebccfgd,r4 + +1: + /*----------------------------------------------------------------------- + * Memory Bank 2-3-4-5-6 (not used) initialization + *-----------------------------------------------------------------------*/ + addi r4,0,pb2cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb3cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb4cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb5cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + addi r4,0,pb6cr + mtdcr ebccfga,r4 + addis r4,0,0x0000 + ori r4,r4,0x0000 + mtdcr ebccfgd,r4 + + /*----------------------------------------------------------------------- + * Memory Bank 7 (Config Register) initialization + *----------------------------------------------------------------------- */ + addi r4,0,pb7ap + mtdcr ebccfga,r4 + addis r4,0,0x0181 /* Doc says TWT=3 and Openios TWT=3!! */ + ori r4,r4,0x5280 /* disable Ready, BEM=0 */ + mtdcr ebccfgd,r4 + + addi r4,0,pb7cr + mtdcr ebccfga,r4 + /* BS=0x0(1MB),BU=0x3(R/W), */ + addis r4,0,((CONFIG_PORT_ADDR & 0xFFF00000) | 0x00010000)@h + ori r4,r4,0x8000 /* BW=0x0(8 bits) */ + mtdcr ebccfgd,r4 + nop /* pass2 DCR errata #8 */ + blr + +/*----------------------------------------------------------------------------- + * Function: sdram_init + * Description: Configures the internal SRAM memory. and setup the + * Stackpointer in it. + *----------------------------------------------------------------------------- */ + .globl sdram_init + +sdram_init: + + /*------------------------------------------------------------------- + * init OnChip Memory for a temporary stack + *------------------------------------------------------------------- */ + + lis r0, 0x7FFF + ori r0, r0, 0xFFFF + mfdcr r3, ocmiscntl /* get instr-side IRAM config */ + mfdcr r4, ocmdscntl /* get data-side IRAM config */ + and r3, r3, r0 /* disable data-side IRAM */ + and r4, r4, r0 /* disable data-side IRAM */ + mtdcr ocmiscntl, r3 /* set instr-side IRAM config */ + mtdcr ocmdscntl, r4 /* set data-side IRAM config */ + isync + lis r0, OCM_DATA_ADDR@h/* IRAM is mapped here */ + mtdcr ocmdsarc, r0 /* set data-side IRAM address */ + oris r4, r4, 0xC000 /* enable data-side IRAM */ + mtdcr ocmdscntl, r4 /* set data-side IRAM config */ + isync + + mfdcr r3, ocmdsarc /* set temp stackpointer (needed by CONS_Init) */ + andis. r3, r3, 0xFC00 + addi r1, r3, 0x1000-16 + + blr + diff --git a/board/mpl/pip405/pip405.c b/board/mpl/pip405/pip405.c new file mode 100644 index 0000000..f961eb4 --- /dev/null +++ b/board/mpl/pip405/pip405.c @@ -0,0 +1,1162 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + * + * TODO: clean-up + */ + +#include +#include "pip405.h" +#include +#include <405gp_i2c.h> +#include +#include "../common/isa.h" +#include "../common/video.h" + + +extern block_dev_desc_t * scsi_get_dev(int dev); +extern block_dev_desc_t * ide_get_dev(int dev); + +#undef SDRAM_DEBUG + +#define FALSE 0 +#define TRUE 1 + +/* stdlib.h causes some compatibility problems; should fixe these! -- wd */ +#ifndef __ldiv_t_defined +typedef struct { + long int quot; /* Quotient */ + long int rem; /* Remainder */ +} ldiv_t; +extern ldiv_t ldiv (long int __numer, long int __denom); +# define __ldiv_t_defined 1 +#endif + + + + +typedef enum { + SDRAM_NO_ERR, + SDRAM_SPD_COMM_ERR, + SDRAM_SPD_CHKSUM_ERR, + SDRAM_UNSUPPORTED_ERR, + SDRAM_UNKNOWN_ERR +} SDRAM_ERR; + +typedef struct { + const unsigned char mode; + const unsigned char row; + const unsigned char col; + const unsigned char bank; +} SDRAM_SETUP; + +static const SDRAM_SETUP sdram_setup_table[] = { + {1, 11, 9, 2}, + {1, 11, 10, 2}, + {2, 12, 9, 4}, + {2, 12, 10, 4}, + {3, 13, 9, 4}, + {3, 13, 10, 4}, + {3, 13, 11, 4}, + {4, 12, 8, 2}, + {4, 12, 8, 4}, + {5, 11, 8, 2}, + {5, 11, 8, 4}, + {6, 13, 8, 2}, + {6, 13, 8, 4}, + {7, 13, 9, 2}, + {7, 13, 10, 2}, + {0, 0, 0, 0} +}; + +static const unsigned char cal_indextable[] = { + 9, 23, 25 +}; + + +/* + * translate ns.ns/10 coding of SPD timing values + * into 10 ps unit values + */ + +unsigned short NS10to10PS(unsigned char spd_byte, unsigned char spd_version) +{ + unsigned short ns, ns10; + + /* isolate upper nibble */ + ns = (spd_byte >> 4) & 0x0F; + /* isolate lower nibble */ + ns10 = (spd_byte & 0x0F); + + return(ns*100 + ns10*10); +} + +/* + * translate ns.ns/4 coding of SPD timing values + * into 10 ps unit values + */ + +unsigned short NS4to10PS(unsigned char spd_byte, unsigned char spd_version) +{ + unsigned short ns, ns4; + + /* isolate upper 6 bits */ + ns = (spd_byte >> 2) & 0x3F; + /* isloate lower 2 bits */ + ns4 = (spd_byte & 0x03); + + return(ns*100 + ns4*25); +} + +/* + * translate ns coding of SPD timing values + * into 10 ps unit values + */ + +unsigned short NSto10PS(unsigned char spd_byte) +{ + return(spd_byte*100); +} + +void SDRAM_err(const char *s) +{ +#ifndef SDRAM_DEBUG + serial_init(get_gclk_freq(),9600); +#endif + serial_puts("\n"); + serial_puts(s); + serial_puts("\n enable SDRAM_DEBUG for more info\n"); + for (;;); +} + + +#ifdef SDRAM_DEBUG + +void write_hex(unsigned char i) +{ + char cc; + cc=i>>4; + cc&=0xf; + if(cc>9) + serial_putc(cc+55); + else + serial_putc(cc+48); + cc=i&0xf; + if(cc>9) + serial_putc(cc+55); + else + serial_putc(cc+48); +} + +void write_4hex(unsigned long val) +{ + write_hex((unsigned char)(val>>24)); + write_hex((unsigned char)(val>>16)); + write_hex((unsigned char)(val>>8)); + write_hex((unsigned char)val); +} + +#endif + +int board_pre_init (void) +{ + unsigned char dataout[1]; + unsigned char datain[128]; + unsigned long sdram_size; + SDRAM_SETUP *t = (SDRAM_SETUP *)sdram_setup_table; + unsigned long memclk; + unsigned long tmemclk; + unsigned long tmp, bank, baseaddr, bank_size; + unsigned short i; + unsigned char rows, cols, banks, sdram_banks, density; + unsigned char supported_cal, trp_clocks, trcd_clocks, tras_clocks, trc_clocks,tctp_clocks; + unsigned char cal_index, cal_val, spd_version, spd_chksum; + unsigned char buf[8]; + + memclk = get_bus_freq(tmemclk); + tmemclk = 1000000000 / (memclk / 100); /* in 10 ps units */ + +#ifdef SDRAM_DEBUG + serial_init(get_gclk_freq(),9600); + serial_puts("\nstart SDRAM Setup\n"); +#endif + + /* Read Serial Presence Detect Information */ + dataout[0] = 0; + for (i=0; i<128;i++) + datain[i] = 127; + i=i2c_send(SDRAM_EEPROM_WRITE_ADDRESS,1,dataout); +#ifdef SDRAM_DEBUG + serial_puts("i2c_send returns "); + write_hex(i); +#endif + i=i2c_receive(SDRAM_EEPROM_READ_ADDRESS,128,datain); +#ifdef SDRAM_DEBUG + serial_puts("\ni2c_receive returns "); + write_hex(i); + serial_puts("\n"); +#endif + +#ifdef SDRAM_DEBUG + for (i=0;i<128;i++) + { + write_hex(datain[i]); + serial_puts(" "); + if (((i+1)%16) == 0) + serial_puts("\n"); + } + serial_puts("\n"); +#endif + spd_chksum = 0; + for (i = 0; i < 63; i++) { + spd_chksum += datain[i]; + } /* endfor */ + if (datain[63] != spd_chksum) { +#ifdef SDRAM_DEBUG + serial_puts("SPD chksum: 0x"); + write_hex(datain[63]); + serial_puts(" != calc. chksum: 0x"); + write_hex(spd_chksum); + serial_puts("\n"); +#endif + SDRAM_err("SPD checksum Error"); + } + /* SPD seems to be ok, use it */ + + /* get SPD version */ + spd_version = datain[62]; + + /* do some sanity checks on the kind of RAM */ + if ((datain[0] < 0x80) || /* less than 128 valid bytes in SPD */ + (datain[2] != 0x04) || /* if not SDRAM */ + (!((datain[6] == 0x40) || + (datain[6] == 0x48))) || /* or not (64 Bit or 72 Bit) */ + (datain[7] != 0x00) || + (datain[8] != 0x01) || /* or not LVTTL signal levels */ + (datain[126] == 0x66)) /* or a 66Mhz modules */ + SDRAM_err("unsupported SDRAM"); +#ifdef SDRAM_DEBUG + serial_puts("SDRAM sanity ok\n"); +#endif + + /* get number of rows/cols/banks out of byte 3+4+5 */ + rows = datain[3]; cols = datain[4]; banks = datain[5]; + + /* get number of SDRAM banks out of byte 17 and + supported CAS latencies out of byte 18 */ + sdram_banks = datain[17]; supported_cal = datain[18] & ~0x81; + + while (t->mode != 0) { + if ((t->row == rows) && (t->col == cols) && (t->bank == sdram_banks)) + break; + t++; + } /* endwhile */ + +#ifdef SDRAM_DEBUG + serial_puts("rows: "); + write_hex(rows); + serial_puts(" cols: "); + write_hex(cols); + serial_puts(" banks: "); + write_hex(banks); + serial_puts(" mode: "); + write_hex(t->mode); + serial_puts("\n"); +#endif + if (t->mode == 0) + SDRAM_err("unsupported SDRAM"); + /* get tRP, tRCD, tRAS and density from byte 27+29+30+31 */ +#ifdef SDRAM_DEBUG + serial_puts("tRP: "); + write_hex(datain[27]); + serial_puts("\ntRCD: "); + write_hex(datain[29]); + serial_puts("\ntRAS: "); + write_hex(datain[30]); + serial_puts("\n"); +#endif + + trp_clocks = (NSto10PS(datain[27])+(tmemclk-1)) / tmemclk; + trcd_clocks = (NSto10PS(datain[29])+(tmemclk-1)) / tmemclk; + tras_clocks = (NSto10PS(datain[30])+(tmemclk-1)) / tmemclk; + density = datain[31]; + + /* trc_clocks is sum of trp_clocks + tras_clocks */ + trc_clocks = trp_clocks + tras_clocks; + /* ctp = ((trp + tras) - trp - trcd) => tras - trcd */ + tctp_clocks = ((NSto10PS(datain[30])-NSto10PS(datain[29]))+(tmemclk-1)) / tmemclk; + +#ifdef SDRAM_DEBUG + serial_puts("c_RP: "); + write_hex(trp_clocks); + serial_puts("\nc_RCD: "); + write_hex(trcd_clocks); + serial_puts("\nc_RAS: "); + write_hex(tras_clocks); + serial_puts("\nc_RC: (RP+RAS): "); + write_hex(trc_clocks); + serial_puts("\nc_CTP: ((RP+RAS)-RP-RCD): "); + write_hex(tctp_clocks); + serial_puts("\nt_CTP: RAS - RCD: "); + write_hex((unsigned char)((NSto10PS(datain[30])-NSto10PS(datain[29]))>>8)); + write_hex((unsigned char)(NSto10PS(datain[30])-NSto10PS(datain[29]))); + serial_puts("\ntmemclk: "); + write_hex((unsigned char)(tmemclk>>8)); + write_hex((unsigned char)(tmemclk)); + serial_puts("\n"); +#endif + + + cal_val = 255; + for (i = 6, cal_index = 0; (i > 0) && (cal_index < 3); i--) { + /* is this CAS latency supported ? */ + if ((supported_cal >> i) & 0x01) { + buf[0]=datain[cal_indextable[cal_index]]; + if (cal_index < 2) { + if (NS10to10PS(buf[0], spd_version) <= tmemclk) + cal_val = i; + } + else { + /* SPD bytes 25+26 have another format */ + if (NS4to10PS(buf[0], spd_version) <= tmemclk) + cal_val = i; + } /* endif */ + cal_index++; + } /* endif */ + } /* endfor */ +#ifdef SDRAM_DEBUG + serial_puts("CAL: "); + write_hex(cal_val+1); + serial_puts("\n"); +#endif + + if (cal_val == 255) + SDRAM_err("unsupported SDRAM"); + + /* get SDRAM timing register */ + mtdcr(memcfga,mem_sdtr1); + tmp=mfdcr(memcfgd) & ~0x018FC01F; + /* insert CASL value */ +/* tmp |= ((unsigned long)cal_val) << 23; */ + tmp |= ((unsigned long)cal_val) << 23; + /* insert PTA value */ + tmp |= ((unsigned long)(trp_clocks - 1)) << 18; + /* insert CTP value */ +/* tmp |= ((unsigned long)(trc_clocks - trp_clocks - trcd_clocks - 1)) << 16; */ + tmp |= ((unsigned long)(trc_clocks - trp_clocks - trcd_clocks)) << 16; + /* insert LDF (always 01) */ + tmp |= ((unsigned long)0x01) << 14; + /* insert RFTA value */ + tmp |= ((unsigned long)(trc_clocks - 4)) << 2; + /* insert RCD value */ + tmp |= ((unsigned long)(trcd_clocks - 1)) << 0; + +#ifdef SDRAM_DEBUG + serial_puts("sdtr: "); + write_4hex(tmp); + serial_puts("\n"); +#endif + + /* write SDRAM timing register */ + mtdcr(memcfga,mem_sdtr1); + mtdcr(memcfgd,tmp); + baseaddr=CFG_SDRAM_BASE; + bank_size = (((unsigned long)density) << 22) / 2; + /* insert AM value */ + tmp = ((unsigned long)t->mode-1) << 13; + /* insert SZ value; */ + switch (bank_size) { + case 0x00400000: tmp |= ((unsigned long)0x00) << 17; break; + case 0x00800000: tmp |= ((unsigned long)0x01) << 17; break; + case 0x01000000: tmp |= ((unsigned long)0x02) << 17; break; + case 0x02000000: tmp |= ((unsigned long)0x03) << 17; break; + case 0x04000000: tmp |= ((unsigned long)0x04) << 17; break; + case 0x08000000: tmp |= ((unsigned long)0x05) << 17; break; + case 0x10000000: tmp |= ((unsigned long)0x06) << 17; break; + default: SDRAM_err("unsupported SDRAM"); + } /* endswitch */ + /* get SDRAM bank 0 register */ + mtdcr(memcfga,mem_mb0cf); + bank = mfdcr(memcfgd) & ~0xFFCEE001; + bank |= (baseaddr | tmp | 0x01); +#ifdef SDRAM_DEBUG + serial_puts("bank0: baseaddr: "); + write_4hex(baseaddr); + serial_puts(" banksize: "); + write_4hex(bank_size); + serial_puts(" mb0cf: "); + write_4hex(bank); + serial_puts("\n"); +#endif + baseaddr += bank_size; + sdram_size += bank_size; + + /* write SDRAM bank 0 register */ + mtdcr(memcfga,mem_mb0cf); + mtdcr(memcfgd,bank); + + /* get SDRAM bank 1 register */ + mtdcr(memcfga,mem_mb1cf); + bank = mfdcr(memcfgd) & ~0xFFCEE001; + sdram_size=0; + +#ifdef SDRAM_DEBUG + serial_puts("bank1: baseaddr: "); + write_4hex(baseaddr); + serial_puts(" banksize: "); + write_4hex(bank_size); +#endif + if (banks == 2) { + bank |= (baseaddr | tmp | 0x01); + baseaddr += bank_size; + sdram_size += bank_size; + } /* endif */ +#ifdef SDRAM_DEBUG + serial_puts(" mb1cf: "); + write_4hex(bank); + serial_puts("\n"); +#endif + /* write SDRAM bank 1 register */ + mtdcr(memcfga,mem_mb1cf); + mtdcr(memcfgd,bank); + + /* get SDRAM bank 2 register */ + mtdcr(memcfga,mem_mb2cf); + bank = mfdcr(memcfgd) & ~0xFFCEE001; + + bank |= (baseaddr | tmp | 0x01); + +#ifdef SDRAM_DEBUG + serial_puts("bank2: baseaddr: "); + write_4hex(baseaddr); + serial_puts(" banksize: "); + write_4hex(bank_size); + serial_puts(" mb2cf: "); + write_4hex(bank); + serial_puts("\n"); +#endif + + baseaddr += bank_size; + sdram_size += bank_size; + + /* write SDRAM bank 2 register */ + mtdcr(memcfga,mem_mb2cf); + mtdcr(memcfgd,bank); + + /* get SDRAM bank 3 register */ + mtdcr(memcfga,mem_mb3cf); + bank = mfdcr(memcfgd) & ~0xFFCEE001; + +#ifdef SDRAM_DEBUG + serial_puts("bank3: baseaddr: "); + write_4hex(baseaddr); + serial_puts(" banksize: "); + write_4hex(bank_size); +#endif + + if (banks == 2) { + bank |= (baseaddr | tmp | 0x01); + baseaddr += bank_size; + sdram_size += bank_size; + } /* endif */ + +#ifdef SDRAM_DEBUG + serial_puts(" mb3cf: "); + write_4hex(bank); + serial_puts("\n"); +#endif + + /* write SDRAM bank 3 register */ + mtdcr(memcfga,mem_mb3cf); + mtdcr(memcfgd,bank); + + + /* get SDRAM refresh interval register */ + mtdcr(memcfga,mem_rtr); + tmp = mfdcr(memcfgd) & ~0x3FF80000; + + if (tmemclk < NSto10PS(16)) + tmp |= 0x05F00000; + else + tmp |= 0x03F80000; + + /* write SDRAM refresh interval register */ + mtdcr(memcfga,mem_rtr); + mtdcr(memcfgd,tmp); + + /* enable SDRAM controller with no ECC, 32-bit SDRAM width, 16 byte burst */ + mtdcr(memcfga,mem_mcopt1); + tmp = (mfdcr(memcfgd) & ~0xFFE00000) | 0x80E00000; + mtdcr(memcfga,mem_mcopt1); + mtdcr(memcfgd,tmp); + + + + /*-------------------------------------------------------------------------+ + | Interrupt controller setup for the PIP405 board. + | Note: IRQ 0-15 405GP internally generated; active high; level sensitive + | IRQ 16 405GP internally generated; active low; level sensitive + | IRQ 17-24 RESERVED + | IRQ 25 (EXT IRQ 0) SouthBridg; active low; level sensitive + | IRQ 26 (EXT IRQ 1) NMI: active low; level sensitive + | IRQ 27 (EXT IRQ 2) SMI: active Low; level sensitive + | IRQ 28 (EXT IRQ 3) PCI SLOT 3; active low; level sensitive + | IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive + | IRQ 30 (EXT IRQ 5) PCI SLOT 1; active low; level sensitive + | IRQ 31 (EXT IRQ 6) PCI SLOT 0; active low; level sensitive + | Note for PIP405 board: + | An interrupt taken for the SouthBridge (IRQ 25) indicates that + | the Interrupt Controller in the South Bridge has caused the + | interrupt. The IC must be read to determine which device + | caused the interrupt. + | + +-------------------------------------------------------------------------*/ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + mtdcr(uicer, 0x00000000); /* disable all ints */ + mtdcr(uiccr, 0x00000000); /* set all to be non-critical (for now)*/ + mtdcr(uicpr, 0xFFFFFF80); /* set int polarities */ + mtdcr(uictr, 0x10000000); /* set int trigger levels */ + mtdcr(uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority*/ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + + return 0; +} + + +/* ------------------------------------------------------------------------- */ +#define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */ + +void get_backup_values(backup_t *buf) +{ + eeprom_read (CFG_DEF_EEPROM_ADDR, + I2C_BACKUP_ADDR, + (void *)buf, + sizeof(backup_t)); +} + +void set_backup_values(int overwrite) +{ + backup_t back; + int i; + + get_backup_values(&back); + if(!overwrite) { + if(strncmp(back.signature,"MPL\0",4)==0) { + printf("Not possible to write Backup\n"); + return; + } + } + memcpy(back.signature,"MPL\0",4); + i=getenv_r("serial#",back.serial_name,16); + if(i==0) { + printf("Not possible to write Backup\n"); + return; + } + back.serial_name[16]=0; + i=getenv_r("ethaddr",back.eth_addr,20); + if(i==0) { + printf("Not possible to write Backup\n"); + return; + } + back.eth_addr[20]=0; + eeprom_write (CFG_DEF_EEPROM_ADDR, + CFG_ENV_OFFSET+I2C_BACKUP_ADDR, + (void *)&back, + sizeof(backup_t)); +} + + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + unsigned char s[50]; + unsigned char bc; + int i; + backup_t *b=(backup_t *)s; + + i=getenv_r("serial#",s,32); + if ((i==0) || strncmp(s, "PIP405", 6)) { + get_backup_values(b); + if(strncmp(b->signature,"MPL\0",4)!=0) { + printf("### No HW ID - assuming PIP405"); + } + else { + b->serial_name[6]=0; + printf("%s SN: %s",b->serial_name,&b->serial_name[7]); + } + } + else { + s[6]=0; + printf("%s SN: %s",s,&s[7]); + } + bc=in8(CONFIG_PORT_ADDR); + printf(" Boot Config: 0x%x\n",bc); + return (0); +} + + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +/* + initdram(int board_type) reads EEPROM via I2c. EEPROM contains all of + the necessary info for SDRAM controller configuration +*/ +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +int testdram (unsigned long ramsize); + +long int initdram (int board_type) +{ + + unsigned long bank_reg[4],tmp,bank_size; + int i,ds; + unsigned long TotalSize; + + ds=0; + /* since the DRAM controller is allready set up, calculate the size with the + bank registers */ + mtdcr(memcfga,mem_mb0cf); + bank_reg[0] = mfdcr(memcfgd); + mtdcr(memcfga,mem_mb1cf); + bank_reg[1] = mfdcr(memcfgd); + mtdcr(memcfga,mem_mb2cf); + bank_reg[2] = mfdcr(memcfgd); + mtdcr(memcfga,mem_mb3cf); + bank_reg[3] = mfdcr(memcfgd); + TotalSize=0; + for(i=0;i<4;i++) + { + if((bank_reg[i]&0x1)==0x1) + { + tmp=(bank_reg[i]>>17)&0x7; + bank_size=4<220000000) + TotalSize/=2; + return (TotalSize*1024*1024); +} + +/* ------------------------------------------------------------------------- */ + + +int testdram (unsigned long ramsize) +{ + /* not yet implemented */ + return(1); +} + +/* ------------------------------------------------------------------------- */ + + /* switches the cs0 and the cs1 to the locations. + When boot is TRUE, the the mapping is switched + to the boot configuration, If it is FALSE, the + flash will be switched in the boot area */ + + +#undef SW_CS_DBG +#ifdef SW_CS_DBG +#define SW_CS_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define SW_CS_PRINTF(fmt,args...) +#endif + + +int switch_cs(unsigned char boot) +{ + unsigned long pbcr; + mtdcr(ebccfga, pb0cr); /* get cs0 config reg */ + pbcr = mfdcr(ebccfgd); + if((pbcr&0x00002000)==0) { + /* we need only to switch if boot from MPS */ + SW_CS_PRINTF(" MPS boot mode detected. "); + /* printf("cs0 cfg: %lx\n",pbcr); */ + if(boot==TRUE) { + /* switch to boot configuration */ + /* this is a 8bit boot, switch cs0 to flash location */ + SW_CS_PRINTF("switch to boot mode (MPS on High address\n"); + pbcr&=0x000FFFFF; /*mask base address of the cs0 */ + pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000); + mtdcr(ebccfga, pb0cr); + mtdcr(ebccfgd, pbcr); + SW_CS_PRINTF(" new cs0 cfg: %lx\n",pbcr); + mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */ + pbcr = mfdcr(ebccfgd); + SW_CS_PRINTF(" old cs1 cfg: %lx\n",pbcr); + pbcr&=0x000FFFFF; /*mask base address of the cs1 */ + pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000); + mtdcr(ebccfga, pb1cr); + mtdcr(ebccfgd, pbcr); + SW_CS_PRINTF(" new cs1 cfg: %lx, MPS is on High Address\n",pbcr); + } + else + { + /* map flash to boot area, */ + SW_CS_PRINTF("map Flash to boot area\n"); + pbcr&=0x000FFFFF; /*mask base address of the cs0 */ + pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000); + mtdcr(ebccfga, pb0cr); + mtdcr(ebccfgd, pbcr); + SW_CS_PRINTF(" new cs0 cfg: %lx\n",pbcr); + mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */ + pbcr = mfdcr(ebccfgd); + SW_CS_PRINTF(" cs1 cfg: %lx\n",pbcr); + pbcr&=0x000FFFFF; /*mask base address of the cs1 */ + pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000); + mtdcr(ebccfga, pb1cr); + mtdcr(ebccfgd, pbcr); + SW_CS_PRINTF(" new cs1 cfg: %lx Flash is on High Address\n",pbcr); + } + return TRUE; + } + else { + SW_CS_PRINTF("Normal boot, no switching necessary\n"); + return FALSE; + } +} + +void misc_init_r(bd_t *bd) +{ + unsigned char bc; + char buf[128]; + unsigned char *s; + + bc=in8(CONFIG_PORT_ADDR); + bc>>=4; + bc &= 0x0f; + sprintf(buf,"bootcmd%d",bc); + s = getenv(buf); + if(s) { + sprintf(buf,"%s",s); + setenv("bootcmd",buf); + } + sprintf(buf,"bootargs%d",bc); + s = getenv(buf); + if(s) { + sprintf(buf,"%s",s); + setenv("bootargs",buf); + } +} + +/*************************************************************************** + * some helping routines + */ + +int overwrite_console(void) +{ + return(in8(CONFIG_PORT_ADDR) & 0x1); /* return TRUE if console should be overwritten */ +} + + +void set_init_backup(void) +{ + unsigned char *s; + char buf[32]; + backup_t back; + + s=getenv("serial#"); + if(!s) { + get_backup_values(&back); + if(strncmp(back.signature,"MPL\0",4)==0) { + sprintf(buf,"%s",back.serial_name); + setenv("serial#",buf); + sprintf(buf,"%s",back.eth_addr); + setenv("ethaddr",buf); + printf("INFO: serial# and ethaddr recovered, use saveenv\n"); + } + } + else { + /* check if back up is set */ + get_backup_values(&back); + if(strncmp(back.signature,"MPL\0",4)!=0) { + set_backup_values(0); + } + } +} + +extern int isa_init(void); + + +void print_pip405_rev(void) +{ + unsigned char part,vers,cfg; + part=in8(PLD_PART_REG); + vers=in8(PLD_VERS_REG); + cfg=in8(PLD_BOARD_CFG_REG); + printf("Rev: PIP405-%d Rev %c PLD%d %d PLD%d %d\n",16-((cfg>>4)&0xf),(cfg&0xf)+'A', + part&0xf,vers&0xf,(part>>4)&0xf,(vers>>4)&0xf); +} + +extern device_t *stdio_devices[]; +extern char *stdio_names[]; + +void show_stdio_dev(void) +{ + /* Print informations */ + printf ("In: "); + if (stdio_devices[stdin] == NULL) { + printf ("No input devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdin]->name); + } + + printf ("Out: "); + if (stdio_devices[stdout] == NULL) { + printf ("No output devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdout]->name); + } + + printf ("Err: "); + if (stdio_devices[stderr] == NULL) { + printf ("No error devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stderr]->name); + } +} + + + +int last_stage_init(void) +{ + print_pip405_rev(); + set_init_backup(); + isa_init(); + show_stdio_dev(); + return 0; +} + +/************************************************************************ +* Print PIP405 Info +************************************************************************/ +void print_pip405_info(void) +{ + unsigned char part,vers,cfg,ledu,sysman,flashcom,can,serpwr,compwr,nicvga,scsirst; + + part=in8(PLD_PART_REG); + vers=in8(PLD_VERS_REG); + cfg=in8(PLD_BOARD_CFG_REG); + ledu=in8(PLD_LED_USER_REG); + sysman=in8(PLD_SYS_MAN_REG); + flashcom=in8(PLD_FLASH_COM_REG); + can=in8(PLD_CAN_REG); + serpwr=in8(PLD_SER_PWR_REG); + compwr=in8(PLD_COM_PWR_REG); + nicvga=in8(PLD_NIC_VGA_REG); + scsirst=in8(PLD_SCSI_RST_REG); + printf("PLD Part %d version %d\n",part&0xf,vers&0xf); + printf("PLD Part %d version %d\n",(part>>4)&0xf,(vers>>4)&0xf); + printf("Board Revision %c\n",(cfg&0xf)+'A'); + printf("Population Options %d %d %d %d\n",(cfg>>4)&0x1,(cfg>>5)&0x1,(cfg>>6)&0x1,(cfg>>7)&0x1); + printf("User LED0 %s User LED1 %s\n",((ledu&0x1)==0x1) ? "on" : "off",((ledu&0x2)==0x2) ? "on" : "off"); + printf("Additionally Options %d %d\n",(ledu>>2)&0x1,(ledu>>3)&0x1); + printf("User Config Switch %d %d %d %d\n",(ledu>>4)&0x1,(ledu>>5)&0x1,(ledu>>6)&0x1,(ledu>>7)&0x1); + switch(sysman&0x3) + { + case 0: printf("PCI Clocks are running\n"); break; + case 1: printf("PCI Clocks are stopped in POS State\n"); break; + case 2: printf("PCI Clocks are stopped when PCI_STP# is asserted\n"); break; + case 3: printf("PCI Clocks are stopped\n"); break; + } + switch((sysman>>2)&0x3) + { + case 0: printf("Main Clocks are running\n"); break; + case 1: printf("Main Clocks are stopped in POS State\n"); break; + case 2: + case 3: printf("PCI Clocks are stopped\n"); break; + } + printf("INIT asserts %sINT2# (SMI)\n",((sysman&0x10)==0x10) ? "" : "not "); + printf("INIT asserts %sINT1# (NMI)\n",((sysman&0x20)==0x20) ? "" : "not "); + printf("INIT occured %d\n",(sysman>>6)&0x1); + printf("SER1 is routed to %s\n",((flashcom&0x1)==0x1) ? "RS485" : "RS232"); + printf("COM2 is routed to %s\n",((flashcom&0x2)==0x2) ? "RS485" : "RS232"); + printf("RS485 is configured as %s duplex\n",((flashcom&0x4)==0x4) ? "full" : "half"); + printf("RS485 is connected to %s\n",((flashcom&0x8)==0x8) ? "COM1" : "COM2"); + printf("SER1 uses handshakes %s\n",((flashcom&0x10)==0x10) ? "DTR/DSR" : "RTS/CTS"); + printf("Bootflash is %swriteprotected\n",((flashcom&0x20)==0x20) ? "not " : ""); + printf("Bootflash VPP is %s\n",((flashcom&0x40)==0x40) ? "on" : "off"); + printf("Bootsector is %swriteprotected\n",((flashcom&0x80)==0x80) ? "not " : ""); + switch((can)&0x3) + { + case 0: printf("CAN Controller is on address 0x1000..0x10FF\n"); break; + case 1: printf("CAN Controller is on address 0x8000..0x80FF\n"); break; + case 2: printf("CAN Controller is on address 0xE000..0xE0FF\n"); break; + case 3: printf("CAN Controller is disabled\n"); break; + } + switch((can>>2)&0x3) + { + case 0: printf("CAN Controller Reset is ISA Reset\n"); break; + case 1: printf("CAN Controller Reset is ISA Reset and POS State\n"); break; + case 2: + case 3: printf("CAN Controller is in reset\n"); break; + } + if(((can>>4)<3)||((can>>4)==8)||((can>>4)==13)) + printf("CAN Interrupt is disabled\n"); + else + printf("CAN Interrupt is ISA INT%d\n",(can>>4)&0xf); + switch(serpwr&0x3) + { + case 0: printf("SER0 Drivers are enabled\n"); break; + case 1: printf("SER0 Drivers are disabled in the POS state\n"); break; + case 2: + case 3: printf("SER0 Drivers are disabled\n"); break; + } + switch((serpwr>>2)&0x3) + { + case 0: printf("SER1 Drivers are enabled\n"); break; + case 1: printf("SER1 Drivers are disabled in the POS state\n"); break; + case 2: + case 3: printf("SER1 Drivers are disabled\n"); break; + } + switch(compwr&0x3) + { + case 0: printf("COM1 Drivers are enabled\n"); break; + case 1: printf("COM1 Drivers are disabled in the POS state\n"); break; + case 2: + case 3: printf("COM1 Drivers are disabled\n"); break; + } + switch((compwr>>2)&0x3) + { + case 0: printf("COM2 Drivers are enabled\n"); break; + case 1: printf("COM2 Drivers are disabled in the POS state\n"); break; + case 2: + case 3: printf("COM2 Drivers are disabled\n"); break; + } + switch((nicvga)&0x3) + { + case 0: printf("PHY is running\n"); break; + case 1: printf("PHY is in Power save mode in POS state\n"); break; + case 2: + case 3: printf("PHY is in Power save mode\n"); break; + } + switch((nicvga>>2)&0x3) + { + case 0: printf("VGA is running\n"); break; + case 1: printf("VGA is in Power save mode in POS state\n"); break; + case 2: + case 3: printf("VGA is in Power save mode\n"); break; + } + printf("PHY is %sreseted\n",((nicvga&0x10)==0x10)?"":"not "); + printf("VGA is %sreseted\n",((nicvga&0x20)==0x20)?"":"not "); + printf("Reserved Configuration is %d %d\n",(nicvga>>6)&0x1,(nicvga>>7)&0x1); + switch((scsirst)&0x3) + { + case 0: printf("SCSI Controller is running\n"); break; + case 1: printf("SCSI Controller is in Power save mode in POS state\n"); break; + case 2: + case 3: printf("SCSI Controller is in Power save mode\n"); break; + } + printf("SCSI termination is %s\n",((scsirst&0x4)==0x4)?"disabled":"enabled"); + printf("SCSI Controller is %sreseted\n",((scsirst&0x10)==0x10)?"":"not "); + printf("IDE disks are %sreseted\n",((scsirst&0x20)==0x20)?"":"not "); + printf("ISA Bus is %sreseted\n",((scsirst&0x40)==0x40)?"":"not "); + printf("Super IO is %sreseted\n",((scsirst&0x80)==0x80)?"":"not "); +} + +void user_led0(unsigned char on) +{ + if(on==TRUE) + out8(PLD_LED_USER_REG,(in8(PLD_LED_USER_REG)|0x1)); + else + out8(PLD_LED_USER_REG,(in8(PLD_LED_USER_REG)&0xfe)); +} + +void user_led1(unsigned char on) +{ + if(on==TRUE) + out8(PLD_LED_USER_REG,(in8(PLD_LED_USER_REG)|0x2)); + else + out8(PLD_LED_USER_REG,(in8(PLD_LED_USER_REG)&0xfd)); +} + +void ide_set_reset(int idereset) +{ + /* if reset = 1 IDE reset will be asserted */ + unsigned char resreg; + resreg=in8(PLD_SCSI_RST_REG); + if(idereset==1) + resreg|=0x20; + else + resreg&=0xdf; + out8(PLD_SCSI_RST_REG,resreg); +} + + +/****************************************************** + * Routines to display the Board information + * to the screen (since the VGA will be initialized as last, + * we must resend the infos) + */ + +void video_put_dev_string(block_dev_desc_t *dev_desc) +{ + char buf[80]; + ldiv_t mb,gb; + unsigned long lba512; /* number of blocks if 512bytes block size */ + + if(dev_desc->type!=DEV_TYPE_UNKNOWN) { + if(dev_desc->if_type==IF_TYPE_SCSI) + sprintf(buf,"SCSI %d: (%d:%d) ",dev_desc->dev,dev_desc->target,dev_desc->lun); + else + sprintf(buf,"IDE %d: ",dev_desc->dev); + video_puts(buf); + switch(dev_desc->type & 0x1F) { + case DEV_TYPE_HARDDISK: video_puts("Hard Disk"); break; + case DEV_TYPE_CDROM: video_puts("CD ROM"); break; + case DEV_TYPE_OPDISK: video_puts("Optical Device"); break; + case DEV_TYPE_TAPE: video_puts("Tape"); break; + default: video_puts("unknown"); break; + } + video_puts(" "); + video_puts(dev_desc->vendor); + video_puts(" "); + if(dev_desc->if_type!=IF_TYPE_IDE) + video_puts(dev_desc->product); + + if((dev_desc->lba * dev_desc->blksz)>0L) { + lba512=(dev_desc->lba * (dev_desc->blksz/512)); + mb = ldiv(lba512, 2048); /* (1024 *1024 / 512 MB */ + /* we do NOT round, because if we round 0.95MByte up, we get 0.10MByte !!*/ + mb.rem *= 10; + mb.rem /= 2048; + gb = ldiv(10 * mb.quot + mb.rem, 10240); + gb.rem += 512; + gb.rem /= 1024; + printf (" Capacity: %ld.%ld MB = %ld.%ld GB (%ld x %ld)\n", + mb.quot, mb.rem, + gb.quot, gb.rem, + dev_desc->lba, + dev_desc->blksz); + } + else { + sprintf (buf," Capacity: not available\n"); + } + video_puts(buf); + } +} + +void video_write_board_info(void) +{ + extern char version_string[]; + unsigned long pvr = get_pvr(); + char buf[32],tmpbuf[80]; + PPC405_SYS_INFO sys_info; + init_data_t *idata = (init_data_t *)(CFG_INIT_RAM_ADDR + CFG_INIT_DATA_OFFSET); + unsigned char *s = getenv("serial#"); + unsigned char *e; + unsigned char bc; + + /* first write PPCBOOT Info */ + video_puts("\n"); + video_puts(version_string); + video_puts("\n\n"); + /* then CPU and board infos */ + get_sys_info(&sys_info); + video_puts("CPU: IBM PowerPC 405GP Rev. "); + switch (pvr) { + case PVR_405GP_RB: video_putc('B'); break; + case PVR_405GP_RC: video_putc('C'); break; + case PVR_405GP_RD: video_putc('D'); break; + case PVR_405GP_RE: video_putc('E'); break; + default: video_puts("unknown"); break; + } + sprintf(tmpbuf," at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf,idata->cpu_clk), + sys_info.freqPLB / 1000000, + sys_info.freqPLB / sys_info.pllOpbDiv / 1000000, + sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000); + video_puts(tmpbuf); + if (mfdcr(strap) & PSR_PCI_ASYNC_EN) + video_puts(" PCI async ext clock used, "); + else { + sprintf(buf," PCI sync clock at %lu MHz, ", sys_info.freqPLB / sys_info.pllPciDiv / 1000000); + video_puts(buf); + } + if (mfdcr(strap) & PSR_PCI_ARBIT_EN) + video_puts("internal PCI arbiter enabled\n"); + else + video_puts("external PCI arbiter enabled\n"); + video_puts(" 16 kB I-Cache 8 kB D-Cache\n"); + /* now some board infos */ + video_puts("Board: "); + if (!s || strncmp(s, "PIP405", 6)) { + bc=video_set_attr(VGA_ATTR_CLR_RED | VGA_ATTR_ITN); + video_puts("### No HW ID - assuming PIP405"); + } + else { + bc=video_set_attr(VGA_ATTR_CLR_GRN); + for (e=s; *e; ++e) { + if (*e == ' ') + break; + } + for ( ; sbi_memsize/0x100000); + video_puts(buf); + /* flash size: */ + video_puts("FLASH: "); + if(switch_cs(0)==0) { + bc=video_set_attr(VGA_ATTR_CLR_GRN); + video_puts("(Flash boot)"); + video_set_attr(bc); + } + else { + bc=video_set_attr(VGA_ATTR_CLR_RED | VGA_ATTR_ITN); + video_puts("(Multi Purpose Socket boot)"); + video_set_attr(bc); + } + sprintf(buf," %lu MBytes\n",bd_ptr->bi_flashsize/0x100000); + video_puts(buf); +} + + + + + + diff --git a/board/mpl/pip405/pip405.h b/board/mpl/pip405/pip405.h new file mode 100644 index 0000000..7adfcef --- /dev/null +++ b/board/mpl/pip405/pip405.h @@ -0,0 +1,62 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * 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 + * + */ + /**************************************************************************** + * Global routines used for PIP405 + *****************************************************************************/ + +int switch_cs(unsigned char boot); + +extern int mem_test(unsigned long start, unsigned long ramsize,int mode); + +void print_pip405_info(void); + +void user_led0(unsigned char on); +void user_led1(unsigned char on); + +typedef struct { + char signature[4]; + char serial_name[17]; /* "PIP405_1000xxxxx" */ + char eth_addr[21]; /* "00:60:C2:08:00:00" */ +} backup_t; + +void get_backup_values(backup_t *buf); +void set_backup_values(int overwrite); + +#define PLD_BASE_ADDRESS CFG_ISA_IO_BASE_ADDRESS + 0x800 +#define PLD_PART_REG PLD_BASE_ADDRESS + 0 +#define PLD_VERS_REG PLD_BASE_ADDRESS + 1 +#define PLD_BOARD_CFG_REG PLD_BASE_ADDRESS + 2 +#define PLD_LED_USER_REG PLD_BASE_ADDRESS + 3 +#define PLD_SYS_MAN_REG PLD_BASE_ADDRESS + 4 +#define PLD_FLASH_COM_REG PLD_BASE_ADDRESS + 5 +#define PLD_CAN_REG PLD_BASE_ADDRESS + 6 +#define PLD_SER_PWR_REG PLD_BASE_ADDRESS + 7 +#define PLD_COM_PWR_REG PLD_BASE_ADDRESS + 8 +#define PLD_NIC_VGA_REG PLD_BASE_ADDRESS + 9 +#define PLD_SCSI_RST_REG PLD_BASE_ADDRESS + 0xA + +#define PIIX4_VENDOR_ID 0x8086 +#define PIIX4_IDE_DEV_ID 0x7111 + + diff --git a/board/mpl/pip405/ppcboot.lds b/board/mpl/pip405/ppcboot.lds new file mode 100644 index 0000000..c260b18 --- /dev/null +++ b/board/mpl/pip405/ppcboot.lds @@ -0,0 +1,144 @@ +/* + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.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 + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + .resetvec 0xFFFFFFFC : + { + *(.resetvec) + } = 0xffff + + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/ppc4xx/start.o (.text) + board/mpl/pip405/init.o (.text) + cpu/ppc4xx/kgdb.o (.text) + cpu/ppc4xx/traps.o (.text) + cpu/ppc4xx/interrupts.o (.text) + cpu/ppc4xx/serial.o (.text) + cpu/ppc4xx/cpu_init.o (.text) + cpu/ppc4xx/speed.o (.text) + cpu/ppc4xx/405gp_enet.o (.text) + common/dlmalloc.o (.text) + ppc/crc32.o (.text) + ppc/extable.o (.text) + ppc/zlib.o (.text) + +/* . = env_offset;*/ +/* common/environment.o(.text)*/ + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/mpl/pip405/ppcboot.lds.debug b/board/mpl/pip405/ppcboot.lds.debug new file mode 100644 index 0000000..b8ec990 --- /dev/null +++ b/board/mpl/pip405/ppcboot.lds.debug @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.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 + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + ppc/vsprintf.o (.text) + ppc/crc32.o (.text) + ppc/extable.o (.text) + + common/environment.o(.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} + diff --git a/common/Makefile b/common/Makefile index ffbda63..6c32caa 100644 --- a/common/Makefile +++ b/common/Makefile @@ -36,6 +36,7 @@ COBJS = board.o main.o command.o environment.o bedbug.o \ cmd_nvedit.o cmd_pcmcia.o \ cmd_reginfo.o cmd_scsi.o \ console.o devices.o dlmalloc.o \ + usb.o usb_storage.o usb_kbd.o cmd_usb.o \ flash.o hush.o kgdb.o \ lists.o miiphybb.o miiphyutil.o \ s_record.o diff --git a/common/board.c b/common/board.c index de3bf8d..f1603df 100644 --- a/common/board.c +++ b/common/board.c @@ -176,7 +176,6 @@ board_init_f (ulong bootflag) defined(CONFIG_LWMON) || \ defined(CONFIG_MPC8260ADS)|| \ defined(CONFIG_OCRTC) || \ - defined(CONFIG_PIP405) || \ defined(CONFIG_RPXSUPER) || \ defined(CONFIG_WALNUT405) || \ defined(CONFIG_W7O) @@ -761,9 +760,20 @@ void board_init_r (bd_t *bd, ulong dest_addr) #if (CONFIG_COMMANDS & CFG_CMD_SCSI) WATCHDOG_RESET(); + puts ("SCSI: "); scsi_init(); #endif +#ifdef CONFIG_LAST_STAGE_INIT + WATCHDOG_RESET(); + /* + * Some parts can be only initialized if all others (like + * Interrupts) are up and running (i.e. the PC-style ISA + * keyboard). + */ + last_stage_init (); +#endif + #if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) WATCHDOG_RESET(); bedbug_init(); diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index fd9146c..0b88e9d 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -53,7 +53,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #if !defined(CONFIG_CPCI405) && !defined(CONFIG_AR405) && \ - !defined(CONFIG_PIP405) && !defined(CONFIG_W7O) && \ + !defined(CONFIG_I2C405) && !defined(CONFIG_W7O) && \ !defined (CONFIG_WALNUT405) && !defined (CONFIG_ERIC) i2c_state_t state; @@ -71,7 +71,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) if (strncmp (argv[1], "res", 3) == 0) { printf ("I2C reset 50kHz ... "); #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) i2c_init (); #else @@ -90,7 +90,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) else printf ("I2C reset %dkHz ... ", speed/1000); #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) i2c_init (); #else @@ -118,7 +118,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) , i2c_addr, (ulong)data_addr, size); #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) #else @@ -127,7 +127,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) rc = i2c_receive (i2c_addr, size, data_addr); @@ -145,7 +145,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) } #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) #else @@ -170,7 +170,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) #else @@ -178,7 +178,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #endif #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) rc = i2c_send (i2c_addr, size, data_addr); @@ -193,7 +193,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) } #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) #else @@ -223,7 +223,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) i2c_addr, sec_addr, (ulong)data_addr, size); #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) #else @@ -231,7 +231,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #endif #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) rc = i2c_receive (i2c_addr, size, data_addr); @@ -248,7 +248,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) } #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) #else @@ -275,7 +275,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) i2c_addr, sec_addr, (ulong)data_addr, size); #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) #else @@ -283,7 +283,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #endif #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) rc = i2c_send (i2c_addr, size, data_addr); @@ -299,7 +299,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) } #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \ + defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) #else diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c index 93b393d..d46f3c0 100644 --- a/common/cmd_pcmcia.c +++ b/common/cmd_pcmcia.c @@ -307,7 +307,8 @@ static int check_ide_device (void) ident = p + 4; break; case CISTPL_FUNCID: - func_id = *p; + /* Fix for broken SanDisk which may have 0x80 bit set */ + func_id = *p & 0x7F; break; case CISTPL_FUNCE: if (n_features < MAX_FEATURES) diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 49a131a..267c6d8 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -101,7 +101,7 @@ void scsi_scan(int mode) ccb* pccb=(ccb *)&tempccb; if(mode==1) { - printf("SCSI: scanning bus for devices...\n"); + printf("scanning bus for devices...\n"); } for(i=0;i +#include + +#if (CONFIG_COMMANDS & CFG_CMD_USB) + +#include +#include + +#undef CMD_USB_DEBUG + +#ifdef CMD_USB_DEBUG +#define CMD_USB_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define CMD_USB_PRINTF(fmt,args...) +#endif +static int usb_stor_curr_dev=-1; /* current device */ + +/* somme display routines (info command) */ +char * usb_get_class_desc(unsigned char dclass) +{ + switch(dclass) { + case USB_CLASS_PER_INTERFACE: + return("See Interface"); + case USB_CLASS_AUDIO: + return("Audio"); + case USB_CLASS_COMM: + return("Communication"); + case USB_CLASS_HID: + return("Human Interface"); + case USB_CLASS_PRINTER: + return("Printer"); + case USB_CLASS_MASS_STORAGE: + return("Mass Storage"); + case USB_CLASS_HUB: + return("Hub"); + case USB_CLASS_DATA: + return("CDC Data"); + case USB_CLASS_VENDOR_SPEC: + return("Vendor specific"); + default : + return(""); + } +} + +void usb_display_class_sub(unsigned char dclass,unsigned char subclass,unsigned char proto) +{ + switch(dclass) { + case USB_CLASS_PER_INTERFACE: + printf("See Interface"); + break; + case USB_CLASS_HID: + printf("Human Interface, Subclass: "); + switch(subclass) { + case USB_SUB_HID_NONE: + printf("None"); + break; + case USB_SUB_HID_BOOT: + printf("Boot "); + switch(proto) { + case USB_PROT_HID_NONE: + printf("None"); + break; + case USB_PROT_HID_KEYBOARD: + printf("Keyboard"); + break; + case USB_PROT_HID_MOUSE: + printf("Mouse"); + break; + default: + printf("reserved"); + } + break; + default: + printf("reserved"); + } + break; + case USB_CLASS_MASS_STORAGE: + printf("Mass Storage, "); + switch(subclass) { + case US_SC_RBC: + printf("RBC "); + break; + case US_SC_8020: + printf("SFF-8020i (ATAPI)"); + break; + case US_SC_QIC: + printf("QIC-157 (Tape)"); + break; + case US_SC_UFI: + printf("UFI"); + break; + case US_SC_8070: + printf("SFF-8070"); + break; + case US_SC_SCSI: + printf("Transp. SCSI"); + break; + default: + printf("reserved"); + break; + } + printf(", "); + switch(proto) { + case US_PR_CB: + printf("Command/Bulk"); + break; + case US_PR_CBI: + printf("Command/Bulk/Int"); + break; + case US_PR_BULK: + printf("Bulk only"); + break; + default: + printf("reserved"); + } + break; + default: + printf("%s",usb_get_class_desc(dclass)); + } +} + +void usb_display_string(struct usb_device *dev,int index) +{ + char buffer[256]; + if(index!=0) { + if(usb_string(dev,index,&buffer[0],256)>0); + printf("String: \"%s\"",buffer); + } +} + +void usb_display_desc(struct usb_device *dev) +{ + if(dev->descriptor.bDescriptorType==USB_DT_DEVICE) { + printf("%d: %s, USB Revision %x.%x\n",dev->devnum,usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass), + (dev->descriptor.bcdUSB>>8) & 0xff,dev->descriptor.bcdUSB & 0xff); + if(strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial)) + printf(" - %s %s %s\n",dev->mf,dev->prod,dev->serial); + if(dev->descriptor.bDeviceClass) { + printf(" - Class: "); + usb_display_class_sub(dev->descriptor.bDeviceClass,dev->descriptor.bDeviceSubClass,dev->descriptor.bDeviceProtocol); + printf("\n"); + } + else { + printf(" - Class: (from Interface) %s\n",usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass)); + } + printf(" - PacketSize: %d Configurations: %d\n",dev->descriptor.bMaxPacketSize0,dev->descriptor.bNumConfigurations); + printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n",dev->descriptor.idVendor,dev->descriptor.idProduct,(dev->descriptor.bcdDevice>>8) & 0xff,dev->descriptor.bcdDevice & 0xff); + } + +} + +void usb_display_conf_desc(struct usb_config_descriptor *config,struct usb_device *dev) +{ + printf(" Configuration: %d\n",config->bConfigurationValue); + printf(" - Interfaces: %d %s%s%dmA\n",config->bNumInterfaces,(config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ", + (config->bmAttributes & 0x20) ? "Remote Wakeup " : "",config->MaxPower*2); + if(config->iConfiguration) { + printf(" - "); + usb_display_string(dev,config->iConfiguration); + printf("\n"); + } +} + +void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,struct usb_device *dev) +{ + printf(" Interface: %d\n",ifdesc->bInterfaceNumber); + printf(" - Alternate Settings %d, Endpoints: %d\n",ifdesc->bAlternateSetting,ifdesc->bNumEndpoints); + printf(" - Class "); + usb_display_class_sub(ifdesc->bInterfaceClass,ifdesc->bInterfaceSubClass,ifdesc->bInterfaceProtocol); + printf("\n"); + if(ifdesc->iInterface) { + printf(" - "); + usb_display_string(dev,ifdesc->iInterface); + printf("\n"); + } +} + +void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc) +{ + printf(" - Endpoint %d %s ",epdesc->bEndpointAddress & 0xf,(epdesc->bEndpointAddress & 0x80) ? "In" : "Out"); + switch((epdesc->bmAttributes & 0x03)) + { + case 0: printf("Control"); break; + case 1: printf("Isochronous"); break; + case 2: printf("Bulk"); break; + case 3: printf("Interrupt"); break; + } + printf(" MaxPacket %d",epdesc->wMaxPacketSize); + if((epdesc->bmAttributes & 0x03)==0x3) + printf(" Interval %dms",epdesc->bInterval); + printf("\n"); +} + +/* main routine to diasplay the configs, interfaces and endpoints */ +void usb_display_config(struct usb_device *dev) +{ + struct usb_config_descriptor *config; + struct usb_interface_descriptor *ifdesc; + struct usb_endpoint_descriptor *epdesc; + int i,ii; + + config= &dev->config; + usb_display_conf_desc(config,dev); + for(i=0;ino_of_if;i++) { + ifdesc= &config->if_desc[i]; + usb_display_if_desc(ifdesc,dev); + for(ii=0;iino_of_ep;ii++) { + epdesc= &ifdesc->ep_desc[ii]; + usb_display_ep_desc(epdesc); + } + } + printf("\n"); +} + +/* shows the device tree recursively */ +void usb_show_tree_graph(struct usb_device *dev,char *pre) +{ + int i,index; + int has_child,last_child,port; + + index=strlen(pre); + printf(" %s",pre); + /* check if the device has connected children */ + has_child=0; + for(i=0;imaxchild;i++) { + if(dev->children[i]!=NULL) + has_child=1; + } + /* check if we are the last one */ + last_child=1; + if(dev->parent!=NULL) { + for(i=0;iparent->maxchild;i++) { + /* search for children */ + if(dev->parent->children[i]==dev) { + /* found our pointer, see if we have a little sister */ + port=i; + while(i++parent->maxchild) { + if(dev->parent->children[i]!=NULL) { + /* found a sister */ + last_child=0; + break; + } /* if */ + } /* while */ + } /* device found */ + } /* for all children of the parent */ + printf("\b+-"); + /* correct last child */ + if(last_child) { + pre[index-1]=' '; + } + } /* if not root hub */ + else + printf(" "); + printf("%d ",dev->devnum); + pre[index++]=' '; + pre[index++]= has_child ? '|' : ' '; + pre[index]=0; + printf(" %s (%s, %dmA)\n",usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass), + dev->slow ? "1.5MBit/s" : "12MBit/s",dev->config.MaxPower * 2); + if(strlen(dev->mf) || + strlen(dev->prod) || + strlen(dev->serial)) + printf(" %s %s %s %s\n",pre,dev->mf,dev->prod,dev->serial); + printf(" %s\n",pre); + if(dev->maxchild>0) { + for(i=0;imaxchild;i++) { + if(dev->children[i]!=NULL) { + usb_show_tree_graph(dev->children[i],pre); + pre[index]=0; + } + } + } +} + +/* main routine for the tree command */ +void usb_show_tree(struct usb_device *dev) +{ + char preamble[32]; + + memset(preamble,0,32); + usb_show_tree_graph(dev,&preamble[0]); +} + + + +/****************************************************************************** + * usb boot command intepreter. Derived from diskboot + */ +#ifdef CONFIG_USB_STORAGE +int do_usbboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + char *boot_device = NULL; + char *ep; + int dev, part,rcode; + ulong cnt; + ulong addr; + disk_partition_t info; + image_header_t *hdr; + block_dev_desc_t *stor_dev; + + + switch (argc) { + case 1: + addr = CFG_LOAD_ADDR; + boot_device = getenv ("bootdevice"); + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = getenv ("bootdevice"); + break; + case 3: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + break; + default: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (!boot_device) { + puts ("\n** No boot device **\n"); + return 1; + } + + dev = simple_strtoul(boot_device, &ep, 16); + stor_dev=usb_stor_get_dev(dev); + if (stor_dev->type == DEV_TYPE_UNKNOWN) { + printf ("\n** Device %d not available\n", dev); + return 1; + } + if(stor_dev->block_read==NULL) { + printf("storage device not initialized. Use usb scan\n"); + return 1; + } + if (*ep) { + if (*ep != ':') { + puts ("\n** Invalid boot device, use `dev[:part]' **\n"); + return 1; + } + part = simple_strtoul(++ep, NULL, 16); + } + + if (get_partition_info (stor_dev, part, &info)) { + /* try to boot raw .... */ + strncpy(&info.type[0], BOOT_PART_TYPE, sizeof(BOOT_PART_TYPE)); + strncpy(&info.name[0], "Raw", 4); + info.start=0; + info.blksz=0x200; + info.size=2880; + printf("error reading partinfo...try to boot raw\n"); + } + if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) { + printf ("\n** Invalid partition type \"%.32s\"" + " (expect \"" BOOT_PART_TYPE "\")\n", + info.type); + return 1; + } + printf ("\nLoading from USB device %d, partition %d: " + "Name: %.32s Type: %.32s\n", + dev, part, info.name, info.type); + + printf ("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", + info.start, info.size, info.blksz); + + if (stor_dev->block_read(dev, info.start, 1, (ulong *)addr) != 1) { + printf ("** Read error on %d:%d\n", dev, part); + return 1; + } + + hdr = (image_header_t *)addr; + + if (hdr->ih_magic == IH_MAGIC) { + print_image_hdr (hdr); + cnt = (hdr->ih_size + sizeof(image_header_t)); + cnt += info.blksz - 1; + cnt /= info.blksz; + cnt -= 1; + } else { + printf("\n** Bad Magic Number **\n"); + return 1; + } + + if (stor_dev->block_read (dev, info.start+1, cnt, + (ulong *)(addr+info.blksz)) != cnt) { + printf ("\n** Read error on %d:%d\n", dev, part); + return 1; + } + /* Loading ok, update default load address */ + load_addr = addr; + /* Check if we should attempt an auto-start */ + if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { + char *local_args[2]; + extern int do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]); + local_args[0] = argv[0]; + local_args[1] = NULL; + printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + rcode=do_bootm (cmdtp, bd, 0, 1, local_args); + return rcode; + } + return 0; +} +#endif /* CONFIG_USB_STORAGE */ + + + + +/********************************************************************************* + * usb command intepreter + */ +int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + + int i; + struct usb_device *dev; + block_dev_desc_t *stor_dev; + + if ((strncmp(argv[1],"reset",5) == 0) || + (strncmp(argv[1],"start",5) == 0)){ + usb_stop(); + printf("(Re)start USB...\n"); + usb_init(); + return 0; + } + if (strncmp(argv[1],"stop",4) == 0) { +#ifdef CONFIG_USB_KEYBOARD + if(argc==2) { + if(usb_kbd_deregister()!=0) { + printf("USB not stopped: usbkbd still using USB\n"); + return 1; + } + } + else { /* forced stop, switch console in to serial */ + console_assign(stdin,"serial"); + usb_kbd_deregister(); + } +#endif + printf("stopping USB..\n"); + usb_stop(); + return 0; + } + if (strncmp(argv[1],"tree",4) == 0) { + printf("\nDevice Tree:\n"); + usb_show_tree(usb_get_dev_index(0)); + return 0; + } + if (strncmp(argv[1],"inf",3) == 0) { + int d; + if(argc==2) { + for(d=0;ddevnum==i) + break; + } + if(dev==NULL) { + printf("*** NO Device avaiable ***\n"); + return 0; + } + else { + usb_display_desc(dev); + usb_display_config(dev); + } + } + return 0; + } +#ifdef CONFIG_USB_STORAGE + if (strncmp(argv[1],"scan",4) == 0) { + printf("Scan for storage device:\n"); + usb_stor_curr_dev=usb_stor_scan(1); + if(usb_stor_curr_dev==-1) { + printf("No device found. Not initialized?\n"); + return 1; + } + return 0; + } + if (strncmp(argv[1],"part",4) == 0) { + int devno, ok; + for (ok=0, devno=0; devnotype!=DEV_TYPE_UNKNOWN) { + ok++; + if (devno) + printf("\n"); + printf("print_part of %x\n",devno); + print_part(stor_dev); + } + } + if (!ok) { + printf("\nno USB devices available\n"); + return 1; + } + return 0; + } + if (strcmp(argv[1],"read") == 0) { + if(usb_stor_curr_dev<0) { + printf("no current device selected\n"); + return 1; + } + if(argc==5) { + unsigned long addr = simple_strtoul(argv[2], NULL, 16); + unsigned long blk = simple_strtoul(argv[3], NULL, 16); + unsigned long cnt = simple_strtoul(argv[4], NULL, 16); + unsigned long n; + printf ("\nUSB read: device %d block # %ld, count %ld ... ", + usb_stor_curr_dev, blk, cnt); + stor_dev=usb_stor_get_dev(usb_stor_curr_dev); + n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt, (ulong *)addr); + printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); + if(n==cnt) + return 0; + return 1; + } + } + if (strcmp(argv[1],"dev") == 0) { + if(argc==3) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + printf ("\nUSB device %d: ", dev); + if (dev >= USB_MAX_STOR_DEV) { + printf("unknown device\n"); + return 1; + } + printf ("\n Device %d: ", dev); + stor_dev=usb_stor_get_dev(dev); + dev_print(stor_dev); + if(stor_dev->type == DEV_TYPE_UNKNOWN) { + return 1; + } + usb_stor_curr_dev = dev; + printf("... is now current device\n"); + return 0; + } + else { + printf ("\nUSB device %d: ", usb_stor_curr_dev); + stor_dev=usb_stor_get_dev(usb_stor_curr_dev); + dev_print(stor_dev); + if(stor_dev->type == DEV_TYPE_UNKNOWN) { + return 1; + } + return 0; + } + return 0; + } +#endif /* CONFIG_USB_STORAGE */ + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} + + +#endif /* (CONFIG_COMMANDS & CFG_CMD_USB) */ + + diff --git a/common/command.c b/common/command.c index 87001f3..e6f5ee4 100644 --- a/common/command.c +++ b/common/command.c @@ -49,6 +49,7 @@ #include #include /* Floppy support */ +#include /* USB support */ #include #include #include /* 4xx DCR register access */ @@ -288,6 +289,8 @@ cmd_tbl_t cmd_tbl[] = { CMD_TBL_STACK CMD_TBL_STEP CMD_TBL_TFTPB + CMD_TBL_USBBOOT + CMD_TBL_USB CMD_TBL_VERS CMD_TBL_BSP CMD_TBL_QUES diff --git a/common/devices.c b/common/devices.c index 0a4a2e8..89f3b79 100644 --- a/common/devices.c +++ b/common/devices.c @@ -21,6 +21,7 @@ * MA 02111-1307 USA */ +#include #include #include #include @@ -74,6 +75,49 @@ int device_register (device_t * dev) return 0; } +/* deregister the device "devname". + * returns 0 if success, -1 if device is assigned and 1 if devname not found + */ +#ifdef CFG_DEVICE_DEREGISTER +int device_deregister(char *devname) +{ + int i,l,dev_index; + device_t *dev; + char temp_names[3][8]; + + dev_index=-1; + for (i=1; i<=ListNumItems(devlist); i++) { + dev = ListGetPtrToItem (devlist, i); + if(strcmp(dev->name,devname)==0) { + dev_index=i; + break; + } + } + if(dev_index<0) /* device not found */ + return 0; + /* get stdio devices (ListRemoveItem changes the dev list) */ + for (l=0 ; l< MAX_FILES; l++) { + if (stdio_devices[l] == dev) { + /* Device is assigned -> report error */ + return -1; + } + memcpy (&temp_names[l][0], + stdio_devices[l]->name, + sizeof(stdio_devices[l]->name)); + } + ListRemoveItem(devlist,NULL,dev_index); + /* reassign Device list */ + for (i=1; i<=ListNumItems(devlist); i++) { + dev = ListGetPtrToItem (devlist, i); + for (l=0 ; l< MAX_FILES; l++) { + if(strcmp(dev->name,temp_names[l])==0) { + stdio_devices[l] = dev; + } + } + } + return 0; +} +#endif /* CFG_DEVICE_DEREGISTER */ int devices_init (bd_t *bd, ulong relocation_offset) { @@ -103,9 +147,6 @@ int devices_init (bd_t *bd, ulong relocation_offset) #endif #ifdef CONFIG_WL_4PPM_KEYBOARD drv_wlkbd_init (); -#endif -#ifdef CONFIG_ISA_KEYBOARD - drv_isa_kbd_init (); #endif drv_system_init (); diff --git a/common/lists.c b/common/lists.c index e650bee..ee40292 100644 --- a/common/lists.c +++ b/common/lists.c @@ -6,596 +6,627 @@ #define MIN(a,b) (((a)<(b)) ? (a) : (b)) #define CAT4CHARS(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d) -#define kDefaultAllocationPercentIncrease 10 /* increase list size by 10% every time it is full */ -#define kDefaultAllocationminNumItemsIncrease 4 /* always increase list size by 4 items when it is full */ +/* increase list size by 10% every time it is full */ +#define kDefaultAllocationPercentIncrease 10 - /* how many items to expand the list by when it becomes full = current listSize (in items) + (hiword percent of list size) + loword */ -#define NUMITEMSPERALLOC(list) MAX(((*list)->listSize * ((*list)->percentIncrease + 100)) / 100 , (*list)->minNumItemsIncrease) +/* always increase list size by 4 items when it is full */ +#define kDefaultAllocationminNumItemsIncrease 4 -#define ITEMPTR(list, item) &(((char *)&(*list)->itemList)[ (*(list))->itemSize * (item)]) +/* + * how many items to expand the list by when it becomes full + * = current listSize (in items) + (hiword percent of list size) + loword + */ +#define NUMITEMSPERALLOC(list) MAX(((*list)->listSize * \ + ((*list)->percentIncrease + 100)) / 100, \ + (*list)->minNumItemsIncrease ) -#define LIST_SIGNATURE CAT4CHARS('L', 'I', 'S', 'T'); +#define ITEMPTR(list,item) &(((char *)&(*list)->itemList)[(*(list))->itemSize * (item)]) + +#define LIST_SIGNATURE CAT4CHARS('L', 'I', 'S', 'T'); #define calloc(size,num) malloc(size*num) /********************************************************************/ -Handle NewHandle(unsigned int numBytes) +Handle NewHandle (unsigned int numBytes) { - void *memPtr; - HandleRecord *hanPtr; + void *memPtr; + HandleRecord *hanPtr; - memPtr = calloc(numBytes, 1); - hanPtr = (HandleRecord*)calloc(sizeof(HandleRecord), 1); - if (hanPtr && (memPtr || numBytes == 0)) - { - hanPtr->ptr = memPtr; - hanPtr->size = numBytes; - return (Handle)hanPtr; - } - else - { - free(memPtr); - free(hanPtr); - return NULL; - } + memPtr = calloc (numBytes, 1); + hanPtr = (HandleRecord *) calloc (sizeof (HandleRecord), 1); + if (hanPtr && (memPtr || numBytes == 0)) { + hanPtr->ptr = memPtr; + hanPtr->size = numBytes; + return (Handle) hanPtr; + } else { + free (memPtr); + free (hanPtr); + return NULL; + } } - /********************************************************************/ -void DisposeHandle(Handle handle) +void DisposeHandle (Handle handle) { - if (handle) - { - free(*handle); - free((void *)handle); - } + if (handle) { + free (*handle); + free ((void *) handle); + } } - /********************************************************************/ -unsigned int GetHandleSize(Handle handle) +unsigned int GetHandleSize (Handle handle) { - return ((HandleRecord *)handle)->size; + return ((HandleRecord *) handle)->size; } - /********************************************************************/ -int SetHandleSize(Handle handle, unsigned int newSize) +int SetHandleSize (Handle handle, unsigned int newSize) { - HandleRecord *hanRecPtr = (HandleRecord *)handle; - void *newPtr, *oldPtr; - unsigned int oldSize; + HandleRecord *hanRecPtr = (HandleRecord *) handle; + void *newPtr, *oldPtr; + unsigned int oldSize; - oldPtr = hanRecPtr->ptr; - oldSize = hanRecPtr->size; + oldPtr = hanRecPtr->ptr; + oldSize = hanRecPtr->size; - if (oldSize == newSize) - return 1; + if (oldSize == newSize) + return 1; - if (oldPtr == NULL) - { - newPtr = malloc(newSize); - } - else - { - newPtr = realloc(oldPtr, newSize); - } - if (newPtr || (newSize == 0)) - { - hanRecPtr->ptr = newPtr; - hanRecPtr->size = newSize; - if (newSize > oldSize) - memset ((char *)newPtr+oldSize, 0, newSize-oldSize); - return 1; - } - else - return 0; + if (oldPtr == NULL) { + newPtr = malloc (newSize); + } else { + newPtr = realloc (oldPtr, newSize); + } + if (newPtr || (newSize == 0)) { + hanRecPtr->ptr = newPtr; + hanRecPtr->size = newSize; + if (newSize > oldSize) + memset ((char *) newPtr + oldSize, 0, newSize - oldSize); + return 1; + } else + return 0; } #ifdef CFG_ALL_LIST_FUNCTIONS - /* Used to compare list elements by their raw data contents */ -static int ListMemBlockCmp(void *a, void *b, int size) +/* Used to compare list elements by their raw data contents */ +static int ListMemBlockCmp (void *a, void *b, int size) { - return memcmp(a, b, size); + return memcmp (a, b, size); } - /***************************************************************************/ - /* Binary search numElements of size elementSize in array for a match - to the. item. Return the index of the element that matches (0 - numElements - 1). - If no match is found return the -i-1 where i is the index (0 - numElements) - where the item should be placed. (*theCmp)(a,b) should return <0 if a0 if a>b. - - This function is like the C-Library function bsearch() except that this - function returns the index where the item should be placed if it is not - found. - */ -int BinSearch(void *array, int numElements, int elementSize, void *itemPtr, CompareFunction compareFunction) -{ - int low, high, mid, cmp; - void *arrayItemPtr; - - for(low=0, high= numElements-1, mid=0, cmp= -1; low <= high; ) - { - mid = (low + high) >> 1; - - arrayItemPtr = (void *) (((char *)array) + (mid*elementSize)); - cmp = compareFunction ? compareFunction(itemPtr, arrayItemPtr) - : ListMemBlockCmp(itemPtr, arrayItemPtr, elementSize); - if (cmp == 0) - return mid; - else - if (cmp < 0) - high= mid - 1; - else - low= mid + 1; - } - if (cmp > 0) - mid++; - - return -mid-1; +/* + * Binary search numElements of size elementSize in array for a match + * to the. item. Return the index of the element that matches + * (0 - numElements - 1). If no match is found return the -i-1 where + * i is the index (0 - numElements) where the item should be placed. + * (*theCmp)(a,b) should return <0 if a0 if a>b. + * + * This function is like the C-Library function bsearch() except that + * this function returns the index where the item should be placed if + * it is not found. + */ +int BinSearch ( void *array, int numElements, int elementSize, + void *itemPtr, CompareFunction compareFunction) +{ + int low, high, mid, cmp; + void *arrayItemPtr; + + for (low = 0, high = numElements - 1, mid = 0, cmp = -1; low <= high;) { + mid = (low + high) >> 1; + + arrayItemPtr = (void *) (((char *) array) + (mid * elementSize)); + cmp = compareFunction + ? compareFunction (itemPtr, arrayItemPtr) + : ListMemBlockCmp (itemPtr, arrayItemPtr, elementSize); + if (cmp == 0) { + return mid; + } else if (cmp < 0) { + high = mid - 1; + } else { + low = mid + 1; + } + } + if (cmp > 0) + mid++; + + return -mid - 1; } #endif /* CFG_ALL_LIST_FUNCTIONS */ /*******************************************************************************/ - /* BEGIN PATCH to 4.0.1 - jag 8-29-96 */ - /* If numNewItems == 0 then expand the list by the number of items - indicated by its allocation policy. - If numNewItems > 0 then expand the list by exactly the number of - items indicated. - If numNewItems < 0 then expand the list by the absolute value of - numNewItems plus the number of items indicated by its allocation - policy. - Returns 1 for success, 0 if out of memory - */ -static int ExpandListSpace (list_t list, int numNewItems) -{ - if (numNewItems == 0) - numNewItems = NUMITEMSPERALLOC(list); - else - if (numNewItems < 0) - numNewItems = (-numNewItems) + NUMITEMSPERALLOC(list); - - if (SetHandleSize ((Handle)list, - sizeof(ListStruct) + - ((*list)->listSize + numNewItems) * (*list)->itemSize)) - { - (*list)->listSize += numNewItems; - return 1; - } - else - { - return 0; - } +/* + * If numNewItems == 0 then expand the list by the number of items + * indicated by its allocation policy. + * If numNewItems > 0 then expand the list by exactly the number of + * items indicated. + * If numNewItems < 0 then expand the list by the absolute value of + * numNewItems plus the number of items indicated by its allocation + * policy. + * Returns 1 for success, 0 if out of memory +*/ +static int ExpandListSpace (list_t list, int numNewItems) +{ + if (numNewItems == 0) { + numNewItems = NUMITEMSPERALLOC (list); + } else if (numNewItems < 0) { + numNewItems = (-numNewItems) + NUMITEMSPERALLOC (list); + } + + if (SetHandleSize ((Handle) list, + sizeof (ListStruct) + + ((*list)->listSize + + numNewItems) * (*list)->itemSize)) { + (*list)->listSize += numNewItems; + return 1; + } else { + return 0; + } } /*******************************/ #ifdef CFG_ALL_LIST_FUNCTIONS - /* This function reallocate the list, minus any currently unused portion of its allotted memory. */ -void ListCompact (list_t list) +/* + * This function reallocate the list, minus any currently unused + * portion of its allotted memory. + */ +void ListCompact (list_t list) { - if (!SetHandleSize ((Handle)list, - sizeof (ListStruct) + (*list)->numItems * (*list)->itemSize)) - return; + if (!SetHandleSize ((Handle) list, + sizeof (ListStruct) + + (*list)->numItems * (*list)->itemSize)) { + return; + } - (*list)->listSize = (*list)->numItems; + (*list)->listSize = (*list)->numItems; } #endif /* CFG_ALL_LIST_FUNCTIONS */ /*******************************/ -list_t ListCreate (int elementSize) +list_t ListCreate (int elementSize) { - list_t list; + list_t list; - list = (list_t)(NewHandle (sizeof(ListStruct))); /* create empty list */ - if (list) - { - (*list)->signature = LIST_SIGNATURE; - (*list)->numItems = 0; - (*list)->listSize = 0; - (*list)->itemSize = elementSize; - (*list)->percentIncrease = kDefaultAllocationPercentIncrease; - (*list)->minNumItemsIncrease = kDefaultAllocationminNumItemsIncrease; - } + list = (list_t) (NewHandle (sizeof (ListStruct))); /* create empty list */ + if (list) { + (*list)->signature = LIST_SIGNATURE; + (*list)->numItems = 0; + (*list)->listSize = 0; + (*list)->itemSize = elementSize; + (*list)->percentIncrease = kDefaultAllocationPercentIncrease; + (*list)->minNumItemsIncrease = + kDefaultAllocationminNumItemsIncrease; + } - return list; + return list; } /*******************************/ -void ListSetAllocationPolicy (list_t list, int minItemsPerAlloc, int percentIncreasePerAlloc) +void ListSetAllocationPolicy (list_t list, int minItemsPerAlloc, + int percentIncreasePerAlloc) { - - (*list)->percentIncrease = percentIncreasePerAlloc; - (*list)->minNumItemsIncrease = minItemsPerAlloc; + (*list)->percentIncrease = percentIncreasePerAlloc; + (*list)->minNumItemsIncrease = minItemsPerAlloc; } /*******************************/ -void ListDispose (list_t list) +void ListDispose (list_t list) { - DisposeHandle ((Handle)list); + DisposeHandle ((Handle) list); } - /*******************************/ #ifdef CFG_ALL_LIST_FUNCTIONS -void ListDisposePtrList(list_t list) +void ListDisposePtrList (list_t list) { - int index; - int numItems; + int index; + int numItems; - if (list) - { - numItems = ListNumItems(list); + if (list) { + numItems = ListNumItems (list); - for (index = 1; index <= numItems; index++) - free(*(void **)ListGetPtrToItem(list, index)); + for (index = 1; index <= numItems; index++) + free (*(void **) ListGetPtrToItem (list, index)); - ListDispose(list); - } + ListDispose (list); + } } /*******************************/ -void ListClear (list_t list) /* keeps memory, resets the number of items to 0 */ +/* + * keeps memory, resets the number of items to 0 + */ +void ListClear (list_t list) { - if (!list) - return; - (*list)->numItems = 0; + if (!list) + return; + (*list)->numItems = 0; } /*******************************/ -list_t ListCopy (list_t originalList) /* copy is only as large as necessary */ +/* + * copy is only as large as necessary + */ +list_t ListCopy (list_t originalList) { - list_t tempList = NULL; - int numItems; + list_t tempList = NULL; + int numItems; - if (!originalList) - return NULL; + if (!originalList) + return NULL; - tempList = ListCreate ((*originalList)->itemSize); - if (tempList) { - numItems = ListNumItems (originalList); + tempList = ListCreate ((*originalList)->itemSize); + if (tempList) { + numItems = ListNumItems (originalList); - if (!SetHandleSize ((Handle)tempList, - sizeof (ListStruct) + numItems * (*tempList)->itemSize)) { - ListDispose (tempList); - return NULL; - } + if (!SetHandleSize ((Handle) tempList, + sizeof (ListStruct) + + numItems * (*tempList)->itemSize)) { + ListDispose (tempList); + return NULL; + } - (*tempList)->numItems = (*originalList)->numItems; - (*tempList)->listSize = (*originalList)->numItems; - (*tempList)->itemSize = (*originalList)->itemSize; - (*tempList)->percentIncrease = (*originalList)->percentIncrease; - (*tempList)->minNumItemsIncrease = (*originalList)->minNumItemsIncrease; + (*tempList)->numItems = (*originalList)->numItems; + (*tempList)->listSize = (*originalList)->numItems; + (*tempList)->itemSize = (*originalList)->itemSize; + (*tempList)->percentIncrease = (*originalList)->percentIncrease; + (*tempList)->minNumItemsIncrease = + (*originalList)->minNumItemsIncrease; - memcpy (ITEMPTR(tempList,0), ITEMPTR(originalList,0), - numItems * (*tempList)->itemSize); - } + memcpy (ITEMPTR (tempList, 0), ITEMPTR (originalList, 0), + numItems * (*tempList)->itemSize); + } - return tempList; + return tempList; } /********************************/ -int ListAppend (list_t list1, list_t list2) /* list1 = list1 + list2 */ +/* + * list1 = list1 + list2 + */ +int ListAppend (list_t list1, list_t list2) { - int numItemsL1, numItemsL2; + int numItemsL1, numItemsL2; - if (!list2) - return 1; + if (!list2) + return 1; - if (!list1) - return 0; - if ((*list1)->itemSize != (*list2)->itemSize) - return 0; + if (!list1) + return 0; + if ((*list1)->itemSize != (*list2)->itemSize) + return 0; - numItemsL1 = ListNumItems (list1); - numItemsL2 = ListNumItems (list2); + numItemsL1 = ListNumItems (list1); + numItemsL2 = ListNumItems (list2); - if (numItemsL2 == 0) - return 1; + if (numItemsL2 == 0) + return 1; - if (!SetHandleSize ((Handle)list1, - sizeof (ListStruct) + (numItemsL1 + numItemsL2) * (*list1)->itemSize)) - return 0; + if (!SetHandleSize ((Handle) list1, + sizeof (ListStruct) + (numItemsL1 + numItemsL2) * + (*list1)->itemSize)) { + return 0; + } - (*list1)->numItems = numItemsL1 + numItemsL2; - (*list1)->listSize = numItemsL1 + numItemsL2; + (*list1)->numItems = numItemsL1 + numItemsL2; + (*list1)->listSize = numItemsL1 + numItemsL2; - memmove (ITEMPTR(list1,numItemsL1), ITEMPTR(list2,0), - numItemsL2 * (*list2)->itemSize); + memmove (ITEMPTR (list1, numItemsL1), + ITEMPTR (list2, 0), + numItemsL2 * (*list2)->itemSize); - return 1; + return 1; } #endif /* CFG_ALL_LIST_FUNCTIONS */ /*******************************/ - /* returns 1 if the item is inserted, returns 0 if out of memory or - bad arguments were passed. - */ -int ListInsertItem (list_t list, void *ptrToItem, int itemPosition) +/* + * returns 1 if the item is inserted, returns 0 if out of memory or + * bad arguments were passed. + */ +int ListInsertItem (list_t list, void *ptrToItem, int itemPosition) { - return ListInsertItems (list, ptrToItem, itemPosition, 1); + return ListInsertItems (list, ptrToItem, itemPosition, 1); } /*******************************/ -int ListInsertItems (list_t list, void *ptrToItems, int firstItemPosition, int numItemsToInsert) -{ - int numItems = (*list)->numItems; - - if (firstItemPosition == numItems + 1) - firstItemPosition = LIST_END; - else - if (firstItemPosition > numItems) - return 0; - - if ((*list)->numItems >= (*list)->listSize) - { - if (!ExpandListSpace (list, -numItemsToInsert)) /* PATCH to 4.0.1 - jag 8-29-96 */ - return 0; - } - - if (firstItemPosition == LIST_START) - { - if (numItems == 0) - firstItemPosition = LIST_END; /* special case for empty list */ - else - firstItemPosition = 1; - } - - if (firstItemPosition == LIST_END) /* add at the end of the list */ - { - if (ptrToItems) - memcpy (ITEMPTR(list, numItems), ptrToItems, (*list)->itemSize * numItemsToInsert); - else - memset (ITEMPTR(list, numItems), 0, - (*list)->itemSize * numItemsToInsert); - - (*list)->numItems += numItemsToInsert; - } - else - { /* move part of list up to make room for new item */ - memmove (ITEMPTR(list,firstItemPosition-1+numItemsToInsert), - ITEMPTR(list,firstItemPosition-1), - (numItems + 1 - firstItemPosition) * (*list)->itemSize); - - if (ptrToItems) - memmove (ITEMPTR(list,firstItemPosition-1), ptrToItems, - (*list)->itemSize * numItemsToInsert); - else - memset (ITEMPTR(list,firstItemPosition-1), 0, - (*list)->itemSize * numItemsToInsert); - - (*list)->numItems += numItemsToInsert; - } - - return 1; +int ListInsertItems (list_t list, void *ptrToItems, int firstItemPosition, + int numItemsToInsert) +{ + int numItems = (*list)->numItems; + + if (firstItemPosition == numItems + 1) + firstItemPosition = LIST_END; + else if (firstItemPosition > numItems) + return 0; + + if ((*list)->numItems >= (*list)->listSize) { + if (!ExpandListSpace (list, -numItemsToInsert)) + return 0; + } + + if (firstItemPosition == LIST_START) { + if (numItems == 0) { + /* special case for empty list */ + firstItemPosition = LIST_END; + } else { + firstItemPosition = 1; + } + } + + if (firstItemPosition == LIST_END) { /* add at the end of the list */ + if (ptrToItems) + memcpy (ITEMPTR (list, numItems), ptrToItems, + (*list)->itemSize * numItemsToInsert); + else + memset (ITEMPTR (list, numItems), 0, + (*list)->itemSize * numItemsToInsert); + + (*list)->numItems += numItemsToInsert; + } else { /* move part of list up to make room for new item */ + memmove (ITEMPTR (list, firstItemPosition - 1 + numItemsToInsert), + ITEMPTR (list, firstItemPosition - 1), + (numItems + 1 - firstItemPosition) * (*list)->itemSize); + + if (ptrToItems) + memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems, + (*list)->itemSize * numItemsToInsert); + else + memset (ITEMPTR (list, firstItemPosition - 1), 0, + (*list)->itemSize * numItemsToInsert); + + (*list)->numItems += numItemsToInsert; + } + + return 1; } -#ifdef CFG_ALL_LIST_FUNCTIONS +#ifdef CFG_ALL_LIST_FUNCTIONS /*******************************/ -int ListEqual (list_t list1, list_t list2) +int ListEqual (list_t list1, list_t list2) { - if (list1 == list2) - return 1; + if (list1 == list2) + return 1; - if (list1 == NULL || list2 == NULL) - return 0; + if (list1 == NULL || list2 == NULL) + return 0; - if ((*list1)->itemSize == (*list1)->itemSize) - if ((*list1)->numItems == (*list2)->numItems) - return (memcmp (ITEMPTR(list1,0), ITEMPTR(list2,0), - (*list1)->itemSize * (*list1)->numItems) == 0); + if ((*list1)->itemSize == (*list1)->itemSize) { + if ((*list1)->numItems == (*list2)->numItems) { + return (memcmp (ITEMPTR (list1, 0), ITEMPTR (list2, 0), + (*list1)->itemSize * (*list1)->numItems) == 0); + } + } - return 0; + return 0; } /*******************************/ - /* The item pointed to by ptrToItem is copied over the current item at itemPosition */ -void ListReplaceItem (list_t list, void *ptrToItem, int itemPosition) +/* + * The item pointed to by ptrToItem is copied over the current item + * at itemPosition + */ +void ListReplaceItem (list_t list, void *ptrToItem, int itemPosition) { - ListReplaceItems (list, ptrToItem, itemPosition, 1); + ListReplaceItems (list, ptrToItem, itemPosition, 1); } /*******************************/ - /* The item pointed to by ptrToItems is copied over the current item at itemPosition */ -void ListReplaceItems (list_t list, void *ptrToItems, int firstItemPosition, int numItemsToReplace) +/* + * The item pointed to by ptrToItems is copied over the current item + * at itemPosition + */ +void ListReplaceItems ( list_t list, void *ptrToItems, + int firstItemPosition, int numItemsToReplace) { - if (firstItemPosition == LIST_END) - firstItemPosition = (*list)->numItems; - else - if (firstItemPosition == LIST_START) - firstItemPosition = 1; + if (firstItemPosition == LIST_END) + firstItemPosition = (*list)->numItems; + else if (firstItemPosition == LIST_START) + firstItemPosition = 1; - memmove (ITEMPTR(list,firstItemPosition-1), ptrToItems, - (*list)->itemSize * numItemsToReplace); + memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems, + (*list)->itemSize * numItemsToReplace); } /*******************************/ -void ListRemoveItem (list_t list, void *itemDestination, int itemPosition) +void ListGetItem (list_t list, void *itemDestination, int itemPosition) { - ListRemoveItems (list, itemDestination, itemPosition, 1); + ListGetItems (list, itemDestination, itemPosition, 1); } +#endif /* CFG_ALL_LIST_FUNCTIONS */ + /*******************************/ -void ListRemoveItems (list_t list, void *itemsDestination, int firstItemPosition, int numItemsToRemove) +#if defined(CFG_ALL_LIST_FUNCTIONS) || defined(CFG_DEVICE_DEREGISTER) + +void ListRemoveItem (list_t list, void *itemDestination, int itemPosition) { - int firstItemAfterChunk, numToMove; + ListRemoveItems (list, itemDestination, itemPosition, 1); +} - if (firstItemPosition == LIST_START) - firstItemPosition = 1; - else - if (firstItemPosition == LIST_END) - firstItemPosition = (*list)->numItems; +/*******************************/ - if (itemsDestination != NULL) - memcpy (itemsDestination, ITEMPTR(list,firstItemPosition-1), - (*list)->itemSize * numItemsToRemove); +void ListRemoveItems (list_t list, void *itemsDestination, + int firstItemPosition, int numItemsToRemove) +{ + int firstItemAfterChunk, numToMove; - firstItemAfterChunk = firstItemPosition + numItemsToRemove; - numToMove = (*list)->numItems - (firstItemAfterChunk - 1); + if (firstItemPosition == LIST_START) + firstItemPosition = 1; + else if (firstItemPosition == LIST_END) + firstItemPosition = (*list)->numItems; - if (numToMove > 0) /* move part of list down to cover hole left by removed item */ - memmove (ITEMPTR(list,firstItemPosition-1), - ITEMPTR(list,firstItemAfterChunk-1), - (*list)->itemSize * numToMove); + if (itemsDestination != NULL) + memcpy (itemsDestination, ITEMPTR (list, firstItemPosition - 1), + (*list)->itemSize * numItemsToRemove); - (*list)->numItems -= numItemsToRemove; -} + firstItemAfterChunk = firstItemPosition + numItemsToRemove; + numToMove = (*list)->numItems - (firstItemAfterChunk - 1); -/*******************************/ + if (numToMove > 0) { + /* + * move part of list down to cover hole left by removed item + */ + memmove (ITEMPTR (list, firstItemPosition - 1), + ITEMPTR (list, firstItemAfterChunk - 1), + (*list)->itemSize * numToMove); + } -void ListGetItem (list_t list, void *itemDestination, int itemPosition) -{ - ListGetItems (list, itemDestination, itemPosition, 1); + (*list)->numItems -= numItemsToRemove; } - -#endif /* CFG_ALL_LIST_FUNCTIONS */ +#endif /* CFG_ALL_LIST_FUNCTIONS || CFG_DEVICE_DEREGISTER */ /*******************************/ -void ListGetItems(list_t list, void *itemsDestination, int firstItemPosition, int numItemsToGet) +void ListGetItems (list_t list, void *itemsDestination, + int firstItemPosition, int numItemsToGet) { - if (firstItemPosition == LIST_START) - firstItemPosition = 1; - else - if (firstItemPosition == LIST_END) - firstItemPosition = (*list)->numItems; + if (firstItemPosition == LIST_START) + firstItemPosition = 1; + else if (firstItemPosition == LIST_END) + firstItemPosition = (*list)->numItems; - memcpy (itemsDestination, ITEMPTR(list,firstItemPosition-1), - (*list)->itemSize * numItemsToGet); + memcpy (itemsDestination, + ITEMPTR (list, firstItemPosition - 1), + (*list)->itemSize * numItemsToGet); } /*******************************/ - /* Returns a pointer to the item at itemPosition. returns null if an errors occurred. - */ -void * ListGetPtrToItem (list_t list, int itemPosition) +/* + * Returns a pointer to the item at itemPosition. returns null if an + * errors occurred. + */ +void *ListGetPtrToItem (list_t list, int itemPosition) { - if (itemPosition == LIST_START) - itemPosition = 1; - else - if (itemPosition == LIST_END) - itemPosition = (*list)->numItems; + if (itemPosition == LIST_START) + itemPosition = 1; + else if (itemPosition == LIST_END) + itemPosition = (*list)->numItems; - return ITEMPTR(list,itemPosition-1); + return ITEMPTR (list, itemPosition - 1); } /*******************************/ - /* returns a pointer the lists data (abstraction violation for optimization) */ -void * ListGetDataPtr (list_t list) +/* + * returns a pointer the lists data (abstraction violation for + * optimization) + */ +void *ListGetDataPtr (list_t list) { - return &((*list)->itemList[0]); + return &((*list)->itemList[0]); } /********************************/ #ifdef CFG_ALL_LIST_FUNCTIONS -int ListApplyToEach (list_t list, int ascending, ListApplicationFunc funcToApply, void *callbackData) -{ - int result = 0, index; - - if (!list || !funcToApply) - goto Error; - - if (ascending) - { - for (index = 1; index <= ListNumItems (list); index++) - { - result = funcToApply (index, ListGetPtrToItem (list, index), - callbackData); - if (result < 0) - goto Error; - } - } - else - { - for (index = ListNumItems (list); index > 0 && - index <= ListNumItems (list); index--) - { - result = funcToApply (index, ListGetPtrToItem (list, index), - callbackData); - if (result < 0) - goto Error; - } - } +int ListApplyToEach (list_t list, int ascending, + ListApplicationFunc funcToApply, + void *callbackData) +{ + int result = 0, index; + + if (!list || !funcToApply) + goto Error; + + if (ascending) { + for (index = 1; index <= ListNumItems (list); index++) { + result = funcToApply (index, + ListGetPtrToItem (list, index), + callbackData); + if (result < 0) + goto Error; + } + } else { + for (index = ListNumItems (list); + index > 0 && index <= ListNumItems (list); + index--) { + result = funcToApply (index, + ListGetPtrToItem (list, index), + callbackData); + if (result < 0) + goto Error; + } + } Error: - return result; + return result; } -#endif /* CFG_ALL_LIST_FUNCTIONS */ +#endif /* CFG_ALL_LIST_FUNCTIONS */ /********************************/ -int ListGetItemSize (list_t list) +int ListGetItemSize (list_t list) { - return (*list)->itemSize; + return (*list)->itemSize; } /********************************/ -int ListNumItems (list_t list) +int ListNumItems (list_t list) { - return (*list)->numItems; + return (*list)->numItems; } /*******************************/ #ifdef CFG_ALL_LIST_FUNCTIONS -void ListRemoveDuplicates (list_t list, CompareFunction compareFunction) +void ListRemoveDuplicates (list_t list, CompareFunction compareFunction) { - int numItems, index, startIndexForFind, duplicatesIndex; + int numItems, index, startIndexForFind, duplicatesIndex; - numItems = ListNumItems (list); + numItems = ListNumItems (list); - for (index = 1; index < numItems; index++) - { - startIndexForFind = index + 1; - while (startIndexForFind <= numItems) - { - duplicatesIndex = ListFindItem (list, ListGetPtrToItem (list, index), - startIndexForFind, compareFunction); - if (duplicatesIndex > 0) - { - ListRemoveItem (list, NULL, duplicatesIndex); - numItems--; - startIndexForFind = duplicatesIndex; - } - else - break; - } - } + for (index = 1; index < numItems; index++) { + startIndexForFind = index + 1; + while (startIndexForFind <= numItems) { + duplicatesIndex = + ListFindItem (list, + ListGetPtrToItem (list, index), + startIndexForFind, + compareFunction); + if (duplicatesIndex > 0) { + ListRemoveItem (list, NULL, duplicatesIndex); + numItems--; + startIndexForFind = duplicatesIndex; + } else { + break; + } + } + } } /*******************************/ @@ -603,93 +634,101 @@ void ListRemoveDuplicates (list_t list, CompareFunction compareFunction) /*******************************/ -int ListFindItem (list_t list, void *ptrToItem, int startingPosition, CompareFunction compareFunction) +int ListFindItem (list_t list, void *ptrToItem, int startingPosition, + CompareFunction compareFunction) { - int numItems, size, index, cmp; - void *listItemPtr; + int numItems, size, index, cmp; + void *listItemPtr; - if ((numItems = (*list)->numItems) == 0) - return 0; + if ((numItems = (*list)->numItems) == 0) + return 0; - size = (*list)->itemSize; + size = (*list)->itemSize; - if (startingPosition == LIST_START) - startingPosition = 1; - else - if (startingPosition == LIST_END) - startingPosition = numItems; + if (startingPosition == LIST_START) + startingPosition = 1; + else if (startingPosition == LIST_END) + startingPosition = numItems; - for (index = startingPosition; index <= numItems; index++) - { - listItemPtr = ITEMPTR(list,index-1); - cmp = compareFunction ? compareFunction(ptrToItem, listItemPtr) - : ListMemBlockCmp(ptrToItem, listItemPtr, size); - if (cmp == 0) - return index; - } + for (index = startingPosition; index <= numItems; index++) { + listItemPtr = ITEMPTR (list, index - 1); + cmp = compareFunction + ? compareFunction (ptrToItem, listItemPtr) + : ListMemBlockCmp (ptrToItem, listItemPtr, size); + if (cmp == 0) + return index; + } - return 0; + return 0; } /*******************************/ -int ShortCompare(void *a, void *b) +int ShortCompare (void *a, void *b) { - if (*(short *)a < *(short *)b) return -1; - if (*(short *)a > *(short *)b) return 1; - return 0; + if (*(short *) a < *(short *) b) + return -1; + if (*(short *) a > *(short *) b) + return 1; + return 0; } /*******************************/ -int IntCompare(void *a, void *b) +int IntCompare (void *a, void *b) { - if (*(int *)a < *(int *)b) return -1; - if (*(int *)a > *(int *)b) return 1; - return 0; + if (*(int *) a < *(int *) b) + return -1; + if (*(int *) a > *(int *) b) + return 1; + return 0; } /*******************************/ -int CStringCompare(void *a, void *b) +int CStringCompare (void *a, void *b) { - return strcmp(*(char **)a, *(char **)b); + return strcmp (*(char **) a, *(char **) b); } /*******************************/ -int ListBinSearch (list_t list, void *ptrToItem, CompareFunction compareFunction) +int ListBinSearch (list_t list, void *ptrToItem, + CompareFunction compareFunction) { - int index; + int index; - index = BinSearch (ITEMPTR(list,0), (int)(*list)->numItems, - (int)(*list)->itemSize, ptrToItem, compareFunction); + index = BinSearch (ITEMPTR (list, 0), + (int) (*list)->numItems, + (int) (*list)->itemSize, ptrToItem, + compareFunction); - if (index >= 0) - index++; /* lists start from 1 */ - else - index = 0; /* item not found */ + if (index >= 0) + index++; /* lists start from 1 */ + else + index = 0; /* item not found */ - return index; + return index; } /**************************************************************************/ - /* Reserves memory for numItems in the list. If it succeeds then - numItems items can be inserted without possibility of an - out of memory error (useful to simplify error recovery in - complex functions). Returns 1 if success, 0 if - out of memory. - */ -int ListPreAllocate (list_t list, int numItems) +/* + * Reserves memory for numItems in the list. If it succeeds then + * numItems items can be inserted without possibility of an out of + * memory error (useful to simplify error recovery in complex + * functions). Returns 1 if success, 0 if out of memory. + */ +int ListPreAllocate (list_t list, int numItems) { - - if ((*list)->listSize - (*list)->numItems < numItems) - return ExpandListSpace (list, - numItems - ((*list)->listSize - (*list)->numItems)); - else - return 1; /* enough items are already pre-allocated */ + if ((*list)->listSize - (*list)->numItems < numItems) { + return ExpandListSpace (list, + numItems - ((*list)->listSize - + (*list)->numItems)); + } else { + return 1; /* enough items are already pre-allocated */ + } } -#endif /* CFG_ALL_LIST_FUNCTIONS */ +#endif /* CFG_ALL_LIST_FUNCTIONS */ diff --git a/common/usb.c b/common/usb.c new file mode 100644 index 0000000..b9f577e --- /dev/null +++ b/common/usb.c @@ -0,0 +1,1066 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * Most of this source has been derived from the Linux USB + * project. + * + * 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 + * + */ + + +/* + * How it works: + * + * Since this is a bootloader, the devices will not be automatic + * (re)configured on hotplug, but after a restart of the USB the + * device should work. + * + * For each transfer (except "Interrupt") we wait for completion. + */ +#include +#include +#include + +#if (CONFIG_COMMANDS & CFG_CMD_USB) + +#include +#ifdef CONFIG_4xx +#include <405gp_pci.h> +#endif + + + +#undef USB_DEBUG + +#ifdef USB_DEBUG +#define USB_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define USB_PRINTF(fmt,args...) +#endif + +static struct usb_device usb_dev[USB_MAX_DEVICE]; +static int dev_index; +static int running; +static int asynch_allowed; +static struct devrequest setup_packet; + +/********************************************************************** + * some forward declerations... + */ +void usb_scan_devices(void); + +int usb_hub_probe(struct usb_device *dev, int ifnum); +void usb_hub_reset(void); + +/*********************************************************************** + * wait_ms + */ + +void __inline__ wait_ms(unsigned long ms) +{ + while(ms-->0) + udelay(1000); +} +/*************************************************************************** + * Init USB Device + */ + +int usb_init(void) +{ + int result; + + running=0; + dev_index=0; + asynch_allowed=1; + usb_hub_reset(); + /* init low_level USB */ + printf("USB: "); + result = usb_lowlevel_init(); + /* if lowlevel init is OK, scan the bus for devices i.e. search HUBs and configure them */ + if(result==0) { + printf("scanning bus for devices... "); + running=1; + usb_scan_devices(); + return 0; + } + else { + printf("Error, couldn't init Lowlevel part\n"); + return -1; + } +} + +/****************************************************************************** + * Stop USB this stops the LowLevel Part and deregisters USB devices. + */ +int usb_stop(void) +{ + asynch_allowed=1; + usb_hub_reset(); + return usb_lowlevel_stop(); +} + +/* + * disables the asynch behaviour of the control message. This is used for data + * transfers that uses the exclusiv access to the control and bulk messages. + */ +void usb_disable_asynch(int disable) +{ + asynch_allowed=!disable; +} + + +/*------------------------------------------------------------------- + * Message wrappers. + * + */ + +/* + * submits an Interrupt Message + */ +int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer,int transfer_len, int interval) +{ + return submit_int_msg(dev,pipe,buffer,transfer_len,interval); +} + +/* + * submits a control message and waits for comletion (at least timeout * 1ms) + * If timeout is 0, we don't wait for completion (used as example to set and + * clear keyboards LEDs). For data transfers, (storage transfers) we don't + * allow control messages with 0 timeout, by previousely resetting the flag + * asynch_allowed (usb_disable_asynch(1)). + * returns the transfered length if OK or -1 if error. The transfered length + * and the current status are stored in the dev->act_len and dev->status. + */ +int usb_control_msg(struct usb_device *dev, unsigned int pipe, + unsigned char request, unsigned char requesttype, + unsigned short value, unsigned short index, + void *data, unsigned short size, int timeout) +{ + if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */ + return -1; + /* set setup command */ + setup_packet.requesttype = requesttype; + setup_packet.request = request; + setup_packet.value = swap_16(value); + setup_packet.index = swap_16(index); + setup_packet.length = swap_16(size); + USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X\nvalue 0x%X index 0x%X length 0x%X\n", + request,requesttype,value,index,size); + dev->status=USB_ST_NOT_PROC; /*not yet processed */ + + submit_control_msg(dev,pipe,data,size,&setup_packet); + if(timeout==0) { + return (int)size; + } + while(timeout--) { + if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) + break; + wait_ms(1); + } + if(dev->status==0) + return dev->act_len; + else { + return -1; + } +} + +/*------------------------------------------------------------------- + * submits bulk message, and waits for completion. returns 0 if Ok or + * -1 if Error. + * synchronous behavior + */ +int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout) +{ + if (len < 0) + return -1; + dev->status=USB_ST_NOT_PROC; /*not yet processed */ + submit_bulk_msg(dev,pipe,data,len); + while(timeout--) { + if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) + break; + wait_ms(1); + } + *actual_length=dev->act_len; + if(dev->status==0) + return 0; + else + return -1; +} + + +/*------------------------------------------------------------------- + * Max Packet stuff + */ + +/* + * returns the max packet size, depending on the pipe direction and + * the configurations values + */ +int usb_maxpacket(struct usb_device *dev,unsigned long pipe) +{ + if((pipe & USB_DIR_IN)==0) /* direction is out -> use emaxpacket out */ + return(dev->epmaxpacketout[((pipe>>15) & 0xf)]); + else + return(dev->epmaxpacketin[((pipe>>15) & 0xf)]); +} + +/* + * set the max packed value of all endpoints in the given configuration + */ +int usb_set_maxpacket(struct usb_device *dev) +{ + int i,ii,b; + struct usb_endpoint_descriptor *ep; + + for(i=0; iconfig.bNumInterfaces;i++) { + for(ii=0; iiconfig.if_desc[i].bNumEndpoints; ii++) { + ep=&dev->config.if_desc[i].ep_desc[ii]; + b=ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + + if((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)==USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ + dev->epmaxpacketout[b] = ep->wMaxPacketSize; + dev->epmaxpacketin [b] = ep->wMaxPacketSize; + USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",b,dev->epmaxpacketin[b]); + } + else { + if ((ep->bEndpointAddress & 0x80)==0) { /* OUT Endpoint */ + if(ep->wMaxPacketSize > dev->epmaxpacketout[b]) { + dev->epmaxpacketout[b] = ep->wMaxPacketSize; + USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",b,dev->epmaxpacketout[b]); + } + } + else { /* IN Endpoint */ + if(ep->wMaxPacketSize > dev->epmaxpacketin[b]) { + dev->epmaxpacketin[b] = ep->wMaxPacketSize; + USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",b,dev->epmaxpacketin[b]); + } + } /* if out */ + } /* if control */ + } /* for each endpoint */ + } + return 0; +} + +/******************************************************************************* + * Parse the config, located in buffer, and fills the dev->config structure. + * Note that all little/big endian swapping are done automatically. + */ +int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno) +{ + struct usb_descriptor_header *head; + int index,ifno,epno; + ifno=-1; + epno=-1; + + dev->configno=cfgno; + head =(struct usb_descriptor_header *)&buffer[0]; + if(head->bDescriptorType!=USB_DT_CONFIG) { + printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType); + return -1; + } + memcpy(&dev->config,buffer,buffer[0]); + dev->config.wTotalLength=swap_16(dev->config.wTotalLength); + dev->config.no_of_if=0; + + index=dev->config.bLength; + /* Ok the first entry must be a configuration entry, now process the others */ + head=(struct usb_descriptor_header *)&buffer[index]; + while(index+1 < dev->config.wTotalLength) { + switch(head->bDescriptorType) { + case USB_DT_INTERFACE: + ifno=dev->config.no_of_if; + dev->config.no_of_if++; /* found an interface desc, increase numbers */ + memcpy(&dev->config.if_desc[ifno],&buffer[index],buffer[index]); /* copy new desc */ + dev->config.if_desc[ifno].no_of_ep=0; + + break; + case USB_DT_ENDPOINT: + epno=dev->config.if_desc[ifno].no_of_ep; + dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */ + memcpy(&dev->config.if_desc[ifno].ep_desc[epno],&buffer[index],buffer[index]); + dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize + =swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize); + USB_PRINTF("if %d, ep %d\n",ifno,epno); + break; + default: + if(head->bLength==0) + return 1; + USB_PRINTF("unknown Description Type : %x\n",head->bDescriptorType); + { + int i; + unsigned char *ch; + ch=(unsigned char *)head; + for(i=0;ibLength; i++) + USB_PRINTF("%02X ",*ch++); + USB_PRINTF("\n\n\n"); + } + break; + } + index+=head->bLength; + head=(struct usb_descriptor_header *)&buffer[index]; + } + return 1; +} + +/*********************************************************************** + * Clears an endpoint + * endp: endpoint number in bits 0-3; + * direction flag in bit 7 (1 = IN, 0 = OUT) + */ +int usb_clear_halt(struct usb_device *dev, int pipe) +{ + int result; + unsigned short status; + int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7); + + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3); + + /* don't clear if failed */ + if (result < 0) + return result; + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp, + &status, sizeof(status), USB_CNTL_TIMEOUT * 3); + if (result < 0) + return result; + USB_PRINTF("usb_clear_halt: status 0x%x\n",status); + if (status & 1) + return -1; /* still halted */ + usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); + /* toggle is reset on clear */ + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); + return 0; +} + + +/********************************************************************** + * get_descriptor type + */ +int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) +{ + int res; + res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (type << 8) + index, 0, + buf, size, USB_CNTL_TIMEOUT); + return res; +} + +/********************************************************************** + * gets configuration cfgno and store it in the buffer + */ +int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno) +{ + int result; + unsigned int tmp; + struct usb_config_descriptor *config; + + + config=(struct usb_config_descriptor *)&buffer[0]; + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); + if (result < 8) { + if (result < 0) + printf("unable to get descriptor, error %lX\n",dev->status); + else + printf("config descriptor too short (expected %i, got %i)\n",8,result); + return -1; + } + tmp=swap_16(config->wTotalLength); + + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp); + USB_PRINTF("get_conf_no %d Result %d, wLength %d\n",cfgno,result,tmp); + return result; +} + +/******************************************************************** + * set address of a device to the value in dev->devnum. + * This can only be done by addressing the device via the default address (0) + */ +int usb_set_address(struct usb_device *dev) +{ + int res; + + USB_PRINTF("set address %d\n",dev->devnum); + res=usb_control_msg(dev, usb_snddefctrl(dev), + USB_REQ_SET_ADDRESS, 0, + (dev->devnum),0, + NULL,0, USB_CNTL_TIMEOUT); + return res; +} + +/******************************************************************** + * set interface number to interface + */ +int usb_set_interface(struct usb_device *dev, int interface, int alternate) +{ + struct usb_interface_descriptor *if_face = NULL; + int ret, i; + + for (i=0; iconfig.bNumInterfaces; i++) { + if (dev->config.if_desc[i].bInterfaceNumber == interface) { + if_face = &dev->config.if_desc[i]; + break; + } + } + if (!if_face) { + printf("selecting invalid interface %d", interface); + return -1; + } + + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, + interface, NULL, 0, USB_CNTL_TIMEOUT * 5)) < 0) + return ret; + + if_face->act_altsetting = (unsigned char)alternate; + usb_set_maxpacket(dev); + return 0; +} + +/******************************************************************** + * set configuration number to configuration + */ +int usb_set_configuration(struct usb_device *dev, int configuration) +{ + int res; + USB_PRINTF("set configuration %d\n",configuration); + /* set setup command */ + res=usb_control_msg(dev, usb_sndctrlpipe(dev,0), + USB_REQ_SET_CONFIGURATION, 0, + configuration,0, + NULL,0, USB_CNTL_TIMEOUT); + if(res==0) { + dev->toggle[0] = 0; + dev->toggle[1] = 0; + return 0; + } + else + return -1; +} + +/******************************************************************** + * set protocol to protocol + */ +int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + protocol, ifnum, NULL, 0, USB_CNTL_TIMEOUT); +} + +/******************************************************************** + * set idle + */ +int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (duration << 8) | report_id, ifnum, NULL, 0, USB_CNTL_TIMEOUT); +} + +/******************************************************************** + * get report + */ +int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); +} + +/******************************************************************** + * get class descriptor + */ +int usb_get_class_descriptor(struct usb_device *dev, int ifnum, + unsigned char type, unsigned char id, void *buf, int size) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, + (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); +} + +/******************************************************************** + * get string index in buffer + */ +int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, buf, size, USB_CNTL_TIMEOUT); +} + +/******************************************************************** + * usb_string: + * Get string index and translate it to ascii. + * returns string length (> 0) or error (< 0) + */ +int usb_string(struct usb_device *dev, int index, char *buf, size_t size) +{ + + unsigned char mybuf[256]; + unsigned char *tbuf; + int err; + unsigned int u, idx; + + if (size <= 0 || !buf || !index) + return -1; + buf[0] = 0; + tbuf=&mybuf[0]; + + /* get langid for strings if it's not yet known */ + if (!dev->have_langid) { + err = usb_get_string(dev, 0, 0, tbuf, 4); + if (err < 0) { + USB_PRINTF("error getting string descriptor 0 (error=%x)\n",dev->status); + return -1; + } else if (tbuf[0] < 4) { + USB_PRINTF("string descriptor 0 too short\n"); + return -1; + } else { + dev->have_langid = -1; + dev->string_langid = tbuf[2] | (tbuf[3]<< 8); + /* always use the first langid listed */ + USB_PRINTF("USB device number %d default language ID 0x%x\n", + dev->devnum, dev->string_langid); + } + } + /* Just ask for a maximum length string and then take the length + * that was returned. */ + err = usb_get_string(dev, dev->string_langid, index, tbuf, 4); + if (err < 0) + return err; + u=tbuf[0]; + USB_PRINTF("Strn Len %d, index %d\n",u,index); + err = usb_get_string(dev, dev->string_langid, index, tbuf, u); + if (err < 0) + return err; + size--; /* leave room for trailing NULL char in output buffer */ + for (idx = 0, u = 2; u < err; u += 2) { + if (idx >= size) + break; + if (tbuf[u+1]) /* high byte */ + buf[idx++] = '?'; /* non-ASCII character */ + else + buf[idx++] = tbuf[u]; + } + buf[idx] = 0; + err = idx; + return err; +} + + +/******************************************************************** + * USB device handling: + * the USB device are static allocated [USB_MAX_DEVICE]. + */ + + +/* returns a pointer to the device with the index [index]. + * if the device is not assigned (dev->devnum==-1) returns NULL + */ +struct usb_device * usb_get_dev_index(int index) +{ + if(usb_dev[index].devnum==-1) + return NULL; + else + return &usb_dev[index]; +} + + +/* returns a pointer of a new device structure or NULL, if + * no device struct is available + */ +struct usb_device * usb_alloc_new_device(void) +{ + int i; + USB_PRINTF("New Device %d\n",dev_index); + if(dev_index==USB_MAX_DEVICE) { + printf("ERROR, to many USB Devices max=%d\n",USB_MAX_DEVICE); + return NULL; + } + usb_dev[dev_index].devnum=dev_index+1; /* default Address is 0, real addresses start with 1 */ + usb_dev[dev_index].maxchild=0; + for(i=0;idescriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ + dev->maxpacketsize = 0; /* Default to 8 byte max packet size */ + dev->epmaxpacketin [0] = 8; + dev->epmaxpacketout[0] = 8; + + /* We still haven't set the Address yet */ + addr = dev->devnum; + dev->devnum = 0; + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); + if (err < 8) { + printf("\n USB device not responding, giving up (status=%lX)\n",dev->status); + return 1; + } + dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; + dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; + switch (dev->descriptor.bMaxPacketSize0) { + case 8: dev->maxpacketsize = 0; break; + case 16: dev->maxpacketsize = 1; break; + case 32: dev->maxpacketsize = 2; break; + case 64: dev->maxpacketsize = 3; break; + } + dev->devnum = addr; + + err = usb_set_address(dev); /* set address */ + + if (err < 0) { + printf("\n USB device not accepting new address (error=%lX)\n", dev->status); + return 1; + } + + wait_ms(10); /* Let the SET_ADDRESS settle */ + + tmp = sizeof(dev->descriptor); + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); + if (err < tmp) { + if (err < 0) + printf("unable to get device descriptor (error=%d)\n",err); + else + printf("USB device descriptor short read (expected %i, got %i)\n",tmp,err); + return 1; + } + /* correct le values */ + dev->descriptor.bcdUSB=swap_16(dev->descriptor.bcdUSB); + dev->descriptor.idVendor=swap_16(dev->descriptor.idVendor); + dev->descriptor.idProduct=swap_16(dev->descriptor.idProduct); + dev->descriptor.bcdDevice=swap_16(dev->descriptor.bcdDevice); + /* only support for one config for now */ + usb_get_configuration_no(dev,&tmpbuf[0],0); + usb_parse_config(dev,&tmpbuf[0],0); + usb_set_maxpacket(dev); + /* we set the default configuration here */ + if (usb_set_configuration(dev, dev->config.bConfigurationValue)) { + printf("failed to set default configuration len %d, status %lX\n",dev->act_len,dev->status); + return -1; + } + USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", + dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); + memset(dev->mf, 0, sizeof(dev->mf)); + memset(dev->prod, 0, sizeof(dev->prod)); + memset(dev->serial, 0, sizeof(dev->serial)); + if (dev->descriptor.iManufacturer) + usb_string(dev, dev->descriptor.iManufacturer, dev->mf, sizeof(dev->mf)); + if (dev->descriptor.iProduct) + usb_string(dev, dev->descriptor.iProduct, dev->prod, sizeof(dev->prod)); + if (dev->descriptor.iSerialNumber) + usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial)); + USB_PRINTF("Manufacturer %s\n", dev->mf); + USB_PRINTF("Product %s\n", dev->prod); + USB_PRINTF("SerialNumber %s\n", dev->serial); + /* now prode if the device is a hub */ + usb_hub_probe(dev,0); + return 0; +} + +/* build device Tree */ +void usb_scan_devices(void) +{ + int i; + struct usb_device *dev; + + /* first make all devices unknown */ + for(i=0;ipusb_dev; + /* Enable power to the ports */ + USB_HUB_PRINTF("enabling power on all ports\n"); + for (i = 0; i < dev->maxchild; i++) { + usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + USB_HUB_PRINTF("port %d returns %lX\n",i+1,dev->status); + wait_ms(hub->desc.bPwrOn2PwrGood * 2); + } +} + +void usb_hub_reset(void) +{ + usb_hub_index=0; +} + +struct usb_hub_device *usb_hub_allocate(void) +{ + if(usb_hub_indexchildren[port])) { + USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n"); + /* Return now if nothing is connected */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) + return; + } + wait_ms(200); + + /* Reset the port */ + + for(tries=0;triesstatus); + return; + } + portstatus = swap_16(portsts.wPortStatus); + portchange = swap_16(portsts.wPortChange); + USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus ,portchange, + portstatus&(1<slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0; + + dev->children[port] = usb; + usb->parent=dev; + /* Run it through the hoops (find a driver, etc) */ + if (usb_new_device(usb)) { + /* Woops, disable the port */ + USB_HUB_PRINTF("hub: disabling port %d\n", port + 1); + usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE); + } +} + + +int usb_hub_configure(struct usb_device *dev) +{ + unsigned char buffer[256], *bitmap; + struct usb_hub_descriptor *descriptor; + struct usb_hub_status *hubsts; + int i; + struct usb_hub_device *hub; + + /* "allocate" Hub device */ + hub=usb_hub_allocate(); + if(hub==NULL) + return -1; + hub->pusb_dev=dev; + /* Get the the hub descriptor */ + if (usb_get_hub_descriptor(dev, buffer, 4) < 0) { + USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor, giving up %lX\n",dev->status); + return -1; + } + descriptor = (struct usb_hub_descriptor *)buffer; + if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) { + USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor 2nd giving up %lX\n",dev->status); + return -1; + } + memcpy((unsigned char *)&hub->desc,buffer,descriptor->bLength); + /* adjust 16bit values */ + hub->desc.wHubCharacteristics=swap_16(descriptor->wHubCharacteristics); + /* set the bitmap */ + bitmap=(unsigned char *)&hub->desc.DeviceRemovable[0]; + memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* devices not removable by default */ + bitmap=(unsigned char *)&hub->desc.PortPowerCtrlMask[0]; + memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */ + for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) { + hub->desc.DeviceRemovable[i]=descriptor->DeviceRemovable[i]; + } + for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) { + hub->desc.DeviceRemovable[i]=descriptor->PortPowerCtrlMask[i]; + } + dev->maxchild = descriptor->bNbrPorts; + USB_HUB_PRINTF("%d ports detected\n", dev->maxchild); + + switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) { + case 0x00: + USB_HUB_PRINTF("ganged power switching\n"); + break; + case 0x01: + USB_HUB_PRINTF("individual port power switching\n"); + break; + case 0x02: + case 0x03: + USB_HUB_PRINTF("unknown reserved power switching mode\n"); + break; + } + + if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND) + USB_HUB_PRINTF("part of a compound device\n"); + else + USB_HUB_PRINTF("standalone hub\n"); + + switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) { + case 0x00: + USB_HUB_PRINTF("global over-current protection\n"); + break; + case 0x08: + USB_HUB_PRINTF("individual port over-current protection\n"); + break; + case 0x10: + case 0x18: + USB_HUB_PRINTF("no over-current protection\n"); + break; + } + USB_HUB_PRINTF("power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2); + USB_HUB_PRINTF("hub controller current requirement: %dmA\n", descriptor->bHubContrCurrent); + for (i = 0; i < dev->maxchild; i++) + USB_HUB_PRINTF("port %d is%s removable\n", i + 1, + hub->desc.DeviceRemovable[(i + 1)/8] & (1 << ((i + 1)%8)) ? " not" : ""); + if (usb_get_hub_status(dev, buffer) < 0) { + USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",dev->status); + return -1; + } + hubsts = (struct usb_hub_status *)buffer; + USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n", + swap_16(hubsts->wHubStatus),swap_16(hubsts->wHubChange)); + USB_HUB_PRINTF("local power source is %s\n", + (swap_16(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); + USB_HUB_PRINTF("%sover-current condition exists\n", + (swap_16(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no "); + usb_hub_power_on(hub); + for (i = 0; i < dev->maxchild; i++) { + struct usb_port_status portsts; + unsigned short portstatus, portchange; + + if (usb_get_port_status(dev, i + 1, &portsts) < 0) { + USB_HUB_PRINTF("get_port_status failed\n"); + continue; + } + portstatus = swap_16(portsts.wPortStatus); + portchange = swap_16(portsts.wPortChange); + USB_HUB_PRINTF("Port %d Status %X Change %X\n",i+1,portstatus,portchange); + if (portchange & USB_PORT_STAT_C_CONNECTION) { + USB_HUB_PRINTF("port %d connection change\n", i + 1); + usb_hub_port_connect_change(dev, i); + } + if (portchange & USB_PORT_STAT_C_ENABLE) { + USB_HUB_PRINTF("port %d enable change, status %x\n", i + 1, portstatus); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); + + /* EM interference sometimes causes bad shielded USB devices to + * be shutdown by the hub, this hack enables them again. + * Works at least with mouse driver */ + if (!(portstatus & USB_PORT_STAT_ENABLE) && + (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) { + USB_HUB_PRINTF("already running port %i disabled by hub (EMI?), re-enabling...\n", + i + 1); + usb_hub_port_connect_change(dev, i); + } + } + if (portstatus & USB_PORT_STAT_SUSPEND) { + USB_HUB_PRINTF("port %d suspend change\n", i + 1); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_SUSPEND); + } + + if (portchange & USB_PORT_STAT_C_OVERCURRENT) { + USB_HUB_PRINTF("port %d over-current change\n", i + 1); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); + usb_hub_power_on(hub); + } + + if (portchange & USB_PORT_STAT_C_RESET) { + USB_HUB_PRINTF("port %d reset change\n", i + 1); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); + } + } /* end for i all ports */ + + return 0; +} + +int usb_hub_probe(struct usb_device *dev, int ifnum) +{ + struct usb_interface_descriptor *iface; + struct usb_endpoint_descriptor *ep; + int ret; + + iface = &dev->config.if_desc[ifnum]; + /* Is it a hub? */ + if (iface->bInterfaceClass != USB_CLASS_HUB) + return 0; + /* Some hubs have a subclass of 1, which AFAICT according to the */ + /* specs is not defined, but it works */ + if ((iface->bInterfaceSubClass != 0) && + (iface->bInterfaceSubClass != 1)) + return 0; + /* Multiple endpoints? What kind of mutant ninja-hub is this? */ + if (iface->bNumEndpoints != 1) + return 0; + ep = &iface->ep_desc[0]; + /* Output endpoint? Curiousier and curiousier.. */ + if (!(ep->bEndpointAddress & USB_DIR_IN)) + return 0; + /* If it's not an interrupt endpoint, we'd better punt! */ + if ((ep->bmAttributes & 3) != 3) + return 0; + /* We found a hub */ + USB_HUB_PRINTF("USB hub found\n"); + ret=usb_hub_configure(dev); + return ret; +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_USB) */ + +/* EOF */ diff --git a/common/usb_kbd.c b/common/usb_kbd.c new file mode 100644 index 0000000..5f5d619 --- /dev/null +++ b/common/usb_kbd.c @@ -0,0 +1,734 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * Part of this source has been derived from the Linux USB + * project. + * + * 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 + * + */ +#include +#include + +#ifdef CONFIG_USB_KEYBOARD + +#include + +#undef USB_KBD_DEBUG +/* + * if overwrite_console returns 1, the stdin, stderr and stdout + * are switched to the serial port, else the settings in the + * environment are used + */ +#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE +extern int overwrite_console (void); +#else +int overwrite_console (void) +{ + return (0); +} +#endif + +#ifdef USB_KBD_DEBUG +#define USB_KBD_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define USB_KBD_PRINTF(fmt,args...) +#endif + + +#define REPEAT_RATE 40/4 /* 40msec -> 25cps */ +#define REPEAT_DELAY 10 /* 10 x REAPEAT_RATE = 400msec */ + +#define NUM_LOCK 0x53 +#define CAPS_LOCK 0x39 +#define SCROLL_LOCK 0x47 + + +/* Modifier bits */ +#define LEFT_CNTR 0 +#define LEFT_SHIFT 1 +#define LEFT_ALT 2 +#define LEFT_GUI 3 +#define RIGHT_CNTR 4 +#define RIGHT_SHIFT 5 +#define RIGHT_ALT 6 +#define RIGHT_GUI 7 + +#define USB_KBD_BUFFER_LEN 0x20 /* size of the keyboardbuffer */ + +static volatile char usb_kbd_buffer[USB_KBD_BUFFER_LEN]; +static volatile int usb_in_pointer = 0; +static volatile int usb_out_pointer = 0; + +unsigned char new[8]; +unsigned char old[8]; +int repeat_delay; +#define DEVNAME "usbkbd" +static unsigned char num_lock = 0; +static unsigned char caps_lock = 0; +static unsigned char scroll_lock = 0; + +static unsigned char leds __attribute__ ((aligned (0x4))); + +static unsigned char usb_kbd_numkey[] = { + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0','\r',0x1b,'\b','\t',' ', '-', + '=', '[', ']','\\', '#', ';', '\'', '`', ',', '.', '/' +}; +static unsigned char usb_kbd_numkey_shifted[] = { + '!', '@', '#', '$', '%', '^', '&', '*', '(', ')','\r',0x1b,'\b','\t',' ', '_', + '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?' +}; + +/****************************************************************** + * Queue handling + ******************************************************************/ +/* puts character in the queue and sets up the in and out pointer */ +static void usb_kbd_put_queue(char data) +{ + if((usb_in_pointer+1)==USB_KBD_BUFFER_LEN) { + if(usb_out_pointer==0) { + return; /* buffer full */ + } else{ + usb_in_pointer=0; + } + } else { + if((usb_in_pointer+1)==usb_out_pointer) + return; /* buffer full */ + usb_in_pointer++; + } + usb_kbd_buffer[usb_in_pointer]=data; + return; +} + +/* test if a character is in the queue */ +static int usb_kbd_testc(void) +{ + if(usb_in_pointer==usb_out_pointer) + return(0); /* no data */ + else + return(1); +} +/* gets the character from the queue */ +static int usb_kbd_getc(void) +{ + char c; + while(usb_in_pointer==usb_out_pointer); + if((usb_out_pointer+1)==USB_KBD_BUFFER_LEN) + usb_out_pointer=0; + else + usb_out_pointer++; + c=usb_kbd_buffer[usb_out_pointer]; + return (int)c; + +} + +/* forward decleration */ +static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum); + +/* search for keyboard and register it if found */ +int drv_usb_kbd_init(void) +{ + int error,i,index; + device_t usb_kbd_dev,*old_dev; + struct usb_device *dev; + char *stdinname = getenv ("stdin"); + + usb_in_pointer=0; + usb_out_pointer=0; + /* scan all USB Devices */ + for(i=0;idevnum!=-1) { + if(usb_kbd_probe(dev,0)==1) { /* Ok, we found a keyboard */ + /* check, if it is already registered */ + USB_KBD_PRINTF("USB KBD found set up device.\n"); + for (index=1; index<=ListNumItems(devlist); index++) { + old_dev = ListGetPtrToItem(devlist, index); + if(strcmp(old_dev->name,DEVNAME)==0) { + /* ok, already registered, just return ok */ + USB_KBD_PRINTF("USB KBD is already registered.\n"); + return 1; + } + } + /* register the keyboard */ + USB_KBD_PRINTF("USB KBD register.\n"); + memset (&usb_kbd_dev, 0, sizeof(device_t)); + strcpy(usb_kbd_dev.name, DEVNAME); + usb_kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + usb_kbd_dev.putc = NULL; + usb_kbd_dev.puts = NULL; + usb_kbd_dev.getc = usb_kbd_getc; + usb_kbd_dev.tstc = usb_kbd_testc; + error = device_register (&usb_kbd_dev); + if(error==0) { + /* check if this is the standard input device */ + if(strcmp(stdinname,DEVNAME)==0) { + /* reassign the console */ + if(overwrite_console()) { + return 1; + } + error=console_assign(stdin,DEVNAME); + if(error==0) + return 1; + else + return error; + } + return 1; + } + return error; + } + } + } + /* no USB Keyboard found */ + return -1; +} + + +/* deregistering the keyboard */ +int usb_kbd_deregister(void) +{ + return device_deregister(DEVNAME); +} + +/************************************************************************** + * Low Level drivers + */ + +/* set the LEDs. Since this is used in the irq routine, the control job + is issued with a timeout of 0. This means, that the job is queued without + waiting for job completion */ + +static void usb_kbd_setled(struct usb_device *dev) +{ + struct usb_interface_descriptor *iface; + iface = &dev->config.if_desc[0]; + leds=0; + if(scroll_lock!=0) + leds|=1; + leds<<=1; + if(caps_lock!=0) + leds|=1; + leds<<=1; + if(num_lock!=0) + leds|=1; + usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0x200, iface->bInterfaceNumber,(void *)&leds, 1, 0); + +} + + +#define CAPITAL_MASK 0x20 +/* Translate the scancode in ASCII */ +static int usb_kbd_translate(unsigned char scancode,unsigned char modifier,int pressed) +{ + unsigned char keycode; + + if(pressed==0) { + /* key released */ + repeat_delay=0; + return 0; + } + if(pressed==2) { + repeat_delay++; + if(repeat_delay3) && (scancode<0x1d)) { /* alpha numeric values */ + keycode=scancode-4 + 0x61; + if(caps_lock) + keycode&=~CAPITAL_MASK; /* switch to capital Letters */ + if(((modifier&(1<0x1d) && (scancode<0x3A)) { + if(((modifier&(1<irq_status!=0)||(dev->irq_act_len!=8)) + { + USB_KBD_PRINTF("usb_keyboard Error %lX, len %d\n",dev->irq_status,dev->irq_act_len); + return 1; + } + res=0; + for (i = 2; i < 8; i++) { + if (old[i] > 3 && memscan(&new[2], old[i], 6) == &new[8]) { + res|=usb_kbd_translate(old[i],new[0],0); + } + if (new[i] > 3 && memscan(&old[2], new[i], 6) == &old[8]) { + res|=usb_kbd_translate(new[i],new[0],1); + } + } + if((new[2]>3) && (old[2]==new[2])) /* still pressed */ + res|=usb_kbd_translate(new[2],new[0],2); + if(res==1) + usb_kbd_setled(dev); + memcpy(&old[0],&new[0], 8); + return 1; /* install IRQ Handler again */ +} + +/* probes the USB device dev for keyboard type */ +static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) +{ + struct usb_interface_descriptor *iface; + struct usb_endpoint_descriptor *ep; + int pipe,maxp; + + if (dev->descriptor.bNumConfigurations != 1) return 0; + iface = &dev->config.if_desc[ifnum]; + + if (iface->bInterfaceClass != 3) return 0; + if (iface->bInterfaceSubClass != 1) return 0; + if (iface->bInterfaceProtocol != 1) return 0; + if (iface->bNumEndpoints != 1) return 0; + + ep = &iface->ep_desc[0]; + + if (!(ep->bEndpointAddress & 0x80)) return 0; + if ((ep->bmAttributes & 3) != 3) return 0; + USB_KBD_PRINTF("USB KBD found set protocol...\n"); + /* ok, we found a USB Keyboard, install it */ + /* usb_kbd_get_hid_desc(dev); */ + usb_set_protocol(dev, iface->bInterfaceNumber, 0); + USB_KBD_PRINTF("USB KBD found set idle...\n"); + usb_set_idle(dev, iface->bInterfaceNumber, REPEAT_RATE, 0); + memset(&new[0], 0, 8); + memset(&old[0], 0, 8); + repeat_delay=0; + pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe); + dev->irq_handle=usb_kbd_irq; + USB_KBD_PRINTF("USB KBD enable interrupt pipe...\n"); + usb_submit_int_msg(dev,pipe,&new[0], maxp > 8 ? 8 : maxp,ep->bInterval); + return 1; +} + + +#if 0 +struct usb_hid_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; /* 0x21 for HID */ + unsigned short bcdHID; /* release number */ + unsigned char bCountryCode; + unsigned char bNumDescriptors; + unsigned char bReportDescriptorType; + unsigned short wDescriptorLength; +} __attribute__ ((packed)); + +/* + * We parse each description item into this structure. Short items data + * values are expanded to 32-bit signed int, long items contain a pointer + * into the data area. + */ + +struct hid_item { + unsigned char format; + unsigned char size; + unsigned char type; + unsigned char tag; + union { + unsigned char u8; + char s8; + unsigned short u16; + short s16; + unsigned long u32; + long s32; + unsigned char *longdata; + } data; +}; + +/* + * HID report item format + */ + +#define HID_ITEM_FORMAT_SHORT 0 +#define HID_ITEM_FORMAT_LONG 1 + +/* + * Special tag indicating long items + */ + +#define HID_ITEM_TAG_LONG 15 + + + +static struct usb_hid_descriptor usb_kbd_hid_desc; + +void usb_kbd_display_hid(struct usb_hid_descriptor *hid) +{ + printf("USB_HID_DESC:\n"); + printf(" bLenght 0x%x\n",hid->bLength); + printf(" bcdHID 0x%x\n",hid->bcdHID); + printf(" bCountryCode %d\n",hid->bCountryCode); + printf(" bNumDescriptors 0x%x\n",hid->bNumDescriptors); + printf(" bReportDescriptorType 0x%x\n",hid->bReportDescriptorType); + printf(" wDescriptorLength 0x%x\n",hid->wDescriptorLength); +} + + +/* + * Fetch a report description item from the data stream. We support long + * items, though they are not used yet. + */ + +static int fetch_item(unsigned char *start,unsigned char *end, struct hid_item *item) +{ + if((end - start) > 0) { + unsigned char b = *start++; + item->type = (b >> 2) & 3; + item->tag = (b >> 4) & 15; + if (item->tag == HID_ITEM_TAG_LONG) { + item->format = HID_ITEM_FORMAT_LONG; + if ((end - start) >= 2) { + item->size = *start++; + item->tag = *start++; + if ((end - start) >= item->size) { + item->data.longdata = start; + start += item->size; + return item->size; + } + } + } else { + item->format = HID_ITEM_FORMAT_SHORT; + item->size = b & 3; + switch (item->size) { + case 0: + return item->size; + case 1: + if ((end - start) >= 1) { + item->data.u8 = *start++; + return item->size; + } + break; + case 2: + if ((end - start) >= 2) { + item->data.u16 = swap_16((unsigned short *)start); + start+=2; + return item->size; + } + case 3: + item->size++; + if ((end - start) >= 4) { + item->data.u32 = swap_32((unsigned long *)start); + start+=4; + return item->size; + } + } + } + } + return -1; +} + +/* + * HID report descriptor item type (prefix bit 2,3) + */ + +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 +/* + * HID report descriptor main item tags + */ + +#define HID_MAIN_ITEM_TAG_INPUT 8 +#define HID_MAIN_ITEM_TAG_OUTPUT 9 +#define HID_MAIN_ITEM_TAG_FEATURE 11 +#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10 +#define HID_MAIN_ITEM_TAG_END_COLLECTION 12 +/* + * HID report descriptor main item contents + */ + +#define HID_MAIN_ITEM_CONSTANT 0x001 +#define HID_MAIN_ITEM_VARIABLE 0x002 +#define HID_MAIN_ITEM_RELATIVE 0x004 +#define HID_MAIN_ITEM_WRAP 0x008 +#define HID_MAIN_ITEM_NONLINEAR 0x010 +#define HID_MAIN_ITEM_NO_PREFERRED 0x020 +#define HID_MAIN_ITEM_NULL_STATE 0x040 +#define HID_MAIN_ITEM_VOLATILE 0x080 +#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100 + +/* + * HID report descriptor collection item types + */ + +#define HID_COLLECTION_PHYSICAL 0 +#define HID_COLLECTION_APPLICATION 1 +#define HID_COLLECTION_LOGICAL 2 +/* + * HID report descriptor global item tags + */ + +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0 +#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1 +#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2 +#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3 +#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4 +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5 +#define HID_GLOBAL_ITEM_TAG_UNIT 6 +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7 +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8 +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9 +#define HID_GLOBAL_ITEM_TAG_PUSH 10 +#define HID_GLOBAL_ITEM_TAG_POP 11 + +/* + * HID report descriptor local item tags + */ + +#define HID_LOCAL_ITEM_TAG_USAGE 0 +#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1 +#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5 +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7 +#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8 +#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9 +#define HID_LOCAL_ITEM_TAG_DELIMITER 10 + + + +static void usb_kbd_show_item(struct hid_item *item) +{ + switch(item->type) { + case HID_ITEM_TYPE_MAIN: + switch(item->tag) { + case HID_MAIN_ITEM_TAG_INPUT: + printf("Main Input"); + break; + case HID_MAIN_ITEM_TAG_OUTPUT: + printf("Main Output"); + break; + case HID_MAIN_ITEM_TAG_FEATURE: + printf("Main Feature"); + break; + case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: + printf("Main Begin Collection"); + break; + case HID_MAIN_ITEM_TAG_END_COLLECTION: + printf("Main End Collection"); + break; + default: + printf("Main reserved %d",item->tag); + break; + } + break; + case HID_ITEM_TYPE_GLOBAL: + switch(item->tag) { + case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: + printf("- Global Usage Page"); + break; + case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: + printf("- Global Logical Minimum"); + break; + case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: + printf("- Global Logical Maximum"); + break; + case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: + printf("- Global physical Minimum"); + break; + case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: + printf("- Global physical Maximum"); + break; + case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: + printf("- Global Unit Exponent"); + break; + case HID_GLOBAL_ITEM_TAG_UNIT: + printf("- Global Unit"); + break; + case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: + printf("- Global Report Size"); + break; + case HID_GLOBAL_ITEM_TAG_REPORT_ID: + printf("- Global Report ID"); + break; + case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: + printf("- Global Report Count"); + break; + case HID_GLOBAL_ITEM_TAG_PUSH: + printf("- Global Push"); + break; + case HID_GLOBAL_ITEM_TAG_POP: + printf("- Global Pop"); + break; + default: + printf("- Global reserved %d",item->tag); + break; + } + break; + case HID_ITEM_TYPE_LOCAL: + switch(item->tag) { + case HID_LOCAL_ITEM_TAG_USAGE: + printf("-- Local Usage"); + break; + case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: + printf("-- Local Usage Minimum"); + break; + case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: + printf("-- Local Usage Maximum"); + break; + case HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX: + printf("-- Local Designator Index"); + break; + case HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM: + printf("-- Local Designator Minimum"); + break; + case HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM: + printf("-- Local Designator Maximum"); + break; + case HID_LOCAL_ITEM_TAG_STRING_INDEX: + printf("-- Local String Index"); + break; + case HID_LOCAL_ITEM_TAG_STRING_MINIMUM: + printf("-- Local String Minimum"); + break; + case HID_LOCAL_ITEM_TAG_STRING_MAXIMUM: + printf("-- Local String Maximum"); + break; + case HID_LOCAL_ITEM_TAG_DELIMITER: + printf("-- Local Delimiter"); + break; + default: + printf("-- Local reserved %d",item->tag); + break; + } + break; + default: + printf("--- reserved %d",item->type); + break; + } + switch(item->size) { + case 1: + printf(" %d",item->data.u8); + break; + case 2: + printf(" %d",item->data.u16); + break; + case 4: + printf(" %ld",item->data.u32); + break; + } + printf("\n"); +} + + + +static int usb_kbd_get_hid_desc(struct usb_device *dev) +{ + unsigned char buffer[256]; + struct usb_descriptor_header *head; + struct usb_config_descriptor *config; + int index,len,i; + unsigned char *start, *end; + struct hid_item item; + + if(usb_get_configuration_no(dev,&buffer[0],0)==-1) + return -1; + head =(struct usb_descriptor_header *)&buffer[0]; + if(head->bDescriptorType!=USB_DT_CONFIG) { + printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType); + return -1; + } + index=head->bLength; + config=(struct usb_config_descriptor *)&buffer[0]; + len=swap_16(config->wTotalLength); + /* Ok the first entry must be a configuration entry, now process the others */ + head=(struct usb_descriptor_header *)&buffer[index]; + while(index+1 < len) { + if(head->bDescriptorType==USB_DT_HID) { + printf("HID desc found\n"); + memcpy(&usb_kbd_hid_desc,&buffer[index],buffer[index]); + usb_kbd_hid_desc.bcdHID=swap_16(usb_kbd_hid_desc.bcdHID); + usb_kbd_hid_desc.wDescriptorLength=swap_16(usb_kbd_hid_desc.wDescriptorLength); + usb_kbd_display_hid(&usb_kbd_hid_desc); + len=0; + break; + } + index+=head->bLength; + head=(struct usb_descriptor_header *)&buffer[index]; + } + if(len>0) + return -1; + len=usb_kbd_hid_desc.wDescriptorLength; + if((index = usb_get_class_descriptor(dev, 0, USB_DT_REPORT, 0, &buffer[0], len)) < 0) { + printf("reading report descriptor failed\n"); + return -1; + } + printf(" report descriptor (size %u, read %d)\n", len, index); + start=&buffer[0]; + end=&buffer[len]; + i=0; + do { + index=fetch_item(start,end,&item); + i+=index; + i++; + if(index>=0) + usb_kbd_show_item(&item); + + start+=index; + start++; + } while(index>=0); + +} + + +#endif + +#endif /* CONFIG_USB_KEYBOARD */ + +/* eof */ + diff --git a/common/usb_storage.c b/common/usb_storage.c new file mode 100644 index 0000000..9b84038 --- /dev/null +++ b/common/usb_storage.c @@ -0,0 +1,895 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * Most of this source has been derived from the Linux USB + * project. + * + * 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 + * + */ + +/* Note: + * Currently only the CBI transport protocoll has been implemented, and it + * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB + * transport protocoll may work as well. + */ + + + +#include +#include +#include + + +#if (CONFIG_COMMANDS & CFG_CMD_USB) +#include + +#ifdef CONFIG_USB_STORAGE + +#undef USB_STOR_DEBUG + +#ifdef USB_STOR_DEBUG +#define USB_STOR_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define USB_STOR_PRINTF(fmt,args...) +#endif + +#include +/* direction table -- this indicates the direction of the data + * transfer for each command code -- a 1 indicates input + */ +unsigned char us_direction[256/8] = { + 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, + 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) + +static unsigned char usb_stor_buf[512]; +static ccb usb_ccb; + +/* + * CBI style + */ + +#define US_CBI_ADSC 0 + + +#define USB_MAX_STOR_DEV 5 +static int usb_max_devs; /* number of highest available usb device */ + +static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV]; + +struct us_data; +typedef int (*trans_cmnd)(ccb*, struct us_data*); +typedef int (*trans_reset)(struct us_data*); + +struct us_data { + struct usb_device *pusb_dev; /* this usb_device */ + unsigned int flags; /* from filter initially */ + unsigned char ifnum; /* interface number */ + unsigned char ep_in; /* in endpoint */ + unsigned char ep_out; /* out ....... */ + unsigned char ep_int; /* interrupt . */ + unsigned char subclass; /* as in overview */ + unsigned char protocol; /* .............. */ + unsigned char attention_done; /* force attn on first cmd */ + unsigned short ip_data; /* interrupt data */ + int action; /* what to do */ + int ip_wanted; /* needed */ + int *irq_handle; /* for USB int requests */ + unsigned int irqpipe; /* pipe for release_irq */ + unsigned char irqmaxp; /* max packed for irq Pipe */ + unsigned char irqinterval; /* Intervall for IRQ Pipe */ + ccb *srb; /* current srb */ + trans_reset transport_reset; /* reset routine */ + trans_cmnd transport; /* transport routine */ +}; + +static struct us_data usb_stor[USB_MAX_STOR_DEV]; + + + +#define USB_STOR_TRANSPORT_GOOD 0 +#define USB_STOR_TRANSPORT_FAILED -1 +#define USB_STOR_TRANSPORT_ERROR -2 + + + + + + +int usb_stor_get_info(struct usb_device *dev, struct us_data *us, block_dev_desc_t *dev_desc); +int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss); +unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, unsigned long *buffer); +struct usb_device * usb_get_dev_index(int index); +void uhci_show_temp_int_td(void); + +block_dev_desc_t *usb_stor_get_dev(int index) +{ + return &usb_dev_desc[index]; +} + + +void usb_show_progress(void) +{ + printf("."); +} + +/********************************************************************************* + * (re)-scan the usb and reports device info + * to the user if mode = 1 + * returns current device or -1 if no + */ +int usb_stor_scan(int mode) +{ + unsigned char i; + struct usb_device *dev; + + if(mode==1) { + printf("scanning bus for storage devices...\n"); + } + usb_disable_asynch(1); /* asynch transfer not allowed */ + + for(i=0;i0) + return 0; + else + return-1; +} + +static int usb_stor_irq(struct usb_device *dev) +{ + struct us_data *us; + us=(struct us_data *)dev->privptr; + + if(us->ip_wanted) { + us->ip_wanted=0; + } + return 0; +} + + +#ifdef USB_STOR_DEBUG + +static void usb_show_srb(ccb * pccb) +{ + int i; + printf("SRB: len %d datalen 0x%lX\n ",pccb->cmdlen,pccb->datalen); + for(i=0;i<12;i++) { + printf("%02X ",pccb->cmd[i]); + } + printf("\n"); +} + +static void display_int_status(unsigned long tmp) +{ + printf("Status: %s %s %s %s %s %s %s\n", + (tmp & USB_ST_ACTIVE) ? "Active" : "", + (tmp & USB_ST_STALLED) ? "Stalled" : "", + (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "", + (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "", + (tmp & USB_ST_NAK_REC) ? "NAKed" : "", + (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "", + (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : ""); +} +#endif +/*********************************************************************** + * Data transfer routines + ***********************************************************************/ + +static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length) +{ + int max_size; + int this_xfer; + int result; + int partial; + int maxtry; + int stat; + + /* determine the maximum packet size for these transfers */ + max_size = usb_maxpacket(us->pusb_dev, pipe) * 16; + + /* while we have data left to transfer */ + while (length) { + + /* calculate how long this will be -- maximum or a remainder */ + this_xfer = length > max_size ? max_size : length; + length -= this_xfer; + + /* setup the retry counter */ + maxtry = 10; + + /* set up the transfer loop */ + do { + /* transfer the data */ + USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n", + (unsigned int)buf, this_xfer, 11 - maxtry); + result = usb_bulk_msg(us->pusb_dev, pipe, buf, + this_xfer, &partial, USB_CNTL_TIMEOUT*5); + USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n", + result, partial, this_xfer); + if(us->pusb_dev->status!=0) { + /* if we stall, we need to clear it before we go on */ +#ifdef USB_STOR_DEBUG + display_int_status(us->pusb_dev->status); +#endif + if (us->pusb_dev->status & USB_ST_STALLED) { + USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe); + stat = us->pusb_dev->status; + usb_clear_halt(us->pusb_dev, pipe); + us->pusb_dev->status=stat; + if(this_xfer == partial) { + USB_STOR_PRINTF("bulk transferred with error %X, but data ok\n",us->pusb_dev->status); + return 0; + } + else + return result; + } + if (us->pusb_dev->status & USB_ST_NAK_REC) { + USB_STOR_PRINTF("Device NAKed bulk_msg\n"); + return result; + } + if(this_xfer == partial) { + USB_STOR_PRINTF("bulk transferred with error %d, but data ok\n",us->pusb_dev->status); + return 0; + } + /* if our try counter reaches 0, bail out */ + USB_STOR_PRINTF("bulk transferred with error %d, data %d\n",us->pusb_dev->status,partial); + if (!maxtry--) + return result; + } + /* update to show what data was transferred */ + this_xfer -= partial; + buf += partial; + /* continue until this transfer is done */ + } while ( this_xfer ); + } + + /* if we get here, we're done and successful */ + return 0; +} + +/* FIXME: this reset function doesn't really reset the port, and it + * should. Actually it should probably do what it's doing here, and + * reset the port physically + */ +static int usb_stor_CB_reset(struct us_data *us) +{ + unsigned char cmd[12]; + int result; + + USB_STOR_PRINTF("CB_reset\n"); + memset(cmd, 0xFF, sizeof(cmd)); + cmd[0] = SCSI_SEND_DIAG; + cmd[1] = 4; + result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, cmd, sizeof(cmd), USB_CNTL_TIMEOUT*5); + + /* long wait for reset */ + wait_ms(1500); + USB_STOR_PRINTF("CB_reset result %d: status %X clearing endpoint halt\n",result,us->pusb_dev->status); + usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); + usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out)); + + USB_STOR_PRINTF("CB_reset done\n"); + return 0; +} + +/* FIXME: we also need a CBI_command which sets up the completion + * interrupt, and waits for it + */ +int usb_stor_CB_comdat(ccb *srb, struct us_data *us) +{ + int result; + int dir_in,retry; + unsigned int pipe; + unsigned long status; + + retry=5; + dir_in=US_DIRECTION(srb->cmd[0]); + + if(dir_in) + pipe=usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + else + pipe=usb_sndbulkpipe(us->pusb_dev, us->ep_out); + while(retry--) { + USB_STOR_PRINTF("CBI gets a command: Try %d\n",5-retry); +#ifdef USB_STOR_DEBUG + usb_show_srb(srb); +#endif + /* let's send the command via the control pipe */ + result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, + srb->cmd, srb->cmdlen, USB_CNTL_TIMEOUT*5); + USB_STOR_PRINTF("CB_transport: control msg returned %d, status %X\n",result,us->pusb_dev->status); + /* check the return code for the command */ + if (result < 0) { + if(us->pusb_dev->status & USB_ST_STALLED) { + status=us->pusb_dev->status; + USB_STOR_PRINTF(" stall during command found, clear pipe\n"); + usb_clear_halt(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0)); + us->pusb_dev->status=status; + } + USB_STOR_PRINTF(" error during command %02X Stat = %X\n",srb->cmd[0],us->pusb_dev->status); + return result; + } + /* transfer the data payload for this command, if one exists*/ + + USB_STOR_PRINTF("CB_transport: control msg returned %d, direction is %s to go 0x%lx\n",result,dir_in ? "IN" : "OUT",srb->datalen); + if (srb->datalen) { + result = us_one_transfer(us, pipe, srb->pdata,srb->datalen); + USB_STOR_PRINTF("CBI attempted to transfer data, result is %d status %lX, len %d\n", result,us->pusb_dev->status,us->pusb_dev->act_len); + if(!(us->pusb_dev->status & USB_ST_NAK_REC)) + break; + } /* if (srb->datalen) */ + else + break; + } + /* return result */ + + return result; +} + + +int usb_stor_CBI_get_status(ccb *srb, struct us_data *us) +{ + int timeout; + + us->ip_wanted=1; + submit_int_msg(us->pusb_dev,us->irqpipe, + (void *)&us->ip_data,us->irqmaxp ,us->irqinterval); + timeout=1000; + while(timeout--) { + if((volatile int *)us->ip_wanted==0) + break; + wait_ms(10); + } + if (us->ip_wanted) { + printf(" Did not get interrupt on CBI\n"); + us->ip_wanted = 0; + return USB_STOR_TRANSPORT_ERROR; + } + USB_STOR_PRINTF("Got interrupt data 0x%x, transfered %d status 0x%lX\n", us->ip_data,us->pusb_dev->irq_act_len,us->pusb_dev->irq_status); + /* UFI gives us ASC and ASCQ, like a request sense */ + if (us->subclass == US_SC_UFI) { + if (srb->cmd[0] == SCSI_REQ_SENSE || + srb->cmd[0] == SCSI_INQUIRY) + return USB_STOR_TRANSPORT_GOOD; /* Good */ + else + if (us->ip_data) + return USB_STOR_TRANSPORT_FAILED; + else + return USB_STOR_TRANSPORT_GOOD; + } + /* otherwise, we interpret the data normally */ + switch (us->ip_data) { + case 0x0001: + return USB_STOR_TRANSPORT_GOOD; + case 0x0002: + return USB_STOR_TRANSPORT_FAILED; + default: + return USB_STOR_TRANSPORT_ERROR; + } /* switch */ + return USB_STOR_TRANSPORT_ERROR; +} + +#define USB_TRANSPORT_UNKNOWN_RETRY 5 +#define USB_TRANSPORT_NOT_READY_RETRY 10 + +int usb_stor_CB_transport(ccb *srb, struct us_data *us) +{ + int result,status; + ccb *psrb; + ccb reqsrb; + int retry,notready; + + psrb=&reqsrb; + status=USB_STOR_TRANSPORT_GOOD; + retry=0; + notready=0; + /* issue the command */ +do_retry: + result=usb_stor_CB_comdat(srb,us); + USB_STOR_PRINTF("command / Data returned %d, status %X\n",result,us->pusb_dev->status); + /* if this is an CBI Protocol, get IRQ */ + if(us->protocol==US_PR_CBI) { + status=usb_stor_CBI_get_status(srb,us); + /* if the status is error, report it */ + if(status==USB_STOR_TRANSPORT_ERROR) { + USB_STOR_PRINTF(" USB CBI Command Error\n"); + return status; + } + srb->sense_buf[12]=(unsigned char)(us->ip_data>>8); + srb->sense_buf[13]=(unsigned char)(us->ip_data&0xff); + if(!us->ip_data) { + /* if the status is good, report it */ + if(status==USB_STOR_TRANSPORT_GOOD) { + USB_STOR_PRINTF(" USB CBI Command Good\n"); + return status; + } + } + } + /* do we have to issue an auto request? */ + /* HERE we have to check the result */ + if((result<0) && !(us->pusb_dev->status & USB_ST_STALLED)) { + USB_STOR_PRINTF("ERROR %X\n",us->pusb_dev->status); + us->transport_reset(us); + return USB_STOR_TRANSPORT_ERROR; + } + if((us->protocol==US_PR_CBI) && + ((srb->cmd[0]==SCSI_REQ_SENSE) || + (srb->cmd[0]==SCSI_INQUIRY))) { /* do not issue an autorequest after request sense */ + USB_STOR_PRINTF("No auto request and good\n"); + return USB_STOR_TRANSPORT_GOOD; + } + /* issue an request_sense */ + memset(&psrb->cmd[0],0,12); + psrb->cmd[0]=SCSI_REQ_SENSE; + psrb->cmd[1]=srb->lun<<5; + psrb->cmd[4]=18; + psrb->datalen=18; + psrb->pdata=&srb->sense_buf[0]; + psrb->cmdlen=12; + /* issue the command */ + result=usb_stor_CB_comdat(psrb,us); + USB_STOR_PRINTF("auto request returned %d\n",result); + /* if this is an CBI Protocol, get IRQ */ + if(us->protocol==US_PR_CBI) { + status=usb_stor_CBI_get_status(psrb,us); + } + if((result<0)&&!(us->pusb_dev->status & USB_ST_STALLED)) { + USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",us->pusb_dev->status); + return USB_STOR_TRANSPORT_ERROR; + } + USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]); + /* Check the auto request result */ + if((srb->sense_buf[2]==0) && + (srb->sense_buf[12]==0) && + (srb->sense_buf[13]==0)) /* ok, no sense */ + return USB_STOR_TRANSPORT_GOOD; + /* Check the auto request result */ + switch(srb->sense_buf[2]) { + case 0x01: /* Recovered Error */ + return USB_STOR_TRANSPORT_GOOD; + break; + case 0x02: /* Not Ready */ + if(notready++ > USB_TRANSPORT_NOT_READY_RETRY) { + printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X (NOT READY)\n", + srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]); + return USB_STOR_TRANSPORT_FAILED; + } + else { + wait_ms(100); + goto do_retry; + } + break; + default: + if(retry++ > USB_TRANSPORT_UNKNOWN_RETRY) { + printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X\n", + srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]); + return USB_STOR_TRANSPORT_FAILED; + } + else + goto do_retry; + break; + } + return USB_STOR_TRANSPORT_FAILED; +} + + + +static int usb_inquiry(ccb *srb,struct us_data *ss) +{ + int retry,i; + retry=3; + do { + memset(&srb->cmd[0],0,12); + srb->cmd[0]=SCSI_INQUIRY; + srb->cmd[1]=srb->lun<<5; + srb->cmd[4]=36; + srb->datalen=36; + srb->cmdlen=12; + i=ss->transport(srb,ss); + USB_STOR_PRINTF("inquiry returns %d\n",i); + if(i==0) + break; + }while(retry--); + if(!retry) { + printf("error in inquiry\n"); + return -1; + } + return 0; +} + +static int usb_request_sense(ccb *srb,struct us_data *ss) +{ + char *ptr; + return 0; + ptr=srb->pdata; + memset(&srb->cmd[0],0,12); + srb->cmd[0]=SCSI_REQ_SENSE; + srb->cmd[1]=srb->lun<<5; + srb->cmd[4]=18; + srb->datalen=18; + srb->pdata=&srb->sense_buf[0]; + srb->cmdlen=12; + ss->transport(srb,ss); + USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]); + srb->pdata=ptr; + return 0; +} + +static int usb_test_unit_ready(ccb *srb,struct us_data *ss) +{ + int retries=10; + do { + memset(&srb->cmd[0],0,12); + srb->cmd[0]=SCSI_TST_U_RDY; + srb->cmd[1]=srb->lun<<5; + srb->datalen=0; + srb->cmdlen=12; + if(ss->transport(srb,ss)==USB_STOR_TRANSPORT_GOOD) + { + return 0; + } + } while(retries--); + return -1; +} + +static int usb_read_capacity(ccb *srb,struct us_data *ss) +{ + int retry; + retry=2; /* retries */ + do { + memset(&srb->cmd[0],0,12); + srb->cmd[0]=SCSI_RD_CAPAC; + srb->cmd[1]=srb->lun<<5; + srb->datalen=8; + srb->cmdlen=12; + if(ss->transport(srb,ss)==USB_STOR_TRANSPORT_GOOD) { + return 0; + } + }while(retry--); + return -1; +} + +static int usb_read_10(ccb *srb,struct us_data *ss, unsigned long start, unsigned short blocks) +{ + memset(&srb->cmd[0],0,12); + srb->cmd[0]=SCSI_READ10; + srb->cmd[1]=srb->lun<<5; + srb->cmd[2]=((unsigned char) (start>>24))&0xff; + srb->cmd[3]=((unsigned char) (start>>16))&0xff; + srb->cmd[4]=((unsigned char) (start>>8))&0xff; + srb->cmd[5]=((unsigned char) (start))&0xff; + srb->cmd[7]=((unsigned char) (blocks>>8))&0xff; + srb->cmd[8]=(unsigned char) blocks & 0xff; + srb->cmdlen=12; + USB_STOR_PRINTF("read10: start %lx blocks %x\n",start,blocks); + return ss->transport(srb,ss); +} + + +#define USB_MAX_READ_BLK 20 + +unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, unsigned long *buffer) +{ + unsigned long start,blks, buf_addr; + unsigned short smallblks; + struct usb_device *dev; + int retry,i; + ccb *srb=&usb_ccb; + device&=0xff; + /* Setup device + */ + USB_STOR_PRINTF("\nusb_read: dev %d \n",device); + dev=NULL; + for(i=0;idevnum==usb_dev_desc[device].target) + break; + } + + usb_disable_asynch(1); /* asynch transfer not allowed */ + srb->lun=usb_dev_desc[device].lun; + buf_addr=(unsigned long)buffer; + start=blknr; + blks=blkcnt; + if(usb_test_unit_ready(srb,(struct us_data *)dev->privptr)) { + printf("Device NOT ready\n Request Sense returned %02X %02X %02X\n", + srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]); + return 0; + } + USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx buffer %lx\n",device,start,blks, buf_addr); + do { + retry=2; + srb->pdata=(unsigned char *)buf_addr; + if(blks>USB_MAX_READ_BLK) { + smallblks=USB_MAX_READ_BLK; + } + else { + smallblks=(unsigned short) blks; + } +retry_it: + if(smallblks==USB_MAX_READ_BLK) + usb_show_progress(); + srb->datalen=usb_dev_desc[device].blksz * smallblks; + srb->pdata=(unsigned char *)buf_addr; + if(usb_read_10(srb,(struct us_data *)dev->privptr, start, smallblks)) { + USB_STOR_PRINTF("Read ERROR\n"); + usb_request_sense(srb,(struct us_data *)dev->privptr); + if(retry--) + goto retry_it; + blkcnt-=blks; + break; + } + start+=smallblks; + blks-=smallblks; + buf_addr+=srb->datalen; + } while(blks!=0); + USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr); + usb_disable_asynch(0); /* asynch transfer allowed */ + if(blkcnt>=USB_MAX_READ_BLK) + printf("\n"); + return(blkcnt); +} + + +/* Probe to see if a new device is actually a Storage device */ +int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss) +{ + struct usb_interface_descriptor *iface; + int i; + unsigned int flags = 0; + + int protocol = 0; + int subclass = 0; + + + memset(ss, 0, sizeof(struct us_data)); + + /* let's examine the device now */ + iface = &dev->config.if_desc[ifnum]; + +#if 0 + /* this is the place to patch some storage devices */ + USB_STOR_PRINTF("iVendor %X iProduct %X\n",dev->descriptor.idVendor,dev->descriptor.idProduct); + if ((dev->descriptor.idVendor) == 0x066b && (dev->descriptor.idProduct) == 0x0103) { + USB_STOR_PRINTF("patched for E-USB\n"); + protocol = US_PR_CB; + subclass = US_SC_UFI; /* an assumption */ + } +#endif + + if (dev->descriptor.bDeviceClass != 0 || + iface->bInterfaceClass != USB_CLASS_MASS_STORAGE || + iface->bInterfaceSubClass < US_SC_MIN || + iface->bInterfaceSubClass > US_SC_MAX) { + /* if it's not a mass storage, we go no further */ + return 0; + } + + /* At this point, we know we've got a live one */ + USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n"); + + /* Initialize the us_data structure with some useful info */ + ss->flags = flags; + ss->ifnum = ifnum; + ss->pusb_dev = dev; + ss->attention_done = 0; + + /* If the device has subclass and protocol, then use that. Otherwise, + * take data from the specific interface. + */ + if (subclass) { + ss->subclass = subclass; + ss->protocol = protocol; + } else { + ss->subclass = iface->bInterfaceSubClass; + ss->protocol = iface->bInterfaceProtocol; + } + + /* set the handler pointers based on the protocol */ + USB_STOR_PRINTF("Transport: "); + switch (ss->protocol) { + case US_PR_CB: + USB_STOR_PRINTF("Control/Bulk\n"); + ss->transport = usb_stor_CB_transport; + ss->transport_reset = usb_stor_CB_reset; + break; + + case US_PR_CBI: + USB_STOR_PRINTF("Control/Bulk/Interrupt\n"); + ss->transport = usb_stor_CB_transport; + ss->transport_reset = usb_stor_CB_reset; + break; + default: + printf("USB Starage Transport unknown / not yet implemented\n"); + return 0; + break; + } + + /* + * We are expecting a minimum of 2 endpoints - in and out (bulk). + * An optional interrupt is OK (necessary for CBI protocol). + * We will ignore any others. + */ + for (i = 0; i < iface->bNumEndpoints; i++) { + /* is it an BULK endpoint? */ + if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK) { + if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN) + ss->ep_in = iface->ep_desc[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + else + ss->ep_out = iface->ep_desc[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + } + + /* is it an interrupt endpoint? */ + if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT) { + ss->ep_int = iface->ep_desc[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + ss->irqinterval = iface->ep_desc[i].bInterval; + } + } + USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n", + ss->ep_in, ss->ep_out, ss->ep_int); + + /* Do some basic sanity checks, and bail if we find a problem */ + if (usb_set_interface(dev, iface->bInterfaceNumber, 0) || + !ss->ep_in || !ss->ep_out || + (ss->protocol == US_PR_CBI && ss->ep_int == 0)) { + USB_STOR_PRINTF("Problems with device\n"); + return 0; + } + /* set class specific stuff */ + /* We only handle certain protocols. Currently, this is + * the only one. + */ + if (ss->subclass != US_SC_UFI) { + printf("Sorry, protocol %d not yet supported.\n",ss->subclass); + return 0; + } + if(ss->ep_int) /* we had found an interrupt endpoint, prepare irq pipe */ + { + /* set up the IRQ pipe and handler */ + + ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255; + ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); + ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe); + dev->irq_handle=usb_stor_irq; + dev->privptr=(void *)ss; + } + return 1; +} + +int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t *dev_desc) +{ + unsigned char perq,modi; + unsigned long cap[2]; + unsigned long *capacity,*blksz; + ccb *pccb=&usb_ccb; + + ss->transport_reset(ss); + pccb->pdata=usb_stor_buf; + + dev_desc->target=dev->devnum; + pccb->lun=dev_desc->lun; + USB_STOR_PRINTF(" address %d\n",dev_desc->target); + + if(usb_inquiry(pccb,ss)) + return -1; + perq=usb_stor_buf[0]; + modi=usb_stor_buf[1]; + if((perq & 0x1f)==0x1f) { + return 0; /* skip unknown devices */ + } + if((modi&0x80)==0x80) {/* drive is removable */ + dev_desc->removable=1; + } + memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8); + memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16); + memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4); + dev_desc->vendor[8]=0; + dev_desc->product[16]=0; + dev_desc->revision[4]=0; + USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n",usb_stor_buf[2],usb_stor_buf[3]); + if(usb_test_unit_ready(pccb,ss)) { + printf("Device NOT ready\n Request Sense returned %02X %02X %02X\n",pccb->sense_buf[2],pccb->sense_buf[12],pccb->sense_buf[13]); + if(dev_desc->removable==1) { + dev_desc->type=perq; + return 1; + } + else + return 0; + } + pccb->pdata=(unsigned char *)&cap[0]; + memset(pccb->pdata,0,8); + if(usb_read_capacity(pccb,ss)!=0) { + printf("READ_CAP ERROR\n"); + cap[0]=2880; + cap[1]=0x200; + } + USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n",cap[0],cap[1]); +#if 0 + if(cap[0]>(0x200000 * 10)) /* greater than 10 GByte */ + cap[0]>>=16; +#endif + cap[0]+=1; + capacity=&cap[0]; + blksz=&cap[1]; + USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",*capacity,*blksz); + dev_desc->lba=*capacity; + dev_desc->blksz=*blksz; + dev_desc->type=perq; + USB_STOR_PRINTF(" address %d\n",dev_desc->target); + USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type); + + init_part(dev_desc); + + USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type); + return 1; +} + +#endif +#endif /* CONFIG_USB_STORAGE */ + + + diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c index 8cc3ddd..030e497 100644 --- a/cpu/ppc4xx/405gp_pci.c +++ b/cpu/ppc4xx/405gp_pci.c @@ -68,7 +68,7 @@ #include <405gp_pci.h> #include -#ifndef CONFIG_PIP405 +#if !(defined(CONFIG_PIP405) || defined (CONFIG_MIP405)) void pciinfo(int bus_no); diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c index 4cb5246..aa2b38f 100644 --- a/cpu/ppc4xx/i2c.c +++ b/cpu/ppc4xx/i2c.c @@ -109,8 +109,9 @@ int i2c_transfer(unsigned char command_is_reading, unsigned char address, int bytes_transfered; int result; int status; - int i, TimeReady, TimeOut; + int i, TimeReady; ulong freqOPB,freqProc; + ulong TimeOut; /* _must_ be unsigned long for fast speeds */ result = IIC_OK; bytes_transfered = 0; @@ -146,8 +147,9 @@ int i2c_transfer(unsigned char command_is_reading, unsigned char address, /* IIC time out => wait for TimeOut cycles */ /* TimeOut /= 2; because waiting-loop is 2-instruction loop */ - TimeOut = freqProc*IIC_TIMEOUT*10; - TimeOut /= 2; + /* Take care we get no overflow (266MHz = 0x0FDAD680) first divide */ + TimeOut = freqProc/2; + TimeOut *= IIC_TIMEOUT*10; while ((bytes_transfered < size_to_transfer) && (result == IIC_OK)) { diff --git a/disk/part.c b/disk/part.c index 2e93894..59ca1f4 100644 --- a/disk/part.c +++ b/disk/part.c @@ -36,33 +36,22 @@ #if (CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI) -/* stdlib.h causes some compatibility problems; should fixe these! -- wd */ -#ifndef __ldiv_t_defined -typedef struct { - long int quot; /* Quotient */ - long int rem; /* Remainder */ -} ldiv_t; -extern ldiv_t ldiv (long int __numer, long int __denom); -# define __ldiv_t_defined 1 -#endif - - /* ------------------------------------------------------------------------- */ /* * reports device info to the user */ -void dev_print(block_dev_desc_t *dev_desc) +void dev_print (block_dev_desc_t *dev_desc) { - ldiv_t mb, gb; ulong lba512; /* number of blocks if 512bytes block size */ + if (dev_desc->type==DEV_TYPE_UNKNOWN) { - printf("not available\n"); + puts ("not available\n"); return; } - if(dev_desc->if_type==IF_TYPE_SCSI) { + if (dev_desc->if_type==IF_TYPE_SCSI) { printf ("(%d:%d) ", dev_desc->target,dev_desc->lun); } - if(dev_desc->if_type==IF_TYPE_IDE) { + if (dev_desc->if_type==IF_TYPE_IDE) { printf ("Model: %s Firm: %s Ser#: %s\n", dev_desc->vendor, dev_desc->revision, @@ -73,40 +62,43 @@ void dev_print(block_dev_desc_t *dev_desc) dev_desc->product, dev_desc->revision); } - printf(" Type: "); - if(dev_desc->removable) - printf ("Removable "); - switch(dev_desc->type & 0x1F) { - case DEV_TYPE_HARDDISK: printf("Hard Disk"); + puts (" Type: "); + if (dev_desc->removable) + puts ("Removable "); + switch (dev_desc->type & 0x1F) { + case DEV_TYPE_HARDDISK: puts ("Hard Disk"); break; - case DEV_TYPE_CDROM: printf("CD ROM"); + case DEV_TYPE_CDROM: puts ("CD ROM"); break; - case DEV_TYPE_OPDISK: printf("Optical Device"); + case DEV_TYPE_OPDISK: puts ("Optical Device"); break; - case DEV_TYPE_TAPE: printf("Tape"); + case DEV_TYPE_TAPE: puts ("Tape"); break; - default: printf("# %02X #", dev_desc->type & 0x1F); + default: printf ("# %02X #", dev_desc->type & 0x1F); break; } - printf("\n"); - if((dev_desc->lba * dev_desc->blksz)>0L) { - lba512=(dev_desc->lba * (dev_desc->blksz/512)); - mb = ldiv(lba512, 2048); /* (1024 *1024 / 512 MB */ + puts ("\n"); + if ((dev_desc->lba * dev_desc->blksz)>0L) { + ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem; + + lba512 = (dev_desc->lba * (dev_desc->blksz/512)); + + mb = (10 * lba512) / 2048; /* 2048 = (1024 * 1024) / 512 MB */ /* round to 1 digit */ - mb.rem *= 10 * 512; - mb.rem += 512 * 1024; - mb.rem /= 1024 * 1024; - gb = ldiv(10 * mb.quot + mb.rem, 10240); - gb.rem += 512; - gb.rem /= 1024; + mb_quot = mb / 10; + mb_rem = mb - (10 * mb_quot); + + gb = mb / 1024; + gb_quot = gb / 10; + gb_rem = gb - (10 * gb_quot); + printf (" Capacity: %ld.%ld MB = %ld.%ld GB (%ld x %ld)\n", - mb.quot, mb.rem, - gb.quot, gb.rem, + mb_quot, mb_rem, + gb_quot, gb_rem, dev_desc->lba, dev_desc->blksz); - } - else { - printf (" Capacity: not available\n"); + } else { + puts (" Capacity: not available\n"); } } @@ -141,9 +133,9 @@ void init_part (block_dev_desc_t * dev_desc) } -int get_partition_info(block_dev_desc_t *dev_desc, int part, disk_partition_t *info) +int get_partition_info (block_dev_desc_t *dev_desc, int part, disk_partition_t *info) { - switch(dev_desc->part_type) { + switch (dev_desc->part_type) { #ifdef CONFIG_MAC_PARTITION case PART_TYPE_MAC: if (get_partition_info_mac(dev_desc,part,info) == 0) { @@ -178,25 +170,25 @@ int get_partition_info(block_dev_desc_t *dev_desc, int part, disk_partition_t *i static void print_part_header (const char *type, block_dev_desc_t * dev_desc) { - printf ("\nPartition Map for "); - switch(dev_desc->if_type) { - case IF_TYPE_IDE: printf("IDE"); + puts ("\nPartition Map for "); + switch (dev_desc->if_type) { + case IF_TYPE_IDE: puts ("IDE"); break; - case IF_TYPE_SCSI: printf("SCSI"); + case IF_TYPE_SCSI: puts ("SCSI"); break; - case IF_TYPE_ATAPI: printf("ATAPI"); + case IF_TYPE_ATAPI: puts ("ATAPI"); break; - default: printf("UNKNOWN"); + default: puts ("UNKNOWN"); break; } - printf(" device %d -- Partition Type: %s\n\n", + printf (" device %d -- Partition Type: %s\n\n", dev_desc->dev, type); } void print_part (block_dev_desc_t * dev_desc) { - switch(dev_desc->part_type) { + switch (dev_desc->part_type) { #ifdef CONFIG_MAC_PARTITION case PART_TYPE_MAC: PRINTF ("## Testing for valid MAC partition ##\n"); @@ -220,7 +212,7 @@ void print_part (block_dev_desc_t * dev_desc) return; #endif } - printf ("## Unknown partition table\n"); + puts ("## Unknown partition table\n"); } diff --git a/doc/README.commands b/doc/README.commands index 44552c7..c19e1f5 100644 --- a/doc/README.commands +++ b/doc/README.commands @@ -87,5 +87,7 @@ spiinfo 3 stack 5 step 4 tftpboot 4 +usbboot 5 +usb 4 version 4 ? 1 diff --git a/doc/README.usb b/doc/README.usb new file mode 100644 index 0000000..fa5fbec --- /dev/null +++ b/doc/README.usb @@ -0,0 +1,80 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + */ + +USB Support for PIP405 and MIP405 (UHCI) +======================================== + +The USB support is implemented on the base of the UHCI Host +controller. + +Currently supported are USB Hubs, USB Keyboards and USB Floppys. +Tested with a TEAC Floppy TEAC FD-05PUB and Chicony KU-8933 Keyboard. + +How it works: +------------- + +The USB (at least the USB UHCI) needs a frame list (4k), transfer +descripor and queue headers which are all located in the main memory. +The UHCI allocates every milisecond the PCI bus and reads the current +frame pointer. This may cause to crash the OS during boot. So the USB +_MUST_ be stopped during OS boot. This is the reason, why the USB is +NOT automatically started during start-up. If someone needs the USB +he has to start it and should therefore be aware that he had to stop +it before booting the OS. + +For USB keyboards this can be done by a script which is automatically +started after the ppcboot is up and running. To boot an OS with a an +USB keyboard another script is necessary, which first disables the +USB and then executes the boot command. If the boot command fails, +the script can reenable the USB kbd. + +Common USB Commands: +- usb start: +- usb reset: (re)starts the USB. All USB devices will be + initialized and a device tree is build for them. +- usb tree: shows all USB devices in a tree like display +- usb info [dev]: shows all USB infos of the device dev, or of all + the devices +- usb stop [f]: stops the USB. If f==1 the USB will also stop if + an USB keyboard is assigned as stdin. The stdin + is then switched to serial input. +Storage USB Commands: +- usb scan: scans the USB for storage devices.The USB must be + running for this command (usb start) +- usb device [dev]: show or set current USB staorage device +- usb part [dev]: print partition table of one or all USB storage + devices +- usb read addr blk# cnt: + read `cnt' blocks starting at block `blk#'to + memory address `addr' +- usbboot addr dev:part: + boot from USB device + +Config Switches: +---------------- +CFG_CMD_USB enables basic USB support and the usb command +CONFIG_USB_UHCI defines the lowlevel part.A lowlevel part must be defined if + using CFG_CMD_USB +CONFIG_USB_KEYBOARD enables the USB Keyboard +CONFIG_USB_STORAGE enables the USB storage devices diff --git a/include/cmd_bsp.h b/include/cmd_bsp.h index 570a3a8..cbe6a92 100644 --- a/include/cmd_bsp.h +++ b/include/cmd_bsp.h @@ -79,6 +79,20 @@ int do_pip405 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]); #endif /* CONFIG_PIP405 */ /* ----------------------------------------------------------------------------*/ +/* ----- MIP405 ----------------------------------------------------------------- + */ +#if defined(CONFIG_MIP405) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "mip405", 4, 6, 1, do_mip405, \ + "mip405 - MIP405 specific Cmds\n", \ + "flash mem [SrcAddr] - updates PPCBOOT with image in memory\n" \ + "mip405 flash mps - updates PPCBOOT with image from MPS\n" \ +), +int do_mip405 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]); + +#endif /* CONFIG_MIP405 */ +/* ----------------------------------------------------------------------------*/ /* ----- DASA_SIM --------------------------------------------------------------- */ diff --git a/include/cmd_confdefs.h b/include/cmd_confdefs.h index 2e339c0..8242930 100644 --- a/include/cmd_confdefs.h +++ b/include/cmd_confdefs.h @@ -66,6 +66,7 @@ #define CFG_CMD_ELF 0x0000000100000000 /* ELF (VxWorks) load/boot cmd */ #define CFG_CMD_MISC 0x0000000200000000 /* Misc functions like sleep etc*/ +#define CFG_CMD_USB 0x0000000400000000 /* USB Support */ #define CFG_CMD_ALL 0xFFFFFFFFFFFFFFFF /* ALL commands */ @@ -89,6 +90,7 @@ CFG_CMD_DATE | \ CFG_CMD_BEDBUG | \ CFG_CMD_ELF | \ + CFG_CMD_USB | \ CFG_CMD_MII | \ CFG_CMD_BSP ) diff --git a/include/cmd_usb.h b/include/cmd_usb.h new file mode 100644 index 0000000..f1917d7 --- /dev/null +++ b/include/cmd_usb.h @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 _CMD_USB_H +#define _CMD_USB_H + +#include +#include + + +#if (CONFIG_COMMANDS & CFG_CMD_USB) + +#ifdef CONFIG_USB_STORAGE +#define CMD_TBL_USB MK_CMD_TBL_ENTRY( \ + "usb", 4, 5, 1, do_usb, \ + "usb - USB sub-system\n", \ + "reset - reset (rescan) USB controller\n" \ + "usb stop [f] - stop USB [f]=force stop\n" \ + "usb tree - show USB device tree\n" \ + "usb info [dev] - show available USB devices\n" \ + "usb scan - (re-)scan USB bus for storage devices\n" \ + "usb device [dev] - show or set current USB staorage device\n" \ + "usb part [dev] - print partition table of one or all USB storage devices\n" \ + "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"\ + " to memory address `addr'\n" \ +), + + +#define CMD_TBL_USBBOOT MK_CMD_TBL_ENTRY( \ + "usbboot", 5, 3, 1, do_usbboot, \ + "usbboot - boot from USB device\n", \ + "loadAddr dev:part\n" \ +), + +#else +#define CMD_TBL_USB MK_CMD_TBL_ENTRY( \ + "usb", 4, 5, 1, do_usb, \ + "usb - USB sub-system\n", \ + "reset - reset (rescan) USB controller\n" \ + "usb tree - show USB device tree\n" \ + "usb info [dev] - show available USB devices\n" \ +), + +#define CMD_TBL_USBBOOT +#endif + +int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]); +int do_usbboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]); + + +#else +#define CMD_TBL_USB +#define CMD_TBL_USBBOOT +#endif + +#endif /* _CMD_SCSI_H */ + diff --git a/include/config_LANTEC.h b/include/config_LANTEC.h index fefc7fd..1be4dce 100644 --- a/include/config_LANTEC.h +++ b/include/config_LANTEC.h @@ -95,6 +95,7 @@ & ~CFG_CMD_MII \ & ~CFG_CMD_PCI \ & ~CFG_CMD_PCMCIA \ + & ~CFG_CMD_USB \ & ~CFG_CMD_SCSI ) #if CONFIG_LANTEC >= 2 diff --git a/include/config_MIP405.h b/include/config_MIP405.h new file mode 100644 index 0000000..3e155de --- /dev/null +++ b/include/config_MIP405.h @@ -0,0 +1,339 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.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 + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/*********************************************************** + * High Level Configuration Options + * (easy to change) + ***********************************************************/ +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_MIP405 1 /* ...on a MIP405 board */ +/*********************************************************** + * Clock + ***********************************************************/ +#define CONFIG_SYS_CLK_FREQ 33000000 /* external frequency to pll */ + +/*********************************************************** + * Command definitions + ***********************************************************/ +#define CONFIG_COMMANDS \ + (CONFIG_CMD_DFL | \ + CFG_CMD_IDE | \ + CFG_CMD_DHCP | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_EEPROM | \ + CFG_CMD_I2C | \ + CFG_CMD_REGINFO | \ + CFG_CMD_DATE | \ + CFG_CMD_ELF | \ + CFG_CMD_USB | \ + CFG_CMD_MII | \ + CFG_CMD_BSP ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +/************************************************************** + * I2C Stuff: + * the PIP405 is equiped with an Atmel 24C128/256 EEPROM at address + * 0x53. + * Caution: on the same bus is the SPD (Serial Presens Detect + * EEPROM of the SDRAM + * The Atmel EEPROM uses 16Bit addressing. + ***************************************************************/ +#define CONFIG_I2C405 +#define CONFIG_I2C +#define CONFIG_I2C_X +#define CFG_I2C_EEPROM_ADDR 0x53 +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x00000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x00800 /* 2k bytes may be used for env vars */ +/* The Atmel 24C128/256 has 64 byte page write mode using last 6 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_BITS 6 +#define CFG_EEPROM_PAGE_WRITE_ENABLE /* enable Page write */ +/*************************************************************** + * Definitions for Serial Presence Detect EEPROM address + * (to get SDRAM settings) + ***************************************************************/ +#define SDRAM_EEPROM_WRITE_ADDRESS 0xA0 +#define SDRAM_EEPROM_READ_ADDRESS 0xA1 + +/************************************************************** + * Environment definitions + **************************************************************/ +#define CONFIG_BAUDRATE 9600 /* STD Baudrate */ +#define CONFIG_BOOTDELAY -1 /* no autoboot */ + +#define CONFIG_BOOTCOMMAND "diskboot 200000 0:1; bootm" /* autoboot command */ +#define CONFIG_BOOTARGS "console=ttyS0,9600 root=/dev/hda5" /* boot arguments */ + +#define CONFIG_IPADDR 10.0.0.100 +#define CONFIG_SERVERIP 10.0.0.1 + +/*************************************************************** + * defines if the console is stored in the environment + ***************************************************************/ +#define CFG_CONSOLE_IS_IN_ENV /* stdin, stdout and stderr are in evironment */ +/*************************************************************** + * defines if an overwrite_console function exists + *************************************************************/ +#define CFG_CONSOLE_OVERWRITE_ROUTINE +#define CFG_CONSOLE_INFO_QUIET +/*************************************************************** + * defines if the overwrite_console should be stored in the + * environment + **************************************************************/ +#undef CFG_CONSOLE_ENV_OVERWRITE + +/************************************************************** + * loads config + *************************************************************/ +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MISC_INIT_R +/*********************************************************** + * Miscellaneous configurable options + **********************************************************/ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#undef CFG_EXT_SERIAL_CLOCK /* no external serial clock used */ + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x200000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_HOST /* configure as pci-host */ +#define CONFIG_PCI_PNP /* pci plug-and-play */ + /* resource configuration */ +#define CFG_PCI_SUBSYS_VENDORID 0x0000 /* PCI Vendor ID: to-do!!! */ +#define CFG_PCI_SUBSYS_DEVICEID 0x0000 /* PCI Device ID: to-do!!! */ +#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ +#define CFG_PCI_PTM1MS 0x80000001 /* 2GB, enable hard-wired to 1 */ +#define CFG_PCI_PTM2LA 0x00000000 /* disabled */ +#define CFG_PCI_PTM2MS 0x00000000 /* disabled */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFF80000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (512 * 1024) /* Reserve 512 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 16 /* For all MPC8xx CPUs */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 4 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + */ + +#define FLASH_BASE0_PRELIM 0xFFC00000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0 /* FLASH bank #1 */ + +#define CONFIG_BOARD_PRE_INIT + +/* On Chip Memory location */ +#define OCM_DATA_ADDR 0xF0000000 + +/* Peripheral Bus Mapping */ +#define PER_PLD_ADDR 0xF4000000 /* smallest window is 1MByte 0x10 0000*/ +#define PER_UART0_ADDR 0xF4100000 /* smallest window is 1MByte 0x10 0000*/ +#define PER_UART1_ADDR 0xF4200000 /* smallest window is 1MByte 0x10 0000*/ + +#define MULTI_PURPOSE_SOCKET_ADDR 0xF8000000 + + + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in On Chip SRAM) + */ +#define CFG_INIT_RAM_ADDR OCM_DATA_ADDR /* inside of On Chip SRAM */ +#define CFG_INIT_RAM_END 0x1000 /* End of On Chip SRAM */ +#define CFG_INIT_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_INIT_DATA_OFFSET (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_INIT_DATA_OFFSET + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +/*********************************************************************** + * External peripheral base address + ***********************************************************************/ +#define CFG_ISA_IO_BASE_ADDRESS 0xE8000000 + +/*********************************************************************** + * Last Stage Init + ***********************************************************************/ +#define CONFIG_LAST_STAGE_INIT +/************************************************************ + * Ethernet Stuff + ***********************************************************/ +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 1 /* PHY address */ + +/************************************************************ + * RTC + ***********************************************************/ +#define CONFIG_RTC_MC146818 +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +/************************************************************ + * IDE/ATA stuff + ************************************************************/ +#define CFG_IDE_MAXBUS 2 /* max. 2 IDE busses */ +#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */ + +#define CFG_ATA_BASE_ADDR CFG_ISA_IO_BASE_ADDRESS /* base address */ +#define CFG_ATA_IDE0_OFFSET 0x01F0 /* ide0 offste */ +#define CFG_ATA_IDE1_OFFSET 0x0170 /* ide1 offset */ +#define CFG_ATA_DATA_OFFSET 0 /* data reg offset */ +#define CFG_ATA_REG_OFFSET 0 /* reg offset */ +#define CFG_ATA_ALT_OFFSET 0x200 /* alternate register offset */ + +#undef CONFIG_IDE_PCMCIA /* no pcmcia interface required */ +#undef CONFIG_IDE_LED /* no led for ide supported */ +#define CONFIG_IDE_RESET /* reset for ide supported... */ +#define CONFIG_IDE_RESET_ROUTINE /* with a special reset function */ + +/************************************************************ + * ATAPI support (experimental) + ************************************************************/ +#define CONFIG_ATAPI /* enable ATAPI Support */ + +/************************************************************ + * SCSI support (experimental) only SYM53C8xx supported + ************************************************************/ +#undef CONFIG_SCSI_SYM53C8XX + +#ifdef CONFIG_SCSI_SYM53C8XX +#define CFG_SCSI_MAX_LUN 8 /* number of supported LUNs */ +#define CFG_SCSI_MAX_SCSI_ID 7 /* maximum SCSI ID (0..6) */ +#define CFG_SCSI_MAX_DEVICE CFG_SCSI_MAX_SCSI_ID * CFG_SCSI_MAX_LUN /* maximum Target devices */ +#endif /* CONFIG_SCSI_SYM53C8XX */ +/************************************************************ + * DISK Partition support + ************************************************************/ +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION /* Experimental */ + +/************************************************************ + * Keyboard support + ************************************************************/ +#undef CONFIG_ISA_KEYBOARD + +/************************************************************ + * Video support + ************************************************************/ +#undef CONFIG_VIDEO /*To enable video controller support */ +#undef CONFIG_VIDEO_CT69000 + +/************************************************************ + * USB support EXPERIMENTAL + ************************************************************/ +#define CONFIG_USB_UHCI +#define CONFIG_USB_KEYBOARD +#define CONFIG_USB_STORAGE + +/* Enable needed helper functions */ +#define CFG_DEVICE_DEREGISTER /* needs device_deregister */ + +/************************************************************ + * Debug support + ************************************************************/ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE 230400 /* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */ +#endif + +/************************************************************ + * Ident + ************************************************************/ +#define VERSION_TAG "REL_1_1_1" +#define CONFIG_IDENT_STRING "\n(c) 2001 by MPL AG Switzerland, MEV-10072-001 " VERSION_TAG + + +#endif /* __CONFIG_H */ diff --git a/include/config_MPC8260ADS.h b/include/config_MPC8260ADS.h index 8688c19..b412bd1 100644 --- a/include/config_MPC8260ADS.h +++ b/include/config_MPC8260ADS.h @@ -91,6 +91,7 @@ CFG_CMD_EEPROM | \ CFG_CMD_FDC | \ CFG_CMD_IDE | \ + CFG_CMD_USB | \ CFG_CMD_KGDB | \ CFG_CMD_MII | \ CFG_CMD_PCI | \ diff --git a/include/config_PIP405.h b/include/config_PIP405.h index 64f654c..e6a1a9b 100644 --- a/include/config_PIP405.h +++ b/include/config_PIP405.h @@ -44,30 +44,43 @@ * Command definitions ***********************************************************/ #define CONFIG_COMMANDS \ - (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_IRQ | \ - CFG_CMD_DATE | CFG_CMD_IDE | CFG_CMD_BSP | \ - CFG_CMD_FDC | CFG_CMD_SCSI ) - + (CONFIG_CMD_DFL | \ + CFG_CMD_IDE | \ + CFG_CMD_DHCP | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_EEPROM | \ + CFG_CMD_I2C | \ + CFG_CMD_REGINFO | \ + CFG_CMD_FDC | \ + CFG_CMD_SCSI | \ + CFG_CMD_DATE | \ + CFG_CMD_ELF | \ + CFG_CMD_USB | \ + CFG_CMD_MII | \ + CFG_CMD_BSP ) /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include - +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " /************************************************************** * I2C Stuff: * the PIP405 is equiped with an Atmel 24C128/256 EEPROM at address - * 0x53. + * 0x53. * Caution: on the same bus is the SPD (Serial Presens Detect * EEPROM of the SDRAM * The Atmel EEPROM uses 16Bit addressing. - ***************************************************************/ + ***************************************************************/ #define CONFIG_I2C_X +#define CONFIG_I2C405 #define CFG_I2C_EEPROM_ADDR 0x53 #define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ #define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ #define CFG_ENV_SIZE 0x200 /* 512 bytes may be used for env vars */ /* The Atmel 24C128/256 has 64 byte page write mode using last 6 bits of the address */ -#define CFG_EEPROM_PAGE_WRITE_BITS 6 -#define CFG_EEPROM_PAGE_WRITE_ENABLE /* enable Page write */ +#define CFG_EEPROM_PAGE_WRITE_BITS 6 +#define CFG_EEPROM_PAGE_WRITE_ENABLE /* enable Page write */ /*************************************************************** * Definitions for Serial Presence Detect EEPROM address * (to get SDRAM settings) @@ -75,6 +88,7 @@ #define SDRAM_EEPROM_WRITE_ADDRESS 0xA0 #define SDRAM_EEPROM_READ_ADDRESS 0xA1 +#define CONFIG_BOARD_PRE_INIT /************************************************************** * Environment definitions **************************************************************/ @@ -89,13 +103,13 @@ /*************************************************************** * defines if the console is stored in the environment - ***************************************************************/ -#define CFG_CONSOLE_IS_IN_ENV /* stdin, stdout and stderr are in evironment */ + ***************************************************************/ +#define CFG_CONSOLE_IS_IN_ENV /* stdin, stdout and stderr are in evironment */ /*************************************************************** * defines if an overwrite_console function exists *************************************************************/ #define CFG_CONSOLE_OVERWRITE_ROUTINE - +#define CFG_CONSOLE_INFO_QUIET /*************************************************************** * defines if the overwrite_console should be stored in the * environment @@ -189,7 +203,7 @@ /* * Init Memory Controller: - */ + */ #define FLASH_BASE0_PRELIM 0xFFC00000 /* FLASH bank #0 */ #define FLASH_BASE1_PRELIM 0 /* FLASH bank #1 */ @@ -227,7 +241,10 @@ ***********************************************************************/ #define CFG_ISA_IO_BASE_ADDRESS 0xE8000000 - +/*********************************************************************** + * Last Stage Init + ***********************************************************************/ +#define CONFIG_LAST_STAGE_INIT /************************************************************ * Ethernet Stuff ***********************************************************/ @@ -272,25 +289,35 @@ #define CFG_SCSI_MAX_DEVICE CFG_SCSI_MAX_SCSI_ID * CFG_SCSI_MAX_LUN /* maximum Target devices */ /************************************************************ - * DISK Partition support + * DISK Partition support ************************************************************/ -#define CONFIG_DOS_PARTITION -#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION #define CONFIG_ISO_PARTITION /* Experimental */ /************************************************************ - * Keyboard support + * Keyboard support ************************************************************/ #define CONFIG_ISA_KEYBOARD /************************************************************ - * Video support + * Video support ************************************************************/ #define CONFIG_VIDEO /*To enable video controller support */ #define CONFIG_VIDEO_CT69000 /************************************************************ - * Debug support + * USB support + ************************************************************/ +#define CONFIG_USB_UHCI +#define CONFIG_USB_KEYBOARD +#define CONFIG_USB_STORAGE + +/* Enable needed helper functions */ +#define CFG_DEVICE_DEREGISTER /* needs device_deregister */ + +/************************************************************ + * Debug support ************************************************************/ #if (CONFIG_COMMANDS & CFG_CMD_KGDB) #define CONFIG_KGDB_BAUDRATE 230400 /* speed to run kgdb serial port */ @@ -298,10 +325,10 @@ #endif /************************************************************ - * Ident + * Ident ************************************************************/ -#define VERSION_TAG "REL_1.0.0" -#define CONFIG_IDENT_STRING "\n(c) 2001 by MPL AG Switzerland, MEV-10066-001 " VERSION_TAG +#define VERSION_TAG "REL_1_1_1" +#define CONFIG_IDENT_STRING "\n(c) 2001 by MPL AG Switzerland, MEV-10066-001 " VERSION_TAG #endif /* __CONFIG_H */ diff --git a/include/config_hymod.h b/include/config_hymod.h index 3e0c0cf..1244317 100644 --- a/include/config_hymod.h +++ b/include/config_hymod.h @@ -100,6 +100,7 @@ CFG_CMD_MII | \ CFG_CMD_PCMCIA | \ CFG_CMD_PCI | \ + CFG_CMD_USB | \ CFG_CMD_SCSI ) ) /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ diff --git a/include/devices.h b/include/devices.h index 97cf63a..1b65639 100644 --- a/include/devices.h +++ b/include/devices.h @@ -92,6 +92,7 @@ extern char *stdio_names[MAX_FILES]; int device_register (device_t * dev); int devices_init (bd_t *, ulong); int devices_done (void); +int device_deregister(char *devname); #ifdef CONFIG_LCD int drv_lcd_init (bd_t *); #endif @@ -101,8 +102,5 @@ int drv_video_init (void); #ifdef CONFIG_WL_4PPM_KEYBOARD int drv_wlkbd_init (void); #endif -#ifdef CONFIG_ISA_KEYBOARD -int drv_isa_kbd_init (void); -#endif #endif /* _DEVICES_H_ */ diff --git a/include/lists.h b/include/lists.h index e1534bd..839330c 100644 --- a/include/lists.h +++ b/include/lists.h @@ -36,9 +36,10 @@ int ListInsertItem(list_t list, void *ptrToItem, int itemPosition); int ListInsertItems(list_t list, void *ptrToItems, int firstItemPosition, int numItemsToInsert); void ListDispose(list_t list); void *ListGetPtrToItem(list_t list, int itemPosition); +void ListRemoveItem(list_t list, void *itemDestination, int itemPosition); +void ListRemoveItems(list_t list, void *itemsDestination, int firstItemPosition, int numItemsToRemove); /* - void ListDisposePtrList(list_t list); void ListGetItem(list_t list, void *itemDestination, int itemPosition); void ListReplaceItem(list_t list, void *ptrToItem, int itemPosition); diff --git a/include/ppcboot.h b/include/ppcboot.h index 5467c98..3585759 100644 --- a/include/ppcboot.h +++ b/include/ppcboot.h @@ -182,6 +182,9 @@ int checkboard (void); int checkflash (void); int checkdram (void); char * strmhz(char *buf, long hz); +#ifdef CONFIG_LAST_STAGE_INIT +int last_stage_init(void); +#endif /* common/cmd_bootm.c */ void print_image_hdr (image_header_t *hdr); @@ -200,6 +203,7 @@ int saveenv(void); defined(CONFIG_AR405) || \ defined (CONFIG_WALNUT405) || \ defined (CONFIG_PIP405) || \ + defined (CONFIG_MIP405) || \ defined (CONFIG_CPCIISER4) || \ defined (CONFIG_OCRTC) || \ defined (CONFIG_DASA_SIM) || \ @@ -250,6 +254,7 @@ void reset_phy (void); defined(CONFIG_OCRTC) || \ defined(CONFIG_PCU_E) || \ defined(CONFIG_PIP405) || \ + defined(CONFIG_MIP405) || \ defined(CONFIG_PM826) || \ defined(CONFIG_SXNI855T) || \ defined(CONFIG_TQM8260) || \ @@ -314,6 +319,7 @@ void load_sernum_ethaddr(bd_t *bd); defined(CONFIG_CANBT) || \ defined(CONFIG_WALNUT405) || \ defined(CONFIG_PIP405) || \ + defined(CONFIG_MIP405) || \ defined(CONFIG_CPCIISER4) || \ defined(CONFIG_OCRTC) || \ defined(CONFIG_ADCIOP) || \ diff --git a/include/usb.h b/include/usb.h new file mode 100644 index 0000000..c1c8d4c --- /dev/null +++ b/include/usb.h @@ -0,0 +1,352 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + * Note: Part of this code has been derived from linux + * + */ +#ifndef _USB_H_ +#define _USB_H_ + +#include + +/* Everything is aribtrary */ +#define USB_ALTSETTINGALLOC 4 +#define USB_MAXALTSETTING 128 /* Hard limit */ + +#define USB_MAX_DEVICE 32 +#define USB_MAXCONFIG 8 +#define USB_MAXINTERFACES 8 +#define USB_MAXENDPOINTS 16 +#define USB_MAXCHILDREN 8 /* This is arbitrary */ +#define USB_MAX_HUB 16 + +#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ + + +/* String descriptor */ +struct usb_string_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short wData[1]; +} __attribute__ ((packed)); + +/* device request (setup) */ +struct devrequest { + unsigned char requesttype; + unsigned char request; + unsigned short value; + unsigned short index; + unsigned short length; +} __attribute__ ((packed)); + + + +/* All standard descriptors have these 2 fields in common */ +struct usb_descriptor_header { + unsigned char bLength; + unsigned char bDescriptorType; +} __attribute__ ((packed)); + +/* Device descriptor */ +struct usb_device_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short bcdUSB; + unsigned char bDeviceClass; + unsigned char bDeviceSubClass; + unsigned char bDeviceProtocol; + unsigned char bMaxPacketSize0; + unsigned short idVendor; + unsigned short idProduct; + unsigned short bcdDevice; + unsigned char iManufacturer; + unsigned char iProduct; + unsigned char iSerialNumber; + unsigned char bNumConfigurations; +} __attribute__ ((packed)); + + +/* Endpoint descriptor */ +struct usb_endpoint_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bEndpointAddress; + unsigned char bmAttributes; + unsigned short wMaxPacketSize; + unsigned char bInterval; + unsigned char bRefresh; + unsigned char bSynchAddress; + +} __attribute__ ((packed)); +/* Interface descriptor */ +struct usb_interface_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bInterfaceNumber; + unsigned char bAlternateSetting; + unsigned char bNumEndpoints; + unsigned char bInterfaceClass; + unsigned char bInterfaceSubClass; + unsigned char bInterfaceProtocol; + unsigned char iInterface; + + unsigned char no_of_ep; + unsigned char act_altsetting; + struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS]; +} __attribute__ ((packed)); + + +/* Configuration descriptor information.. */ +struct usb_config_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short wTotalLength; + unsigned char bNumInterfaces; + unsigned char bConfigurationValue; + unsigned char iConfiguration; + unsigned char bmAttributes; + unsigned char MaxPower; + + unsigned char no_of_if; /* number of interfaces */ + struct usb_interface_descriptor if_desc[USB_MAXINTERFACES]; +} __attribute__ ((packed)); + + +struct usb_device { + int devnum; /* Device number on USB bus */ + int slow; /* Slow device? */ + char mf[32]; /* manufacturer */ + char prod[32]; /* product */ + char serial[32]; /* serial number */ + + int maxpacketsize; /* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */ + unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ + unsigned int halted[2]; /* endpoint halts; one bit per endpoint # & direction; */ + /* [0] = IN, [1] = OUT */ + int epmaxpacketin[16]; /* INput endpoint specific maximums */ + int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ + + int configno; /* selected config number */ + struct usb_device_descriptor descriptor; /* Device Descriptor */ + struct usb_config_descriptor config; /* config descriptor */ + + int have_langid; /* whether string_langid is valid yet */ + int string_langid; /* language ID for strings */ + int (*irq_handle)(struct usb_device *dev); + unsigned long irq_status; + int irq_act_len; /* transfered bytes */ + void *privptr; + /* + * Child devices - if this is a hub device + * Each instance needs its own set of data structures. + */ + unsigned long status; + int act_len; /* transfered bytes */ + int maxchild; /* Number of ports if hub */ + struct usb_device *parent; + struct usb_device *children[USB_MAXCHILDREN]; +}; + +/********************************************************************** + * this is how the lowlevel part communicate with the outer world + */ + +#ifdef CONFIG_USB_UHCI +int usb_lowlevel_init(void); +int usb_lowlevel_stop(void); +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len); +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len,struct devrequest *setup); +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval); + +/* Defines */ +#define USB_UHCI_VEND_ID 0x8086 +#define USB_UHCI_DEV_ID 0x7112 + +#else +#error USB Lowlevel not defined +#endif + +#ifdef CONFIG_USB_STORAGE + +#define USB_MAX_STOR_DEV 5 +block_dev_desc_t *usb_stor_get_dev(int index); +int usb_stor_scan(int mode); + +#endif + +#ifdef CONFIG_USB_KEYBOARD + +int drv_usb_kbd_init(void); +int usb_kbd_deregister(void); + +#endif +/* routines */ +int usb_init(void); /* initialize the USB Controller */ +int usb_stop(void); /* stop the USB Controller */ + + +int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); +int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id); +struct usb_device * usb_get_dev_index(int index); +int usb_control_msg(struct usb_device *dev, unsigned int pipe, + unsigned char request, unsigned char requesttype, + unsigned short value, unsigned short index, + void *data, unsigned short size, int timeout); +int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout); +int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer,int transfer_len, int interval); +void usb_disable_asynch(int disable); +int usb_maxpacket(struct usb_device *dev,unsigned long pipe); +void __inline__ wait_ms(unsigned long ms); +int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno); +int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size); +int usb_get_class_descriptor(struct usb_device *dev, int ifnum, + unsigned char type, unsigned char id, void *buf, int size); +int usb_clear_halt(struct usb_device *dev, int pipe); +int usb_string(struct usb_device *dev, int index, char *buf, size_t size); +int usb_set_interface(struct usb_device *dev, int interface, int alternate); + +/* big endian -> little endian conversion */ +#define swap_16(x) \ + ((unsigned short)( \ + (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \ + (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) )) +#define swap_32(x) \ + ((unsigned long)( \ + (((unsigned long)(x) & (unsigned long)0x000000ffUL) << 24) | \ + (((unsigned long)(x) & (unsigned long)0x0000ff00UL) << 8) | \ + (((unsigned long)(x) & (unsigned long)0x00ff0000UL) >> 8) | \ + (((unsigned long)(x) & (unsigned long)0xff000000UL) >> 24) )) + +/* + * Calling this entity a "pipe" is glorifying it. A USB pipe + * is something embarrassingly simple: it basically consists + * of the following information: + * - device number (7 bits) + * - endpoint number (4 bits) + * - current Data0/1 state (1 bit) + * - direction (1 bit) + * - speed (1 bit) + * - max packet size (2 bits: 8, 16, 32 or 64) + * - pipe type (2 bits: control, interrupt, bulk, isochronous) + * + * That's 18 bits. Really. Nothing more. And the USB people have + * documented these eighteen bits as some kind of glorious + * virtual data structure. + * + * Let's not fall in that trap. We'll just encode it as a simple + * unsigned int. The encoding is: + * + * - max size: bits 0-1 (00 = 8, 01 = 16, 10 = 32, 11 = 64) + * - direction: bit 7 (0 = Host-to-Device [Out], 1 = Device-to-Host [In]) + * - device: bits 8-14 + * - endpoint: bits 15-18 + * - Data0/1: bit 19 + * - speed: bit 26 (0 = Full, 1 = Low Speed) + * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk) + * + * Why? Because it's arbitrary, and whatever encoding we select is really + * up to us. This one happens to share a lot of bit positions with the UHCI + * specification, so that much of the uhci driver can just mask the bits + * appropriately. + */ +/* Create various pipes... */ +#define create_pipe(dev,endpoint) \ + (((dev)->devnum << 8) | (endpoint << 15) | ((dev)->slow << 26) | (dev)->maxpacketsize) +#define default_pipe(dev) ((dev)->slow <<26) + +#define usb_sndctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | create_pipe(dev,endpoint)) +#define usb_rcvctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | create_pipe(dev,endpoint)) +#define usb_rcvisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | create_pipe(dev,endpoint)) +#define usb_rcvbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | create_pipe(dev,endpoint)) +#define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | default_pipe(dev)) +#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | default_pipe(dev) | USB_DIR_IN) + +/* The D0/D1 toggle bits */ +#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1) +#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep)) +#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep)) + +/* Endpoint halt control/status */ +#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1) +#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) +#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) +#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) + +#define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT) + +#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1) +#define usb_pipein(pipe) (((pipe) >> 7) & 1) +#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) +#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) +#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) +#define usb_pipedata(pipe) (((pipe) >> 19) & 1) +#define usb_pipeslow(pipe) (((pipe) >> 26) & 1) +#define usb_pipetype(pipe) (((pipe) >> 30) & 3) +#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS) +#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT) +#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL) +#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK) + + +/************************************************************************* + * Hub Stuff + */ +struct usb_port_status { + unsigned short wPortStatus; + unsigned short wPortChange; +} __attribute__ ((packed)); + +struct usb_hub_status { + unsigned short wHubStatus; + unsigned short wHubChange; +} __attribute__ ((packed)); + + +/* Hub descriptor */ +struct usb_hub_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bNbrPorts; + unsigned short wHubCharacteristics; + unsigned char bPwrOn2PwrGood; + unsigned char bHubContrCurrent; + unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8]; + unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8]; + /* DeviceRemovable and PortPwrCtrlMask want to be variable-length + bitmaps that hold max 255 entries. (bit0 is ignored) */ +} __attribute__ ((packed)); + + +struct usb_hub_device { + struct usb_device *pusb_dev; + struct usb_hub_descriptor desc; +}; + +#endif /*_USB_H_ */ diff --git a/include/usb_defs.h b/include/usb_defs.h new file mode 100644 index 0000000..541aa04 --- /dev/null +++ b/include/usb_defs.h @@ -0,0 +1,256 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 + * + * Note: Part of this code has been derived from linux + * + */ +#ifndef _USB_DEFS_H_ +#define _USB_DEFS_H_ + + +/* Everything is aribtrary */ +#define USB_ALTSETTINGALLOC 4 +#define USB_MAXALTSETTING 128 /* Hard limit */ + +#define USB_MAX_DEVICE 32 +#define USB_MAXCONFIG 8 +#define USB_MAXINTERFACES 8 +#define USB_MAXENDPOINTS 16 +#define USB_MAXCHILDREN 8 /* This is arbitrary */ +#define USB_MAX_HUB 16 + +#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ + +/* USB constants */ + +/* Device and/or Interface Class codes */ +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_DATA 10 +#define USB_CLASS_VENDOR_SPEC 0xff + +/* some HID sub classes */ +#define USB_SUB_HID_NONE 0 +#define USB_SUB_HID_BOOT 1 + +/* some UID Protocols */ +#define USB_PROT_HID_NONE 0 +#define USB_PROT_HID_KEYBOARD 1 +#define USB_PROT_HID_MOUSE 2 + + +/* Sub STORAGE Classes */ +#define US_SC_RBC 1 /* Typically, flash devices */ +#define US_SC_8020 2 /* CD-ROM */ +#define US_SC_QIC 3 /* QIC-157 Tapes */ +#define US_SC_UFI 4 /* Floppy */ +#define US_SC_8070 5 /* Removable media */ +#define US_SC_SCSI 6 /* Transparent */ +#define US_SC_MIN US_SC_RBC +#define US_SC_MAX US_SC_SCSI + +/* STORAGE Protocols */ +#define US_PR_CB 1 /* Control/Bulk w/o interrupt */ +#define US_PR_CBI 0 /* Control/Bulk/Interrupt */ +#define US_PR_BULK 0x50 /* bulk only */ + +/* USB types */ +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +/* USB recipients */ +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +/* USB directions */ +#define USB_DIR_OUT 0 +#define USB_DIR_IN 0x80 + +/* Descriptor types */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 + +#define USB_DT_HID (USB_TYPE_CLASS | 0x01) +#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02) +#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) +#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) + +/* Descriptor sizes per descriptor type */ +#define USB_DT_DEVICE_SIZE 18 +#define USB_DT_CONFIG_SIZE 9 +#define USB_DT_INTERFACE_SIZE 9 +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ +#define USB_DT_HUB_NONVAR_SIZE 7 +#define USB_DT_HID_SIZE 9 + +/* Endpoints */ +#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 + +/* USB Packet IDs (PIDs) */ +#define USB_PID_UNDEF_0 0xf0 +#define USB_PID_OUT 0xe1 +#define USB_PID_ACK 0xd2 +#define USB_PID_DATA0 0xc3 +#define USB_PID_UNDEF_4 0xb4 +#define USB_PID_SOF 0xa5 +#define USB_PID_UNDEF_6 0x96 +#define USB_PID_UNDEF_7 0x87 +#define USB_PID_UNDEF_8 0x78 +#define USB_PID_IN 0x69 +#define USB_PID_NAK 0x5a +#define USB_PID_DATA1 0x4b +#define USB_PID_PREAMBLE 0x3c +#define USB_PID_SETUP 0x2d +#define USB_PID_STALL 0x1e +#define USB_PID_UNDEF_F 0x0f + +/* Standard requests */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +/* HID requests */ +#define USB_REQ_GET_REPORT 0x01 +#define USB_REQ_GET_IDLE 0x02 +#define USB_REQ_GET_PROTOCOL 0x03 +#define USB_REQ_SET_REPORT 0x09 +#define USB_REQ_SET_IDLE 0x0A +#define USB_REQ_SET_PROTOCOL 0x0B + + +/* "pipe" definitions */ + +#define PIPE_ISOCHRONOUS 0 +#define PIPE_INTERRUPT 1 +#define PIPE_CONTROL 2 +#define PIPE_BULK 3 +#define PIPE_DEVEP_MASK 0x0007ff00 + +#define USB_ISOCHRONOUS 0 +#define USB_INTERRUPT 1 +#define USB_CONTROL 2 +#define USB_BULK 3 + +/* USB-status codes: */ +#define USB_ST_ACTIVE 0x1 /* TD is active */ +#define USB_ST_STALLED 0x2 /* TD is stalled */ +#define USB_ST_BUF_ERR 0x4 /* buffer error */ +#define USB_ST_BABBLE_DET 0x8 /* Babble detected */ +#define USB_ST_NAK_REC 0x10 /* NAK Received*/ +#define USB_ST_CRC_ERR 0x20 /* CRC/timeout Error */ +#define USB_ST_BIT_ERR 0x40 /* Bitstuff error */ +#define USB_ST_NOT_PROC 0x80000000L /* Not yet processed */ + + + +/************************************************************************* + * Hub defines + */ + +/* + * Hub request types + */ + +#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) +#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) + +/* + * Hub Class feature numbers + */ +#define C_HUB_LOCAL_POWER 0 +#define C_HUB_OVER_CURRENT 1 + +/* + * Port feature numbers + */ +#define USB_PORT_FEAT_CONNECTION 0 +#define USB_PORT_FEAT_ENABLE 1 +#define USB_PORT_FEAT_SUSPEND 2 +#define USB_PORT_FEAT_OVER_CURRENT 3 +#define USB_PORT_FEAT_RESET 4 +#define USB_PORT_FEAT_POWER 8 +#define USB_PORT_FEAT_LOWSPEED 9 +#define USB_PORT_FEAT_C_CONNECTION 16 +#define USB_PORT_FEAT_C_ENABLE 17 +#define USB_PORT_FEAT_C_SUSPEND 18 +#define USB_PORT_FEAT_C_OVER_CURRENT 19 +#define USB_PORT_FEAT_C_RESET 20 + +/* wPortStatus bits */ +#define USB_PORT_STAT_CONNECTION 0x0001 +#define USB_PORT_STAT_ENABLE 0x0002 +#define USB_PORT_STAT_SUSPEND 0x0004 +#define USB_PORT_STAT_OVERCURRENT 0x0008 +#define USB_PORT_STAT_RESET 0x0010 +#define USB_PORT_STAT_POWER 0x0100 +#define USB_PORT_STAT_LOW_SPEED 0x0200 + +/* wPortChange bits */ +#define USB_PORT_STAT_C_CONNECTION 0x0001 +#define USB_PORT_STAT_C_ENABLE 0x0002 +#define USB_PORT_STAT_C_SUSPEND 0x0004 +#define USB_PORT_STAT_C_OVERCURRENT 0x0008 +#define USB_PORT_STAT_C_RESET 0x0010 + +/* wHubCharacteristics (masks) */ +#define HUB_CHAR_LPSM 0x0003 +#define HUB_CHAR_COMPOUND 0x0004 +#define HUB_CHAR_OCPM 0x0018 + +/* + *Hub Status & Hub Change bit masks + */ +#define HUB_STATUS_LOCAL_POWER 0x0001 +#define HUB_STATUS_OVERCURRENT 0x0002 + +#define HUB_CHANGE_LOCAL_POWER 0x0001 +#define HUB_CHANGE_OVERCURRENT 0x0002 + +#endif /*_USB_DEFS_H_ */