Add files to repository

This commit is contained in:
Alec Murphy 2022-01-14 11:29:08 -05:00
parent 443c63b64d
commit 12553eeeb1
7 changed files with 1489 additions and 1 deletions

48
Install.HC Normal file
View file

@ -0,0 +1,48 @@
U0 Install() {
"Primary IDE base0 (0x01F0): ";
U8 *pri_base0 = GetStr;
if (!StrCmp(pri_base0, ""))
pri_base0 = "0x01F0";
"Primary IDE base1 (0x03F6): ";
U8 *pri_base1 = GetStr;
if (!StrCmp(pri_base1, ""))
pri_base1 = "0x03F6";
"Secondary IDE base0 (0x0170): ";
U8 *sec_base0 = GetStr;
if (!StrCmp(sec_base0, ""))
sec_base0 = "0x0170";
"Secondary IDE base1 (0x0376): ";
U8 *sec_base1 = GetStr;
if (!StrCmp(sec_base1, ""))
sec_base1 = "0x0376";
Copy("T:/KMain.HC", "::/Kernel/KMain.HC");
Copy("T:/Src/DskAddDev.HC", "::/Kernel/BlkDev/DskAddDev.HC.Z");
Copy("T:/Src/DskATA.HC", "::/Kernel/BlkDev/DskATA.HC.Z");
Copy("T:/Src/BootHelper.HC", "::/Home/BootHelper.HC.Z");
CDoc *doc1 = DocNew("::/Kernel/BlkDev/DskATAId.HC.Z");
CDoc *doc2 = DocRead("T:/Src/DskATAId.HC");
DocPrint(doc1, "#define BMIK_PRI_BASE0 %s\n", pri_base0);
DocPrint(doc1, "#define BMIK_PRI_BASE1 %s\n", pri_base1);
DocPrint(doc1, "#define BMIK_SEC_BASE0 %s\n", sec_base0);
DocPrint(doc1, "#define BMIK_SEC_BASE1 %s\n", sec_base1);
DocInsDoc(doc1, doc2);
DocDel(doc2);
DocWrite(doc1);
DocDel(doc1);
doc1 = DocNew("::/Home/Once.HC.Z");
doc2 = DocRead("::/Home/Once.HC.Z");
DocPrint(doc1, "#include \"BootHelper\"\n\n");
DocInsDoc(doc1, doc2);
DocDel(doc2);
DocWrite(doc1);
DocDel(doc1);
XTalkWait(Fs, "Cd;\n");
XTalkWait(Fs, "BootHDIns;\n");
XTalkWait(Fs, "\n");
XTalkWait(Fs, "C\ns");
XTalkWait(Fs, "0x01F0\n");
XTalkWait(Fs, "0x03F6\n");
XTalkWait(Fs, "0\n\n\n");
}
Install;

View file

@ -1,3 +1,39 @@
# bmik
Bare-Metal Installation Kit - Easily install TempleOS on bare-metal
Bare-Metal Installation Kit - Easily install TempleOS on bare-metal
# Details
The goal for this project is to provide an easy way to create a hard disk image that can be booted on bare-metal hardware and QEMU seamlessly, to allow for transfer of files between PCs while developing software projects.
The intended usage is to create a disk image that can be copied to a hard disk mounted in a removable enclosure, and the hard disk transferred between the virtual environment and a bare-metal machine.
# Usage
- Create a raw disk image, at least large enough to hold 2*1G TempleOS RedSea partitions + partition table `qemu-img create -f raw disk_img.raw 4G`
- Run the VM install wizard, then re-run install wizard w/o VM option from each partition and choose RedSea format for each install
OR
- Use the provided disk image `disk_img.raw.xz` which skips these steps for you.
THEN
- Clone the repo, add files to `bmik.ISO.C`
- `qemu-system-x86_64 -drive format=raw,file=disk_img.raw -m 1024 -cdrom bmik.ISO.C`
FINALLY, for each partition:
- Mount the CDROM, if it is not mounted already `Mount;` - drive letter 'T', 'p' for probe, number '2' for Secondary IDE
- `Cd("T:"); #include "Install";`
- Enter your Primary/Secondary base0, base1 I/O ports from `lspci -v`
- Reboot
# Done
`dd` the resulting `disk_img.raw` to your target HDD, and you now have a TempleOS RedSea installation with 2 partitions, bootable on bare-metal and QEMU.

26
Src/BootHelper.HC Normal file
View file

@ -0,0 +1,26 @@
// This script will clean up non-existent removable drives when booting in QEMU
U0 BootHelper() {
I64 i;
Bool is_qemu = FALSE;
U8 *drv_model = DrvModelNum(':');
if (!MemCmp("QEMU", drv_model, 4))
is_qemu = TRUE;
Free(drv_model);
if (is_qemu) {
// Remove non-existent removable drives
for (i = 'T'; i < 'X'; i++) {
if (Let2Drv(i, 0))
DrvDel(Let2Drv(i));
}
// Add default QEMU CDROM
CBlkDev *bd = CAlloc(sizeof(CBlkDev));
bd = BlkDevNextFreeSlot('T', 5);
bd->unit = 0;
bd->base0 = 0x170;
bd->base1 = 0x374;
BlkDevAdd(bd, , 0, 0);
}
}
BootHelper;

601
Src/DskATA.HC Normal file
View file

@ -0,0 +1,601 @@
U0 ATABlkSel(CBlkDev *bd, I64 blk, I64 cnt) {
if (bd->type != BDT_ATAPI && bd->base1)
OutU8(bd->base1 + ATAR1_CTRL, 0x8);
if (bd->flags & BDF_EXT_SIZE) { // 48 Bit LBA?
OutU8(bd->base0 + ATAR0_NSECT, cnt.u8[1]);
OutU8(bd->base0 + ATAR0_SECT, blk.u8[3]);
OutU8(bd->base0 + ATAR0_LCYL, blk.u8[4]);
OutU8(bd->base0 + ATAR0_HCYL, blk.u8[5]);
OutU8(bd->base0 + ATAR0_NSECT, cnt);
OutU8(bd->base0 + ATAR0_SECT, blk);
OutU8(bd->base0 + ATAR0_LCYL, blk.u8[1]);
OutU8(bd->base0 + ATAR0_HCYL, blk.u8[2]);
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
} else { // 28 Bit LBA
OutU8(bd->base0 + ATAR0_NSECT, cnt);
OutU8(bd->base0 + ATAR0_SECT, blk);
OutU8(bd->base0 + ATAR0_LCYL, blk.u8[1]);
OutU8(bd->base0 + ATAR0_HCYL, blk.u8[2]);
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4 | blk.u8[3]);
}
}
Bool ATAWaitNotBUSY(CBlkDev *bd, F64 timeout) {
I64 i;
do {
for (i = 0; i < 3; i++)
if (!(InU8(bd->base0 + ATAR0_STAT) & ATAS_BSY))
return TRUE;
Yield;
} while (!(0 < timeout < tS));
return FALSE;
}
Bool ATAWaitDRQ(CBlkDev *bd, F64 timeout) {
I64 i;
do {
for (i = 0; i < 3; i++)
if (InU8(bd->base0 + ATAR0_STAT) & ATAS_DRQ)
return TRUE;
Yield;
} while (!(0 < timeout < tS));
return FALSE;
}
Bool ATANop(CBlkDev *bd, F64 timeout) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_FEAT, 0);
OutU8(bd->base0 + ATAR0_CMD, ATA_NOP);
return ATAWaitNotBUSY(bd, timeout);
}
U0 ATACmd(CBlkDev *bd, U8 cmd) {
OutU8(bd->base0 + ATAR0_FEAT, 0);
OutU8(bd->base0 + ATAR0_CMD, cmd);
bd->last_time = tS;
PortNop;
}
Bool ATAGetRes(CBlkDev *bd, F64 timeout, U8 *buf, I64 cnt, I64 _avail,
Bool one_read) {
I64 avail, overflow;
bd->flags &= ~BDF_LAST_WAS_WRITE;
MemSet(buf, 0, cnt);
while (cnt > 0) {
if (!ATAWaitDRQ(bd, timeout))
return FALSE;
if (_avail)
avail = _avail;
else
avail = InU8(bd->base0 + ATAR0_HCYL) << 8 + InU8(bd->base0 + ATAR0_LCYL);
if (avail) {
if (avail > cnt) {
overflow = avail - cnt;
avail = cnt;
} else
overflow = 0;
if (avail & 2)
RepInU16(buf, avail >> 1, bd->base0 + ATAR0_DATA);
else
RepInU32(buf, avail >> 2, bd->base0 + ATAR0_DATA);
cnt -= avail;
buf += avail;
while (overflow > 0) {
InU16(bd->base0 + ATAR0_DATA);
overflow -= 2;
if (0 < timeout < tS)
return FALSE;
}
if (one_read)
break;
} else
Yield;
}
return ATAWaitNotBUSY(bd, timeout);
}
Bool ATAPIWritePktWord(CBlkDev *bd, F64 timeout, ...) {
I64 i;
for (i = 0; i < argc; i++) {
if (!ATAWaitDRQ(bd, timeout))
return FALSE;
OutU16(bd->base0 + ATAR0_DATA, EndianU16(argv[i]));
bd->last_time = tS;
}
return TRUE;
}
Bool ATAPISetMaxSpeed(CBlkDev *bd) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 0);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePktWord(bd, 0, 0xBB00, 0xFFFF, 0xFFFF, 0, 0, 0);
return ATAWaitNotBUSY(bd, 0);
}
Bool ATAPISeek(CBlkDev *bd, I64 native_blk) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 0);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePktWord(bd, 0, 0x2B00, native_blk >> 16, native_blk, 0, 0, 0);
return ATAWaitNotBUSY(bd, 0);
}
Bool ATAPIStartStop(CBlkDev *bd, F64 timeout, Bool start) {
I64 i;
if (start)
i = 0x100;
else
i = 0;
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
ATACmd(bd, ATA_PACKET);
// Start/Stop
if (ATAPIWritePktWord(bd, timeout, 0x1B00, 0, i, 0, 0, 0))
return ATAWaitNotBUSY(bd, timeout);
else
return FALSE;
}
I64 ATAGetDevId(CBlkDev *bd, F64 timeout, Bool keep_id_record) {
I64 res = BDT_NULL;
U16 *id_record = NULL;
if (bd->type != BDT_ATAPI && bd->base1)
OutU8(bd->base1 + ATAR1_CTRL, 0x8);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
ATACmd(bd, ATA_ID_DEV);
ATAWaitNotBUSY(bd, timeout);
if (InU8(bd->base0 + ATAR0_STAT) & ATAS_ERR)
res = BDT_ATAPI;
else {
id_record = ACAlloc(512);
if (ATAGetRes(bd, timeout, id_record, 512, 512, FALSE))
res = BDT_ATA;
else {
Free(id_record);
id_record = NULL;
}
}
if (keep_id_record) {
Free(bd->dev_id_record);
bd->dev_id_record = id_record;
}
return res;
}
I64 ATAReadNativeMax(CBlkDev *bd, F64 timeout) { // Returns zero on err
I64 res = 0;
Bool okay = TRUE;
if (bd->type == BDT_ATAPI) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
ATACmd(bd, ATA_DEV_RST);
if (!ATAWaitNotBUSY(bd, 0))
okay = FALSE;
} else {
while (InU8(bd->base0 + ATAR0_STAT) & ATAS_BSY) {
if (bd->flags & BDF_LAST_WAS_WRITE)
OutU16(bd->base0 + ATAR0_DATA, 0);
else
InU16(bd->base0 + ATAR0_DATA);
Yield;
if (0 < timeout < tS)
return FALSE;
}
if (ATAGetDevId(bd, timeout, TRUE) == BDT_NULL)
okay = FALSE;
else
BEqu(&bd->flags, BDf_EXT_SIZE, Bt(&bd->dev_id_record[86], 10));
}
if (okay) {
if (bd->flags & BDF_EXT_SIZE && bd->base1) {
OutU8(bd->base1 + ATAR1_CTRL, 0x8);
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
ATACmd(bd, ATA_READ_NATIVE_MAX_EXT);
if (ATAWaitNotBUSY(bd, timeout)) {
res.u8[0] = InU8(bd->base0 + ATAR0_SECT);
res.u8[1] = InU8(bd->base0 + ATAR0_LCYL);
res.u8[2] = InU8(bd->base0 + ATAR0_HCYL);
OutU8(bd->base1 + ATAR1_CTRL, 0x80);
res.u8[3] = InU8(bd->base0 + ATAR0_SECT);
res.u8[4] = InU8(bd->base0 + ATAR0_LCYL);
res.u8[5] = InU8(bd->base0 + ATAR0_HCYL);
if (res >> 24 == res & 0xFFFFFF) { // Kludge to make QEMU work
bd->flags &= ~BDF_EXT_SIZE;
res &= 0xFFFFFF;
}
}
} else {
if (bd->type != BDT_ATAPI && bd->base1)
OutU8(bd->base1 + ATAR1_CTRL, 0x8);
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
ATACmd(bd, ATA_READ_NATIVE_MAX);
if (ATAWaitNotBUSY(bd, timeout)) {
res.u8[0] = InU8(bd->base0 + ATAR0_SECT);
res.u8[1] = InU8(bd->base0 + ATAR0_LCYL);
res.u8[2] = InU8(bd->base0 + ATAR0_HCYL);
res.u8[3] = InU8(bd->base0 + ATAR0_SEL) & 0xF;
}
}
}
return bd->max_blk = res;
}
I64 ATAPIReadCapacity(
CBlkDev *bd,
I64 *_blk_size = NULL) { // Supposedly this can return a res +/- 75 sects.
// Error might just be for music.
Bool unlock = BlkDevLock(bd);
U32 buf[2];
if (ATAWaitNotBUSY(bd, 0)) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 8);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePktWord(bd, 0, 0x2500, 0, 0, 0, 0, 0);
if (!ATAGetRes(bd, 0, buf, 8, 0, TRUE))
buf[0] = buf[1] = 0;
} else
buf[0] = buf[1] = 0;
if (unlock)
BlkDevUnlock(bd);
if (_blk_size)
*_blk_size = EndianU32(buf[1]);
return EndianU32(buf[0]);
}
CATAPITrack *ATAPIReadTrackInfo(CBlkDev *bd, I64 blk) {
CATAPITrack *res = CAlloc(sizeof(CATAPITrack));
Bool unlock = BlkDevLock(bd);
if (ATAWaitNotBUSY(bd, 0)) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, sizeof(CATAPITrack) & 0xFF);
OutU8(bd->base0 + ATAR0_HCYL, sizeof(CATAPITrack) >> 8);
ATACmd(bd, ATA_PACKET);
ATAPIWritePktWord(bd, 0, 0x5200, blk.u16[1], blk.u16[0],
(sizeof(CATAPITrack) & 0xFF00) >> 8,
(sizeof(CATAPITrack) & 0x00FF) << 8, 0);
if (!ATAGetRes(bd, 0, res, sizeof(CATAPITrack), 0, TRUE)) {
Free(res);
res = NULL;
}
} else {
Free(res);
res = NULL;
}
if (unlock)
BlkDevUnlock(bd);
return res;
}
Bool ATAInit(CBlkDev *bd) {
Bool unlock = BlkDevLock(bd), okay = FALSE;
if (bd->type == BDT_ATAPI)
bd->flags &= ~BDF_EXT_SIZE;
else
bd->flags |= BDF_EXT_SIZE;
if (ATAReadNativeMax(bd, tS + 0.1)) {
ATABlkSel(bd, bd->max_blk, 0);
if (bd->flags & BDF_EXT_SIZE)
ATACmd(bd, ATA_SET_MAX_EXT);
else
ATACmd(bd, ATA_SET_MAX);
if (ATAWaitNotBUSY(bd, 0)) {
okay = TRUE;
if (bd->type == BDT_ATAPI) {
if (ATAPIStartStop(bd, 0, TRUE)) {
if (!ATAPISetMaxSpeed(bd))
okay = FALSE;
} else
okay = FALSE;
}
}
}
if (unlock)
BlkDevUnlock(bd);
return okay;
}
Bool ATAPIWaitReady(CBlkDev *bd, F64 timeout) {
do {
if (!ATAWaitNotBUSY(bd, timeout) || !ATANop(bd, timeout) ||
!ATAPIStartStop(bd, timeout, TRUE))
return FALSE;
if (InU8(bd->base0 + ATAR0_STAT) & ATAS_DRDY &&
!InU8(bd->base0 + ATAR0_FEAT))
;
return TRUE;
ATAInit(bd);
Yield;
} while (!(0 < timeout < tS));
return FALSE;
}
U0 ATAReadBlks(CBlkDev *bd, U8 *buf, I64 blk, I64 cnt) {
I64 retries = 3;
Bool unlock = BlkDevLock(bd);
retry:
ATABlkSel(bd, blk, cnt);
if (bd->flags & BDF_EXT_SIZE)
ATACmd(bd, ATA_READ_MULTI_EXT);
else
ATACmd(bd, ATA_READ_MULTI);
if (!ATAGetRes(bd, tS + 1.0, buf, cnt * bd->blk_size, BLK_SIZE, FALSE)) {
if (retries--) {
ATAWaitNotBUSY(bd, 0);
goto retry;
} else
throw('BlkDev');
}
blkdev.read_cnt += (cnt * bd->blk_size) >> BLK_SIZE_BITS;
if (unlock)
BlkDevUnlock(bd);
}
I64 ATAProbe(I64 base0, I64 base1, I64 unit) {
CBlkDev bd;
MemSet(&bd, 0, sizeof(CBlkDev));
bd.type = BDT_ATAPI;
bd.base0 = base0;
bd.base1 = base1;
bd.unit = unit;
bd.blk_size = DVD_BLK_SIZE;
return ATAGetDevId(&bd, tS + 0.1, FALSE);
}
Bool ATAPIReadBlks2(CBlkDev *bd, F64 timeout, U8 *buf, I64 native_blk, I64 cnt,
Bool lock) {
Bool res = FALSE, unlock;
if (cnt <= 0)
return FALSE;
if (lock)
unlock = BlkDevLock(bd);
if (ATAPIWaitReady(bd, timeout)) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, bd->blk_size);
OutU8(bd->base0 + ATAR0_HCYL, bd->blk_size.u8[1]);
ATACmd(bd, ATA_PACKET);
if (ATAPIWritePktWord(bd, timeout, 0xA800, native_blk.u16[1], native_blk,
cnt.u16[1], cnt, 0) &&
ATAGetRes(bd, timeout, buf, cnt * bd->blk_size, 0, FALSE)) {
blkdev.read_cnt += (cnt * bd->blk_size) >> BLK_SIZE_BITS;
res = TRUE;
}
}
// ATAPIStartStop(bd,0,FALSE);
if (lock && unlock)
BlkDevUnlock(bd);
return res;
}
U0 ATAPIReadBlks(CBlkDev *bd, U8 *buf, I64 blk, I64 cnt) {
CDrv *dv = Let2Drv(bd->first_drv_let);
I64 retry, spc = bd->blk_size >> BLK_SIZE_BITS, n, blk2,
l2 = bd->max_reads << 1 + spc << 1;
U8 *dvd_buf = MAlloc(l2 << BLK_SIZE_BITS);
if (cnt > 0) {
if (blk <= bd->max_reads)
blk2 = 0;
else
blk2 = FloorU64(blk - bd->max_reads, spc);
if (blk2 + l2 > dv->size + dv->drv_offset)
l2 = dv->size + dv->drv_offset - blk2;
n = (l2 + spc - 1) / spc;
retry = 4;
while (--retry)
if (ATAPIReadBlks2(bd, tS + 7.0 + 0.004 * n, dvd_buf, blk2 / spc, n,
TRUE))
// n is 0x800 if max_reads. Up to 8 additional seconds
break;
if (!retry)
ATAPIReadBlks2(bd, 0, dvd_buf, blk2 / spc, n, TRUE);
if (bd->flags & BDF_READ_CACHE)
DskCacheAdd(dv, dvd_buf, blk2, n * spc);
MemCpy(buf, dvd_buf + (blk - blk2) << BLK_SIZE_BITS, cnt << BLK_SIZE_BITS);
}
Free(dvd_buf);
}
Bool ATARBlks(CDrv *dv, U8 *buf, I64 blk, I64 cnt) {
I64 n;
CBlkDev *bd = dv->bd;
while (cnt > 0) {
n = cnt;
if (n > bd->max_reads)
n = bd->max_reads;
if (bd->type == BDT_ATAPI)
ATAPIReadBlks(bd, buf, blk, n);
else
ATAReadBlks(bd, buf, blk, n);
buf += n << BLK_SIZE_BITS;
blk += n;
cnt -= n;
}
return TRUE;
}
U0 ATAWriteBlks(CBlkDev *bd, U8 *buf, I64 blk,
I64 cnt) { // For low level disk access.
// Use BlkWrite() instead.
I64 i, U32s_avail, sects_avail, retries = 3;
F64 timeout;
Bool unlock = BlkDevLock(bd);
retry:
ATABlkSel(bd, blk, cnt);
if (bd->flags & BDF_EXT_SIZE)
ATACmd(bd, ATA_WRITE_MULTI_EXT);
else
ATACmd(bd, ATA_WRITE_MULTI);
bd->flags |= BDF_LAST_WAS_WRITE;
while (cnt > 0) {
timeout = tS + 1.0;
while (TRUE) {
i = InU8(bd->base0 + ATAR0_STAT);
if (!(i & ATAS_DRDY) || !(i & ATAS_DRQ)) {
Yield;
} else
break;
if (/* i&ATAS_ERR||*/ tS > timeout) {
if (retries--) {
ATAWaitNotBUSY(bd, 0);
goto retry;
} else
throw('BlkDev');
}
}
sects_avail = 1;
U32s_avail = sects_avail << BLK_SIZE_BITS >> 2;
RepOutU32(buf, U32s_avail, bd->base0 + ATAR0_DATA);
buf += U32s_avail << 2;
cnt -= sects_avail;
retries = 3;
}
ATAWaitNotBUSY(bd, 0);
if (unlock)
BlkDevUnlock(bd);
}
Bool ATAPISync(CBlkDev *bd) {
Bool okay = TRUE;
if (!ATAWaitNotBUSY(bd, 0))
okay = FALSE;
else {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 0);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePktWord(bd, 0, 0x3500, 0, 0, 0, 0, 0);
if (!ATAWaitNotBUSY(bd, 0))
okay = FALSE;
}
return okay;
}
U0 ATAPIClose(CBlkDev *bd, I64 close_field = 0x200,
I64 track = 0) { // 0x200 CD/DVD part 1
// 0x300 DVD part 2
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, 0);
OutU8(bd->base0 + ATAR0_HCYL, 0);
ATACmd(bd, ATA_PACKET);
ATAPIWritePktWord(bd, 0, 0x5B00, close_field, track, 0, 0, 0);
ATAWaitNotBUSY(bd, 0);
}
U0 ATAPIWriteBlks(CBlkDev *bd, U8 *buf, I64 native_blk, I64 cnt) {
I64 U32s_avail;
U8 *buf2;
ATAWaitNotBUSY(bd, 0);
ATAPISeek(bd, native_blk);
OutU8(bd->base0 + ATAR0_FEAT, 0);
OutU8(bd->base0 + ATAR0_LCYL, bd->blk_size);
OutU8(bd->base0 + ATAR0_HCYL, bd->blk_size.u8[1]);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_CMD, ATA_PACKET);
ATAPIWritePktWord(bd, 0, 0x0400, native_blk.u16[1], native_blk, cnt.u16[1],
cnt, 0);
bd->flags |= BDF_LAST_WAS_WRITE;
ATAWaitNotBUSY(bd, 0);
ATAPISeek(bd, native_blk);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0 + ATAR0_SEL, 0xEF | bd->unit << 4);
else
OutU8(bd->base0 + ATAR0_SEL, 0xE0 | bd->unit << 4);
OutU8(bd->base0 + ATAR0_LCYL, bd->blk_size);
OutU8(bd->base0 + ATAR0_HCYL, bd->blk_size.u8[1]);
ATACmd(bd, ATA_PACKET);
ATAPIWritePktWord(bd, 0, 0xAA00, native_blk.u16[1], native_blk, cnt.u16[1],
cnt, 0);
buf2 = buf + bd->blk_size * cnt;
while (buf < buf2) {
ATAWaitDRQ(bd, 0);
U32s_avail =
(InU8(bd->base0 + ATAR0_HCYL) << 8 + InU8(bd->base0 + ATAR0_LCYL)) >> 2;
if (buf + U32s_avail << 2 > buf2)
U32s_avail = (buf2 - buf) >> 2;
if (U32s_avail) {
RepOutU32(buf, U32s_avail, bd->base0 + ATAR0_DATA);
buf += U32s_avail << 2;
blkdev.write_cnt += U32s_avail >> (BLK_SIZE_BITS - 2);
}
}
ATAWaitNotBUSY(bd, 0);
}
Bool ATAWBlks(CDrv *dv, U8 *buf, I64 blk, I64 cnt) {
I64 n, spc;
CBlkDev *bd = dv->bd;
Bool unlock;
spc = bd->blk_size >> BLK_SIZE_BITS;
if (bd->type == BDT_ATAPI) {
unlock = BlkDevLock(bd);
ATAPIWaitReady(bd, 0);
}
while (cnt > 0) {
n = cnt;
if (n > bd->max_writes)
n = bd->max_writes;
if (bd->type == BDT_ATAPI)
ATAPIWriteBlks(bd, buf, blk / spc, (n + spc - 1) / spc);
else
ATAWriteBlks(bd, buf, blk, n);
buf += n << BLK_SIZE_BITS;
blk += n;
cnt -= n;
blkdev.write_cnt += n;
}
if (bd->type == BDT_ATAPI) {
ATAPISync(bd);
// ATAPIStartStop(bd,0,FALSE);
if (unlock)
BlkDevUnlock(bd);
}
return TRUE;
}

301
Src/DskATAId.HC Normal file
View file

@ -0,0 +1,301 @@
Bool BootDVDProbe(CBlkDev *bd) {
U8 *img = CAlloc(DVD_BLK_SIZE);
I64 i;
Bool res = FALSE;
"Port:%04X,%04XUnit:%02X", bd->base0, bd->base1, bd->unit;
if (ATAProbe(bd->base0, bd->base1, bd->unit) == BDT_ATAPI) {
"ATAPI";
if (ATAPIStartStop(bd, tS + 5.0, TRUE)) {
"Started";
for (i = 0; i < 2; i++) { // Retry
if (ATAPIReadBlks2(bd, tS + 7.0, img, sys_boot_blk, 1, FALSE)) {
if ((img + sys_boot_src.u16[1] << BLK_SIZE_BITS)(CKernel *)
->compile_time == sys_compile_time) {
"Found\n";
return TRUE;
} else
"Read";
} else
"NoRead";
}
}
}
"Nope\n";
Free(img);
return res;
}
Bool BootDVDProbeAll(CBlkDev *bd) {
I64 d1, d2, i, j, k;
bd->base1 = 0;
for (k = 0; k < 256; k++) {
i = -1;
while (TRUE) {
j = PCIClassFind(0x010100 + k, ++i);
if (j < 0)
break;
"Subcode:0x%X Bus:0x%X Dev:0x%X Fun:0x%X\n", k, j.u8[2], j.u8[1], j.u8[0];
d1 = PCIReadU32(j.u8[2], j.u8[1], j.u8[0], 0x10);
d2 = PCIReadU32(j.u8[2], j.u8[1], j.u8[0], 0x14);
if (d1 & 1 && d2 & 1) {
if (bd->base0 = d1 & ~7) {
bd->unit = 0;
if (BootDVDProbe(bd))
return TRUE;
bd->unit = 1;
if (BootDVDProbe(bd))
return TRUE;
}
}
d1 = PCIReadU32(j.u8[2], j.u8[1], j.u8[0], 0x18);
d2 = PCIReadU32(j.u8[2], j.u8[1], j.u8[0], 0x1C);
if (d1 & 1 && d2 & 1) {
if (bd->base0 = d1 & ~7) {
bd->unit = 0;
if (BootDVDProbe(bd))
return TRUE;
bd->unit = 1;
if (BootDVDProbe(bd))
return TRUE;
}
}
}
}
d1 = BMIK_PRI_BASE0;
d2 = BMIK_PRI_BASE1;
if (bd->base0 = d1 & ~7) {
bd->unit = 0;
if (BootDVDProbe(bd))
return TRUE;
bd->unit = 1;
if (BootDVDProbe(bd))
return TRUE;
}
d1 = BMIK_SEC_BASE0;
d2 = BMIK_SEC_BASE1;
if (bd->base0 = d1 & ~7) {
bd->unit = 0;
if (BootDVDProbe(bd))
return TRUE;
bd->unit = 1;
if (BootDVDProbe(bd))
return TRUE;
}
}
U0 ATARepEntry(I64 base0, I64 base1, I64 unit, U8 *msg, CATARep **_head,
I64 *num_hints) {
I64 type;
base0 &= -8;
base1 &= -4;
CATARep *tmpha;
if (type = ATAProbe(base0, base1, unit)) {
*num_hints += 1;
"\n$$PURPLE$$$$BT+X,\"%d\",LM=\"%d\\n\"$$$$FG$$$$LM,4$$", *num_hints,
*num_hints;
if (type == BDT_ATA)
"$$RED$$HardDrive$$LTBLUE$$ATA";
else
"$$RED$$CD/DVDDrive$$LTBLUE$$ATAPI";
"%s$$FG$$\n", msg;
if (base0 == blkdev.ins_base0 && unit == blkdev.ins_unit)
"$$PURPLE$$(Drive originally installed from.)$$FG$$\n";
"Base0:0x%04XBase1:0x%04XUnit:%d$$LM,0$$\n", base0, base1, unit;
if (_head) {
tmpha = CAlloc(sizeof(CATARep));
tmpha->next = *_head;
*_head = tmpha;
tmpha->num = *num_hints;
tmpha->type = type;
tmpha->base0 = base0;
tmpha->base1 = base1;
tmpha->unit = unit;
}
}
}
Bool ATARepExitAllApplications() {
"\nWe're going to probe hardware.\n"
"$$RED$$Exit all other applications.$$FG$$\n"
"Press '$$PURPLE$$p$$FG$$' to probe or '$$PURPLE$$s$$FG$$' to skip.\n";
if (ToUpper(GetChar(, FALSE)) == 'S')
return TRUE;
else
return FALSE;
}
public
I64 ATARep(Bool pmt = TRUE, Bool just_ide = FALSE,
CATARep **_head = NULL) { // Report possible ATA devices by probing.
// Hard disks and CD/DVDs.
I64 d1, d2, i, j, k, cnt = 0, unlock_flags = 0, num_hints = 0;
#assert BLKDEVS_NUM <= 64
if (_head)
*_head = NULL;
if (pmt && ATARepExitAllApplications)
return 0;
for (i = 0; i < BLKDEVS_NUM; i++)
if (blkdev.blkdevs[i].bd_signature == BD_SIGNATURE_VAL)
BEqu(&unlock_flags, i, BlkDevLock(&blkdev.blkdevs[i]));
if (!just_ide)
for (k = 0; k < 256; k++) {
i = -1;
while (TRUE) {
j = PCIClassFind(0x010100 + k, ++i);
if (j < 0)
break;
"\nSubcode:0x%X Bus:0x%X Dev:0x%X Fun:0x%X\n", k, j.u8[2], j.u8[1],
j.u8[0];
cnt++;
d1 = PCIReadU32(j.u8[2], j.u8[1], j.u8[0], 0x10);
d2 = PCIReadU32(j.u8[2], j.u8[1], j.u8[0], 0x14);
if (d1 & 1 && d2 & 1) {
ATARepEntry(d1, d2, 0, "Primary IDE", _head, &num_hints);
ATARepEntry(d1, d2, 1, "Primary IDE", _head, &num_hints);
} else {
d1 = BMIK_PRI_BASE0;
d2 = BMIK_PRI_BASE1;
ATARepEntry(d1, d2, 0, "Primary IDE", _head, &num_hints);
ATARepEntry(d1, d2, 1, "Primary IDE", _head, &num_hints);
}
d1 = PCIReadU32(j.u8[2], j.u8[1], j.u8[0], 0x18);
d2 = PCIReadU32(j.u8[2], j.u8[1], j.u8[0], 0x1C);
if (d1 & 1 && d2 & 1) {
ATARepEntry(d1, d2, 0, "Secondary IDE", _head, &num_hints);
ATARepEntry(d1, d2, 1, "Secondary IDE", _head, &num_hints);
} else {
d1 = BMIK_SEC_BASE0;
d2 = BMIK_SEC_BASE1;
ATARepEntry(d1, d2, 0, "Secondary IDE", _head, &num_hints);
ATARepEntry(d1, d2, 1, "Secondary IDE", _head, &num_hints);
}
}
}
if (!cnt) {
d1 = BMIK_PRI_BASE0;
d2 = BMIK_PRI_BASE1;
ATARepEntry(d1, d2, 0, "Primary IDE", _head, &num_hints);
ATARepEntry(d1, d2, 1, "Primary IDE", _head, &num_hints);
d1 = BMIK_SEC_BASE0;
d2 = BMIK_SEC_BASE1;
ATARepEntry(d1, d2, 0, "Secondary IDE", _head, &num_hints);
ATARepEntry(d1, d2, 1, "Secondary IDE", _head, &num_hints);
}
'\n\n';
for (i = 0; i < BLKDEVS_NUM; i++)
if (Bt(&unlock_flags, i))
BlkDevUnlock(&blkdev.blkdevs[i]);
return num_hints;
}
CATARep *ATARepFind(CATARep *haystack_head, I64 needle_num) {
while (haystack_head) {
if (haystack_head->num == needle_num)
return haystack_head;
haystack_head = haystack_head->next;
}
return NULL;
}
CATARep *
ATAIDDrvs(CATARep *head, CATARep **_ata_drv,
CATARep **_atapi_drv) { // This is for when trying to sort-out main
// hard drives and CD/DVD drives.
CATARep *res = NULL, *tmpha = head, *ata_drv = NULL, *atapi_drv = NULL;
CBlkDev *bd;
Bool was_silent = Silent, ins_found = FALSE;
bd = Let2BlkDev(':', FALSE);
Silent(was_silent);
while (tmpha) {
if (!res && bd && bd->type == tmpha->type) {
if (bd->type == BDT_ATAPI && bd->base0 == tmpha->base0 &&
bd->unit == tmpha->unit)
res = atapi_drv = tmpha;
else if (bd->type == BDT_ATA && bd->base0 == tmpha->base0 &&
bd->base1 == tmpha->base1 && bd->unit == tmpha->unit)
res = ata_drv = tmpha;
}
if (!res || res->type != tmpha->type) {
if (tmpha->type == BDT_ATA) {
if (!ata_drv || tmpha->unit < ata_drv->unit ||
tmpha->unit == ata_drv->unit && tmpha->num < ata_drv->num)
ata_drv = tmpha;
} else if (tmpha->type == BDT_ATAPI) {
if (!atapi_drv || !ins_found && (tmpha->unit < atapi_drv->unit ||
tmpha->unit == atapi_drv->unit &&
tmpha->num < atapi_drv->num))
atapi_drv = tmpha;
}
}
if (tmpha->type == BDT_ATAPI && bd && bd->type == BDT_ATA &&
tmpha->base0 == blkdev.ins_base0 && tmpha->unit == blkdev.ins_unit) {
if (!ins_found) {
atapi_drv = tmpha;
ins_found = TRUE;
}
}
tmpha = tmpha->next;
}
if (_ata_drv)
*_ata_drv = ata_drv;
if (_atapi_drv)
*_atapi_drv = atapi_drv;
return res;
}
CBlkDev *ATAMount(U8 first_drv_let, I64 type, I64 base0, I64 base1, I64 unit) {
CBlkDev *res;
if (0 <= first_drv_let - 'A' < DRVS_NUM &&
(type == BDT_ATA || type == BDT_ATAPI) && 0 <= unit <= 1) {
res = BlkDevNextFreeSlot(first_drv_let, type);
res->unit = unit;
res->base0 = base0;
res->base1 = base1;
if (BlkDevAdd(res, , FALSE, FALSE))
return res;
}
return NULL;
}
I64 MountIDEAuto() { // Try to mount hard drive and CD/DVD, automatically.
// (Kernel.Cfg option).
// It uses 'C' and 'T' as first drive letters or whatever you set
// in config when compiling Kernel.BIN.
I64 res = 0;
CATARep *head = NULL, *ata_drv = NULL, *atapi_drv = NULL, *tmpha;
ATARep(FALSE, TRUE, &head);
ATAIDDrvs(head, &ata_drv, &atapi_drv);
if (ata_drv && ATAMount(blkdev.first_hd_drv_let, BDT_ATA, ata_drv->base0,
ata_drv->base1, ata_drv->unit))
res++;
if (atapi_drv &&
ATAMount(blkdev.first_dvd_drv_let, BDT_ATAPI, atapi_drv->base0,
atapi_drv->base1, atapi_drv->unit))
res++;
tmpha = head;
while (tmpha) {
if (tmpha != ata_drv && tmpha != atapi_drv) {
if (tmpha->type == BDT_ATA &&
ATAMount(blkdev.first_hd_drv_let, BDT_ATA, tmpha->base0, tmpha->base1,
tmpha->unit))
res++;
else if (tmpha->type == BDT_ATAPI &&
ATAMount(blkdev.first_dvd_drv_let, BDT_ATAPI, tmpha->base0,
tmpha->base1, tmpha->unit))
res++;
}
tmpha = tmpha->next;
}
LinkedLstDel(head);
blkdev.mount_ide_auto_cnt = res;
return res;
}

238
Src/DskAddDev.HC Normal file
View file

@ -0,0 +1,238 @@
U0 BlkDevLockFwdingSet(
CBlkDev *bd) { // If two blkdevs on same controller, use just one lock
CBlkDev *bd1;
I64 i;
switch (bd->type) {
case BDT_RAM:
break;
case BDT_ISO_FILE_READ:
case BDT_ISO_FILE_WRITE:
bd->lock_fwding = Let2BlkDev(*bd->file_dsk_name);
break;
case BDT_ATA:
case BDT_ATAPI:
for (i = 0; i < BLKDEVS_NUM; i++) {
bd1 = &blkdev.blkdevs[i];
if (bd1->bd_signature == BD_SIGNATURE_VAL && bd != bd1 &&
(bd1->type == BDT_ATAPI || bd1->type == BDT_ATA) &&
bd1->base0 == bd->base0) {
bd->lock_fwding = bd1;
break;
}
}
break;
}
}
I64 BlkDevAdd(
CBlkDev *bd, I64 prt_num = I64_MIN, Bool whole_drv,
Bool make_free) { // It will mount just one partition of prt_num>=0.
// When repartitioing whole drive, whole_drv=TRUE.
I64 i, j, ext_base, offset, res = 0, num = 0;
CDrv *dv;
CRedSeaBoot br;
CMasterBoot mbr;
bd->bd_signature = BD_SIGNATURE_VAL;
if (make_free)
dv = DrvMakeFreeSlot(bd->first_drv_let);
else
dv = DrvMakeFreeSlot(DrvNextFreeLet(bd->first_drv_let));
dv->bd = bd;
dv->drv_offset = bd->drv_offset;
dv->size = bd->max_blk + 1 - bd->drv_offset;
switch (bd->type) {
case BDT_RAM:
case BDT_ISO_FILE_READ:
case BDT_ISO_FILE_WRITE:
dv->dv_signature = DRV_SIGNATURE_VAL;
dv->prt_num = num;
dv->fs_type = FSt_REDSEA;
// This is to force creation of a RAM
// drive during boot, so it is probably
// MAlloced to the same addr and can
// be assumed to be already formatted.
// If this line is removed, RAM Drives
// will be alloced on a just-in-time
// basis.
if (BlkDevInit(bd))
res++;
else
dv->dv_signature = 0;
break;
case BDT_ATA:
dv->dv_signature = DRV_SIGNATURE_VAL; // Temporarily validate
if (!BlkDevInit(bd))
dv->dv_signature = 0; // Revoke validation
else {
dv->dv_signature = 0; // Revoke validation
if (whole_drv) {
dv->dv_signature = DRV_SIGNATURE_VAL;
dv->prt_num = num;
res++;
dv->fs_type = FSt_REDSEA;
dv->size = bd->max_blk + 1 - bd->drv_offset;
// The following read is a test read.
// if it hangs, the drive is not supported.
ATAReadBlks(bd, &mbr, 0, 1);
break;
}
offset = 0;
ext_base = INVALID_CLUS;
while (prt_num < 0 || num <= prt_num) {
ATAReadBlks(bd, &mbr, offset, 1);
if (mbr.signature != 0xAA55)
break;
j = -1;
for (i = 0; i < 4 && (prt_num < 0 || num <= prt_num); i++) {
if (mbr.p[i].type) {
if (make_free)
dv = DrvMakeFreeSlot(bd->first_drv_let + res);
else
dv = DrvMakeFreeSlot(DrvNextFreeLet(bd->first_drv_let + res));
dv->bd = bd;
dv->drv_offset = mbr.p[i].offset + offset;
dv->size = mbr.p[i].size;
switch (mbr.p[i].type) {
case MBR_PT_REDSEA:
dv->dv_signature = DRV_SIGNATURE_VAL;
dv->prt_num = num;
res++;
dv->fs_type = FSt_REDSEA;
RedSeaInit(dv);
break;
case MBR_PT_FAT32a:
case MBR_PT_FAT32b:
case MBR_PT_FAT32c:
case MBR_PT_FAT32d:
case MBR_PT_FAT32e:
case MBR_PT_FAT32f:
ATAReadBlks(bd, &br, dv->drv_offset, 1);
dv->dv_signature = DRV_SIGNATURE_VAL;
dv->prt_num = num;
res++;
if (br.signature == MBR_PT_REDSEA) {
dv->fs_type = FSt_REDSEA;
RedSeaInit(dv);
} else {
dv->fs_type = FSt_FAT32;
FAT32Init(dv);
}
break;
case MBR_PT_NTFS:
dv->dv_signature = DRV_SIGNATURE_VAL;
dv->prt_num = num;
res++;
dv->fs_type = FSt_NTFS;
break;
case 5:
case 15:
j = i;
break;
default:
dv->dv_signature = DRV_SIGNATURE_VAL;
dv->prt_num = num;
res++;
dv->fs_type = FSt_UNKNOWN;
}
num++;
}
}
if (Let2BlkDevType(bd->first_drv_let + res) != bd->type)
break;
if (j < 0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base == INVALID_CLUS) {
offset = mbr.p[j].offset;
ext_base = offset;
} else
offset = mbr.p[j].offset + ext_base;
}
}
break;
case BDT_ATAPI:
dv->dv_signature = DRV_SIGNATURE_VAL;
dv->prt_num = num;
res++;
dv->fs_type = FSt_ISO9660; // Start with this
dv->size = 0;
break;
}
if (res)
BlkDevLockFwdingSet(bd);
else
BlkDevDel(bd);
return res;
}
Bool DrvEnable(
U8 drv_let,
Bool val) { // Can unmount or remount, but not mount the first time.
CDrv *dv;
if (dv = Let2Drv(drv_let, FALSE))
return !LBEqu(&dv->fs_type, FStf_DISABLE, !val);
else
return FALSE;
}
I64 SysGetI64() {
U8 st[STR_LEN];
GetS(st, STR_LEN, FALSE);
return Str2I64(st, 16);
}
Bool GetBaseUnit(CBlkDev *bd) {
I64 ch;
Bool probe;
#exe {
if (kernel_cfg->opts[CFG_DONT_PROBE])
StreamPrint("probe=FALSE;");
else
StreamPrint("probe=TRUE;");
};
if (!probe || !BootDVDProbeAll(bd)) {
"\nDon't worry. This is not a product\n"
"registration. TempleOS just needs the\n"
"I/O port numbers for the CD/DVD.\n"
"\nRetry the ports above or check Windows\n"
"system information under I/O ports for\n"
"'IDE', 'ATA' or 'SATA'.\n"
"In Linux, use 'lspci -v' for ports.\n"
"\n\nEnter 4-digit hex I/O Port number.\n"
"CD/DVD I/O Port Base0: 0x";
bd->base0 = SysGetI64;
bd->base1 = 0;
bd->unit = 0;
if (bd->base0) {
"\nUnit (0 or 1): ";
do
ch = GetChar(, FALSE);
while (!('0' <= ch <= '1'));
'' ch;
bd->unit = ch - '0';
blkdev.dvd_boot_is_good = BootDVDProbe(bd);
return TRUE;
} else {
blkdev.dvd_boot_is_good = FALSE;
return FALSE;
}
}
return FALSE;
}
U0 BlkDevsInitAll() {
CBlkDev *bd;
I64 i;
blkdev.blkdevs = CAlloc(sizeof(CBlkDev) * BLKDEVS_NUM);
blkdev.drvs = CAlloc(sizeof(CDrv) * DRVS_NUM);
for (i = 0; i < DRVS_NUM; i++)
blkdev.let_to_drv[i] = &blkdev.drvs[i];
#exe {
StreamPrint("MountIDEAuto;");
StreamPrint("#exe {Option(OPTf_WARN_PAREN,OFF);}");
StreamDoc(kernel_cfg->add_dev);
StreamPrint("#exe {Option(OPTf_WARN_PAREN,ON);}");
};
}

238
Src/KMain.HC Normal file
View file

@ -0,0 +1,238 @@
U0 SysGlblsInit() {
I64 i, j;
CRAXRBCRCXRDX ee;
CPUId(0x1, &ee);
sys_cache_line_width = ee.rbx.u8[1] * 8;
sys_focus_task = Fs;
QueInit(&sys_macro_head);
blkdev.dft_iso_filename = AStrNew(DFT_ISO_FILENAME);
blkdev.dft_iso_c_filename = AStrNew(DFT_ISO_C_FILENAME);
blkdev.tmp_filename = AStrNew("~/Tmp.DD.Z");
blkdev.dvd_boot_is_good = TRUE;
#exe {
if (!kernel_cfg->mount_ide_auto_hd_let)
kernel_cfg->mount_ide_auto_hd_let = 'C';
if (!kernel_cfg->mount_ide_auto_cd_let)
kernel_cfg->mount_ide_auto_cd_let = 'T';
StreamPrint("blkdev.first_hd_drv_let=%d;", kernel_cfg->mount_ide_auto_hd_let);
StreamPrint("blkdev.first_dvd_drv_let=%d;",
kernel_cfg->mount_ide_auto_cd_let);
}
DbgMode(ON);
rev_bits_table = CAlloc(256);
set_bits_table = CAlloc(256);
for (i = 0; i < 256; i++)
for (j = 0; j < 8; j++) {
if (Bt(&i, 7 - j))
LBts(rev_bits_table + i, j);
if (Bt(&i, j))
set_bits_table[i]++;
}
ext = CAlloc(EXT_EXTS_NUM * sizeof(U8 *));
fp_getstr2 = &SysGetStr2;
KeyDevInit;
#exe {
StreamPrint("blkdev.boot_drv_let='%C';", kernel_cfg->boot_drv_let);
StreamPrint("#exe{Option(OPTf_WARN_PAREN,OFF);}");
StreamPrint("DskCacheInit(%s);", kernel_cfg->dsk_cache_size_exp);
StreamPrint("#exe{Option(OPTf_WARN_PAREN,ON);}");
}
;
pow10_I64 = CAlloc(sizeof(F64) * (308 + 308 + 1));
for (i = -308; i < 309; i++)
pow10_I64[i + 309] = Pow10(i);
QueInit(&scrncast.snd_head);
scrncast.t0_now = Now;
scrncast.t0_tS = tS;
scrncast.ona = scrncast.snd_head.ona = 0;
ProgressBarsRst;
QueInit(&dev.pci_head);
dev.mem64_ptr = mem_mapped_space;
dbg.fun_seg_cache = CAlloc(FUN_SEG_CACHE_SIZE * sizeof(CFunSegCache));
dbg.int_fault_code = IntFaultHndlrsNew;
}
U0 SysGrInit() {
text.font = sys_font_std;
text.aux_font = sys_font_cyrillic;
text.vga_alias = dev.uncached_alias + VGAM_GRAPHICS;
text.vga_text_alias = dev.uncached_alias + VGAM_TEXT;
if (!Bt(&sys_run_level, RLf_VGA)) { // if text mode
text.cols = 80;
text.rows = 25;
MemSet(text.vga_text_alias, 0, text.rows * text.cols << 1);
text.border_chars[2](I64) = '<EFBFBD>ͳ<EFBFBD><EFBFBD>ɿ<EFBFBD>';
text.border_chars[10](U32) = '<EFBFBD><EFBFBD>ټ';
} else { // if 640x480 16 color
text.cols = GR_WIDTH / FONT_WIDTH;
text.rows = GR_HEIGHT / FONT_HEIGHT;
OutU8(VGAP_IDX, VGAR_MAP_MASK);
OutU8(VGAP_DATA, 0x0F);
MemSet(text.vga_alias, 0, GR_WIDTH * GR_HEIGHT >> 3);
text.raw_scrn_image = CAlloc(GR_WIDTH * GR_HEIGHT / 8);
text.border_chars[2](I64) = 0x0908070605040302;
text.border_chars[10](U32) = 0x0D0C0B0A;
}
}
U0 TimersInit() {
I64 i, *_q;
U32 *_d;
OutU8(0x43, 0x34);
OutU8(0x40, SYS_TIMER0_PERIOD);
OutU8(0x40, SYS_TIMER0_PERIOD >> 8);
// High Precision Event Timer
if (PCIReadU16(0, 31, 0, 0) == 0x8086) { // Intel?
// D31 F0, cfg 0xF0=RCBA of PCI-LPC Bridge
_d = PCIReadU32(0, 31, 0, 0xF0)(U8 *) & ~0x3FFF + 0x3404; // HPET cfg
// 7 enable
// 1:0 HPET is at 0xFED00000,0xFED01000, 0xFED02000 or 0xFED03000.
*_d = *_d & 3 | 0x80;
}
_q = dev.uncached_alias + HPET_GCAP_ID;
i = *_q; // i.u32[1]= period in femtoS (10e-15)
if (100000 < i.u32[1] < 1000000000) {
cnts.HPET_freq = 1000000000000000 / i.u32[1];
cnts.HPET_kHz_freq = 1000000000000 / i.u32[1];
_q = dev.uncached_alias + HPET_GEN_CONF;
*_q |= 1; // Enable counting
cnts.HPET_initial = HPET;
} else {
cnts.HPET_freq = 0;
cnts.HPET_kHz_freq = 0;
cnts.HPET_initial = 0;
}
}
U0 Reboot() { // Hardware reset.
CLI if (mp_cnt > 1) MPHalt;
*0x472(U16 *) = 0;
OutU8(0x70, 0x8F);
OutU8(0x71, 0x00);
OutU8(0x70, 0x00);
OutU8(0x92, InU8(0x92) | 1);
SysHlt;
}
U0 KMain() { // Continued from $LK,"KStart64.HC",A="FF:::/Kernel/KStart64.HC,I32
// &KMain"$
CBlkDev *bd;
OutU8(0x61, InU8(0x61) & ~3); // Snd;
adam_task = Fs;
BlkPoolsInit;
SysGlblsInit;
Mem32DevInit;
UncachedAliasAlloc;
LoadKernel;
SysGrInit;
StrCpy(Fs->task_name, "Adam Task CPU00");
StrCpy(Fs->task_title, Fs->task_name);
Fs->title_src = TTS_TASK_NAME;
Fs->win_right = text.cols - 2;
Fs->win_top++;
TaskDerivedValsUpdate;
SysDefinesLoad;
Core0Init;
IntInit1;
// Before this point use $LK,"Snd",A="MN:Snd"$() and $LK,"Busy",A="MN:Busy"$()
// to debug.After this point, use $LK,"RawPrint",A="MN:RawPrint"$()
LBts(&sys_run_level, RLf_RAW);
"TempleOS V%5.3f\t%D %T\n\n", sys_os_version, sys_compile_time,
sys_compile_time;
TimersInit;
if (BIOSTotalMem < ToI64(0.95 * MEM_MIN_MEG * 0x100000))
RawPrint(4000, "!!! Requires $TX," 512Meg ",D=" DD_MEM_MIN_MEG
"$ of RAM Memory !!!");
IntsInit;
"Enable IRQ's\n";
SetRFlags(RFLAGG_NORMAL);
Busy(2000);
IntInit2;
LBts(&sys_run_level, RLf_INTERRUPTS);
TimeCal;
KbdMsInit;
MsInit;
KbdInit;
Spawn(&MsHardDrvrInstall);
BlkDevsInitAll;
"DskChg(':');\n";
DskChg(':');
#exe {
StreamPrint("HomeSet(\"%s\");\n"
"blkdev.ins_base0=%d;blkdev.ins_base1=%d;blkdev.ins_unit =%d;\n",
kernel_cfg->home_dir, blkdev.ins_base0, blkdev.ins_base1,
blkdev.ins_unit);
}
Gs->idle_task->cur_dv = blkdev.let_to_drv[*blkdev.home_dir - 'A'];
DrvRep;
if (blkdev.dvd_boot_is_good) {
bd = Let2BlkDev(':');
if (bd->type == BDT_ATAPI) {
blkdev.ins_base0 = bd->base0;
blkdev.ins_base1 = bd->base1;
blkdev.ins_unit = bd->unit;
}
}
LBts(&sys_run_level, RLf_BLKDEV);
#exe {
if (!kernel_cfg->opts[CFG_NO_MP])
StreamPrint("\"MultiCore Start\\n\\n\";"
"Core0StartMP;"
"LBts(&sys_run_level,RLf_MP);");
}
;
"Loading Compiler\n";
Cd("/Compiler");
Load("Compiler", LDF_SILENT);
LBts(&sys_run_level, RLf_COMPILER);
DbgMode(OFF);
cnts.time_stamp_freq_initial = TimeCal;
Cd("/");
try ExeFile("StartOS"); // Continues $LK,"/StartOS.HC",A="FL:/StartOS.HC,1"$
catch {
Raw(ON);
Silent(OFF);
GetOutOfDollar;
PutExcept;
Dbg;
}
LBts(&sys_run_level, RLf_ADAM_SERVER);
SrvTaskCont; // Never to return
}
asm { ALIGN 16,OC_NOP
SYS_KERNEL_END::
#exe {
if (kernel_cfg->opts[CFG_DBG_DISTRO])
StreamPrint("DU8 0x%X-(SYS_KERNEL_END-SYS_KERNEL+"
"BOOT_RAM_BASE+sizeof(CBinFile)) DUP (0);"
"BINFILE \"%s\";",kernel_cfg->dbg_distro_start,
kernel_cfg->dbg_distro_file);
}
;
}