I64 SATARep()
{
    I64          /*bdf, */i, j, num = 0;
    CAHCIPort   *port;
//  CPCIDev     *pci;
    CBlkDev     *temp_blkdev;
    U16         *st, *model, *serial;

    "\nAHCI version %X.%1X%1X\n",
        blkdev.ahci_hba->version >> 16, (blkdev.ahci_hba->version & 0xFF00) >> 8, blkdev.ahci_hba->version & 0xFF;

/*  if (dev.pci_head)
    {
        pci = PCIDevFind(PCIC_STORAGE, PCISC_AHCI);
//      ClassRep(pci);
        "$PURPLE$$HL,1$Bus: 0x%02X, Dev: 0x%02X, Fun: 0x%02X$HL,0$$FG$\n\n", pci->bus, pci->dev, pci->fun;
        "$PURPLE$Vendor$FG$: $BLACK$%s$FG$\n", pci->vendor_str;
        "$PURPLE$Device$FG$: $BLACK$%s$FG$\n", pci->dev_id_str;
    }   
    else
    {
        bdf = PCIClassFind(PCIC_STORAGE << 16 | PCISC_AHCI << 8 + 1, 0);
        "Bus:%02X, Dev:%02X, Fun:%02X", bdf.u8[2], bdf.u8[1], bdf.u8[0];
        "HBA Base Address: 0x%X", PCIReadU32(bdf.u8[2], bdf.u8[1], bdf.u8[0], PCIR_BASE5) & ~0x1F;
    }
*/


    if (blkdev.ahci_hba)
    {
        "\nImplemented Ports:\n\n";
        for (i = 0; i < AHCI_MAX_PORTS; i++)
        {
            if (Bt(&blkdev.ahci_hba->ports_implemented, i))
            {
                port = &blkdev.ahci_hba->ports[i];

                if (port->signature == AHCI_PxSIG_ATAPI || port->signature == AHCI_PxSIG_ATA)
                {
                    "$PURPLE$ $BT,\"%d\",LM=\"%d\n\"$$FG$", i, i;

                    if (port->signature == AHCI_PxSIG_ATA)
                        "$LM,4$$RED$Hard Drive   $LTBLUE$ATA$FG$\n";
                    else if (port->signature == AHCI_PxSIG_ATAPI)
                        "$LM,4$$RED$CD/DVD Drive $LTBLUE$ATAPI$FG$\n";
//                  else
//                      "$LM,4$$RED$Unknown      $LTBLUE$0x%0X$FG$\n", port->signature;

                    "$LM,0$\n\t";

                    temp_blkdev = CAlloc(sizeof(CBlkDev));
                    AHCIPortInit(temp_blkdev, port, i);
                    "\n\t";

                    if (temp_blkdev->dev_id_record)
                    {
                        st = CAlloc(40 + 1);
                        for (j = 0; j < 20; j++)
                            st[j] = EndianU16(temp_blkdev->dev_id_record[27 + j]);
                        model = MStrUtil(st, SUF_REM_LEADING | SUF_REM_TRAILING);
                        "Model:  %s\n\t", model;
                        Free(st);
                        Free(model);

                        st = CAlloc(20 + 1);
                        for (j = 0; j < 10; j++)
                            st[j] = EndianU16(temp_blkdev->dev_id_record[10 + j]);
                        serial = MStrUtil(st, SUF_REM_LEADING | SUF_REM_TRAILING);
                        "Serial: %s\n", serial;
                        Free(st);
                        Free(serial);
                    }

                    "\n";

                    BlkDevDel(temp_blkdev);
                    Free(temp_blkdev);
                }
                num++;
            }
        }
    }
    else
        "$HL,1$blkdev.ahci_hba$HL,0$ is NULL !\n\n";

    return num;
}

#help_index "Install;File/Cmd Line (Typically);Cmd Line (Typically);"
U8 Mount2(U8 boot_drive_let, CDoc *_doc, Bool _caller_is_prtdisk)
{//If _doc, called by ::/Kernel/KConfig.CC else called by Mount().
    I64      count, total = 0, num_hints, drv_let, type, unit, prt_num, port = -1;
    U8       blks_buf[STR_LEN], addr_buf[STR_LEN], port_str[STR_LEN],
            *filename = NULL, *filename2 = NULL, res = 0;
    Bool     whole_drive, make_free;
    CDoc    *doc;

    if (boot_drive_let)
        boot_drive_let = Letter2Letter(boot_drive_let);
    do
    {
        count = 0;
        if (!_doc)
            DriveRep;

        "\n****** Mount Drives ******\n"
        "$GREEN$A$FG$-$GREEN$B$FG$ are RAM drives.\n"
        "$GREEN$C$FG$-$GREEN$L$FG$ are ATA hard drives.\n"
        "$GREEN$M$FG$-$GREEN$P$FG$ are ISO file read drives.\n"
        "$GREEN$Q$FG$-$GREEN$S$FG$ are ISO file write drives.\n"
        "$GREEN$T$FG$-$GREEN$Z$FG$ are ATAPI CD/DVD drives.\n"
        "\nDrive Letter ($PURPLE$<ENTER>$FG$ to exit):";
        drv_let = Letter2Letter(CharGet);
        '\n';
        if (type = Letter2BlkDevType(drv_let))
        {
            whole_drive = FALSE;
            if (_doc)
            { //Called by ::/Kernel/KConfig.CC
                doc = _doc;
                make_free = FALSE;
            }
            else
            { //Called by Mount()
                doc = DocNew;
                DocPrint(doc, "CBlkDev *bd;\n");
                make_free = TRUE;
            }
            unit = 0;
            prt_num = I64_MIN;
            switch (type)
            {
                case BDT_RAM:
                    "Addr of RAM disk ($PURPLE$<ENTER>$FG$ to MAlloc):";
                    StrNGet(addr_buf, STR_LEN);
                case BDT_ISO_FILE_WRITE:
                    "Blks of 512 bytes:";
                    StrNGet(blks_buf, STR_LEN);
                    break;

                case BDT_ISO_FILE_READ:
                    filename = StrGet("File Name:");
                    break;

                case BDT_ATA:
                    prt_num = I64Get("Partition Num (Default=All):", prt_num);
                case BDT_ATAPI:
                    num_hints = SATARep;
                    if (type == BDT_ATAPI && boot_drive_let)
                        "<ENTER> to use booted CD/DVD\n"; //Only ::/Kernel/KConfig.CC
                    do
                    {
                        if (num_hints)
                            "Enter port number: \n";
                        StrNGet(port_str, STR_LEN);
                    }
                    while ((0 > Str2I64(port_str) || Str2I64(port_str) > num_hints - 1) &&
                            (type != BDT_ATAPI || !boot_drive_let));

                    port = Str2I64(port_str);
                    break;
            }
            DocPrint(doc, "\"bd = BlkDevNextFreeSlot('%C', %d); bd->unit = %d;\n\";\n", drv_let, type, unit);
            DocPrint(doc, "bd = BlkDevNextFreeSlot(\'%C\', %d); bd->unit = %d;\n", drv_let, type, unit);
            if (port != -1 && *port_str)
            {
                DocPrint(doc, "\"AHCIPortInit(bd, &blkdev.ahci_hba->ports[%d], %d);\n\";\n", port, port);
                DocPrint(doc, "AHCIPortInit(bd, &blkdev.ahci_hba->ports[%d], %d);\n", port, port);

            }

            switch (type)
            {
                case BDT_RAM:
                    if (!*addr_buf) StrCopy(addr_buf, "0");
                    DocPrint(doc, "bd->RAM_disk = %s;\n", addr_buf);
                case BDT_ISO_FILE_WRITE:
                    if (!*blks_buf) StrCopy(blks_buf, "0");
                    DocPrint(doc, "bd->max_blk = (%s) - 1;\n", blks_buf);
                    DocPrint(doc, "bd->drv_offset = 19 << 2 + (DVD_BLK_SIZE * 2 + DVD_BOOT_LOADER_SIZE) / BLK_SIZE;\n");
                    break;

                case BDT_ISO_FILE_READ:
                    filename2 = FileNameAbs(filename);
                    DocPrint(doc, "bd->file_disk_name = SysStrNew(\"%s\");\n", filename2);
                    DocPrint(doc, "bd->drv_offset = 19 << 2 + (DVD_BLK_SIZE * 2 + DVD_BOOT_LOADER_SIZE) / BLK_SIZE;\n");
                    break;

                case BDT_ATA:
                case BDT_ATAPI:
                    if (type == BDT_ATAPI && !*port_str && _doc)
                    {
                        DocPrint(doc, "\"AHCIBootDVDProbeAll(bd);\n\";\n");
                        DocPrint(doc, "AHCIBootDVDProbeAll(bd);\n"); //Only ::/Kernel/KConfig.CC

                        if (drv_let == boot_drive_let)
                            make_free = TRUE;
                    }
                    if (type == BDT_ATA && _caller_is_prtdisk)
                    {
                        "\nReformat WHOLE drive!";
                        whole_drive = YorN;
                    }
                    break;
            }
            DocPrint(doc, "\"BlkDevAdd(bd, 0x%0X, %d, %d);\n\";\n", prt_num, whole_drive, make_free);
            DocPrint(doc, "BlkDevAdd(bd, 0x%0X, %d, %d);\n", prt_num, whole_drive, make_free);
            if (_doc) //Called by ::/Kernel/KConfig.CC
                count++;
            else
            { //Called by Mount()
                if ((count = ExeDoc(doc)) && whole_drive)
                {
                    if (_caller_is_prtdisk)
                    {
                        res = drv_let;
                        DiskPart(drv_let, 1.0); //First mount whole drive.
                    }
                    else
                        DiskPart(drv_let);
                }
                DocDel(doc);
            }
        }
        total += count;
    }
    while (count && !_caller_is_prtdisk || !total && _doc); //At least 1 if Called by ::/Kernel/KConfig.CC

    Free(filename);
    Free(filename2);

    return res;
}

public U8 Mount(Bool caller_is_prtdisk=FALSE)
{//Mount drives. Called from DiskPart(Mount).
    return Mount2(0, NULL, caller_is_prtdisk);
}

public U0 Unmount(U8 drv_let=0)
{//Unmount drive(s).
    BlkDevDel(Letter2BlkDev(drv_let));
}

public U8 MountFile(U8 *filename)
{//Mount ISO.C file.
    U8      *filename2 = ExtDefault(filename, "ISO.C"), *filename3 = FileNameAbs(filename2);
    CDrive  *drive = DriveMakeFreeSlot(DriveNextFreeLet('M')); //First BDT_ISO_FILE_READ
    CBlkDev *bd = BlkDevNextFreeSlot(drive->drv_let, BDT_ISO_FILE_READ);

    bd->drv_offset = 19 << 2 + (DVD_BLK_SIZE * 2 + DVD_BOOT_LOADER_SIZE) / BLK_SIZE;
    bd->file_disk_name = SysStrNew(filename3);
    BlkDevAdd(bd,, TRUE, TRUE);
    Free(filename3);
    Free(filename2);

    return drive->drv_let;
}