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 {
if (kernel_cfg->opts[CFG_MOUNT_IDE_AUTO])
StreamPrint("MountIDEAuto;");
StreamPrint("#exe {Option(OPTf_WARN_PAREN,OFF);}");
StreamDoc(kernel_cfg->add_dev);
StreamPrint("#exe {Option(OPTf_WARN_PAREN,ON);}");
};
}