remove unmaintained bitsy (ipaq) kernel

This commit is contained in:
cinap_lenrek 2016-05-05 16:32:15 +02:00
parent 8d9a94a66e
commit 76e4f7caf9
49 changed files with 0 additions and 24206 deletions

View file

@ -1,245 +0,0 @@
The bitsy comes with Wince. To get to Plan 9, you will need a serial cable,
a Windows machine with a serial interface, the CDROM that comes with the bitsy,
and a Plan 9 machine with a serial interface. The Windows machine is used to
get the Linux boot loader onto the bitsy (and to save away wince, if you so
desire). The Plan 9 machine is used to get the plan 9 kernel and a read only
file system onto the bitsy.
0. charge up the bitsy.
1. go to
ftp://ftp.handhelds.org/pub/linux/compaq/ipaq/stable/install.html
Get the latest version of the Linux "osloader" and "bootldr" programs
(we have tried versions 1.3.0 and 0000-2.14.8, respectively; newest
versions seem not to allow you to suspend your bitsy due to a bug
which is probably ours). You can find them all at
www.collyer.net/who/geoff/9/bitsy/.
2. Use ActiveSync to copy osloader and bootldr to the bitsy. Copy or
rename the bootldr binary to "bootldr" on Windows, then copy it to the
bitsy; trying to rename it on WinCE won't produce the right result.
Steps 3 - 7 may work on a Pocket PC bitsy, but see Steps 3a - 7a
if they don't or if you have a Pocket PC 2002 bitsy.
3. Run osloader by clicking on it under the WinCE File Explorer
4. Use osloader to save your WinCE flash away. This takes a while,
as it's 16MB over a 115,200 baud line.
5. Select "Run" from the osloader menu. Ignore "Run from RAM"; it's
not needed.
6. At this point, the bitsy's screen turns blank, but you can still
talk to the bitsy over its serial port. The serial port is connected
to the OS loader's terminal program. On Windows, you have to exit
ActiveSync before the serial port is available for a terminal program.
I moved the bitsy and its cable over to a Plan 9 machine and connected
using "con -b 115200 /dev/eia[01]" to talk to the console. The
command "help" lists the OS loader's commands.
7. Now you need to download the BOOT loader program into flash (right
now, you're only running the OS loader program out of RAM; rebooting
will get you back to WinCE). In the con window, "load bootldr" to the
bitsy. It will indicate that it's starting an xmodem download.
Under con, type "Ctrl-\" to get a ">>>" prompt. At this prompt, you
want to run Plan 9's xms program to pipe the bootldr program to the
bitsy. For example, to download /tmp/bootldr, type "!xms /tmp/bootldr".
If this step works successfully, the OS loader will print out some sort
of OK checksum message.
If you have a Pocket PC 2002 or steps 3 - 7 above didn't work for you,
try 3a - 7a.
3a. Copy BootBlaster (also) to the bitsy via ActiveSync.
4a. Save your flash by running osloader and selecting "Flash->Save to
File". As it produces 4MB files, use ActiveSync to copy them off the
bitsy.
5a. Move the bitsy and its cable over to a Plan 9 machine and connect
using "con -b 115200 /dev/eia[01]" to talk to the console.
6a. Run BootBlaster by clicking on it under the WinCE File Explorer.
7a. Select "Program"; it should copy "bootldr" into your flash in
about 15 seconds.
8. Reboot your bitsy (either cycle the power or use the reset
switch). The new boot loader runs out of Flash. You'll get the linux
penguin splash screen and a bunch of options triggered by buttons.
Pick the one that gets you to the boot loader.
9. Make the partitions you need in the bitsy's flash, type, using
the con program:
partition reset
partition define bootldr 0x000000 0x040000 2
partition define params 0x040000 0x040000 0
partition define kernel 0x080000 0x0c0000 0
partition define user 0x140000 0x0c0000 0
partition define ramdisk 0x200000 0x600000 0
partition define fs 0x800000 0x800000 0
params save
These are the partitions as shown by partition show:
boot> partition show
argv[1]=partition
npartitions=00000006
bootldr
base: 00000000
size: 00040000
flags: 00000002
params
base: 00040000
size: 00040000
flags: 00000000
kernel
base: 00080000
size: 000C0000
flags: 00000000
user
base: 00140000
size: 000C0000
flags: 00000000
ramdisk
base: 00200000
size: 00600000
flags: 00000000
fs
base: 00800000
size: 00800000
flags: 00000000
After each line you'll get a message like `defining partition: params'.
Different versions of the bootloader predefine different partitions.
The bootldr partition is usually predefined, so you don't have to remake
that. You may have to delete one or two partitions. The command is
partition delete <name>
Make sure the partition layout is as given above; some of this knowledge is
built into the kernel.
10. Before you can fill the new partitions with a kernel and a read-only
file system, you'll have to make them. In the directory /sys/src/9/bitsy,
type mk and mk paqdisk. Before mk-ing paqdisk, make sure you have all
the necessary arm binaries installed in /arm and examine the file
paqfiles/mfs to see what you need to change for connecting to your local
file servers.
11. Now you can type "load kernel". The boot loader will prompt for
another xmodem download. Again escape using "Ctrl-\", then use
"!xms /sys/src/9/bitsy/9bitsy" (or "!xms /arm/9bitsy" if you've already
installed it).
12. Download the ramdisk, using "load ramdisk" and
"!xms /sys/src/9/bitsy/paqdisk" (or "!xms /arm/paqdisk" if you've already
installed it), similarly to 10, above.
13. Type `boot' or `boot flash' depending on your version of the boot loader.
If you need the latter, you may want to
set boot_type flash
params save
to make boot flash the default.
You'll get a Dutch flag (or a French one, if you hold the iPaq the wrong way),
then the boot screen will say, on the serial port, thus in your con window:
root is from [paq]:
Just wait a while or hit enter in the con window and it'll continue.
14. The bitsy will now want to calibrate the screen. It'll put up a
series of crosses that you should press the center of. Hold the pen
down over each cross for a second or so; aim carefully. Hold the
machine in your hand the way you'ld normally use it or the calibration
could be off since there is depth to the glass in the screen.
15. You'll get a new screen with a single line at the top and a
keyboard/scribble area at the bottom. This is a simple one file
editor. This file is similar to plan9.ini on PC's. There may be
garbage on the top line. If there is, delete the garbage letters.
(Be careful here: the backspace and delete keys are adjacent on the
wee keyboard and it's much too easy to hit delete instead of
backspace, especially if you haven't calibrated the screen dead-on.)
You should be left with a single line containing (with different
numbers):
calibrate='-16374 22919 251 -24'
You need to enter a few more things, including, but not limited to:
user=<user-name>
wvkey1=<key string>
wvkey2=<key string>
wvkey3=<key string>
wvtxkey=<key string>
wvessid=<wavelan name>
auth=<ip address>
cpu=<ip address>
proxy=<ip address>
fs=<ip address>
Your best bet is to copy these off a working bitsy. wv*key* only
matter if your wireless network is encrypted. When roaming the world,
omit wv*. When you're done, hit the "ESC" key on the simulated
keyboard, or the side button near the word iPAQ on the bitsy. The
system will now come up as you. However, you'll get a message about
the flash file system being corrupted, because we haven't yet
initialized it.
16. To set up the file systems, sweep a window and give the following
sequence of commands.
# aux/mkflashfs /dev/flash/fs
# aux/flashfs
aux/flashfs created a Plan 9 server in /srv/brzr, which we can use to set up
default directories.
# mount -c /srv/brzr /n/brzr
# cd /n/brzr
# mkdir n usr
# mkdir n/fs n/emelie n/choline n/nslocum
# mkdir usr/yourname usr/yourfriend
17. For safety, reboot the system:
# reboot
18. Now reboot, go through the Linux splash screen, the Plan 9 boot
editor, and sweep yourself a new rio window.
Before you can connect to other machines, you need a way to enter
passwords and keys into factotum. The easiest way to do this is to
run
# auth/fgui &
in the window you just made. The window will disappear (fgui spends
most of its time hidden), so sweep a new window and run the command
# mfs
to connect to file servers. You will probably need to modify mfs to
work in your environment (see point 10), though you can supply many
of the variables it needs in step 15, and doing
# import $cpu /net
before running mfs can go a long ways.
19. When you're all set with a working wavelan, you can download new
kernels more quickly using
# bitsyload k
and new paqdisks using
# bitsyload r
(r stands for ramdisk, the name of the partition into which paqdisk goes).
Note that overwriting the ramdisk partition will cause the read-only file
system which forms the root of you namespace to fail. You'll need to
reboot immediately after bytsyload r.

View file

@ -1,49 +0,0 @@
dev
root
cons
dup
env
ether netif
flash
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
kprof
mnt
µc
pcmcia cis
draw
penmouse
pipe
proc
cap
srv
ssl
uart
uda1341
sd
ip
tcp
udp
ipifc
icmp
icmp6
gre
ipmux
link
etherwavelan wavelan
ethermedium
misc
uartsa1110
sdata
port
int cpuserver = 1;
bootdir
/$objtype/bin/paqfs
/$objtype/bin/auth/factotum
bootfs.paq
boot

View file

@ -1,103 +0,0 @@
#include "mem.h"
// Bitsy development board uses two banks: KM416S4030C,
// 12 row address bits, 8 col address bits
// Bitsy uses two banks KM416S8030C, 12 row address bits,
// 9 col address bits
// Have to set DRAC0 to 14 row bits or else you only get 8 col bits
// from the formfactor unit configuration registers: 0xF3536257
mdcnfg: // DRAM Configuration Register 10.2.1
WORD 1<<0 | 1<<2 | 0<<3 | 0x5<<4 | 0x3<<8 | 3<<12 | 3<<14
mdrefr0: // DRAM Refresh Control Register 10.2.2
WORD 1<<0 | 0x200<<4 | 1<<21 | 1<<22 | 1 <<31
mdrefr1: // DRAM Refresh Control Register 10.2.2
WORD 1<<0 | 0x200<<4 | 1<<21 | 1<<22
mdrefr2: // DRAM Refresh Control Register 10.2.2
WORD 1<<0 | 0x200<<4 | 1<<20 | 1<<21 | 1<<22
/* MDCAS settings from [1] Table 10-3 (page 10-18) */
waveform0:
WORD 0xAAAAAAA7
waveform1:
WORD 0xAAAAAAAA
waveform2:
WORD 0xAAAAAAAA
delay: // delay without using memory
mov $100, r1 // 200MHz: 100 × (2 instructions @ 5 ns) == 1 ms
l1:
sub $1, r1
bgt l1
sub $1, r0
bgt delay
ret
reset:
mov $INTREGS+4, r0 // turn off interrupts
mov $0, (r0)
// Is this necessary on wakeup?
mov $POWERREGS+14, r0 // set clock speed to 191.7MHz
mov $0xb, (r0)
// This is necessary on hard reset, but not on sleep reset
mov $0x80, r0 // wait ±128 µs
bl delay
/* check to see if we're operating out of DRAM */
bic $0x000000ff, pc, r4
bic $0x0000ff00, r4
bic $0x00ff0000, r4
cmp r4, $PHYSDRAM0
beq dram
dramwakeup:
mov $POWERREGS+0x4, r1 // Clear DH in Power Manager Sleep Status Register
bic $(1<<3), (r1) // DH == DRAM Hold
// This releases nCAS/DQM and nRAS/nSDCS pins to make DRAM exit selfrefresh
/* Set up the DRAM in banks 0 and 1 [1] 10.3 */
mov $MEMCONFREGS, r1
mov mdrefr0, r2 // Turn on K1RUN
mov r2, 0x1c(r1)
mov mdrefr1, r2 // Turn off SLFRSH
mov r2, 0x1c(r1)
mov mdrefr2, r2 // Turn on E1PIN
mov r2, 0x1c(r1)
mov waveform0, r2
mov r2, 0x4(r1)
mov waveform1, r2
mov r2, 0x8(r1)
mov waveform2, r2
mov r2, 0xc(r1)
mov $PHYSDRAM0, r0
mov 0x00(r0), r2 // Eight non-burst read cycles
mov 0x20(r0), r2
mov 0x40(r0), r2
mov 0x60(r0), r2
mov 0x80(r0), r2
mov 0xa0(r0), r2
mov 0xc0(r0), r2
mov 0xe0(r0), r2
mov mdcnfg, r2 // Enable memory banks
mov r2, 0x0(r1)
// Is there any use in turning on EAPD and KAPD in the MDREFR register?
ret
dram:

View file

@ -1,254 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
enum {
RTCREGS = 0x90010000, /* real time clock registers */
RTSR_al = 0x01, /* alarm detected */
RTSR_hz = 0x02, /* 1Hz tick */
RTSR_ale= 0x04, /* alarm interrupt enable */
RTSR_hze= 0x08, /* 1Hz tick enable */
Never = 0xffffffff,
};
typedef struct OSTimer
{
ulong osmr[4]; /* match registers */
volatile ulong oscr; /* counter register */
ulong ossr; /* status register */
ulong ower; /* watchdog enable register */
ulong oier; /* timer interrupt enable register */
} OSTimer;
typedef struct RTCregs
{
ulong rtar; /* alarm */
ulong rcnr; /* count */
ulong rttr; /* trim */
ulong dummy; /* hole */
ulong rtsr; /* status */
} RTCregs;
OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
RTCregs *rtcregs = (RTCregs*)RTCREGS;
static int clockinited;
static void clockintr(Ureg*, void*);
static void rtcintr(Ureg*, void*);
static Tval when; /* scheduled time of next interrupt */
long timeradjust;
enum
{
Minfreq = ClockFreq/HZ, /* At least one interrupt per HZ (50 ms) */
Maxfreq = ClockFreq/10000, /* At most one interrupt every 100 µs */
};
ulong
clockpower(int on)
{
static ulong savedtime;
if (on){
timerregs->ossr |= 1<<0;
timerregs->oier = 1<<0;
timerregs->osmr[0] = timerregs->oscr + Minfreq;
if (rtcregs->rttr == 0){
rtcregs->rttr = 0x8000; // nominal frequency.
rtcregs->rcnr = 0;
rtcregs->rtar = 0xffffffff;
rtcregs->rtsr |= RTSR_ale;
rtcregs->rtsr |= RTSR_hze;
}
if (rtcregs->rcnr > savedtime)
return rtcregs->rcnr - savedtime;
} else
savedtime = rtcregs->rcnr;
clockinited = on;
return 0L;
}
void
clockinit(void)
{
ulong x;
ulong id;
/* map the clock registers */
timerregs = mapspecial(OSTIMERREGS, sizeof(OSTimer));
rtcregs = mapspecial(RTCREGS, sizeof(RTCregs));
/* enable interrupts on match register 0, turn off all others */
timerregs->ossr |= 1<<0;
intrenable(IRQ, IRQtimer0, clockintr, nil, "clock");
timerregs->oier = 1<<0;
/* figure out processor frequency */
x = powerregs->ppcr & 0x1f;
conf.hz = ClockFreq*(x*4+16);
conf.mhz = (conf.hz+499999)/1000000;
/* get processor type */
id = getcpuid();
print("%lud MHZ ARM, ver %lux/part %lux/step %lud\n", conf.mhz,
(id>>16)&0xff, (id>>4)&0xfff, id&0xf);
/* post interrupt 1/HZ secs from now */
when = timerregs->oscr + Minfreq;
timerregs->osmr[0] = when;
/* enable RTC interrupts and alarms */
intrenable(IRQ, IRQrtc, rtcintr, nil, "rtc");
rtcregs->rttr = 0x8000; // make rcnr 1Hz
rtcregs->rcnr = 0; // reset counter
rtcregs->rtsr |= RTSR_al;
rtcregs->rtsr |= RTSR_ale;
timersinit();
clockinited = 1;
}
/* turn 32 bit counter into a 64 bit one. since todfix calls
* us at least once a second and we overflow once every 1165
* seconds, we won't miss an overflow.
*/
uvlong
fastticks(uvlong *hz)
{
static uvlong high;
static ulong last;
ulong x;
if(hz != nil)
*hz = ClockFreq;
x = timerregs->oscr;
if(x < last)
high += 1LL<<32;
last = x;
return high+x;
}
ulong
µs(void)
{
return fastticks2us(fastticks(nil));
}
void
timerset(Tval v)
{
ulong next, tics; /* Must be unsigned! */
static int count;
next = v;
/* post next interrupt: calculate # of tics from now */
tics = next - timerregs->oscr - Maxfreq;
if (tics > Minfreq){
timeradjust++;
next = timerregs->oscr + Maxfreq;
}
timerregs->osmr[0] = next;
}
static void
clockintr(Ureg *ureg, void*)
{
/* reset previous interrupt */
timerregs->ossr |= 1<<0;
when += Minfreq;
timerregs->osmr[0] = when; /* insurance */
timerintr(ureg, when);
}
void
rtcalarm(ulong secs)
{
vlong t;
if (t == 0){
iprint("RTC alarm cancelled\n");
rtcregs->rtsr &= ~RTSR_ale;
rtcregs->rtar = 0xffffffff;
} else {
t = todget(nil);
t = t / 1000000000ULL; // nsec to secs
if (secs < t)
return;
secs -= t;
iprint("RTC alarm set to %uld seconds from now\n", secs);
rtcregs->rtar = rtcregs->rcnr + secs;
rtcregs->rtsr|= RTSR_ale;
}
}
static void
rtcintr(Ureg*, void*)
{
/* reset interrupt */
rtcregs->rtsr&= ~RTSR_ale;
rtcregs->rtsr&= ~RTSR_al;
rtcregs->rtar = 0;
iprint("RTC alarm: %lud\n", rtcregs->rcnr);
}
void
delay(int ms)
{
ulong start;
int i;
if(clockinited){
while(ms-- > 0){
start = timerregs->oscr;
while(timerregs->oscr-start < ClockFreq/1000)
;
}
} else {
while(ms-- > 0){
for(i = 0; i < 1000; i++)
;
}
}
}
void
microdelay(int µs)
{
ulong start;
int i;
µs++;
if(clockinited){
start = timerregs->oscr;
while(timerregs->oscr - start < 1UL+(µs*ClockFreq)/1000000UL)
;
} else {
while(µs-- > 0){
for(i = 0; i < 10; i++)
;
}
}
}
/*
* performance measurement ticks. must be low overhead.
* doesn't have to count over a second.
*/
ulong
perfticks(void)
{
return timerregs->oscr;
}

View file

@ -1,289 +0,0 @@
typedef struct Cisdat Cisdat;
typedef struct Conf Conf;
typedef struct Confmem Confmem;
typedef struct FPU FPU;
typedef struct FPenv FPenv;
typedef struct FPsave FPsave;
typedef struct DevConf DevConf;
typedef struct Label Label;
typedef struct Lock Lock;
typedef struct MMU MMU;
typedef struct Mach Mach;
typedef struct Notsave Notsave;
typedef struct Page Page;
typedef struct PCMmap PCMmap;
typedef struct PCMslot PCMslot;
typedef struct PCMconftab PCMconftab;
typedef struct PhysUart PhysUart;
typedef struct PMMU PMMU;
typedef struct Proc Proc;
typedef struct Uart Uart;
typedef struct Ureg Ureg;
typedef struct Vctl Vctl;
typedef long Tval;
#pragma incomplete Ureg
typedef void IntrHandler(Ureg*, void*);
#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
/*
* parameters for sysproc.c
*/
#define AOUT_MAGIC (E_MAGIC)
struct Lock
{
ulong key;
ulong sr;
ulong pc;
Proc *p;
Mach *m;
ushort isilock;
};
struct Label
{
ulong sp;
ulong pc;
};
/*
* FPsave.status
*/
enum
{
FPinit,
FPactive,
FPinactive,
};
struct FPsave
{
ulong status;
ulong control;
ulong regs[8][3]; /* emulated fp */
};
struct Confmem
{
ulong base;
ulong npage;
ulong limit;
ulong kbase;
ulong klimit;
};
struct Conf
{
ulong nmach; /* processors */
ulong nproc; /* processes */
Confmem mem[2];
ulong npage; /* total physical pages of memory */
ulong upages; /* user page pool */
ulong nimage; /* number of page cache image headers */
ulong nswap; /* number of swap pages */
int nswppo; /* max # of pageouts per segment pass */
ulong copymode; /* 0 is copy on write, 1 is copy on reference */
int monitor;
ulong ialloc; /* bytes available for interrupt time allocation */
ulong pipeqsize; /* size in bytes of pipe queues */
ulong hz; /* processor cycle freq */
ulong mhz;
};
/*
* MMU stuff in proc
*/
enum
{
NCOLOR= 1, /* 1 level cache, don't worry about VCE's */
Nmeg= 32, /* maximum size of user space */
};
struct PMMU
{
Page *l1page[Nmeg]; /* this's process' level 1 entries */
ulong l1table[Nmeg]; /* ... */
Page *mmufree; /* free mmu pages */
};
/*
* things saved in the Proc structure during a notify
*/
struct Notsave
{
int dummy;
};
#include "../port/portdat.h"
struct Mach
{
int machno; /* physical id of processor */
ulong splpc; /* pc of last caller to splhi */
Proc *proc; /* current process */
ulong mmupid; /* process id currently in mmu & cache */
ulong ticks; /* of the clock since boot time */
Label sched; /* scheduler wakeup */
Lock alarmlock; /* access to alarm list */
void* alarm; /* alarms bound to this clock */
int inclockintr;
Proc* readied; /* for runproc */
ulong schedticks; /* next forced context switch */
/* stats */
int tlbfault;
int tlbpurge;
int pfault;
int cs;
int syscall;
int load;
int intr;
vlong fastclock; /* last sampled value */
uvlong inidle; /* time spent in idlehands() */
ulong spuriousintr;
int lastintr;
int ilockdepth;
Perf perf; /* performance counters */
int flushmmu; /* make current proc flush it's mmu state */
Proc *pid2proc[31]; /* what proc holds what pid */
int lastpid; /* highest assigned pid slot */
int cpumhz; /* speed of cpu */
vlong cpuhz; /* ... */
uvlong cyclefreq; /* Frequency of user readable cycle counter */
/* save areas for exceptions */
ulong sfiq[5];
ulong sirq[5];
ulong sund[5];
ulong sabt[5];
int stack[1];
};
/*
* Fake kmap since we direct map dram
*/
typedef void KMap;
#define VA(k) ((ulong)(k))
#define kmap(p) (KMap*)((p)->pa)
#define kunmap(k)
struct
{
Lock;
char machs[MAXMACH]; /* active CPUs */
int exiting; /* shutdown */
}active;
#define MACHP(n) ((Mach *)(MACHADDR+(n)*BY2PG))
extern Mach *m;
extern Proc *up;
enum
{
OneMeg= 1024*1024,
};
/*
* PCMCIA structures known by both port/cis.c and the pcmcia driver
*/
/*
* Map between ISA memory space and PCMCIA card memory space.
*/
struct PCMmap {
ulong ca; /* card address */
ulong cea; /* card end address */
ulong isa; /* local virtual address */
int len; /* length of the ISA area */
int attr; /* attribute memory */
};
/*
* a PCMCIA configuration entry
*/
struct PCMconftab
{
int index;
ushort irqs; /* legal irqs */
uchar irqtype;
uchar bit16; /* true for 16 bit access */
struct {
ulong start;
ulong len;
} io[16];
int nio;
uchar vpp1;
uchar vpp2;
uchar memwait;
ulong maxwait;
ulong readywait;
ulong otherwait;
};
/*
* PCMCIA card slot
*/
struct PCMslot
{
RWlock;
Ref ref;
long memlen; /* memory length */
uchar slotno; /* slot number */
void *regs; /* i/o registers */
void *mem; /* memory */
void *attr; /* attribute memory */
/* status */
uchar occupied; /* card in the slot */
uchar configed; /* card configured */
uchar inserted; /* card just inserted */
Dev *dev; /* set in ctlwrite `configure' */
/* cis info */
int cisread; /* set when the cis has been read */
char verstr[512]; /* version string */
int ncfg; /* number of configurations */
struct {
ushort cpresent; /* config registers present */
ulong caddr; /* relative address of config registers */
} cfg[8];
int nctab; /* number of config table entries */
PCMconftab ctab[8];
PCMconftab *def; /* default conftab */
/* maps are fixed */
PCMmap memmap;
PCMmap attrmap;
};
/*
* hardware info about a device
*/
typedef struct {
ulong port;
int size;
} Devport;
struct DevConf
{
RWlock; /* write: configure/unconfigure/suspend; read: normal access */
ulong mem; /* mapped memory address */
Devport *ports; /* ports[0]: mapped i/o regs, access size */
int nports; /* always 1 for the bitsy */
int itype; /* type of interrupt */
ulong intnum; /* interrupt number */
char *type; /* card type, mallocated */
};

View file

@ -1,291 +0,0 @@
#include <u.h>
#include <libc.h>
#include <draw.h>
/*
* /tmp/latin1.6x13, in uncompressed form
*/
uchar
defontdata[] =
{
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x35,0x33,0x36,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x33,0x20,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2a,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x41,0x0e,0x00,0x60,0xc2,0x0a,0x00,
0x00,0x00,0x60,0xc2,0x00,0x60,0xc2,0x00,0x00,0xa6,0x0c,0x20,0xa0,0x00,0x01,0x83,
0x08,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x0c,0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x00,0x00,0x00,0x3f,
0x30,0x03,0x1c,0x30,0x00,0x00,0x00,0x83,0x00,0x41,0x02,0x00,0x31,0x85,0x14,0x51,
0xc0,0x00,0x31,0x85,0x14,0x31,0x85,0x14,0x01,0x43,0x18,0x51,0x45,0x00,0x08,0xc6,
0x14,0x51,0x86,0x1c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,
0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x08,0x00,0x0c,0x00,0x73,0xe0,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x85,0x00,0x71,0x24,0x0c,0x11,0x00,0x00,0x00,0x00,0x02,
0x20,0x87,0x3e,0x13,0xe7,0x3e,0x71,0xc0,0x00,0x08,0x08,0x1c,0x70,0x8f,0x1c,0xf3,
0xef,0x9c,0x89,0xc3,0xa2,0x82,0x28,0x9c,0xf1,0xcf,0x1c,0xfa,0x28,0xa2,0x8a,0x2f,
0x9c,0x81,0xc2,0x00,0x30,0x08,0x00,0x08,0x03,0x00,0x80,0x00,0x20,0x60,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x23,0x04,0xaa,0x8f,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x0c,0x80,0x00,0x02,0x22,0x12,0x00,0xc0,0x80,0x00,0x03,0x00,
0x48,0x04,0x82,0x60,0x06,0xc0,0x00,0x84,0x80,0x49,0x24,0x08,0x00,0x08,0x80,0x01,
0x40,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x88,0x00,0x00,0x70,0x00,
0x00,0x00,0x04,0x22,0x60,0xc5,0x0a,0x00,0x00,0x00,0x60,0xc5,0x00,0x60,0xc5,0x00,
0x09,0x46,0x0c,0x51,0x40,0x00,0x01,0x83,0x14,0x00,0xc8,0x00,0x1b,0xe0,0x00,0x03,
0x84,0x00,0xc0,0x00,0x00,0xf0,0x0e,0x38,0xc3,0x0c,0x30,0xc2,0x4e,0x38,0x63,0x8e,
0x38,0xe3,0x8c,0x28,0x00,0x85,0x14,0xa2,0xaa,0x08,0x20,0x82,0x00,0x00,0x00,0x02,
0x51,0x88,0x82,0x12,0x08,0x82,0x8a,0x20,0x00,0x10,0x04,0x22,0x89,0x44,0xa2,0x4a,
0x08,0x22,0x88,0x81,0x22,0x82,0x2c,0xa2,0x8a,0x28,0xa2,0x22,0x28,0xa2,0x8a,0x20,
0x90,0x80,0x45,0x00,0x10,0x08,0x00,0x08,0x04,0x80,0x80,0x81,0x20,0x20,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x08,0x20,0x8a,0x94,0x77,0xff,0xff,0x1e,
0xff,0xcf,0xff,0xff,0xc3,0xfc,0x71,0xcf,0x3c,0xf3,0xcf,0x6c,0x71,0xe7,0x1c,0x71,
0xc7,0x3c,0x73,0xd7,0x00,0x02,0x00,0x8a,0x22,0x10,0x51,0x23,0x82,0x00,0x04,0x80,
0x48,0x01,0x0c,0x00,0x0a,0x80,0x00,0x84,0xa0,0x51,0x42,0x80,0x71,0xc7,0x1c,0x71,
0xc7,0xa2,0xfb,0xef,0xbe,0x71,0xc7,0x1c,0x4a,0x27,0x1c,0x71,0xc7,0x00,0x9a,0x28,
0xa2,0x8a,0x27,0x22,0x31,0x88,0x94,0x51,0xc0,0x00,0x31,0x88,0x94,0x31,0x88,0x94,
0x7e,0x83,0x18,0x8a,0x85,0x0c,0x00,0xc6,0x22,0x51,0x88,0x14,0x9f,0xee,0x38,0xe2,
0x0a,0x08,0xa2,0x88,0x22,0x81,0xc8,0x20,0xa2,0x8a,0x28,0xa3,0x48,0x20,0x92,0x08,
0x20,0x82,0x0a,0x28,0x00,0x85,0x14,0xa1,0x4a,0x10,0x20,0x8a,0x88,0x00,0x00,0x04,
0x8a,0x88,0x84,0x32,0x08,0x04,0x8a,0x22,0x08,0x20,0x02,0x22,0x8a,0x24,0xa0,0x4a,
0x08,0x20,0x88,0x81,0x24,0x83,0x6c,0xa2,0x8a,0x28,0xa0,0x22,0x28,0xa2,0x51,0x41,
0x10,0x40,0x48,0x80,0x08,0x08,0x00,0x08,0x04,0x00,0x80,0x00,0x20,0x20,0x00,0x00,
0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x08,0x20,0x89,0x2a,0x74,0x71,0xc7,0x7d,
0x7d,0xd7,0x5d,0xf7,0x5f,0x8d,0xf7,0xd7,0x5d,0x75,0xd7,0x2d,0xf7,0xdb,0x7d,0xf7,
0xdf,0x5d,0xf5,0xd7,0x00,0x82,0x0c,0x71,0x42,0x10,0x02,0x14,0x84,0x00,0x08,0x40,
0x48,0x82,0x02,0x00,0x0a,0x80,0x00,0x83,0x10,0x20,0x8d,0x08,0x8a,0x28,0xa2,0x8a,
0x2a,0x20,0x82,0x08,0x20,0x20,0x82,0x08,0x4b,0x28,0xa2,0x8a,0x28,0x80,0x9a,0x28,
0xa2,0x89,0x44,0xa6,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x08,0x00,0x00,0x00,0x00,0x0c,0x08,0x00,0x00,0x00,0x08,0x00,0xff,0xe8,0x20,0x83,
0x8a,0x1c,0xc2,0x88,0x22,0xe2,0x0e,0x38,0xa2,0x8a,0x28,0xa2,0xce,0x30,0x83,0x8e,
0x38,0xe2,0x8c,0x28,0x00,0x80,0x3e,0x70,0x44,0x00,0x40,0x4f,0x88,0x00,0x00,0x04,
0x88,0x80,0x88,0x52,0xc8,0x04,0x8a,0x27,0x1c,0x43,0xe1,0x02,0x9a,0x24,0xa0,0x4a,
0x08,0x20,0x88,0x81,0x28,0x82,0xaa,0xa2,0x8a,0x28,0xa0,0x22,0x28,0xa2,0x51,0x41,
0x10,0x40,0x40,0x00,0x01,0xcf,0x1c,0x79,0xc4,0x1c,0xb1,0x83,0x24,0x23,0x4b,0x1c,
0xf1,0xeb,0x1c,0xf2,0x28,0xa2,0x8a,0x2f,0x88,0x20,0x80,0x14,0xf5,0xf7,0xdf,0x1d,
0x78,0xcf,0x5d,0xf7,0x47,0x7c,0x71,0xd7,0x5d,0x75,0xd7,0x4c,0x73,0xdf,0x1c,0x71,
0xc7,0x3d,0x73,0xd7,0x00,0x87,0x12,0x51,0x42,0x1c,0x02,0xd4,0x8a,0xf8,0x0b,0x40,
0x30,0x87,0x9c,0x01,0x2a,0x80,0x00,0x80,0x28,0x49,0x42,0x88,0x8a,0x28,0xa2,0x8a,
0x2a,0x20,0x82,0x08,0x20,0x20,0x82,0x08,0x4b,0x28,0xa2,0x8a,0x28,0xa1,0xaa,0x28,
0xa2,0x89,0x44,0xac,0x71,0xc7,0x1c,0x71,0xcf,0x1c,0x71,0xc7,0x1c,0x61,0x86,0x18,
0x7a,0xc7,0x1c,0x71,0xc7,0x00,0x72,0x28,0xa2,0x8a,0x2f,0x22,0x1b,0xee,0x38,0xc2,
0x0e,0x1c,0xa3,0x88,0x14,0x82,0x02,0x08,0xa2,0x8a,0x28,0xa2,0x42,0x20,0x92,0x02,
0x20,0x82,0x8a,0x28,0x00,0x80,0x14,0x28,0x8a,0x00,0x40,0x47,0x3e,0x03,0xe0,0x08,
0x88,0x81,0x1c,0x53,0x2f,0x08,0x71,0xe2,0x08,0x80,0x00,0x84,0xaa,0x27,0x20,0x4b,
0xcf,0x20,0xf8,0x81,0x30,0x82,0xaa,0xa2,0xf2,0x2f,0x1c,0x22,0x25,0x2a,0x20,0x82,
0x10,0x20,0x40,0x00,0x00,0x28,0xa2,0x8a,0x2f,0x22,0xc8,0x81,0x28,0x22,0xac,0xa2,
0x8a,0x2c,0xa2,0x42,0x28,0xa2,0x52,0x21,0x30,0x20,0x60,0x2a,0xec,0x71,0xcf,0x7c,
0x78,0xd7,0x1d,0xfa,0xdf,0x7f,0x7d,0xd7,0x5d,0x75,0xd7,0x6f,0x77,0xdb,0x7f,0x77,
0xdf,0x5d,0x75,0xd7,0x00,0x8a,0x90,0x50,0x80,0x12,0x02,0x93,0x94,0x09,0xea,0x40,
0x03,0xe0,0x00,0x01,0x26,0x8c,0x00,0x07,0x94,0x9a,0xa5,0x90,0x8a,0x28,0xa2,0x8a,
0x2b,0xa0,0xf3,0xcf,0x3c,0x20,0x82,0x08,0xea,0xa8,0xa2,0x8a,0x28,0x92,0xaa,0x28,
0xa2,0x88,0x85,0xa6,0x08,0x20,0x82,0x08,0x22,0xa2,0x8a,0x28,0xa2,0x20,0x82,0x08,
0x8b,0x28,0xa2,0x8a,0x28,0x9e,0x9a,0x28,0xa2,0x8a,0x28,0xa2,0x3b,0xe2,0x20,0x83,
0x8a,0x14,0xc2,0x8e,0x08,0x81,0xce,0x38,0xc3,0x0c,0x30,0xc2,0x4e,0x38,0x63,0x8e,
0x38,0x83,0x8a,0x10,0x00,0x80,0x3e,0x29,0x09,0x80,0x40,0x4f,0x88,0x00,0x00,0x10,
0x88,0x82,0x02,0x90,0x28,0x88,0x88,0x20,0x00,0x40,0x01,0x08,0xab,0xe4,0xa0,0x4a,
0x08,0x26,0x88,0x81,0x28,0x82,0x29,0xa2,0x82,0x2a,0x02,0x22,0x25,0x2a,0x50,0x84,
0x10,0x10,0x40,0x00,0x01,0xe8,0xa0,0x8b,0xe4,0x22,0x88,0x81,0x30,0x22,0xa8,0xa2,
0x8a,0x28,0x18,0x42,0x28,0xaa,0x22,0x22,0x08,0x20,0x80,0x14,0xdf,0x77,0xdf,0x1d,
0x7a,0xcf,0x5c,0x7d,0xdf,0x8c,0x71,0xcf,0x3c,0xf3,0xcf,0x6c,0x71,0xe7,0x1c,0x71,
0xdf,0x5c,0x75,0xef,0x00,0x8a,0x3c,0x53,0xe2,0x0e,0x02,0xd0,0x28,0x09,0xea,0x40,
0x00,0x80,0x00,0x01,0x22,0x8c,0x00,0x00,0x0a,0x28,0x2a,0xa0,0xfb,0xef,0xbe,0xfb,
0xee,0x20,0x82,0x08,0x20,0x20,0x82,0x08,0x4a,0xa8,0xa2,0x8a,0x28,0x8c,0xaa,0x28,
0xa2,0x88,0x86,0x22,0x79,0xe7,0x9e,0x79,0xe7,0xa0,0xfb,0xef,0xbe,0x20,0x82,0x08,
0x8a,0x28,0xa2,0x8a,0x28,0x9e,0xaa,0x28,0xa2,0x8a,0x28,0xa2,0x33,0xee,0x38,0xf0,
0xc5,0x3e,0x72,0x87,0x00,0x79,0xc0,0x00,0x20,0x01,0x0e,0x18,0xa4,0x98,0x49,0x16,
0x1c,0x71,0xc7,0x1c,0x00,0x80,0x14,0x71,0x49,0x00,0x20,0x8a,0x88,0x00,0x00,0x10,
0x88,0x84,0x02,0xf8,0x28,0x90,0x88,0x20,0x00,0x23,0xe2,0x08,0xb2,0x24,0xa0,0x4a,
0x08,0x22,0x88,0x81,0x24,0x82,0x29,0xa2,0x82,0x29,0x02,0x22,0x25,0x2a,0x50,0x84,
0x10,0x10,0x40,0x00,0x02,0x28,0xa0,0x8a,0x04,0x22,0x88,0x81,0x28,0x22,0xa8,0xa2,
0x8a,0x28,0x04,0x42,0x25,0x2a,0x22,0x64,0x08,0x20,0x80,0x2a,0xdc,0x71,0xc3,0xce,
0xb0,0x63,0x5e,0x3f,0xe1,0x8f,0xff,0xf7,0xff,0xbc,0x79,0xd6,0xd9,0xed,0xba,0x78,
0xe3,0x8e,0x38,0xe3,0x00,0x8a,0x08,0x50,0x82,0x02,0x02,0x17,0x94,0x08,0x08,0x40,
0x00,0x80,0x00,0x01,0x22,0x80,0x00,0x00,0x14,0x48,0x44,0xa2,0x8a,0x28,0xa2,0x8a,
0x2a,0x20,0x82,0x08,0x20,0x20,0x82,0x08,0x4a,0x68,0xa2,0x8a,0x28,0x8c,0xca,0x28,
0xa2,0x88,0x84,0x22,0x8a,0x28,0xa2,0x8a,0x2a,0x20,0x82,0x08,0x20,0x20,0x82,0x08,
0x8a,0x28,0xa2,0x8a,0x28,0x80,0xaa,0x28,0xa2,0x8a,0x68,0xa6,0x33,0xe4,0x92,0x41,
0x25,0x08,0x41,0xc4,0x3e,0x41,0x23,0x04,0x20,0x42,0x82,0x28,0xa6,0x94,0x69,0xb5,
0x10,0x41,0x04,0x10,0x00,0x00,0x14,0x22,0xa6,0x80,0x20,0x82,0x00,0x30,0x02,0x20,
0x50,0x88,0x22,0x12,0x28,0x90,0x8a,0x22,0x0c,0x10,0x04,0x00,0x82,0x24,0xa2,0x4a,
0x08,0x22,0x88,0x89,0x22,0x82,0x28,0xa2,0x82,0xa8,0xa2,0x22,0x22,0x36,0x88,0x88,
0x10,0x08,0x40,0x00,0x02,0x28,0xa2,0x8a,0x24,0x1e,0x88,0x81,0x24,0x22,0xa8,0xa2,
0xf1,0xe8,0x22,0x4a,0x65,0x2a,0x51,0xa8,0x08,0x20,0x80,0x14,0xfe,0xdb,0x6f,0xb6,
0xbd,0xef,0x8e,0xf0,0x6f,0xb7,0x3e,0xf7,0xef,0x5f,0x75,0xd6,0x5a,0xe5,0x92,0xbb,
0xef,0xbe,0xfb,0xef,0x00,0x8a,0xbc,0x73,0xe2,0x02,0x01,0x20,0x0a,0x00,0x04,0x80,
0x03,0xe0,0x00,0x01,0x62,0x80,0x00,0x00,0x28,0x78,0x87,0xa2,0x8a,0x28,0xa2,0x8a,
0x2a,0x22,0x82,0x08,0x20,0x20,0x82,0x08,0x4a,0x68,0xa2,0x8a,0x28,0x92,0xca,0x28,
0xa2,0x88,0x84,0x26,0x8a,0x28,0xa2,0x8a,0x2a,0xa2,0x8a,0x28,0xa2,0x20,0x82,0x08,
0x8a,0x28,0xa2,0x8a,0x28,0x8c,0xca,0x69,0xa6,0x99,0xa8,0x9a,0x03,0xe3,0x0c,0x61,
0x26,0x00,0x70,0x86,0x08,0x71,0xc4,0x84,0x20,0x41,0x04,0x48,0xc5,0x98,0x59,0x56,
0x1c,0x71,0xc7,0x1c,0x00,0x80,0x00,0x02,0x40,0x00,0x11,0x00,0x00,0x20,0x07,0x20,
0x23,0xef,0x9c,0x11,0xc7,0x10,0x71,0xc7,0x08,0x08,0x08,0x08,0x7a,0x2f,0x1c,0xf3,
0xe8,0x1c,0x89,0xc6,0x22,0xfa,0x28,0x9c,0x81,0xc8,0x9c,0x21,0xc2,0x22,0x88,0x8f,
0x9c,0x09,0xc0,0x00,0x01,0xef,0x1c,0x79,0xc4,0x02,0x89,0xc9,0x22,0x72,0x28,0x9c,
0x80,0x28,0x1c,0x31,0xa2,0x14,0x88,0x2f,0x86,0x23,0x00,0x2a,0xdf,0x3c,0xe7,0xb6,
0x7f,0xe3,0xde,0x7d,0xe3,0x8e,0xde,0xf7,0xef,0xbe,0xed,0xce,0x99,0xe9,0xaa,0x78,
0xe3,0x8e,0x38,0xe3,0xc0,0x87,0x2a,0x88,0x82,0x12,0x00,0xc0,0x04,0x00,0x03,0x00,
0x00,0x00,0x00,0x01,0xa2,0x80,0x10,0x00,0x10,0x08,0xe0,0x9c,0x8a,0x28,0xa2,0x8a,
0x2b,0x9c,0xfb,0xef,0xbe,0x71,0xc7,0x1c,0xf2,0x27,0x1c,0x71,0xc7,0x21,0x71,0xc7,
0x1c,0x70,0x84,0x2c,0x79,0xe7,0x9e,0x79,0xe7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,
0x7a,0x27,0x1c,0x71,0xc7,0x0c,0x71,0xa6,0x9a,0x68,0x2f,0x02,0x03,0xe3,0x0c,0x40,
0xc5,0x00,0x10,0x84,0x08,0x41,0x44,0x84,0x20,0x42,0x02,0x7c,0xa4,0x94,0x49,0x15,
0x04,0x10,0x41,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x02,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x09,0x00,0x00,0x00,0x00,
0x80,0x20,0x00,0x00,0x00,0x00,0x02,0x20,0x00,0x00,0x00,0x14,0xff,0x3c,0xef,0xce,
0xbf,0xfb,0xde,0xfd,0xef,0xae,0xde,0xf7,0xef,0x7f,0x60,0xd6,0xda,0xed,0xba,0xbe,
0xfb,0xef,0xbe,0xfb,0xc0,0x02,0x38,0x00,0x00,0x0c,0x00,0x00,0x02,0x00,0x00,0x00,
0x00,0x00,0x00,0x02,0x00,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,
0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x28,0x22,0x00,0x04,0x92,0x40,
0x24,0x80,0x70,0x84,0x08,0x41,0x23,0x04,0x38,0x43,0x8e,0x08,0x94,0x98,0x49,0x16,
0x1c,0x71,0xc7,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x06,0x00,0x00,0x00,0x00,
0x80,0x20,0x00,0x00,0x00,0x00,0x01,0xc0,0x00,0x00,0x00,0x2a,0x02,0xdb,0x6f,0xf6,
0xdf,0xe3,0xde,0xfd,0xef,0xb7,0x3e,0xf1,0xef,0x1c,0x7d,0xda,0xd9,0xed,0xba,0x78,
0xe3,0x8e,0x38,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xc8,0x1c,
0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x32,0x35,0x36,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x31,0x33,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x31,
0x20,0x00,0x00,0x02,0x0a,0x00,0x06,0x06,0x00,0x02,0x0c,0x00,0x06,0x0c,0x00,0x04,
0x0d,0x00,0x06,0x12,0x00,0x04,0x0d,0x00,0x06,0x18,0x00,0x04,0x0d,0x00,0x06,0x1e,
0x00,0x03,0x0d,0x00,0x06,0x24,0x00,0x03,0x0d,0x00,0x06,0x2a,0x00,0x04,0x0a,0x00,
0x06,0x30,0x00,0x03,0x0d,0x00,0x06,0x36,0x00,0x04,0x0d,0x00,0x06,0x3c,0x00,0x04,
0x0d,0x00,0x06,0x42,0x00,0x04,0x0d,0x00,0x06,0x48,0x00,0x03,0x0d,0x00,0x06,0x4e,
0x00,0x04,0x0d,0x00,0x06,0x54,0x00,0x03,0x0d,0x00,0x06,0x5a,0x00,0x03,0x0d,0x00,
0x06,0x60,0x00,0x03,0x0d,0x00,0x06,0x66,0x00,0x03,0x0d,0x00,0x06,0x6c,0x00,0x03,
0x0d,0x00,0x06,0x72,0x00,0x03,0x0d,0x00,0x06,0x78,0x00,0x03,0x0d,0x00,0x06,0x7e,
0x00,0x03,0x0d,0x00,0x06,0x84,0x00,0x03,0x0d,0x00,0x06,0x8a,0x00,0x03,0x0d,0x00,
0x06,0x90,0x00,0x03,0x0d,0x00,0x06,0x96,0x00,0x03,0x0d,0x00,0x06,0x9c,0x00,0x03,
0x0d,0x00,0x06,0xa2,0x00,0x03,0x0d,0x00,0x06,0xa8,0x00,0x03,0x0d,0x00,0x06,0xae,
0x00,0x03,0x0d,0x00,0x06,0xb4,0x00,0x03,0x0d,0x00,0x06,0xba,0x00,0x03,0x0d,0x00,
0x06,0xc0,0x00,0x00,0x00,0x00,0x06,0xc6,0x00,0x02,0x0b,0x00,0x06,0xcc,0x00,0x02,
0x05,0x00,0x06,0xd2,0x00,0x03,0x0a,0x00,0x06,0xd8,0x00,0x01,0x0a,0x00,0x06,0xde,
0x00,0x02,0x0b,0x00,0x06,0xe4,0x00,0x02,0x0a,0x00,0x06,0xea,0x00,0x02,0x05,0x00,
0x06,0xf0,0x00,0x02,0x0b,0x00,0x06,0xf6,0x00,0x02,0x0b,0x00,0x06,0xfc,0x00,0x03,
0x0a,0x00,0x06,0x02,0x01,0x04,0x09,0x00,0x06,0x08,0x01,0x09,0x0c,0x00,0x06,0x0e,
0x01,0x06,0x07,0x00,0x06,0x14,0x01,0x09,0x0c,0x00,0x06,0x1a,0x01,0x02,0x0b,0x00,
0x06,0x20,0x01,0x02,0x0b,0x00,0x06,0x26,0x01,0x02,0x0b,0x00,0x06,0x2c,0x01,0x02,
0x0b,0x00,0x06,0x32,0x01,0x02,0x0b,0x00,0x06,0x38,0x01,0x02,0x0b,0x00,0x06,0x3e,
0x01,0x02,0x0b,0x00,0x06,0x44,0x01,0x02,0x0b,0x00,0x06,0x4a,0x01,0x02,0x0b,0x00,
0x06,0x50,0x01,0x02,0x0b,0x00,0x06,0x56,0x01,0x02,0x0b,0x00,0x06,0x5c,0x01,0x00,
0x0d,0x00,0x06,0x62,0x01,0x00,0x0d,0x00,0x06,0x68,0x01,0x02,0x0b,0x00,0x06,0x6e,
0x01,0x00,0x0d,0x00,0x06,0x74,0x01,0x02,0x0b,0x00,0x06,0x7a,0x01,0x02,0x0b,0x00,
0x06,0x80,0x01,0x02,0x0b,0x00,0x06,0x86,0x01,0x02,0x0b,0x00,0x06,0x8c,0x01,0x02,
0x0b,0x00,0x06,0x92,0x01,0x02,0x0b,0x00,0x06,0x98,0x01,0x02,0x0b,0x00,0x06,0x9e,
0x01,0x02,0x0b,0x00,0x06,0xa4,0x01,0x02,0x0b,0x00,0x06,0xaa,0x01,0x02,0x0b,0x00,
0x06,0xb0,0x01,0x02,0x0b,0x00,0x06,0xb6,0x01,0x02,0x0b,0x00,0x06,0xbc,0x01,0x02,
0x0b,0x00,0x06,0xc2,0x01,0x02,0x0b,0x00,0x06,0xc8,0x01,0x02,0x0b,0x00,0x06,0xce,
0x01,0x02,0x0b,0x00,0x06,0xd4,0x01,0x02,0x0b,0x00,0x06,0xda,0x01,0x02,0x0b,0x00,
0x06,0xe0,0x01,0x02,0x0b,0x00,0x06,0xe6,0x01,0x02,0x0c,0x00,0x06,0xec,0x01,0x02,
0x0b,0x00,0x06,0xf2,0x01,0x02,0x0b,0x00,0x06,0xf8,0x01,0x02,0x0b,0x00,0x06,0xfe,
0x01,0x02,0x0b,0x00,0x06,0x04,0x02,0x02,0x0b,0x00,0x06,0x0a,0x02,0x02,0x0b,0x00,
0x06,0x10,0x02,0x02,0x0b,0x00,0x06,0x16,0x02,0x02,0x0b,0x00,0x06,0x1c,0x02,0x02,
0x0b,0x00,0x06,0x22,0x02,0x02,0x0b,0x00,0x06,0x28,0x02,0x02,0x0b,0x00,0x06,0x2e,
0x02,0x02,0x0b,0x00,0x06,0x34,0x02,0x02,0x05,0x00,0x06,0x3a,0x02,0x0b,0x0c,0x00,
0x06,0x40,0x02,0x02,0x05,0x00,0x06,0x46,0x02,0x05,0x0b,0x00,0x06,0x4c,0x02,0x02,
0x0b,0x00,0x06,0x52,0x02,0x05,0x0b,0x00,0x06,0x58,0x02,0x02,0x0b,0x00,0x06,0x5e,
0x02,0x05,0x0b,0x00,0x06,0x64,0x02,0x02,0x0b,0x00,0x06,0x6a,0x02,0x05,0x0d,0x00,
0x06,0x70,0x02,0x02,0x0b,0x00,0x06,0x76,0x02,0x03,0x0b,0x00,0x06,0x7c,0x02,0x03,
0x0d,0x00,0x06,0x82,0x02,0x02,0x0b,0x00,0x06,0x88,0x02,0x02,0x0b,0x00,0x06,0x8e,
0x02,0x05,0x0b,0x00,0x06,0x94,0x02,0x05,0x0b,0x00,0x06,0x9a,0x02,0x05,0x0b,0x00,
0x06,0xa0,0x02,0x05,0x0d,0x00,0x06,0xa6,0x02,0x05,0x0d,0x00,0x06,0xac,0x02,0x05,
0x0b,0x00,0x06,0xb2,0x02,0x05,0x0b,0x00,0x06,0xb8,0x02,0x03,0x0b,0x00,0x06,0xbe,
0x02,0x05,0x0b,0x00,0x06,0xc4,0x02,0x05,0x0b,0x00,0x06,0xca,0x02,0x05,0x0b,0x00,
0x06,0xd0,0x02,0x05,0x0b,0x00,0x06,0xd6,0x02,0x05,0x0d,0x00,0x06,0xdc,0x02,0x05,
0x0b,0x00,0x06,0xe2,0x02,0x02,0x0b,0x00,0x06,0xe8,0x02,0x02,0x0b,0x00,0x06,0xee,
0x02,0x02,0x0b,0x00,0x06,0xf4,0x02,0x02,0x05,0x00,0x06,0xfa,0x02,0x00,0x0d,0x00,
0x06,0x00,0x03,0x00,0x0c,0x00,0x06,0x06,0x03,0x00,0x0d,0x00,0x06,0x0c,0x03,0x00,
0x0d,0x00,0x06,0x12,0x03,0x00,0x0d,0x00,0x06,0x18,0x03,0x00,0x0d,0x00,0x06,0x1e,
0x03,0x00,0x0d,0x00,0x06,0x24,0x03,0x00,0x0d,0x00,0x06,0x2a,0x03,0x00,0x0d,0x00,
0x06,0x30,0x03,0x00,0x0d,0x00,0x06,0x36,0x03,0x00,0x0d,0x00,0x06,0x3c,0x03,0x00,
0x0d,0x00,0x06,0x42,0x03,0x00,0x0d,0x00,0x06,0x48,0x03,0x00,0x0d,0x00,0x06,0x4e,
0x03,0x00,0x0d,0x00,0x06,0x54,0x03,0x00,0x0d,0x00,0x06,0x5a,0x03,0x00,0x0d,0x00,
0x06,0x60,0x03,0x00,0x0d,0x00,0x06,0x66,0x03,0x00,0x0d,0x00,0x06,0x6c,0x03,0x00,
0x0d,0x00,0x06,0x72,0x03,0x00,0x0d,0x00,0x06,0x78,0x03,0x00,0x0d,0x00,0x06,0x7e,
0x03,0x00,0x0d,0x00,0x06,0x84,0x03,0x00,0x0d,0x00,0x06,0x8a,0x03,0x00,0x0d,0x00,
0x06,0x90,0x03,0x00,0x0d,0x00,0x06,0x96,0x03,0x00,0x0d,0x00,0x06,0x9c,0x03,0x00,
0x0d,0x00,0x06,0xa2,0x03,0x00,0x0d,0x00,0x06,0xa8,0x03,0x00,0x0d,0x00,0x00,0xae,
0x03,0x00,0x0d,0x00,0x00,0xb4,0x03,0x00,0x0d,0x00,0x00,0xba,0x03,0x00,0x0d,0x00,
0x00,0xc0,0x03,0x01,0x0c,0x00,0x06,0xc6,0x03,0x02,0x0b,0x00,0x06,0xcc,0x03,0x03,
0x0c,0x00,0x06,0xd2,0x03,0x04,0x0c,0x00,0x06,0xd8,0x03,0x03,0x0b,0x00,0x06,0xde,
0x03,0x02,0x0b,0x00,0x06,0xe4,0x03,0x02,0x0b,0x00,0x06,0xea,0x03,0x01,0x0c,0x00,
0x06,0xf0,0x03,0x03,0x04,0x00,0x06,0xf6,0x03,0x02,0x0b,0x00,0x06,0xfc,0x03,0x01,
0x09,0x00,0x06,0x02,0x04,0x03,0x0c,0x00,0x06,0x08,0x04,0x05,0x09,0x00,0x06,0x0e,
0x04,0x06,0x08,0x00,0x06,0x14,0x04,0x02,0x0b,0x00,0x06,0x1a,0x04,0x01,0x02,0x00,
0x06,0x20,0x04,0x01,0x06,0x00,0x06,0x26,0x04,0x04,0x0a,0x00,0x06,0x2c,0x04,0x01,
0x06,0x00,0x06,0x32,0x04,0x01,0x06,0x00,0x06,0x38,0x04,0x00,0x03,0x00,0x06,0x3e,
0x04,0x05,0x0c,0x00,0x06,0x44,0x04,0x02,0x0b,0x00,0x06,0x4a,0x04,0x06,0x08,0x00,
0x06,0x50,0x04,0x0a,0x0d,0x00,0x06,0x56,0x04,0x01,0x06,0x00,0x06,0x5c,0x04,0x01,
0x07,0x00,0x06,0x62,0x04,0x03,0x0c,0x00,0x06,0x68,0x04,0x00,0x0b,0x00,0x06,0x6e,
0x04,0x00,0x0b,0x00,0x06,0x74,0x04,0x00,0x0b,0x00,0x06,0x7a,0x04,0x02,0x0b,0x00,
0x06,0x80,0x04,0x00,0x0b,0x00,0x06,0x86,0x04,0x00,0x0b,0x00,0x06,0x8c,0x04,0x00,
0x0b,0x00,0x06,0x92,0x04,0x00,0x0b,0x00,0x06,0x98,0x04,0x01,0x0b,0x00,0x06,0x9e,
0x04,0x01,0x0b,0x00,0x06,0xa4,0x04,0x03,0x0b,0x00,0x06,0xaa,0x04,0x02,0x0d,0x00,
0x06,0xb0,0x04,0x00,0x0b,0x00,0x06,0xb6,0x04,0x00,0x0b,0x00,0x06,0xbc,0x04,0x00,
0x0b,0x00,0x06,0xc2,0x04,0x01,0x0b,0x00,0x06,0xc8,0x04,0x00,0x0b,0x00,0x06,0xce,
0x04,0x00,0x0b,0x00,0x06,0xd4,0x04,0x00,0x0b,0x00,0x06,0xda,0x04,0x01,0x0b,0x00,
0x06,0xe0,0x04,0x02,0x0b,0x00,0x06,0xe6,0x04,0x00,0x0b,0x00,0x06,0xec,0x04,0x00,
0x0b,0x00,0x06,0xf2,0x04,0x00,0x0b,0x00,0x06,0xf8,0x04,0x00,0x0b,0x00,0x06,0xfe,
0x04,0x00,0x0b,0x00,0x06,0x04,0x05,0x01,0x0b,0x00,0x06,0x0a,0x05,0x05,0x0b,0x00,
0x06,0x10,0x05,0x01,0x0c,0x00,0x06,0x16,0x05,0x00,0x0b,0x00,0x06,0x1c,0x05,0x00,
0x0b,0x00,0x06,0x22,0x05,0x00,0x0b,0x00,0x06,0x28,0x05,0x01,0x0b,0x00,0x06,0x2e,
0x05,0x00,0x0b,0x00,0x06,0x34,0x05,0x01,0x0b,0x00,0x06,0x3a,0x05,0x01,0x0c,0x00,
0x06,0x40,0x05,0x02,0x0b,0x00,0x06,0x46,0x05,0x02,0x0b,0x00,0x06,0x4c,0x05,0x01,
0x0b,0x00,0x06,0x52,0x05,0x02,0x0b,0x00,0x06,0x58,0x05,0x03,0x0b,0x00,0x06,0x5e,
0x05,0x03,0x0b,0x00,0x06,0x64,0x05,0x05,0x0b,0x00,0x06,0x6a,0x05,0x05,0x0d,0x00,
0x06,0x70,0x05,0x02,0x0b,0x00,0x06,0x76,0x05,0x02,0x0b,0x00,0x06,0x7c,0x05,0x01,
0x0b,0x00,0x06,0x82,0x05,0x03,0x0b,0x00,0x06,0x88,0x05,0x02,0x0b,0x00,0x06,0x8e,
0x05,0x02,0x0b,0x00,0x06,0x94,0x05,0x01,0x0b,0x00,0x06,0x9a,0x05,0x03,0x0b,0x00,
0x06,0xa0,0x05,0x02,0x0b,0x00,0x06,0xa6,0x05,0x02,0x0b,0x00,0x06,0xac,0x05,0x02,
0x0b,0x00,0x06,0xb2,0x05,0x02,0x0b,0x00,0x06,0xb8,0x05,0x01,0x0b,0x00,0x06,0xbe,
0x05,0x02,0x0b,0x00,0x06,0xc4,0x05,0x03,0x0b,0x00,0x06,0xca,0x05,0x03,0x0b,0x00,
0x06,0xd0,0x05,0x04,0x0c,0x00,0x06,0xd6,0x05,0x02,0x0b,0x00,0x06,0xdc,0x05,0x02,
0x0b,0x00,0x06,0xe2,0x05,0x01,0x0b,0x00,0x06,0xe8,0x05,0x03,0x0b,0x00,0x06,0xee,
0x05,0x02,0x0d,0x00,0x06,0xf4,0x05,0x01,0x0d,0x00,0x06,0xfa,0x05,0x03,0x0d,0x00,
0x06,0x00,0x06,0x00,0x00,0x00,0x00,
};
int sizeofdefont = sizeof defontdata;
void
_unpackinfo(Fontchar *fc, uchar *p, int n)
{
int j;
for(j=0; j<=n; j++){
fc->x = p[0]|(p[1]<<8);
fc->top = p[2];
fc->bottom = p[3];
fc->left = p[4];
fc->width = p[5];
fc++;
p += 6;
}
}

View file

@ -1,594 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
static volatile Ether *etherxx[MaxEther];
static struct {
char* type;
int (*reset)(Ether*);
} cards[MaxEther+1];
void
addethercard(char* t, int (*r)(Ether*))
{
static int ncard;
if(ncard == MaxEther)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
}
void
etherpower(int on)
{
int i;
Ether *ether;
/* Power all ether cards on or off */
iprint("etherpower %d\n", on);
for (i = 0; i < MaxEther; i++){
if ((ether = etherxx[i]) == nil)
continue;
if(on){
if (ether->writer == 0){
print("etherpower: already powered up\n");
continue;
}
if (ether->power)
ether->power(ether, on);
wunlock(ether);
/* Unlock when power restored */
}else{
if (ether->writer != 0){
print("etherpower: already powered down\n");
continue;
}
/* Keep locked until power goes back on */
wlock(ether);
if (ether->power)
ether->power(ether, on);
}
}
}
int
etherconfig(int on, char *spec, DevConf *cf)
{
Ether *ether;
int n, ctlrno;
char name[32], buf[128];
char *p, *e;
ctlrno = atoi(spec);
sprint(name, "ether%d", ctlrno);
if(on == 0)
return -1;
if(etherxx[ctlrno] != nil)
return -1;
ether = malloc(sizeof(Ether));
if(ether == nil)
panic("etherconfig");
ether->DevConf = *cf;
for(n = 0; cards[n].type; n++){
if(strcmp(cards[n].type, ether->type) != 0)
continue;
if(cards[n].reset(ether))
break;
if(ether->mbps >= 100){
netifinit(ether, name, Ntypes, 256*1024);
if(ether->oq == 0)
ether->oq = qopen(256*1024, Qmsg, 0, 0);
}
else{
netifinit(ether, name, Ntypes, 65*1024);
if(ether->oq == 0)
ether->oq = qopen(65*1024, Qmsg, 0, 0);
}
if(ether->oq == 0)
panic("etherreset %s", name);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(ether->interrupt != nil)
intrenable(cf->itype, cf->intnum, ether->interrupt, ether, name);
p = buf;
e = buf+sizeof(buf);
p = seprint(p, e, "#l%d: %s: %dMbps port 0x%luX",
ctlrno, ether->type, ether->mbps, ether->ports[0].port);
if(ether->mem)
p = seprint(p, e, " addr 0x%luX", PADDR(ether->mem));
if(ether->ports[0].size)
p = seprint(p, e, " size 0x%X", ether->ports[0].size);
p = seprint(p, e, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
seprint(p, e, "\n");
print("%s", buf);
etherxx[ctlrno] = ether;
return 0;
}
if (ether->type)
free(ether->type);
free(ether);
return -1;
}
Chan*
etherattach(char* spec)
{
ulong ctlrno;
char *p;
Chan *chan;
Ether *ether;
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
error(Ebadarg);
}
if((ether = etherxx[ctlrno]) == 0)
error(Enodev);
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
chan = devattach('l', spec);
chan->dev = ctlrno;
if(ether->attach)
ether->attach(ether);
poperror();
runlock(ether);
return chan;
}
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
Walkqid *q;
Ether *ether;
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
q = netifwalk(ether, chan, nchan, name, nname);
poperror();
runlock(ether);
return q;
}
static int
etherstat(Chan* chan, uchar* dp, int n)
{
int s;
Ether *ether;
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
s = netifstat(ether, chan, dp, n);
poperror();
runlock(ether);
return s;
}
static Chan*
etheropen(Chan* chan, int omode)
{
Chan *c;
Ether *ether;
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
c = netifopen(ether, chan, omode);
poperror();
runlock(ether);
return c;
}
static void
ethercreate(Chan*, char*, int, ulong)
{
}
static void
etherclose(Chan* chan)
{
Ether *ether;
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
netifclose(ether, chan);
poperror();
runlock(ether);
}
static long
etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
long r;
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid){
r = ether->ifstat(ether, buf, n, offset);
goto out;
}
if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
}
r = netifread(ether, chan, buf, n, offset);
out:
poperror();
runlock(ether);
return r;
}
static Block*
etherbread(Chan* chan, long n, ulong offset)
{
Block *b;
Ether *ether;
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
b = netifbread(ether, chan, n, offset);
poperror();
runlock(ether);
return b;
}
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
Ether *ether;
int r;
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
r = netifwstat(ether, chan, dp, n);
poperror();
runlock(ether);
return r;
}
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
int i, n;
Block *bp;
if(qwindow(f->in) <= 0)
return;
if(len > 58)
n = 58;
else
n = len;
bp = iallocb(64);
if(bp == nil)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(MACHP(0)->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int fromwire)
{
Etherpkt *pkt;
ushort type;
int len, multi, tome, fromme;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = &ether->f[Ntypes];
multi = pkt->d[0] & 1;
/* check for valid multicast addresses */
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(fromwire){
freeb(bp);
bp = 0;
}
return bp;
}
}
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (fromwire != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
if(f = *fp)
if(f->type == type || f->type < 0)
if(tome || multi || f->prom){
/* Don't want to hear bridged packets */
if(f->bridge && !fromwire && !fromme)
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
qpass(f->in, xbp);
}
else
ether->soverflows++;
}
else
etherrtrace(f, pkt, len);
}
}
if(fx){
if(qpass(fx->in, bp) < 0)
ether->soverflows++;
return 0;
}
if(fromwire){
freeb(bp);
return 0;
}
return bp;
}
static int
etheroq(Ether* ether, Block* bp)
{
int len, loopback;
Etherpkt *pkt;
ether->outpackets++;
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
* To enable bridging to work, only packets that were originated
* by this interface are fed back.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
if(etheriq(ether, bp, loopback) == 0)
return len;
qbwrite(ether->oq, bp);
if(ether->transmit != nil)
ether->transmit(ether);
return len;
}
static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
Ether *ether;
Block *bp;
long l;
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
if(NETTYPE(chan->qid.path) != Ndataqid) {
l = netifwrite(ether, chan, buf, n);
if(l >= 0)
goto out;
if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
qnoblock(ether->oq, 1);
goto out;
}
if(ether->ctl!=nil){
l = ether->ctl(ether,buf,n);
goto out;
}
error(Ebadctl);
}
if(n > ether->maxmtu)
error(Etoobig);
if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
memmove(bp->rp, buf, n);
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
bp->wp += n;
l = etheroq(ether, bp);
out:
poperror();
runlock(ether);
return l;
}
static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
Ether *ether;
long n;
n = BLEN(bp);
if(NETTYPE(chan->qid.path) != Ndataqid){
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
}
if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
n = etheroq(ether, bp);
poperror();
runlock(ether);
return n;
}
int
parseether(uchar *to, char *from)
{
char nip[4];
char *p;
int i;
p = from;
for(i = 0; i < 6; i++){
if(*p == 0)
return -1;
nip[0] = *p++;
if(*p == 0)
return -1;
nip[1] = *p++;
nip[2] = 0;
to[i] = strtoul(nip, 0, 16);
if(*p == ':')
p++;
}
return 0;
}
static void
etherreset(void)
{
}
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
Dev etherdevtab = {
'l',
"ether",
etherreset,
devinit,
devshutdown,
etherattach,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
devremove,
etherwstat,
etherpower,
etherconfig,
};

View file

@ -1,876 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
/*
* on the bitsy, all 32 bit accesses to flash are mapped to two 16 bit
* accesses, one to the low half of the chip and the other to the high
* half. Therefore for all command accesses, ushort indices in the
* manuals turn into ulong indices in our code. Also, by copying all
* 16 bit commands to both halves of a 32 bit command, we erase 2
* sectors for each request erase request.
*/
#define mirror(x) (((x)<<16)|(x))
/* this defines a contiguous set of erase blocks of one size */
typedef struct FlashRegion FlashRegion;
struct FlashRegion
{
ulong addr; /* start of region */
ulong end; /* end of region + 1 */
ulong n; /* number of blocks */
ulong size; /* size of each block */
};
/* this defines a particular access algorithm */
typedef struct FlashAlg FlashAlg;
struct FlashAlg
{
int id;
char *name;
void (*identify)(void); /* identify device */
void (*erase)(ulong); /* erase a region */
void (*write)(void*, long, ulong); /* write a region */
};
static void ise_id(void);
static void ise_erase(ulong);
static void ise_write(void*, long, ulong);
static void afs_id(void);
static void afs_erase(ulong);
static void afs_write(void*, long, ulong);
static ulong blockstart(ulong);
static ulong blockend(ulong);
FlashAlg falg[] =
{
{ 1, "Intel/Sharp Extended", ise_id, ise_erase, ise_write },
{ 2, "AMD/Fujitsu Standard", afs_id, afs_erase, afs_write },
};
struct
{
RWlock;
ulong *p;
ushort algid; /* access algorithm */
FlashAlg *alg;
ushort manid; /* manufacturer id */
ushort devid; /* device id */
ulong size; /* size in bytes */
int wbsize; /* size of write buffer */
ulong nr; /* number of regions */
uchar bootprotect;
FlashRegion r[32];
} flash;
enum
{
Maxwchunk= 1024, /* maximum chunk written by one call to falg->write */
};
/*
* common flash interface
*/
static uchar
cfigetc(int off)
{
uchar rv;
flash.p[0x55] = mirror(0x98);
rv = flash.p[off];
flash.p[0x55] = mirror(0xFF);
return rv;
}
static ushort
cfigets(int off)
{
return (cfigetc(off+1)<<8)|cfigetc(off);
}
static ulong
cfigetl(int off)
{
return (cfigetc(off+3)<<24)|(cfigetc(off+2)<<16)|
(cfigetc(off+1)<<8)|cfigetc(off);
}
static void
cfiquery(void)
{
uchar q, r, y;
ulong x, addr;
q = cfigetc(0x10);
r = cfigetc(0x11);
y = cfigetc(0x12);
if(q != 'Q' || r != 'R' || y != 'Y'){
print("cfi query failed: %ux %ux %ux\n", q, r, y);
return;
}
flash.algid = cfigetc(0x13);
flash.size = 1<<(cfigetc(0x27)+1);
flash.wbsize = 1<<(cfigetc(0x2a)+1);
flash.nr = cfigetc(0x2c);
if(flash.nr > nelem(flash.r)){
print("cfi reports > %d regions\n", nelem(flash.r));
flash.nr = nelem(flash.r);
}
addr = 0;
for(q = 0; q < flash.nr; q++){
x = cfigetl(q+0x2d);
flash.r[q].size = 2*256*(x>>16);
flash.r[q].n = (x&0xffff)+1;
flash.r[q].addr = addr;
addr += flash.r[q].size*flash.r[q].n;
flash.r[q].end = addr;
}
}
/*
* flash device interface
*/
enum
{
Qtopdir,
Q2nddir,
Qfctl,
Qfdata,
Maxpart= 8,
};
typedef struct FPart FPart;
struct FPart
{
char *name;
char *ctlname;
ulong start;
ulong end;
};
static FPart part[Maxpart];
#define FQID(p,q) ((p)<<8|(q))
#define FTYPE(q) ((q) & 0xff)
#define FPART(q) (&part[(q) >>8])
static int
gen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
{
Qid q;
FPart *fp;
q.vers = 0;
/* top level directory contains the name of the network */
if(c->qid.path == Qtopdir){
switch(i){
case DEVDOTDOT:
q.path = Qtopdir;
q.type = QTDIR;
devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
break;
case 0:
q.path = Q2nddir;
q.type = QTDIR;
devdir(c, q, "flash", 0, eve, DMDIR|0555, dp);
break;
default:
return -1;
}
return 1;
}
/* second level contains all partitions and their control files */
switch(i) {
case DEVDOTDOT:
q.path = Qtopdir;
q.type = QTDIR;
devdir(c, q, "#F", 0, eve, DMDIR|0555, dp);
break;
default:
if(i >= 2*Maxpart)
return -1;
fp = &part[i>>1];
if(fp->name == nil)
return 0;
if(i & 1){
q.path = FQID(i>>1, Qfdata);
q.type = QTFILE;
devdir(c, q, fp->name, fp->end-fp->start, eve, 0660, dp);
} else {
q.path = FQID(i>>1, Qfctl);
q.type = QTFILE;
devdir(c, q, fp->ctlname, 0, eve, 0660, dp);
}
break;
}
return 1;
}
static FPart*
findpart(char *name)
{
int i;
for(i = 0; i < Maxpart; i++)
if(part[i].name != nil && strcmp(name, part[i].name) == 0)
break;
if(i >= Maxpart)
return nil;
return &part[i];
}
static void
addpart(FPart *fp, char *name, ulong start, ulong end)
{
int i;
char ctlname[64];
if(fp == nil){
if(start >= flash.size || end > flash.size)
error(Ebadarg);
} else {
start += fp->start;
end += fp->start;
if(start >= fp->end || end > fp->end)
error(Ebadarg);
}
if(blockstart(start) != start)
error("must start on erase boundary");
if(blockstart(end) != end && end != flash.size)
error("must end on erase boundary");
fp = findpart(name);
if(fp != nil)
error(Eexist);
for(i = 0; i < Maxpart; i++)
if(part[i].name == nil)
break;
if(i == Maxpart)
error("no more partitions");
fp = &part[i];
kstrdup(&fp->name, name);
snprint(ctlname, sizeof ctlname, "%sctl", name);
kstrdup(&fp->ctlname, ctlname);
fp->start = start;
fp->end = end;
}
static void
rempart(FPart *fp)
{
char *p, *cp;
p = fp->name;
fp->name = nil;
cp = fp->ctlname;
fp->ctlname = nil;
free(p);
free(cp);
}
void
flashinit(void)
{
int i;
flash.p = (ulong*)FLASHZERO;
cfiquery();
for(i = 0; i < nelem(falg); i++)
if(flash.algid == falg[i].id){
flash.alg = &falg[i];
(*flash.alg->identify)();
break;
}
flash.bootprotect = 1;
addpart(nil, "flash", 0, flash.size);
}
static Chan*
flashattach(char* spec)
{
return devattach('F', spec);
}
static Walkqid*
flashwalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name, nname, nil, 0, gen);
}
static int
flashstat(Chan *c, uchar *db, int n)
{
return devstat(c, db, n, nil, 0, gen);
}
static Chan*
flashopen(Chan* c, int omode)
{
omode = openmode(omode);
if(strcmp(up->user, eve)!=0)
error(Eperm);
return devopen(c, omode, nil, 0, gen);
}
static void
flashclose(Chan*)
{
}
static long
flashctlread(FPart *fp, void* a, long n, vlong off)
{
char *buf, *p, *e;
int i;
ulong addr, end;
buf = smalloc(1024);
e = buf + 1024;
p = seprint(buf, e, "0x%-9lux 0x%-9x 0x%-9ux 0x%-9ux\n", fp->end-fp->start,
flash.wbsize, flash.manid, flash.devid);
addr = fp->start;
for(i = 0; i < flash.nr && addr < fp->end; i++)
if(flash.r[i].addr <= addr && flash.r[i].end > addr){
if(fp->end <= flash.r[i].end)
end = fp->end;
else
end = flash.r[i].end;
p = seprint(p, e, "0x%-9lux 0x%-9lux 0x%-9lux\n", addr,
(end-addr)/flash.r[i].size, flash.r[i].size);
addr = end;
}
n = readstr(off, a, n, buf);
free(buf);
return n;
}
static long
flashdataread(FPart *fp, void* a, long n, vlong off)
{
rlock(&flash);
if(waserror()){
runlock(&flash);
nexterror();
}
if(fp->name == nil)
error("partition vanished");
if(!iseve())
error(Eperm);
off += fp->start;
if(off >= fp->end)
n = 0;
if(off+n >= fp->end)
n = fp->end - off;
if(n > 0)
memmove(a, ((uchar*)FLASHZERO)+off, n);
runlock(&flash);
poperror();
return n;
}
static long
flashread(Chan* c, void* a, long n, vlong off)
{
int t;
if(c->qid.type == QTDIR)
return devdirread(c, a, n, nil, 0, gen);
t = FTYPE(c->qid.path);
switch(t){
default:
error(Eperm);
case Qfctl:
n = flashctlread(FPART(c->qid.path), a, n, off);
break;
case Qfdata:
n = flashdataread(FPART(c->qid.path), a, n, off);
break;
}
return n;
}
static void
bootprotect(ulong addr)
{
FlashRegion *r;
if(flash.bootprotect == 0)
return;
if(flash.nr == 0)
error("writing over boot loader disallowed");
r = flash.r;
if(addr >= r->addr && addr < r->addr + r->size)
error("writing over boot loader disallowed");
}
static ulong
blockstart(ulong addr)
{
FlashRegion *r, *e;
ulong x;
r = flash.r;
for(e = &flash.r[flash.nr]; r < e; r++)
if(addr >= r->addr && addr < r->end){
x = addr - r->addr;
x /= r->size;
return r->addr + x*r->size;
}
return (ulong)-1;
}
static ulong
blockend(ulong addr)
{
FlashRegion *r, *e;
ulong x;
r = flash.r;
for(e = &flash.r[flash.nr]; r < e; r++)
if(addr >= r->addr && addr < r->end){
x = addr - r->addr;
x /= r->size;
return r->addr + (x+1)*r->size;
}
return (ulong)-1;
}
static long
flashctlwrite(FPart *fp, char *p, long n)
{
Cmdbuf *cmd;
ulong off;
if(fp == nil)
panic("flashctlwrite");
cmd = parsecmd(p, n);
wlock(&flash);
if(waserror()){
wunlock(&flash);
nexterror();
}
if(strcmp(cmd->f[0], "erase") == 0){
switch(cmd->nf){
case 2:
/* erase a single block in the partition */
off = atoi(cmd->f[1]);
off += fp->start;
if(off >= fp->end)
error("region not in partition");
if(off != blockstart(off))
error("erase must be a block boundary");
bootprotect(off);
(*flash.alg->erase)(off);
break;
case 1:
/* erase the whole partition */
bootprotect(fp->start);
for(off = fp->start; off < fp->end; off = blockend(off))
(*flash.alg->erase)(off);
break;
default:
error(Ebadarg);
}
} else if(strcmp(cmd->f[0], "add") == 0){
if(cmd->nf != 4)
error(Ebadarg);
addpart(fp, cmd->f[1], strtoul(cmd->f[2], nil, 0), strtoul(cmd->f[3], nil, 0));
} else if(strcmp(cmd->f[0], "remove") == 0){
rempart(fp);
} else if(strcmp(cmd->f[0], "protectboot") == 0){
if(cmd->nf == 0 || strcmp(cmd->f[1], "off") != 0)
flash.bootprotect = 1;
else
flash.bootprotect = 0;
} else
error(Ebadarg);
poperror();
wunlock(&flash);
free(cmd);
return n;
}
static long
flashdatawrite(FPart *fp, uchar *p, long n, long off)
{
uchar *end;
int m;
int on;
long ooff;
uchar *buf;
if(fp == nil)
panic("flashctlwrite");
buf = nil;
wlock(&flash);
if(waserror()){
wunlock(&flash);
if(buf != nil)
free(buf);
nexterror();
}
if(fp->name == nil)
error("partition vanished");
if(!iseve())
error(Eperm);
/* can't cross partition boundaries */
off += fp->start;
if(off >= fp->end || off+n > fp->end || n <= 0)
error(Ebadarg);
/* make sure we're not writing the boot sector */
bootprotect(off);
on = n;
/*
* get the data into kernel memory to avoid faults during writing.
* if write is not on a quad boundary or not a multiple of 4 bytes,
* extend with data already in flash.
*/
buf = smalloc(n+8);
m = off & 3;
if(m){
*(ulong*)buf = flash.p[(off)>>2];
n += m;
off -= m;
}
if(n & 3){
n -= n & 3;
*(ulong*)(&buf[n]) = flash.p[(off+n)>>2];
n += 4;
}
memmove(&buf[m], p, on);
/* (*flash.alg->write) can't cross blocks */
ooff = off;
p = buf;
for(end = p + n; p < end; p += m){
m = blockend(off) - off;
if(m > end - p)
m = end - p;
if(m > Maxwchunk)
m = Maxwchunk;
(*flash.alg->write)(p, m, off);
off += m;
}
/* make sure write succeeded */
if(memcmp(buf, &flash.p[ooff>>2], n) != 0)
error("written bytes don't match");
wunlock(&flash);
free(buf);
poperror();
return on;
}
static long
flashwrite(Chan* c, void* a, long n, vlong off)
{
int t;
if(c->qid.type == QTDIR)
error(Eperm);
if(!iseve())
error(Eperm);
t = FTYPE(c->qid.path);
switch(t){
default:
panic("flashwrite");
case Qfctl:
n = flashctlwrite(FPART(c->qid.path), a, n);
break;
case Qfdata:
n = flashdatawrite(FPART(c->qid.path), a, n, off);
break;
}
return n;
}
Dev flashdevtab = {
'F',
"flash",
devreset,
flashinit,
devshutdown,
flashattach,
flashwalk,
flashstat,
flashopen,
devcreate,
flashclose,
flashread,
devbread,
flashwrite,
devbwrite,
devremove,
devwstat,
};
enum
{
/* status register */
ISEs_lockerr= 1<<1,
ISEs_powererr= 1<<3,
ISEs_progerr= 1<<4,
ISEs_eraseerr= 1<<5,
ISEs_ready= 1<<7,
ISEs_err= (ISEs_lockerr|ISEs_powererr|ISEs_progerr|ISEs_eraseerr),
/* extended status register */
ISExs_bufavail= 1<<7,
};
/* intel/sharp extended command set */
static void
ise_reset(void)
{
flash.p[0x55] = mirror(0xff); /* reset */
}
static void
ise_id(void)
{
ise_reset();
flash.p[0x555] = mirror(0x90); /* uncover vendor info */
flash.manid = flash.p[00];
flash.devid = flash.p[01];
ise_reset();
}
static void
ise_clearerror(void)
{
flash.p[0x100] = mirror(0x50);
}
static void
ise_error(int bank, ulong status)
{
char err[64];
if(status & (ISEs_lockerr)){
sprint(err, "flash%d: block locked %lux", bank, status);
error(err);
}
if(status & (ISEs_powererr)){
sprint(err, "flash%d: low prog voltage %lux", bank, status);
error(err);
}
if(status & (ISEs_progerr|ISEs_eraseerr)){
sprint(err, "flash%d: i/o error %lux", bank, status);
error(err);
}
}
static void
ise_erase(ulong addr)
{
ulong start;
ulong x;
addr >>= 2; /* convert to ulong offset */
flashprogpower(1);
flash.p[addr] = mirror(0x20);
flash.p[addr] = mirror(0xd0);
start = m->ticks;
do {
x = flash.p[addr];
if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))
break;
} while(TK2MS(m->ticks-start) < 1500);
flashprogpower(0);
ise_clearerror();
ise_error(0, x);
ise_error(1, x>>16);
ise_reset();
}
/*
* the flash spec claimes writing goes faster if we use
* the write buffer. We fill the write buffer and then
* issue the write request. After the write request,
* subsequent reads will yield the status register.
*
* returns the status, even on timeouts.
*
* NOTE: I tried starting back to back buffered writes
* without reading the status in between, as the
* flowchart in the intel data sheet suggests.
* However, it always responded with an illegal
* command sequence, so I must be missing something.
* If someone learns better, please email me, though
* I doubt it will be much faster. - presotto@bell-labs.com
*/
static int
ise_wbwrite(ulong *p, int n, ulong off, ulong baddr, ulong *status)
{
ulong x, start;
int i;
int s;
/* put flash into write buffer mode */
start = m->ticks;
for(;;) {
s = splhi();
/* request write buffer mode */
flash.p[baddr] = mirror(0xe8);
/* look at extended status reg for status */
if((flash.p[baddr] & mirror(1<<7)) == mirror(1<<7))
break;
splx(s);
/* didn't work, keep trying for 2 secs */
if(TK2MS(m->ticks-start) > 2000){
/* set up to read status */
flash.p[baddr] = mirror(0x70);
*status = flash.p[baddr];
pprint("write buffered cmd timed out\n");
return -1;
}
}
/* fill write buffer */
flash.p[baddr] = mirror(n-1);
for(i = 0; i < n; i++)
flash.p[off+i] = *p++;
/* program from buffer */
flash.p[baddr] = mirror(0xd0);
splx(s);
/* wait till the programming is done */
start = m->ticks;
for(;;) {
x = *status = flash.p[baddr]; /* read status register */
if((x & mirror(ISEs_ready)) == mirror(ISEs_ready))
break;
if(TK2MS(m->ticks-start) > 2000){
pprint("read status timed out\n");
return -1;
}
}
if(x & mirror(ISEs_err))
return -1;
return n;
}
static void
ise_write(void *a, long n, ulong off)
{
ulong *p, *end;
int i, wbsize;
ulong x, baddr;
/* everything in terms of ulongs */
wbsize = flash.wbsize>>2;
baddr = blockstart(off);
off >>= 2;
n >>= 2;
p = a;
baddr >>= 2;
/* first see if write will succeed */
for(i = 0; i < n; i++)
if((p[i] & flash.p[off+i]) != p[i])
error("flash needs erase");
if(waserror()){
ise_reset();
flashprogpower(0);
nexterror();
}
flashprogpower(1);
/*
* use the first write to reach
* a write buffer boundary. the intel maunal
* says writes startng at wb boundaries
* maximize speed.
*/
i = wbsize - (off & (wbsize-1));
for(end = p + n; p < end;){
if(i > end - p)
i = end - p;
if(ise_wbwrite(p, i, off, baddr, &x) < 0)
break;
off += i;
p += i;
i = wbsize;
}
ise_clearerror();
ise_error(0, x);
ise_error(1, x>>16);
ise_reset();
flashprogpower(0);
poperror();
}
/* amd/fujitsu standard command set
* I don't have an amd chipset to work with
* so I'm loathe to write this yet. If someone
* else does, please send it to me and I'll
* incorporate it -- presotto@bell-labs.com
*/
static void
afs_reset(void)
{
flash.p[0x55] = mirror(0xf0); /* reset */
}
static void
afs_id(void)
{
afs_reset();
flash.p[0x55] = mirror(0xf0); /* reset */
flash.p[0x555] = mirror(0xaa); /* query vendor block */
flash.p[0x2aa] = mirror(0x55);
flash.p[0x555] = mirror(0x90);
flash.manid = flash.p[00];
afs_reset();
flash.p[0x555] = mirror(0xaa); /* query vendor block */
flash.p[0x2aa] = mirror(0x55);
flash.p[0x555] = mirror(0x90);
flash.devid = flash.p[01];
afs_reset();
}
static void
afs_erase(ulong)
{
error("amd/fujistsu erase not implemented");
}
static void
afs_write(void*, long, ulong)
{
error("amd/fujistsu write not implemented");
}

View file

@ -1,713 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
/*
* BUG: insertion events are detected by polling.
* Should look into the compaq docs to see if
* there's an interrupt for card insertion
* there's probably one.
*/
static PCMslot slot[2];
int nslot = 2;
struct {
Ref;
Rendez event; // where to wait for card events
int evreader; // there's a reader for events
} pcmcia;
enum
{
Qdir,
Qmem,
Qattr,
Qctl,
Qevs,
Nents = 3,
};
enum
{
/*
* configuration registers - they start at an offset in attribute
* memory found in the CIS.
*/
Rconfig= 0,
Creset= (1<<7), /* reset device */
Clevel= (1<<6), /* level sensitive interrupt line */
};
static void increfp(PCMslot*);
static void decrefp(PCMslot*);
static void slotmap(int, ulong, ulong, ulong);
static void slottiming(int, int, int, int, int);
static void slotinfo(Ureg*, void*);
#define TYPE(c) (((ulong)c->qid.path)&0xff)
#define PATH(s,t) (((s)<<8)|(t))
static PCMslot*
slotof(Chan *c)
{
ulong x;
x = c->qid.path;
return slot + ((x>>8)&0xff);
}
static int
pcmgen(Chan *c, char *, Dirtab * , int, int i, Dir *dp)
{
int slotno;
Qid qid;
long len;
PCMslot *sp;
if(i == DEVDOTDOT){
mkqid(&qid, Qdir, 0, QTDIR);
devdir(c, qid, "#y", 0, eve, 0555, dp);
return 1;
}
if(i >= Nents*nslot + 1)
return -1;
if(i == Nents*nslot){
len = 0;
qid.path = PATH(0, Qevs);
snprint(up->genbuf, sizeof up->genbuf, "pcmevs");
goto found;
}
slotno = i/Nents;
sp = slot + slotno;
len = 0;
switch(i%Nents){
case 0:
qid.path = PATH(slotno, Qmem);
snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
len = sp->memlen;
break;
case 1:
qid.path = PATH(slotno, Qattr);
snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
len = sp->memlen;
break;
case 2:
qid.path = PATH(slotno, Qctl);
snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
break;
}
found:
qid.vers = 0;
qid.type = QTFILE;
devdir(c, qid, up->genbuf, len, eve, 0660, dp);
return 1;
}
static int
bitno(ulong x)
{
int i;
for(i = 0; i < 8*sizeof(x); i++)
if((1<<i) & x)
break;
return i;
}
/*
* set up the cards, default timing is 300 ns
*/
static void
pcmciareset(void)
{
/* staticly map the whole area */
slotmap(0, PHYSPCM0REGS, PYHSPCM0ATTR, PYHSPCM0MEM);
slotmap(1, PHYSPCM1REGS, PYHSPCM1ATTR, PYHSPCM1MEM);
/* set timing to the default, 300 */
slottiming(0, 300, 300, 300, 0);
slottiming(1, 300, 300, 300, 0);
/* if there's no pcmcia sleave, no interrupts */
if(gpioregs->level & GPIO_OPT_IND_i)
return;
/* sleave there, interrupt on card removal */
intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
}
static Chan*
pcmciaattach(char *spec)
{
return devattach('y', spec);
}
static Walkqid*
pcmciawalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name, nname, 0, 0, pcmgen);
}
static int
pcmciastat(Chan *c, uchar *db, int n)
{
return devstat(c, db, n, 0, 0, pcmgen);
}
static Chan*
pcmciaopen(Chan *c, int omode)
{
PCMslot *slotp;
if(c->qid.type & QTDIR){
if(omode != OREAD)
error(Eperm);
} else {
slotp = slotof(c);
increfp(slotp);
}
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
return c;
}
static void
pcmciaclose(Chan *c)
{
if(c->flag & COPEN)
if((c->qid.type & QTDIR) == 0)
decrefp(slotof(c));
}
/* a memmove using only bytes */
static void
memmoveb(uchar *to, uchar *from, int n)
{
while(n-- > 0)
*to++ = *from++;
}
/* a memmove using only shorts & bytes */
static void
memmoves(uchar *to, uchar *from, int n)
{
ushort *t, *f;
if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){
while(n-- > 0)
*to++ = *from++;
} else {
n = n/2;
t = (ushort*)to;
f = (ushort*)from;
while(n-- > 0)
*t++ = *f++;
}
}
static long
pcmread(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
{
rlock(sp);
if(waserror()){
runlock(sp);
nexterror();
}
if(off > len)
return 0;
if(off + n > len)
n = len - off;
memmoveb(a, start+off, n);
runlock(sp);
poperror();
return n;
}
static long
pcmctlread(void *a, long n, ulong off, PCMslot *sp)
{
char *p, *buf, *e;
buf = p = malloc(READSTR);
if(waserror()){
free(buf);
nexterror();
}
e = p + READSTR;
buf[0] = 0;
if(sp->occupied){
p = seprint(p, e, "occupied\n");
if(sp->verstr[0])
p = seprint(p, e, "version %s\n", sp->verstr);
}
USED(p);
n = readstr(off, a, n, buf);
free(buf);
poperror();
return n;
}
static int
inserted(void *)
{
if (slot[0].inserted)
return 1;
if (slot[1].inserted)
return 2;
return 0;
}
static long
pcmevsread(void *a, long n, ulong off)
{
int i;
char *buf = nil;
char *e;
if (pcmcia.evreader)
error("At most one reader");
off = 0;
pcmcia.evreader++;
if (waserror()){
free(buf);
pcmcia.evreader--;
nexterror();
}
while((i = inserted(nil)) == 0){
slotinfo(nil, nil);
tsleep(&pcmcia.event, inserted, nil, 500);
}
pcmcia.evreader--;
slot[i-1].inserted = 0;
buf = malloc(READSTR);
e = buf + READSTR;
buf[0] = 0;
seprint(buf, e, "#y/pcm%dctl\n", i-1);
n = readstr(off, a, n, buf);
free(buf);
poperror();
return n;
}
static long
pcmciaread(Chan *c, void *a, long n, vlong off)
{
PCMslot *sp;
ulong offset = off;
sp = slotof(c);
switch(TYPE(c)){
case Qdir:
return devdirread(c, a, n, 0, 0, pcmgen);
case Qmem:
if(!sp->occupied)
error(Eio);
return pcmread(a, n, offset, sp, sp->mem, 64*OneMeg);
case Qattr:
if(!sp->occupied)
error(Eio);
return pcmread(a, n, offset, sp, sp->attr, OneMeg);
case Qevs:
return pcmevsread(a, n, offset);
case Qctl:
return pcmctlread(a, n, offset, sp);
}
error(Ebadarg);
return -1; /* not reached */
}
static long
pcmwrite(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
{
rlock(sp);
if(waserror()){
runlock(sp);
nexterror();
}
if(off > len)
error(Eio);
if(off + n > len)
error(Eio);
memmoveb(start+off, a, n);
poperror();
runlock(sp);
return n;
}
static long
pcmctlwrite(char *p, long n, ulong, PCMslot *sp)
{
Cmdbuf *cmd;
uchar *cp;
int index, i, dtx;
Rune r;
DevConf cf;
Devport port;
cmd = parsecmd(p, n);
if(strcmp(cmd->f[0], "configure") == 0){
wlock(sp);
if(waserror()){
wunlock(sp);
nexterror();
}
/* see if driver exists and is configurable */
if(cmd->nf < 3)
error(Ebadarg);
p = cmd->f[1];
if(*p++ != '#')
error(Ebadarg);
p += chartorune(&r, p);
dtx = devno(r, 1);
if(dtx < 0)
error("no such device type");
if(devtab[dtx]->config == nil)
error("not a dynamicly configurable device");
/* set pcmcia card configuration */
index = 0;
if(sp->def != nil)
index = sp->def->index;
if(cmd->nf > 3){
i = atoi(cmd->f[3]);
if(i < 0 || i >= sp->nctab)
error("bad configuration index");
index = i;
}
if(sp->cfg[0].cpresent & (1<<Rconfig)){
cp = sp->attr;
cp += sp->cfg[0].caddr + Rconfig;
*cp = index;
}
/* configure device */
memset(&cf, 0, sizeof cf);
kstrdup(&cf.type, cmd->f[2]);
cf.mem = (ulong)sp->mem;
cf.ports = &port;
cf.ports[0].port = (ulong)sp->regs;
cf.ports[0].size = 0;
cf.nports = 1;
cf.itype = GPIOfalling;
cf.intnum = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
if(devtab[dtx]->config(1, p, &cf) < 0)
error("couldn't configure device");
sp->dev = devtab[dtx];
free(cf.type);
wunlock(sp);
poperror();
/* don't let the power turn off */
increfp(sp);
}else if(strcmp(cmd->f[0], "remove") == 0){
/* see if driver exists and is configurable */
if(cmd->nf != 2)
error(Ebadarg);
p = cmd->f[1];
if(*p++ != '#')
error(Ebadarg);
p += chartorune(&r, p);
dtx = devno(r, 1);
if(dtx < 0)
error("no such device type");
if(devtab[dtx]->config == nil)
error("not a dynamicly configurable device");
if(devtab[dtx]->config(0, p, nil) < 0)
error("couldn't unconfigure device");
/* let the power turn off */
decrefp(sp);
}
free(cmd);
return 0;
}
static long
pcmciawrite(Chan *c, void *a, long n, vlong off)
{
PCMslot *sp;
ulong offset = off;
sp = slotof(c);
switch(TYPE(c)){
case Qmem:
if(!sp->occupied)
error(Eio);
return pcmwrite(a, n, offset, sp, sp->mem, 64*OneMeg);
case Qattr:
if(!sp->occupied)
error(Eio);
return pcmwrite(a, n, offset, sp, sp->attr, OneMeg);
case Qevs:
break;
case Qctl:
if(!sp->occupied)
error(Eio);
return pcmctlwrite(a, n, offset, sp);
}
error(Ebadarg);
return -1; /* not reached */
}
/*
* power up/down pcmcia
*/
void
pcmciapower(int on)
{
PCMslot *sp;
/* if there's no pcmcia sleave, no interrupts */
iprint("pcmciapower %d\n", on);
if (on){
/* set timing to the default, 300 */
slottiming(0, 300, 300, 300, 0);
slottiming(1, 300, 300, 300, 0);
/* if there's no pcmcia sleave, no interrupts */
if(gpioregs->level & GPIO_OPT_IND_i){
iprint("pcmciapower: no sleeve\n");
return;
}
for (sp = slot; sp < slot + nslot; sp++){
if (sp->dev){
increfp(sp);
iprint("pcmciapower: %s\n", sp->verstr);
delay(10000);
if (sp->dev->power)
sp->dev->power(on);
}
}
}else{
if(gpioregs->level & GPIO_OPT_IND_i){
iprint("pcmciapower: no sleeve\n");
return;
}
for (sp = slot; sp < slot + nslot; sp++){
if (sp->dev){
if (sp->dev->power)
sp->dev->power(on);
decrefp(sp);
}
sp->occupied = 0;
sp->cisread = 0;
}
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
}
}
Dev pcmciadevtab = {
'y',
"pcmcia",
pcmciareset,
devinit,
devshutdown,
pcmciaattach,
pcmciawalk,
pcmciastat,
pcmciaopen,
devcreate,
pcmciaclose,
pcmciaread,
devbread,
pcmciawrite,
devbwrite,
devremove,
devwstat,
pcmciapower,
};
/* see what's there */
static void
slotinfo(Ureg*, void*)
{
ulong x = gpioregs->level;
if(x & GPIO_OPT_IND_i){
/* no expansion pack */
slot[0].occupied = slot[0].inserted = 0;
slot[1].occupied = slot[1].inserted = 0;
} else {
if(x & GPIO_CARD_IND0_i){
slot[0].occupied = slot[0].inserted = 0;
slot[0].cisread = 0;
} else {
if(slot[0].occupied == 0){
slot[0].inserted = 1;
slot[0].cisread = 0;
}
slot[0].occupied = 1;
}
if(x & GPIO_CARD_IND1_i){
slot[1].occupied = slot[1].inserted = 0;
slot[1].cisread = 0;
} else {
if(slot[1].occupied == 0){
slot[1].inserted = 1;
slot[1].cisread = 0;
}
slot[1].occupied = 1;
}
if (inserted(nil))
wakeup(&pcmcia.event);
}
}
/* use reference card to turn cards on and off */
static void
increfp(PCMslot *sp)
{
wlock(sp);
if(waserror()){
wunlock(sp);
nexterror();
}
iprint("increfp %ld\n", sp - slot);
if(incref(&pcmcia) == 1){
iprint("increfp full power\n");
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
delay(200);
egpiobits(EGPIO_pcmcia_reset, 1);
delay(100);
egpiobits(EGPIO_pcmcia_reset, 0);
delay(500);
}
incref(&sp->ref);
slotinfo(nil, nil);
if(sp->occupied && sp->cisread == 0) {
pcmcisread(sp);
}
wunlock(sp);
poperror();
}
static void
decrefp(PCMslot *sp)
{
iprint("decrefp %ld\n", sp - slot);
decref(&sp->ref);
if(decref(&pcmcia) == 0){
iprint("increfp power down\n");
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
}
}
/*
* the regions are staticly mapped
*/
static void
slotmap(int slotno, ulong regs, ulong attr, ulong mem)
{
PCMslot *sp;
sp = &slot[slotno];
sp->slotno = slotno;
sp->memlen = 64*OneMeg;
sp->verstr[0] = 0;
sp->mem = mapmem(mem, 64*OneMeg, 0);
sp->memmap.ca = 0;
sp->memmap.cea = 64*MB;
sp->memmap.isa = (ulong)mem;
sp->memmap.len = 64*OneMeg;
sp->memmap.attr = 0;
sp->attr = mapmem(attr, OneMeg, 0);
sp->attrmap.ca = 0;
sp->attrmap.cea = MB;
sp->attrmap.isa = (ulong)attr;
sp->attrmap.len = OneMeg;
sp->attrmap.attr = 1;
sp->regs = mapspecial(regs, 32*1024);
}
PCMmap*
pcmmap(int slotno, ulong, int, int attr)
{
if(slotno > nslot)
panic("pcmmap");
if(attr)
return &slot[slotno].attrmap;
else
return &slot[slotno].memmap;
}
void
pcmunmap(int, PCMmap*)
{
}
/*
* setup card timings
* times are in ns
* count = ceiling[access-time/(2*3*T)] - 1, where T is a processor cycle
*
*/
static int
ns2count(int ns)
{
ulong y;
/* get 100 times cycle time */
y = 100000000/(conf.hz/1000);
/* get 10 times ns/(cycle*6) */
y = (1000*ns)/(6*y);
/* round up */
y += 9;
y /= 10;
/* subtract 1 */
return y-1;
}
static void
slottiming(int slotno, int tio, int tattr, int tmem, int fast)
{
ulong x;
x = 0;
if(fast)
x |= 1<<MECR_fast0;
x |= ns2count(tio) << MECR_io0;
x |= ns2count(tattr) << MECR_attr0;
x |= ns2count(tmem) << MECR_mem0;
if(slotno == 0){
x |= memconfregs->mecr & 0xffff0000;
} else {
x <<= 16;
x |= memconfregs->mecr & 0xffff;
}
memconfregs->mecr = x;
}
/* For compat with ../pc devices. Don't use it for the bitsy
*/
int
pcmspecial(char*, ISAConf*)
{
return -1;
}

View file

@ -1,510 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#define Image IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
#include <ctype.h>
typedef struct Mouseinfo Mouseinfo;
typedef struct Mousestate Mousestate;
typedef struct Calibration Calibration;
struct Calibration
{
long scalex;
long scaley;
long transx;
long transy;
} calibration = {
-16435,
23275,
253,
-23
};
/* The pen goes down, tracks some and goes up again. The pen alone can
* only simulate a one-button mouse.
* To simulate a more-button (five, in this case) mouse, we use the four
* keys along the the bottom of the iPaq as modifiers.
* When one (or more) of the modifier keys is (are) down, a pen-down event
* causes the corresponding bottons to go down. If no modifier key is
* depressed, a pen-down event is translated into a button-one down event.
* Releasing the modifier keys has no direct effect. The pen-up event is
* the one that triggers mouse-up events.
*/
struct Mousestate
{
Point xy; /* mouse.xy */
int buttons; /* mouse.buttons */
int modifiers; /* state of physical buttons 2, 3, 4, 5 */
ulong counter; /* increments every update */
ulong msec; /* time of last event */
};
struct Mouseinfo
{
Lock;
Mousestate;
ulong lastcounter; /* value when /dev/mouse read */
ulong resize;
ulong lastresize;
Rendez r;
Ref;
QLock;
int open;
int inopen;
Mousestate queue[16]; /* circular buffer of click events */
int ri; /* read index into queue */
int wi; /* write index into queue */
uchar qfull; /* queue is full */
};
Mouseinfo mouse;
int mouseshifted;
int penmousechanged(void*);
static void penmousetrack(int b, int x, int y);
enum{
Qdir,
Qmouse,
Qmousein,
Qmousectl,
};
static Dirtab mousedir[]={
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
"mouse", {Qmouse}, 0, 0666,
"mousein", {Qmousein}, 0, 0220,
"mousectl", {Qmousectl}, 0, 0660,
};
enum
{
CMcalibrate,
CMswap,
};
static Cmdtab penmousecmd[] =
{
CMcalibrate, "calibrate", 0,
CMswap, "swap", 1,
};
static uchar buttonmap[8] = {
0, 1, 2, 3, 4, 5, 6, 7,
};
static int mouseswap;
extern Memimage* gscreen;
void
penbutton(int up, int b) {
// button 5 (side button) immediately causes an event
// when the pen is down (button 1), other buttons also
// cause events, allowing chording with button 1
if ((b & 0x20) || (mouse.buttons & 0x1)) {
if (up)
mouse.buttons &= ~b;
else
mouse.buttons |= b;
penmousetrack(mouse.buttons, -1, -1);
} else {
if (up)
mouse.modifiers &= ~b;
else
mouse.modifiers |= b;
}
}
void
pentrackxy(int x, int y) {
if (x == -1) {
/* pen up. associate with button 1 through 5 up */
mouse.buttons &= ~0x1f;
} else {
x = ((x*calibration.scalex)>>16) + calibration.transx;
y = ((y*calibration.scaley)>>16) + calibration.transy;
if ((mouse.buttons & 0x1f) == 0) {
if (mouse.modifiers)
mouse.buttons |= mouse.modifiers;
else
mouse.buttons |= 0x1;
}
}
penmousetrack(mouse.buttons, x, y);
}
static void
penmousereset(void)
{
if(!conf.monitor)
return;
}
static void
penmouseinit(void)
{
if(!conf.monitor)
return;
}
static Chan*
penmouseattach(char *spec)
{
if(!conf.monitor)
error(Egreg);
return devattach('m', spec);
}
static Walkqid*
penmousewalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
}
static int
penmousestat(Chan *c, uchar *db, int n)
{
return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
}
static Chan*
penmouseopen(Chan *c, int omode)
{
switch((ulong)c->qid.path){
case Qdir:
if(omode != OREAD)
error(Eperm);
break;
case Qmouse:
lock(&mouse);
if(mouse.open){
unlock(&mouse);
error(Einuse);
}
mouse.open = 1;
mouse.ref++;
unlock(&mouse);
break;
case Qmousein:
/* error("disabled"); */
lock(&mouse);
if(mouse.inopen){
unlock(&mouse);
error(Einuse);
}
mouse.inopen = 1;
unlock(&mouse);
break;
default:
incref(&mouse);
}
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
return c;
}
static Chan*
penmousecreate(Chan*, char*, int, ulong)
{
if(!conf.monitor)
error(Egreg);
error(Eperm);
return 0;
}
static void
penmouseclose(Chan *c)
{
if(c->qid.path != Qdir && (c->flag&COPEN)){
lock(&mouse);
if(c->qid.path == Qmouse)
mouse.open = 0;
else if(c->qid.path == Qmousein){
mouse.inopen = 0;
unlock(&mouse);
return;
}
--mouse.ref;
unlock(&mouse);
}
}
static long
penmouseread(Chan *c, void *va, long n, vlong)
{
char buf[4*12+1];
static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
Mousestate m;
switch((ulong)c->qid.path){
case Qdir:
return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
case Qmousectl:
sprint(buf, "c%11ld %11ld %11ld %11ld",
calibration.scalex, calibration.scaley,
calibration.transx, calibration.transy);
if(n > 1+4*12)
n = 1+4*12;
memmove(va, buf, n);
return n;
case Qmouse:
while(penmousechanged(0) == 0)
sleep(&mouse.r, penmousechanged, 0);
mouse.qfull = 0;
/*
* No lock of the indices is necessary here, because ri is only
* updated by us, and there is only one mouse reader
* at a time. I suppose that more than one process
* could try to read the fd at one time, but such behavior
* is degenerate and already violates the calling
* conventions for sleep above.
*/
if(mouse.ri != mouse.wi) {
m = mouse.queue[mouse.ri];
if(++mouse.ri == nelem(mouse.queue))
mouse.ri = 0;
} else {
m = mouse.Mousestate;
}
sprint(buf, "m%11d %11d %11d %11lud",
m.xy.x, m.xy.y,
m.buttons,
m.msec);
mouse.lastcounter = m.counter;
if(n > 1+4*12)
n = 1+4*12;
if(mouse.lastresize != mouse.resize){
mouse.lastresize = mouse.resize;
buf[0] = 'r';
}
memmove(va, buf, n);
return n;
}
return 0;
}
static void
setbuttonmap(char* map)
{
int i, x, one, two, three;
one = two = three = 0;
for(i = 0; i < 3; i++){
if(map[i] == 0)
error(Ebadarg);
if(map[i] == '1'){
if(one)
error(Ebadarg);
one = 1<<i;
}
else if(map[i] == '2'){
if(two)
error(Ebadarg);
two = 1<<i;
}
else if(map[i] == '3'){
if(three)
error(Ebadarg);
three = 1<<i;
}
else
error(Ebadarg);
}
if(map[i])
error(Ebadarg);
memset(buttonmap, 0, 8);
for(i = 0; i < 8; i++){
x = 0;
if(i & 1)
x |= one;
if(i & 2)
x |= two;
if(i & 4)
x |= three;
buttonmap[x] = i;
}
}
static long
penmousewrite(Chan *c, void *va, long n, vlong)
{
char *p;
Point pt;
Cmdbuf *cb;
Cmdtab *ct;
char buf[64];
int b;
p = va;
switch((ulong)c->qid.path){
case Qdir:
error(Eisdir);
case Qmousectl:
cb = parsecmd(va, n);
if(waserror()){
free(cb);
nexterror();
}
ct = lookupcmd(cb, penmousecmd, nelem(penmousecmd));
switch(ct->index){
case CMswap:
if(mouseswap)
setbuttonmap("123");
else
setbuttonmap("321");
mouseswap ^= 1;
break;
case CMcalibrate:
if (cb->nf == 1) {
calibration.scalex = 1<<16;
calibration.scaley = 1<<16;
calibration.transx = 0;
calibration.transy = 0;
} else if (cb->nf == 5) {
if ((!isdigit(*cb->f[1]) && *cb->f[1] != '-')
|| (!isdigit(*cb->f[2]) && *cb->f[2] != '-')
|| (!isdigit(*cb->f[3]) && *cb->f[3] != '-')
|| (!isdigit(*cb->f[4]) && *cb->f[4] != '-'))
error("bad syntax in control file message");
calibration.scalex = strtol(cb->f[1], nil, 0);
calibration.scaley = strtol(cb->f[2], nil, 0);
calibration.transx = strtol(cb->f[3], nil, 0);
calibration.transy = strtol(cb->f[4], nil, 0);
} else
cmderror(cb, Ecmdargs);
break;
}
free(cb);
poperror();
return n;
case Qmousein:
if(n > sizeof buf-1)
n = sizeof buf -1;
memmove(buf, va, n);
buf[n] = 0;
p = 0;
pt.x = strtol(buf+1, &p, 0);
if(p == 0)
error(Eshort);
pt.y = strtol(p, &p, 0);
if(p == 0)
error(Eshort);
b = strtol(p, &p, 0);
penmousetrack(b, pt.x, pt.y);
return n;
case Qmouse:
if(n > sizeof buf-1)
n = sizeof buf -1;
memmove(buf, va, n);
buf[n] = 0;
p = 0;
pt.x = strtoul(buf+1, &p, 0);
if(p == 0)
error(Eshort);
pt.y = strtoul(p, 0, 0);
qlock(&mouse);
if(ptinrect(pt, gscreen->r))
penmousetrack(mouse.buttons, pt.x, pt.y);
qunlock(&mouse);
return n;
}
error(Egreg);
return -1;
}
Dev penmousedevtab = {
'm',
"penmouse",
penmousereset,
penmouseinit,
devshutdown,
penmouseattach,
penmousewalk,
penmousestat,
penmouseopen,
penmousecreate,
penmouseclose,
penmouseread,
devbread,
penmousewrite,
devbwrite,
devremove,
devwstat,
};
/*
* called at interrupt level to update the structure and
* awaken any waiting procs.
*/
static void
penmousetrack(int b, int x, int y)
{
int lastb;
if (x >= 0)
mouse.xy = Pt(x, y);
lastb = mouse.buttons;
mouse.buttons = b;
mouse.counter++;
mouse.msec = TK2MS(MACHP(0)->ticks);
/*
* if the queue fills, we discard the entire queue and don't
* queue any more events until a reader polls the mouse.
*/
if(!mouse.qfull && lastb != b) { /* add to ring */
mouse.queue[mouse.wi] = mouse.Mousestate;
if(++mouse.wi == nelem(mouse.queue))
mouse.wi = 0;
if(mouse.wi == mouse.ri)
mouse.qfull = 1;
}
wakeup(&mouse.r);
drawactive(1);
resetsuspendtimer();
}
int
penmousechanged(void*)
{
return mouse.lastcounter != mouse.counter ||
mouse.lastresize != mouse.resize;
}
Point
penmousexy(void)
{
return mouse.xy;
}
/*
* notify reader that screen has been resized (ha!)
*/
void
mouseresize(void)
{
mouse.resize++;
wakeup(&mouse.r);
}

File diff suppressed because it is too large Load diff

View file

@ -1,407 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
enum{
Qdir,
Qbacklight,
Qbattery,
Qbuttons,
Qcruft,
Qled,
Qversion,
Qpower,
/* command types */
BLversion= 0,
BLbuttons= 2, /* button events */
BLtouch= 3, /* read touch screen events */
BLled= 8, /* turn LED on/off */
BLbattery= 9, /* read battery status */
BLbacklight= 0xd, /* backlight control */
SOF= 0x2, /* start of frame */
};
Dirtab µcdir[]={
".", { Qdir, 0, QTDIR }, 0, DMDIR|0755,
"backlight", { Qbacklight, 0 }, 0, 0664,
"battery", { Qbattery, 0 }, 0, 0664,
"buttons", { Qbuttons, 0 }, 0, 0664,
"cruft", { Qcruft, 0 }, 0, 0664,
"led", { Qled, 0 }, 0, 0664,
"version", { Qversion, 0 }, 0, 0664,
"power", { Qpower, 0 }, 0, 0600,
};
static struct µcontroller
{
/* message being rcvd */
int state;
uchar buf[16+4];
uchar n;
/* for messages that require acks */
QLock;
Rendez r;
/* battery */
uchar acstatus;
uchar voltage;
ushort batstatus;
uchar batchem;
/* version string */
char version[16+2];
} ctlr;
extern int landscape;
int
µcputc(Queue*, int ch)
{
int i, len, b, up;
uchar cksum;
uchar *p;
static int samseq;
static int touching; /* guard against something we call going spllo() */
static int buttoning; /* guard against something we call going spllo() */
if(ctlr.n > sizeof(ctlr.buf))
panic("µcputc");
ctlr.buf[ctlr.n++] = (uchar)ch;
for(;;){
/* message hasn't started yet? */
if(ctlr.buf[0] != SOF){
p = memchr(ctlr.buf, SOF, ctlr.n);
if(p == nil){
ctlr.n = 0;
break;
} else {
ctlr.n -= p-ctlr.buf;
memmove(ctlr.buf, p, ctlr.n);
}
}
/* whole msg? */
len = ctlr.buf[1] & 0xf;
if(ctlr.n < 3 || ctlr.n < len+3)
break;
/* check the sum */
ctlr.buf[0] = ~SOF; /* make sure we process this msg exactly once */
cksum = 0;
for(i = 1; i < len+2; i++)
cksum += ctlr.buf[i];
if(ctlr.buf[len+2] != cksum)
continue;
/* parse resulting message */
p = ctlr.buf+2;
switch(ctlr.buf[1] >> 4){
case BLversion:
strncpy(ctlr.version, (char*)p, len);
ctlr.version[len] = '0';
strcat(ctlr.version, "\n");
wakeup(&ctlr.r);
break;
case BLbuttons:
if(len < 1 || buttoning)
break;
buttoning = 1;
b = p[0] & 0x7f;
up = p[0] & 0x80;
if(b <= 5){
/* like mouse buttons */
if(--b == 0)
b = 5;
penbutton(up, 1<<b);
}
buttoning = 0;
break;
case BLtouch:
if(touching)
break;
touching = 1;
if(len == 4) {
if (samseq++ > 10){
if (landscape)
pentrackxy((p[0]<<8)|p[1], (p[2]<<8)|p[3]);
else
pentrackxy((p[2]<<8)|p[3], (p[0]<<8)|p[1]);
}
} else {
samseq = 0;
pentrackxy(-1, -1);
}
touching = 0;
break;
case BLled:
wakeup(&ctlr.r);
break;
case BLbattery:
if(len >= 5){
ctlr.acstatus = p[0];
ctlr.voltage = (p[3]<<8)|p[2];
ctlr.batstatus = p[4];
ctlr.batchem = p[1];
}
wakeup(&ctlr.r);
break;
case BLbacklight:
wakeup(&ctlr.r);
break;
default:
print("unknown µc message: %ux", ctlr.buf[1] >> 4);
for(i = 0; i < len; i++)
print(" %ux", p[i]);
print("\n");
break;
}
/* remove the message */
ctlr.n -= len+3;
memmove(ctlr.buf, &ctlr.buf[len+3], ctlr.n);
}
return 0;
}
static void
_sendmsg(uchar id, uchar *data, int len)
{
uchar buf[20];
uchar cksum;
uchar c;
uchar *p = buf;
int i;
/* create the message */
if(sizeof(buf) < len+4)
return;
cksum = (id<<4) | len;
*p++ = SOF;
*p++ = cksum;
for(i = 0; i < len; i++){
c = data[i];
cksum += c;
*p++ = c;
}
*p++ = cksum;
/* send the message - there should be a more generic way to do this */
serialµcputs(buf, p-buf);
}
/* the tsleep takes care of lost acks */
static void
sendmsgwithack(uchar id, uchar *data, int len)
{
if(waserror()){
qunlock(&ctlr);
nexterror();
}
qlock(&ctlr);
_sendmsg(id, data, len);
tsleep(&ctlr.r, return0, 0, 100);
qunlock(&ctlr);
poperror();
}
static void
sendmsg(uchar id, uchar *data, int len)
{
if(waserror()){
qunlock(&ctlr);
nexterror();
}
qlock(&ctlr);
_sendmsg(id, data, len);
qunlock(&ctlr);
poperror();
}
void
µcinit(void)
{
}
static Chan*
µcattach(char* spec)
{
return devattach('r', spec);
}
static Walkqid*
µcwalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name, nname, µcdir, nelem(µcdir), devgen);
}
static int
µcstat(Chan *c, uchar *dp, int n)
{
return devstat(c, dp, n, µcdir, nelem(µcdir), devgen);
}
static Chan*
µcopen(Chan* c, int omode)
{
omode = openmode(omode);
if(!iseve())
error(Eperm);
return devopen(c, omode, µcdir, nelem(µcdir), devgen);
}
static void
µcclose(Chan*)
{
}
char*
acstatus(int x)
{
if(x)
return "attached";
else
return "detached";
}
char*
batstatus(int x)
{
switch(x){
case 1: return "high";
case 2: return "low";
case 4: return "critical";
case 8: return "charging";
case 0x80: return "none";
}
return "ok";
}
static long
µcread(Chan* c, void* a, long n, vlong off)
{
char buf[64];
if(c->qid.path == Qdir)
return devdirread(c, a, n, µcdir, nelem(µcdir), devgen);
switch((ulong)c->qid.path){
case Qbattery:
sendmsgwithack(BLbattery, nil, 0); /* send a battery request */
sprint(buf, "voltage: %d\nac: %s\nstatus: %s\n", ctlr.voltage,
acstatus(ctlr.acstatus),
batstatus(ctlr.batstatus));
return readstr(off, a, n, buf);
case Qversion:
sendmsgwithack(BLversion, nil, 0); /* send a battery request */
return readstr(off, a, n, ctlr.version);
}
error(Ebadarg);
return 0;
}
#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)
static uchar lightdata[16];
static long
µcwrite(Chan* c, void* a, long n, vlong)
{
Cmdbuf *cmd;
uchar data[16];
char str[64];
int i, j;
ulong l;
Rune r;
extern ulong resumeaddr[];
extern void power_resume(void);
if(c->qid.path == Qpower){
if(!iseve())
error(Eperm);
if(strncmp(a, "suspend", 7) == 0)
*resumeaddr = (ulong)power_resume;
else if(strncmp(a, "halt", 4) == 0)
*resumeaddr = 0;
else if(strncmp(a, "wakeup", 6) == 0){
cmd = parsecmd(a, n);
if (cmd->nf != 2)
error(Ebadarg);
l = strtoul(cmd->f[1], 0, 0);
rtcalarm(l);
return n;
} else
error(Ebadarg);
deepsleep();
return n;
}
cmd = parsecmd(a, n);
if(cmd->nf > 15)
error(Ebadarg);
for(i = 0; i < cmd->nf; i++)
data[i] = strtol(cmd->f[i], 0, 0);
switch((ulong)c->qid.path){
case Qled:
sendmsgwithack(BLled, data, cmd->nf);
break;
case Qbacklight:
memmove(lightdata, data, 16);
sendmsgwithack(BLbacklight, data, cmd->nf);
break;
case Qcruft:
// lcdtweak(cmd);
break;
default:
error(Ebadarg);
}
return n;
}
void
µcpower(int on)
{
uchar data[16];
if (on == 0)
return;
/* maybe dangerous, not holding the lock */
if (lightdata[0] == 0){
data[0]= 2;
data[1]= 1;
data[2]= 0;
} else
memmove(data, lightdata, 16);
_sendmsg(0xd, data, 3);
wakeup(&ctlr.r);
}
Dev µcdevtab = {
'r',
"µc",
devreset,
µcinit,
devshutdown,
µcattach,
µcwalk,
µcstat,
µcopen,
devcreate,
µcclose,
µcread,
devbread,
µcwrite,
devbwrite,
devremove,
devwstat,
};

View file

@ -1,39 +0,0 @@
enum {
MaxEther = 24,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
DevConf;
int ctlrno;
int tbdf; /* type+busno+devno+funcno */
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
int encry;
void (*attach)(Ether*); /* filled in by reset routine */
void (*detach)(Ether*);
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void (*power)(Ether*, int); /* power on/off */
void (*shutdown)(Ether*); /* shutdown hardware before reboot */
void *ctlr;
Queue* oq;
Netif;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))

View file

@ -1,49 +0,0 @@
/* Bitsy pcmcia code for wavelan.c */
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
#include "../pc/wavelan.h"
static int
wavelanpcmciareset(Ether *ether)
{
Ctlr *ctlr;
if((ctlr = malloc(sizeof(Ctlr))) == nil)
return -1;
ilock(ctlr);
ctlr->ctlrno = ether->ctlrno;
if (ether->ports == nil){
ether->ports = malloc(sizeof(Devport));
ether->ports[0].port = 0;
ether->ports[0].size = 0;
ether->nports= 1;
}
if (ether->ports[0].port==0)
ether->ports[0].port=WDfltIOB;
ctlr->iob = ether->ports[0].port;
if(wavelanreset(ether, ctlr) < 0){
iunlock(ctlr);
free(ctlr);
ether->ctlr = nil;
return -1;
}
iunlock(ctlr);
return 0;
}
void
etherwavelanlink(void)
{
addethercard("wavelan", wavelanpcmciareset);
}

View file

@ -1,121 +0,0 @@
#include "../port/portfns.h"
void audiopower(int);
void audioamppower(int);
void audioicpower(int);
void cacheflush(void);
void cachewb(void);
void cachewbaddr(void*);
void cachewbregion(ulong, int);
ulong cankaddr(ulong);
void dcacheinvalidate(void);
int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
void clockinit(void);
ulong clockpower(int);
int cmpswap(long*, long, long);
#define coherence()
#define cycles(x) do{}while(0)
#define dcflush(a, b)
void delay(int);
void µcpower(int);
void deepsleep(void);
void dmainit(void);
void doze(void);
void egpiobits(ulong, int);
void evenaddr(ulong);
ulong findva(ulong, ulong, ulong);
void flashprogpower(int);
void flushmmu(void);
int fpiarm(Ureg *ur);
char* getconf(char*);
ulong getcpuid(void);
ulong getfar(void);
ulong getfsr(void);
ulong getcontrol(void);
ulong getdac(void);
ulong getttb(void);
void* getlink(void);
#define getpgcolor(a) 0
ulong getsp(void);
void icacheinvalidate(void);
void idle(void);
void idlehands(void);
uchar inb(ulong);
ushort ins(ulong);
void inss(ulong, void*, int);
ulong inl(ulong);
void intrdisable(int, int, void (*)(Ureg*, void*), void*, char*);
void intrenable(int, int, void (*)(Ureg*, void*), void*, char*);
void irpower(int);
#define kexit(a)
#define kmapinval()
void lcdpower(int);
void links(void);
void* mapmem(ulong, int, int);
void mappedIvecEnable(void);
void mappedIvecDisable(void);
void* mapspecial(ulong, int);
void meminit(void);
void mmuinit(void);
void mmuenable(void);
void mmudisable(void);
void mmuinvalidate(void);
void mmuinvalidateaddr(ulong);
void mmurestart(void);
ulong mmu_kaddr(ulong);
ulong mmu_paddr(ulong);
int µcputc(Queue*, int);
void noted(Ureg*, ulong);
int notify(Ureg*);
void outb(ulong, uchar);
void outs(ulong, ushort);
void outss(ulong, void*, int);
void outl(ulong, ulong);
void pcmciapower(int);
void pcmcisread(PCMslot*);
int pcmcistuple(int, int, int, void*, int);
PCMmap* pcmmap(int, ulong, int, int);
void pcmunmap(int, PCMmap*);
void penbutton(int, int);
void pentrackxy(int x, int y);
void power_down(void);
void powerinit(void);
void powerkproc(void*);
#define procrestore(p)
void procsave(Proc*);
void procsetup(Proc*);
void procfork(Proc*);
void putdac(ulong);
void putttb(ulong);
void putpid(ulong);
void resetsuspendtimer(void);
void rs232power(int);
void rtcalarm(ulong);
void sa1110_uartsetup(int);
void screeninit(void);
void screenpower(int);
void serialµcputs(uchar *str, int n);
void setr13(int, ulong*);
uchar* tarlookup(uchar*, char*, int*);
void timersinit(void);
void timeradd(Timer*);
void timerdel(Timer*);
void timerset(Tval);
void touser(void*);
void trapdump(char *tag);
void trapinit(void);
void trapresume(void);
int tas(void*);
void uartpower(int);
int uartstageoutput(Uart*);
void uartkick(void*);
void uartrecv(Uart*, char);
#define userureg(ur) (((ur)->psr & PsrMask) == PsrMusr)
void vectors(void);
void vtable(void);
void wbflush(void);
#define KADDR(a) (void*)mmu_kaddr((ulong)(a))
#define PADDR(a) mmu_paddr((ulong)(a))
#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))

View file

@ -1,300 +0,0 @@
/*
* Floating Point Interpreter.
* shamelessly stolen from an original by ark.
*/
#include "fpi.h"
void
fpiround(Internal *i)
{
unsigned long guard;
guard = i->l & GuardMask;
i->l &= ~GuardMask;
if(guard > (LsBit>>1) || (guard == (LsBit>>1) && (i->l & LsBit))){
i->l += LsBit;
if(i->l & CarryBit){
i->l &= ~CarryBit;
i->h++;
if(i->h & CarryBit){
if (i->h & 0x01)
i->l |= CarryBit;
i->l >>= 1;
i->h >>= 1;
i->e++;
}
}
}
}
static void
matchexponents(Internal *x, Internal *y)
{
int count;
count = y->e - x->e;
x->e = y->e;
if(count >= 2*FractBits){
x->l = x->l || x->h;
x->h = 0;
return;
}
if(count >= FractBits){
count -= FractBits;
x->l = x->h|(x->l != 0);
x->h = 0;
}
while(count > 0){
count--;
if(x->h & 0x01)
x->l |= CarryBit;
if(x->l & 0x01)
x->l |= 2;
x->l >>= 1;
x->h >>= 1;
}
}
static void
shift(Internal *i)
{
i->e--;
i->h <<= 1;
i->l <<= 1;
if(i->l & CarryBit){
i->l &= ~CarryBit;
i->h |= 0x01;
}
}
static void
normalise(Internal *i)
{
while((i->h & HiddenBit) == 0)
shift(i);
}
static void
renormalise(Internal *i)
{
if(i->e < -2 * FractBits)
i->e = -2 * FractBits;
while(i->e < 1){
i->e++;
if(i->h & 0x01)
i->l |= CarryBit;
i->h >>= 1;
i->l = (i->l>>1)|(i->l & 0x01);
}
if(i->e >= ExpInfinity)
SetInfinity(i);
}
void
fpinormalise(Internal *x)
{
if(!IsWeird(x) && !IsZero(x))
normalise(x);
}
void
fpiadd(Internal *x, Internal *y, Internal *i)
{
Internal *t;
i->s = x->s;
if(IsWeird(x) || IsWeird(y)){
if(IsNaN(x) || IsNaN(y))
SetQNaN(i);
else
SetInfinity(i);
return;
}
if(x->e > y->e){
t = x;
x = y;
y = t;
}
matchexponents(x, y);
i->e = x->e;
i->h = x->h + y->h;
i->l = x->l + y->l;
if(i->l & CarryBit){
i->h++;
i->l &= ~CarryBit;
}
if(i->h & (HiddenBit<<1)){
if(i->h & 0x01)
i->l |= CarryBit;
i->l = (i->l>>1)|(i->l & 0x01);
i->h >>= 1;
i->e++;
}
if(IsWeird(i))
SetInfinity(i);
}
void
fpisub(Internal *x, Internal *y, Internal *i)
{
Internal *t;
if(y->e < x->e
|| (y->e == x->e && (y->h < x->h || (y->h == x->h && y->l < x->l)))){
t = x;
x = y;
y = t;
}
i->s = y->s;
if(IsNaN(y)){
SetQNaN(i);
return;
}
if(IsInfinity(y)){
if(IsInfinity(x))
SetQNaN(i);
else
SetInfinity(i);
return;
}
matchexponents(x, y);
i->e = y->e;
i->h = y->h - x->h;
i->l = y->l - x->l;
if(i->l < 0){
i->l += CarryBit;
i->h--;
}
if(i->h == 0 && i->l == 0)
SetZero(i);
else while(i->e > 1 && (i->h & HiddenBit) == 0)
shift(i);
}
#define CHUNK (FractBits/2)
#define CMASK ((1<<CHUNK)-1)
#define HI(x) ((short)((x)>>CHUNK) & CMASK)
#define LO(x) ((short)(x) & CMASK)
#define SPILL(x) ((x)>>CHUNK)
#define M(x, y) ((long)a[x]*(long)b[y])
#define C(h, l) (((long)((h) & CMASK)<<CHUNK)|((l) & CMASK))
void
fpimul(Internal *x, Internal *y, Internal *i)
{
long a[4], b[4], c[7], f[4];
i->s = x->s^y->s;
if(IsWeird(x) || IsWeird(y)){
if(IsNaN(x) || IsNaN(y) || IsZero(x) || IsZero(y))
SetQNaN(i);
else
SetInfinity(i);
return;
}
else if(IsZero(x) || IsZero(y)){
SetZero(i);
return;
}
normalise(x);
normalise(y);
i->e = x->e + y->e - (ExpBias - 1);
a[0] = HI(x->h); b[0] = HI(y->h);
a[1] = LO(x->h); b[1] = LO(y->h);
a[2] = HI(x->l); b[2] = HI(y->l);
a[3] = LO(x->l); b[3] = LO(y->l);
c[6] = M(3, 3);
c[5] = M(2, 3) + M(3, 2) + SPILL(c[6]);
c[4] = M(1, 3) + M(2, 2) + M(3, 1) + SPILL(c[5]);
c[3] = M(0, 3) + M(1, 2) + M(2, 1) + M(3, 0) + SPILL(c[4]);
c[2] = M(0, 2) + M(1, 1) + M(2, 0) + SPILL(c[3]);
c[1] = M(0, 1) + M(1, 0) + SPILL(c[2]);
c[0] = M(0, 0) + SPILL(c[1]);
f[0] = c[0];
f[1] = C(c[1], c[2]);
f[2] = C(c[3], c[4]);
f[3] = C(c[5], c[6]);
if((f[0] & HiddenBit) == 0){
f[0] <<= 1;
f[1] <<= 1;
f[2] <<= 1;
f[3] <<= 1;
if(f[1] & CarryBit){
f[0] |= 1;
f[1] &= ~CarryBit;
}
if(f[2] & CarryBit){
f[1] |= 1;
f[2] &= ~CarryBit;
}
if(f[3] & CarryBit){
f[2] |= 1;
f[3] &= ~CarryBit;
}
i->e--;
}
i->h = f[0];
i->l = f[1];
if(f[2] || f[3])
i->l |= 1;
renormalise(i);
}
void
fpidiv(Internal *x, Internal *y, Internal *i)
{
i->s = x->s^y->s;
if(IsNaN(x) || IsNaN(y)
|| (IsInfinity(x) && IsInfinity(y)) || (IsZero(x) && IsZero(y))){
SetQNaN(i);
return;
}
else if(IsZero(x) || IsInfinity(y)){
SetInfinity(i);
return;
}
else if(IsInfinity(x) || IsZero(y)){
SetZero(i);
return;
}
normalise(x);
normalise(y);
i->h = 0;
i->l = 0;
i->e = y->e - x->e + (ExpBias + 2*FractBits - 1);
do{
if(y->h > x->h || (y->h == x->h && y->l >= x->l)){
i->l |= 0x01;
y->h -= x->h;
y->l -= x->l;
if(y->l < 0){
y->l += CarryBit;
y->h--;
}
}
shift(y);
shift(i);
}while ((i->h & HiddenBit) == 0);
if(y->h || y->l)
i->l |= 0x01;
renormalise(i);
}
int
fpicmp(Internal *x, Internal *y)
{
if(IsNaN(x) && IsNaN(y))
return 0;
if(IsInfinity(x) && IsInfinity(y))
return y->s - x->s;
if(x->e == y->e && x->h == y->h && x->l == y->l)
return y->s - x->s;
if(x->e < y->e
|| (x->e == y->e && (x->h < y->h || (x->h == y->h && x->l < y->l))))
return y->s ? 1: -1;
return x->s ? -1: 1;
}

View file

@ -1,61 +0,0 @@
typedef long Word;
typedef unsigned long Single;
typedef struct {
unsigned long l;
unsigned long h;
} Double;
enum {
FractBits = 28,
CarryBit = 0x10000000,
HiddenBit = 0x08000000,
MsBit = HiddenBit,
NGuardBits = 3,
GuardMask = 0x07,
LsBit = (1<<NGuardBits),
SingleExpBias = 127,
SingleExpMax = 255,
DoubleExpBias = 1023,
DoubleExpMax = 2047,
ExpBias = DoubleExpBias,
ExpInfinity = DoubleExpMax,
};
typedef struct {
unsigned char s;
short e;
long l; /* 0000FFFFFFFFFFFFFFFFFFFFFFFFFGGG */
long h; /* 0000HFFFFFFFFFFFFFFFFFFFFFFFFFFF */
} Internal;
#define IsWeird(n) ((n)->e >= ExpInfinity)
#define IsInfinity(n) (IsWeird(n) && (n)->h == HiddenBit && (n)->l == 0)
#define SetInfinity(n) ((n)->e = ExpInfinity, (n)->h = HiddenBit, (n)->l = 0)
#define IsNaN(n) (IsWeird(n) && (((n)->h & ~HiddenBit) || (n)->l))
#define SetQNaN(n) ((n)->s = 0, (n)->e = ExpInfinity, \
(n)->h = HiddenBit|(LsBit<<1), (n)->l = 0)
#define IsZero(n) ((n)->e == 1 && (n)->h == 0 && (n)->l == 0)
#define SetZero(n) ((n)->e = 1, (n)->h = 0, (n)->l = 0)
/*
* fpi.c
*/
extern void fpiround(Internal *);
extern void fpiadd(Internal *, Internal *, Internal *);
extern void fpisub(Internal *, Internal *, Internal *);
extern void fpimul(Internal *, Internal *, Internal *);
extern void fpidiv(Internal *, Internal *, Internal *);
extern int fpicmp(Internal *, Internal *);
extern void fpinormalise(Internal*);
/*
* fpimem.c
*/
extern void fpis2i(Internal *, void *);
extern void fpid2i(Internal *, void *);
extern void fpiw2i(Internal *, void *);
extern void fpii2s(void *, Internal *);
extern void fpii2d(void *, Internal *);
extern void fpii2w(Word *, Internal *);

View file

@ -1,570 +0,0 @@
/*
* this doesn't attempt to implement ARM floating-point properties
* that aren't visible in the Inferno environment.
* all arithmetic is done in double precision.
* the FP trap status isn't updated.
*/
#include <u.h>
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include <ureg.h>
#include "fpi.h"
/* undef this if correct kernel r13 isn't in Ureg;
* check calculation in fpiarm below
*/
#define REG(ur, x) (*(long*)(((char*)(ur))+roff[(x)]))
#define FR(ufp, x) (*(Internal*)(ufp)->regs[(x)&7])
typedef struct FP2 FP2;
typedef struct FP1 FP1;
struct FP2 {
char* name;
void (*f)(Internal, Internal, Internal*);
};
struct FP1 {
char* name;
void (*f)(Internal*, Internal*);
};
enum {
N = 1<<31,
Z = 1<<30,
C = 1<<29,
V = 1<<28,
REGPC = 15,
};
int fpemudebug = 0;
#undef OFR
#define OFR(X) ((ulong)&((Ureg*)0)->X)
static int roff[] = {
OFR(r0), OFR(r1), OFR(r2), OFR(r3),
OFR(r4), OFR(r5), OFR(r6), OFR(r7),
OFR(r8), OFR(r9), OFR(r10), OFR(r11),
OFR(r12), OFR(r13), OFR(r14), OFR(pc),
};
static Internal fpconst[8] = { /* indexed by op&7 */
/* s, e, l, h */
{0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */
{0, 0x3FF, 0x00000000, 0x08000000}, /* 1.0 */
{0, 0x400, 0x00000000, 0x08000000}, /* 2.0 */
{0, 0x400, 0x00000000, 0x0C000000}, /* 3.0 */
{0, 0x401, 0x00000000, 0x08000000}, /* 4.0 */
{0, 0x401, 0x00000000, 0x0A000000}, /* 5.0 */
{0, 0x3FE, 0x00000000, 0x08000000}, /* 0.5 */
{0, 0x402, 0x00000000, 0x0A000000}, /* 10.0 */
};
/*
* arm binary operations
*/
static void
fadd(Internal m, Internal n, Internal *d)
{
(m.s == n.s? fpiadd: fpisub)(&m, &n, d);
}
static void
fsub(Internal m, Internal n, Internal *d)
{
m.s ^= 1;
(m.s == n.s? fpiadd: fpisub)(&m, &n, d);
}
static void
fsubr(Internal m, Internal n, Internal *d)
{
n.s ^= 1;
(n.s == m.s? fpiadd: fpisub)(&n, &m, d);
}
static void
fmul(Internal m, Internal n, Internal *d)
{
fpimul(&m, &n, d);
}
static void
fdiv(Internal m, Internal n, Internal *d)
{
fpidiv(&m, &n, d);
}
static void
fdivr(Internal m, Internal n, Internal *d)
{
fpidiv(&n, &m, d);
}
/*
* arm unary operations
*/
static void
fmov(Internal *m, Internal *d)
{
*d = *m;
}
static void
fmovn(Internal *m, Internal *d)
{
*d = *m;
d->s ^= 1;
}
static void
fabsf(Internal *m, Internal *d)
{
*d = *m;
d->s = 0;
}
static void
frnd(Internal *m, Internal *d)
{
short e;
(m->s? fsub: fadd)(fpconst[6], *m, d);
if(IsWeird(d))
return;
fpiround(d);
e = (d->e - ExpBias) + 1;
if(e <= 0)
SetZero(d);
else if(e > FractBits){
if(e < 2*FractBits)
d->l &= ~((1<<(2*FractBits - e))-1);
}else{
d->l = 0;
if(e < FractBits)
d->h &= ~((1<<(FractBits-e))-1);
}
}
static FP1 optab1[16] = { /* Fd := OP Fm */
[0] {"MOVF", fmov},
[1] {"NEGF", fmovn},
[2] {"ABSF", fabsf},
[3] {"RNDF", frnd},
[4] {"SQTF", /*fsqt*/0},
/* LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN all `deprecated' */
/* URD and NRM aren't implemented */
};
static FP2 optab2[16] = { /* Fd := Fn OP Fm */
[0] {"ADDF", fadd},
[1] {"MULF", fmul},
[2] {"SUBF", fsub},
[3] {"RSUBF", fsubr},
[4] {"DIVF", fdiv},
[5] {"RDIVF", fdivr},
/* POW, RPW deprecated */
[8] {"REMF", /*frem*/0},
[9] {"FMF", fmul}, /* fast multiply */
[10] {"FDV", fdiv}, /* fast divide */
[11] {"FRD", fdivr}, /* fast reverse divide */
/* POL deprecated */
};
static ulong
fcmp(Internal *n, Internal *m)
{
int i;
Internal rm, rn;
if(IsWeird(m) || IsWeird(n)){
/* BUG: should trap if not masked */
return V|C;
}
rn = *n;
rm = *m;
fpiround(&rn);
fpiround(&rm);
i = fpicmp(&rn, &rm);
if(i > 0)
return C;
else if(i == 0)
return C|Z;
else
return N;
}
static void
fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPsave *ufp)
{
void *mem;
mem = (void*)ea;
(*f)(&FR(ufp, d), mem);
if(fpemudebug)
print("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d);
}
static void
fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPsave *ufp)
{
Internal tmp;
void *mem;
mem = (void*)ea;
tmp = FR(ufp, s);
if(fpemudebug)
print("MOV%c F%d,#%lux\n", n==8? 'D': 'F', s, ea);
(*f)(mem, &tmp);
}
static int
condok(int cc, int c)
{
switch(c){
case 0: /* Z set */
return cc&Z;
case 1: /* Z clear */
return (cc&Z) == 0;
case 2: /* C set */
return cc&C;
case 3: /* C clear */
return (cc&C) == 0;
case 4: /* N set */
return cc&N;
case 5: /* N clear */
return (cc&N) == 0;
case 6: /* V set */
return cc&V;
case 7: /* V clear */
return (cc&V) == 0;
case 8: /* C set and Z clear */
return cc&C && (cc&Z) == 0;
case 9: /* C clear or Z set */
return (cc&C) == 0 || cc&Z;
case 10: /* N set and V set, or N clear and V clear */
return (~cc&(N|V))==0 || (cc&(N|V)) == 0;
case 11: /* N set and V clear, or N clear and V set */
return (cc&(N|V))==N || (cc&(N|V))==V;
case 12: /* Z clear, and either N set and V set or N clear and V clear */
return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0);
case 13: /* Z set, or N set and V clear or N clear and V set */
return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V;
case 14: /* always */
return 1;
case 15: /* never (reserved) */
return 0;
}
return 0; /* not reached */
}
static void
unimp(ulong pc, ulong op)
{
char buf[60];
snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", pc, op);
if(fpemudebug)
print("FPE: %s\n", buf);
error(buf);
/* no return */
}
static void
fpemu(ulong pc, ulong op, Ureg *ur, FPsave *ufp)
{
int rn, rd, tag, o;
long off;
ulong ea;
Internal tmp, *fm, *fn;
/* note: would update fault status here if we noted numeric exceptions */
/*
* LDF, STF; 10.1.1
*/
if(((op>>25)&7) == 6){
if(op & (1<<22))
unimp(pc, op); /* packed or extended */
rn = (op>>16)&0xF;
off = (op&0xFF)<<2;
if((op & (1<<23)) == 0)
off = -off;
ea = REG(ur, rn);
if(rn == REGPC)
ea += 8;
if(op & (1<<24))
ea += off;
rd = (op>>12)&7;
if(op & (1<<20)){
if(op & (1<<15))
fld(fpid2i, rd, ea, 8, ufp);
else
fld(fpis2i, rd, ea, 4, ufp);
}else{
if(op & (1<<15))
fst(fpii2d, ea, rd, 8, ufp);
else
fst(fpii2s, ea, rd, 4, ufp);
}
if((op & (1<<24)) == 0)
ea += off;
if(op & (1<<21))
REG(ur, rn) = ea;
return;
}
/*
* CPRT/transfer, 10.3
*/
if(op & (1<<4)){
rd = (op>>12) & 0xF;
/*
* compare, 10.3.1
*/
if(rd == 15 && op & (1<<20)){
rn = (op>>16)&7;
fn = &FR(ufp, rn);
if(op & (1<<3)){
fm = &fpconst[op&7];
tag = 'C';
}else{
fm = &FR(ufp, op&7);
tag = 'F';
}
switch((op>>21)&7){
default:
unimp(pc, op);
case 4: /* CMF: Fn :: Fm */
case 6: /* CMFE: Fn :: Fm (with exception) */
ur->psr &= ~(N|C|Z|V);
ur->psr |= fcmp(fn, fm);
break;
case 5: /* CNF: Fn :: -Fm */
case 7: /* CNFE: Fn :: -Fm (with exception) */
tmp = *fm;
tmp.s ^= 1;
ur->psr &= ~(N|C|Z|V);
ur->psr |= fcmp(fn, &tmp);
break;
}
if(fpemudebug)
print("CMPF %c%d,F%ld =%lux\n", tag, rn, op&7, ur->psr>>28);
return;
}
/*
* other transfer, 10.3
*/
switch((op>>20)&0xF){
default:
unimp(pc, op);
case 0: /* FLT */
rn = (op>>16) & 7;
fpiw2i(&FR(ufp, rn), &REG(ur, rd));
if(fpemudebug)
print("MOVW[FD] R%d, F%d\n", rd, rn);
break;
case 1: /* FIX */
if(op & (1<<3))
unimp(pc, op);
rn = op & 7;
tmp = FR(ufp, rn);
fpii2w(&REG(ur, rd), &tmp);
if(fpemudebug)
print("MOV[FD]W F%d, R%d =%ld\n", rn, rd, REG(ur, rd));
break;
case 2: /* FPSR := Rd */
ufp->status = REG(ur, rd);
if(fpemudebug)
print("MOVW R%d, FPSR\n", rd);
break;
case 3: /* Rd := FPSR */
REG(ur, rd) = ufp->status;
if(fpemudebug)
print("MOVW FPSR, R%d\n", rd);
break;
case 4: /* FPCR := Rd */
ufp->control = REG(ur, rd);
if(fpemudebug)
print("MOVW R%d, FPCR\n", rd);
break;
case 5: /* Rd := FPCR */
REG(ur, rd) = ufp->control;
if(fpemudebug)
print("MOVW FPCR, R%d\n", rd);
break;
}
return;
}
/*
* arithmetic
*/
if(op & (1<<3)){ /* constant */
fm = &fpconst[op&7];
tag = 'C';
}else{
fm = &FR(ufp, op&7);
tag = 'F';
}
rd = (op>>12)&7;
o = (op>>20)&0xF;
if(op & (1<<15)){ /* monadic */
FP1 *fp;
fp = &optab1[o];
if(fp->f == nil)
unimp(pc, op);
if(fpemudebug)
print("%s %c%ld,F%d\n", fp->name, tag, op&7, rd);
(*fp->f)(fm, &FR(ufp, rd));
} else {
FP2 *fp;
fp = &optab2[o];
if(fp->f == nil)
unimp(pc, op);
rn = (op>>16)&7;
if(fpemudebug)
print("%s %c%ld,F%d,F%d\n", fp->name, tag, op&7, rn, rd);
(*fp->f)(*fm, FR(ufp, rn), &FR(ufp, rd));
}
}
void
casemu(ulong pc, ulong op, Ureg *ur)
{
ulong *rp, ro, rn, *rd;
USED(pc);
rp = (ulong*)ur;
ro = rp[op>>16 & 0x7];
rn = rp[op>>0 & 0x7];
rd = rp + (op>>12 & 0x7);
rp = (ulong*)*rd;
validaddr((ulong)rp, 4, 1);
splhi();
if(*rd = (*rp == ro))
*rp = rn;
spllo();
}
int ldrexvalid;
void
ldrex(ulong pc, ulong op, Ureg *ur)
{
ulong *rp, *rd, *addr;
USED(pc);
rp = (ulong*)ur;
rd = rp + (op>>16 & 0x7);
addr = (ulong*)*rd;
validaddr((ulong)addr, 4, 0);
ldrexvalid = 1;
rp[op>>12 & 0x7] = *addr;
if(fpemudebug)
print("ldrex, r%ld = [r%ld]@0x%8.8p = 0x%8.8lux",
op>>12 & 0x7, op>>16 & 0x7, addr, rp[op>>12 & 0x7]);
}
void
strex(ulong pc, ulong op, Ureg *ur)
{
ulong *rp, rn, *rd, *addr;
USED(pc);
rp = (ulong*)ur;
rd = rp + (op>>16 & 0x7);
rn = rp[op>>0 & 0x7];
addr = (ulong*)*rd;
validaddr((ulong)addr, 4, 1);
splhi();
if(ldrexvalid){
if(fpemudebug)
print("strex valid, [r%ld]@0x%8.8p = r%ld = 0x%8.8lux",
op>>16 & 0x7, addr, op>>0 & 0x7, rn);
*addr = rn;
ldrexvalid = 0;
rp[op>>12 & 0x7] = 0;
}else{
if(fpemudebug)
print("strex invalid, r%ld = 1", op>>16 & 0x7);
rp[op>>12 & 0x7] = 1;
}
spllo();
}
struct {
ulong opc;
ulong mask;
void (*f)(ulong, ulong, Ureg*);
} specialopc[] = {
{ 0x01900f9f, 0x0ff00fff, ldrex },
{ 0x01800f90, 0x0ff00ff0, strex },
{ 0x0ed00100, 0x0ef08100, casemu },
{ 0x00000000, 0x00000000, nil }
};
/*
* returns the number of FP instructions emulated
*/
int
fpiarm(Ureg *ur)
{
ulong op, o;
FPsave *ufp;
int i, n;
if (up == nil)
panic("fpiarm not in a process");
ufp = &up->fpsave;
/* because all the state is in the proc structure,
* it need not be saved/restored
*/
if(up->fpstate != FPactive) {
// assert(sizeof(Internal) == sizeof(ufp->regs[0]));
up->fpstate = FPactive;
ufp->control = 0;
ufp->status = (0x01<<28)|(1<<12); /* software emulation, alternative C flag */
for(n = 0; n < 8; n++)
FR(ufp, n) = fpconst[0];
}
for(n=0; ;n++){
if(fpemudebug)
print("0x%8.8lux ", ur->pc);
validaddr(ur->pc, 4, 0);
op = *(ulong*)(ur->pc);
o = (op>>24) & 0xF;
if(condok(ur->psr, op>>28)){
for(i = 0; specialopc[i].f; i++)
if((op & specialopc[i].mask) == specialopc[i].opc)
break;
if(specialopc[i].f)
specialopc[i].f(ur->pc, op, ur);
else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC)
break;
else
fpemu(ur->pc, op, ur, ufp);
}else if((op & 0xF00) != 0x100 || o != 0xE && (o&~1) != 0xC)
break;
ur->pc += 4;
}
if(fpemudebug) print("\n");
return n;
}

View file

@ -1,136 +0,0 @@
#include "fpi.h"
/*
* the following routines depend on memory format, not the machine
*/
void
fpis2i(Internal *i, void *v)
{
Single *s = v;
i->s = (*s & 0x80000000) ? 1: 0;
if((*s & ~0x80000000) == 0){
SetZero(i);
return;
}
i->e = ((*s>>23) & 0x00FF) - SingleExpBias + ExpBias;
i->h = (*s & 0x007FFFFF)<<(1+NGuardBits);
i->l = 0;
if(i->e)
i->h |= HiddenBit;
else
i->e++;
}
void
fpid2i(Internal *i, void *v)
{
Double *d = v;
i->s = (d->h & 0x80000000) ? 1: 0;
i->e = (d->h>>20) & 0x07FF;
i->h = ((d->h & 0x000FFFFF)<<(4+NGuardBits))|((d->l>>25) & 0x7F);
i->l = (d->l & 0x01FFFFFF)<<NGuardBits;
if(i->e)
i->h |= HiddenBit;
else
i->e++;
}
void
fpiw2i(Internal *i, void *v)
{
Word w, word = *(Word*)v;
short e;
if(word < 0){
i->s = 1;
word = -word;
}
else
i->s = 0;
if(word == 0){
SetZero(i);
return;
}
if(word > 0){
for (e = 0, w = word; w; w >>= 1, e++)
;
} else
e = 32;
if(e > FractBits){
i->h = word>>(e - FractBits);
i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
}
else {
i->h = word<<(FractBits - e);
i->l = 0;
}
i->e = (e - 1) + ExpBias;
}
void
fpii2s(void *v, Internal *i)
{
short e;
Single *s = (Single*)v;
fpiround(i);
if(i->h & HiddenBit)
i->h &= ~HiddenBit;
else
i->e--;
*s = i->s ? 0x80000000: 0;
e = i->e;
if(e < ExpBias){
if(e <= (ExpBias - SingleExpBias))
return;
e = SingleExpBias - (ExpBias - e);
}
else if(e >= (ExpBias + (SingleExpMax-SingleExpBias))){
*s |= SingleExpMax<<23;
return;
}
else
e = SingleExpBias + (e - ExpBias);
*s |= (e<<23)|(i->h>>(1+NGuardBits));
}
void
fpii2d(void *v, Internal *i)
{
Double *d = (Double*)v;
fpiround(i);
if(i->h & HiddenBit)
i->h &= ~HiddenBit;
else
i->e--;
i->l = ((i->h & GuardMask)<<25)|(i->l>>NGuardBits);
i->h >>= NGuardBits;
d->h = i->s ? 0x80000000: 0;
d->h |= (i->e<<20)|((i->h & 0x00FFFFFF)>>4);
d->l = (i->h<<28)|i->l;
}
void
fpii2w(Word *word, Internal *i)
{
Word w;
short e;
fpiround(i);
e = (i->e - ExpBias) + 1;
if(e <= 0)
w = 0;
else if(e > 31)
w = 0x7FFFFFFF;
else if(e > FractBits)
w = (i->h<<(e - FractBits))|(i->l>>(2*FractBits - e));
else
w = i->h>>(FractBits-e);
if(i->s)
w = -w;
*word = w;
}

View file

@ -1,51 +0,0 @@
#include <u.h>
#include <libc.h>
#include <stdio.h>
double gamma = 1.6;
int
remap5(int i)
{
double v;
v = (double)i/31.0;
return 31.0*pow(v, gamma);
}
int
remap6(int i)
{
double v;
v = (double)i/63.0;
return 63.0*pow(v, gamma);
}
int
remap(int i)
{
int r, g, b;
b = i & 0x1F;
g = (i>>5) & 0x3F;
r = (i>>11) & 0x1F;
return (remap5(r)<<11) | (remap6(g)<<5) | (remap5(b)<<0);
}
void
main(void)
{
int i;
printf("/* gamma = %.2f */\n", gamma);
printf("ushort gamma[65536] = {\n");
for(i=0; i<65536; i++){
if((i%8) == 0)
printf("\t");
printf("0x%.4x, ", remap(i));
if((i%8) == 7)
printf("\n");
}
printf("};\n");
}

File diff suppressed because it is too large Load diff

View file

@ -1,12 +0,0 @@
TEXT _main(SB),$8
MOVW $setR12(SB), R12 /* load the SB */
MOVW $boot(SB), R0
ADD $12, R13, R1 /* get a pointer to 0(FP) */
MOVW R0, 4(R13)
MOVW R1, 8(R13)
BL startboot(SB)

View file

@ -1,337 +0,0 @@
/*
* Definitions for IO devices. Used only in C.
*/
enum
{
/* hardware counter frequency */
ClockFreq= 3686400,
};
/*
* IRQ's defined by SA1100
*/
enum
{
IRQgpio0= 0,
IRQgpio1= 1,
IRQgpio2= 2,
IRQgpio3= 3,
IRQgpio4= 4,
IRQgpio5= 5,
IRQgpio6= 6,
IRQgpio7= 7,
IRQgpio8= 8,
IRQgpio9= 9,
IRQgpio10= 10,
IRQgpiohi= 11,
IRQlcd= 12,
IRQudc= 13,
IRQuart1b= 15,
IRQuart2= 16,
IRQuart3= 17,
IRQmcp= 18,
IRQssp= 19,
IRQdma0= 20,
IRQdma1= 21,
IRQdma2= 22,
IRQdma3= 23,
IRQdma4= 24,
IRQdma5= 25,
IRQtimer0= 26,
IRQtimer1= 27,
IRQtimer2= 28,
IRQtimer3= 29,
IRQsecond= 30,
IRQrtc= 31,
};
/*
* GPIO lines (signal names from compaq document). _i indicates input
* and _o output.
*/
enum
{
GPIO_PWR_ON_i= 1<<0, /* power button */
GPIO_UP_IRQ_i= 1<<1, /* microcontroller interrupts */
GPIO_LDD8_o= 1<<2, /* LCD data 8-15 */
GPIO_LDD9_o= 1<<3,
GPIO_LDD10_o= 1<<4,
GPIO_LDD11_o= 1<<5,
GPIO_LDD12_o= 1<<6,
GPIO_LDD13_o= 1<<7,
GPIO_LDD14_o= 1<<8,
GPIO_LDD15_o= 1<<9,
GPIO_CARD_IND1_i= 1<<10, /* card inserted in PCMCIA socket 1 */
GPIO_CARD_IRQ1_i= 1<<11, /* PCMCIA socket 1 interrupt */
GPIO_CLK_SET0_o= 1<<12, /* clock selects for audio codec */
GPIO_CLK_SET1_o= 1<<13,
GPIO_L3_SDA_io= 1<<14, /* UDA1341 interface */
GPIO_L3_MODE_o= 1<<15,
GPIO_L3_SCLK_o= 1<<16,
GPIO_CARD_IND0_i= 1<<17, /* card inserted in PCMCIA socket 0 */
GPIO_KEY_ACT_i= 1<<18, /* hot key from cradle */
GPIO_SYS_CLK_i= 1<<19, /* clock from codec */
GPIO_BAT_FAULT_i= 1<<20, /* battery fault */
GPIO_CARD_IRQ0_i= 1<<21, /* PCMCIA socket 0 interrupt */
GPIO_LOCK_i= 1<<22, /* expansion pack lock/unlock */
GPIO_COM_DCD_i= 1<<23, /* DCD from UART3 */
GPIO_OPT_IRQ_i= 1<<24, /* expansion pack IRQ */
GPIO_COM_CTS_i= 1<<25, /* CTS from UART3 */
GPIO_COM_RTS_o= 1<<26, /* RTS to UART3 */
GPIO_OPT_IND_i= 1<<27, /* expansion pack inserted */
/* Peripheral Unit GPIO pin assignments: alternate functions */
GPIO_SSP_TXD_o= 1<<10, /* SSP Transmit Data */
GPIO_SSP_RXD_i= 1<<11, /* SSP Receive Data */
GPIO_SSP_SCLK_o= 1<<12, /* SSP Sample CLocK */
GPIO_SSP_SFRM_o= 1<<13, /* SSP Sample FRaMe */
/* ser. port 1: */
GPIO_UART_TXD_o= 1<<14, /* UART Transmit Data */
GPIO_UART_RXD_i= 1<<15, /* UART Receive Data */
GPIO_SDLC_SCLK_io= 1<<16, /* SDLC Sample CLocK (I/O) */
GPIO_SDLC_AAF_o= 1<<17, /* SDLC Abort After Frame */
GPIO_UART_SCLK1_i= 1<<18, /* UART Sample CLocK 1 */
/* ser. port 4: */
GPIO_SSP_CLK_i= 1<<19, /* SSP external CLocK */
/* ser. port 3: */
GPIO_UART_SCLK3_i= 1<<20, /* UART Sample CLocK 3 */
/* ser. port 4: */
GPIO_MCP_CLK_i= 1<<21, /* MCP CLocK */
/* test controller: */
GPIO_TIC_ACK_o= 1<<21, /* TIC ACKnowledge */
GPIO_MBGNT_o= 1<<21, /* Memory Bus GraNT */
GPIO_TREQA_i= 1<<22, /* TIC REQuest A */
GPIO_MBREQ_i= 1<<22, /* Memory Bus REQuest */
GPIO_TREQB_i= 1<<23, /* TIC REQuest B */
GPIO_1Hz_o= 1<<25, /* 1 Hz clock */
GPIO_RCLK_o= 1<<26, /* internal (R) CLocK (O, fcpu/2) */
GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */
};
/*
* types of interrupts
*/
enum
{
GPIOrising,
GPIOfalling,
GPIOboth,
IRQ,
};
/* hardware registers */
typedef struct Uartregs Uartregs;
struct Uartregs
{
ulong ctl[4];
ulong dummya;
ulong data;
ulong dummyb;
ulong status[2];
};
extern Uartregs *uart3regs;
extern Uartregs *uart1regs;
/* general purpose I/O lines control registers */
typedef struct GPIOregs GPIOregs;
struct GPIOregs
{
ulong level; /* 1 == high */
ulong direction; /* 1 == output */
ulong set; /* a 1 sets the bit, 0 leaves it alone */
ulong clear; /* a 1 clears the bit, 0 leaves it alone */
ulong rising; /* rising edge detect enable */
ulong falling; /* falling edge detect enable */
ulong edgestatus; /* writing a 1 bit clears */
ulong altfunc; /* turn on alternate function for any set bits */
};
extern GPIOregs *gpioregs;
/* extra general purpose I/O bits, output only */
enum
{
EGPIO_prog_flash= 1<<0,
EGPIO_pcmcia_reset= 1<<1,
EGPIO_exppack_reset= 1<<2,
EGPIO_codec_reset= 1<<3,
EGPIO_exp_nvram_power= 1<<4,
EGPIO_exp_full_power= 1<<5,
EGPIO_lcd_3v= 1<<6,
EGPIO_rs232_power= 1<<7,
EGPIO_lcd_ic_power= 1<<8,
EGPIO_ir_power= 1<<9,
EGPIO_audio_power= 1<<10,
EGPIO_audio_ic_power= 1<<11,
EGPIO_audio_mute= 1<<12,
EGPIO_fir= 1<<13, /* not set is sir */
EGPIO_lcd_5v= 1<<14,
EGPIO_lcd_9v= 1<<15,
};
extern ulong *egpioreg;
/* Peripheral pin controller registers */
typedef struct PPCregs PPCregs;
struct PPCregs {
ulong direction;
ulong state;
ulong assignment;
ulong sleepdir;
ulong flags;
};
extern PPCregs *ppcregs;
/* Synchronous Serial Port controller registers */
typedef struct SSPregs SSPregs;
struct SSPregs {
ulong control0;
ulong control1;
ulong dummy0;
ulong data;
ulong dummy1;
ulong status;
};
extern SSPregs *sspregs;
/* Multimedia Communications Port controller registers */
typedef struct MCPregs MCPregs;
struct MCPregs {
ulong control0;
ulong reserved0;
ulong data0;
ulong data1;
ulong data2;
ulong reserved1;
ulong status;
ulong reserved[11];
ulong control1;
};
extern MCPregs *mcpregs;
/*
* memory configuration
*/
enum
{
/* bit shifts for pcmcia access time counters */
MECR_io0= 0,
MECR_attr0= 5,
MECR_mem0= 10,
MECR_fast0= 11,
MECR_io1= MECR_io0+16,
MECR_attr1= MECR_attr0+16,
MECR_mem1= MECR_mem0+16,
MECR_fast1= MECR_fast0+16,
REFR_kapd= 29,
REFR_eapd= 28,
REFR_k1db2= 22,
REFR_slfrsh= 31,
};
typedef struct MemConfRegs MemConfRegs;
struct MemConfRegs
{
ulong mdcnfg; /* 0x00 dram */
ulong mdcas00; /* 0x04 dram banks 0/1 */
ulong mdcas01; /* 0x08 */
ulong mdcas02; /* 0x0c */
ulong msc0; /* 0x10 static */
ulong msc1; /* 0x14 */
ulong mecr; /* 0x18 pcmcia */
ulong mdrefr; /* 0x1c dram refresh */
ulong mdcas20; /* 0x20 dram banks 2/3 */
ulong mdcas21; /* 0x24 */
ulong mdcas22; /* 0x28 */
ulong msc2; /* 0x2c static */
ulong smcnfg; /* 0x30 SMROM config */
};
extern MemConfRegs *memconfregs;
/*
* power management
*/
/* Power management ops */
typedef struct PowerRegs PowerRegs;
struct PowerRegs
{
ulong pmcr; /* 0x0 Power manager control register */
ulong pssr; /* 0x4 Power manager sleep status register */
ulong pspr; /* 0x8 Power manager scratch pad register */
ulong pwer; /* 0xc Power manager wakeup enable register */
ulong pcfr; /* 0x10 Power manager general configuration register */
ulong ppcr; /* 0x14 Power manager PPL configuration register */
ulong pgsr; /* 0x18 Power manager GPIO sleep state register */
ulong posr; /* 0x1c Power manager oscillator status register */
};
extern PowerRegs *powerregs;
/*
* reset controller
*/
enum
{
RCSR_hwr = 0x00000001, /* hw reset */
RCSR_swr = 0x00000002, /* sw reset */
RCSR_wdr = 0x00000004, /* watch dog */
RCSR_smr = 0x00000008, /* sleep mode reset */
};
typedef struct ResetRegs ResetRegs;
struct ResetRegs
{
ulong rsrr; /* reset controller software reset register */
ulong rcsr; /* reset controller status register */
};
extern ResetRegs *resetregs;
typedef struct OSTimerRegs OSTimerRegs;
struct OSTimerRegs
{
ulong osmr[4]; /* match registers */
ulong oscr; /* counter register */
ulong ossr; /* status register */
ulong ower; /* watchdog enable register */
ulong oier; /* timer interrupt enable register */
};
extern OSTimerRegs* timerregs;
typedef struct Intrregs Intrregs;
struct Intrregs
{
ulong icip; /* pending IRQs */
ulong icmr; /* IRQ mask */
ulong iclr; /* IRQ if bit == 0, FRIQ if 1 */
ulong iccr; /* control register */
ulong icfp; /* pending FIQs */
ulong dummy1[3];
ulong icpr; /* pending interrupts */
};
extern Intrregs *intrregs;
typedef struct Gpclkregs Gpclkregs;
struct Gpclkregs
{
ulong r0;
ulong r1;
ulong dummya;
ulong r2;
ulong r3;
};
extern Gpclkregs *gpclkregs;
/*
* Dont use this on bitsy drivers.
* This is for compat with code compiled
* from the ../pc directory
*/
typedef struct Pcidev Pcidev;
typedef struct ISAConf ISAConf;
struct Pcidev { int dummy; };
struct ISAConf{ int port; int irq; };
int pcmspecial(char*, ISAConf*);

View file

@ -1,857 +0,0 @@
#include "mem.h"
/*
* Entered here from Compaq's bootldr with MMU disabled.
*/
TEXT _start(SB), $-4
MOVW $setR12(SB), R12 /* load the SB */
_main:
/* SVC mode, interrupts disabled */
MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
MOVW R1, CPSR
/* disable the MMU */
MOVW $0x130, R1
MCR CpMMU, 0, R1, C(CpControl), C(0x0)
/* flush caches */
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
/* drain prefetch */
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
/* drain write buffer */
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
MOVW $(MACHADDR+4*BY2PG), R13 /* stack */
SUB $4, R13 /* link */
BL main(SB)
BL exit(SB)
/* we shouldn't get here */
_mainloop:
B _mainloop
BL _div(SB) /* hack to get _div etc loaded */
/* flush tlb's */
TEXT mmuinvalidate(SB), $-4
MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
RET
/* flush tlb's */
TEXT mmuinvalidateaddr(SB), $-4
MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
RET
/* write back and invalidate i and d caches */
TEXT cacheflush(SB), $-4
/* splhi */
MOVW CPSR, R3
ORR $(PsrDirq), R3, R1
MOVW R1, CPSR
/* write back any dirty data */
MOVW $0xe0000000,R0
ADD $(8*1024),R0,R1
_cfloop:
MOVW.P 32(R0),R2
CMP.S R0,R1
BGE _cfloop
/* drain write buffer and invalidate i cache contents */
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x5), 0
/* drain prefetch */
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
/* splx */
MOVW R3, CPSR
RET
/* write back d cache */
TEXT cachewb(SB), $-4
/* write back any dirty data */
_cachewb:
MOVW $0xe0000000,R0
ADD $(8*1024),R0,R1
_cwbloop:
MOVW.P 32(R0),R2
CMP.S R0,R1
BGE _cwbloop
/* drain write buffer */
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
RET
/* write back a single cache line */
TEXT cachewbaddr(SB), $-4
BIC $31,R0
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
B _wbflush
/* write back a region of cache lines */
TEXT cachewbregion(SB), $-4
MOVW 4(FP),R1
CMP.S $(4*1024),R1
BGT _cachewb
ADD R0,R1
BIC $31,R0
_cwbrloop:
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
ADD $32,R0
CMP.S R0,R1
BGT _cwbrloop
B _wbflush
/* invalidate the dcache */
TEXT dcacheinvalidate(SB), $-4
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
RET
/* invalidate the icache */
TEXT icacheinvalidate(SB), $-4
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
RET
/* drain write buffer */
TEXT wbflush(SB), $-4
_wbflush:
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
RET
/* return cpu id */
TEXT getcpuid(SB), $-4
MRC CpMMU, 0, R0, C(CpCPUID), C(0x0)
RET
/* return fault status */
TEXT getfsr(SB), $-4
MRC CpMMU, 0, R0, C(CpFSR), C(0x0)
RET
/* return mmu control register */
TEXT getcontrol(SB), $-4
SUB R0, R0
MRC CpMMU, 0, R0, C(CpControl), C(0x0)
RET
/* return mmu dac register */
TEXT getdac(SB), $-4
SUB R0, R0
MRC CpMMU, 0, R0, C(CpDAC), C(0x0)
RET
/* return mmu ttb register */
TEXT getttb(SB), $-4
SUB R0, R0
MRC CpMMU, 0, R0, C(CpTTB), C(0x0)
RET
/* return fault address */
TEXT getfar(SB), $-4
MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
RET
/* set the translation table base */
TEXT putttb(SB), $-4
MCR CpMMU, 0, R0, C(CpTTB), C(0x0)
RET
/*
* enable mmu, i and d caches
*/
TEXT mmuenable(SB), $-4
MRC CpMMU, 0, R0, C(CpControl), C(0x0)
ORR $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCsystem), R0
BIC $(CpCrom), R0
MCR CpMMU, 0, R0, C(CpControl), C(0x0)
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
RET
TEXT mmudisable(SB), $-4
MRC CpMMU, 0, R0, C(CpControl), C(0x0)
BIC $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
MCR CpMMU, 0, R0, C(CpControl), C(0x0)
RET
/*
* use exception vectors at 0xffff0000
*/
TEXT mappedIvecEnable(SB), $-4
MRC CpMMU, 0, R0, C(CpControl), C(0x0)
ORR $(CpCvivec), R0
MCR CpMMU, 0, R0, C(CpControl), C(0x0)
RET
TEXT mappedIvecDisable(SB), $-4
MRC CpMMU, 0, R0, C(CpControl), C(0x0)
BIC $(CpCvivec), R0
MCR CpMMU, 0, R0, C(CpControl), C(0x0)
RET
/* set the translation table base */
TEXT putdac(SB), $-4
MCR CpMMU, 0, R0, C(CpDAC), C(0x0)
RET
/* set address translation pid */
TEXT putpid(SB), $-4
MCR CpMMU, 0, R0, C(CpPID), C(0x0)
RET
/*
* set the stack value for the mode passed in R0
*/
TEXT setr13(SB), $-4
MOVW 4(FP), R1
MOVW CPSR, R2
BIC $PsrMask, R2, R3
ORR R0, R3
MOVW R3, CPSR
MOVW R13, R0
MOVW R1, R13
MOVW R2, CPSR
RET
/*
* exception vectors, copied by trapinit() to somewhere useful
*/
TEXT vectors(SB), $-4
MOVW 0x18(R15), R15 /* reset */
MOVW 0x18(R15), R15 /* undefined */
MOVW 0x18(R15), R15 /* SWI */
MOVW 0x18(R15), R15 /* prefetch abort */
MOVW 0x18(R15), R15 /* data abort */
MOVW 0x18(R15), R15 /* reserved */
MOVW 0x18(R15), R15 /* IRQ */
MOVW 0x18(R15), R15 /* FIQ */
TEXT vtable(SB), $-4
WORD $_vsvc(SB) /* reset, in svc mode already */
WORD $_vund(SB) /* undefined, switch to svc mode */
WORD $_vsvc(SB) /* swi, in svc mode already */
WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
WORD $_vdabt(SB) /* data abort, switch to svc mode */
WORD $_vsvc(SB) /* reserved */
WORD $_virq(SB) /* IRQ, switch to svc mode */
WORD $_vfiq(SB) /* FIQ, switch to svc mode */
TEXT _vrst(SB), $-4
BL resettrap(SB)
TEXT _vsvc(SB), $-4 /* SWI */
MOVW.W R14, -4(R13) /* ureg->pc = interupted PC */
MOVW SPSR, R14 /* ureg->psr = SPSR */
MOVW.W R14, -4(R13) /* ... */
MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
MOVW.W R14, -4(R13) /* ... */
MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
MOVW R13, R0 /* first arg is pointer to ureg */
SUB $8, R13 /* space for argument+link */
BL syscall(SB)
ADD $(8+4*15), R13 /* make r13 point to ureg->type */
MOVW 8(R13), R14 /* restore link */
MOVW 4(R13), R0 /* restore SPSR */
MOVW R0, SPSR /* ... */
MOVM.DB.S (R13), [R0-R14] /* restore registers */
ADD $8, R13 /* pop past ureg->{type+psr} */
RFE /* MOVM.IA.S.W (R13), [R15] */
TEXT _vund(SB), $-4 /* undefined */
MOVM.IA [R0-R4], (R13) /* free some working space */
MOVW $PsrMund, R0
B _vswitch
TEXT _vpabt(SB), $-4 /* prefetch abort */
MOVM.IA [R0-R4], (R13) /* free some working space */
MOVW $PsrMabt, R0 /* r0 = type */
B _vswitch
TEXT _vdabt(SB), $-4 /* prefetch abort */
MOVM.IA [R0-R4], (R13) /* free some working space */
MOVW $(PsrMabt+1), R0 /* r0 = type */
B _vswitch
TEXT _virq(SB), $-4 /* IRQ */
MOVM.IA [R0-R4], (R13) /* free some working space */
MOVW $PsrMirq, R0 /* r0 = type */
B _vswitch
/*
* come here with type in R0 and R13 pointing above saved [r0-r4]
* and type in r0. we'll switch to SVC mode and then call trap.
*/
_vswitch:
MOVW SPSR, R1 /* save SPSR for ureg */
MOVW R14, R2 /* save interrupted pc for ureg */
MOVW R13, R3 /* save pointer to where the original [R0-R3] are */
/* switch to svc mode */
MOVW CPSR, R14
BIC $PsrMask, R14
ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
MOVW R14, CPSR
/* interupted code kernel or user? */
AND.S $0xf, R1, R4
BEQ _userexcep
/* here for trap from SVC mode */
MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
MOVM.DB.W [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
MOVW R13, R0 /* first arg is pointer to ureg */
SUB $8, R13 /* space for argument+link (for debugger) */
MOVW $0xdeaddead,R11 /* marker */
BL trap(SB)
ADD $(8+4*15), R13 /* make r13 point to ureg->type */
MOVW 8(R13), R14 /* restore link */
MOVW 4(R13), R0 /* restore SPSR */
MOVW R0, SPSR /* ... */
MOVM.DB (R13), [R0-R14] /* restore registers */
ADD $8, R13 /* pop past ureg->{type+psr} */
RFE /* MOVM.IA.S.W (R13), [R15] */
/* here for trap from USER mode */
_userexcep:
MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
MOVW R13, R0 /* first arg is pointer to ureg */
SUB $8, R13 /* space for argument+link (for debugger) */
BL trap(SB)
ADD $(8+4*15), R13 /* make r13 point to ureg->type */
MOVW 8(R13), R14 /* restore link */
MOVW 4(R13), R0 /* restore SPSR */
MOVW R0, SPSR /* ... */
MOVM.DB.S (R13), [R0-R14] /* restore registers */
ADD $8, R13 /* pop past ureg->{type+psr} */
RFE /* MOVM.IA.S.W (R13), [R15] */
TEXT _vfiq(SB), $-4 /* FIQ */
RFE /* FIQ is special, ignore it for now */
/*
* This is the first jump from kernel to user mode.
* Fake a return from interrupt.
*
* Enter with R0 containing the user stack pointer.
* UTZERO + 0x20 is always the entry point.
*
*/
TEXT touser(SB),$-4
/* store the user stack pointer into the USR_r13 */
MOVM.DB.W [R0], (R13)
MOVM.S.IA.W (R13),[R13]
/* set up a PSR for user level */
MOVW $(PsrMusr), R0
MOVW R0,SPSR
/* save the PC on the stack */
MOVW $(UTZERO+0x20), R0
MOVM.DB.W [R0],(R13)
/* return from interrupt */
RFE /* MOVM.IA.S.W (R13), [R15] */
/*
* here to jump to a newly forked process
*/
TEXT forkret(SB),$-4
ADD $(4*15), R13 /* make r13 point to ureg->type */
MOVW 8(R13), R14 /* restore link */
MOVW 4(R13), R0 /* restore SPSR */
MOVW R0, SPSR /* ... */
MOVM.DB.S (R13), [R0-R14] /* restore registers */
ADD $8, R13 /* pop past ureg->{type+psr} */
RFE /* MOVM.IA.S.W (R13), [R15] */
TEXT splhi(SB), $-4
/* save caller pc in Mach */
MOVW $(MACHADDR+0x04),R2
MOVW R14,0(R2)
/* turn off interrupts */
MOVW CPSR, R0
ORR $(PsrDirq), R0, R1
MOVW R1, CPSR
RET
TEXT spllo(SB), $-4
MOVW CPSR, R0
BIC $(PsrDirq), R0, R1
MOVW R1, CPSR
RET
TEXT splx(SB), $-4
/* save caller pc in Mach */
MOVW $(MACHADDR+0x04),R2
MOVW R14,0(R2)
/* reset interrupt level */
MOVW R0, R1
MOVW CPSR, R0
MOVW R1, CPSR
RET
TEXT splxpc(SB), $-4 /* for iunlock */
MOVW R0, R1
MOVW CPSR, R0
MOVW R1, CPSR
RET
TEXT spldone(SB), $0
RET
TEXT islo(SB), $-4
MOVW CPSR, R0
AND $(PsrDirq), R0
EOR $(PsrDirq), R0
RET
TEXT cpsrr(SB), $-4
MOVW CPSR, R0
RET
TEXT spsrr(SB), $-4
MOVW SPSR, R0
RET
TEXT getsp(SB), $-4
MOVW R13, R0
RET
TEXT getlink(SB), $-4
MOVW R14, R0
RET
TEXT getcallerpc(SB), $-4
MOVW 0(R13), R0
RET
TEXT tas(SB), $-4
TEXT _tas(SB), $-4
MOVW R0, R1
MOVW $0xDEADDEAD, R0
MOVW R0, R3
SWPW R0, (R1)
CMP.S R0, R3
BEQ _tasout
EOR R3, R3
CMP.S R0, R3
BEQ _tasout
MOVW $1,R15
_tasout:
RET
TEXT setlabel(SB), $-4
MOVW R13, 0(R0) /* sp */
MOVW R14, 4(R0) /* pc */
MOVW $0, R0
RET
TEXT gotolabel(SB), $-4
MOVW 0(R0), R13 /* sp */
MOVW 4(R0), R14 /* pc */
MOVW $1, R0
RET
/* save the state machine in power_state[] for an upcoming suspend
*/
TEXT setpowerlabel(SB), $-4
MOVW $power_state+0(SB), R0
/* svc */ /* power_state[]: what */
MOVW R1, 0(R0)
MOVW R2, 4(R0)
MOVW R3, 8(R0)
MOVW R4, 12(R0)
MOVW R5, 16(R0)
MOVW R6, 20(R0)
MOVW R7, 24(R0)
MOVW R8, 28(R0)
MOVW R9, 32(R0)
MOVW R10,36(R0)
MOVW R11,40(R0)
MOVW R12,44(R0)
MOVW R13,48(R0)
MOVW R14,52(R0)
MOVW SPSR, R1
MOVW R1, 56(R0)
MOVW CPSR, R2
MOVW R2, 60(R0)
/* copro */
MRC CpMMU, 0, R3, C(CpDAC), C(0x0)
MOVW R3, 144(R0)
MRC CpMMU, 0, R3, C(CpTTB), C(0x0)
MOVW R3, 148(R0)
MRC CpMMU, 0, R3, C(CpControl), C(0x0)
MOVW R3, 152(R0)
MRC CpMMU, 0, R3, C(CpFSR), C(0x0)
MOVW R3, 156(R0)
MRC CpMMU, 0, R3, C(CpFAR), C(0x0)
MOVW R3, 160(R0)
MRC CpMMU, 0, R3, C(CpPID), C(0x0)
MOVW R3, 164(R0)
/* usr */
BIC $(PsrMask), R2, R3
ORR $(0xdf), R3
MOVW R3, CPSR
MOVW SPSR, R11
MOVW R11, 168(R0)
MOVW R12, 172(R0)
MOVW R13, 176(R0)
MOVW R14, 180(R0)
/* irq */
BIC $(PsrMask), R2, R3
ORR $(0xd2), R3
MOVW R3, CPSR
MOVW SPSR, R11
MOVW R11, 64(R0)
MOVW R12, 68(R0)
MOVW R13, 72(R0)
MOVW R14, 76(R0)
/* und */
BIC $(PsrMask), R2, R3
ORR $(0xdb), R3
MOVW R3, CPSR
MOVW SPSR, R11
MOVW R11, 80(R0)
MOVW R12, 84(R0)
MOVW R13, 88(R0)
MOVW R14, 92(R0)
/* abt */
BIC $(PsrMask), R2, R3
ORR $(0xd7), R3
MOVW R3, CPSR
MOVW SPSR, R11
MOVW R11, 96(R0)
MOVW R12, 100(R0)
MOVW R13, 104(R0)
MOVW R14, 108(R0)
/* fiq */
BIC $(PsrMask), R2, R3
ORR $(0xd1), R3
MOVW R3, CPSR
MOVW SPSR, R7
MOVW R7, 112(R0)
MOVW R8, 116(R0)
MOVW R9, 120(R0)
MOVW R10,124(R0)
MOVW R11,128(R0)
MOVW R12,132(R0)
MOVW R13,136(R0)
MOVW R14,140(R0)
/* done */
MOVW R2, CPSR
MOVW R1, SPSR
MOVW $0, R0
RET
/* Entered after a resume from suspend state.
* The bootldr jumps here after a processor reset.
*/
TEXT power_resume(SB), $-4
MOVW $setR12(SB), R12 /* load the SB */
/* SVC mode, interrupts disabled */
MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
MOVW R1, CPSR
/* gotopowerlabel() */
/* svc */
MOVW $power_state+0(SB), R0
MOVW 56(R0), R1 /* R1: SPSR, R2: CPSR */
MOVW 60(R0), R2
MOVW R1, SPSR
MOVW R2, CPSR
/* copro */
/* flush caches */
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
/* drain prefetch */
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
/* drain write buffer */
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
MOVW 144(R0), R3
MCR CpMMU, 0, R3, C(CpDAC), C(0x0)
MOVW 148(R0), R3
MCR CpMMU, 0, R3, C(CpTTB), C(0x0)
MOVW 156(R0), R3
MCR CpMMU, 0, R3, C(CpFSR), C(0x0)
MOVW 160(R0), R3
MCR CpMMU, 0, R3, C(CpFAR), C(0x0)
MOVW 164(R0), R3
MCR CpMMU, 0, R3, C(CpPID), C(0x0)
MOVW 152(R0), R3
MCR CpMMU, 0, R3, C(CpControl), C(0x0) /* Enable cache */
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
/* flush i&d caches */
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
/* flush tlb */
MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7), 0
/* drain prefetch */
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
/* usr */
BIC $(PsrMask), R2, R3
ORR $(0xdf), R3
MOVW 168(R0), R11
MOVW 172(R0), R12
MOVW 176(R0), R13
MOVW 180(R0), R14
MOVW R11, SPSR
/* irq */
BIC $(PsrMask), R2, R3
ORR $(0xd2), R3
MOVW R3, CPSR
MOVW 64(R0), R11
MOVW 68(R0), R12
MOVW 72(R0), R13
MOVW 76(R0), R14
MOVW R11, SPSR
/* und */
BIC $(PsrMask), R2, R3
ORR $(0xdb), R3
MOVW R3, CPSR
MOVW 80(R0), R11
MOVW 84(R0), R12
MOVW 88(R0), R13
MOVW 92(R0), R14
MOVW R11, SPSR
/* abt */
BIC $(PsrMask), R2, R3
ORR $(0xd7), R3
MOVW R3, CPSR
MOVW 96(R0), R11
MOVW 100(R0), R12
MOVW 104(R0), R13
MOVW 108(R0), R14
MOVW R11, SPSR
/* fiq */
BIC $(PsrMask), R2, R3
ORR $(0xd1), R3
MOVW R3, CPSR
MOVW 112(R0), R7
MOVW 116(R0), R8
MOVW 120(R0), R9
MOVW 124(R0), R10
MOVW 128(R0), R11
MOVW 132(R0), R12
MOVW 136(R0), R13
MOVW 140(R0), R14
MOVW R7, SPSR
/* svc */
MOVW 56(R0), R1
MOVW 60(R0), R2
MOVW R1, SPSR
MOVW R2, CPSR
MOVW 0(R0), R1
MOVW 4(R0), R2
MOVW 8(R0), R3
MOVW 12(R0),R4
MOVW 16(R0),R5
MOVW 20(R0),R6
MOVW 24(R0),R7
MOVW 28(R0),R8
MOVW 32(R0),R9
MOVW 36(R0),R10
MOVW 40(R0),R11
MOVW 44(R0),R12
MOVW 48(R0),R13
MOVW 52(R0),R14
RET
loop:
B loop
TEXT power_down(SB), $-4
TEXT sa1100_power_off<>+0(SB),$8
MOVW resetregs+0(SB),R7
MOVW gpioregs+0(SB),R6
MOVW memconfregs+0(SB),R5
MOVW powerregs+0(SB),R3
/* wakeup on power | rtc */
MOVW $(PWR_rtc|PWR_gpio0),R2
MOVW R2,0xc(R3)
/* clear reset status */
MOVW $(RCSR_all), R2
MOVW R2, 0x4(R7)
/* float */
MOVW $(PCFR_opde|PCFR_fp|PCFR_fs), R2
MOVW R2,0x10(R3)
/* sleep state */
MOVW $0,R2
MOVW R2,0x18(R3)
/* set resume address (pspr)*/
MOVW $resumeaddr+0(SB),R1
MOVW 0x0(R1), R2
MOVW R2,0x8(R3)
BL cacheflush(SB)
/* disable clock switching */
MCR CpPWR, 0, R1, C(CpTest), C(0x2), 2
/* adjust mem timing */
MOVW memconfregs+0(SB),R5
MOVW 0x1c(R5), R2
ORR $(MDREFR_k1db2), R2
MOVW R2, 0x1c(R5)
/* set PLL to lower speed w/ delay (ppcr = 0)*/
MOVW powerregs+0(SB),R3
MOVW $(120*206),R0
l11: SUB $1,R0
BGT l11
MOVW $0, R2
MOVW R2, 0x14(R3)
MOVW $(120*206),R0
l12: SUB $1,R0
BGT l12
/* setup registers for suspend procedure:
* 1. clear RT in mscx (R1, R7, R8)
* 2. clear DRI in mdrefr (R4)
* 3. set slfrsh in mdrefr (R6)
* 4. clear DE in mdcnfg (R9)
* 5. clear dram refresh (R10)
* 6. force sleep (R2)
*/
/* 1 */
MOVW 0x10(R5), R2
BIC $(MSC_rt), R2
MOVW R2, R1
MOVW 0x14(R5), R2
BIC $(MSC_rt), R2
MOVW R2, R7
MOVW 0x2c(R5), R2
BIC $(MSC_rt), R2
MOVW R2, R8
/* 2 */
MOVW 0x1c(R5), R2
BIC $(0xff00), R2
BIC $(0x00f0), R2
MOVW R2, R4
/* 3 */
ORR $(MDREFR_slfrsh), R2, R6
/* 4 */
MOVW 0x0(R5), R9
BIC $(MDCFNG_de), R9, R9
/* 5 */
MOVW R4, R2
BIC $(MDREFR_slfrsh), R2, R2
BIC $(MDREFR_e1pin), R2, R2
MOVW R2, R10
/* 6 */
MOVW $1,R2
TEXT power_magic(SB), $-4
/* power_code gets copied into the area of no-ops below,
* at a cache-line boundary (8 instructions)
*/
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
MOVW R0, R0
TEXT power_code(SB), $-4
/* Follow the procedure; this code gets copied to the no-op
* area preceding this code
*/
/* 1 */
MOVW R1, 0x10(R5)
MOVW R7, 0x14(R5)
MOVW R8, 0x2c(R5)
/* 2 */
MOVW R4, 0x1c(R5)
/* 3 */
MOVW R6, 0x1c(R5)
/* 4 */
MOVW R9, 0x0(R5)
/* 5 */
MOVW R10, 0x1c(R5)
/* 6 */
MOVW R2, 0x0(R3)
slloop:
B slloop /* loop waiting for sleep */
/* The first MCR instruction of this function needs to be on a cache-line
* boundary; to make this happen, it will be copied to the first cache-line
* boundary 8 words from the start of doze.
*
* Doze puts the machine into idle mode. Any interrupt will get it out
* at the next instruction (the RET, to be precise).
*/
TEXT doze(SB), $-4
MOVW $UCDRAMZERO, R1
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
MOVW R0,R0
RET
TEXT doze_code(SB), $-4
MCR CpPWR, 0, R0, C(CpTest), C(0x2), 2
MOVW (R1), R0
MCR CpPWR, 0, R0, C(CpTest), C(0x8), 2

View file

@ -1,536 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "init.h"
#include "pool.h"
Mach *m;
Proc *up;
Conf conf;
int noprint;
void
main(void)
{
mmuinvalidate();
/* zero out bss */
memset(edata, 0, end-edata);
/* point to Mach structure */
m = (Mach*)MACHADDR;
memset(m, 0, sizeof(Mach));
m->ticks = 1;
active.machs[0] = 1;
rs232power(1);
quotefmtinstall();
iprint("\nPlan 9 bitsy kernel\n");
confinit();
xinit();
mmuinit();
machinit();
trapinit();
sa1110_uartsetup(1);
dmainit();
screeninit();
printinit(); /* from here on, print works, before this we need iprint */
clockinit();
procinit0();
initseg();
links();
chandevreset();
pageinit();
swapinit();
userinit();
powerinit();
schedinit();
}
/* need to do better */
void
reboot(void*, void*, ulong)
{
}
/*
* exit kernel either on a panic or user request
*/
void
exit(int)
{
void (*f)(void);
cpushutdown();
splhi();
iprint("it's a wonderful day to die\n");
cacheflush();
mmuinvalidate();
mmudisable();
f = nil;
(*f)();
}
static uchar *sp;
/*
* starting place for first process
*/
void
init0(void)
{
up->nerrlab = 0;
spllo();
/*
* These are o.k. because rootinit is null.
* Then early kproc's will have a root and dot.
*/
up->slash = namec("#/", Atodir, 0, 0);
pathclose(up->slash->path);
up->slash->path = newpath("/");
up->dot = cclone(up->slash);
chandevinit();
if(!waserror()){
ksetenv("terminal", "bitsy", 0);
ksetenv("cputype", "arm", 0);
if(cpuserver)
ksetenv("service", "cpu", 0);
else
ksetenv("service", "terminal", 0);
poperror();
}
kproc("alarm", alarmkproc, 0);
kproc("power", powerkproc, 0);
touser(sp);
}
/*
* pass boot arguments to /boot
*/
static uchar *
pusharg(char *p)
{
int n;
n = strlen(p)+1;
sp -= n;
memmove(sp, p, n);
return sp;
}
static void
bootargs(ulong base)
{
int i, ac;
uchar *av[32];
uchar *bootpath;
uchar **lsp;
/*
* the sizeof(Sargs) is to make the validaddr check in
* trap.c's syscall() work even when we have less than the
* max number of args.
*/
sp = (uchar*)base + BY2PG - sizeof(Sargs);
bootpath = pusharg("/boot/boot");
ac = 0;
av[ac++] = pusharg("boot");
/* 4 byte word align stack */
sp = (uchar*)((ulong)sp & ~3);
/* build argc, argv on stack */
sp -= (ac+1)*sizeof(sp);
lsp = (uchar**)sp;
for(i = 0; i < ac; i++)
*lsp++ = av[i] + ((USTKTOP - BY2PG) - base);
*lsp = 0;
/* push argv onto stack */
sp -= BY2WD;
lsp = (uchar**)sp;
*lsp = sp + BY2WD + ((USTKTOP - BY2PG) - base);
/* push pointer to "/boot" */
sp -= BY2WD;
lsp = (uchar**)sp;
*lsp = bootpath + ((USTKTOP - BY2PG) - base);
/* leave space for where the initcode's caller's return PC would normally reside */
sp -= BY2WD;
/* relocate stack to user's virtual addresses */
sp += (USTKTOP - BY2PG) - base;
}
/*
* create the first process
*/
void
userinit(void)
{
Proc *p;
Segment *s;
KMap *k;
Page *pg;
/* no processes yet */
up = nil;
p = newproc();
p->pgrp = newpgrp();
p->egrp = smalloc(sizeof(Egrp));
p->egrp->ref = 1;
p->fgrp = dupfgrp(nil);
p->rgrp = newrgrp();
p->procmode = 0640;
kstrdup(&eve, "");
kstrdup(&p->text, "*init*");
kstrdup(&p->user, eve);
/*
* Kernel Stack
*/
p->sched.pc = (ulong)init0;
p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
/*
* User Stack
*/
s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
p->seg[SSEG] = s;
pg = newpage(1, 0, USTKTOP-BY2PG);
segpage(s, pg);
k = kmap(pg);
bootargs(VA(k));
kunmap(k);
/*
* Text
*/
s = newseg(SG_TEXT, UTZERO, 1);
p->seg[TSEG] = s;
pg = newpage(1, 0, UTZERO);
pg->txtflush = ~0;
segpage(s, pg);
k = kmap(s->map[0]->pages[0]);
memmove((ulong*)VA(k), initcode, sizeof initcode);
kunmap(k);
ready(p);
}
/*
* set mach dependent process state for a new process
*/
void
procsetup(Proc *p)
{
p->fpstate = FPinit;
}
void
procfork(Proc*)
{
}
/*
* Save the mach dependent part of the process state.
*/
void
procsave(Proc *p)
{
USED(p);
}
/* place holder */
/*
* dummy since rdb is not included
*/
void
rdb(void)
{
}
/*
* probe the last location in a meg of memory, make sure it's not
* reflected into something else we've already found.
*/
int
probemem(ulong addr)
{
int i;
ulong *p;
ulong a;
addr += OneMeg - sizeof(ulong);
p = (ulong*)addr;
*p = addr;
for(i=0; i<nelem(conf.mem); i++){
for(a = conf.mem[i].base+OneMeg-sizeof(ulong); a < conf.mem[i].limit; a += OneMeg){
p = (ulong*)a;
*p = 0;
}
}
p = (ulong*)addr;
if(*p != addr)
return -1;
return 0;
}
/*
* we assume that the kernel is at the beginning of one of the
* contiguous chunks of memory.
*/
void
confinit(void)
{
int i, j;
ulong addr;
ulong ktop;
/* find first two contiguous sections of available memory */
addr = PHYSDRAM0;
for(i=0; i<nelem(conf.mem); i++){
conf.mem[i].base = addr;
conf.mem[i].limit = addr;
}
for(j=0; j<nelem(conf.mem); j++){
conf.mem[j].base = addr;
conf.mem[j].limit = addr;
for(i = 0; i < 512; i++){
if(probemem(addr) == 0)
break;
addr += OneMeg;
}
for(; i < 512; i++){
if(probemem(addr) < 0)
break;
addr += OneMeg;
conf.mem[j].limit = addr;
}
}
conf.npage = 0;
for(i=0; i<nelem(conf.mem); i++){
/* take kernel out of allocatable space */
ktop = PGROUND((ulong)end);
if(ktop >= conf.mem[i].base && ktop <= conf.mem[i].limit)
conf.mem[i].base = ktop;
/* zero memory */
memset((void*)conf.mem[i].base, 0, conf.mem[i].limit - conf.mem[i].base);
conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
conf.npage += conf.mem[i].npage;
}
if(conf.npage > 16*MB/BY2PG){
conf.upages = (conf.npage*60)/100;
imagmem->minarena = 4*1024*1024;
}else
conf.upages = (conf.npage*40)/100;
conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
/* only one processor */
conf.nmach = 1;
/* set up other configuration parameters */
conf.nproc = 100;
conf.nswap = conf.npage*3;
conf.nswppo = 4096;
conf.nimage = 200;
conf.monitor = 1;
conf.copymode = 0; /* copy on write */
}
GPIOregs *gpioregs;
ulong *egpioreg = (ulong*)EGPIOREGS;
PPCregs *ppcregs;
MemConfRegs *memconfregs;
PowerRegs *powerregs;
ResetRegs *resetregs;
/*
* configure the machine
*/
void
machinit(void)
{
/* set direction of SA1110 io pins and select alternate functions for some */
gpioregs = mapspecial(GPIOREGS, sizeof(GPIOregs));
gpioregs->direction =
GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
|GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
|GPIO_CLK_SET0_o|GPIO_CLK_SET1_o
|GPIO_L3_SDA_io|GPIO_L3_MODE_o|GPIO_L3_SCLK_o
|GPIO_COM_RTS_o;
gpioregs->rising = 0;
gpioregs->falling = 0;
gpioregs->altfunc |=
GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
|GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
|GPIO_SSP_CLK_i;
/* map in special H3650 io pins */
egpioreg = mapspecial(EGPIOREGS, sizeof(ulong));
/* map in peripheral pin controller (ssp will need it) */
ppcregs = mapspecial(PPCREGS, sizeof(PPCregs));
/* SA1110 power management */
powerregs = mapspecial(POWERREGS, sizeof(PowerRegs));
/* memory configuraton */
memconfregs = mapspecial(MEMCONFREGS, sizeof(MemConfRegs));
/* reset controller */
resetregs = mapspecial(RESETREGS, sizeof(ResetRegs));
}
/*
* manage egpio bits
*/
static ulong egpiosticky;
void
egpiobits(ulong bits, int on)
{
if(on)
egpiosticky |= bits;
else
egpiosticky &= ~bits;
*egpioreg = egpiosticky;
}
void
rs232power(int on)
{
egpiobits(EGPIO_rs232_power, on);
delay(50);
}
void
audioamppower(int on)
{
egpiobits(EGPIO_audio_power, on);
delay(50);
}
void
audioicpower(int on)
{
egpiobits(EGPIO_audio_ic_power, on);
delay(50);
}
void
irpower(int on)
{
egpiobits(EGPIO_ir_power, on);
delay(50);
}
void
lcdpower(int on)
{
egpiobits(EGPIO_lcd_3v|EGPIO_lcd_ic_power|EGPIO_lcd_5v|EGPIO_lcd_9v, on);
delay(50);
}
void
flashprogpower(int on)
{
egpiobits(EGPIO_prog_flash, on);
}
/* here on hardware reset */
void
resettrap(void)
{
}
/*
* for drivers that used to run on x86's
*/
void
outb(ulong a, uchar v)
{
*(uchar*)a = v;
}
void
outs(ulong a, ushort v)
{
*(ushort*)a = v;
}
void
outss(ulong a, void *p, int n)
{
ushort *sp = p;
while(n-- > 0)
*(ushort*)a = *sp++;
}
void
outl(ulong a, ulong v)
{
*(ulong*)a = v;
}
uchar
inb(ulong a)
{
return *(uchar*)a;
}
ushort
ins(ulong a)
{
return *(ushort*)a;
}
void
inss(ulong a, void *p, int n)
{
ushort *sp = p;
while(n-- > 0)
*sp++ = *(ushort*)a;
}
ulong
inl(ulong a)
{
return *(ulong*)a;
}
char*
getconf(char*)
{
return nil;
}
int
cmpswap(long *addr, long old, long new)
{
int r, s;
s = splhi();
if(r = (*addr==old))
*addr = new;
splx(s);
return r;
}

View file

@ -1,10 +0,0 @@
defn acidmap()
{
local dfoffset;
dfoffset = map()[1][3];
map({"text", _start, etext, 0x20});
map({"data", etext+1, edata, dfoffset});
print("Set map for plan 9 kernel image\n");
print("btext ", _start, " etext ", etext, "\n");
}

View file

@ -1,234 +0,0 @@
/*
* Memory and machine-specific definitions. Used in C and assembler.
*/
/*
* Sizes
*/
#define BI2BY 8 /* bits per byte */
#define BI2WD 32 /* bits per word */
#define BY2WD 4 /* bytes per word */
#define BY2V 8 /* bytes per double word */
#define BY2PG 4096 /* bytes per page */
#define WD2PG (BY2PG/BY2WD) /* words per page */
#define PGSHIFT 12 /* log(BY2PG) */
#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
#define PGROUND(s) ROUND(s, BY2PG)
#define BLOCKALIGN 8
#define MAXMACH 1 /* max # cpus system can run */
/*
* Time
*/
#define HZ (20) /* clock frequency */
#define MS2HZ (1000/HZ) /* millisec per clock tick */
#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
/*
* Virtual addresses:
*
* We direct map all discovered DRAM and the area twixt 0xe0000000 and
* 0xe8000000 used to provide zeros for cache flushing.
*
* Flash is mapped to 0xb0000000 and special registers are mapped
* on demand to areas starting at 0xa0000000.
*
* The direct mapping is convenient but not necessary. It means
* that we don't have to turn on the MMU till well into the
* kernel. This can be changed by providing a mapping in l.s
* before calling main.
*/
#define UZERO 0 /* base of user address space */
#define UTZERO (UZERO+BY2PG) /* first address in user text */
#define KZERO 0xC0000000 /* base of kernel address space */
#define KTZERO 0xC0008000 /* first address in kernel text */
#define EMEMZERO 0x90000000 /* 256 meg for add on memory */
#define EMEMTOP 0xA0000000 /* ... */
#define REGZERO 0xA0000000 /* 128 meg for mapspecial regs */
#define REGTOP 0xA8000000 /* ... */
#define FLASHZERO 0xB0000000 /* 128 meg for flash */
#define FLASHTOP 0xB8000000 /* ... */
#define DRAMZERO 0xC0000000 /* 128 meg for dram */
#define DRAMTOP 0xC8000000 /* ... */
#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */
#define UCDRAMTOP 0xD0000000 /* ... */
#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
#define NULLTOP 0xE8000000 /* ... */
#define USTKTOP 0x2000000 /* byte just beyond user stack */
#define USTKSIZE (8*1024*1024) /* size of user stack */
#define MACHADDR (KZERO+0x00001000)
#define EVECTORS 0xFFFF0000 /* virt base of exception vectors */
#define KSTACK (16*1024) /* Size of kernel stack */
/*
* Offsets into flash
*/
#define Flash_bootldr (FLASHZERO+0x0) /* boot loader */
#define Flash_kernel (FLASHZERO+0x10000) /* boot kernel */
#define Flash_tar (FLASHZERO+0x200000) /* fs.sac (tar file) */
/*
* virtual MMU
*/
#define PTEMAPMEM (1024*1024)
#define PTEPERTAB (PTEMAPMEM/BY2PG)
#define SEGMAPSIZE 1984
#define SSEGMAPSIZE 16
#define PPN(x) ((x)&~(BY2PG-1))
/*
* SA1110 definitions
*/
/*
* memory physical addresses
*/
#define PHYSFLASH0 0x00000000
#define PHYSDRAM0 0xC0000000
#define PHYSNULL0 0xE0000000
/*
* peripheral control module physical addresses
*/
#define USBREGS 0x80000000 /* serial port 0 - USB */
#define UART1REGS 0x80010000 /* serial port 1 - UART */
#define GPCLKREGS 0x80020060 /* serial port 1 - general purpose clock */
#define UART2REGS 0x80030000 /* serial port 2 - low speed IR */
#define HSSPREGS 0x80040060 /* serial port 2 - high speed IR */
#define UART3REGS 0x80050000 /* serial port 3 - RS232 UART */
#define MCPREGS 0x80060000 /* serial port 4 - multimedia comm port */
#define SSPREGS 0x80070060 /* serial port 4 - synchronous serial port */
#define OSTIMERREGS 0x90000000 /* operating system timer registers */
#define POWERREGS 0x90020000 /* power management */
#define RESETREGS 0x90030000 /* reset controller */
#define GPIOREGS 0x90040000 /* 28 general purpose IO pins */
#define INTRREGS 0x90050000 /* interrupt registers */
#define PPCREGS 0x90060000 /* peripheral pin controller */
#define MEMCONFREGS 0xA0000000 /* memory configuration */
#define LCDREGS 0xB0100000 /* display */
/*
* PCMCIA addresses
*/
#define PHYSPCM0REGS 0x20000000
#define PYHSPCM0ATTR 0x28000000
#define PYHSPCM0MEM 0x2C000000
#define PHYSPCM1REGS 0x30000000
#define PYHSPCM1ATTR 0x38000000
#define PYHSPCM1MEM 0x3C000000
/*
* Program Status Registers
*/
#define PsrMusr 0x00000010 /* mode */
#define PsrMfiq 0x00000011
#define PsrMirq 0x00000012
#define PsrMsvc 0x00000013
#define PsrMabt 0x00000017
#define PsrMund 0x0000001B
#define PsrMask 0x0000001F
#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
#define PsrDirq 0x00000080 /* disable IRQ interrupts */
#define PsrV 0x10000000 /* overflow */
#define PsrC 0x20000000 /* carry/borrow/extend */
#define PsrZ 0x40000000 /* zero */
#define PsrN 0x80000000 /* negative/less than */
/*
* Coprocessors
*/
#define CpMMU 15
#define CpPWR 15
/*
* Internal MMU coprocessor registers
*/
#define CpCPUID 0 /* R: */
#define CpControl 1 /* RW: */
#define CpTTB 2 /* RW: translation table base */
#define CpDAC 3 /* RW: domain access control */
#define CpFSR 5 /* RW: fault status */
#define CpFAR 6 /* RW: fault address */
#define CpCacheFlush 7 /* W: cache flushing, wb draining*/
#define CpTLBFlush 8 /* W: TLB flushing */
#define CpRBFlush 9 /* W: Read Buffer ops */
#define CpPID 13 /* RW: PID for virtual mapping */
#define CpBpt 14 /* W: Breakpoint register */
#define CpTest 15 /* W: Test, Clock and Idle Control */
/*
* CpControl
*/
#define CpCmmuena 0x00000001 /* M: MMU enable */
#define CpCalign 0x00000002 /* A: alignment fault enable */
#define CpCdcache 0x00000004 /* C: data cache on */
#define CpCwb 0x00000008 /* W: write buffer turned on */
#define CpCi32 0x00000010 /* P: 32-bit program space */
#define CpCd32 0x00000020 /* D: 32-bit data space */
#define CpCbe 0x00000080 /* B: big-endian operation */
#define CpCsystem 0x00000100 /* S: system permission */
#define CpCrom 0x00000200 /* R: ROM permission */
#define CpCicache 0x00001000 /* I: instruction cache on */
#define CpCvivec 0x00002000 /* X: virtual interrupt vector adjust */
/*
* fault codes
*/
#define FCterm 0x2 /* terminal */
#define FCvec 0x0 /* vector */
#define FCalignf 0x1 /* unaligned full word data access */
#define FCalignh 0x3 /* unaligned half word data access */
#define FCl1abort 0xc /* level 1 external abort on translation */
#define FCl2abort 0xe /* level 2 external abort on translation */
#define FCtransSec 0x5 /* section translation */
#define FCtransPage 0x7 /* page translation */
#define FCdomainSec 0x9 /* section domain */
#define FCdomainPage 0x11 /* page domain */
#define FCpermSec 0x9 /* section permissions */
#define FCpermPage 0x11 /* page permissions */
#define FCabortLFSec 0x4 /* external abort on linefetch for section */
#define FCabortLFPage 0x6 /* external abort on linefetch for page */
#define FCabortNLFSec 0x8 /* external abort on non-linefetch for section */
#define FCabortNLFPage 0xa /* external abort on non-linefetch for page */
/*
* PTE bits used by fault.h. mmu.c translates them to real values.
*/
#define PTEVALID (1<<0)
#define PTERONLY 0 /* this is implied by the absence of PTEWRITE */
#define PTEWRITE (1<<1)
#define PTEUNCACHED (1<<2)
#define PTEKERNEL (1<<3) /* no user access */
/*
* H3650 specific definitions
*/
#define EGPIOREGS 0x49000000 /* Additional GPIO register */
/* Power management */
#define PWR_rtc 0x80000000 /* resume on RTC */
#define PWR_gpio0 0x00000001 /* resume on power button */
#define RCSR_all 0x0000000f
#define PCFR_opde 0x00000001 /* oscillator power-down enable */
#define PCFR_suspend 0x00000001
#define PCFR_fp 0x00000002 /* float pcmcia */
#define PCFR_fs 0x00000004 /* float static memory */
#define PCFR_fo 0x00000008
#define MDREFR_k1db2 (1 << 22)
#define MDREFR_slfrsh 0x80000000 /* self refresh */
#define MDREFR_e1pin (1 << 20)
#define MSC_rt 0x00030003
#define MDCNFG_de0 0x00000001 /* dram enable */
#define MDCNFG_de1 0x00000002
#define MDCNFG_de2 0x00000004
#define MDCNFG_de3 0x00000008
#define MDCFNG_de 0x0000000f
#define PMCR_sf 1

View file

@ -1,139 +0,0 @@
CONF=bitsy
CONFLIST=bitsy
objtype=arm
</$objtype/mkfile
p=9
DEVS=`{rc ../port/mkdevlist $CONF}
PORT=\
alarm.$O\
alloc.$O\
allocb.$O\
auth.$O\
cache.$O\
chan.$O\
dev.$O\
edf.$O\
fault.$O\
mul64fract.$O\
rebootcmd.$O\
page.$O\
parse.$O\
pgrp.$O\
portclock.$O\
print.$O\
proc.$O\
qio.$O\
qlock.$O\
segment.$O\
swap.$O\
sysfile.$O\
sysproc.$O\
taslock.$O\
tod.$O\
xalloc.$O\
random.$O\
OBJ=\
l.$O\
clock.$O\
defont.$O\
fpi.$O\
fpiarm.$O\
fpimem.$O\
main.$O\
mmu.$O\
power.$O\
sa1110dma.$O\
screen.$O\
trap.$O\
$CONF.root.$O\
$CONF.rootc.$O\
$DEVS\
$PORT\
LIB=\
/$objtype/lib/libmemlayer.a\
/$objtype/lib/libmemdraw.a\
/$objtype/lib/libdraw.a\
/$objtype/lib/libip.a\
/$objtype/lib/libc.a\
/$objtype/lib/libsec.a\
/$objtype/lib/libip.a\
size:VQ: $p$CONF
ls -l $p$CONF|sed 's/^[^ ]+ [^ ]+ [^ ]+ [^ ]+ [^ ]+ ([^ ]+).*/load ram 0xc0008000 \1/'
echo load kernel
echo !xms /sys/src/9/bitsy/^$p$CONF
echo jump 0xc0008010
acid:VQ:
echo acid -lmap s9bitsy
$p$CONF: $OBJ $CONF.c $LIB /arm/inflate
$CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
$LD -o $target -H5 -R4 -T0xC0008010 -l $OBJ $CONF.$O $LIB
$LD -o s$target -R4 -T0xC0008010 -l $OBJ $CONF.$O $LIB
gzip $target
cat /arm/inflate $target.gz > $target
echo the boot loader misses the last 12 bytes >> $target
rm $target.gz
install:V: $p$CONF paqdisk
if(test -d /n/once/arm){
cp $p$CONF /n/once/arm/$p$CONF
cp s$p$CONF /n/once/arm/s$p$CONF
cp paqdisk /n/once/arm/paqdisk
}
if not
status=''
# 9fs lookout && cp $p$CONF /n/lookout/$objtype/$p$CONF
installkern:V: $p$CONF
cp $p$CONF /$objtype/$p$CONF
cp s$p$CONF /$objtype/s$p$CONF
<../boot/bootmkfile
<../port/portmkfile
<|../port/mkbootrules $CONF
init.h:D: ../port/initcode.c init9.s
$CC ../port/initcode.c
$AS init9.s
$LD -l -R1 -s -o init.out init9.$O initcode.$O /arm/lib/libc.a
{echo 'uchar initcode[]={'
xd -1x <init.out |
sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
echo '};'} > init.h
clock.$O: /$objtype/include/ureg.h
devether.$O: /$objtype/include/ureg.h ../port/netif.h
devpcmcia.$O: /$objtype/include/ureg.h
fpi.$O: fpi.h
fpiarm.$O: /$objtype/include/ureg.h fpi.h
fpimem.$O: fpi.h
main.$O: /$objtype/include/ureg.h errstr.h init.h
mmu.$O: /$objtype/include/ureg.h
power.$O: /$objtype/include/ureg.h
scu.$O: /$objtype/include/ureg.h
sa1110dma.$O: /$objtype/include/ureg.h
screen.$O: gamma.h
sdata.$O: /$objtype/include/ureg.h
trap$O: /$objtype/include/ureg.h
wavelan.$O: /$objtype/include/ureg.h wavelan.c wavelan.h ../pc/wavelan.h
paqdisk:V:
rm -fr armpaq
mkdir armpaq
cd armpaq
disk/mkfs -d . /sys/lib/sysconfig/proto/armpaqproto
mkpaqfs -o ../paqdisk
cd ..
echo load ramdisk
echo !xms /sys/src/9/bitsy/paqdisk
bitsy.clean:
rm -rf armpaq $p$CONF s$p$CONF paqdisk $CONF.c boot$CONF.c ../boot/libboot.a5

View file

@ -1,532 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
/*
* to avoid mmu and cash flushing, we use the pid register in the MMU
* to map all user addresses. Although there are 64 possible pids, we
* can only use 31 because there are only 32 protection domains and we
* need one for the kernel. Pid i is thus associated with domain i.
* Domain 0 is used for the kernel.
*/
/* real protection bits */
enum
{
/* level 1 descriptor bits */
L1TypeMask= (3<<0),
L1Invalid= (0<<0),
L1PageTable= (1<<0),
L1Section= (2<<0),
L1Cached= (1<<3),
L1Buffered= (1<<2),
L1DomShift= 5,
L1Domain0= (0<<L1DomShift),
L1KernelRO= (0x0<<10),
L1KernelRW= (0x1<<10),
L1UserRO= (0x2<<10),
L1UserRW= (0x3<<10),
L1SectBaseMask= (0xFFF<<20),
L1PTBaseMask= (0x3FFFFF<<10),
/* level 2 descriptor bits */
L2TypeMask= (3<<0),
L2SmallPage= (2<<0),
L2LargePage= (1<<0),
L2Cached= (1<<3),
L2Buffered= (1<<2),
L2KernelRW= (0x55<<4),
L2UserRO= (0xAA<<4),
L2UserRW= (0xFF<<4),
L2PageBaseMask= (0xFFFFF<<12),
/* domain values */
Dnoaccess= 0,
Dclient= 1,
Dmanager= 3,
};
ulong *l1table;
static int mmuinited;
/*
* We map all of memory, flash, and the zeros area with sections.
* Special use space is mapped on the fly with regmap.
*/
void
mmuinit(void)
{
ulong a, o;
ulong *t;
/* get a prototype level 1 page */
l1table = xspanalloc(16*1024, 16*1024, 0);
memset(l1table, 0, 16*1024);
/* map low mem (I really don't know why I have to do this -- presotto) */
for(o = 0; o < 1*OneMeg; o += OneMeg)
l1table[(0+o)>>20] = L1Section | L1KernelRW| L1Domain0
| L1Cached | L1Buffered
| ((0+o)&L1SectBaseMask);
/* map DRAM */
for(o = 0; o < DRAMTOP-DRAMZERO; o += OneMeg)
l1table[(DRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0
| L1Cached | L1Buffered
| ((PHYSDRAM0+o)&L1SectBaseMask);
/* uncached DRAM */
for(o = 0; o < UCDRAMTOP-UCDRAMZERO; o += OneMeg)
l1table[(UCDRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0
| ((PHYSDRAM0+o)&L1SectBaseMask);
/* map zeros area */
for(o = 0; o < NULLTOP-NULLZERO; o += OneMeg)
l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
| L1Cached | L1Buffered
| ((PHYSNULL0+o)&L1SectBaseMask);
/* map flash */
for(o = 0; o < FLASHTOP-FLASHZERO; o += OneMeg)
l1table[(FLASHZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
| ((PHYSFLASH0+o)&L1SectBaseMask);
/* map peripheral control module regs */
mapspecial(0x80000000, OneMeg);
/* map system control module regs */
mapspecial(0x90000000, OneMeg);
/*
* double map start of ram to exception vectors
*/
a = EVECTORS;
t = xspanalloc(BY2PG, 1024, 0);
memset(t, 0, BY2PG);
l1table[a>>20] = L1PageTable | L1Domain0 | (((ulong)t) & L1PTBaseMask);
t[(a&0xfffff)>>PGSHIFT] = L2SmallPage | L2KernelRW | (PHYSDRAM0 & L2PageBaseMask);
mmurestart();
mmuinited = 1;
}
void
mmurestart(void) {
/* set up the domain register to cause all domains to obey pte access bits */
putdac(Dclient);
/* point to map */
putttb((ulong)l1table);
/* enable mmu */
wbflush();
mmuinvalidate();
mmuenable();
cacheflush();
}
/*
* map on request
*/
static void*
_map(ulong pa, int len, ulong zero, ulong top, ulong l1prop, ulong l2prop)
{
ulong *t;
ulong va, i, base, end, off, entry;
int large;
ulong* rv;
rv = nil;
large = len >= 128*1024;
if(large){
base = pa & ~(OneMeg-1);
end = (pa+len-1) & ~(OneMeg-1);
} else {
base = pa & ~(BY2PG-1);
end = (pa+len-1) & ~(BY2PG-1);
}
off = pa - base;
for(va = zero; va < top && base <= end; va += OneMeg){
switch(l1table[va>>20] & L1TypeMask){
default:
/* found unused entry on level 1 table */
if(large){
if(rv == nil)
rv = (ulong*)(va+off);
l1table[va>>20] = L1Section | l1prop | L1Domain0 |
(base & L1SectBaseMask);
base += OneMeg;
continue;
} else {
/* create an L2 page table and keep going */
t = xspanalloc(BY2PG, 1024, 0);
memset(t, 0, BY2PG);
l1table[va>>20] = L1PageTable | L1Domain0 |
(((ulong)t) & L1PTBaseMask);
}
break;
case L1Section:
/* if it's already mapped in a one meg area, don't remap */
entry = l1table[va>>20];
i = entry & L1SectBaseMask;
if(pa >= i && (pa+len) <= i + OneMeg)
if((entry & ~L1SectBaseMask) == (L1Section | l1prop | L1Domain0))
return (void*)(va + (pa & (OneMeg-1)));
continue;
case L1PageTable:
if(large)
continue;
break;
}
/* here if we're using page maps instead of sections */
t = (ulong*)(l1table[va>>20] & L1PTBaseMask);
for(i = 0; i < OneMeg && base <= end; i += BY2PG){
entry = t[i>>PGSHIFT];
/* found unused entry on level 2 table */
if((entry & L2TypeMask) != L2SmallPage){
if(rv == nil)
rv = (ulong*)(va+i+off);
t[i>>PGSHIFT] = L2SmallPage | l2prop |
(base & L2PageBaseMask);
base += BY2PG;
continue;
}
}
}
/* didn't fit */
if(base <= end)
return nil;
cacheflush();
return rv;
}
/* map in i/o registers */
void*
mapspecial(ulong pa, int len)
{
return _map(pa, len, REGZERO, REGTOP, L1KernelRW, L2KernelRW);
}
/* map add on memory */
void*
mapmem(ulong pa, int len, int cached)
{
ulong l1, l2;
if(cached){
l1 = L1KernelRW|L1Cached|L1Buffered;
l2 = L2KernelRW|L2Cached|L2Buffered;
} else {
l1 = L1KernelRW;
l2 = L2KernelRW;
}
return _map(pa, len, EMEMZERO, EMEMTOP, l1, l2);
}
/* map a virtual address to a physical one */
ulong
mmu_paddr(ulong va)
{
ulong entry;
ulong *t;
entry = l1table[va>>20];
switch(entry & L1TypeMask){
case L1Section:
return (entry & L1SectBaseMask) | (va & (OneMeg-1));
case L1PageTable:
t = (ulong*)(entry & L1PTBaseMask);
va &= OneMeg-1;
entry = t[va>>PGSHIFT];
switch(entry & L1TypeMask){
case L2SmallPage:
return (entry & L2PageBaseMask) | (va & (BY2PG-1));
}
}
return 0;
}
/* map a physical address to a virtual one */
ulong
findva(ulong pa, ulong zero, ulong top)
{
int i;
ulong entry, va;
ulong start, end;
ulong *t;
for(va = zero; va < top; va += OneMeg){
/* search the L1 entry */
entry = l1table[va>>20];
switch(entry & L1TypeMask){
default:
return 0; /* no holes */
case L1Section:
start = entry & L1SectBaseMask;
end = start + OneMeg;
if(pa >= start && pa < end)
return va | (pa & (OneMeg-1));
continue;
case L1PageTable:
break;
}
/* search the L2 entry */
t = (ulong*)(l1table[va>>20] & L1PTBaseMask);
for(i = 0; i < OneMeg; i += BY2PG){
entry = t[i>>PGSHIFT];
/* found unused entry on level 2 table */
if((entry & L2TypeMask) != L2SmallPage)
break;
start = entry & L2PageBaseMask;
end = start + BY2PG;
if(pa >= start && pa < end)
return va | (BY2PG*i) | (pa & (BY2PG-1));
}
}
return 0;
}
ulong
mmu_kaddr(ulong pa)
{
ulong va;
/* try the easy stuff first (the first case is true most of the time) */
if(pa >= PHYSDRAM0 && pa <= PHYSDRAM0+(DRAMTOP-DRAMZERO))
return DRAMZERO+(pa-PHYSDRAM0);
if(pa >= PHYSFLASH0 && pa <= PHYSFLASH0+(FLASHTOP-FLASHZERO))
return FLASHZERO+(pa-PHYSFLASH0);
if(pa >= PHYSNULL0 && pa <= PHYSNULL0+(NULLTOP-NULLZERO))
return NULLZERO+(pa-PHYSNULL0);
if(!mmuinited)
return 0; /* this shouldn't happen */
/* walk the map for the special regs and extended memory */
va = findva(pa, EMEMZERO, EMEMTOP);
if(va != 0)
return va;
return findva(pa, REGZERO, REGTOP);
}
/*
* Return the number of bytes that can be accessed via KADDR(pa).
* If pa is not a valid argument to KADDR, return 0.
*/
ulong
cankaddr(ulong pa)
{
/*
* Is this enough?
* We'll find out if anyone still has one
* of these...
*/
if(pa >= PHYSDRAM0 && pa <= PHYSDRAM0+(DRAMTOP-DRAMZERO))
return PHYSDRAM0+(DRAMTOP-DRAMZERO) - pa;
return 0;
}
/*
* table to map fault.c bits to physical bits
*/
static ulong mmubits[16] =
{
[PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2UserRO,
[PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2UserRW,
[PTEVALID|PTEUNCACHED] L2SmallPage|L2UserRO,
[PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2UserRW,
[PTEKERNEL|PTEVALID] L2SmallPage|L2Cached|L2Buffered|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEWRITE] L2SmallPage|L2Cached|L2Buffered|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEUNCACHED] L2SmallPage|L2KernelRW,
[PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE] L2SmallPage|L2KernelRW,
};
/*
* add an entry to the current map
*/
void
putmmu(uintptr va, uintptr pa, Page *pg)
{
Page *l2pg;
ulong *t, *l1p, *l2p;
int s;
s = splhi();
/* clear out the current entry */
mmuinvalidateaddr(va);
l2pg = up->l1page[va>>20];
if(l2pg == nil){
l2pg = up->mmufree;
if(l2pg != nil){
up->mmufree = l2pg->next;
} else {
splx(s);
l2pg = newpage(0, 0, 0);
splhi();
}
l2pg->va = VA(kmap(l2pg));
up->l1page[va>>20] = l2pg;
memset((uchar*)(l2pg->va), 0, BY2PG);
}
/* always point L1 entry to L2 page, can't hurt */
l1p = &l1table[va>>20];
*l1p = L1PageTable | L1Domain0 | (l2pg->pa & L1PTBaseMask);
up->l1table[va>>20] = *l1p;
t = (ulong*)l2pg->va;
/* set L2 entry */
l2p = &t[(va & (OneMeg-1))>>PGSHIFT];
*l2p = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)]
| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE));
/* write back dirty entries - we need this because the pio() in
* fault.c is writing via a different virt addr and won't clean
* its changes out of the dcache. Page coloring doesn't work
* on this mmu because the virtual cache is set associative
* rather than direct mapped.
*/
cachewb();
if(pg->txtflush){
icacheinvalidate();
pg->txtflush = 0;
}
splx(s);
}
/*
* free up all page tables for this proc
*/
void
mmuptefree(Proc *p)
{
Page *pg;
int i;
for(i = 0; i < Nmeg; i++){
pg = p->l1page[i];
if(pg == nil)
continue;
p->l1page[i] = nil;
pg->next = p->mmufree;
p->mmufree = pg;
}
memset(p->l1table, 0, sizeof(p->l1table));
}
/*
* this is called with palloc locked so the pagechainhead is kosher
*/
void
mmurelease(Proc* p)
{
Page *pg, *next;
/* write back dirty cache entries before changing map */
cacheflush();
mmuptefree(p);
for(pg = p->mmufree; pg != nil; pg = next){
next = pg->next;
if(--pg->ref)
panic("mmurelease: pg->ref %d\n", pg->ref);
pagechainhead(pg);
}
if(p->mmufree != nil)
pagechaindone();
p->mmufree = nil;
memset(l1table, 0, sizeof(p->l1table));
cachewbregion((ulong)l1table, sizeof(p->l1table));
}
void
mmuswitch(Proc *p)
{
if(m->mmupid == p->pid && p->newtlb == 0)
return;
m->mmupid = p->pid;
/* write back dirty cache entries and invalidate all cache entries */
cacheflush();
if(p->newtlb){
mmuptefree(p);
p->newtlb = 0;
}
/* move in new map */
memmove(l1table, p->l1table, sizeof(p->l1table));
/* make sure map is in memory */
cachewbregion((ulong)l1table, sizeof(p->l1table));
/* lose any possible stale tlb entries */
mmuinvalidate();
}
void
flushmmu(void)
{
int s;
s = splhi();
up->newtlb = 1;
mmuswitch(up);
splx(s);
}
void
peekmmu(ulong va)
{
ulong e, d;
e = l1table[va>>20];
switch(e & L1TypeMask){
default:
iprint("l1: %#p[%#lux] = %#lux invalid\n", l1table, va>>20, e);
break;
case L1PageTable:
iprint("l1: %#p[%#lux] = %#lux pt\n", l1table, va>>20, e);
va &= OneMeg-1;
va >>= PGSHIFT;
e &= L1PTBaseMask;
d = ((ulong*)e)[va];
iprint("l2: %#lux[%#lux] = %#lux\n", e, va, d);
break;
case L1Section:
iprint("l1: %#p[%#lux] = %#lux section\n", l1table, va>>20, e);
break;
}
}
void
checkmmu(uintptr, uintptr)
{
}
void
countpagerefs(ulong*, int)
{
}

View file

@ -1,63 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#define Image IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
enum {
Button1 = 0x1;
Button2 = 0x2;
Button3 = 0x4;
};
int buttons;
Point position;
static void
mousevent(void) {
static int curbuttons;
static Point curposition;
if (buttons == curbuttons && eqpt(position, curposition))
return;
/* generate a mouse event */
curbuttons = buttons;
curposition = position;
}
void
buttonevent(int event) {
switch (event) {
case 0x02:
/* Button 2 down */
buttons |= Button2;
mousevent();
break;
case 0x82:
/* Button 2 up */
buttons &= ~Button2;
mousevent();
break;
case 0x03:
/* Button 3 down */
buttons |= Button3;
mousevent();
break;
case 0x83:
/* Button 3 up */
buttons &= ~Button3;
mousevent();
break;
default:
/* other buttons */
}
}

View file

@ -1,175 +0,0 @@
#!/bin/rc
debug=0
#set service to terminal (necessary for factotum, handy for everything else)
service=terminal
echo -n terminal > /env/service
echo -n plan9 > /env/site
echo -n astro > /env/facedom
echo -n emelie > /env/fs
bind -a '#y' /dev
bind -a '#F' /dev
bind -a '#I' /net
bind -a '#D' /net
# parallelism for mk
NPROC=1
sysname=`{cat /dev/sysname}
if (~ $sysname ''){
sysname=bitsy
echo $sysname>/dev/sysname
}
prompt=($sysname^'# ' ' ')
# flavor
fileserver=emelie
cpu=olive
# user defined flash partitions
echo -n add fs 0x0800000 0x1000000 > /dev/flash/flashctl
# so we can see things
light 0
# set variables
if(~ $debug 1) echo ramfs
ramfs
if(~ $debug 1) echo pencal
params -f
if(! grep -s '^calibrate=' /tmp/tmpparams)
pencal >>/tmp/tmpparams
if not {
eval `{grep '^calibrate=' /tmp/tmpparams}
echo calibrate $calibrate > '#m/mousectl'
}
prompter /tmp/tmpparams
params
if(~ $debug 1) {
echo tmpparams:
cat /tmp/tmpparams
}
. /tmp/tmpparams
if(~ $debug 1) echo set user
# set userid
if(test -e /env/user){
echo -n $user > /dev/hostowner
}
if(~ $debug 1) echo start flashfs
# bind in read/write file system
if (aux/flashfs) {
if (~ $debug 1) echo flashfs started
mount /srv/brzr /n/tmp
bind -a /n /n/tmp/n
bind -a /sys/lib /n/tmp/sys/lib
bind -a /sys /n/tmp/sys
bind -a /arm/bin/auth /n/tmp/arm/bin/auth
bind -a /arm/bin/ndb /n/tmp/arm/bin/ndb
bind -a /arm/bin/ip /n/tmp/arm/bin/ip
bind -a /arm/bin/aux /n/tmp/arm/bin/aux
bind -a /arm/bin /n/tmp/arm/bin
bind -a /arm /n/tmp/arm
bind -a /lib/ndb /n/tmp/lib/ndb
bind -a /lib/font /n/tmp/lib/font
bind -a /lib /n/tmp/lib
bind -a / /n/tmp
bind /n/tmp /
unmount /n/tmp
} >[2] /dev/null
# start network
if(grep -s WaveLAN/IEEE /dev/pcm0ctl){
if (~ $debug 1) echo 'configure #l0 wavelan'
echo -n 'configure #l0 wavelan'>/dev/pcm0ctl
bind -a '#l0' /net
switch($wvkey1){
case ''
;
case *
echo -n 'key1 '^$wvkey1 >/net/ether0/clone
}
switch($wvkey2){
case ''
;
case *
echo -n 'key2 '^$wvkey2 >/net/ether0/clone
}
switch($wvkey3){
case ''
;
case *
echo -n 'key3 '^$wvkey3 >/net/ether0/clone
}
switch($wvtxkey){
case ''
;
case *
echo -n 'txkey '^$wvtxkey >/net/ether0/clone
}
switch($wvmode){
case ''
;
case *
echo -n 'mode '^$wvmode >/net/ether0/clone
}
switch($wvibss){
case ''
;
case *
echo -n 'ibss '^$wvibss >/net/ether0/clone
}
switch($wvessid){
case ''
;
case *
echo -n 'essid '^$wvessid >/net/ether0/clone
}
switch($wvcrypt){
case ''
;
case *
echo -n 'crypt '^$wvcrypt >/net/ether0/clone
}
if (~ $debug 1) echo ip/ipconfig ether /net/ether0 $ipaddr $ipmask
ip/ipconfig ether /net/ether0 $ipaddr $ipmask
if(test -e /env/auth)
echo ' auth='^$auth >>/net/ndb
if(test -e /env/dns)
echo ' dns='^$dns >>/net/ndb
if(test -e /env/dnsdomain)
echo ' dnsdomain='^$dnsdomain >>/net/ndb
if(test -e /env/authdom)
echo ' authdom='^$authdom >>/net/ndb
if (~ $debug 1) echo ndb/cs
ndb/cs
ndb/dns -r
}
auth/factotum -n -s factotum -a $auth
if(! test -e /env/font)
font=/lib/font/bit/lucidasans/unicode.6.font
if(! test -e /env/tabstop)
tabstop=2
if (test -d /usr/$user) {
home=/usr/$user
cd $home
if (test -r lib/profile) {
. lib/profile
exec /bin/rc
}
if (test -r lib/windows) {
if (~ $debug 1) echo 'exec rio -sk ''/bin/keyboard -l'' -i '$home'/lib/windows'
exec rio -sk '/bin/keyboard -l -w' -i $home/lib/windows
}
}
# bind in read/write file system
if (~ $debug 1) echo 'exec rio -sk ''/bin/keyboard -l'''
exec rio -sk '/bin/keyboard -l -w'

View file

@ -1,6 +0,0 @@
#
# files comprising the database
#
database=
file=/lib/ndb/local
file=/lib/ndb/common

View file

@ -1,41 +0,0 @@
#!/bin/rc
# $proxy is typically set to tailfan's address.
ipnet=`{grep 'ip=' /net/ndb | sed 's/^.*ip=([0-9]+\.[0-9]+\.[0-9]+\.).*$/\1/'}
if (~ $proxy $ipnet^*){
# Use a proxy
echo import $proxy /net /net
import $proxy /net /net
}
switch($fs){
case ''
echo you must set the environment variable fs
exit 0
}
if (! test -e /mnt/factotum) {
if (test -e /srv/factotum) {
mount -b /srv/factotum /mnt
}
if not {
auth/factotum -u
}
}
srv -m $fs $fs /n/fs
bind -b /n/fs/arm/bin /bin
bind -b /n/fs/rc/bin /bin
bind -a /n/fs/lib /lib
bind -b /n/fs/sys /sys
bind -a /n/fs/usr /usr
bind -c /n/fs/mail /mail
bind -c /n/fs/acme /acme
user=`{cat /dev/user}
home=/usr/$user
bind -a /n/fs/usr/$user /usr/$user
bind -cb /usr/$user/tmp /tmp
bind -b /usr/$user/bin/rc /bin
bind -b /usr/$user/bin/arm /bin
bind -a /n/fs/lib/font/bit/lucidasans /lib/font/bit/lucidasans
bind -a /n/fs/lib/font/bit/lucida /lib/font/bit/lucida
bind -a /n/fs/lib/font/bit/misc /lib/font/bit/misc
#service=cpu aux/listen -t /bin/service

View file

@ -1,53 +0,0 @@
# root
mount #s/boot /root
bind -a /root /
bind -c /root/mnt /mnt
# kernel devices
bind #c /dev
bind #d /fd
bind -c #e /env
bind #p /proc
bind -c #s /srv
bind -a #t /dev
bind -a #r /dev
bind -a #m /dev
bind -a #y /dev
bind -a #I /net
bind -a #A /dev
bind -a #F /dev
bind -a #¤ /dev
# servers
mount -a /srv/cs /net
mount -a /srv/dns /net
mount -a /srv/factotum /mnt
# read/write file system
mount /srv/brzr /n/brzr
mount /srv/brzr /n/tmp
bind -a /n /n/tmp/n
bind -a /sys/lib /n/tmp/sys/lib
bind -a /sys /n/tmp/sys
bind -a /arm/bin/auth /n/tmp/arm/bin/auth
bind -a /arm/bin/ndb /n/tmp/arm/bin/ndb
bind -a /arm/bin/ip /n/tmp/arm/bin/ip
bind -a /arm/bin/aux /n/tmp/arm/bin/aux
bind -a /arm/bin /n/tmp/arm/bin
bind -a /arm /n/tmp/arm
bind -a /lib/ndb /n/tmp/lib/ndb
bind -a /lib/font /n/tmp/lib/font
bind -a /lib /n/tmp/lib
bind -a / /n/tmp
bind /n/tmp /
unmount /n/tmp
# standard bin
bind /arm/bin /bin
bind -a /rc/bin /bin
bind -a /arm/bin/bitsy /bin
# user defines
bind -cb /usr/$user/tmp /tmp
bind -b /usr/$user/bin/rc /bin
bind -b /usr/$user/bin/arm /bin

View file

@ -1,9 +0,0 @@
#!/bin/rc
if(grep -s WaveLAN/IEEE /dev/pcm0ctl){
echo -n 'configure #l0 WaveLAN/IEEE'>/dev/pcm0ctl
bind -a '#l0' /net
echo -n 'key moon1'>/net/ether0/clone
ip/ipconfig ether /net/ether0
ndb/cs
ndb/dns -r
}

View file

@ -1,5 +0,0 @@
11 9
0x0000 0x00FF lsr.10
0x0100 0x01f0 ../lucida/EuroLatin.5.0
0x2000 0x20aa ../lucida/GenPunct.5.0
0x2200 0x22f1 ../lucida/MathOps1.5.0

View file

@ -1,358 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "pool.h"
/* Power management for the bitsy */
#define TODFREQ 1000000000LL
/* saved state during power down.
* it's only used up to 164/4.
* it's only used by routines in l.s
*/
ulong power_state[200/4];
ulong resumeaddr[1];
Rendez powerr;
ulong powerflag = 0; /* set to start power-off sequence */
extern void power_resume(void);
extern int setpowerlabel(void);
extern void _start(void);
extern Uart sa1110uart[];
GPIOregs savedgpioregs;
Intrregs savedintrregs;
#define R(p) ((Uartregs*)((p)->regs))
uchar *savedtext;
static void
checkflash(void)
{
ulong *p;
ulong s;
s = 0;
for (p = (ulong*)FLASHZERO; p < (ulong*)(FLASHZERO+8*1024*1024); p++)
s += *p;
iprint("flash checksum is 0x%lux\n", s);
}
static void
checkktext(void)
{
ulong *p;
ulong s;
s = 0;
for (p = (ulong*)_start; p < (ulong*)etext; p++){
if(*p == 0)
iprint("%#p->0\n", p);
if (((ulong)p & 0x1fff) == 0){
iprint("page 0x%lux checksum 0x%lux\n",
(ulong)(p-1)&~0x1fff, s);
s = 0;
}
s += *p;
}
iprint("page 0x%lux checksum 0x%lux\n", (ulong)(p-1)&~0x1fff, s);
}
static void
checkpagetab(void)
{
extern ulong l1table;
ulong *p;
ulong s;
s = 0;
for (p = (ulong*)l1table; p < (ulong*)(l1table+16*1024); p++)
s += *p;
iprint("page table checksum is 0x%lux\n", s);
}
static void
dumpitall(void)
{
extern ulong l1table;
iprint("intr: icip %lux iclr %lux iccr %lux icmr %lux\n",
intrregs->icip,
intrregs->iclr, intrregs->iccr, intrregs->icmr );
iprint("gpio: lvl %lux dir %lux, re %lux, fe %lux sts %lux alt %lux\n",
gpioregs->level,
gpioregs->direction, gpioregs->rising, gpioregs->falling,
gpioregs->edgestatus, gpioregs->altfunc);
iprint("uart1: %lux %lux %lux \nuart3: %lux %lux %lux\n",
R(&sa1110uart[0])->ctl[0], R(&sa1110uart[0])->status[0], R(&sa1110uart[0])->status[1],
R(&sa1110uart[1])->ctl[0], R(&sa1110uart[1])->status[0], R(&sa1110uart[1])->status[1]);
iprint("tmr: osmr %lux %lux %lux %lux oscr %lux ossr %lux oier %lux\n",
timerregs->osmr[0], timerregs->osmr[1],
timerregs->osmr[2], timerregs->osmr[3],
timerregs->oscr, timerregs->ossr, timerregs->oier);
iprint("dram: mdcnfg %lux mdrefr %lux cas %lux %lux %lux %lux %lux %lux\n",
memconfregs->mdcnfg, memconfregs->mdrefr,
memconfregs->mdcas00, memconfregs->mdcas01,memconfregs->mdcas02,
memconfregs->mdcas20, memconfregs->mdcas21,memconfregs->mdcas22);
iprint("dram: mdcnfg msc %lux %lux %lux mecr %lux\n",
memconfregs->msc0, memconfregs->msc1,memconfregs->msc2,
memconfregs->mecr);
iprint("mmu: CpControl %lux CpTTB %lux CpDAC %lux l1table 0x%lux\n",
getcontrol(), getttb(), getdac(), l1table);
iprint("powerregs: pmcr %lux pssr %lux pcfr %lux ppcr %lux pwer %lux pspr %lux pgsr %lux posr %lux\n",
powerregs->pmcr, powerregs->pssr, powerregs->pcfr, powerregs->ppcr,
powerregs->pwer, powerregs->pspr, powerregs->pgsr, powerregs->posr);
checkpagetab();
checkflash();
checkktext();
iprint("\n\n");
}
static void
intrcpy(Intrregs *to, Intrregs *from)
{
to->iclr = from->iclr;
to->iccr = from->iccr;
to->icmr = from->icmr; // interrupts enabled
}
static void
gpiosave(GPIOregs *to, GPIOregs *from)
{
to->level = from->level;
to->rising = from->rising; // gpio intrs enabled
to->falling= from->falling; // gpio intrs enabled
to->altfunc = from->altfunc;
to->direction = from->direction;
}
static void
gpiorestore(GPIOregs *to, GPIOregs *from)
{
to->direction = from->direction;
to->altfunc = from->altfunc;
to->set = from->level & 0x0fffffff;
to->clear = ~from->level & 0x0fffffff;
to->rising = from->rising; // gpio intrs enabled
to->falling= from->falling; // gpio intrs enabled
}
void (*restart)(void) = nil;
static int
bitno(ulong x)
{
int i;
for(i = 0; i < 8*sizeof(x); i++)
if((1<<i) & x)
break;
return i;
}
int
powerdown(void *)
{
return powerflag;
}
void
deepsleep(void) {
static int power_pl;
ulong xsp, xlink;
// ulong mecr;
ulong clkd;
vlong savedtod;
extern void power_resume(void);
power_pl = splhi();
xlink = getcallerpc(&xlink);
/* Power down */
pcmciapower(0);
irpower(0);
audiopower(0);
screenpower(0);
µcpower(0);
iprint("entering suspend mode, sp = %#p, pc = 0x%lux, psw = 0x%ux\n",
&xsp, xlink, power_pl);
// dumpitall();
delay(1000);
uartpower(0);
rs232power(0);
clockpower(0);
gpiosave(&savedgpioregs, gpioregs);
intrcpy(&savedintrregs, intrregs);
cacheflush();
delay(50);
if(setpowerlabel()){
/* return here with mmu back on */
trapresume();
gpiorestore(gpioregs, &savedgpioregs);
delay(50);
intrcpy(intrregs, &savedintrregs);
if(intrregs->icip & (1<<IRQgpio0)){
// don't want to sleep now. clear on/off irq.
gpioregs->edgestatus = (1<<IRQgpio0);
intrregs->icip = (1<<IRQgpio0);
}
clkd = clockpower(1);
gpclkregs->r0 = 1<<0;
todset(savedtod + clkd * TODFREQ, 0LL, 0);
resetsuspendtimer();
rs232power(1);
uartpower(1);
delay(100);
xlink = getcallerpc(&xlink);
iprint("\nresuming execution, sp = %#p, pc = 0x%lux, psw = 0x%ux\n",
&xsp, xlink, splhi());
// dumpitall();
delay(1000);
// irpower(1);
audiopower(1);
µcpower(1);
screenpower(1);
pcmciapower(1);
splx(power_pl);
return;
}
cacheflush();
delay(100);
savedtod = todget(nil);
power_down();
/* no return */
}
void
powerkproc(void*)
{
ulong xlink, xlink1;
while(waserror())
;
for(;;){
while(powerflag == 0)
sleep(&powerr, powerdown, 0);
xlink = getcallerpc(&xlink);
// iprint("call deepsleep, pc = 0x%lux, sp = 0x%lux\n", xlink, &xlink);
deepsleep();
xlink1 = getcallerpc(&xlink1);
delay(2000);
// iprint("deepsleep returned, pc = 0x%lux, sp = 0x%lux\n", xlink1, &xlink);
powerflag = 0;
}
}
void
onoffintr(Ureg* , void*)
{
int i;
/* Power down interrupt comes on power button release.
* Act only after button has been released a full 100 ms
*/
if (powerflag)
return;
for (i = 0; i < 100; i++) {
delay(1);
if ((gpioregs->level & GPIO_PWR_ON_i) == 0)
return; /* bounced */
}
powerflag = 1;
wakeup(&powerr);
}
static void
blanktimer(void)
{
drawactive(0);
}
static ulong suspendtime = 120 * HZ;
static int lastsuspend;
void
resetsuspendtimer(void)
{
suspendtime = 60 * HZ;
}
static void
suspendtimer(void)
{
#ifdef notdef
uvlong now;
if (suspendtime > 0)
suspendtime--;
if (suspendtime == 0){
now = seconds();
if (now < lastsuspend + 10){
resetsuspendtimer();
return;
}
lastsuspend = seconds();
deepsleep();
lastsuspend = seconds();
return;
}
#endif /* notdef */
}
void
powerinit(void)
{
extern ulong power_magic;
extern ulong power_code;
extern ulong doze_code;
ulong *p, *q, i;
p = (ulong*)(((ulong)&power_magic + 0x1f) & ~0x1f);
q = &power_code;
for (i = 0; i < 8; i++)
*p++ = *q++;
p = (ulong*)(((ulong)doze + 0x3f) & ~0x1f);
q = &doze_code;
for (i = 0; i < 3; i++)
*p++ = *q++;
*resumeaddr = (ulong) power_resume;
addclock0link(blanktimer, 1000/HZ);
addclock0link(suspendtimer, 1000/HZ);
intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, nil, "on/off");
}
void
idlehands(void)
{
char *msgb = "idlehands called with splhi\n";
char *msga = "doze returns with splhi\n";
if(!islo()){
uartputs(msga, strlen(msga));
spllo();
}
doze();
if(!islo()){
uartputs(msgb, strlen(msgb));
spllo();
}
}

View file

@ -1,227 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "sa1110dma.h"
static int debug = 0;
/*
* DMA helper routines
*/
enum {
NDMA = 6, /* Number of DMA channels */
DMAREGS = 0xb0000000, /* DMA registers, physical */
};
enum {
/* Device Address Register, DDAR */
RW = 0,
E = 1,
BS = 2,
DW = 3,
DS = 4, /* bits 4 - 7 */
DA = 8 /* bits 8 - 31 */
};
enum {
/* Device Control & Status Register, DCSR */
RUN = 0,
IE = 1,
ERROR = 2,
DONEA = 3,
STRTA = 4,
DONEB = 5,
STRTB = 6,
BIU = 7
};
typedef struct DMAchan {
int allocated;
Rendez r;
void (*intr)(void*, ulong);
void *param;
} DMAchan;
struct {
Lock;
DMAchan chan[6];
} dma;
struct dmaregs {
ulong ddar;
ulong dcsr_set;
ulong dcsr_clr;
ulong dcsr_rd;
ulong dstrtA;
ulong dxcntA;
ulong dstrtB;
ulong dxcntB;
} *dmaregs;
static void dmaintr(Ureg*, void *);
void
dmainit(void) {
int i;
/* map the lcd regs into the kernel's virtual space */
dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));
if (debug) print("dma: dmaalloc registers 0x%ux mapped at 0x%p\n",
DMAREGS, dmaregs);
for (i = 0; i < NDMA; i++) {
intrenable(IRQ, IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
}
}
void
dmareset(int i, int rd, int bigendian, int burstsize, int datumsize, int device, ulong port) {
ulong ddar;
ddar =
(rd?1:0)<<RW |
(bigendian?1:0)<<E |
((burstsize==8)?1:0)<<BS |
((datumsize==2)?1:0)<<DW |
device<<DS |
0x80000000 | ((ulong)port << 6);
dmaregs[i].ddar = ddar;
dmaregs[i].dcsr_clr = 0xff;
if (debug) print("dma: dmareset: 0x%lux\n", ddar);
}
int
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong port, void (*intr)(void*, ulong), void *param) {
int i;
lock(&dma);
for (i = 0; i < NDMA; i++) {
if (dma.chan[i].allocated)
continue;
dma.chan[i].allocated++;
unlock(&dma);
dmareset(i, rd, bigendian, burstsize, datumsize, device, port);
dma.chan[i].intr = intr;
dma.chan[i].param = param;
return i;
}
unlock(&dma);
return -1;
}
void
dmafree(int i) {
dmaregs[i].dcsr_clr = 0xff;
dmaregs[i].ddar = 0;
dma.chan[i].allocated = 0;
dma.chan[i].intr = nil;
}
void
dmastop(int i) {
dmaregs[i].dcsr_clr = 0xff;
}
ulong
dmastart(int chan, ulong addr, int count) {
ulong status, n;
static int last;
/* If this gets called from interrupt routines, make sure ilocks are used */
status = dmaregs[chan].dcsr_rd;
if (debug > 1)
iprint("dma: dmastart 0x%lux\n", status);
if ((status & (1<<STRTA|1<<STRTB|1<<RUN)) == (1<<STRTA|1<<STRTB|1<<RUN)) {
return 0;
}
cachewbregion(addr, count);
n = 0x100;
if ((status & (1<<BIU | 1<<STRTB)) == (1<<BIU | 1<<STRTB) ||
(status & (1<<BIU | 1<<STRTA)) == 0) {
if (status & 1<<STRTA)
iprint("writing busy dma entry 0x%lux\n", status);
if (status & 1<<STRTB)
n = (last == 1)?0x200:0x300;
last = 2;
dmaregs[chan].dstrtA = addr;
dmaregs[chan].dxcntA = count;
dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTA;
n |= 1<<DONEA;
} else {
if (status & 1<<STRTB)
iprint("writing busy dma entry 0x%lux\n", status);
if (status & 1<<STRTA)
n = (last == 2)?0x200:0x300;
last = 1;
dmaregs[chan].dstrtB = addr;
dmaregs[chan].dxcntB = count;
dmaregs[chan].dcsr_set = 1<<RUN | 1<<IE | 1<<STRTB;
n |= 1<<DONEB;
}
return n;
}
int
dmaidle(int chan) {
ulong status;
status = dmaregs[chan].dcsr_rd;
if (debug > 1) print("dmaidle: 0x%lux\n", status);
return (status & (1<<STRTA|1<<STRTB)) == 0;
}
static int
_dmaidle(void* chan) {
ulong status;
status = dmaregs[(int)chan].dcsr_rd;
return (status & (1<<STRTA|1<<STRTB)) == 0;
}
void
dmawait(int chan) {
while (!dmaidle(chan))
sleep(&dma.chan[chan].r, _dmaidle, (void*)chan);
}
/*
* interrupt routine
*/
static void
dmaintr(Ureg*, void *x)
{
int i;
struct dmaregs *regs = x;
ulong dcsr, donebit;
i = regs - dmaregs;
dcsr = regs->dcsr_rd;
if (debug > 1)
iprint("dma: interrupt channel %d, status 0x%lux\n", i, dcsr);
if (dcsr & 1<<ERROR)
iprint("error, channel %d, status 0x%lux\n", i, dcsr);
donebit = 1<<((dcsr&1<<BIU)?DONEA:DONEB);
if (dcsr & donebit) {
regs->dcsr_clr = 1<<DONEA|1<<DONEB;
if (dma.chan[i].intr) {
(*dma.chan[i].intr)(dma.chan[i].param, dcsr & (1<<DONEA|1<<DONEB));
}
wakeup(&dma.chan[i].r);
return;
}
if (dcsr & 1<<ERROR) {
regs->dcsr_clr = ERROR;
iprint("DMA error, channel %d, status 0x%lux\n", i, dcsr);
if (dma.chan[i].intr) {
(*dma.chan[i].intr)(dma.chan[i].param, 0);
}
wakeup(&dma.chan[i].r);
return;
}
iprint("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
}

View file

@ -1,19 +0,0 @@
enum {
Port4MCP = 0x80060008,
Port4SSP = 0x8007006c,
AudioDMA = 0xa,
SSPXmitDMA = 0xe,
SSPRecvDMA = 0xf,
};
void dmainit(void);
int dmaalloc(int, int, int, int, int, ulong, void (*)(void*, ulong), void*);
void dmareset(int, int, int, int, int, int, ulong);
void dmafree(int);
ulong dmastart(int, ulong, int);
void dmawait(int);
void dmastop(int);
int dmaidle(int);

View file

@ -1,492 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
#define Image IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
#include "gamma.h"
#define MINX 8
int landscape = 0; /* orientation of the screen, default is 0: portait */
enum {
Wid = 240,
Ht = 320,
Pal0 = 0x2000, /* 16-bit pixel data in active mode (12 in passive) */
hsw = 0x00,
elw = 0x0e,
blw = 0x0d,
vsw = 0x02,
efw = 0x01,
bfw = 0x0a,
pcd = 0x10,
};
struct sa1110fb {
/* Frame buffer for 16-bit active color */
short palette[16]; /* entry 0 set to Pal0, the rest to 0 */
ushort pixel[Wid*Ht]; /* Pixel data */
} *framebuf;
enum {
/* LCD Control Register 0, lcd->lccr0 */
LEN = 0, /* 1 bit */
CMS = 1, /* 1 bit */
SDS = 2, /* 1 bit */
LDM = 3, /* 1 bit */
BAM = 4, /* 1 bit */
ERM = 5, /* 1 bit */
PAS = 7, /* 1 bit */
BLE = 8, /* 1 bit */
DPD = 9, /* 1 bit */
PDD = 12, /* 8 bits */
};
enum {
/* LCD Control Register 1, lcd->lccr1 */
PPL = 0, /* 10 bits */
HSW = 10, /* 6 bits */
ELW = 16, /* 8 bits */
BLW = 24, /* 8 bits */
};
enum {
/* LCD Control Register 2, lcd->lccr2 */
LPP = 0, /* 10 bits */
VSW = 10, /* 6 bits */
EFW = 16, /* 8 bits */
BFW = 24, /* 8 bits */
};
enum {
/* LCD Control Register 3, lcd->lccr3 */
PCD = 0, /* 8 bits */
ACB = 8, /* 8 bits */
API = 16, /* 4 bits */
VSP = 20, /* 1 bit */
HSP = 21, /* 1 bit */
PCP = 22, /* 1 bit */
OEP = 23, /* 1 bit */
};
enum {
/* LCD Status Register, lcd->lcsr */
LDD = 0, /* 1 bit */
BAU = 1, /* 1 bit */
BER = 2, /* 1 bit */
ABC = 3, /* 1 bit */
IOL = 4, /* 1 bit */
IUL = 5, /* 1 bit */
OIU = 6, /* 1 bit */
IUU = 7, /* 1 bit */
OOL = 8, /* 1 bit */
OUL = 9, /* 1 bit */
OOU = 10, /* 1 bit */
OUU = 11, /* 1 bit */
};
struct sa1110regs {
ulong lccr0;
ulong lcsr;
ulong dummies[2];
short* dbar1;
ulong dcar1;
ulong dbar2;
ulong dcar2;
ulong lccr1;
ulong lccr2;
ulong lccr3;
} *lcd;
static Memdata xgdata;
static Memimage xgscreen =
{
{ 0, 0, Wid, Ht }, /* r */
{ 0, 0, Wid, Ht }, /* clipr */
16, /* depth */
3, /* nchan */
RGB16, /* chan */
nil, /* cmap */
&xgdata, /* data */
0, /* zero */
Wid/2, /* width */
0, /* layer */
0, /* flags */
};
struct{
Point pos;
int bwid;
}out;
Memimage *gscreen;
Memimage *conscol;
Memimage *back;
Memsubfont *memdefont;
Lock screenlock;
ushort *vscreen; /* virtual screen */
Rectangle window;
Point curpos;
int h, w;
static ulong rep(ulong, int);
static void screenwin(void);
static void screenputc(char *buf);
static void bitsyscreenputs(char *s, int n);
static void scroll(void);
static void
lcdinit(void)
{
/* the following line works because main memory is direct mapped */
gpioregs->direction |=
GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
|GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o;
gpioregs->altfunc |=
GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
|GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o;
framebuf->palette[0] = Pal0;
lcd->dbar1 = framebuf->palette;
lcd->lccr3 = pcd<<PCD | 0<<ACB | 0<<API | 1<<VSP | 1<<HSP | 0<<PCP | 0<<OEP;
lcd->lccr2 = (Wid-1)<<LPP | vsw<<VSW | efw<<EFW | bfw<<BFW;
lcd->lccr1 = (Ht-16)<<PPL | hsw<<HSW | elw<<ELW | blw<<BLW;
lcd->lccr0 = 1<<LEN | 0<<CMS | 0<<SDS | 1<<LDM | 1<<BAM | 1<<ERM | 1<<PAS | 0<<BLE | 0<<DPD | 0<<PDD;
}
void
flipscreen(int ls) {
if (ls == landscape)
return;
if (ls) {
gscreen->r = Rect(0, 0, Ht, Wid);
gscreen->clipr = gscreen->r;
gscreen->width = Ht/2;
xgdata.bdata = (uchar *)framebuf->pixel;
} else {
gscreen->r = Rect(0, 0, Wid, Ht);
gscreen->clipr = gscreen->r;
gscreen->width = Wid/2;
xgdata.bdata = (uchar *)vscreen;
}
landscape = ls;
}
void
lcdtweak(Cmdbuf *cmd)
{
if(cmd->nf < 4)
return;
if(*cmd->f[0] == 'h')
lcd->lccr1 = ((Ht-16)<<PPL)
| (strtol(cmd->f[1], 0, 0)<<HSW)
| (strtol(cmd->f[2], 0, 0)<<ELW)
| (strtol(cmd->f[3], 0, 0)<<BLW);
if(*cmd->f[0] == 'v')
lcd->lccr2 = ((Wid-1)<<LPP)
| (strtol(cmd->f[1], 0, 0)<<VSW)
| (strtol(cmd->f[2], 0, 0)<<EFW)
| (strtol(cmd->f[3], 0, 0)<<BFW);
}
void
screenpower(int on)
{
blankscreen(on == 0);
}
void
screeninit(void)
{
int i;
/* map the lcd regs into the kernel's virtual space */
lcd = (struct sa1110regs*)mapspecial(LCDREGS, sizeof(struct sa1110regs));;
framebuf = xspanalloc(sizeof *framebuf, 0x100, 0);
vscreen = xalloc(sizeof(ushort)*Wid*Ht);
lcdpower(1);
lcdinit();
gscreen = &xgscreen;
xgdata.ref = 1;
i = 0;
if (landscape) {
gscreen->r = Rect(0, 0, Ht, Wid);
gscreen->clipr = gscreen->r;
gscreen->width = Ht/2;
xgdata.bdata = (uchar *)framebuf->pixel;
while (i < Wid*Ht*1/3) framebuf->pixel[i++] = 0xf800; /* red */
while (i < Wid*Ht*2/3) framebuf->pixel[i++] = 0xffff; /* white */
while (i < Wid*Ht*3/3) framebuf->pixel[i++] = 0x001f; /* blue */
} else {
gscreen->r = Rect(0, 0, Wid, Ht);
gscreen->clipr = gscreen->r;
gscreen->width = Wid/2;
xgdata.bdata = (uchar *)vscreen;
while (i < Wid*Ht*1/3) vscreen[i++] = 0xf800; /* red */
while (i < Wid*Ht*2/3) vscreen[i++] = 0xffff; /* white */
while (i < Wid*Ht*3/3) vscreen[i++] = 0x001f; /* blue */
flushmemscreen(gscreen->r);
}
memimageinit();
memdefont = getmemdefont();
out.pos.x = MINX;
out.pos.y = 0;
out.bwid = memdefont->info[' '].width;
blanktime = 3; /* minutes */
screenwin();
// screenputs = bitsyscreenputs;
screenputs = nil;
}
void
flushmemscreen(Rectangle r)
{
int x, y;
ulong start, end;
if (landscape == 0) {
if (r.min.x < 0) r.min.x = 0;
if (r.max.x > Wid) r.max.x = Wid;
if (r.min.y < 0) r.min.y = 0;
if (r.max.y > Ht) r.max.y = Ht;
for (x = r.min.x; x < r.max.x; x++)
for (y = r.min.y; y < r.max.y; y++)
framebuf->pixel[(x+1)*Ht-1-y] = gamma[vscreen[y*Wid+x]];
start = (ulong)&framebuf->pixel[(r.min.x+1)*Ht-1-(r.max.y-1)];
end = (ulong)&framebuf->pixel[(r.max.x-1+1)*Ht-1-(r.min.y)];
} else {
start = (ulong)&framebuf->pixel[r.min.y*Ht + r.min.x];
end = (ulong)&framebuf->pixel[(r.max.y-1)*Ht + r.max.x - 1];
}
cachewbregion(start, end-start);
}
/*
* export screen to devdraw
*/
uchar*
attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
{
*r = gscreen->r;
*d = gscreen->depth;
*chan = gscreen->chan;
*width = gscreen->width;
*softscreen = (landscape == 0);
return (uchar*)gscreen->data->bdata;
}
void
getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
{
USED(p, pr, pg, pb);
}
int
setcolor(ulong p, ulong r, ulong g, ulong b)
{
USED(p,r,g,b);
return 0;
}
void
blankscreen(int blank)
{
int cnt;
if (blank) {
lcd->lccr0 &= ~(1<<LEN); /* disable the LCD */
cnt = 0;
while((lcd->lcsr & (1<<LDD)) == 0) {
delay(10);
if (++cnt == 100) {
iprint("LCD doesn't stop\n");
break;
}
}
lcdpower(0);
} else {
lcdpower(1);
lcdinit();
}
}
static void
bitsyscreenputs(char *s, int n)
{
int i;
Rune r;
char buf[4];
if(!islo()) {
/* don't deadlock trying to print in interrupt */
if(!canlock(&screenlock))
return;
}
else
lock(&screenlock);
while(n > 0){
i = chartorune(&r, s);
if(i == 0){
s++;
--n;
continue;
}
memmove(buf, s, i);
buf[i] = 0;
n -= i;
s += i;
screenputc(buf);
}
unlock(&screenlock);
}
static void
screenwin(void)
{
Point p, q;
char *greet;
Memimage *orange;
Rectangle r;
memsetchan(gscreen, RGB16);
back = memwhite;
conscol = memblack;
orange = allocmemimage(Rect(0,0,1,1), RGB16);
orange->flags |= Frepl;
orange->clipr = gscreen->r;
orange->data->bdata[0] = 0x40;
orange->data->bdata[1] = 0xfd;
w = memdefont->info[' '].width;
h = memdefont->height;
r = insetrect(gscreen->r, 4);
memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
window = insetrect(r, 4);
memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
memimagedraw(gscreen, Rect(window.min.x, window.min.y,
window.max.x, window.min.y+h+5+6), orange, ZP, nil, ZP, S);
freememimage(orange);
window = insetrect(window, 5);
greet = " Plan 9 Console ";
p = addpt(window.min, Pt(10, 0));
q = memsubfontwidth(memdefont, greet);
memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
flushmemscreen(r);
window.min.y += h+6;
curpos = window.min;
window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
}
static void
screenputc(char *buf)
{
Point p;
int w, pos;
Rectangle r;
static int *xp;
static int xbuf[256];
if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
xp = xbuf;
switch(buf[0]) {
case '\n':
if(curpos.y+h >= window.max.y)
scroll();
curpos.y += h;
screenputc("\r");
break;
case '\r':
xp = xbuf;
curpos.x = window.min.x;
break;
case '\t':
p = memsubfontwidth(memdefont, " ");
w = p.x;
if(curpos.x >= window.max.x-4*w)
screenputc("\n");
pos = (curpos.x-window.min.x)/w;
pos = 4-(pos%4);
*xp++ = curpos.x;
r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
flushmemscreen(r);
curpos.x += pos*w;
break;
case '\b':
if(xp <= xbuf)
break;
xp--;
r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
flushmemscreen(r);
curpos.x = *xp;
break;
case '\0':
break;
default:
p = memsubfontwidth(memdefont, buf);
w = p.x;
if(curpos.x >= window.max.x-w)
screenputc("\n");
*xp++ = curpos.x;
r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
flushmemscreen(r);
curpos.x += w;
}
}
static void
scroll(void)
{
int o;
Point p;
Rectangle r;
o = 8*h;
r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
p = Pt(window.min.x, window.min.y+o);
memimagedraw(gscreen, r, gscreen, p, nil, p, S);
flushmemscreen(r);
r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
flushmemscreen(r);
curpos.y -= o;
}

View file

@ -1,14 +0,0 @@
typedef struct Cursorinfo Cursorinfo;
typedef struct Cursor Cursor;
extern ulong blanktime;
struct Cursorinfo {
Lock;
};
extern void blankscreen(int);
extern void flushmemscreen(Rectangle);
extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*);
#define ishwimage(i) 0

View file

File diff suppressed because it is too large Load diff

View file

@ -1,81 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
typedef union Hblock Hblock;
#define TBLOCK 512
#define NAMSIZ 100
union Hblock
{
char dummy[TBLOCK];
struct header
{
char name[NAMSIZ];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char linkflag;
char linkname[NAMSIZ];
} dbuf;
};
static int getdir(Hblock *hb, Dir *sp);
static int checksum(Hblock *hb);
uchar*
tarlookup(uchar *addr, char *file, int *dlen)
{
Hblock *hp;
Dir dir;
hp = (Hblock*)addr;
while(getdir(hp, &dir) != 0) {
if(strcmp(file, hp->dbuf.name) == 0) {
*dlen = dir.length;
return (uchar*)(hp+1);
}
hp += (dir.length+TBLOCK-1)/TBLOCK + 1;
}
return 0;
}
static int
getdir(Hblock *hp, Dir *sp)
{
int chksum;
if (hp->dbuf.name[0] == '\0')
return 0;
sp->length = strtol(hp->dbuf.size, 0, 8);
sp->mtime = strtol(hp->dbuf.mtime, 0, 8);
chksum = strtol(hp->dbuf.chksum, 0, 8);
if (chksum != checksum(hp)) {
print("directory checksum error\n");
return 0;
}
return 1;
}
static int
checksum(Hblock *hp)
{
int i;
char *cp;
i = 0;
for (cp = hp->dummy; cp < &hp->dummy[TBLOCK]; cp++) {
if(cp < hp->dbuf.chksum || cp >= &hp->dbuf.chksum[sizeof(hp->dbuf.chksum)])
i += *cp & 0xff;
else
i += ' ' & 0xff;
}
return(i);
}

View file

@ -1,926 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
#include "tos.h"
Intrregs *intrregs;
typedef struct Vctl {
Vctl* next; /* handlers on this vector */
char *name; /* of driver, xallocated */
void (*f)(Ureg*, void*); /* handler to call */
void* a; /* argument to call it with */
} Vctl;
static Lock vctllock;
static Vctl *vctl[32];
static Vctl *gpiovctl[27];
static int gpioirqref[12];
/*
* Layout at virtual address 0.
*/
typedef struct Vpage0 {
void (*vectors[8])(void);
ulong vtable[8];
} Vpage0;
Vpage0 *vpage0;
static int irq(Ureg*);
static void gpiointr(Ureg*, void*);
/* recover state after power suspend
* NB: to help debugging bad suspend code,
* I changed some prints below to iprints,
* to avoid deadlocks when a panic is being
* issued during the suspend/resume handler.
*/
void
trapresume(void)
{
vpage0 = (Vpage0*)EVECTORS;
memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
wbflush();
mappedIvecEnable();
}
/*
* set up for exceptions
*/
void
trapinit(void)
{
/* set up the exception vectors */
vpage0 = (Vpage0*)EVECTORS;
memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
wbflush();
/* use exception vectors at 0xFFFF0000 */
mappedIvecEnable();
/* set up the stacks for the interrupt modes */
setr13(PsrMfiq, m->sfiq);
setr13(PsrMirq, m->sirq);
setr13(PsrMabt, m->sabt);
setr13(PsrMund, m->sund);
/* map in interrupt registers */
intrregs = mapspecial(INTRREGS, sizeof(*intrregs));
/* make all interrupts IRQ (i.e. not FIQ) and disable all interrupts */
intrregs->iclr = 0;
intrregs->icmr = 0;
/* turn off all gpio interrupts */
gpioregs->rising = 0;
gpioregs->falling = 0;
gpioregs->edgestatus = gpioregs->edgestatus;
/* allow all enabled interrupts to take processor out of sleep mode */
intrregs->iccr = 0;
}
void
trapdump(char *tag)
{
iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
tag, intrregs->icip, intrregs->icmr, intrregs->iclr,
intrregs->iccr, intrregs->icfp);
}
void
warnregs(Ureg *ur, char *tag)
{
char buf[1024];
char *e = buf+sizeof(buf);
char *p;
p = seprint(buf, e, "%s:\n", tag);
p = seprint(p, e, "type 0x%.8lux psr 0x%.8lux pc 0x%.8lux\n",
ur->type, ur->psr, ur->pc);
p = seprint(p, e, "r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n",
ur->r0, ur->r1, ur->r2, ur->r3);
p = seprint(p, e, "r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n",
ur->r4, ur->r5, ur->r6, ur->r7);
p = seprint(p, e, "r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n",
ur->r8, ur->r9, ur->r10, ur->r11);
seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",
ur->r12, ur->r13, ur->r14);
iprint("%s", buf);
}
/*
* enable an irq interrupt
*/
static void
irqenable(int irq, IntrHandler *f, void* a, char *name)
{
Vctl *v;
if(irq >= nelem(vctl) || irq < 0)
panic("intrenable");
v = malloc(sizeof(Vctl));
v->f = f;
v->a = a;
v->name = xalloc(strlen(name)+1);
strcpy(v->name, name);
lock(&vctllock);
v->next = vctl[irq];
vctl[irq] = v;
intrregs->icmr |= 1<<irq;
unlock(&vctllock);
}
/*
* disable an irq interrupt
*/
static void
irqdisable(int irq, IntrHandler *f, void* a, char *name)
{
Vctl **vp, *v;
if(irq >= nelem(vctl) || irq < 0)
panic("intrdisable");
lock(&vctllock);
for(vp = &vctl[irq]; v = *vp; vp = &v->next)
if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
print("irqdisable: remove %s\n", name);
*vp = v->next;
free(v);
break;
}
if (v == nil)
print("irqdisable: irq %d, name %s not enabled\n", irq, name);
if (vctl[irq] == nil){
print("irqdisable: clear icmr bit %d\n", irq);
intrregs->icmr &= ~(1<<irq);
}
unlock(&vctllock);
}
/*
* enable an interrupt
*/
void
intrenable(int type, int which, IntrHandler *f, void* a, char *name)
{
int irq;
Vctl *v;
if(type == IRQ){
irqenable(which, f, a, name);
return;
}
/* from here down, it must be a GPIO edge interrupt */
irq = which;
if(which >= nelem(gpiovctl) || which < 0)
panic("intrenable");
if(which > 11)
irq = 11;
/* the pin had better be configured as input */
if((1<<which) & gpioregs->direction)
panic("intrenable of output pin %d", which);
/* create a second level vctl for the gpio edge interrupt */
v = malloc(sizeof(Vctl));
v->f = f;
v->a = a;
v->name = xalloc(strlen(name)+1);
strcpy(v->name, name);
lock(&vctllock);
v->next = gpiovctl[which];
gpiovctl[which] = v;
/* set edge register to enable interrupt */
switch(type){
case GPIOboth:
gpioregs->rising |= 1<<which;
gpioregs->falling |= 1<<which;
break;
case GPIOfalling:
gpioregs->falling |= 1<<which;
break;
case GPIOrising:
gpioregs->rising |= 1<<which;
break;
}
unlock(&vctllock);
/* point the irq to the gpio interrupt handler */
if(gpioirqref[irq]++ == 0)
irqenable(irq, gpiointr, nil, "gpio edge");
}
/*
* disable an interrupt
*/
void
intrdisable(int type, int which, IntrHandler *f, void* a, char *name)
{
int irq;
Vctl **vp, *v;
if(type == IRQ){
irqdisable(which, f, a, name);
return;
}
/* from here down, it must be a GPIO edge interrupt */
irq = which;
if(which >= nelem(gpiovctl) || which < 0)
panic("intrdisable");
if(which > 11)
irq = 11;
lock(&vctllock);
for(vp = &gpiovctl[which]; v = *vp; vp = &v->next)
if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
break;
}
if (gpiovctl[which] == nil){
/* set edge register to enable interrupt */
switch(type){
case GPIOboth:
print("intrdisable: gpio-rising+falling clear bit %d\n", which);
gpioregs->rising &= ~(1<<which);
gpioregs->falling &= ~(1<<which);
break;
case GPIOfalling:
print("intrdisable: gpio-falling clear bit %d\n", which);
gpioregs->falling &= ~(1<<which);
break;
case GPIOrising:
print("intrdisable: gpio-rising clear bit %d\n", which);
gpioregs->rising &= ~(1<<which);
break;
}
}
if (v) {
print("intrdisable: removing %s\n", name);
*vp = v->next;
}else
print("intrdisable: which %d, name %s not enabled\n", which, name);
unlock(&vctllock);
/* disable the gpio interrupt handler if necessary */
if(--gpioirqref[irq] == 0){
print("intrdisable: inrqdisable gpiointr\n");
irqdisable(irq, gpiointr, nil, "gpio edge");
}
free(v);
}
/*
* called by trap to handle access faults
*/
static void
faultarm(Ureg *ureg, ulong va, int user, int read)
{
int n, insyscall;
char buf[ERRMAX];
if (up == nil) {
warnregs(ureg, "kernel fault");
panic("fault: nil up in faultarm, accessing 0x%lux", va);
}
insyscall = up->insyscall;
up->insyscall = 1;
n = fault(va, read);
if(n < 0){
if(!user){
warnregs(ureg, "kernel fault");
panic("fault: kernel accessing 0x%lux", va);
}
// warnregs(ureg, "user fault");
sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va);
postnote(up, 1, buf, NDebug);
}
up->insyscall = insyscall;
}
/*
* returns 1 if the instruction writes memory, 0 otherwise
*/
int
writetomem(ulong inst)
{
/* swap always write memory */
if((inst & 0x0FC00000) == 0x01000000)
return 1;
/* loads and stores are distinguished by bit 20 */
if(inst & (1<<20))
return 0;
return 1;
}
/*
* here on all exceptions other than syscall (SWI)
*/
void
trap(Ureg *ureg)
{
ulong inst;
int clockintr, user, x, rv;
ulong va, fsr;
char buf[ERRMAX];
int rem;
if(up != nil)
rem = ((char*)ureg)-up->kstack;
else
rem = ((char*)ureg)-((char*)(MACHADDR+sizeof(Mach)));
if(rem < 256) {
dumpstack();
panic("trap %d bytes remaining, up = %#p, ureg = %#p, at pc 0x%lux",
rem, up, ureg, ureg->pc);
}
user = (ureg->psr & PsrMask) == PsrMusr;
/*
* All interrupts/exceptions should be resumed at ureg->pc-4,
* except for Data Abort which resumes at ureg->pc-8.
*/
if(ureg->type == (PsrMabt+1))
ureg->pc -= 8;
else
ureg->pc -= 4;
clockintr = 0;
switch(ureg->type){
default:
panic("unknown trap");
break;
case PsrMirq:
clockintr = irq(ureg);
break;
case PsrMabt: /* prefetch fault */
faultarm(ureg, ureg->pc, user, 1);
break;
case PsrMabt+1: /* data fault */
va = getfar();
inst = *(ulong*)(ureg->pc);
fsr = getfsr() & 0xf;
switch(fsr){
case 0x0:
panic("vector exception at %lux", ureg->pc);
break;
case 0x1:
case 0x3:
if(user){
snprint(buf, sizeof(buf), "sys: alignment: pc 0x%lux va 0x%lux\n",
ureg->pc, va);
postnote(up, 1, buf, NDebug);
} else
panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va);
break;
case 0x2:
panic("terminal exception at %lux", ureg->pc);
break;
case 0x4:
case 0x6:
case 0x8:
case 0xa:
case 0xc:
case 0xe:
panic("external abort 0x%lux pc 0x%lux addr 0x%lux", fsr, ureg->pc, va);
break;
case 0x5:
case 0x7:
/* translation fault, i.e., no pte entry */
faultarm(ureg, va, user, !writetomem(inst));
break;
case 0x9:
case 0xb:
/* domain fault, accessing something we shouldn't */
if(user){
sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n",
ureg->pc, va);
postnote(up, 1, buf, NDebug);
} else
panic("kernel access violation: pc 0x%lux va 0x%lux",
ureg->pc, va);
break;
case 0xd:
case 0xf:
/* permission error, copy on write or real permission error */
faultarm(ureg, va, user, !writetomem(inst));
break;
}
break;
case PsrMund: /* undefined instruction */
if (user) {
/* look for floating point instructions to interpret */
x = spllo();
rv = fpiarm(ureg);
splx(x);
if (rv == 0) {
sprint(buf, "undefined instruction: pc 0x%lux\n", ureg->pc);
postnote(up, 1, buf, NDebug);
}
}else{
iprint("undefined instruction: pc=0x%lux, inst=0x%lux, 0x%lux, 0x%lux, 0x%lux, 0x%lux\n", ureg->pc, ((ulong*)ureg->pc)[-2], ((ulong*)ureg->pc)[-1], ((ulong*)ureg->pc)[0], ((ulong*)ureg->pc)[1], ((ulong*)ureg->pc)[2]);
panic("undefined instruction");
}
break;
}
splhi();
/* delaysched set because we held a lock or because our quantum ended */
if(up && up->delaysched && clockintr){
sched();
splhi();
}
if(user){
if(up->procctl || up->nnote)
notify(ureg);
kexit(ureg);
}
}
/*
* here on irq's
*/
static int
irq(Ureg *ur)
{
ulong va;
int clockintr, i;
Vctl *v;
va = intrregs->icip;
if(va & (1<<IRQtimer0))
clockintr = 1;
else
clockintr = 0;
for(i = 0; i < 32; i++){
if(((1<<i) & va) == 0)
continue;
for(v = vctl[i]; v != nil; v = v->next){
v->f(ur, v->a);
va &= ~(1<<i);
}
}
if(va)
print("unknown interrupt: %lux\n", va);
return clockintr;
}
/*
* here on gpio interrupts
*/
static void
gpiointr(Ureg *ur, void*)
{
ulong va;
int i;
Vctl *v;
va = gpioregs->edgestatus;
gpioregs->edgestatus = va;
for(i = 0; i < 27; i++){
if(((1<<i) & va) == 0)
continue;
for(v = gpiovctl[i]; v != nil; v = v->next){
v->f(ur, v->a);
va &= ~(1<<i);
}
}
if(va)
print("unknown gpio interrupt: %lux\n", va);
}
/*
* system calls
*/
#include "../port/systab.h"
/*
* Syscall is called directly from assembler without going through trap().
*/
void
syscall(Ureg* ureg)
{
char *e;
ulong sp;
long ret;
int i, scallnr;
if((ureg->psr & PsrMask) != PsrMusr) {
panic("syscall: pc 0x%lux r14 0x%lux cs 0x%lux", ureg->pc, ureg->r14, ureg->psr);
}
m->syscall++;
up->insyscall = 1;
up->pc = ureg->pc;
up->dbgreg = ureg;
scallnr = ureg->r0;
up->scallnr = scallnr;
spllo();
sp = ureg->sp;
up->nerrlab = 0;
ret = -1;
if(!waserror()){
if(scallnr >= nsyscall){
pprint("bad sys call number %d pc %lux\n",
scallnr, ureg->pc);
postnote(up, 1, "sys: bad sys call", NDebug);
error(Ebadarg);
}
if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
validaddr(sp, sizeof(Sargs)+BY2WD, 0);
up->s = *((Sargs*)(sp+BY2WD));
up->psstate = sysctab[scallnr];
ret = systab[scallnr]((va_list)up->s.args);
poperror();
}else{
/* failure: save the error buffer for errstr */
e = up->syserrstr;
up->syserrstr = up->errstr;
up->errstr = e;
}
if(up->nerrlab){
print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
for(i = 0; i < NERR; i++)
print("sp=%lux pc=%lux\n",
up->errlab[i].sp, up->errlab[i].pc);
panic("error stack");
}
up->insyscall = 0;
up->psstate = 0;
/*
* Put return value in frame. On the x86 the syscall is
* just another trap and the return value from syscall is
* ignored. On other machines the return value is put into
* the results register by caller of syscall.
*/
ureg->r0 = ret;
if(scallnr == NOTED)
noted(ureg, *(ulong*)(sp+BY2WD));
if(up->delaysched)
sched();
splhi();
if(scallnr != RFORK && (up->procctl || up->nnote))
notify(ureg);
}
/*
* Return user to state before notify()
*/
void
noted(Ureg* ureg, ulong arg0)
{
Ureg *nureg;
ulong oureg, sp;
qlock(&up->debug);
if(arg0!=NRSTR && !up->notified) {
qunlock(&up->debug);
pprint("call to noted() when not notified\n");
pexit("Suicide", 0);
}
up->notified = 0;
nureg = up->ureg; /* pointer to user returned Ureg struct */
/* sanity clause */
oureg = (ulong)nureg;
if(!okaddr(oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
qunlock(&up->debug);
pprint("bad ureg in noted or call to noted when not notified\n");
pexit("Suicide", 0);
}
/* don't let user change system flags */
nureg->psr = (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq)) |
(nureg->psr & (PsrMask|PsrDfiq|PsrDirq));
memmove(ureg, nureg, sizeof(Ureg));
switch(arg0){
case NCONT:
case NRSTR:
if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->sp, BY2WD, 0)){
qunlock(&up->debug);
pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
qunlock(&up->debug);
break;
case NSAVE:
if(!okaddr(nureg->pc, BY2WD, 0)
|| !okaddr(nureg->sp, BY2WD, 0)){
qunlock(&up->debug);
pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
qunlock(&up->debug);
sp = oureg-4*BY2WD-ERRMAX;
splhi();
ureg->sp = sp;
((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
((ulong*)sp)[0] = 0; /* arg 0 is pc */
break;
default:
up->lastnote.flag = NDebug;
/* fall through */
case NDFLT:
qunlock(&up->debug);
if(up->lastnote.flag == NDebug)
pprint("suicide: %s\n", up->lastnote.msg);
pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
}
}
/*
* Call user, if necessary, with note.
* Pass user the Ureg struct and the note on his stack.
*/
int
notify(Ureg* ureg)
{
int l;
ulong s, sp;
Note *n;
if(up->procctl)
procctl();
if(up->nnote == 0)
return 0;
s = spllo();
qlock(&up->debug);
up->notepending = 0;
n = &up->note[0];
if(strncmp(n->msg, "sys:", 4) == 0){
l = strlen(n->msg);
if(l > ERRMAX-15) /* " pc=0x12345678\0" */
l = ERRMAX-15;
sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
}
if(n->flag!=NUser && (up->notified || up->notify==0)){
qunlock(&up->debug);
if(n->flag == NDebug)
pprint("suicide: %s\n", n->msg);
pexit(n->msg, n->flag!=NDebug);
}
if(up->notified) {
qunlock(&up->debug);
splhi();
return 0;
}
if(!up->notify){
qunlock(&up->debug);
pexit(n->msg, n->flag!=NDebug);
}
sp = ureg->sp;
sp -= sizeof(Ureg);
if(!okaddr((uintptr)up->notify, 1, 0)
|| !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){
qunlock(&up->debug);
pprint("suicide: bad address in notify\n");
pexit("Suicide", 0);
}
up->ureg = (void*)sp;
memmove((Ureg*)sp, ureg, sizeof(Ureg));
*(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
up->ureg = (void*)sp;
sp -= BY2WD+ERRMAX;
memmove((char*)sp, up->note[0].msg, ERRMAX);
sp -= 3*BY2WD;
*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
*(ulong*)(sp+1*BY2WD) = (ulong)up->ureg; /* arg 1 is ureg* */
*(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
ureg->sp = sp;
ureg->pc = (ulong)up->notify;
up->notified = 1;
up->nnote--;
memmove(&up->lastnote, &up->note[0], sizeof(Note));
memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
qunlock(&up->debug);
splx(s);
return 1;
}
/* Give enough context in the ureg to produce a kernel stack for
* a sleeping process
*/
void
setkernur(Ureg *ureg, Proc *p)
{
ureg->pc = p->sched.pc;
ureg->sp = p->sched.sp+4;
ureg->r14 = (ulong)sched;
}
/*
* return the userpc the last exception happened at
*/
uintptr
userpc(void)
{
Ureg *ureg;
ureg = (Ureg*)up->dbgreg;
return ureg->pc;
}
/* This routine must save the values of registers the user is not permitted
* to write from devproc and then restore the saved values before returning.
*/
void
setregisters(Ureg* ureg, char* pureg, char* uva, int n)
{
USED(ureg, pureg, uva, n);
}
/*
* this is the body for all kproc's
*/
static void
linkproc(void)
{
spllo();
up->kpfun(up->kparg);
pexit("kproc exiting", 0);
}
/*
* setup stack and initial PC for a new kernel proc. This is architecture
* dependent because of the starting stack location
*/
void
kprocchild(Proc *p, void (*func)(void*), void *arg)
{
p->sched.pc = (ulong)linkproc;
p->sched.sp = (ulong)p->kstack+KSTACK;
p->kpfun = func;
p->kparg = arg;
}
/*
* Craft a return frame which will cause the child to pop out of
* the scheduler in user mode with the return register zero. Set
* pc to point to a l.s return function.
*/
void
forkchild(Proc *p, Ureg *ureg)
{
Ureg *cureg;
//print("%lud setting up for forking child %lud\n", up->pid, p->pid);
p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
p->sched.pc = (ulong)forkret;
cureg = (Ureg*)(p->sched.sp);
memmove(cureg, ureg, sizeof(Ureg));
/* syscall returns 0 for child */
cureg->r0 = 0;
/* Things from bottom of syscall which were never executed */
p->psstate = 0;
p->insyscall = 0;
}
/*
* setup stack, initial PC, and any arch dependent regs for an execing user proc.
*/
uintptr
execregs(uintptr entry, ulong ssize, ulong nargs)
{
ulong *sp;
Ureg *ureg;
sp = (ulong*)(USTKTOP - ssize);
*--sp = nargs;
ureg = up->dbgreg;
memset(ureg, 0, 15*sizeof(ulong));
ureg->r13 = (ulong)sp;
ureg->pc = entry;
//print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13);
return USTKTOP-sizeof(Tos); /* address of kernel/user shared data */
}
/*
* Fill in enough of Ureg to get a stack trace, and call a function.
* Used by debugging interface rdb.
*/
void
callwithureg(void (*fn)(Ureg*))
{
Ureg ureg;
ureg.pc = getcallerpc(&fn);
ureg.sp = (ulong)&fn;
fn(&ureg);
}
static void
_dumpstack(Ureg *ureg)
{
ulong l, v, i;
ulong *p;
extern ulong etext;
if(up == 0){
iprint("no current proc\n");
return;
}
iprint("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);
i = 0;
for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){
v = *(ulong*)l;
if(KTZERO < v && v < (ulong)&etext && (v&3)==0){
v -= 4;
p = (ulong*)v;
if((*p & 0x0f000000) == 0x0b000000){
iprint("%.8lux=%.8lux ", l, v);
i++;
}
}
if(i == 4){
i = 0;
iprint("\n");
}
}
if(i)
iprint("\n");
}
void
dumpstack(void)
{
callwithureg(_dumpstack);
}
/*
* pc output by ps
*/
uintptr
dbgpc(Proc *p)
{
Ureg *ureg;
ureg = p->dbgreg;
if(ureg == 0)
return 0;
return ureg->pc;
}
/*
* called in sysfile.c
*/
void
evenaddr(ulong addr)
{
if(addr & 3){
postnote(up, 1, "sys: odd address", NDebug);
error(Ebadarg);
}
}

View file

@ -1,514 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
/* this isn't strictly an sa1110 driver. The rts/cts stuff is h3650 specific */
static void sa1110_uartpower(Uart *, int);
enum
{
/* ctl[0] bits */
Parity= 1<<0,
Even= 1<<1,
Stop2= 1<<2,
Bits8= 1<<3,
SCE= 1<<4, /* synchronous clock enable */
RCE= 1<<5, /* rx on falling edge of clock */
TCE= 1<<6, /* tx on falling edge of clock */
/* ctl[3] bits */
Rena= 1<<0, /* receiver enable */
Tena= 1<<1, /* transmitter enable */
Break= 1<<2, /* force TXD3 low */
Rintena= 1<<3, /* enable receive interrupt */
Tintena= 1<<4, /* enable transmitter interrupt */
Loopback= 1<<5, /* loop back data */
/* data bits */
DEparity= 1<<8, /* parity error */
DEframe= 1<<9, /* framing error */
DEoverrun= 1<<10, /* overrun error */
/* status[0] bits */
Tint= 1<<0, /* transmit fifo half full interrupt */
Rint0= 1<<1, /* receiver fifo 1/3-2/3 full */
Rint1= 1<<2, /* receiver fifo not empty and receiver idle */
Breakstart= 1<<3,
Breakend= 1<<4,
Fifoerror= 1<<5, /* fifo error */
/* status[1] bits */
Tbusy= 1<<0, /* transmitting */
Rnotempty= 1<<1, /* receive fifo not empty */
Tnotfull= 1<<2, /* transmit fifo not full */
ParityError= 1<<3,
FrameError= 1<<4,
Overrun= 1<<5,
};
extern PhysUart sa1110physuart;
//static
Uart sa1110uart[2] = {
{ .regs = (void*)UART3REGS,
.name = "serialport3",
.freq = ClockFreq,
.bits = 8,
.stop = 1,
.parity = 'n',
.baud = 115200,
.phys = &sa1110physuart,
.special = 0,
.next = &sa1110uart[1], },
{ .regs = (void*)UART1REGS,
.name = "serialport1",
.freq = ClockFreq,
.bits = 8,
.stop = 1,
.parity = 'n',
.baud = 115200,
.phys = &sa1110physuart,
.putc = µcputc,
.special = 0,
.next = nil, },
};
static Uart* µcuart;
#define R(p) ((Uartregs*)((p)->regs))
#define SR(p) ((Uartregs*)((p)->saveregs))
/*
* enable a port's interrupts. set DTR and RTS
*/
static void
sa1110_uartenable(Uart *p, int intena)
{
ulong s;
s = R(p)->ctl[3] & ~(Rintena|Tintena|Rena|Tena);
if(intena)
R(p)->ctl[3] = s |Rintena|Tintena|Rena|Tena;
else
R(p)->ctl[3] = s | Rena|Tena;
}
/*
* disable interrupts. clear DTR, and RTS
*/
static void
sa1110_uartdisable(Uart *p)
{
R(p)->ctl[3] &= ~(Rintena|Tintena|Rena|Tena);
}
static long
sa1110_uartstatus(Uart *p, void *buf, long n, long offset)
{
char str[256];
ulong ctl0;
ctl0 = R(p)->ctl[0];
snprint(str, sizeof(str),
"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
"dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",
p->baud,
p->hup_dcd,
0,
p->hup_dsr,
(ctl0 & Bits8) ? 8 : 7,
0,
(ctl0 & Parity) ? ((ctl0 & Even) ? 'e' : 'o') : 'n',
0,
(ctl0 & Stop2) ? 2 : 1,
1,
p->dev,
p->type,
p->ferr,
p->oerr,
"",
"",
"",
"" );
return readstr(offset, buf, n, str);
}
/*
* set the buad rate
*/
static int
sa1110_uartbaud(Uart *p, int rate)
{
ulong brconst;
ulong ctl3;
if(rate <= 0)
return -1;
/* disable */
ctl3 = R(p)->ctl[3];
R(p)->ctl[3] = 0;
brconst = p->freq/(16*rate) - 1;
R(p)->ctl[1] = (brconst>>8) & 0xf;
R(p)->ctl[2] = brconst & 0xff;
/* reenable */
R(p)->ctl[3] = ctl3;
p->baud = rate;
return 0;
}
/*
* send a break
*/
static void
sa1110_uartbreak(Uart *p, int ms)
{
if(ms == 0)
ms = 200;
R(p)->ctl[3] |= Break;
tsleep(&up->sleep, return0, 0, ms);
R(p)->ctl[3] &= ~Break;
}
/*
* set bits/char
*/
static int
sa1110_uartbits(Uart *p, int n)
{
ulong ctl0, ctl3;
ctl0 = R(p)->ctl[0];
switch(n){
case 7:
ctl0 &= ~Bits8;
break;
case 8:
ctl0 |= Bits8;
break;
default:
return -1;
}
/* disable */
ctl3 = R(p)->ctl[3];
R(p)->ctl[3] = 0;
R(p)->ctl[0] = ctl0;
/* reenable */
R(p)->ctl[3] = ctl3;
p->bits = n;
return 0;
}
/*
* set stop bits
*/
static int
sa1110_uartstop(Uart *p, int n)
{
ulong ctl0, ctl3;
ctl0 = R(p)->ctl[0];
switch(n){
case 1:
ctl0 &= ~Stop2;
break;
case 2:
ctl0 |= Stop2;
break;
default:
return -1;
}
/* disable */
ctl3 = R(p)->ctl[3];
R(p)->ctl[3] = 0;
R(p)->ctl[0] = ctl0;
/* reenable */
R(p)->ctl[3] = ctl3;
p->stop = n;
return 0;
}
/*
* turn on/off rts
*/
static void
sa1110_uartrts(Uart*, int)
{
}
/*
* turn on/off dtr
*/
static void
sa1110_uartdtr(Uart*, int)
{
}
/*
* turn on/off modem flow control on/off (rts/cts)
*/
static void
sa1110_uartmodemctl(Uart *p, int on)
{
if(on) {
} else {
p->cts = 1;
}
}
/*
* set parity
*/
static int
sa1110_uartparity(Uart *p, int type)
{
ulong ctl0, ctl3;
ctl0 = R(p)->ctl[0];
switch(type){
case 'e':
ctl0 |= Parity|Even;
break;
case 'o':
ctl0 |= Parity;
break;
default:
ctl0 &= ~(Parity|Even);
break;
}
/* disable */
ctl3 = R(p)->ctl[3];
R(p)->ctl[3] = 0;
R(p)->ctl[0] = ctl0;
/* reenable */
R(p)->ctl[3] = ctl3;
return 0;
}
/*
* restart output if not blocked and OK to send
*/
static void
sa1110_uartkick(Uart *p)
{
int i;
R(p)->ctl[3] &= ~Tintena;
if(p->cts == 0 || p->blocked)
return;
for(i = 0; i < 1024; i++){
if(!(R(p)->status[1] & Tnotfull)){
R(p)->ctl[3] |= Tintena;
break;
}
if(p->op >= p->oe && uartstageoutput(p) == 0)
break;
R(p)->data = *p->op++;
}
}
/*
* take an interrupt
*/
static void
sa1110_uartintr(Ureg*, void *x)
{
Uart *p;
ulong s;
Uartregs *regs;
p = x;
regs = p->regs;
/* receiver interrupt, snarf bytes */
while(regs->status[1] & Rnotempty)
uartrecv(p, regs->data);
/* remember and reset interrupt causes */
s = regs->status[0];
regs->status[0] |= s;
if(s & Tint){
/* transmitter interrupt, restart */
uartkick(p);
}
if(s & (ParityError|FrameError|Overrun)){
if(s & ParityError)
p->parity++;
if(s & FrameError)
p->ferr++;
if(s & Overrun)
p->oerr++;
}
/* receiver interrupt, snarf bytes */
while(regs->status[1] & Rnotempty)
uartrecv(p, regs->data);
}
static Uart*
sa1110_pnp(void)
{
return sa1110uart;
}
static int
sa1110_getc(Uart *uart)
{
Uartregs *ur;
ur = uart->regs;
while((ur->status[1] & Rnotempty) == 0)
;
return ur->data;
}
static void
sa1110_putc(Uart *uart, int c)
{
Uartregs *ur;
ur = uart->regs;
/* wait for output ready */
while((ur->status[1] & Tnotfull) == 0)
;
ur->data = c;
while((ur->status[1] & Tbusy))
;
}
PhysUart sa1110physuart = {
.name= "sa1110",
.pnp= sa1110_pnp,
.enable= sa1110_uartenable,
.disable= sa1110_uartdisable,
.bits= sa1110_uartbits,
.kick= sa1110_uartkick,
.modemctl= sa1110_uartmodemctl,
.baud= sa1110_uartbaud,
.stop= sa1110_uartstop,
.parity= sa1110_uartparity,
.dobreak= sa1110_uartbreak,
.rts= sa1110_uartrts,
.dtr= sa1110_uartdtr,
.status= sa1110_uartstatus,
.power= sa1110_uartpower,
.getc= sa1110_getc,
.putc= sa1110_putc,
};
/*
* for iprint, just write it
*/
void
serialµcputs(uchar *str, int n)
{
Uartregs *ur;
if(µcuart == nil)
return;
ur = µcuart->regs;
while(n-- > 0){
/* wait for output ready */
while((ur->status[1] & Tnotfull) == 0)
;
ur->data = *str++;
}
while((ur->status[1] & Tbusy))
;
}
enum
{
/* gpclk register 0 */
Gpclk_sus= 1<<0, /* set uart mode */
};
Gpclkregs *gpclkregs;
/*
* setup all uarts (called early by main() to allow debugging output to
* a serial port)
*/
void
sa1110_uartsetup(int console)
{
Uart *p;
/* external serial port (eia0) */
p = &sa1110uart[0];
p->regs = mapspecial(UART3REGS, sizeof(Uartregs));
p->saveregs = xalloc(sizeof(Uartregs));
/* set eia0 up as a console */
if(console){
uartctl(p, "b115200 l8 pn s1");
(*p->phys->enable)(p, 0);
p->console = 1;
consuart = p;
}
intrenable(IRQ, IRQuart3, sa1110_uartintr, p, p->name);
/* port for talking to microcontroller (eia1) */
gpclkregs = mapspecial(GPCLKREGS, sizeof(Gpclkregs));
gpclkregs->r0 = Gpclk_sus; /* set uart mode */
p = &sa1110uart[1];
p->regs = mapspecial(UART1REGS, sizeof(Uartregs));
p->saveregs = xalloc(sizeof(Uartregs));
uartctl(p, "b115200 l8 pn s1");
µcuart = p;
p->special = 1;
(*p->phys->enable)(p, 0);
intrenable(IRQ, IRQuart1b, sa1110_uartintr, p, p->name);
}
static void
uartcpy(Uartregs *to, Uartregs *from)
{
to->ctl[0] = from->ctl[0];
// to->ctl[1] = from->ctl[1];
// to->ctl[2] = from->ctl[2];
to->ctl[3] = from->ctl[3];
}
static void
sa1110_uartpower(Uart *p, int powerup)
{
if (powerup) {
/* power up, restore the registers */
uartcpy(R(p), SR(p));
R(p)->status[0] = R(p)->status[0];
} else {
/* power down, save the registers */
uartcpy(SR(p), R(p));
}
}

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
#include "../pc/wavelan.h"

View file

@ -1,6 +1,5 @@
ARCH=\
bcm\
bitsy\
kw\
mtx\
omap\