示例#1
0
文件: vdd.c 项目: jkaessens/opencbm
VOID
VDDDispatch(VOID)
{
    FUNCTIONCODE functioncode;
    CBM_FILE cbmfile;
    BOOLEAN error;

    FUNC_ENTER();

    functioncode = getDL();

    error = FALSE;

    // convert to BX value into a CBM_FILE
    switch (functioncode)
    {
    case FC_VDD_USLEEP:
    case FC_DRIVER_OPEN:
    case FC_GET_DRIVER_NAME:
        // FC_VDD_USLEEP, FC_DRIVER_OPEN and FC_GET_DRIVER_NAME are special,
        // they do not have a BX input.
        break;

    default:
        cbmfile = vdd_cbmfile_get(getBX());

        if (cbmfile == INVALID_HANDLE_VALUE)
        {
            DBG_ERROR((DBG_PREFIX "invalid BX given: %04x", getBX()));
            error = TRUE;
        }
        break;
    }

    if (!error)
    {
        switch (functioncode)
        {
        case FC_DRIVER_OPEN:     error = vdd_driver_open();          break;
        case FC_DRIVER_CLOSE:    error = vdd_driver_close(cbmfile);  break;
        case FC_LISTEN:          error = vdd_listen(cbmfile);        break;
        case FC_TALK:            error = vdd_talk(cbmfile);          break;
        case FC_OPEN:            error = vdd_open(cbmfile);          break;
        case FC_CLOSE:           error = vdd_close(cbmfile);         break;
        case FC_RAW_READ:        error = vdd_raw_read(cbmfile);      break;
        case FC_RAW_WRITE:       error = vdd_raw_write(cbmfile);     break;
        case FC_UNLISTEN:        error = vdd_unlisten(cbmfile);      break;
        case FC_UNTALK:          error = vdd_untalk(cbmfile);        break;
        case FC_GET_EOI:         error = vdd_get_eoi(cbmfile);       break;
        case FC_CLEAR_EOI:       error = vdd_clear_eoi(cbmfile);     break;
        case FC_RESET:           error = vdd_reset(cbmfile);         break;
        case FC_PP_READ:         error = vdd_pp_read(cbmfile);       break;
        case FC_PP_WRITE:        error = vdd_pp_write(cbmfile);      break;
        case FC_IEC_POLL:        error = vdd_iec_poll(cbmfile);      break;
        case FC_IEC_GET:         error = vdd_iec_get(cbmfile);       break;
        case FC_IEC_SET:         error = vdd_iec_set(cbmfile);       break;
        case FC_IEC_RELEASE:     error = vdd_iec_release(cbmfile);   break;
        case FC_IEC_SETRELEASE:  error = vdd_iec_setrelease(cbmfile); break;
        case FC_IEC_WAIT:        error = vdd_iec_wait(cbmfile);      break;
        case FC_UPLOAD:          error = vdd_upload(cbmfile);        break;
        case FC_DEVICE_STATUS:   error = vdd_device_status(cbmfile); break; 
        case FC_EXEC_COMMAND:    error = vdd_exec_command(cbmfile);  break;
        case FC_IDENTIFY:        error = vdd_identify(cbmfile);      break;
        case FC_IDENTIFY_XP1541: error = vdd_identify_xp1541(cbmfile); break;
        case FC_GET_DRIVER_NAME: error = vdd_get_driver_name();      break;

        case FC_VDD_USLEEP:      error = vdd_usleep();               break;

        case FC_VDD_INSTALL_IOHOOK:   error = vdd_install_iohook(cbmfile);   break;
        case FC_VDD_UNINSTALL_IOHOOK: error = vdd_uninstall_iohook(cbmfile); break;

        default:
            // this function is not implemented:
            DBG_ERROR((DBG_PREFIX "unknown function code in DL: %02x", functioncode));
            error = TRUE;
            break;
        }
    }

    setCF(error ? 1 : 0);

    FUNC_LEAVE();
}
示例#2
0
/*static*/
VOID WINAPI BiosDiskService(LPWORD Stack)
{
    BYTE Drive;
    PDISK_IMAGE DiskImage;

    switch (getAH())
    {
        /* Disk -- Reset Disk System */
        case 0x00:
        {
            Drive = getDL();

            if (Drive & 0x80)
            {
                AllDisksReset();

                /* Return success */
                setAH(0x00);
                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
                break;
            }

            Drive &= ~0x80;

            if (Drive >= ARRAYSIZE(FloppyDrive))
            {
                DPRINT1("BiosDiskService(0x00): Drive number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            // TODO: Reset drive

            /* Return success */
            setAH(0x00);
            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            break;
        }

        /* Disk -- Get Status of Last Operation */
        case 0x01:
        {
            BYTE LastOperationStatus = 0x00;

            Drive = getDL();
            DiskImage = GetDisk(Drive);
            if (!DiskImage || !IsDiskPresent(DiskImage))
            {
                DPRINT1("BiosDiskService(0x01): Disk number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            LastOperationStatus = DiskImage->LastOperationStatus;

            if (Drive & 0x80)
                Bda->LastDiskOperation = LastOperationStatus;
            else
                Bda->LastDisketteOperation = LastOperationStatus;

            /* Return last error */
            setAH(LastOperationStatus);
            if (LastOperationStatus == 0x00)
                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            else
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;

            break;
        }

        /* Disk -- Read Sectors into Memory */
        case 0x02:
        {
            BYTE Status;
            BYTE Head = getDH();
            BYTE NumSectors = getAL();

            // CH: Low eight bits of cylinder number
            // CL: High two bits of cylinder (bits 6-7, hard disk only)
            WORD Cylinder = MAKEWORD(getCH(), (getCL() >> 6) & 0x02);

            // CL: Sector number 1-63 (bits 0-5)
            BYTE Sector = (getCL() & 0x3F); // 1-based

            Drive = getDL();
            DiskImage = GetDisk(Drive);
            if (!DiskImage || !IsDiskPresent(DiskImage))
            {
                DPRINT1("BiosDiskService(0x02): Disk number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            /* Read the sectors */
            Status = ReadDisk(DiskImage, Cylinder, Head, Sector, NumSectors);
            if (Status == 0x00)
            {
                /* Return success */
                setAH(0x00);
                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            }
            else
            {
                DPRINT1("BiosDiskService(0x02): Error when reading from disk number 0x%02X (0x%02X)\n", Drive, Status);

                /* Return error */
                setAH(Status);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
            }

            break;
        }

        /* Disk -- Write Disk Sectors */
        case 0x03:
        {
            BYTE Status;
            BYTE Head = getDH();
            BYTE NumSectors = getAL();

            // CH: Low eight bits of cylinder number
            // CL: High two bits of cylinder (bits 6-7, hard disk only)
            WORD Cylinder = MAKEWORD(getCH(), (getCL() >> 6) & 0x02);

            // CL: Sector number 1-63 (bits 0-5)
            BYTE Sector = (getCL() & 0x3F); // 1-based

            Drive = getDL();
            DiskImage = GetDisk(Drive);
            if (!DiskImage || !IsDiskPresent(DiskImage))
            {
                DPRINT1("BiosDiskService(0x03): Disk number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            /* Write the sectors */
            Status = WriteDisk(DiskImage, Cylinder, Head, Sector, NumSectors);
            if (Status == 0x00)
            {
                /* Return success */
                setAH(0x00);
                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            }
            else
            {
                DPRINT1("BiosDiskService(0x03): Error when writing to disk number 0x%02X (0x%02X)\n", Drive, Status);

                /* Return error */
                setAH(Status);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
            }

            break;
        }

        /* Disk -- Verify Disk Sectors */
        case 0x04:

        /* Floppy/Fixed Disk -- Format Track */
        case 0x05:

        /* Fixed Disk -- Format Track and Set Bad Sector Flags */
        case 0x06:

        /* Fixed Disk -- Format Drive starting at Given Track */
        case 0x07:
            goto Default;

        /* Disk -- Get Drive Parameters */
        case 0x08:
        {
            WORD MaxCylinders;
            BYTE MaxHeads;
            BYTE PresentDrives = 0;
            BYTE i;

            Drive = getDL();
            DiskImage = GetDisk(Drive);
            if (!DiskImage || !IsDiskPresent(DiskImage))
            {
                DPRINT1("BiosDiskService(0x08): Disk number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            // Minus 2 because it's the maximum cylinder number (not count),
            // and the last cylinder is reserved (for compatibility with BIOSes
            // which reserve it for testing purposes).
            MaxCylinders = DiskImage->DiskInfo.Cylinders - 2;
            // Minus 1 because it's the maximum head number (not count).
            MaxHeads     = DiskImage->DiskInfo.Heads - 1;

            // CL: Sector number 1-63 (bits 0-5)
            //     High two bits of cylinder (bits 6-7, hard disk only)
            setCL((DiskImage->DiskInfo.Sectors & 0x3F) |
                  ((HIBYTE(MaxCylinders) & 0x02) << 6));
            // CH: Low eight bits of cylinder number
            setCH(LOBYTE(MaxCylinders));

            setDH(MaxHeads);

            if (Drive & 0x80)
            {
                /* Count the number of active HDDs */
                for (i = 0; i < ARRAYSIZE(HardDrive); ++i)
                {
                    if (IsDiskPresent(HardDrive[i]))
                        ++PresentDrives;
                }

                /* Reset ES:DI to NULL */
                // FIXME: NONONO!! Apps expect (for example, MS-DOS kernel)
                // that this function does not modify ES:DI if it was called
                // for a HDD.
                // setES(0x0000);
                // setDI(0x0000);
            }
            else
            {
                /* Count the number of active floppies */
                for (i = 0; i < ARRAYSIZE(FloppyDrive); ++i)
                {
                    if (IsDiskPresent(FloppyDrive[i]))
                        ++PresentDrives;
                }

                /* ES:DI points to the floppy parameter table */
                setES(HIWORD(((PULONG)BaseAddress)[0x1E]));
                setDI(LOWORD(((PULONG)BaseAddress)[0x1E]));
            }
            setDL(PresentDrives);

            setBL(DiskImage->DiskType); // DiskGeometryList[DiskImage->DiskType].biosval
            setAL(0x00);

            /* Return success */
            setAH(0x00);
            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            break;
        }

        /* Hard Disk -- Initialize Controller with Drive Parameters */
        case 0x09:

        /* Hard Disk -- Read Long Sectors */
        case 0x0A:

        /* Hard Disk -- Write Long Sectors */
        case 0x0B:
            goto Default;

        /* Hard Disk -- Seek to Cylinder */
        case 0x0C:
        {
            BYTE Status;
            BYTE Head = getDH();

            // CH: Low eight bits of cylinder number
            // CL: High two bits of cylinder (bits 6-7, hard disk only)
            WORD Cylinder = MAKEWORD(getCH(), (getCL() >> 6) & 0x02);

            // CL: Sector number 1-63 (bits 0-5)
            BYTE Sector = (getCL() & 0x3F); // 1-based

            Drive = getDL();
            if (!(Drive & 0x80))
            {
                DPRINT1("BiosDiskService(0x0C): Disk number 0x%02X is not a HDD\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            DiskImage = GetDisk(Drive);
            if (!DiskImage || !IsDiskPresent(DiskImage))
            {
                DPRINT1("BiosDiskService(0x0C): Disk number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            /* Set position */
            Status = SeekDisk(DiskImage, Cylinder, Head, Sector);
            if (Status == 0x00)
            {
                /* Return success */
                setAH(0x00);
                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            }
            else
            {
                DPRINT1("BiosDiskService(0x0C): Error when seeking in disk number 0x%02X (0x%02X)\n", Drive, Status);

                /* Return error */
                setAH(Status);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
            }

            break;
        }

        /* Hard Disk -- Reset Hard Disks */
        case 0x0D:
        {
            // FIXME: Should do what 0x11 does.
            UNIMPLEMENTED;
        }

        /* Hard Disk -- Read Sector Buffer (XT only) */
        case 0x0E:

        /* Hard Disk -- Write Sector Buffer (XT only) */
        case 0x0F:
            goto Default;

        /* Hard Disk -- Check if Drive is ready */
        case 0x10:
        {
            Drive = getDL();
            if (!(Drive & 0x80))
            {
                DPRINT1("BiosDiskService(0x10): Disk number 0x%02X is not a HDD\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            DiskImage = GetDisk(Drive);
            if (!DiskImage || !IsDiskPresent(DiskImage))
            {
                DPRINT1("BiosDiskService(0x10): Disk number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            /* Return success */
            setAH(0x00);
            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            break;
        }

        /* Hard Disk -- Recalibrate Drive */
        case 0x11:
        {
            BYTE Status;

            Drive = getDL();
            if (!(Drive & 0x80))
            {
                DPRINT1("BiosDiskService(0x11): Disk number 0x%02X is not a HDD\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            DiskImage = GetDisk(Drive);
            if (!DiskImage || !IsDiskPresent(DiskImage))
            {
                DPRINT1("BiosDiskService(0x11): Disk number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            /* Set position to zero */
            Status = SeekDisk(DiskImage, /*Cylinder*/ 0, /*Head*/ 0, /*Sector*/ 1);
            if (Status == 0x00)
            {
                /* Return success */
                setAH(0x00);
                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            }
            else
            {
                DPRINT1("BiosDiskService(0x11): Error when recalibrating disk number 0x%02X (0x%02X)\n", Drive, Status);

                /* Return error */
                setAH(Status);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
            }

            break;
        }

        /* Hard Disk -- Controller RAM Diagnostic */
        case 0x12:

        /* Hard Disk -- Drive Diagnostic */
        case 0x13:

        /* Hard Disk -- Controller Internal Diagnostic */
        case 0x14:
            goto Default;

        /* Disk -- Get Disk Type */
        case 0x15:
        {
            Drive = getDL();
            DiskImage = GetDisk(Drive);
            if (!DiskImage || !IsDiskPresent(DiskImage))
            {
                DPRINT1("BiosDiskService(0x15): Disk number 0x%02X invalid\n", Drive);

                /* Return error */
                setAH(0x01);
                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                break;
            }

            if (Drive & 0x80)
            {
                ULONG NumSectors;

                /* Hard disk */
                setAH(0x03);

                /* Number of 512-byte sectors in CX:DX */
                NumSectors = (ULONG)((ULONG)DiskImage->DiskInfo.Cylinders * DiskImage->DiskInfo.Heads)
                                                                          * DiskImage->DiskInfo.Sectors;
                setCX(HIWORD(NumSectors));
                setDX(LOWORD(NumSectors));
            }
            else
            {
                /* Floppy */
                setAH(0x01);
            }

            /* Return success */
            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
            break;
        }

        /* Floppy Disk -- Detect Disk Change */
        case 0x16:

        /* Floppy Disk -- Set Disk Type for Format */
        case 0x17:

        /* Disk -- Set Media Type for Format */
        case 0x18:
            goto Default;

        default: Default:
        {
            DPRINT1("BIOS Function INT 13h, AH = 0x%02X, AL = 0x%02X, BH = 0x%02X NOT IMPLEMENTED\n",
                    getAH(), getAL(), getBH());
        }
    }
}