summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/Makefile47
-rw-r--r--firmware/app.lds23
-rw-r--r--firmware/fat.c1315
-rw-r--r--firmware/fat.h154
-rw-r--r--firmware/key.h44
-rw-r--r--firmware/lcd.c135
-rw-r--r--firmware/lcd.h263
-rw-r--r--firmware/led.c68
-rw-r--r--firmware/led.h50
-rw-r--r--firmware/serial.c82
-rw-r--r--firmware/serial.h31
-rw-r--r--firmware/sh7034.h167
-rw-r--r--firmware/start.s41
-rw-r--r--firmware/system.c432
-rw-r--r--firmware/system.h267
15 files changed, 3119 insertions, 0 deletions
diff --git a/firmware/Makefile b/firmware/Makefile
new file mode 100644
index 0000000000..9b38303be4
--- /dev/null
+++ b/firmware/Makefile
@@ -0,0 +1,47 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10HPATH = /usr/local/sh-gcc/bin
11CC = $(HPATH)/sh-elf-gcc
12LD = $(HPATH)/sh-elf-ld
13AR = $(HPATH)/sh-elf-ar
14AS = $(HPATH)/sh-elf-as
15OC = $(HPATH)/sh-elf-objcopy
16
17INCLUDES=-I.
18
19CFLAGS = -Os -Wall -m1 -nostdlib -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES)
20AFLAGS += -small -relax
21
22SRC := $(wildcard *.c)
23OBJS := $(SRC:%.c=%.o)
24
25%.o: %.s
26 $(CC) -o $@ $(CFLAGS) $(INCLUDES) $(DEFS) -c $<
27
28
29all : $(OBJS) # archos.mod # archos.asm
30
31archos.elf : $(OBJS) app.lds
32 $(CC) -nostdlib -o archos.elf $(OBJS) -lgcc -Tapp.lds -Wl,-Map,archos.map
33
34archos.bin : archos.elf
35 $(OC) -O binary archos.elf archos.bin
36
37archos.asm: archos.bin
38 sh2d -sh1 archos.bin > archos.asm
39
40archos.mod : archos.bin
41 scramble archos.bin archos.mod
42
43dist:
44 tar czvf dist.tar.gz Makefile main.c start.s app.lds
45
46clean:
47 -rm -f *.x *.i *.o *.elf *.bin *.map *.mod *.bak *~
diff --git a/firmware/app.lds b/firmware/app.lds
new file mode 100644
index 0000000000..03bd1b2b54
--- /dev/null
+++ b/firmware/app.lds
@@ -0,0 +1,23 @@
1ENTRY(_start)
2OUTPUT_FORMAT(elf32-sh)
3SECTIONS
4{
5 .vectors 0x09000000 :
6 {
7 *(.vectors);
8 . = ALIGN(0x200);
9 *(.text.start)
10 *(.text)
11 *(.rodata)
12 }
13
14 .bss :
15 {
16 _stack = . + 0x1000;
17 }
18
19 .pad 0x0900C800 :
20 {
21 LONG(0);
22 }
23 }
diff --git a/firmware/fat.c b/firmware/fat.c
new file mode 100644
index 0000000000..235341f72d
--- /dev/null
+++ b/firmware/fat.c
@@ -0,0 +1,1315 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdio.h>
21#include <string.h>
22#include <math.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include <time.h>
26#include <sys/timeb.h>
27
28#include "fakestorage.h"
29#include "fat.h"
30#include "debug.h"
31
32#define NUM_ROOT_DIR_ENTRIES 512
33#define NUM_FATS 2
34#define NUM_RESERVED_SECTORS 1
35#define NUM_BLOCKS 10000
36
37struct dsksz2secperclus
38{
39 unsigned int disk_size;
40 unsigned int sec_per_cluster;
41};
42
43/*
44** This is the table for FAT16 drives. NOTE that this table includes
45** entries for disk sizes larger than 512 MB even though typically
46** only the entries for disks < 512 MB in size are used.
47** The way this table is accessed is to look for the first entry
48** in the table for which the disk size is less than or equal
49** to the DiskSize field in that table entry. For this table to
50** work properly BPB_RsvdSecCnt must be 1, BPB_NumFATs
51** must be 2, and BPB_RootEntCnt must be 512. Any of these values
52** being different may require the first table entries DiskSize value
53** to be changed otherwise the cluster count may be to low for FAT16.
54*/
55struct dsksz2secperclus dsk_table_fat16 [] =
56{
57 { 8400, 0}, /* disks up to 4.1 MB, the 0 value for SecPerClusVal
58 trips an error */
59 { 32680, 2}, /* disks up to 16 MB, 1k cluster */
60 { 262144, 4}, /* disks up to 128 MB, 2k cluster */
61 { 524288, 8}, /* disks up to 256 MB, 4k cluster */
62 { 1048576, 16}, /* disks up to 512 MB, 8k cluster */
63/* The entries after this point are not used unless FAT16 is forced */
64 { 2097152, 32}, /* disks up to 1 GB, 16k cluster */
65 { 4194304, 64}, /* disks up to 2 GB, 32k cluster */
66 { 0xFFFFFFFF, 0} /* any disk greater than 2GB,
67 0 value for SecPerClusVal trips an error */
68};
69
70int fat_num_rootdir_sectors(struct bpb *bpb);
71int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster);
72int fat_get_fatsize(struct bpb* bpb);
73int fat_get_totsec(struct bpb* bpb);
74int fat_get_rootdir_sector(struct bpb *bpb);
75int fat_first_data_sector(struct bpb* bpb);
76int fat_get_bpb(struct bpb *bpb);
77int fat_bpb_is_sane(struct bpb *bpb);
78int fat_create_fat(struct bpb* bpb);
79int fat_dbg_read_block(char *name, unsigned char *buf);
80int fat_flush_fat(struct bpb *bpb);
81unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum);
82int fat_update_entry(struct bpb *bpb, int entry, unsigned int val);
83unsigned int fat_getcurrdostime(unsigned short *dosdate,
84 unsigned short *dostime,
85 unsigned char *dostenth);
86int fat_create_root_dir(struct bpb *bpb);
87int fat_create_dos_name(unsigned char *name, unsigned char *newname);
88int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name);
89
90unsigned char *fat_cache[256];
91int fat_cache_dirty[256];
92char current_directory[256] = "\\";
93struct bpb *global_bpb;
94struct disk_info di;
95
96extern int yyparse(void);
97
98
99void prompt(void)
100{
101 printf("C:%s>", current_directory);
102}
103
104#ifdef TEST_FAT
105int main(int argc, char *argv[])
106{
107 struct bpb bpb;
108
109 memset(fat_cache, 0, sizeof(fat_cache));
110 memset(fat_cache_dirty, 0, sizeof(fat_cache_dirty));
111
112 disk_init(NUM_BLOCKS);
113
114 di.num_sectors = NUM_BLOCKS;
115 di.sec_per_track = 40;
116 di.num_heads = 250;
117 di.hidden_sectors = 0;
118
119 if(read_disk("diskdump.dmp") < 0)
120 {
121 printf("*** Warning! The disk is uninitialized\n");
122 }
123 else
124 {
125 fat_get_bpb(&bpb);
126 }
127
128 global_bpb = &bpb;
129 prompt();
130 yyparse();
131
132 dump_disk("diskdump.dmp");
133 return 0;
134}
135#endif
136
137int fat_sec2cluster(struct bpb *bpb, unsigned int sec)
138{
139 int first_sec = fat_first_data_sector(bpb);
140
141 if(sec < first_sec)
142 {
143 fprintf(stderr, "fat_sec2cluster() - Bad sector number (%d)\n", sec);
144 return -1;
145 }
146
147 return ((sec - first_sec) / bpb->bpb_secperclus) + 2;
148}
149
150int fat_last_cluster_in_chain(struct bpb *bpb, unsigned int cluster)
151{
152 int iseof = 0;
153
154 switch(bpb->fat_type)
155 {
156 case FATTYPE_FAT12:
157 if(cluster >= 0x0ff8)
158 iseof = 1;
159 break;
160 case FATTYPE_FAT16:
161 if(cluster >= 0xfff8)
162 iseof = 1;
163 break;
164 case FATTYPE_FAT32:
165 if(cluster >= 0x0ffffff8)
166 iseof = 1;
167 break;
168 }
169 return iseof;
170}
171
172int fat_cluster2sec(struct bpb *bpb, unsigned int cluster)
173{
174 int max_cluster = (fat_get_totsec(bpb) - fat_first_data_sector(bpb)) /
175 bpb->bpb_secperclus + 1;
176
177 if(cluster > max_cluster)
178 {
179 fprintf(stderr, "fat_cluster2sec() - Bad cluster number (%d)\n",
180 cluster);
181 return -1;
182 }
183
184 return fat_first_sector_of_cluster(bpb, cluster);
185}
186
187int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster)
188{
189 return (cluster - 2) * bpb->bpb_secperclus + fat_first_data_sector(bpb);
190}
191
192int fat_num_rootdir_sectors(struct bpb *bpb)
193{
194 return ((bpb->bpb_rootentcnt * 32) + (bpb->bpb_bytspersec - 1)) /
195 bpb->bpb_bytspersec;
196}
197
198int fat_get_fatsize(struct bpb* bpb)
199{
200 if(bpb->bpb_fatsz16 != 0)
201 return bpb->bpb_fatsz16;
202 else
203 return bpb->bpb_fatsz32;
204}
205
206int fat_get_totsec(struct bpb* bpb)
207{
208 if(bpb->bpb_totsec16 != 0)
209 return bpb->bpb_totsec16;
210 else
211 return bpb->bpb_totsec32;
212}
213
214int fat_get_rootdir_sector(struct bpb *bpb)
215{
216 return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fat_get_fatsize(bpb);
217}
218
219int fat_first_data_sector(struct bpb* bpb)
220{
221 int fatsz;
222 int rootdirsectors;
223
224 fatsz = fat_get_fatsize(bpb);
225
226 rootdirsectors = fat_num_rootdir_sectors(bpb);
227
228 return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + rootdirsectors;
229}
230
231int fat_format(struct disk_info *di, char *vol_name)
232{
233 unsigned char buf[BLOCK_SIZE];
234 struct bpb bpb;
235 unsigned int root_dir_sectors;
236 unsigned int tmp1, tmp2;
237 int sec_per_clus = 0;
238 int fat_size;
239 int i = 0;
240 int err;
241
242 while(di->num_sectors > dsk_table_fat16[i].disk_size)
243 {
244 i++;
245 }
246
247 sec_per_clus = dsk_table_fat16[i].sec_per_cluster;
248
249 if(sec_per_clus == 0)
250 {
251 fprintf(stderr, "fat_format() - Bad disk size (%u)\n",
252 di->num_sectors);
253 return -1;
254 }
255
256 /* First calculate how many sectors we need for
257 the root directory */
258 root_dir_sectors = ((NUM_ROOT_DIR_ENTRIES * 32) +
259 (BLOCK_SIZE - 1)) / BLOCK_SIZE;
260
261 /* Now calculate the FAT size */
262 tmp1 = di->num_sectors - (NUM_RESERVED_SECTORS + root_dir_sectors);
263 tmp2 = (256 * sec_per_clus) + NUM_FATS;
264
265 fat_size = (tmp1 + (tmp2 - 1)) / tmp2;
266
267 /* Now create the BPB. We must be careful, so we really make
268 it little endian. */
269 memset(buf, 0xff, BLOCK_SIZE);
270
271 strncpy(&buf[BS_OEMNAME], "MSWIN4.1", 8);
272 buf[BPB_BYTSPERSEC] = BLOCK_SIZE & 0xff;
273 buf[BPB_BYTSPERSEC+1] = BLOCK_SIZE >> 8;
274 buf[BPB_SECPERCLUS] = sec_per_clus;
275 buf[BPB_RSVDSECCNT] = 1;
276 buf[BPB_RSVDSECCNT+1] = 0;
277 buf[BPB_NUMFATS] = 2;
278 buf[BPB_ROOTENTCNT] = NUM_ROOT_DIR_ENTRIES & 0xff;
279 buf[BPB_ROOTENTCNT+1] = NUM_ROOT_DIR_ENTRIES >> 8;
280 buf[BPB_TOTSEC16] = di->num_sectors & 0xff;
281 buf[BPB_TOTSEC16+1] = di->num_sectors >> 8;
282 buf[BPB_MEDIA] = 0xf0;
283 buf[BPB_FATSZ16] = fat_size & 0xff;
284 buf[BPB_FATSZ16+1] = fat_size >> 8;
285 buf[BPB_SECPERTRK] = di->sec_per_track & 0xff;
286 buf[BPB_SECPERTRK+1] = di->sec_per_track >> 8;
287 buf[BPB_NUMHEADS] = di->num_heads & 0xff;
288 buf[BPB_NUMHEADS+1] = di->num_heads >> 8;
289 buf[BPB_HIDDSEC] = di->hidden_sectors & 0xff;
290 buf[BPB_HIDDSEC+1] = (di->hidden_sectors >> 8) & 0xff;
291 buf[BPB_HIDDSEC+2] = (di->hidden_sectors >> 16) & 0xff;
292 buf[BPB_HIDDSEC+3] = (di->hidden_sectors >> 24) & 0xff;
293 buf[BPB_TOTSEC32] = 0;
294 buf[BPB_TOTSEC32+1] = 0;
295 buf[BPB_TOTSEC32+2] = 0;
296 buf[BPB_TOTSEC32+3] = 0;
297
298 buf[BS_DRVNUM] = 0;
299 buf[BS_RESERVED1] = 0;
300 buf[BS_BOOTSIG] = 0x29;
301 buf[BS_VOLID] = 0x78;
302 buf[BS_VOLID+1] = 0x56;
303 buf[BS_VOLID+2] = 0x34;
304 buf[BS_VOLID+3] = 0x12;
305 memset(&buf[BS_VOLLAB], ' ', 11);
306 strncpy(&buf[BS_VOLLAB], vol_name, MIN(11, strlen(vol_name));
307 strncpy(&buf[BS_FILSYSTYPE], "FAT16 ", 8);
308
309 /* The final signature */
310 buf[BPB_LAST_WORD] = 0x55;
311 buf[BPB_LAST_WORD+1] = 0xaa;
312
313 /* Now write the sector to disk */
314 err = write_block(buf, 0);
315
316 if(err < 0)
317 {
318 fprintf(stderr, "fat_format() - Couldn't write BSB (error code %i)\n",
319 err);
320 return -1;
321 }
322
323 if(fat_get_bpb(&bpb) < 0)
324 {
325 fprintf(stderr, "fat_format() - Couldn't read BPB\n");
326 return -1;
327 }
328
329 if(fat_create_fat(&bpb) < 0)
330 {
331 fprintf(stderr, "fat_format() - Couldn't create FAT\n");
332 return -1;
333 }
334
335 if(fat_create_root_dir(&bpb) < 0)
336 {
337 fprintf(stderr, "fat_format() - Couldn't write root dir sector\n");
338 return -1;
339 }
340
341 return 0;
342}
343
344int fat_get_bpb(struct bpb *bpb)
345{
346 unsigned char buf[BLOCK_SIZE];
347 int err;
348 int fatsz;
349 int rootdirsectors;
350 int totsec;
351 int datasec;
352 int countofclusters;
353
354 /* Read the sector */
355 err = read_block(buf, 0);
356 if(err < 0)
357 {
358 fprintf(stderr, "fat_get_bpb() - Couldn't read BPB (error code %i)\n",
359 err);
360 return -1;
361 }
362
363 memset(bpb, 0, sizeof(struct bpb));
364
365 strncpy(bpb->bs_oemname, &buf[BS_OEMNAME], 8);
366 bpb->bs_oemname[8] = 0;
367
368 bpb->bpb_bytspersec = buf[BPB_BYTSPERSEC] | (buf[BPB_BYTSPERSEC+1] << 8);
369 bpb->bpb_secperclus = buf[BPB_SECPERCLUS];
370 bpb->bpb_rsvdseccnt = buf[BPB_RSVDSECCNT] | (buf[BPB_RSVDSECCNT+1] << 8);
371 bpb->bpb_numfats = buf[BPB_NUMFATS];
372 bpb->bpb_rootentcnt = buf[BPB_ROOTENTCNT] | (buf[BPB_ROOTENTCNT+1] << 8);
373 bpb->bpb_totsec16 = buf[BPB_TOTSEC16] | (buf[BPB_TOTSEC16+1] << 8);
374 bpb->bpb_media = buf[BPB_MEDIA];
375 bpb->bpb_fatsz16 = buf[BPB_FATSZ16] | (buf[BPB_FATSZ16+1] << 8);
376 bpb->bpb_secpertrk = buf[BPB_SECPERTRK] | (buf[BPB_SECPERTRK+1] << 8);
377 bpb->bpb_numheads = buf[BPB_NUMHEADS] | (buf[BPB_NUMHEADS+1] << 8);
378 bpb->bpb_hiddsec = buf[BPB_HIDDSEC] | (buf[BPB_HIDDSEC+1] << 8) |
379 (buf[BPB_HIDDSEC+2] << 16) | (buf[BPB_HIDDSEC+3] << 24);
380 bpb->bpb_totsec32 = buf[BPB_TOTSEC32] | (buf[BPB_TOTSEC32+1] << 8) |
381 (buf[BPB_TOTSEC32+2] << 16) | (buf[BPB_TOTSEC32+3] << 24);
382
383 bpb->bs_drvnum = buf[BS_DRVNUM];
384 bpb->bs_bootsig = buf[BS_BOOTSIG];
385 if(bpb->bs_bootsig == 0x29)
386 {
387 bpb->bs_volid = buf[BS_VOLID] | (buf[BS_VOLID+1] << 8) |
388 (buf[BS_VOLID+2] << 16) | (buf[BS_VOLID+3] << 24);
389 strncpy(bpb->bs_vollab, &buf[BS_VOLLAB], 11);
390 strncpy(bpb->bs_filsystype, &buf[BS_FILSYSTYPE], 8);
391 }
392
393 bpb->bpb_fatsz32 = (buf[BPB_FATSZ32] + (buf[BPB_FATSZ32+1] << 8)) |
394 (buf[BPB_FATSZ32+2] << 16) | (buf[BPB_FATSZ32+3] << 24);
395
396 bpb->last_word = buf[BPB_LAST_WORD] | (buf[BPB_LAST_WORD+1] << 8);
397
398 /* Determine FAT type */
399 fatsz = fat_get_fatsize(bpb);
400
401 if(bpb->bpb_totsec16 != 0)
402 totsec = bpb->bpb_totsec16;
403 else
404 totsec = bpb->bpb_totsec32;
405
406 rootdirsectors = fat_num_rootdir_sectors(bpb);
407 datasec = totsec - (bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz +
408 rootdirsectors);
409 countofclusters = datasec / bpb->bpb_secperclus;
410
411 if(countofclusters < 4085)
412 {
413 bpb->fat_type = FATTYPE_FAT12;
414 }
415 else
416 {
417 if(countofclusters < 65525)
418 {
419 bpb->fat_type = FATTYPE_FAT16;
420 }
421 else
422 {
423 bpb->fat_type = FATTYPE_FAT32;
424 }
425 }
426
427 if(fat_bpb_is_sane(bpb) < 0)
428 {
429 fprintf(stderr, "fat_get_bpb() - BPB is not sane\n");
430 return -1;
431 }
432
433 return 0;
434}
435
436int fat_bpb_is_sane(struct bpb *bpb)
437{
438 if(bpb->fat_type == FATTYPE_FAT32)
439 {
440 fprintf(stderr, "fat_bpb_is_sane() - Error: FAT32 not supported\n");
441 return -1;
442 }
443
444 if(bpb->bpb_bytspersec != 512)
445 {
446 fprintf(stderr,
447 "fat_bpb_is_sane() - Warning: sector size is not 512 (%i)\n",
448 bpb->bpb_bytspersec);
449 }
450 if(bpb->bpb_secperclus * bpb->bpb_bytspersec > 32768)
451 {
452 fprintf(stderr,
453 "fat_bpb_is_sane() - Warning: cluster size is larger than 32K "
454 "(%i * %i = %i)\n",
455 bpb->bpb_bytspersec, bpb->bpb_secperclus,
456 bpb->bpb_bytspersec * bpb->bpb_secperclus);
457 }
458 if(bpb->bpb_rsvdseccnt != 1)
459 {
460 fprintf(stderr,
461 "fat_bpb_is_sane() - Warning: Reserved sectors is not 1 (%i)\n",
462 bpb->bpb_rsvdseccnt);
463 }
464 if(bpb->bpb_numfats != 2)
465 {
466 fprintf(stderr,
467 "fat_bpb_is_sane() - Warning: NumFATS is not 2 (%i)\n",
468 bpb->bpb_numfats);
469 }
470 if(bpb->bpb_rootentcnt != 512)
471 {
472 fprintf(stderr,
473 "fat_bpb_is_sane() - Warning: RootEntCnt is not 512 (%i)\n",
474 bpb->bpb_rootentcnt);
475 }
476 if(bpb->bpb_totsec16 < 200)
477 {
478 if(bpb->bpb_totsec16 == 0)
479 {
480 fprintf(stderr, "fat_bpb_is_sane() - Error: TotSec16 is 0\n");
481 return -1;
482 }
483 else
484 {
485 fprintf(stderr,
486 "fat_bpb_is_sane() - Warning: TotSec16 "
487 "is quite small (%i)\n",
488 bpb->bpb_totsec16);
489 }
490 }
491 if(bpb->bpb_media != 0xf0 && bpb->bpb_media < 0xf8)
492 {
493 fprintf(stderr,
494 "fat_bpb_is_sane() - Warning: Non-standard "
495 "media type (0x%02x)\n",
496 bpb->bpb_media);
497 }
498 if(bpb->last_word != 0xaa55)
499 {
500 fprintf(stderr, "fat_bpb_is_sane() - Error: Last word is not "
501 "0xaa55 (0x%04x)\n", bpb->last_word);
502 return -1;
503 }
504 return 0;
505}
506
507int fat_create_fat(struct bpb* bpb)
508{
509 unsigned char *sec;
510 int i;
511 int secnum = 0;
512 int fatsz;
513
514 if(fat_bpb_is_sane(bpb) < 0)
515 {
516 fprintf(stderr, "fat_create_fat() - BPB is not sane\n");
517 return -1;
518 }
519
520 if(bpb->bpb_fatsz16 != 0)
521 fatsz = bpb->bpb_fatsz16;
522 else
523 fatsz = bpb->bpb_fatsz32;
524
525 sec = fat_cache_fat_sector(bpb, secnum);
526 if(!sec)
527 {
528 fprintf(stderr, "fat_create_fat() - Couldn't cache fat sector"
529 " (%d)\n", i);
530 return -1;
531 }
532
533 fat_cache_dirty[secnum] = 1;
534
535 /* First entry should have the media type in the
536 low byte and the rest of the bits set to 1.
537 The second should be the EOC mark. */
538 memset(sec, 0, BLOCK_SIZE);
539 sec[0] = bpb->bpb_media;
540 if(bpb->fat_type == FATTYPE_FAT12)
541 {
542 sec[1] = 0xff;
543 sec[2] = 0xff;
544 }
545 if(bpb->fat_type == FATTYPE_FAT16)
546 {
547 sec[0] = bpb->bpb_media;
548 sec[1] = 0xff;
549 sec[2] = 0xff;
550 sec[3] = 0xff;
551 }
552 secnum++;
553
554 for(i = 0; i < fatsz - 1;i++)
555 {
556 sec = fat_cache_fat_sector(bpb, secnum);
557 if(!sec)
558 {
559 fprintf(stderr, "fat_create_fat() - Couldn't cache fat sector"
560 " (%d)\n", i);
561 return -1;
562 }
563 fat_cache_dirty[secnum] = 1;
564 secnum++;
565 memset(sec, 0, BLOCK_SIZE);
566 }
567
568 if(fat_flush_fat(bpb) < 0)
569 {
570 fprintf(stderr, "fat_create_fat() - Couldn't flush fat\n");
571 return -1;
572 }
573 return 0;
574}
575
576int fat_dbg_read_block(char *name, unsigned char *buf)
577{
578 FILE *f;
579
580 f = fopen(name, "rb");
581 if(f)
582 {
583 if(fread(buf, 1, 512, f) != 512)
584 {
585 fprintf(stderr, "Could not read file \"%s\"\n", name);
586 fclose(f);
587 return -1;
588 }
589 /* Now write the sector to disk */
590 write_block(buf, 0);
591 fclose(f);
592 }
593 else
594 {
595 fprintf(stderr, "Could not open file \"%s\"\n", name);
596 return -1;
597 }
598 return 0;
599}
600
601unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum)
602{
603 unsigned char *sec;
604
605 sec = fat_cache[secnum];
606 /* Load the sector if it is not cached */
607 if(!sec)
608 {
609 sec = malloc(bpb->bpb_bytspersec);
610 if(!sec)
611 {
612 fprintf(stderr, "fat_cache_fat_sector() - Out of memory\n");
613 return NULL;
614 }
615 if(read_block(sec, secnum + bpb->bpb_rsvdseccnt) < 0)
616 {
617 fprintf(stderr, "fat_cache_fat_sector() - Could"
618 " not read sector %d\n",
619 secnum);
620 free(sec);
621 return NULL;
622 }
623 fat_cache[secnum] = sec;
624 }
625 return sec;
626}
627
628int fat_update_entry(struct bpb *bpb, int entry, unsigned int val)
629{
630 unsigned char *sec;
631 unsigned char *sec2;
632 int fatsz;
633 int fatoffset;
634 int thisfatsecnum;
635 int thisfatentoffset;
636 unsigned int tmp;
637
638 fatsz = fat_get_fatsize(bpb);
639
640 if(bpb->fat_type == FATTYPE_FAT12)
641 {
642 fatoffset = entry + (entry / 2);
643 }
644 else
645 {
646 if(bpb->fat_type == FATTYPE_FAT16)
647 fatoffset = entry * 2;
648 else
649 fatoffset = entry * 4;
650 }
651 thisfatsecnum = fatoffset / bpb->bpb_bytspersec;
652 thisfatentoffset = fatoffset % bpb->bpb_bytspersec;
653
654 sec = fat_cache_fat_sector(bpb, thisfatsecnum);
655 /* Load the sector if it is not cached */
656 if(!sec)
657 {
658 fprintf(stderr, "fat_update_entry() - Could not cache sector %d\n",
659 thisfatsecnum);
660 return -1;
661 }
662
663 fat_cache_dirty[thisfatsecnum] = 1;
664
665 switch(bpb->fat_type)
666 {
667 case FATTYPE_FAT12:
668 if(thisfatentoffset == bpb->bpb_bytspersec - 1)
669 {
670 /* This entry spans a sector boundary. Take care */
671 sec2 = fat_cache_fat_sector(bpb, thisfatsecnum + 1);
672 /* Load the sector if it is not cached */
673 if(!sec2)
674 {
675 fprintf(stderr, "fat_update_entry() - Could not "
676 "cache sector %d\n",
677 thisfatsecnum + 1);
678 return -1;
679 }
680 fat_cache_dirty[thisfatsecnum + 1] = 1;
681 }
682 else
683 {
684 if(entry & 1) /* Odd entry number? */
685 {
686 tmp = sec[thisfatentoffset] & 0xf0;
687 sec[thisfatentoffset] = tmp | (val & 0x0f);
688 sec[thisfatentoffset+1] = (val >> 4) & 0xff;
689 }
690 else
691 {
692 sec[thisfatentoffset] = val & 0xff;
693 tmp = sec[thisfatentoffset+1] & 0x0f;
694 sec[thisfatentoffset+1] = tmp | ((val >> 4) & 0xf0);
695 }
696 }
697 break;
698 case FATTYPE_FAT16:
699 *(unsigned short *)(&sec[thisfatentoffset]) = val;
700 break;
701 case FATTYPE_FAT32:
702 tmp = *(unsigned short *)(&sec[thisfatentoffset]) & 0xf000000;
703 val = tmp | (val & 0x0fffffff);
704 *(unsigned short *)(&sec[thisfatentoffset]) = val;
705 break;
706 }
707 return 0;
708}
709
710int fat_read_entry(struct bpb *bpb, int entry)
711{
712 unsigned char *sec;
713 unsigned char *sec2;
714 int fatsz;
715 int fatoffset;
716 int thisfatsecnum;
717 int thisfatentoffset;
718 unsigned int val;
719
720 fatsz = fat_get_fatsize(bpb);
721
722 if(bpb->fat_type == FATTYPE_FAT12)
723 {
724 fatoffset = entry + (entry / 2);
725 }
726 else
727 {
728 if(bpb->fat_type == FATTYPE_FAT16)
729 fatoffset = entry * 2;
730 else
731 fatoffset = entry * 4;
732 }
733 thisfatsecnum = fatoffset / bpb->bpb_bytspersec;
734 thisfatentoffset = fatoffset % bpb->bpb_bytspersec;
735
736 sec = fat_cache_fat_sector(bpb, thisfatsecnum);
737 /* Load the sector if it is not cached */
738 if(!sec)
739 {
740 fprintf(stderr, "fat_update_entry() - Could not cache sector %d\n",
741 thisfatsecnum);
742 return -1;
743 }
744
745 switch(bpb->fat_type)
746 {
747 case FATTYPE_FAT12:
748 if(thisfatentoffset == bpb->bpb_bytspersec - 1)
749 {
750 /* This entry spans a sector boundary. Take care */
751 sec2 = fat_cache_fat_sector(bpb, thisfatsecnum + 1);
752 /* Load the sector if it is not cached */
753 if(!sec2)
754 {
755 fprintf(stderr, "fat_update_entry() - Could not "
756 "cache sector %d\n",
757 thisfatsecnum + 1);
758 return -1;
759 }
760 }
761 else
762 {
763 if(entry & 1) /* Odd entry number? */
764 {
765 val = (sec[thisfatentoffset] & 0x0f) |
766 (sec[thisfatentoffset+1] << 4);
767 }
768 else
769 {
770 val = (sec[thisfatentoffset] & 0xff) |
771 ((sec[thisfatentoffset+1] & 0x0f) << 8);
772 }
773 }
774 break;
775 case FATTYPE_FAT16:
776 val = *(unsigned short *)(&sec[thisfatentoffset]);
777 break;
778 case FATTYPE_FAT32:
779 val = *(unsigned int *)(&sec[thisfatentoffset]);
780 break;
781 }
782 return val;
783}
784
785int fat_flush_fat(struct bpb *bpb)
786{
787 int i;
788 int err;
789 unsigned char *sec;
790 int fatsz;
791 unsigned short d, t;
792 char m;
793
794 fatsz = fat_get_fatsize(bpb);
795
796 for(i = 0;i < 256;i++)
797 {
798 if(fat_cache[i] && fat_cache_dirty[i])
799 {
800 printf("Flushing FAT sector %d\n", i);
801 sec = fat_cache[i];
802 err = write_block(sec, i + bpb->bpb_rsvdseccnt);
803 if(err < 0)
804 {
805 fprintf(stderr, "fat_flush_fat() - Couldn't write"
806 " sector (%d)\n", i + bpb->bpb_rsvdseccnt);
807 return -1;
808 }
809 err = write_block(sec, i + bpb->bpb_rsvdseccnt + fatsz);
810 if(err < 0)
811 {
812 fprintf(stderr, "fat_flush_fat() - Couldn't write"
813 " sector (%d)\n", i + bpb->bpb_rsvdseccnt + fatsz);
814 return -1;
815 }
816 fat_cache_dirty[i] = 0;
817 }
818 }
819
820 fat_getcurrdostime(&d, &t, &m);
821 return 0;
822}
823
824unsigned int fat_getcurrdostime(unsigned short *dosdate,
825 unsigned short *dostime,
826 unsigned char *dostenth)
827{
828 struct timeb tb;
829 struct tm *tm;
830
831 ftime(&tb);
832 tm = localtime(&tb.time);
833
834 *dosdate = ((tm->tm_year - 80) << 9) |
835 ((tm->tm_mon + 1) << 5) |
836 (tm->tm_mday);
837
838 *dostime = (tm->tm_hour << 11) |
839 (tm->tm_min << 5) |
840 (tm->tm_sec >> 1);
841
842 *dostenth = (tm->tm_sec & 1) * 100 + tb.millitm / 10;
843 return 0;
844}
845
846int fat_create_root_dir(struct bpb *bpb)
847{
848 unsigned char buf[BLOCK_SIZE];
849 int fatsz;
850 int sec;
851 int res;
852 int i;
853 unsigned short dosdate;
854 unsigned short dostime;
855 unsigned char dostenth;
856 int num_root_sectors;
857
858 fatsz = fat_get_fatsize(bpb);
859
860 sec = bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz;
861
862 memset(buf, 0, sizeof(buf));
863
864 strncpy(&buf[FATDIR_NAME], bpb->bs_vollab, 11);
865 buf[FATDIR_ATTR] = FAT_ATTR_VOLUME_ID;
866 buf[FATDIR_NTRES] = 0;
867
868 fat_getcurrdostime(&dosdate, &dostime, &dostenth);
869 buf[FATDIR_WRTDATE] = dosdate & 0xff;
870 buf[FATDIR_WRTDATE+1] = dosdate >> 8;
871 buf[FATDIR_WRTTIME] = dostime & 0xff;
872 buf[FATDIR_WRTTIME+1] = dostime >> 8;
873
874 printf("Writing rootdir to sector %d...\n", sec);
875
876 res = write_block(buf, sec);
877 if(res < 0)
878 {
879 fprintf(stderr, "fat_create_root_dir() - Couldn't write sector (%d)\n",
880 sec);
881 return -1;
882 }
883
884 printf("Clearing the rest of the root dir.\n");
885 sec++;
886 num_root_sectors = bpb->bpb_rootentcnt * 32 / bpb->bpb_bytspersec;
887 memset(buf, 0, BLOCK_SIZE);
888
889 for(i = 1;i < num_root_sectors;i++)
890 {
891 if(write_block(buf, sec++) < 0)
892 {
893 fprintf(stderr, "fat_create_root_dir() - "
894 " Couldn't write sector (%d)\n", sec);
895 return -1;
896 }
897 }
898
899 return 0;
900}
901
902int fat_get_next_cluster(struct bpb *bpb, unsigned int cluster)
903{
904 int next_cluster = fat_read_entry(bpb, cluster);
905
906 if(fat_last_cluster_in_chain(bpb, next_cluster))
907 return 0;
908 else
909 return next_cluster;
910}
911
912int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir,
913 struct fat_direntry *de)
914{
915 unsigned char buf[BLOCK_SIZE];
916 unsigned char *eptr;
917 int i;
918 int err;
919 unsigned int sec;
920 unsigned int sec_cnt;
921 int need_to_update_last_empty_marker = 0;
922 int is_rootdir = (currdir == 0);
923 int done = 0;
924 unsigned char firstbyte;
925
926 if(is_rootdir)
927 {
928 sec = fat_get_rootdir_sector(bpb);
929 }
930 else
931 {
932 sec = fat_first_sector_of_cluster(bpb, currdir);
933 }
934
935 sec_cnt = 0;
936
937 while(!done)
938 {
939 /* The root dir has a fixed size */
940 if(is_rootdir)
941 {
942 if(sec_cnt >= bpb->bpb_rootentcnt * 32 / bpb->bpb_bytspersec)
943 {
944 /* We have reached the last sector of the root dir */
945 if(need_to_update_last_empty_marker)
946 {
947 /* Since the directory is full, there is no room for
948 a marker, so we just exit */
949 return 0;
950 }
951 else
952 {
953 fprintf(stderr, "fat_add_dir_entry() -"
954 " Root dir is full\n");
955 return -1;
956 }
957 }
958 }
959 else
960 {
961 if(sec_cnt >= bpb->bpb_secperclus)
962 {
963 /* We have reached the end of this cluster */
964 printf("Moving to the next cluster...");
965 currdir = fat_get_next_cluster(bpb, currdir);
966 printf("new cluster is %d\n", currdir);
967
968 if(!currdir)
969 {
970 /* This was the last in the chain,
971 we have to allocate a new cluster */
972 /* TODO */
973 }
974 }
975 }
976
977 printf("Reading sector %d...\n", sec);
978 /* Read the next sector in the current dir */
979 err = read_block(buf, sec);
980 if(err < 0)
981 {
982 fprintf(stderr, "fat_add_dir_entry() - Couldn't read dir sector"
983 " (error code %i)\n", err);
984 return -1;
985 }
986
987 if(need_to_update_last_empty_marker)
988 {
989 /* All we need to do is to set the first entry to 0 */
990 printf("Clearing the first entry in sector %d\n", sec);
991 buf[0] = 0;
992 done = 1;
993 }
994 else
995 {
996 /* Look for a free slot */
997 for(i = 0;i < BLOCK_SIZE;i+=32)
998 {
999 firstbyte = buf[i];
1000 if(firstbyte == 0xe5 || firstbyte == 0)
1001 {
1002 printf("Found free slot at entry %d in sector %d\n",
1003 i/32, sec);
1004 eptr = &buf[i];
1005 memset(eptr, 0, 32);
1006 strncpy(&eptr[FATDIR_NAME], de->name, 11);
1007 eptr[FATDIR_ATTR] = de->attr;
1008 eptr[FATDIR_NTRES] = 0;
1009
1010 eptr[FATDIR_CRTTIMETENTH] = de->crttimetenth;
1011 eptr[FATDIR_CRTDATE] = de->crtdate & 0xff;
1012 eptr[FATDIR_CRTDATE+1] = de->crtdate >> 8;
1013 eptr[FATDIR_CRTTIME] = de->crttime & 0xff;
1014 eptr[FATDIR_CRTTIME+1] = de->crttime >> 8;
1015
1016 eptr[FATDIR_WRTDATE] = de->wrtdate & 0xff;
1017 eptr[FATDIR_WRTDATE+1] = de->wrtdate >> 8;
1018 eptr[FATDIR_WRTTIME] = de->wrttime & 0xff;
1019 eptr[FATDIR_WRTTIME+1] = de->wrttime >> 8;
1020
1021 eptr[FATDIR_FILESIZE] = de->filesize & 0xff;
1022 eptr[FATDIR_FILESIZE+1] = (de->filesize >> 8) & 0xff;
1023 eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff;
1024 eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff;
1025
1026 /* Advance the last_empty_entry marker */
1027 if(firstbyte == 0)
1028 {
1029 i += 32;
1030 if(i < BLOCK_SIZE)
1031 {
1032 buf[i] = 0;
1033 /* We are done */
1034 done = 1;
1035 }
1036 else
1037 {
1038 /* We must fill in the first entry
1039 in the next sector */
1040 need_to_update_last_empty_marker = 1;
1041 }
1042 }
1043
1044 err = write_block(buf, sec);
1045 if(err < 0)
1046 {
1047 fprintf(stderr, "fat_add_dir_entry() - "
1048 " Couldn't write dir"
1049 " sector (error code %i)\n", err);
1050 return -1;
1051 }
1052 break;
1053 }
1054 }
1055 }
1056 sec++;
1057 sec_cnt++;
1058 }
1059
1060 return 0;
1061}
1062
1063unsigned char fat_char2dos(unsigned char c)
1064{
1065 switch(c)
1066 {
1067 case 0xe5: /* Special kanji character */
1068 c = 0x05;
1069 break;
1070 case 0x22:
1071 case 0x2a:
1072 case 0x2b:
1073 case 0x2c:
1074 case 0x2e:
1075 case 0x3a:
1076 case 0x3b:
1077 case 0x3c:
1078 case 0x3d:
1079 case 0x3e:
1080 case 0x3f:
1081 case 0x5b:
1082 case 0x5c:
1083 case 0x5d:
1084 case 0x7c:
1085 /* Illegal name */
1086 c = 0;
1087 break;
1088
1089 default:
1090 if(c < 0x20)
1091 {
1092 /* Illegal name */
1093 c = 0;
1094 }
1095 break;
1096 }
1097 return c;
1098}
1099
1100int fat_create_dos_name(unsigned char *name, unsigned char *newname)
1101{
1102 unsigned char n[12];
1103 unsigned char c;
1104 int i;
1105 char *ext;
1106
1107 if(strlen(name) > 12)
1108 {
1109 return -1;
1110 }
1111
1112 strcpy(n, name);
1113
1114 ext = strchr(n, '.');
1115 if(ext)
1116 {
1117 *ext++ = 0;
1118 }
1119
1120 /* The file name is either empty, or there was only an extension.
1121 In either case it is illegal. */
1122 if(n[0] == 0)
1123 {
1124 return -1;
1125 }
1126
1127 /* Name part */
1128 for(i = 0;n[i] && (i < 8);i++)
1129 {
1130 c = fat_char2dos(n[i]);
1131 if(c)
1132 {
1133 newname[i] = toupper(c);
1134 }
1135 }
1136 while(i < 8)
1137 {
1138 newname[i++] = ' ';
1139 }
1140
1141 /* Extension part */
1142 for(i = 0;ext && ext[i] && (i < 3);i++)
1143 {
1144 c = fat_char2dos(ext[i]);
1145 if(c)
1146 {
1147 newname[8+i] = toupper(c);
1148 }
1149 }
1150 while(i < 3)
1151 {
1152 newname[8+i++] = ' ';
1153 }
1154 return 0;
1155}
1156
1157int fat_create_dir(struct bpb *bpb, unsigned int currdir, char *name)
1158{
1159 struct fat_direntry de;
1160 int err;
1161
1162 printf("fat_create_file()\n");
1163 memset(&de, 0, sizeof(struct fat_direntry));
1164 if(fat_create_dos_name(name, de.name) < 0)
1165 {
1166 fprintf(stderr, "fat_create_file() - Illegal file name (%s)\n", name);
1167 return -1;
1168 }
1169
1170 fat_getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth);
1171 de.wrtdate = de.crtdate;
1172 de.wrttime = de.crttime;
1173 de.filesize = 0;
1174 de.attr = FAT_ATTR_DIRECTORY;
1175
1176 err = fat_add_dir_entry(bpb, currdir, &de);
1177 return 0;
1178}
1179
1180int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name)
1181{
1182 struct fat_direntry de;
1183 int err;
1184
1185 printf("fat_create_file()\n");
1186 memset(&de, 0, sizeof(struct fat_direntry));
1187 if(fat_create_dos_name(name, de.name) < 0)
1188 {
1189 fprintf(stderr, "fat_create_file() - Illegal file name (%s)\n", name);
1190 return -1;
1191 }
1192 fat_getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth);
1193 de.wrtdate = de.crtdate;
1194 de.wrttime = de.crttime;
1195 de.filesize = 0;
1196
1197 err = fat_add_dir_entry(bpb, currdir, &de);
1198 return err;
1199}
1200
1201void fat_fill_direntry(struct fat_direntry *de, char *buf)
1202{
1203 memset(de, 0, sizeof(struct fat_direntry));
1204
1205 strncpy(de->name, &buf[FATDIR_NAME], 11);
1206 de->attr = buf[FATDIR_ATTR];
1207 de->crttimetenth = buf[FATDIR_CRTTIMETENTH];
1208 de->crtdate = buf[FATDIR_CRTDATE] | (buf[FATDIR_CRTDATE+1] << 8);
1209 de->crttime = buf[FATDIR_CRTTIME] | (buf[FATDIR_CRTTIME+1] << 8);
1210 de->wrtdate = buf[FATDIR_WRTDATE] | (buf[FATDIR_WRTDATE+1] << 8);
1211 de->wrttime = buf[FATDIR_WRTTIME] | (buf[FATDIR_WRTTIME+1] << 8);
1212
1213 de->filesize = buf[FATDIR_FILESIZE] |
1214 (buf[FATDIR_FILESIZE+1] << 8) |
1215 (buf[FATDIR_FILESIZE+2] << 16) |
1216 (buf[FATDIR_FILESIZE+3] << 24);
1217}
1218
1219int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir)
1220{
1221 int is_rootdir = (currdir == 0);
1222 unsigned int sec;
1223 int err;
1224
1225 if(is_rootdir)
1226 {
1227 sec = fat_get_rootdir_sector(bpb);
1228 }
1229 else
1230 {
1231 sec = fat_first_sector_of_cluster(bpb, currdir);
1232 }
1233
1234 /* Read the first sector in the current dir */
1235 err = read_block(ent->cached_buf, sec);
1236 if(err < 0)
1237 {
1238 fprintf(stderr, "fat_getfirst() - Couldn't read dir sector"
1239 " (error code %i)\n", err);
1240 return -1;
1241 }
1242
1243 ent->entry = 0;
1244 ent->cached_sec = sec;
1245 ent->num_sec = 0;
1246 return 0;
1247}
1248
1249int fat_getnext(struct bpb *bpb, struct fat_dirent *ent,
1250 struct fat_direntry *entry)
1251{
1252 int done = 0;
1253 int i;
1254 int err;
1255 unsigned char firstbyte;
1256
1257 while(!done)
1258 {
1259 /* Look for a free slot */
1260 for(i = ent->entry;i < BLOCK_SIZE/32;i++)
1261 {
1262 firstbyte = ent->cached_buf[i*32];
1263 if(firstbyte == 0xe5)
1264 {
1265 continue;
1266 }
1267
1268 if(firstbyte == 0)
1269 {
1270 return -1;
1271 }
1272
1273 fat_fill_direntry(entry, &ent->cached_buf[i*32]);
1274 done = 1;
1275 break;
1276 }
1277
1278 /* Next sector? */
1279 if(i >= BLOCK_SIZE/32)
1280 {
1281 ent->num_sec++;
1282 ent->cached_sec++;
1283
1284 /* Do we need to advance one cluster? */
1285 if(ent->num_sec >= bpb->bpb_secperclus)
1286 {
1287 ent->num_sec = 0;
1288 ent->cached_sec = fat_get_next_cluster(
1289 bpb, fat_sec2cluster(bpb, ent->cached_sec));
1290 if(!ent->cached_sec)
1291 {
1292 printf("End of cluster chain.\n");
1293 return -1;
1294 }
1295 }
1296
1297 /* Read the next sector */
1298 err = read_block(ent->cached_buf, ent->cached_sec);
1299 if(err < 0)
1300 {
1301 fprintf(stderr, "fat_getnext() - Couldn't read dir sector"
1302 " (error code %i)\n", err);
1303 return -1;
1304 }
1305
1306 i = 0;
1307 }
1308 else
1309 {
1310 i++;
1311 }
1312 ent->entry = i;
1313 }
1314 return 0;
1315}
diff --git a/firmware/fat.h b/firmware/fat.h
new file mode 100644
index 0000000000..f1dc8dc5a0
--- /dev/null
+++ b/firmware/fat.h
@@ -0,0 +1,154 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef FAT_H
21#define FAT_H
22
23#define FATTYPE_FAT12 0
24#define FATTYPE_FAT16 1
25#define FATTYPE_FAT32 2
26
27#define BS_JMPBOOT 0
28#define BS_OEMNAME 3
29#define BPB_BYTSPERSEC 11
30#define BPB_SECPERCLUS 13
31#define BPB_RSVDSECCNT 14
32#define BPB_NUMFATS 16
33#define BPB_ROOTENTCNT 17
34#define BPB_TOTSEC16 19
35#define BPB_MEDIA 21
36#define BPB_FATSZ16 22
37#define BPB_SECPERTRK 24
38#define BPB_NUMHEADS 26
39#define BPB_HIDDSEC 28
40#define BPB_TOTSEC32 32
41
42#define BS_DRVNUM 36
43#define BS_RESERVED1 37
44#define BS_BOOTSIG 38
45#define BS_VOLID 39
46#define BS_VOLLAB 43
47#define BS_FILSYSTYPE 54
48
49#define BPB_FATSZ32 36
50
51#define BPB_LAST_WORD 510
52
53#define MIN(a,b) (((a) < (b))?(a):(b)))
54
55struct bpb
56{
57 char bs_oemname[9]; /* OEM string, ending with \0 */
58 int bpb_bytspersec; /* Bytes per sectory, typically 512 */
59 int bpb_secperclus; /* Sectors per cluster */
60 int bpb_rsvdseccnt; /* Number of reserved sectors */
61 int bpb_numfats; /* Number of FAT structures, typically 2 */
62 int bpb_rootentcnt; /* Number of dir entries in the root */
63 int bpb_totsec16; /* Number of sectors on the volume (old 16-bit) */
64 int bpb_media; /* Media type (typically 0xf0 or 0xf8) */
65 int bpb_fatsz16; /* Number of used sectors per FAT structure */
66 int bpb_secpertrk; /* Number of sectors per track */
67 int bpb_numheads; /* Number of heads */
68 int bpb_hiddsec; /* Hidden sectors before the volume */
69 unsigned int bpb_totsec32; /* Number of sectors on the volume
70 (new 32-bit) */
71 /**** FAT12/16 specific *****/
72 int bs_drvnum; /* Drive number */
73 int bs_bootsig; /* Is 0x29 if the following 3 fields are valid */
74 unsigned int bs_volid; /* Volume ID */
75 char bs_vollab[12]; /* Volume label, 11 chars plus \0 */
76 char bs_filsystype[9]; /* File system type, 8 chars plus \0 */
77
78 /**** FAT32 specific *****/
79 int bpb_fatsz32;
80
81 int last_word; /* Must be 0xaa55 */
82
83 int fat_type; /* What type of FAT is this? */
84};
85
86#define FAT_ATTR_READ_ONLY 0x01
87#define FAT_ATTR_HIDDEN 0x02
88#define FAT_ATTR_SYSTEM 0x04
89#define FAT_ATTR_VOLUME_ID 0x08
90#define FAT_ATTR_DIRECTORY 0x10
91#define FAT_ATTR_ARCHIVE 0x20
92#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \
93 FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID)
94
95
96#define FATDIR_NAME 0
97#define FATDIR_ATTR 11
98#define FATDIR_NTRES 12
99#define FATDIR_CRTTIMETENTH 13
100#define FATDIR_CRTTIME 14
101#define FATDIR_CRTDATE 16
102#define FATDIR_LSTACCDATE 18
103#define FATDIR_FSTCLUSHI 20
104#define FATDIR_WRTTIME 22
105#define FATDIR_WRTDATE 24
106#define FATDIR_FSTCLUSLO 26
107#define FATDIR_FILESIZE 28
108
109struct fat_direntry
110{
111 unsigned char name[12]; /* Name plus \0 */
112 unsigned short attr; /* Attributes */
113 unsigned char crttimetenth; /* Millisecond creation
114 time stamp (0-199) */
115 unsigned short crttime; /* Creation time */
116 unsigned short crtdate; /* Creation date */
117 unsigned short lstaccdate; /* Last access date */
118 unsigned short fstclushi; /* High word of first cluster
119 (0 for FAT12/16) */
120 unsigned short wrttime; /* Last write time */
121 unsigned short wrtdate; /* Last write date */
122 unsigned short fstcluslo; /* Low word of first cluster */
123 unsigned int filesize; /* File size in bytes */
124};
125
126struct fat_context
127{
128 unsigned int curr_dir_sec; /* Current directory sector */
129
130};
131
132struct disk_info
133{
134 int num_sectors;
135 int sec_per_track;
136 int num_heads;
137 unsigned int hidden_sectors;
138};
139
140struct fat_dirent
141{
142 int entry;
143 unsigned int cached_sec;
144 unsigned int num_sec;
145 char cached_buf[BLOCK_SIZE];
146};
147
148int fat_format(struct disk_info *di, char *vol_name);
149int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name);
150int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir);
151int fat_getnext(struct bpb *bpb, struct fat_dirent *ent,
152 struct fat_direntry *entry);
153
154#endif
diff --git a/firmware/key.h b/firmware/key.h
new file mode 100644
index 0000000000..13d41dbf1e
--- /dev/null
+++ b/firmware/key.h
@@ -0,0 +1,44 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef __key_h__
21#define __key_h__
22
23#include <sh7034.h>
24#include <system.h>
25
26#define key_released(key) \
27 (key_released_##key ())
28#define key_pressed(key) \
29 (!(key_released_##key ()))
30
31static inline int key_released_ON (void)
32 { return (QI(PADR+1)&(1<<5)); }
33static inline int key_released_STOP (void)
34 { return (QI(PADR+0)&(1<<3)); }
35static inline int key_released_MINUS (void)
36 { return (QI(PCDR+0)&(1<<0)); }
37static inline int key_released_MENU (void)
38 { return (QI(PCDR+0)&(1<<1)); }
39static inline int key_released_PLUS (void)
40 { return (QI(PCDR+0)&(1<<2)); }
41static inline int key_released_PLAY (void)
42 { return (QI(PCDR+0)&(1<<3)); }
43
44#endif
diff --git a/firmware/lcd.c b/firmware/lcd.c
new file mode 100644
index 0000000000..5563bbe881
--- /dev/null
+++ b/firmware/lcd.c
@@ -0,0 +1,135 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "lcd.h"
21
22void lcd_data (int data)
23 { lcd_byte (data,1); }
24
25void lcd_instruction (int instruction)
26 { lcd_byte (instruction,0); }
27
28void lcd_zero (int length)
29 { length *= 8; while (--length >= 0) lcd_data (0); }
30
31void lcd_fill (int data,int length)
32 { length *= 8; while (--length >= 0) lcd_data (data); }
33
34void lcd_copy (void *data,int count)
35 { while (--count >= 0) lcd_data (*((char *)data)++); }
36
37
38#ifdef JBP
39# ifndef JBP_OLD
40
41static char const lcd_ascii[] =
42 {
43/*****************************************************************************************/
44/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
45/* ************************************************************************************/
46/* 0x */ 0x00,0x01,0x02,0x03,0x00,0x00,0x00,0x00,0x04,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
47/* 1x */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
48/* 2x */ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
49/* 3x */ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
50/* 4x */ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
51/* 5x */ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
52/* 6x */ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
53/* 7x */ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x20,0x20,0x20,0x20,0x20,
54/* 8x */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
55/* 9x */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
56/* Ax */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
57/* Bx */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
58/* Cx */ 0x41,0x41,0x41,0x41,0x41,0x41,0x20,0x43,0x45,0x45,0x45,0x45,0x49,0x49,0x49,0x49,
59/* Dx */ 0x44,0x4E,0x4F,0x4F,0x4F,0x4F,0x4F,0x20,0x20,0x55,0x55,0x55,0x55,0x59,0x20,0x20,
60/* Ex */ 0x61,0x61,0x61,0x61,0x61,0x61,0x20,0x63,0x65,0x65,0x65,0x65,0x69,0x69,0x69,0x69,
61/* Fx */ 0x64,0x6E,0x6F,0x6F,0x6F,0x6F,0x6F,0x20,0x20,0x75,0x75,0x75,0x75,0x79,0x79,0x79
62/******/
63 };
64
65# else
66
67static char const lcd_ascii[] =
68 {
69/*****************************************************************************************/
70/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
71/* ************************************************************************************/
72/* 0x */ 0x00,0x01,0x02,0x03,0x00,0x00,0x00,0x00,0x85,0x89,0x00,0x00,0x00,0x00,0x00,0x00,
73/* 1x */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
74/* 2x */ 0x24,0x25,0x26,0x37,0x06,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,
75/* 3x */ 0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,
76/* 4x */ 0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,
77/* 5x */ 0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0xA9,0x33,0xCE,0x00,0x15,
78/* 6x */ 0x00,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,
79/* 7x */ 0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x24,0x24,0x24,0x24,0x24,
80/* 8x */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,
81/* 9x */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,
82/* Ax */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,
83/* Bx */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,
84/* Cx */ 0x45,0x45,0x45,0x45,0x45,0x45,0x24,0x47,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D,
85/* Dx */ 0x48,0x52,0x53,0x53,0x53,0x53,0x53,0x24,0x24,0x59,0x59,0x59,0x59,0x5D,0x24,0x24,
86/* Ex */ 0x65,0x65,0x65,0x65,0x65,0x65,0x24,0x67,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D,
87/* Fx */ 0x73,0x72,0x73,0x73,0x73,0x73,0x73,0x24,0x24,0x79,0x79,0x79,0x79,0x7D,0x24,0x7D
88/******/
89 };
90
91# endif
92
93void lcd_puts (char const *string)
94 {
95 while (*string)
96 lcd_data (LCD_ASCII(*string++));
97 }
98
99void lcd_putns (char const *string,int n)
100 {
101 while (n--)
102 lcd_data (LCD_ASCII(*string++));
103 }
104
105void lcd_putc (int character)
106 {
107 lcd_data (LCD_ASCII(character));
108 }
109
110void lcd_pattern (int which,char const *pattern,int count)
111 {
112 lcd_instruction (LCD_PRAM|which);
113 lcd_copy ((void *)pattern,count);
114 }
115
116#else
117# error "JBR : FIX ME"
118#endif
119
120void lcd_puthex (unsigned int value,int digits)
121 {
122 switch (digits)
123 {
124 case 8:
125 lcd_puthex (value >> 16,4);
126 case 4:
127 lcd_puthex (value >> 8,2);
128 case 2:
129 lcd_puthex (value >> 4,1);
130 case 1:
131 value &= 15;
132 lcd_putc (value+((value < 10) ? '0' : ('A'-10)));
133 }
134 }
135
diff --git a/firmware/lcd.h b/firmware/lcd.h
new file mode 100644
index 0000000000..03c459c303
--- /dev/null
+++ b/firmware/lcd.h
@@ -0,0 +1,263 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef __LCD_H__
21#define __LCD_H__
22
23#include <sh7034.h>
24#include <system.h>
25
26#define LCDR (PBDR+1)
27
28/* PA14 : /LCD-BL --- backlight */
29#define LCD_BL (14-8)
30
31#ifdef JBP /* JukeBox MP3 Player - AJB6K, AJBS20 */
32# define LCD_DS +1 // PB0 = 1 --- 0001 --- LCD-DS
33# define LCD_CS +2 // PB1 = 1 --- 0010 --- /LCD-CS
34# define LCD_SD +4 // PB2 = 1 --- 0100 --- LCD-SD
35# define LCD_SC +8 // PB3 = 1 --- 1000 --- LCD-SC
36# ifndef JBP_OLD
37# define LCD_CONTRAST_SET ((char)0x50)
38# define LCD_CRAM ((char)0x80) /* Characters */
39# define LCD_PRAM ((char)0xC0) /* Patterns */
40# define LCD_IRAM ((char)0x40) /* Icons */
41# else
42# define LCD_CONTRAST_SET ((char)0xA8)
43# define LCD_CRAM ((char)0xB0) /* Characters */
44# define LCD_PRAM ((char)0x80) /* Patterns */
45# define LCD_IRAM ((char)0xE0) /* Icons */
46# endif
47# define LCD_ASCII(c) (lcd_ascii[(c)&255])
48# define LCD_CURSOR(x,y) ((char)(LCD_CRAM+((y)*16+(x))))
49# define LCD_ICON(i) ((char)(LCD_IRAM+i))
50# define LCD_ICON_BATTERY 0
51# define LCD_BATTERY_FRAME 0x02
52# define LCD_BATTERY_BAR1 0x08
53# define LCD_BATTERY_BAR2 0x04
54# define LCD_BATTERY_BAR3 0x10
55# define LCD_ICON_USB 2
56# define LCD_USB_LOGO 0xFF
57# define LCD_ICON_PLAY 3
58# define LCD_PLAY_ICON 0xFF
59# define LCD_ICON_RECORD 4
60# define LCD_RECORD_ICON 0x10
61# define LCD_ICON_STOP 5
62# define LCD_STOP_ICON 0x0F
63# define LCD_ICON_AUDIO 5
64# define LCD_AUDIO_ICON 0xF0
65# define LCD_ICON_REVERSE 6
66# define LCD_REVERSE_ICON 0xFF
67# define LCD_ICON_SINGLE 7
68# define LCD_SINGLE_ICON 0xFF
69# define LCD_ICON_VOLUME0 9
70# define LCD_VOLUME_ICON 0x04
71# define LCD_VOLUME_BAR1 0x02
72# define LCD_VOLUME_BAR2 0x01
73# define LCD_ICON_VOLUME1 10
74# define LCD_VOLUME_BAR3 0x08
75# define LCD_VOLUME_BAR4 0x04
76# define LCD_VOLUME_BAR5 0x01
77# define LCD_ICON_PARAM 10
78# define LCD_PARAM_SYMBOL 0xF0
79#endif
80
81#ifdef JBR /* JukeBox MP3 Recorder - AJBR --- FIXME */
82# error "JBR : FIX ME"
83#endif
84
85
86/*
87 * About /CS,DS,SC,SD
88 * ------------------
89 *
90 * LCD on JBP and JBR uses a SPI protocol to receive orders (SDA and SCK lines)
91 *
92 * - /CS -> Chip Selection line :
93 * 0 : LCD chipset is activated.
94 * - DS -> Data Selection line, latched at the rising edge
95 * of the 8th serial clock (*) :
96 * 0 : instruction register,
97 * 1 : data register;
98 * - SC -> Serial Clock line (SDA).
99 * - SD -> Serial Data line (SCK), latched at the rising edge
100 * of each serial clock (*).
101 *
102 * _ _
103 * /CS \ /
104 * \______________________________________________________/
105 * _____ ____ ____ ____ ____ ____ ____ ____ ____ _____
106 * SD \/ D7 \/ D6 \/ D5 \/ D4 \/ D3 \/ D2 \/ D1 \/ D0 \/
107 * _____/\____/\____/\____/\____/\____/\____/\____/\____/\_____
108 *
109 * _____ _ _ _ _ _ _ _ ________
110 * SC \ * \ * \ * \ * \ * \ * \ * \ *
111 * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
112 * _ _________________________________________________________
113 * DS \/
114 * _/\_________________________________________________________
115 *
116 */
117
118/*
119 * The only way to do logical operations in an atomic way
120 * on SH1 is using :
121 *
122 * or.b/and.b/tst.b/xor.b #imm,@(r0,gbr)
123 *
124 * but GCC doesn't generate them at all so some assembly
125 * codes are needed here.
126 *
127 * The Global Base Register gbr is expected to be zero
128 * and r0 is the address of one register in the on-chip
129 * peripheral module.
130 *
131 */
132
133static inline void lcd_start (void)
134 /*
135 * Enter a LCD session :
136 *
137 * QI(LCDR) &= ~(LCD_CS|LCD_DS|LCD_SD|LCD_SC);
138 */
139 {
140 asm
141 ("and.b\t%0,@(r0,gbr)"
142 :
143 : /* %0 */ "I"(~(LCD_CS|LCD_DS|LCD_SD|LCD_SC)),
144 /* %1 */ "z"(LCDR));
145 }
146
147static inline void lcd_stop (void)
148 /*
149 * Leave a LCD session :
150 *
151 * QI(LCDR) |= LCD_CS|LCD_RS|LCD_SD|LCD_SC;
152 */
153 {
154 asm
155 ("or.b\t%0,@(r0,gbr)"
156 :
157 : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC),
158 /* %1 */ "z"(LCDR));
159 }
160
161static inline void lcd_byte (int byte,int rs)
162 /*
163 * char j = 0x80;
164 * if (rs)
165 * do
166 * {
167 * QI(LCDR) &= ~(LCD_SC|LCD_SD);
168 * if (j & byte)
169 * QI(LCDR) |= LCD_SD;
170 * QI(LCDR) |= LCD_SC|LCD_DS;
171 * }
172 * while ((unsigned char)j >>= 1);
173 * else
174 * do
175 * {
176 * QI(LCDR) &= ~(LCD_SC|LCD_SD|LCD_DS);
177 * if (j & byte)
178 * QI(LCDR) |= LCD_SD;
179 * QI(LCDR) |= LCD_SC;
180 * }
181 * while ((unsigned char)j >>= 1);
182 */
183 {
184 if (rs > 0)
185 asm
186 ("shll8\t%0\n"
187 "0:\n\t"
188 "and.b\t%2,@(r0,gbr)\n\t"
189 "shll\t%0\n\t"
190 "bf\t1f\n\t"
191 "or.b\t%3,@(r0,gbr)\n"
192 "1:\n\t"
193 "or.b\t%4,@(r0,gbr)\n"
194 "add\t#-1,%1\n\t"
195 "cmp/pl\t%1\n\t"
196 "bt\t0b"
197 :
198 : /* %0 */ "r"(((unsigned)byte)<<16),
199 /* %1 */ "r"(8),
200 /* %2 */ "I"(~(LCD_SC|LCD_SD)),
201 /* %3 */ "I"(LCD_SD),
202 /* %4 */ "I"(LCD_SC|LCD_DS),
203 /* %5 */ "z"(LCDR));
204 else
205 asm
206 ("shll8\t%0\n"
207 "0:\n\t"
208 "and.b\t%2,@(r0,gbr)\n\t"
209 "shll\t%0\n\t"
210 "bf\t1f\n\t"
211 "or.b\t%3,@(r0,gbr)\n"
212 "1:\n\t"
213 "or.b\t%4,@(r0,gbr)\n"
214 "add\t#-1,%1\n\t"
215 "cmp/pl\t%1\n\t"
216 "bt\t0b"
217 :
218 : /* %0 */ "r"(((unsigned)byte)<<16),
219 /* %1 */ "r"(8),
220 /* %2 */ "I"(~(LCD_SC|LCD_DS|LCD_SD)),
221 /* %3 */ "I"(LCD_SD),
222 /* %4 */ "I"(LCD_SC),
223 /* %5 */ "z"(LCDR));
224 }
225
226extern void lcd_data (int data);
227extern void lcd_instruction (int instruction);
228extern void lcd_zero (int length);
229extern void lcd_fill (int data,int length);
230extern void lcd_copy (void *data,int count);
231
232#ifdef JBP
233
234extern void lcd_puts (char const *string);
235extern void lcd_putns (char const *string,int n);
236extern void lcd_putc (int character);
237extern void lcd_puthex (unsigned int value,int digits);
238
239extern void lcd_pattern (int which,char const *pattern,int count);
240
241static inline void lcd_goto (int x,int y)
242 { lcd_instruction (LCD_CURSOR(x,y)); }
243
244#endif
245
246#ifdef JBR
247# error "JBR : FIX ME"
248#endif
249
250/*** BACKLIGHT ***/
251
252static inline void lcd_toggle_backlight (void)
253 { toggle_bit (LCD_BL,PAIOR); }
254
255static inline void lcd_turn_on_backlight (void)
256 { set_bit (LCD_BL,PAIOR); }
257
258static inline void lcd_turn_off_backlight (void)
259 { clear_bit (LCD_BL,PAIOR); }
260
261/*** ICONS ***/
262
263#endif
diff --git a/firmware/led.c b/firmware/led.c
new file mode 100644
index 0000000000..e8922e7891
--- /dev/null
+++ b/firmware/led.c
@@ -0,0 +1,68 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <led.h>
21
22#define turn_on() \
23 set_bit (LEDB,PBDR+1)
24
25#define turn_off() \
26 clear_bit (LEDB,PBDR+1)
27
28#define start_timer() \
29 set_bit (2,ITUTSTR)
30
31#define stop_timer() \
32 clear_bit (2,ITUTSTR)
33
34#define eoi(subinterrupt) \
35 clear_bit (subinterrupt,ITUTSR2)
36
37#define set_volume(volume) \
38 HI(ITUGRA2) = volume & 0x7FFF
39
40
41void led_set_volume (unsigned short volume)
42 {
43 volume <<= 10;
44 if (volume == 0)
45 led_turn_off ();
46 else if (volume == 0x8000)
47 led_turn_on ();
48 else
49 {
50 set_volume (volume);
51 start_timer ();
52 }
53 }
54
55#pragma interrupt
56void IMIA2 (void)
57 {
58 turn_off ();
59 eoi (0);
60 }
61
62#pragma interrupt
63void OVI2 (void)
64 {
65 turn_on ();
66 eoi (2);
67 }
68
diff --git a/firmware/led.h b/firmware/led.h
new file mode 100644
index 0000000000..0c43a70e74
--- /dev/null
+++ b/firmware/led.h
@@ -0,0 +1,50 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef __LED_H__
21#define __LED_H__
22
23#include <sh7034.h>
24#include <system.h>
25
26#define LEDB 6 /* PB6 : red LED */
27
28static inline void led_turn_off (void)
29 {
30 clear_bit (LEDB,PBDR+1);
31 clear_bit (2,ITUTSTR);
32 }
33
34static inline void led_turn_on (void)
35 {
36 set_bit (LEDB,PBDR+1);
37 set_bit (2,ITUTSTR);
38 }
39
40static inline void led_toggle (void)
41 {
42 toggle_bit (LEDB,PBDR+1);
43 }
44
45extern void led_set_volume (unsigned short volume);
46extern void led_setup (void);
47
48#endif
49
50
diff --git a/firmware/serial.c b/firmware/serial.c
new file mode 100644
index 0000000000..1269083aab
--- /dev/null
+++ b/firmware/serial.c
@@ -0,0 +1,82 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <serial.h>
21#include <lcd.h>
22
23#define TDRE 7 /* transmit data register empty */
24#define RDRF 6 /* receive data register full */
25#define ORER 5 /* overrun error */
26#define FER 4 /* frame error */
27#define PER 3 /* parity error */
28
29static int serial_byte,serial_flag;
30
31void serial_putc (char byte)
32 {
33 static int i = 0;
34 while (!(QI(SCISSR1) & (1<<TDRE)));
35 QI(SCITDR1) = byte;
36 clear_bit (TDRE,SCISSR1);
37 lcd_goto ((i++)%11,1); lcd_putc (byte);
38 }
39
40void serial_puts (char const *string)
41 {
42 int byte;
43 while ((byte = *string++))
44 serial_putc (byte);
45 }
46
47int serial_getc( void )
48 {
49 int byte;
50 while (!serial_flag);
51 byte = serial_byte;
52 serial_flag = 0;
53 serial_putc (byte);
54 return byte;
55 }
56
57void serial_setup (int baudrate)
58 {
59 QI(SCISCR1) =
60 QI(SCISSR1) =
61 QI(SCISMR1) = 0;
62 QI(SCIBRR1) = (PHI/(32*baudrate))-1;
63 QI(SCISCR1) = 0x70;
64 }
65
66#pragma interrupt
67void REI1 (void)
68 {
69 clear_bit (FER,SCISSR1);
70 }
71
72#pragma interrupt
73void RXI1 (void)
74 {
75 serial_byte = QI(SCIRDR1);
76 serial_flag = 1;
77 clear_bit (RDRF,SCISSR1);
78 if (serial_byte == '0')
79 lcd_turn_off_backlight ();
80 if (serial_byte == '1')
81 lcd_turn_on_backlight ();
82 }
diff --git a/firmware/serial.h b/firmware/serial.h
new file mode 100644
index 0000000000..eac02e42e4
--- /dev/null
+++ b/firmware/serial.h
@@ -0,0 +1,31 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef __SERIAL_H__
21#define __SERIAL_H__
22
23#include <sh7034.h>
24#include <system.h>
25
26extern void serial_putc (char);
27extern void serial_puts (char const *);
28extern int serial_getc (void);
29extern void serial_setup (int);
30
31#endif
diff --git a/firmware/sh7034.h b/firmware/sh7034.h
new file mode 100644
index 0000000000..c33b7a91bf
--- /dev/null
+++ b/firmware/sh7034.h
@@ -0,0 +1,167 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef __SH7034_H__
21#define __SH7034_H__
22
23#define GBR 0x00000000
24
25#define SCISMR0 0x05FFFEC0
26#define SCIBRR0 0x05FFFEC1
27#define SCISCR0 0x05FFFEC2
28#define SCITDR0 0x05FFFEC3
29#define SCISSR0 0x05FFFEC4
30#define SCIRDR0 0x05FFFEC5
31#define SCISMR1 0x05FFFEC8
32#define SCIBRR1 0x05FFFEC9
33#define SCISCR1 0x05FFFECA
34#define SCITDR1 0x05FFFECB
35#define SCISSR1 0x05FFFECC
36#define SCIRDR1 0x05FFFECD
37
38#define ADDRA 0x05FFFEE0
39#define ADDRAH 0x05FFFEE0
40#define ADDRAL 0x05FFFEE1
41#define ADDRB 0x05FFFEE2
42#define ADDRBH 0x05FFFEE2
43#define ADDRBL 0x05FFFEE3
44#define ADDRC 0x05FFFEE4
45#define ADDRCH 0x05FFFEE4
46#define ADDRCL 0x05FFFEE5
47#define ADDRD 0x05FFFEE6
48#define ADDRDH 0x05FFFEE6
49#define ADDRDL 0x05FFFEE6
50#define ADCSR 0x05FFFEE8
51#define ADCR 0x05FFFEE9
52
53#define ITUTSTR 0x05FFFF00
54#define ITUTSNC 0x05FFFF01
55#define ITUTMDR 0x05FFFF02
56#define ITUTFCR 0x05FFFF03
57#define ITUTCR0 0x05FFFF04
58#define ITUTIOR0 0x05FFFF05
59#define ITUTIER0 0x05FFFF06
60#define ITUTSR0 0x05FFFF07
61#define ITUTCNT0 0x05FFFF08
62#define ITUGRA0 0x05FFFF0A
63#define ITUGRB0 0x05FFFF0C
64#define ITUTCR1 0x05FFFF0E
65#define ITUTIOR1 0x05FFFF0F
66#define ITUTIER1 0x05FFFF10
67#define ITUTSR1 0x05FFFF11
68#define ITUTCNT1 0x05FFFF12
69#define ITUGRA1 0x05FFFF14
70#define ITUGRB1 0x05FFFF16
71#define ITUTCR2 0x05FFFF18
72#define ITUTIOR2 0x05FFFF19
73#define ITUTIER2 0x05FFFF1A
74#define ITUTSR2 0x05FFFF1B
75#define ITUTCNT2 0x05FFFF1C
76#define ITUGRA2 0x05FFFF1E
77#define ITUGRB2 0x05FFFF20
78#define ITUTCR3 0x05FFFF22
79#define ITUTIOR3 0x05FFFF23
80#define ITUTIER3 0x05FFFF24
81#define ITUTSR3 0x05FFFF25
82#define ITUTCNT3 0x05FFFF26
83#define ITUGRA3 0x05FFFF28
84#define ITUGRB3 0x05FFFF2A
85#define ITUBRA3 0x05FFFF2C
86#define ITUBRB3 0x05FFFF2E
87#define ITUTOCR 0x05FFFF31
88#define ITUTCR4 0x05FFFF32
89#define ITUTIOR4 0x05FFFF33
90#define ITUTIER4 0x05FFFF34
91#define ITUTSR4 0x05FFFF35
92#define ITUTCNT4 0x05FFFF36
93#define ITUGRA4 0x05FFFF38
94#define ITUGRB4 0x05FFFF3A
95#define ITUBRA4 0x05FFFF3C
96#define ITUBRB4 0x05FFFF3E
97
98#define DMACSAR0 0x05FFFF40
99#define DMACDAR0 0x05FFFF44
100#define DMACOR 0x05FFFF48
101#define DMACTCR0 0x05FFFF4A
102#define DMACCHCR0 0x05FFFF4E
103#define DMACSAR1 0x05FFFF50
104#define DMACDAR1 0x05FFFF54
105#define DMACTCR1 0x05FFFF5A
106#define DMACCHCR1 0x05FFFF5E
107#define DMACSAR2 0x05FFFF60
108#define DMACDAR2 0x05FFFF64
109#define DMACTCR2 0x05FFFF6A
110#define DMACCHCR2 0x05FFFF6E
111#define DMACSAR3 0x05FFFF70
112#define DMACDAR3 0x05FFFF74
113#define DMACTCR3 0x05FFFF7A
114#define DMACCHCR3 0x05FFFF7E
115
116#define INTCIPRAB 0x05FFFF84
117#define INTCIPRA 0x05FFFF84
118#define INTCIPRB 0x05FFFF86
119#define INTCIPRCD 0x05FFFF88
120#define INTCIPRC 0x05FFFF88
121#define INTCIPRD 0x05FFFF8A
122#define INTCIPRE 0x05FFFF8C
123#define INTCICR 0x05FFFF8E
124
125#define UBCBAR 0x05FFFF90
126#define UBCBARH 0x05FFFF90
127#define UBCBARL 0x05FFFF92
128#define UBCBAMR 0x05FFFF94
129#define UBCBAMRH 0x05FFFF94
130#define UBCBAMRL 0x05FFFF96
131#define UBCBBR 0x05FFFF98
132
133#define BSCBCR 0x05FFFFA0
134#define BSCWCR1 0x05FFFFA2
135#define BSCWCR2 0x05FFFFA4
136#define BSCWCR3 0x05FFFFA6
137#define BSCDCR 0x05FFFFA8
138#define BSCPCR 0x05FFFFAA
139#define BSCRCR 0x05FFFFAC
140#define BSCRTCSR 0x05FFFFAE
141#define BSCRTCNT 0x05FFFFB0
142#define BSCRTCOR 0x05FFFFB2
143
144#define WDTTCSR 0x05FFFFB8
145#define WDTTCNT 0x05FFFFB9
146#define WDTRSTCSR 0x05FFFFBB
147
148#define SBYCR 0x05FFFFBC
149
150#define PABDR 0x05FFFFC0
151#define PADR 0x05FFFFC0
152#define PBDR 0x05FFFFC2
153#define PABIOR 0x05FFFFC4
154#define PAIOR 0x05FFFFC4
155#define PBIOR 0x05FFFFC6
156#define PACR 0x05FFFFC8
157#define PACR1 0x05FFFFC8
158#define PACR2 0x05FFFFCA
159#define PBCR 0x05FFFFCC
160#define PBCR1 0x05FFFFCC
161#define PBCR2 0x05FFFFCE
162#define PCDR 0x05FFFFD1
163
164#define CASCR 0x05FFFFEE
165
166
167#endif
diff --git a/firmware/start.s b/firmware/start.s
new file mode 100644
index 0000000000..fdc86b2de1
--- /dev/null
+++ b/firmware/start.s
@@ -0,0 +1,41 @@
1!----------------------------------------------------------------------------
2! __________ __ ___.
3! Open \______ \ ____ ____ | | _\_ |__ _______ ___
4! Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5! Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6! Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7! \/ \/ \/ \/ \/
8! $Id$
9!
10! Copyright (C) 2002 by Björn Stenberg
11!
12! All files in this archive are subject to the GNU General Public License.
13! See the file COPYING in the source tree root for full license agreement.
14!
15! This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16! KIND, either express or implied.
17!----------------------------------------------------------------------------
18!
19! note: sh-1 has a "delay cycle" after every branch where you can
20! execute another instruction "for free".
21
22 .file "start.s"
23 .section .text.start
24 .extern _main
25 .extern _vectors
26 .extern _stack
27 .global _start
28 .align 2
29
30_start:
31 mov.l 1f, r1
32 mov.l 3f, r3
33 mov.l 2f, r15
34 jmp @r3
35 ldc r1, vbr
36 nop
37
381: .long _vectors
392: .long _stack
403: .long _main
41 .type _start,@function
diff --git a/firmware/system.c b/firmware/system.c
new file mode 100644
index 0000000000..8e9c7ff692
--- /dev/null
+++ b/firmware/system.c
@@ -0,0 +1,432 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <lcd.h>
21#include <led.h>
22
23#define default_interrupt(name,number) \
24 extern __attribute__((weak,alias("UIE" #number))) void name (void); void UIE##number (void)
25#define reserve_interrupt(number) \
26 void UIE##number (void)
27
28extern void reset_pc (void);
29extern void reset_sp (void);
30
31reserve_interrupt ( 0);
32reserve_interrupt ( 1);
33reserve_interrupt ( 2);
34reserve_interrupt ( 3);
35default_interrupt (GII, 4);
36reserve_interrupt ( 5);
37default_interrupt (ISI, 6);
38reserve_interrupt ( 7);
39reserve_interrupt ( 8);
40default_interrupt (CPUAE, 9);
41default_interrupt (DMAAE, 10);
42default_interrupt (NMI, 11);
43default_interrupt (UB, 12);
44reserve_interrupt ( 13);
45reserve_interrupt ( 14);
46reserve_interrupt ( 15);
47reserve_interrupt ( 16); // TCB #0
48reserve_interrupt ( 17); // TCB #1
49reserve_interrupt ( 18); // TCB #2
50reserve_interrupt ( 19); // TCB #3
51reserve_interrupt ( 20); // TCB #4
52reserve_interrupt ( 21); // TCB #5
53reserve_interrupt ( 22); // TCB #6
54reserve_interrupt ( 23); // TCB #7
55reserve_interrupt ( 24); // TCB #8
56reserve_interrupt ( 25); // TCB #9
57reserve_interrupt ( 26); // TCB #10
58reserve_interrupt ( 27); // TCB #11
59reserve_interrupt ( 28); // TCB #12
60reserve_interrupt ( 29); // TCB #13
61reserve_interrupt ( 30); // TCB #14
62reserve_interrupt ( 31); // TCB #15
63default_interrupt (TRAPA32, 32);
64default_interrupt (TRAPA33, 33);
65default_interrupt (TRAPA34, 34);
66default_interrupt (TRAPA35, 35);
67default_interrupt (TRAPA36, 36);
68default_interrupt (TRAPA37, 37);
69default_interrupt (TRAPA38, 38);
70default_interrupt (TRAPA39, 39);
71default_interrupt (TRAPA40, 40);
72default_interrupt (TRAPA41, 41);
73default_interrupt (TRAPA42, 42);
74default_interrupt (TRAPA43, 43);
75default_interrupt (TRAPA44, 44);
76default_interrupt (TRAPA45, 45);
77default_interrupt (TRAPA46, 46);
78default_interrupt (TRAPA47, 47);
79default_interrupt (TRAPA48, 48);
80default_interrupt (TRAPA49, 49);
81default_interrupt (TRAPA50, 50);
82default_interrupt (TRAPA51, 51);
83default_interrupt (TRAPA52, 52);
84default_interrupt (TRAPA53, 53);
85default_interrupt (TRAPA54, 54);
86default_interrupt (TRAPA55, 55);
87default_interrupt (TRAPA56, 56);
88default_interrupt (TRAPA57, 57);
89default_interrupt (TRAPA58, 58);
90default_interrupt (TRAPA59, 59);
91default_interrupt (TRAPA60, 60);
92default_interrupt (TRAPA61, 61);
93default_interrupt (TRAPA62, 62);
94default_interrupt (TRAPA63, 63);
95default_interrupt (IRQ0, 64);
96default_interrupt (IRQ1, 65);
97default_interrupt (IRQ2, 66);
98default_interrupt (IRQ3, 67);
99default_interrupt (IRQ4, 68);
100default_interrupt (IRQ5, 69);
101default_interrupt (IRQ6, 70);
102default_interrupt (IRQ7, 71);
103default_interrupt (DEI0, 72);
104reserve_interrupt ( 73);
105default_interrupt (DEI1, 74);
106reserve_interrupt ( 75);
107default_interrupt (DEI2, 76);
108reserve_interrupt ( 77);
109default_interrupt (DEI3, 78);
110reserve_interrupt ( 79);
111default_interrupt (IMIA0, 80);
112default_interrupt (IMIB0, 81);
113default_interrupt (OVI0, 82);
114reserve_interrupt ( 83);
115default_interrupt (IMIA1, 84);
116default_interrupt (IMIB1, 85);
117default_interrupt (OVI1, 86);
118reserve_interrupt ( 87);
119default_interrupt (IMIA2, 88);
120default_interrupt (IMIB2, 89);
121default_interrupt (OVI2, 90);
122reserve_interrupt ( 91);
123default_interrupt (IMIA3, 92);
124default_interrupt (IMIB3, 93);
125default_interrupt (OVI3, 94);
126reserve_interrupt ( 95);
127default_interrupt (IMIA4, 96);
128default_interrupt (IMIB4, 97);
129default_interrupt (OVI4, 98);
130reserve_interrupt ( 99);
131default_interrupt (REI0, 100);
132default_interrupt (RXI0, 101);
133default_interrupt (TXI0, 102);
134default_interrupt (TEI0, 103);
135default_interrupt (REI1, 104);
136default_interrupt (RXI1, 105);
137default_interrupt (TXI1, 106);
138default_interrupt (TEI1, 107);
139reserve_interrupt ( 108);
140default_interrupt (ADITI, 109);
141
142void (*vbr[]) (void) __attribute__ ((section (".sram.vbr"))) =
143 {
144 /*** 0-1 Power-on Reset ***/
145
146 reset_pc,reset_sp,
147
148 /*** 2-3 Manual Reset ***/
149
150 reset_pc,reset_sp,
151
152 /*** 4 General Illegal Instruction ***/
153
154 GII,
155
156 /*** 5 Reserved ***/
157
158 UIE5,
159
160 /*** 6 Illegal Slot Instruction ***/
161
162 ISI,
163
164 /*** 7-8 Reserved ***/
165
166 UIE7,UIE8,
167
168 /*** 9 CPU Address Error ***/
169
170 CPUAE,
171
172 /*** 10 DMA Address Error ***/
173
174 DMAAE,
175
176 /*** 11 NMI ***/
177
178 NMI,
179
180 /*** 12 User Break ***/
181
182 UB,
183
184 /*** 13-31 Reserved ***/
185
186 UIE13,UIE14,UIE15,UIE16,UIE17,UIE18,UIE19,UIE20,UIE21,UIE22,UIE23,UIE24,UIE25,UIE26,UIE27,UIE28,UIE29,UIE30,UIE31,
187
188 /*** 32-63 TRAPA #20...#3F ***/
189
190 TRAPA32,TRAPA33,TRAPA34,TRAPA35,TRAPA36,TRAPA37,TRAPA38,TRAPA39,TRAPA40,TRAPA41,TRAPA42,TRAPA43,TRAPA44,TRAPA45,TRAPA46,TRAPA47,TRAPA48,TRAPA49,TRAPA50,TRAPA51,TRAPA52,TRAPA53,TRAPA54,TRAPA55,TRAPA56,TRAPA57,TRAPA58,TRAPA59,TRAPA60,TRAPA61,TRAPA62,TRAPA63,
191
192 /*** 64-71 IRQ0-7 ***/
193
194 IRQ0,IRQ1,IRQ2,IRQ3,IRQ4,IRQ5,IRQ6,IRQ7,
195
196 /*** 72 DMAC0 ***/
197
198 DEI0,
199
200 /*** 73 Reserved ***/
201
202 UIE73,
203
204 /*** 74 DMAC1 ***/
205
206 DEI1,
207
208 /*** 75 Reserved ***/
209
210 UIE75,
211
212 /*** 76 DMAC2 ***/
213
214 DEI2,
215
216 /*** 77 Reserved ***/
217
218 UIE77,
219
220 /*** 78 DMAC3 ***/
221
222 DEI3,
223
224 /*** 79 Reserved ***/
225
226 UIE79,
227
228 /*** 80-82 ITU0 ***/
229
230 IMIA0,IMIB0,OVI0,
231
232 /*** 83 Reserved ***/
233
234 UIE83,
235
236 /*** 84-86 ITU1 ***/
237
238 IMIA1,IMIB1,OVI1,
239
240 /*** 87 Reserved ***/
241
242 UIE87,
243
244 /*** 88-90 ITU2 ***/
245
246 IMIA2,IMIB2,OVI2,
247
248 /*** 91 Reserved ***/
249
250 UIE91,
251
252 /*** 92-94 ITU3 ***/
253
254 IMIA3,IMIB3,OVI3,
255
256 /*** 95 Reserved ***/
257
258 UIE95,
259
260 /*** 96-98 ITU4 ***/
261
262 IMIA4,IMIB4,OVI4,
263
264 /*** 99 Reserved ***/
265
266 UIE99,
267
268 /*** 100-103 SCI0 ***/
269
270 REI0,RXI0,TXI0,TEI0,
271
272 /*** 104-107 SCI1 ***/
273
274 REI1,RXI1,TXI1,TEI1,
275
276 /*** 108 Parity Control Unit ***/
277
278 UIE108,
279
280 /*** 109 AD Converter ***/
281
282 ADITI
283
284 };
285
286
287void system_reboot (void)
288 {
289 cli ();
290
291 asm volatile ("ldc\t%0,vbr" : : "r"(0));
292
293 SI(INTCIPRAB) =
294 SI(INTCIPRCD) = 0;
295 HI(INTCIPRE) =
296 HI(INTCICR) = 0;
297
298 asm volatile ("jmp @%0; mov.l @%1,r15" : : "r"(SI(0)),"r"(4));
299 }
300
301void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */
302 {
303 unsigned int i,n;
304 lcd_stop ();
305 asm volatile ("sts\tpr,%0" : "=r"(n));
306 n = (n - (unsigned)UIE0 - 4)>>2; // get exception or interrupt number
307 lcd_start ();
308 lcd_goto (0,0); lcd_puts ("** UIE00 **");
309 lcd_goto (0,1); lcd_puts ("AT 00000000");
310 lcd_goto (6,0); lcd_puthex (n,2);
311 lcd_goto (3,1); lcd_puthex (pc,8); /* or pc - 4 !? */
312 lcd_stop ();
313
314 while (1)
315 {
316 led_toggle ();
317
318 for (i = 0; i < 240000; ++i);
319 }
320 }
321
322asm (
323 "_UIE0:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
324 "_UIE1:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
325 "_UIE2:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
326 "_UIE3:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
327 "_UIE4:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
328 "_UIE5:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
329 "_UIE6:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
330 "_UIE7:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
331 "_UIE8:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
332 "_UIE9:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
333 "_UIE10:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
334 "_UIE11:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
335 "_UIE12:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
336 "_UIE13:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
337 "_UIE14:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
338 "_UIE15:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
339 "_UIE16:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
340 "_UIE17:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
341 "_UIE18:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
342 "_UIE19:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
343 "_UIE20:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
344 "_UIE21:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
345 "_UIE22:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
346 "_UIE23:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
347 "_UIE24:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
348 "_UIE25:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
349 "_UIE26:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
350 "_UIE27:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
351 "_UIE28:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
352 "_UIE29:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
353 "_UIE30:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
354 "_UIE31:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
355 "_UIE32:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
356 "_UIE33:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
357 "_UIE34:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
358 "_UIE35:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
359 "_UIE36:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
360 "_UIE37:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
361 "_UIE38:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
362 "_UIE39:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
363 "_UIE40:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
364 "_UIE41:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
365 "_UIE42:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
366 "_UIE43:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
367 "_UIE44:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
368 "_UIE45:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
369 "_UIE46:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
370 "_UIE47:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
371 "_UIE48:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
372 "_UIE49:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
373 "_UIE50:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
374 "_UIE51:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
375 "_UIE52:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
376 "_UIE53:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
377 "_UIE54:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
378 "_UIE55:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
379 "_UIE56:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
380 "_UIE57:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
381 "_UIE58:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
382 "_UIE59:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
383 "_UIE60:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
384 "_UIE61:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
385 "_UIE62:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
386 "_UIE63:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
387 "_UIE64:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
388 "_UIE65:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
389 "_UIE66:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
390 "_UIE67:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
391 "_UIE68:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
392 "_UIE69:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
393 "_UIE70:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
394 "_UIE71:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
395 "_UIE72:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
396 "_UIE73:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
397 "_UIE74:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
398 "_UIE75:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
399 "_UIE76:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
400 "_UIE77:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
401 "_UIE78:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
402 "_UIE79:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
403 "_UIE80:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
404 "_UIE81:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
405 "_UIE82:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
406 "_UIE83:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
407 "_UIE84:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
408 "_UIE85:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
409 "_UIE86:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
410 "_UIE87:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
411 "_UIE88:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
412 "_UIE89:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
413 "_UIE90:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
414 "_UIE91:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
415 "_UIE92:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
416 "_UIE93:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
417 "_UIE94:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
418 "_UIE95:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
419 "_UIE96:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
420 "_UIE97:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
421 "_UIE98:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
422 "_UIE99:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
423 "_UIE100:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
424 "_UIE101:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
425 "_UIE102:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
426 "_UIE103:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
427 "_UIE104:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
428 "_UIE105:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
429 "_UIE106:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
430 "_UIE107:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
431 "_UIE108:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\t\n"
432 "_UIE109:\tbsr\t_UIE\n\tmov.l\t@r15+,r4");
diff --git a/firmware/system.h b/firmware/system.h
new file mode 100644
index 0000000000..bacf90ad66
--- /dev/null
+++ b/firmware/system.h
@@ -0,0 +1,267 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef __SYSTEM_H__
21#define __SYSTEM_H__
22#include <sh7034.h>
23
24#define KB *1024
25#define MB *1024 KB
26#define GB *1024 MB
27
28#define Hz *1
29#define KHz *1000 Hz
30#define MHz *1000 KHz
31
32#define ns *1
33#define us *1000 ns
34#define ms *1000 us
35
36/*
37 * 11.059,200 MHz => 90.4224537037037037037037037037037... ns
38 * 12.000,000 MHz => 83.3333333333333333333333333333333... ns
39 */
40
41#define PHI ((int)(12.000000 MHz))
42#define BAUDRATE 9600
43
44//#define PHI ((int)(11.059200 MHz))
45//#define BAUDRATE 115200 /* 115200 - 9600 */
46
47#define SI(a) \
48 (*((volatile int *)a)) /* single integer access - 32-bit */
49#define HI(a) \
50 (*((volatile short *)a)) /* half integer access - 16-bit */
51#define QI(a) \
52 (*((volatile char *)a)) /* quarter integer access - 8-bit */
53
54#define nop \
55 asm volatile ("nop")
56
57#define __set_mask_constant(mask,address) \
58 asm \
59 ("or.b\t%0,@(r0,gbr)" \
60 : \
61 : /* %0 */ "I"((char)(mask)), \
62 /* %1 */ "z"(address-GBR))
63
64#define __clear_mask_constant(mask,address) \
65 asm \
66 ("and.b\t%0,@(r0,gbr)" \
67 : \
68 : /* %0 */ "I"((char)~(mask)), \
69 /* %1 */ "z"(address-GBR))
70
71#define __toggle_mask_constant(mask,address) \
72 asm \
73 ("xor.b\t%0,@(r0,gbr)" \
74 : \
75 : /* %0 */ "I"((char)(mask)), \
76 /* %1 */ "z"(address-GBR))
77
78#define __test_mask_constant(mask,address) \
79 ({ \
80 int result; \
81 asm \
82 ("tst.b\t%1,@(r0,gbr)\n\tmovt\t%0" \
83 : "=r"(result) \
84 : "I"((char)(mask)),"z"(address-GBR)); \
85 result; \
86 })
87
88#define __set_bit_constant(bit,address) \
89 asm \
90 ("or.b\t%0,@(r0,gbr)" \
91 : \
92 : /* %0 */ "I"((char)(1<<(bit))), \
93 /* %1 */ "z"(address-GBR))
94
95#define __clear_bit_constant(bit,address) \
96 asm \
97 ("and.b\t%0,@(r0,gbr)" \
98 : \
99 : /* %0 */ "I"((char)~(1<<(bit))), \
100 /* %1 */ "z"(address-GBR))
101
102#define __toggle_bit_constant(bit,address) \
103 asm \
104 ("xor.b\t%0,@(r0,gbr)" \
105 : \
106 : /* %0 */ "I"((char)(1<<(bit))), \
107 /* %1 */ "z"(address-GBR))
108
109#define __test_bit_constant(bit,address) \
110 ({ \
111 int result; \
112 asm \
113 ("tst.b\t%1,@(r0,gbr)\n\tmovt\t%0" \
114 : "=r"(result) \
115 : "I"((char)(1<<(bit))),"z"(address-GBR)); \
116 result; \
117 })
118
119#define __set_mask(mask,address) /* FIXME */
120#define __test_mask(mask,address) 0 /* FIXME */
121#define __clear_mask(mask,address) /* FIXME */
122#define __toggle_mask(mask,address) /* FIXME */
123
124#define __set_bit(bit,address) /* FIXME */
125#define __test_bit(bit,address) 0 /* FIXME */
126#define __clear_bit(bit,address) /* FIXME */
127#define __toggle_bit(bit,address) /* FIXME */
128
129#define set_mask(mask,address) \
130 if (__builtin_constant_p (mask)) \
131 __set_mask_constant (mask,address); \
132 else \
133 __set_mask (mask,address)
134
135#define clear_mask(mask,address) \
136 if (__builtin_constant_p (mask)) \
137 __clear_mask_constant (mask,address); \
138 else \
139 __clear_mask (mask,address)
140
141#define toggle_mask(mask,address) \
142 if (__builtin_constant_p (mask)) \
143 __toggle_mask_constant (mask,address); \
144 else \
145 __toggle_mask (mask,address)
146
147#define test_mask(mask,address) \
148 ( \
149 (__builtin_constant_p (mask)) \
150 ? (int)__test_mask_constant (mask,address) \
151 : (int)__test_mask (mask,address) \
152 )
153
154
155#define set_bit(bit,address) \
156 if (__builtin_constant_p (bit)) \
157 __set_bit_constant (bit,address); \
158 else \
159 __set_bit (bit,address)
160
161#define clear_bit(bit,address) \
162 if (__builtin_constant_p (bit)) \
163 __clear_bit_constant (bit,address); \
164 else \
165 __clear_bit (bit,address)
166
167#define toggle_bit(bit,address) \
168 if (__builtin_constant_p (bit)) \
169 __toggle_bit_constant (bit,address); \
170 else \
171 __toggle_bit (bit,address)
172
173#define test_bit(bit,address) \
174 ( \
175 (__builtin_constant_p (bit)) \
176 ? (int)__test_bit_constant (bit,address) \
177 : (int)__test_bit (bit,address) \
178 )
179
180
181extern char __swap_bit[256];
182
183#define swap_bit(byte) \
184 __swap_bit[byte]
185
186static inline short swabHI (short value)
187 /*
188 result[15..8] = value[ 7..0];
189 result[ 7..0] = value[15..8];
190 */
191 {
192 short result;
193 asm volatile ("swap.b\t%1,%0" : "=r"(result) : "r"(value));
194 return result;
195 }
196
197static inline int swawSI (int value)
198 /*
199 result[31..16] = value[15.. 0];
200 result[15.. 0] = value[31..16];
201 */
202 {
203 int result;
204 asm volatile ("swap.w\t%1,%0" : "=r"(result) : "r"(value));
205 return result;
206 }
207
208static inline int swabSI (int value) // should be avoided as much as possible
209 /*
210 result[31..24] = value[ 7.. 0];
211 result[23..16] = value[15.. 8];
212 result[15.. 8] = value[23..16];
213 result[ 7.. 0] = value[31..24];
214 */
215 {
216 return swabHI(swawSI(swabSI(value)));
217 }
218
219/* Test And Set - UNTESTED */
220static inline int tas (volatile int *pointer)
221 {
222 int result;
223 asm volatile ("tas.b\t@%1;movt\t%0" : "=t"(result) : "r"((char *)pointer) : "memory");
224 return result;
225 }
226
227static inline void sti (void)
228 {
229 asm volatile ("ldc\t%0,sr" : : "r"(0<<4));
230 }
231
232static inline void cli (void)
233 {
234 asm volatile ("ldc\t%0,sr" : : "r"(15<<4));
235 }
236
237/* Compare And Swap */
238static inline int cas (volatile int *pointer,int requested_value,int new_value)
239 {
240 cli();
241 if (*pointer == requested_value)
242 {
243 *pointer = new_value;
244 sti ();
245 return 1;
246 }
247 sti ();
248 return 0;
249 }
250
251static inline int cas2 (volatile int *pointer1,volatile int *pointer2,int requested_value1,int requested_value2,int new_value1,int new_value2)
252 {
253 cli();
254 if (*pointer1 == requested_value1 && *pointer2 == requested_value2)
255 {
256 *pointer1 = new_value1;
257 *pointer2 = new_value2;
258 sti ();
259 return 1;
260 }
261 sti ();
262 return 0;
263 }
264
265extern void system_reboot (void);
266
267#endif