-CSRCS = devlpr.c devtty.c devfd.c
+CSRCS = devlpr.c devtty.c devfd.c devfhd.c fidhd.c
CSRCS += devices.c main.c
+DSRCS = ../dev/devide.c ../dev/blkdev.c ../dev/mbr.c
+DISCARD_DSRCS = ../dev/devide_discard.c
+
+CROSS_CCOPTS += -I ../dev/
+
ASRCS = crt0.s commonmem.s pcw8256.s
ASRCS += tricks.s fdc765.s
COBJS = $(CSRCS:.c=.rel)
AOBJS = $(ASRCS:.s=.rel)
-OBJS = $(COBJS) $(AOBJS)
+DISCARD_DOBJS = $(patsubst ../dev/%.c,%.rel, $(DISCARD_DSRCS))
+DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS))
+
+OBJS = $(COBJS) $(AOBJS) $(DOBJS) $(DISCARD_DOBJS)
JUNK = $(CSRCS:.c=.lst) $(CSRCS:.c=.asm) $(CSRCS:.c=.sym) $(ASRCS:.s=.lst) $(ASRCS:.s=.sym) $(CSRCS:.c=.rst) $(ASRCS:.s=.rst)
$(AOBJS): %.rel: %.s
$(CROSS_AS) $(ASOPTS) $<
+$(DOBJS): %.rel: ../dev/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(DISCARD_DOBJS): %.rel: ../dev/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
clean:
rm -f $(OBJS) $(JUNK) core *~
The floppy driver is incomplete but given a rootfs image on /dev/fd1 you
should be able to at least get it to mount
-device 0 = fd0 1 = fd1
+device 256 = fd0 257 = fd1
+
+(0-255 are the UIDE hard disks, or FID hard disks on Joyce)
Mixed boot/root images are not currently supported (this just needs a modified
boot block that starts at a different offset)
+
+
+Memory
+------
+
+Then PCW8256 memory is split into multiple banks not all of which can be used
+for any purpose
+
+The display takes 23040 bytes of video line memory. Each line must be within
+the low 128K and is indexed by the roller RAM
+
+The roller RAM must also be within the low 128K and is 512 bytes.
+
+The keyboard magically replaces the top 16 bytes of bank 3.
+
+Our loader puts the screen into bank 4 and bank 5 (part of), then loads the
+OS into bank 0/1/2/3. We really need to rearrange this so we set the
+final kernel map as something like
+
+0 1 3 5 (4 is display in map)
+
+except that means we must field a hole between BFF0 (keyboard) and Cxxx (
+display). We then end up with a map of
+
+0000-0087 Boot loader
+0088-BFEF Kernel image
+BFF0-BFFF Keyboard
+C000-D9FF Video (lower window)
+DA00-DBFF Roller map
+DC00-E3FF Font
+E400-... Video
+... -FFFF Common
+
+Whilst doing video we map over 8000-BFFF and rely upon the video and common
+mappings
+
+That leaves bank 2, 6+ for userspace (kernel + video costs us 80K)
#define VT_RIGHT 89
#define VT_BOTTOM 31
+#define MAX_BLKDEV 1 /* UIDE or FIDHD never both */
+#define CONFIG_IDE /* Has an IDE controller - maybe anyway: UIDE */
+
#define TICKSPERSEC 50 /* Ticks per second */
#define PROGBASE 0x0000 /* memory base of program */
#define PROGLOAD 0x0100 /* load base of program */
#define NMOUNTS 2 /* Number of mounts at a time */
-#define swap_map(x) ((uint8_t *)(x)) /* For now */
+#define swap_map(x) (uint8_t *)(0x4000 + ((x) & 0x3FFF)) /* For now */
#define platform_discard()
--- /dev/null
+/*
+ * An implementation of the FID based hard disk interface for Joyce.
+ * Currently only hard disk interfaces are handled by this driver.
+ */
+#include <kernel.h>
+#include <kdata.h>
+#include <blkdev.h>
+#include <devfhd.h>
+#include <printf.h>
+
+#define MAX_FHD 16
+
+static const char *errstr[2] = { "write", "read" };
+static uint8_t drivemask;
+static uint8_t drivebase;
+static struct dpb dpb[MAX_FHD];
+
+static uint8_t devfhd_transfer_sector(void)
+{
+ uint8_t err;
+ uint8_t drive = blk_op.blkdev->driver_data;
+ fhd_drive = drivebase + drive;
+ fhd_dpb = dpb + drive;
+ /* For now assume HD fixed geometry */
+ fhd_track = blk_op.lba >> 5;
+ fhd_sector = blk_op.lba & 0x1F;
+ fhd_op = blk_op.is_read ? 4 : 5;
+ err = rw_fidhd();
+ if (err) {
+ kprintf("fhd%c: %s error %d\n", 'a' + drive, errstr[blk_op.is_read], err);
+ return 0;
+ }
+ return 1;
+}
+
+static int devfhd_flush_cache(void)
+{
+ uint8_t err;
+ uint8_t drive = blk_op.blkdev->driver_data;
+ fhd_drive = drivebase + drive;
+ fhd_dpb = dpb + drive;
+ err = flush_fidhd();
+ if (err) {
+ kprintf("fhd%c: flush error %d\n", 'a' + drive, err);
+ udata.u_error = EIO;
+ return -1;
+ }
+ return 0;
+}
+
+/* FIXME These bits could be discard.. */
+
+int devfhd_init(void)
+{
+ blkdev_t *blk;
+ uint8_t d;
+
+ /* Either not supported or too old */
+ if (probe_fidhd() < 2)
+ return 0;
+ fhd_op = 4;
+ fhd_drive = 0;
+ fhd_dpb = dpb;
+ /* Find first slot to install */
+ fhd_drive = drivebase = install_fidhd();
+ if (fhd_drive == 0xFF)
+ return 0;
+ /* Now begin registering */
+ fhd_op = 0;
+ for (d = 0; d < MAX_FHD; d++) {
+ uint8_t next = install_fidhd();
+ if (next != 0xFF)
+ drivemask |= (1 << d);
+ /* The current driver guarantees us a 1:1 so we don't do a lookup
+ table. Maybe we should for the future and use next as intended */
+ fhd_drive++;
+ fhd_dpb++;
+ }
+ fhd_dpb = dpb;
+ fhd_drive = drivebase;
+ for (d = 0; d + drivebase < MAX_FHD; d++) {
+ if (drivemask & (1 << d)) {
+ login_fidhd();
+ blk = blkdev_alloc();
+ if (!blk)
+ break;
+ blk->transfer = devfhd_transfer_sector;
+ blk->flush = devfhd_flush_cache;
+ blk->driver_data = d;
+ blk->drive_lba_count = 16834; /* FIXME use dpb */
+ blkdev_scan(blk, SWAPSCAN); /* Won't damage fhd_dpb/drive */
+ }
+ fhd_drive++;
+ fhd_dpb++;
+ }
+ return drivemask;
+}
--- /dev/null
+struct dpb {
+ uint16_t spt;
+ uint8_t bsh;
+ uint8_t blm;
+ uint8_t exm;
+ uint16_t dsm;
+ uint16_t drm;
+ uint8_t al0;
+ uint8_t al1;
+ uint16_t cks;
+ uint16_t off;
+ uint8_t psh;
+ uint8_t phm;
+};
+
+extern int devfhd_init(void);
+
+extern uint8_t fhd_drive;
+extern uint8_t fhd_op;
+extern uint16_t fhd_track;
+extern uint16_t fhd_sector;
+extern struct dpb *fhd_dpb;
+
+extern uint8_t probe_fidhd(void);
+extern uint8_t install_fidhd(void);
+extern uint8_t login_fidhd(void);
+extern uint8_t flush_fidhd(void);
+extern uint8_t rw_fidhd(void);
#include <version.h>
#include <kdata.h>
#include <devfd.h>
+#include <blkdev.h>
+#include <devide.h>
+#include <devfhd.h>
#include <devsys.h>
#include <devlpr.h>
#include <devtty.h>
{
// minor open close read write ioctl
// -----------------------------------------------------------------
- /* 0: /dev/fd Floppy disc block devices */
+ /* 0: /dev/hd Hard disc block devices (UIDE or FIDHD) */
+ { blkdev_open, no_close, blkdev_read, blkdev_write, blkdev_ioctl }, /* 0: /dev/hd -- standard block device interface */
+ /* 1: /dev/fd Floppy disc block devices */
{ fd_open, no_close, fd_read, fd_write, no_ioctl },
- /* 1: /dev/hd Hard disc block devices (absent) */
- { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl },
/* 2: /dev/tty TTY devices */
{ tty_open, tty_close, tty_read, tty_write, vt_ioctl },
/* 3: /dev/lpr Printer devices */
{
tty_init_port();
fd_probe();
+ /* See what we are attaching */
+ if (devfhd_init() == 0)
+ devide_init();
}
--- /dev/null
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <blkdev.h>
+#include <devfhd.h>
+
+char spambuf[93];
+struct dpb *fhd_dpb;
+uint8_t fhd_drive;
+uint8_t fhd_op; /* must follow fhd_drive directly */
+uint16_t fhd_sector;
+uint16_t fhd_track;
+
+uint8_t probe_fidhd(void) __naked
+{
+__asm
+ xor a
+ .db 0xed
+ .db 0xfe
+ ld l,a
+ or a
+ ret z
+ ld l,h
+ ret
+__endasm;
+}
+
+/*
+ * Install a drive using the given dpb, with spambuf as a buffer
+ * for (currrntly) unused messages on error [93 byte]
+ *
+ * Caller sets driveno, returns volume number to use or FF on fail
+ */
+
+uint8_t install_fidhd(void) __naked
+{
+__asm
+ push ix
+ push iy
+ ld bc,#0x00fe ; probably FF for MYZ80 only ?
+ ld ix, (_fhd_dpb)
+ ld hl, #_spambuf
+ ld de, (_fhd_drive) ; d = op e = drive
+ ld a,#7
+ .db 0xed
+ .db 0xfe
+ cp #2
+ ld l,#0xFF
+ jr nz, instbad
+ ld l,b
+instbad:
+ pop iy
+ pop ix
+ ret
+__endasm;
+}
+
+/*
+ * Returns 0 for ok, 1/2/FF on error as others
+ */
+uint8_t flush_fidhd(void) __naked
+{
+__asm
+ push ix
+ push iy
+ ld ix, (_fhd_dpb)
+ ld a, (_fhd_drive)
+ ld b,a
+ ld a,#6
+ .byte 0xed
+ .byte 0xfe
+ pop iy
+ pop ix
+ ld h,#0
+ ld l,a
+ ret z
+ ret c
+ ld h,b
+ ret
+__endasm;
+}
+/*
+ * Returns 0 for OK and if ok also writes the 17 byte DPB for this
+ * drive to ix. In theory the DPB we get handed back could be for a
+ * whole tonload of formats but the main one we care about is the myz80
+ * 8MB image with 16k/track (32 sectors), 512 tracks.
+ *
+ * Currently we must do the login at boot time and we can't tolerate
+ * a media change of size. (see read/write case for why).
+ */
+uint8_t login_fidhd(void) __naked
+{
+__asm
+ push ix
+ push iy
+ ld bc, (_fhd_drive-1)
+ ld ix, (_fhd_dpb)
+ ld a, #3
+ .byte 0xed
+ .byte 0xfe
+ pop iy
+ pop ix
+ ld h,#0
+ ld l,a
+ ret
+__endasm;
+}
+
+COMMON_MEMORY
+
+/*
+ * Low level I/O has to live in common as we switch banks around in
+ * order to read into user space or into a paging bank.
+ *
+ * Warning: because our common is copied per instance our variables
+ * in common are map specific.
+ *
+ * Read a sector. On return 0 = ok, 1 = error FF = mediach
+ * if recoverable error high byte = error code else 0
+ */
+
+uint8_t rw_fidhd(void) __naked
+{
+__asm
+ ld a,(_fhd_op)
+ push ix
+ push iy
+ ; We must fetch these while in kernel bank. dataptr will point into
+ ; the bank we switch to but the dpb is in kernel bank.
+ ;
+ ; We rely upon the fact we scan all the drives before userspace
+ ; runs thus the dpb has been copied into each common copy and is
+ ; static.
+ ;
+ ld ix, (_fhd_dpb)
+ ld iy, (_blk_op+BLKPARAM_ADDR_OFFSET)
+ ld de, (_fhd_sector)
+ ld hl, (_fhd_track)
+ ld bc, (_fhd_drive-1)
+ push af
+ ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET)
+ or a
+ jr z, k_map
+ cp #1
+ call z, map_process_always
+ ld a, (_blk_op+BLKPARAM_SWAP_PAGE)
+ call nz, map_for_swap
+k_map:
+ pop af
+ .byte 0xed
+ .byte 0xfe
+ pop iy
+ pop ix
+ call map_kernel
+ ld h,#0
+ ld l,a
+ ret z
+ ret c
+ ld h,b
+ ret
+__endasm;
+}
platform-pcw8256/devtty.rel
vt.rel
font8x8.rel
+platform-pcw8256/blkdev.rel
+platform-pcw8256/mbr.rel
+platform-pcw8256/devide.rel
+platform-pcw8256/devide_discard.rel
+platform-pcw8256/devfhd.rel
+platform-pcw8256/fidhd.rel
+
-e
.globl _need_resched
.globl map_save
.globl map_restore
+ .globl map_for_swap
.globl platform_interrupt_all
.globl _copy_common
pop af
ret
+map_for_swap:
+ ld (map_current+1),a
+ out (0xF1),a ; map at 0x4000
+ ret
+
map_process_always:
push af
push hl
--- /dev/null
+#define ide_select(x)
+#define ide_deselect()
+
+/* UIDE8 for the PCW series: 8bit, no altstatus/control */
+#define IDE_8BIT_ONLY
+#define IDE_REG_CS1_BASE 0xC8