From 5d03f2220b4e97845c223d1dd54b4a7bc0625baf Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 6 Jan 2015 22:25:18 +0000 Subject: [PATCH] trs80/core: Enable the pieces we need for TRS80 with labels This is very much a work in progress. Mostly pushing it so that Will can compare with the blkdev work and the needs of the two models in terms of functionality and size. --- Kernel/include/kdata.h | 1 + Kernel/platform-trs80/config.h | 4 +- Kernel/platform-trs80/devhd.c | 163 ++++++++++++++++++++++++++------ Kernel/platform-trs80/devhd.h | 2 + Kernel/platform-trs80/devices.c | 7 +- Kernel/platform-trs80/main.c | 22 +++-- 6 files changed, 154 insertions(+), 45 deletions(-) diff --git a/Kernel/include/kdata.h b/Kernel/include/kdata.h index 366cc3cd..aea0e779 100644 --- a/Kernel/include/kdata.h +++ b/Kernel/include/kdata.h @@ -18,6 +18,7 @@ extern uint16_t nready; /* Number of ready processes */ extern inoptr root; /* Address of root dir in inode table */ extern uint16_t root_dev; /* Device number of root filesystem. */ +extern uint16_t swap_dev; /* Device number used for swap */ extern struct blkbuf bufpool[NBUFS]; extern struct p_tab ptab[PTABSIZE]; diff --git a/Kernel/platform-trs80/config.h b/Kernel/platform-trs80/config.h index bce93777..dc1e73ce 100644 --- a/Kernel/platform-trs80/config.h +++ b/Kernel/platform-trs80/config.h @@ -41,7 +41,7 @@ #define SWAPBASE 0x0000 /* We swap the lot in one, include the */ #define SWAPTOP 0x8000 /* vectors so its a round number of sectors */ -#define MAX_SWAPS 16 /* Should be plenty */ +#define MAX_SWAPS 64 /* Should be plenty (2MB!) */ #define BOOT_TTY (512 + 1) /* Set this to default device for stdio, stderr */ /* In this case, the default is the first TTY device */ @@ -52,7 +52,7 @@ /* Device parameters */ #define NUM_DEV_TTY 3 #define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ -#define SWAPDEV (256) /* Device for swapping (1st hd). */ +#define SWAPDEV (swap_dev) /* Device for swapping (dynamic). */ #define NBUFS 10 /* Number of block buffers */ #define NMOUNTS 4 /* Number of mounts at a time */ diff --git a/Kernel/platform-trs80/devhd.c b/Kernel/platform-trs80/devhd.c index 48a8aaa2..4c35e11a 100644 --- a/Kernel/platform-trs80/devhd.c +++ b/Kernel/platform-trs80/devhd.c @@ -6,6 +6,7 @@ #include #include #include +#include __sfr __at 0xC0 hd_wpbits; /* Write protect and IRQ (not used) */ __sfr __at 0xC1 hd_ctrl; /* Reset and enable bits */ @@ -28,7 +29,7 @@ __sfr __at 0xCF hd_cmd; #define HDCMD_INIT 0x60 /* Ditto */ #define HDCMD_SEEK 0x70 -#define RATE_2MS 0x04 /* 2ms step rate for hd (conservative) */ +#define RATE_4MS 0x08 /* 4ms step rate for hd (conservative) */ #define HDCTRL_SOFTRESET 0x10 #define HDCTRL_ENABLE 0x08 @@ -39,11 +40,16 @@ __sfr __at 0xCF hd_cmd; /* Used by the asm helpers */ uint8_t hd_page; +/* Swap is scanned for so not constant */ +uint16_t swap_dev; + /* Seek and restore low 4 bits are the step rate, read/write support multi-sector mode but not all emulators do .. */ #define MAX_HD 4 +struct minipart parts[MAX_HD]; + /* Wait for the drive to show ready */ static uint8_t hd_waitready(void) { @@ -73,21 +79,26 @@ static uint8_t hd_xfer(bool is_read, uint16_t addr) hd_xfer_in(addr); else hd_xfer_out(addr); - /* Should be returning READY, and maybe SEEKDONE */ + /* Should beeturning READY, and maybe SEEKDONE */ return hd_status; } -static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) +int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) { blkno_t block; - uint16_t dptr; + staticfast uint16_t dptr; uint16_t ct = 0; - int tries; + staticfast uint8_t tries; uint8_t err = 0; uint8_t cmd = HDCMD_READ; uint8_t head; uint8_t sector; uint16_t nblock; + staticfast uint16_t cyl; + uint8_t dev = minor >> 4; + staticfast struct minipart *p; + + p = &parts[dev]; if (rawflag == 0) { dptr = (uint16_t)udata.u_buf->bf_data; @@ -105,30 +116,29 @@ static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) if (!is_read) cmd = HDCMD_WRITE; + /* TRS80 hard disk are 32 sectors/track, 256 byte sectors */ - /* We assume 32 sectors per track for now. From our 512 byte - PoV that's 16 */ + hd_precomp = p->g.precomp; + hd_seccnt = 1; - /* For our test purposes we use a disk with 32 sectors, 4 heads so - our blocks map out as 00cccccc ccCCCCCC CCHHSSSS + sector = block; + sector = ((sector << 1) & 0x1E) | 0x01; - This matches a real ST506 which is 153 cyls, 4 heads, 32 sector */ + cyl = block >> 4; - hd_precomp = 0x20; /* For now, matches an ST506 */ - hd_seccnt = 1; - block <<= 1; /* Into 256 byte blocks, limits us to 32MB - so ought to FIXME */ + /* Do the maths once and on 16 bit numbers */ + head = cyl % p->g.head; + cyl /= p->g.head; + if (minor) + cyl += p->cyl[(minor-1)&0x0F]; while (ct < nblock) { - /* 32 sectors per track assumed for now */ - sector = (block & 31) + 1; - head = (block >> 5) & 3; /* Head next bits, plus drive */ - hd_sdh = 0x80 | head | (minor << 3); + hd_sdh = 0x80 | head | (dev << 3); hd_secnum = sector; /* cylinder bits */ - hd_cyllo = (block >> 7) & 0xFF; - hd_cylhi = (block >> 15) & 0xFF; + hd_cyllo = cyl & 0xFF; + hd_cylhi = cyl >> 8; for (tries = 0; tries < 4; tries++) { /* issue the command */ @@ -145,7 +155,7 @@ static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) kprintf("hd%d: err %x\n", minor, err); if (tries > 1) { - hd_cmd = HDCMD_RESTORE; + hd_cmd = HDCMD_RESTORE | p->g.seek; if (hd_waitready() & 1) kprintf("hd%d: restore error %z\n", minor, err); } @@ -155,7 +165,16 @@ static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) goto bad; ct++; dptr += 256; - block ++; + sector++; + /* Cheaper than divison! */ + if (sector == 33) { + sector = 1; + head++; + if (head == p->g.head) { + head = 0; + cyl++; + } + } } return 1; bad: @@ -170,17 +189,13 @@ bad2: int hd_open(uint8_t minor, uint16_t flag) { + uint8_t dev = minor >> 4; flag; - if (minor >= MAX_HD) { + if (dev > MAX_HD || parts[dev].g.head == 0 || + (minor && parts[dev].cyl[(minor-1)&0x0F] == 0xFFFF)) { udata.u_error = ENODEV; return -1; } - hd_sdh = 0xA0 | (minor << 3); - hd_cmd = HDCMD_RESTORE | RATE_2MS; - if (hd_waitready() & 1) { - if ((hd_err & 0x12) == 0x12) - return -ENODEV; - } return 0; } @@ -195,3 +210,93 @@ int hd_write(uint8_t minor, uint8_t rawflag, uint8_t flag) flag; return hd_transfer(minor, false, rawflag); } + +/*------------------- below this is thrown after boot ---------------- */ +DISCARDABLE + +/* + * Mini part processing. This and mbr and other things all one day + * need to become a bit more unified. + */ +static void hd_swapon(struct minipart *p, unsigned int d, unsigned int i) +{ + uint16_t cyls; + if (i == 14 || p->cyl[i+1] == 0xFFFF) + cyls = p->g.cyl; + else + cyls = p->cyl[i+1]; + cyls -= p->cyl[i]; + cyls *= p->g.head; + /* This is now the number of sets of 32 sectors (16K) in swap. + We need 32K per process: hardwire it here - FIX if you change + the mapping model */ + + swap_dev = d << 4 + i + 1 + 0x100; + + if (cyls >= MAX_SWAPS) + cyls = MAX_SWAPS - 1; + for (i = 0; i < cyls; i++) { + swapmap_add(i); + } + kputs("swap-"); +} + +void hd_probe(void) +{ + unsigned int dev = 0; + unsigned int i; + uint8_t *d = tmpbuf(); + /* Second half of second block */ + struct minipart *p = (struct minipart *)(d + 384); + for (dev = 0; dev < 4; dev++) { + hd_sdh = 0x80 | (dev << 3); + hd_cmd = HDCMD_RESTORE | RATE_4MS; + if (hd_waitready() & 1) { + if ((hd_err & 0x12) == 0x12) + continue; + } + hd_seccnt = 1; + hd_sdh = 0x80 | (dev << 3); + hd_secnum = 1; + hd_cyllo = 0; + hd_cylhi = 0; + hd_cmd = HDCMD_READ; + if (hd_waitdrq() & 1) + continue; + if((hd_xfer(1, (uint16_t)d) & 0x41) != 0x40) + continue; + kprintf("hd%c: ", dev + 'a'); + if (p->g.magic != MP_SIG_0) { + p->g.cyl = 1; + p->g.head = 1; + p->g.sec = 32; + p->g.precomp = 0; + p->g.seek = 10; + p->g.secsize = 8; + for (i = 0; i < 15; i++) + p->cyl[i] = 0xFFFFU; + kputs("(unlabelled)\n"); + } else { + for (i = 0; i < 15; i++) { + if (p->cyl[i] != 0xFFFFU) { + if (p->type[i] == 0x56) { + /* Configure swap */ + hd_swapon(p, dev, i); + } + kprintf("hd%c%d ", dev + 'a', i + 1); + } + } + kputs("\n"); + } + if (p->g.seek) { + p->g.seek /= 2; + if (p->g.seek == 0) + p->g.seek = 1; + } + /* Set the step rate */ + hd_cmd = HDCMD_SEEK | p->g.seek; + hd_waitready(); + memcpy(&parts[dev], p, sizeof(parts[dev])); + } + brelse((bufptr)d); +} diff --git a/Kernel/platform-trs80/devhd.h b/Kernel/platform-trs80/devhd.h index 41200a76..bdebb171 100644 --- a/Kernel/platform-trs80/devhd.h +++ b/Kernel/platform-trs80/devhd.h @@ -10,4 +10,6 @@ int hd_open(uint8_t minor, uint16_t flag); int hd_xfer_in(uint16_t addr); int hd_xfer_out(uint16_t addr); +void hd_probe(void); + #endif /* __DEVHD_DOT_H__ */ diff --git a/Kernel/platform-trs80/devices.c b/Kernel/platform-trs80/devices.c index bc59ba16..7287717e 100644 --- a/Kernel/platform-trs80/devices.c +++ b/Kernel/platform-trs80/devices.c @@ -34,14 +34,13 @@ bool validdev(uint16_t dev) return true; } +DISCARDABLE + void device_init(void) { - int i; #ifdef CONFIG_RTC /* Time of day clock */ inittod(); #endif - /* Add 64 swaps (2MB) */ - for (i = MAX_SWAPS - 1 ; i >= 0; i--) - swapmap_add(i); + hd_probe(); } diff --git a/Kernel/platform-trs80/main.c b/Kernel/platform-trs80/main.c index 63935c5b..ad25b077 100644 --- a/Kernel/platform-trs80/main.c +++ b/Kernel/platform-trs80/main.c @@ -32,16 +32,6 @@ void platform_interrupt(void) timer_interrupt(); } -void map_init(void) -{ -} - -void pagemap_init(void) -{ - pagemap_add(0x63); /* Mode 3, U64K low 32K mapped as low 32K */ - pagemap_add(0x73); /* Mode 3, U64K high 32K mapped as low 32K */ -} - #ifdef CONFIG_RTC __sfr __at 0xB0 rtc_secl; @@ -59,3 +49,15 @@ uint8_t rtc_secs(void) } #endif + +DISCARDABLE + +void map_init(void) +{ +} + +void pagemap_init(void) +{ + pagemap_add(0x63); /* Mode 3, U64K low 32K mapped as low 32K */ + pagemap_add(0x73); /* Mode 3, U64K high 32K mapped as low 32K */ +} -- 2.34.1