示例#1
0
/*
 * root hub control
 */
static int musb_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
                              void *buffer, int transfer_len,
                              struct devrequest *cmd)
{
    int leni = transfer_len;
    int len = 0;
    int stat = 0;
    u32 datab[4];
    const u8 *data_buf = (u8 *) datab;
    u16 bmRType_bReq;
    u16 wValue;
    u16 wIndex;
    u16 wLength;
    u16 int_usb;

    if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
        debug("Root-Hub submit IRQ: NOT implemented\n");
        return 0;
    }

    bmRType_bReq = cmd->requesttype | (cmd->request << 8);
    wValue = swap_16(cmd->value);
    wIndex = swap_16(cmd->index);
    wLength = swap_16(cmd->length);

    debug("--- HUB ----------------------------------------\n");
    debug("submit rh urb, req=%x val=%#x index=%#x len=%d\n",
          bmRType_bReq, wValue, wIndex, wLength);
    debug("------------------------------------------------\n");

    switch (bmRType_bReq) {
    case RH_GET_STATUS:
        debug("RH_GET_STATUS\n");

        *(__u16 *) data_buf = swap_16(1);
        len = 2;
        break;

    case RH_GET_STATUS | RH_INTERFACE:
        debug("RH_GET_STATUS | RH_INTERFACE\n");

        *(__u16 *) data_buf = swap_16(0);
        len = 2;
        break;

    case RH_GET_STATUS | RH_ENDPOINT:
        debug("RH_GET_STATUS | RH_ENDPOINT\n");

        *(__u16 *) data_buf = swap_16(0);
        len = 2;
        break;

    case RH_GET_STATUS | RH_CLASS:
        debug("RH_GET_STATUS | RH_CLASS\n");

        *(__u32 *) data_buf = swap_32(0);
        len = 4;
        break;

    case RH_GET_STATUS | RH_OTHER | RH_CLASS:
        debug("RH_GET_STATUS | RH_OTHER | RH_CLASS\n");

        int_usb = readw(&musbr->intrusb);
        if (int_usb & MUSB_INTR_CONNECT) {
            port_status |= USB_PORT_STAT_CONNECTION
                           | (USB_PORT_STAT_C_CONNECTION << 16);
            port_status |= USB_PORT_STAT_HIGH_SPEED
                           | USB_PORT_STAT_ENABLE;
        }

        if (port_status & USB_PORT_STAT_RESET)
            musb_port_reset(0);

        *(__u32 *) data_buf = swap_32(port_status);
        len = 4;
        break;

    case RH_CLEAR_FEATURE | RH_ENDPOINT:
        debug("RH_CLEAR_FEATURE | RH_ENDPOINT\n");

        switch (wValue) {
        case RH_ENDPOINT_STALL:
            debug("C_HUB_ENDPOINT_STALL\n");
            len = 0;
            break;
        }
        port_status &= ~(1 << wValue);
        break;

    case RH_CLEAR_FEATURE | RH_CLASS:
        debug("RH_CLEAR_FEATURE | RH_CLASS\n");

        switch (wValue) {
        case RH_C_HUB_LOCAL_POWER:
            debug("C_HUB_LOCAL_POWER\n");
            len = 0;
            break;

        case RH_C_HUB_OVER_CURRENT:
            debug("C_HUB_OVER_CURRENT\n");
            len = 0;
            break;
        }
        port_status &= ~(1 << wValue);
        break;

    case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
        debug("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS\n");

        switch (wValue) {
        case RH_PORT_ENABLE:
            len = 0;
            break;

        case RH_PORT_SUSPEND:
            len = 0;
            break;

        case RH_PORT_POWER:
            len = 0;
            break;

        case RH_C_PORT_CONNECTION:
            len = 0;
            break;

        case RH_C_PORT_ENABLE:
            len = 0;
            break;

        case RH_C_PORT_SUSPEND:
            len = 0;
            break;

        case RH_C_PORT_OVER_CURRENT:
            len = 0;
            break;

        case RH_C_PORT_RESET:
            len = 0;
            break;

        default:
            debug("invalid wValue\n");
            stat = USB_ST_STALLED;
        }

        port_status &= ~(1 << wValue);
        break;

    case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
        debug("RH_SET_FEATURE | RH_OTHER | RH_CLASS\n");

        switch (wValue) {
        case RH_PORT_SUSPEND:
            len = 0;
            break;

        case RH_PORT_RESET:
            musb_port_reset(1);
            len = 0;
            break;

        case RH_PORT_POWER:
            len = 0;
            break;

        case RH_PORT_ENABLE:
            len = 0;
            break;

        default:
            debug("invalid wValue\n");
            stat = USB_ST_STALLED;
        }

        port_status |= 1 << wValue;
        break;

    case RH_SET_ADDRESS:
        debug("RH_SET_ADDRESS\n");

        rh_devnum = wValue;
        len = 0;
        break;

    case RH_GET_DESCRIPTOR:
        debug("RH_GET_DESCRIPTOR: %x, %d\n", wValue, wLength);

        switch (wValue) {
        case (USB_DT_DEVICE << 8):	/* device descriptor */
            len = min_t(unsigned int,
                        leni, min_t(unsigned int,
                                    sizeof(root_hub_dev_des),
                                    wLength));
            data_buf = root_hub_dev_des;
            break;

        case (USB_DT_CONFIG << 8):	/* configuration descriptor */
            len = min_t(unsigned int,
                        leni, min_t(unsigned int,
                                    sizeof(root_hub_config_des),
                                    wLength));
            data_buf = root_hub_config_des;
            break;

        case ((USB_DT_STRING << 8) | 0x00):	/* string 0 descriptors */
            len = min_t(unsigned int,
                        leni, min_t(unsigned int,
                                    sizeof(root_hub_str_index0),
                                    wLength));
            data_buf = root_hub_str_index0;
            break;

        case ((USB_DT_STRING << 8) | 0x01):	/* string 1 descriptors */
            len = min_t(unsigned int,
                        leni, min_t(unsigned int,
                                    sizeof(root_hub_str_index1),
                                    wLength));
            data_buf = root_hub_str_index1;
            break;

        default:
            debug("invalid wValue\n");
            stat = USB_ST_STALLED;
        }

        break;

    case RH_GET_DESCRIPTOR | RH_CLASS: {
        u8 *_data_buf = (u8 *) datab;
        debug("RH_GET_DESCRIPTOR | RH_CLASS\n");

        _data_buf[0] = 0x09;	/* min length; */
        _data_buf[1] = 0x29;
        _data_buf[2] = 0x1;	/* 1 port */
        _data_buf[3] = 0x01;	/* per-port power switching */
        _data_buf[3] |= 0x10;	/* no overcurrent reporting */

        /* Corresponds to data_buf[4-7] */
        _data_buf[4] = 0;
        _data_buf[5] = 5;
        _data_buf[6] = 0;
        _data_buf[7] = 0x02;
        _data_buf[8] = 0xff;

        len = min_t(unsigned int, leni,
                    min_t(unsigned int, data_buf[0], wLength));
        break;
    }

    case RH_GET_CONFIGURATION:
        debug("RH_GET_CONFIGURATION\n");

        *(__u8 *) data_buf = 0x01;
        len = 1;
        break;

    case RH_SET_CONFIGURATION:
        debug("RH_SET_CONFIGURATION\n");

        len = 0;
        break;

    default:
        debug("*** *** *** unsupported root hub command *** *** ***\n");
        stat = USB_ST_STALLED;
    }

    len = min_t(int, len, leni);
    if (buffer != data_buf)
        memcpy(buffer, data_buf, len);

    dev->act_len = len;
    dev->status = stat;
    debug("dev act_len %d, status %d\n", dev->act_len, dev->status);

    return stat;
}
示例#2
0
文件: af_lavcac3enc.c 项目: chyiz/mpv
static int filter_out(struct af_instance *af)
{
    af_ac3enc_t *s = af->priv;

    if (!s->pending)
        return 0;

    AVFrame *frame = av_frame_alloc();
    if (!frame) {
        MP_FATAL(af, "Could not allocate memory \n");
        return -1;
    }
    int err = -1;

    AVPacket pkt = {0};
    av_init_packet(&pkt);

#if HAVE_AVCODEC_NEW_CODEC_API
    // Send input as long as it wants.
    while (1) {
        err = read_input_frame(af, frame);
        if (err < 0)
            goto done;
        if (err == 0)
            break;
        err = -1;
        int lavc_ret = avcodec_send_frame(s->lavc_actx, frame);
        // On EAGAIN, we're supposed to read remaining output.
        if (lavc_ret == AVERROR(EAGAIN))
            break;
        if (lavc_ret < 0) {
            MP_FATAL(af, "Encode failed.\n");
            goto done;
        }
        s->encoder_buffered += s->input->samples;
        s->input->samples = 0;
    }
    int lavc_ret = avcodec_receive_packet(s->lavc_actx, &pkt);
    if (lavc_ret == AVERROR(EAGAIN)) {
        // Need to buffer more input.
        err = 0;
        goto done;
    }
    if (lavc_ret < 0) {
        MP_FATAL(af, "Encode failed.\n");
        goto done;
    }
#else
    err = read_input_frame(af, frame);
    if (err < 0)
        goto done;
    if (err == 0)
        goto done;
    err = -1;
    int ok;
    int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &pkt, frame, &ok);
    s->input->samples = 0;
    if (lavc_ret < 0 || !ok) {
        MP_FATAL(af, "Encode failed.\n");
        goto done;
    }
#endif

    MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n",
           pkt.size, s->pending->samples + s->input->samples);

    s->encoder_buffered -= AC3_FRAME_SIZE;

    struct mp_audio *out =
        mp_audio_pool_get(af->out_pool, af->data, s->out_samples);
    if (!out)
        goto done;
    mp_audio_copy_attributes(out, s->pending);

    int frame_size = pkt.size;
    int header_len = 0;
    char hdr[8];

    if (s->cfg_add_iec61937_header && pkt.size > 5) {
        int bsmod = pkt.data[5] & 0x7;
        int len = frame_size;

        frame_size = AC3_FRAME_SIZE * 2 * 2;
        header_len = 8;

        AV_WL16(hdr,     0xF872);   // iec 61937 syncword 1
        AV_WL16(hdr + 2, 0x4E1F);   // iec 61937 syncword 2
        hdr[5] = bsmod;             // bsmod
        hdr[4] = 0x01;              // data-type ac3
        AV_WL16(hdr + 6, len << 3); // number of bits in payload
    }

    if (frame_size > out->samples * out->sstride)
        abort();

    char *buf = (char *)out->planes[0];
    memcpy(buf, hdr, header_len);
    memcpy(buf + header_len, pkt.data, pkt.size);
    memset(buf + header_len + pkt.size, 0,
           frame_size - (header_len + pkt.size));
    swap_16((uint16_t *)(buf + header_len), pkt.size / 2);
    out->samples = frame_size / out->sstride;
    af_add_output_frame(af, out);

    err = 0;
done:
    av_packet_unref(&pkt);
    av_frame_free(&frame);
    update_delay(af);
    return err;
}
void process_endpoints(unsigned short usb2d0_intrin)
{
	/*will hold the packet received */
	struct usb_device_descriptor usb_device_packet;
	struct usb_configuration_descriptor usb_config_packet;
	struct usb_string_descriptor usb_string_packet;
	struct devrequest setup_packet;
	unsigned int *setup_packet_pt;
	unsigned char *packet_pt = NULL;
	int temp, temp1;

	int i;

	/*printf("{USB device} - endpoint 0x%X \n", usb2d0_intrin); */

	/*set usb address, seems to not work unless it is done in the next
	   interrupt, so that is why it is done this way */
	if (set_value != -1)
		*(unsigned char *)USB2D0_FADDR_8 = (unsigned char)set_value;

	/*endpoint 1 */
	if (usb2d0_intrin & 0x01) {
		setup_packet_pt = (unsigned int *)&setup_packet;

		/*copy packet */
		setup_packet_pt[0] = *(unsigned int *)USB2D0_FIFO_0;
		setup_packet_pt[1] = *(unsigned int *)USB2D0_FIFO_0;
		temp = *(unsigned int *)USB2D0_FIFO_0;
		temp1 = *(unsigned int *)USB2D0_FIFO_0;

		/*do some swapping */
		setup_packet.value = swap_16(setup_packet.value);
		setup_packet.index = swap_16(setup_packet.index);
		setup_packet.length = swap_16(setup_packet.length);

		/*clear rx packet */
		*(unsigned short *)USB2D0_INCSR0_8 = 0x48;

		/*printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", setup_packet.requesttype,
		   setup_packet.request, setup_packet.value,
		   setup_packet.index, setup_packet.length, temp, temp1 ); */

		switch (setup_packet.request) {
		case USB_REQ_GET_DESCRIPTOR:

			switch (setup_packet.value >> 8) {
			case USB_DT_DEVICE:
				/*create packet */
				usb_device_packet.bLength = 18;
				usb_device_packet.bDescriptorType =
				    USB_DT_DEVICE;
#ifdef USB_2_0_DEVICE
				usb_device_packet.bcdUSB = swap_16(0x200);
#else
				usb_device_packet.bcdUSB = swap_16(0x110);
#endif
				usb_device_packet.bDeviceClass = 0xff;
				usb_device_packet.bDeviceSubClass = 0;
				usb_device_packet.bDeviceProtocol = 0;
				usb_device_packet.bMaxPacketSize0 = 32;
				usb_device_packet.idVendor = swap_16(1);
				usb_device_packet.idProduct = swap_16(2);
				usb_device_packet.bcdDevice = swap_16(0x300);
				usb_device_packet.iManufacturer = 1;
				usb_device_packet.iProduct = 1;
				usb_device_packet.iSerialNumber = 1;
				usb_device_packet.bNumConfigurations = 1;

				/*put packet in fifo */
				packet_pt = (unsigned char *)&usb_device_packet;
				break;

			case USB_DT_CONFIG:
				/*create packet */
				usb_config_packet.bLength = 9;
				usb_config_packet.bDescriptorType =
				    USB_DT_CONFIG;
				usb_config_packet.wTotalLength = swap_16(25);
				usb_config_packet.bNumInterfaces = 1;
				usb_config_packet.bConfigurationValue = 1;
				usb_config_packet.iConfiguration = 0;
				usb_config_packet.bmAttributes = 0x40;
				usb_config_packet.bMaxPower = 0;

				/*put packet in fifo */
				packet_pt = (unsigned char *)&usb_config_packet;
				break;

			case USB_DT_STRING:
				/*create packet */
				usb_string_packet.bLength = 2;
				usb_string_packet.bDescriptorType =
				    USB_DT_STRING;
				usb_string_packet.wData[0] = 0x0094;

				/*put packet in fifo */
				packet_pt = (unsigned char *)&usb_string_packet;
				break;
			}

			/*put packet in fifo */
			for (i = 0; i < (setup_packet.length); i++) {
				*(unsigned char *)USB2D0_FIFO_0 = packet_pt[i];
			}

			/*give tx command */
			*(unsigned short *)USB2D0_INCSR0_8 = 0x0a;

			break;

		case USB_REQ_SET_ADDRESS:

			/*copy usb address */
			set_value = setup_packet.value;

			break;
		}

	}
示例#4
0
void flip_ucac3_star( UCAC3_STAR *star)
{
   swap_32( &star->ra);
   swap_32( &star->spd);
   swap_16( &star->mag1);
   swap_16( &star->mag2);
   swap_16( &star->mag_sigma);
   swap_16( &star->ra_sigma);
   swap_16( &star->dec_sigma);
   swap_16( &star->epoch_ra);
   swap_16( &star->epoch_dec);
   swap_32( &star->pm_ra);
   swap_32( &star->pm_dec);
   swap_16( &star->pm_ra_sigma);
   swap_16( &star->pm_dec_sigma);
   swap_32( &star->twomass_id);
   swap_16( &star->mag_j);
   swap_16( &star->mag_h);
   swap_16( &star->mag_k);
   swap_16( &star->sc_bmag);
   swap_16( &star->sc_rmag);
   swap_16( &star->sc_imag);
   swap_32( &star->running_number);
}
示例#5
0
void BIOSCALL int13_cdrom(uint16_t EHBX, disk_regs_t r)
{
    uint16_t            ebda_seg = read_word(0x0040,0x000E);
    uint8_t             device, status, locks;
    cdb_atapi           atapicmd;
    uint32_t            lba;
    uint16_t            count, segment, offset, size;
    bio_dsk_t __far     *bios_dsk;
    int13ext_t __far    *i13x;
    dpt_t __far         *dpt;

    bios_dsk = ebda_seg :> &EbdaData->bdisk;

    BX_DEBUG_INT13_CD("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES);

    SET_DISK_RET_STATUS(0x00);

    /* basic check : device should be 0xE0+ */
    if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0 + BX_MAX_STORAGE_DEVICES) ) {
        BX_DEBUG("%s: function %02x, ELDL out of range %02x\n", __func__, GET_AH(), GET_ELDL());
        goto int13_fail;
    }

    // Get the ata channel
    device = bios_dsk->cdidmap[GET_ELDL()-0xE0];

    /* basic check : device has to be valid  */
    if (device >= BX_MAX_STORAGE_DEVICES) {
        BX_DEBUG("%s: function %02x, unmapped device for ELDL=%02x\n", __func__, GET_AH(), GET_ELDL());
        goto int13_fail;
    }

    switch (GET_AH()) {

    // all those functions return SUCCESS
    case 0x00: /* disk controller reset */
    case 0x09: /* initialize drive parameters */
    case 0x0c: /* seek to specified cylinder */
    case 0x0d: /* alternate disk reset */
    case 0x10: /* check drive ready */
    case 0x11: /* recalibrate */
    case 0x14: /* controller internal diagnostic */
    case 0x16: /* detect disk change */
        goto int13_success;
        break;

    // all those functions return disk write-protected
    case 0x03: /* write disk sectors */
    case 0x05: /* format disk track */
    case 0x43: // IBM/MS extended write
        SET_AH(0x03);
        goto int13_fail_noah;
        break;

    case 0x01: /* read disk status */
        status = read_byte(0x0040, 0x0074);
        SET_AH(status);
        SET_DISK_RET_STATUS(0);

        /* set CF if error status read */
        if (status)
            goto int13_fail_nostatus;
        else
            goto int13_success_noah;
        break;

    case 0x15: /* read disk drive size */
        SET_AH(0x02);
        goto int13_fail_noah;
        break;

    case 0x41: // IBM/MS installation check
        BX = 0xaa55;    // install check
        SET_AH(0x30);   // EDD 2.1
        CX = 0x0007;    // ext disk access, removable and edd
        goto int13_success_noah;
        break;

    case 0x42: // IBM/MS extended read
    case 0x44: // IBM/MS verify sectors
    case 0x47: // IBM/MS extended seek

        /* Load the I13X struct pointer. */
        i13x = MK_FP(DS, SI);

        count   = i13x->count;
        segment = i13x->segment;
        offset  = i13x->offset;

        // Can't use 64 bits lba
        lba = i13x->lba2;
        if (lba != 0L) {
            BX_PANIC("%s: function %02x. Can't use 64bits lba\n", __func__, GET_AH());
            goto int13_fail;
        }

        // Get 32 bits lba
        lba = i13x->lba1;

        // If verify or seek
        if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
            goto int13_success;

        BX_DEBUG_INT13_CD("%s: read %u sectors @ LBA %lu to %04X:%04X\n",
                          __func__, count, lba, segment, offset);

        _fmemset(&atapicmd, 0, sizeof(atapicmd));
        atapicmd.command = 0x28;    // READ 10 command
        atapicmd.lba     = swap_32(lba);
        atapicmd.nsect   = swap_16(count);

        bios_dsk->drqp.nsect   = count;
        bios_dsk->drqp.sect_sz = 2048;

        status = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, 0, count*2048L, ATA_DATA_IN, MK_FP(segment,offset));

        count = (uint16_t)(bios_dsk->drqp.trsfbytes >> 11);
        i13x->count = count;

        if (status != 0) {
            BX_INFO("%s: function %02x, status %02x !\n", __func__, GET_AH(), status);
            SET_AH(0x0c);
            goto int13_fail_noah;
        }

        goto int13_success;
        break;

    case 0x45: // IBM/MS lock/unlock drive
        if (GET_AL() > 2)
            goto int13_fail;

        locks = bios_dsk->devices[device].lock;

        switch (GET_AL()) {
        case 0 :  // lock
            if (locks == 0xff) {
                SET_AH(0xb4);
                SET_AL(1);
                goto int13_fail_noah;
            }
            bios_dsk->devices[device].lock = ++locks;
            SET_AL(1);
            break;
        case 1 :  // unlock
            if (locks == 0x00) {
                SET_AH(0xb0);
                SET_AL(0);
                goto int13_fail_noah;
            }
            bios_dsk->devices[device].lock = --locks;
            SET_AL(locks==0?0:1);
            break;
        case 2 :  // status
            SET_AL(locks==0?0:1);
            break;
        }
        goto int13_success;
        break;

    case 0x46: // IBM/MS eject media
        locks = bios_dsk->devices[device].lock;

        if (locks != 0) {
            SET_AH(0xb1); // media locked
            goto int13_fail_noah;
        }
        // FIXME should handle 0x31 no media in device
        // FIXME should handle 0xb5 valid request failed

#if 0 /// @todo implement!
        // Call removable media eject
        ASM_START
        push bp
        mov  bp, sp

        mov ah, #0x52
        int #0x15
        mov _int13_cdrom.status + 2[bp], ah
        jnc int13_cdrom_rme_end
        mov _int13_cdrom.status, #1
int13_cdrom_rme_end:
        pop bp
        ASM_END
#endif

        if (status != 0) {
            SET_AH(0xb1); // media locked
            goto int13_fail_noah;
        }

        goto int13_success;
        break;

    /// @todo Part of this should be merged with analogous code in disk.c
    case 0x48: // IBM/MS get drive parameters
        dpt = DS :> (dpt_t *)SI;
        size = dpt->size;

        // Buffer is too small
        if (size < 0x1a)
            goto int13_fail;

        // EDD 1.x
        if (size >= 0x1a) {
            uint16_t   blksize;

            blksize = bios_dsk->devices[device].blksize;

            dpt->size      = 0x1a;
            dpt->infos     = 0x74;  /* Removable, media change, lockable, max values */
            dpt->cylinders = 0xffffffff;
            dpt->heads     = 0xffffffff;
            dpt->spt       = 0xffffffff;
            dpt->blksize   = blksize;
            dpt->sector_count1 = 0xffffffff;  // FIXME should be Bit64
            dpt->sector_count2 = 0xffffffff;
        }

        // EDD 2.x
        if(size >= 0x1e) {
            uint8_t     channel, irq, mode, checksum, i;
            uint16_t    iobase1, iobase2, options;

            dpt->size = 0x1e;
            dpt->dpte_segment = ebda_seg;
            dpt->dpte_offset  = (uint16_t)&EbdaData->bdisk.dpte;

            // Fill in dpte
            channel = device / 2;
            iobase1 = bios_dsk->channels[channel].iobase1;
            iobase2 = bios_dsk->channels[channel].iobase2;
            irq     = bios_dsk->channels[channel].irq;
            mode    = bios_dsk->devices[device].mode;

            // FIXME atapi device
            options  = (1<<4); // lba translation
            options |= (1<<5); // removable device
            options |= (1<<6); // atapi device
#if VBOX_BIOS_CPU >= 80386
            options |= (mode==ATA_MODE_PIO32?1:0<<7);
#endif

            bios_dsk->dpte.iobase1  = iobase1;
            bios_dsk->dpte.iobase2  = iobase2;
            bios_dsk->dpte.prefix   = (0xe | (device % 2))<<4;
            bios_dsk->dpte.unused   = 0xcb;
            bios_dsk->dpte.irq      = irq;
            bios_dsk->dpte.blkcount = 1 ;
            bios_dsk->dpte.dma      = 0;
            bios_dsk->dpte.pio      = 0;
            bios_dsk->dpte.options  = options;
            bios_dsk->dpte.reserved = 0;
            bios_dsk->dpte.revision = 0x11;

            checksum = 0;
            for (i = 0; i < 15; ++i)
                checksum += read_byte(ebda_seg, (uint16_t)&EbdaData->bdisk.dpte + i);
            checksum = -checksum;
            bios_dsk->dpte.checksum = checksum;
        }

        // EDD 3.x
        if(size >= 0x42) {
            uint8_t     channel, iface, checksum, i;
            uint16_t    iobase1;

            channel = device / 2;
            iface   = bios_dsk->channels[channel].iface;
            iobase1 = bios_dsk->channels[channel].iobase1;

            dpt->size       = 0x42;
            dpt->key        = 0xbedd;
            dpt->dpi_length = 0x24;
            dpt->reserved1  = 0;
            dpt->reserved2  = 0;

            if (iface == ATA_IFACE_ISA) {
                dpt->host_bus[0] = 'I';
                dpt->host_bus[1] = 'S';
                dpt->host_bus[2] = 'A';
                dpt->host_bus[3] = ' ';
            }
            else {
                // FIXME PCI
            }
            dpt->iface_type[0] = 'A';
            dpt->iface_type[1] = 'T';
            dpt->iface_type[2] = 'A';
            dpt->iface_type[3] = ' ';
            dpt->iface_type[4] = ' ';
            dpt->iface_type[5] = ' ';
            dpt->iface_type[6] = ' ';
            dpt->iface_type[7] = ' ';

            if (iface == ATA_IFACE_ISA) {
                ((uint16_t __far *)dpt->iface_path)[0] = iobase1;
                ((uint16_t __far *)dpt->iface_path)[1] = 0;
                ((uint32_t __far *)dpt->iface_path)[1] = 0;
            }
            else {
                // FIXME PCI
            }
            ((uint16_t __far *)dpt->device_path)[0] = device & 1;
            ((uint16_t __far *)dpt->device_path)[1] = 0;
            ((uint32_t __far *)dpt->device_path)[1] = 0;

            checksum = 0;
            for (i = 30; i < 64; ++i)
                checksum += ((uint8_t __far *)dpt)[i];
            checksum = -checksum;
            dpt->checksum = checksum;
        }

        goto int13_success;
        break;

    case 0x49: // IBM/MS extended media change
        // always send changed ??
        SET_AH(06);
        goto int13_fail_nostatus;
        break;

    case 0x4e: // // IBM/MS set hardware configuration
        // DMA, prefetch, PIO maximum not supported
        switch (GET_AL()) {
        case 0x01:
        case 0x03:
        case 0x04:
        case 0x06:
            goto int13_success;
            break;
        default :
            goto int13_fail;
        }
        break;

    // all those functions return unimplemented
    case 0x02: /* read sectors */
    case 0x04: /* verify sectors */
    case 0x08: /* read disk drive parameters */
    case 0x0a: /* read disk sectors with ECC */
    case 0x0b: /* write disk sectors with ECC */
    case 0x18: /* set media type for format */
    case 0x50: // ? - send packet command
    default:
        BX_INFO("%s: unsupported AH=%02x\n", __func__, GET_AH());
        goto int13_fail;
        break;
    }

int13_fail:
    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
int13_fail_noah:
    SET_DISK_RET_STATUS(GET_AH());
int13_fail_nostatus:
    SET_CF();     // error occurred
    return;

int13_success:
    SET_AH(0x00); // no error
int13_success_noah:
    SET_DISK_RET_STATUS(0x00);
    CLEAR_CF();   // no error
    return;
}
示例#6
0
void BIOSCALL int13_cdemu(disk_regs_t r)
{
    /// @todo a macro or a function for getting the EBDA segment
    uint16_t            ebda_seg=read_word(0x0040,0x000E);
    uint8_t             device, status;
    uint16_t            vheads, vspt, vcylinders;
    uint16_t            head, sector, cylinder, nbsectors;
    uint32_t            vlba, ilba, slba, elba;
    uint16_t            before, segment, offset;
    cdb_atapi           atapicmd;
    cdemu_t __far       *cdemu;
    bio_dsk_t __far     *bios_dsk;

    cdemu    = ebda_seg :> &EbdaData->cdemu;
    bios_dsk = ebda_seg :> &EbdaData->bdisk;

    BX_DEBUG_INT13_ET("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES);

    /* at this point, we are emulating a floppy/harddisk */

    // Recompute the device number
    device  = cdemu->controller_index * 2;
    device += cdemu->device_spec;

    SET_DISK_RET_STATUS(0x00);

    /* basic checks : emulation should be active, dl should equal the emulated drive */
    if (!cdemu->active || (cdemu->emulated_drive != GET_DL())) {
        BX_INFO("%s: function %02x, emulation not active for DL= %02x\n", __func__, GET_AH(), GET_DL());
        goto int13_fail;
    }

    switch (GET_AH()) {

    case 0x00: /* disk controller reset */
        if (pktacc[bios_dsk->devices[device].type])
        {
            status = softrst[bios_dsk->devices[device].type](device);
        }
        goto int13_success;
        break;
    // all those functions return SUCCESS
    case 0x09: /* initialize drive parameters */
    case 0x0c: /* seek to specified cylinder */
    case 0x0d: /* alternate disk reset */  // FIXME ElTorito Various. should really reset ?
    case 0x10: /* check drive ready */     // FIXME ElTorito Various. should check if ready ?
    case 0x11: /* recalibrate */
    case 0x14: /* controller internal diagnostic */
    case 0x16: /* detect disk change */
        goto int13_success;
        break;

    // all those functions return disk write-protected
    case 0x03: /* write disk sectors */
    case 0x05: /* format disk track */
        SET_AH(0x03);
        goto int13_fail_noah;
        break;

    case 0x01: /* read disk status */
        status=read_byte(0x0040, 0x0074);
        SET_AH(status);
        SET_DISK_RET_STATUS(0);

        /* set CF if error status read */
        if (status)
            goto int13_fail_nostatus;
        else
            goto int13_success_noah;
        break;

    case 0x02: // read disk sectors
    case 0x04: // verify disk sectors
        vspt       = cdemu->vdevice.spt;
        vcylinders = cdemu->vdevice.cylinders;
        vheads     = cdemu->vdevice.heads;
        ilba       = cdemu->ilba;

        sector    = GET_CL() & 0x003f;
        cylinder  = (GET_CL() & 0x00c0) << 2 | GET_CH();
        head      = GET_DH();
        nbsectors = GET_AL();
        segment   = ES;
        offset    = BX;

        BX_DEBUG_INT13_ET("%s: read to %04x:%04x @ VCHS %u/%u/%u (%u sectors)\n", __func__,
                          ES, BX, cylinder, head, sector, nbsectors);

        // no sector to read ?
        if(nbsectors==0)
            goto int13_success;

        // sanity checks sco openserver needs this!
        if ((sector   >  vspt)
          || (cylinder >= vcylinders)
          || (head     >= vheads)) {
            goto int13_fail;
        }

        // After validating the input, verify does nothing
        if (GET_AH() == 0x04)
            goto int13_success;

        segment = ES+(BX / 16);
        offset  = BX % 16;

        // calculate the virtual lba inside the image
        vlba=((((uint32_t)cylinder*(uint32_t)vheads)+(uint32_t)head)*(uint32_t)vspt)+((uint32_t)(sector-1));

        // In advance so we don't lose the count
        SET_AL(nbsectors);

        // start lba on cd
        slba   = (uint32_t)vlba / 4;
        before = (uint32_t)vlba % 4;

        // end lba on cd
        elba = (uint32_t)(vlba + nbsectors - 1) / 4;

        _fmemset(&atapicmd, 0, sizeof(atapicmd));
        atapicmd.command = 0x28;    // READ 10 command
        atapicmd.lba     = swap_32(ilba + slba);
        atapicmd.nsect   = swap_16(elba - slba + 1);

        bios_dsk->drqp.nsect   = nbsectors;
        bios_dsk->drqp.sect_sz = 512;

        bios_dsk->drqp.skip_b = before * 512;
        bios_dsk->drqp.skip_a = ((4 - nbsectors % 4 - before) * 512) % 2048;

        status = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, before*512, nbsectors*512L, ATA_DATA_IN, MK_FP(segment,offset));

        bios_dsk->drqp.skip_b = 0;
        bios_dsk->drqp.skip_a = 0;

        if (status != 0) {
            BX_INFO("%s: function %02x, error %02x !\n", __func__, GET_AH(), status);
            SET_AH(0x02);
            SET_AL(0);
            goto int13_fail_noah;
        }

        goto int13_success;
        break;

    case 0x08: /* read disk drive parameters */
        vspt       = cdemu->vdevice.spt;
        vcylinders = cdemu->vdevice.cylinders - 1;
        vheads     = cdemu->vdevice.heads - 1;

        SET_AL( 0x00 );
        SET_BL( 0x00 );
        SET_CH( vcylinders & 0xff );
        SET_CL((( vcylinders >> 2) & 0xc0) | ( vspt  & 0x3f ));
        SET_DH( vheads );
        SET_DL( 0x02 );   // FIXME ElTorito Various. should send the real count of drives 1 or 2
                          // FIXME ElTorito Harddisk. should send the HD count

        switch (cdemu->media) {
        case 0x01: SET_BL( 0x02 ); break;   /* 1.2 MB  */
        case 0x02: SET_BL( 0x04 ); break;   /* 1.44 MB */
        case 0x03: SET_BL( 0x05 ); break;   /* 2.88 MB */
        }

        /* Only set the DPT pointer for emulated floppies. */
        if (cdemu->media < 4) {
            DI = (uint16_t)&diskette_param_table;   /// @todo should this depend on emulated medium?
            ES = 0xF000;                            /// @todo how to make this relocatable?
        }
        goto int13_success;
        break;

    case 0x15: /* read disk drive size */
        // FIXME ElTorito Harddisk. What geometry to send ?
        SET_AH(0x03);
        goto int13_success_noah;
        break;

    // all those functions return unimplemented
    case 0x0a: /* read disk sectors with ECC */
    case 0x0b: /* write disk sectors with ECC */
    case 0x18: /* set media type for format */
    case 0x41: // IBM/MS installation check
      // FIXME ElTorito Harddisk. Darwin would like to use EDD
    case 0x42: // IBM/MS extended read
    case 0x43: // IBM/MS extended write
    case 0x44: // IBM/MS verify sectors
    case 0x45: // IBM/MS lock/unlock drive
    case 0x46: // IBM/MS eject media
    case 0x47: // IBM/MS extended seek
    case 0x48: // IBM/MS get drive parameters
    case 0x49: // IBM/MS extended media change
    case 0x4e: // ? - set hardware configuration
    case 0x50: // ? - send packet command
    default:
        BX_INFO("%s: function AH=%02x unsupported, returns fail\n", __func__, GET_AH());
        goto int13_fail;
        break;
    }

int13_fail:
    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
int13_fail_noah:
    SET_DISK_RET_STATUS(GET_AH());
int13_fail_nostatus:
    SET_CF();     // error occurred
    return;

int13_success:
    SET_AH(0x00); // no error
int13_success_noah:
    SET_DISK_RET_STATUS(0x00);
    CLEAR_CF();   // no error
    return;
}
示例#7
0
//
// Returns ah: emulated drive, al: error code
//
uint16_t cdrom_boot(void)
{
    /// @todo a macro or a function for getting the EBDA segment
    uint16_t            ebda_seg=read_word(0x0040,0x000E);
    uint8_t             buffer[2048];
    cdb_atapi           atapicmd;
    uint32_t            lba;
    uint16_t            boot_segment, nbsectors, i, error;
    uint8_t             device;
    uint8_t             read_try;
    cdemu_t __far       *cdemu;
    bio_dsk_t __far     *bios_dsk;

    cdemu    = ebda_seg :> &EbdaData->cdemu;
    bios_dsk = ebda_seg :> &EbdaData->bdisk;

    /* Find the first CD-ROM. */
    for (device = 0; device < BX_MAX_STORAGE_DEVICES; ++device) {
        if (device_is_cdrom(device))
            break;
    }

    /* Fail if not found. */
    if (device >= BX_MAX_STORAGE_DEVICES)
        return 2;

    /* Read the Boot Record Volume Descriptor (BRVD). */
    _fmemset(&atapicmd, 0, sizeof(atapicmd));
    atapicmd.command = 0x28;    // READ 10 command
    atapicmd.lba     = swap_32(0x11);
    atapicmd.nsect   = swap_16(1);

    bios_dsk->drqp.nsect   = 1;
    bios_dsk->drqp.sect_sz = 2048;

    for (read_try = 0; read_try <= 4; ++read_try)
    {
        error = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, 0, 2048L, ATA_DATA_IN, &buffer);
        if (!error)
            break;
    }
    if (error)
        return 3;

    /* Check for a valid BRVD. */
    if (buffer[0] != 0)
        return 4;
    /// @todo what's wrong with memcmp()?
    for (i = 0; i < 5; ++i) {
        if (buffer[1+i] != isotag[i])
            return 5;
    }
    for (i = 0; i < 23; ++i)
        if (buffer[7+i] != eltorito[i])
            return 6;

    // ok, now we calculate the Boot catalog address
    lba = *((uint32_t *)&buffer[0x47]);
    BX_DEBUG_ELTORITO("BRVD at LBA %lx\n", lba);

    /* Now we read the Boot Catalog. */
    atapicmd.command = 0x28;    // READ 10 command
    atapicmd.lba     = swap_32(lba);
    atapicmd.nsect   = swap_16(1);

#if 0   // Not necessary as long as previous values are reused
    bios_dsk->drqp.nsect   = 1;
    bios_dsk->drqp.sect_sz = 512;
#endif

    error = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, 0, 2048L, ATA_DATA_IN, &buffer);
    if (error != 0)
        return 7;

    /// @todo Define a struct for the Boot Catalog, the hardcoded offsets are so dumb...

    /* Check if the Boot Catalog looks valid. */
    if (buffer[0x00] != 0x01)
        return 8;   // Header
    if (buffer[0x01] != 0x00)
        return 9;   // Platform
    if (buffer[0x1E] != 0x55)
        return 10;  // key 1
    if (buffer[0x1F] != 0xAA)
        return 10;  // key 2

    // Initial/Default Entry
    if (buffer[0x20] != 0x88)
        return 11; // Bootable

    cdemu->media = buffer[0x21];
    if (buffer[0x21] == 0) {
        // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0.
        // Win2000 cd boot needs to know it booted from cd
        cdemu->emulated_drive = 0xE0;
    }
    else if (buffer[0x21] < 4)
        cdemu->emulated_drive = 0x00;
    else
        cdemu->emulated_drive = 0x80;

    cdemu->controller_index = device / 2;
    cdemu->device_spec      = device % 2;

    boot_segment  = *((uint16_t *)&buffer[0x22]);
    if (boot_segment == 0)
        boot_segment = 0x07C0;

    cdemu->load_segment   = boot_segment;
    cdemu->buffer_segment = 0x0000;

    nbsectors = ((uint16_t *)buffer)[0x26 / 2];
    cdemu->sector_count = nbsectors;

    /* Sanity check the sector count. In incorrectly mastered CDs, it might
     * be zero. If it's more than 512K, reject it as well.
     */
    if (nbsectors == 0 || nbsectors > 1024)
        return 12;

    lba = *((uint32_t *)&buffer[0x28]);
    cdemu->ilba = lba;

    BX_DEBUG_ELTORITO("Emulate drive %02x, type %02x, LBA %lu\n",
                      cdemu->emulated_drive, cdemu->media, cdemu->ilba);

    /* Read the disk image's boot sector into memory. */
    atapicmd.command = 0x28;    // READ 10 command
    atapicmd.lba     = swap_32(lba);
    atapicmd.nsect   = swap_16(1 + (nbsectors - 1) / 4);

    bios_dsk->drqp.nsect   = 1 + (nbsectors - 1) / 4;
    bios_dsk->drqp.sect_sz = 512;

    bios_dsk->drqp.skip_a = (2048 - nbsectors * 512) % 2048;

    error = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, 0, nbsectors*512L, ATA_DATA_IN, MK_FP(boot_segment,0));

    bios_dsk->drqp.skip_a = 0;

    if (error != 0)
        return 13;

    BX_DEBUG_ELTORITO("Emulate drive %02x, type %02x, LBA %lu\n",
                      cdemu->emulated_drive, cdemu->media, cdemu->ilba);
    /* Set up emulated drive geometry based on the media type. */
    switch (cdemu->media) {
    case 0x01:  /* 1.2M floppy */
        cdemu->vdevice.spt       = 15;
        cdemu->vdevice.cylinders = 80;
        cdemu->vdevice.heads     = 2;
        break;
    case 0x02:  /* 1.44M floppy */
        cdemu->vdevice.spt       = 18;
        cdemu->vdevice.cylinders = 80;
        cdemu->vdevice.heads     = 2;
        break;
    case 0x03:  /* 2.88M floppy */
        cdemu->vdevice.spt       = 36;
        cdemu->vdevice.cylinders = 80;
        cdemu->vdevice.heads     = 2;
        break;
    case 0x04:  /* Hard disk */
        cdemu->vdevice.spt       = read_byte(boot_segment,446+6)&0x3f;
        cdemu->vdevice.cylinders = (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1;
        cdemu->vdevice.heads     = read_byte(boot_segment,446+5) + 1;
        break;
    }
    BX_DEBUG_ELTORITO("VCHS=%u/%u/%u\n", cdemu->vdevice.cylinders,
                      cdemu->vdevice.heads, cdemu->vdevice.spt);

    if (cdemu->media != 0) {
        /* Increase BIOS installed number of drives (floppy or fixed). */
        if (cdemu->emulated_drive == 0x00)
            write_byte(0x40,0x10,read_byte(0x40,0x10)|0x41);
        else
            write_byte(ebda_seg,(uint16_t)&EbdaData->bdisk.hdcount, read_byte(ebda_seg, (uint16_t)&EbdaData->bdisk.hdcount) + 1);
    }

    // everything is ok, so from now on, the emulation is active
    if (cdemu->media != 0)
        cdemu->active = 0x01;

    // return the boot drive + no error
    return (cdemu->emulated_drive*0x100)+0;
}
示例#8
0
int HandleServerMessage(tSDL_vnc *vnc)
{
 int i, num_pixels, num_rectangles, num_subrectangles, hx, hy, bx, by, cx, cy, rowindex, bitindex, byteindex;
 int result, bytes_to_read, bytes_read;
 tSDL_vnc_serverMessage serverMessage;
 tSDL_vnc_serverUpdate serverUpdate;
 tSDL_vnc_serverRectangle serverRectangle;
 tSDL_vnc_serverColormap serverColormap;
 tSDL_vnc_serverText serverText;
 tSDL_vnc_serverCopyrect serverCopyrect;
 tSDL_vnc_serverRRE serverRRE;
 tSDL_vnc_serverRREdata serverRREdata;
 tSDL_vnc_serverCoRRE serverCoRRE;
 tSDL_vnc_serverCoRREdata serverCoRREdata;
 tSDL_vnc_serverHextile serverHextile;
 tSDL_vnc_serverHextileBg serverHextileBg;
 tSDL_vnc_serverHextileFg serverHextileFg;
 tSDL_vnc_serverHextileSubrects serverHextileSubrects;
 tSDL_vnc_serverHextileColored serverHextileColored;
 tSDL_vnc_serverHextileRect serverHextileRect;
 unsigned char *target;
 unsigned int *uitarget;
 unsigned char *cursormask;
 SDL_Rect trec, srec;

 DBMESSAGE ("HandleServerMessage\n");
 /* Read message type */
 result = Recv(vnc->socket,&serverMessage,1,0);
 if (result==1) {
  switch (serverMessage.messagetype) {

   case 0:
    DBMESSAGE ("Message: update\n");
    result = Recv(vnc->socket,&serverUpdate,3,0);
    if (result==3) {

     /* ??? Protocol sais U16, TightVNC server sends U8 */
     serverUpdate.rectangles=serverUpdate.rectangles & 0x00ff;
     DBMESSAGE ("Number of rectangles: %u (%04x)\n",serverUpdate.rectangles,serverUpdate.rectangles);

     num_rectangles=0;
     while (num_rectangles<serverUpdate.rectangles) {
      num_rectangles++;
      result = Recv(vnc->socket,&serverRectangle,12,0);
      if (result==12) {
       serverRectangle.x=swap_16(serverRectangle.x);
       serverRectangle.y=swap_16(serverRectangle.y);
       serverRectangle.width=swap_16(serverRectangle.width);
       serverRectangle.height=swap_16(serverRectangle.height);
       serverRectangle.encoding=swap_32(serverRectangle.encoding);
       //
       DBMESSAGE ("Rectangle %i of %i: @ %u,%u size %u,%u encoding %u\n",num_rectangles,serverUpdate.rectangles,serverRectangle.x,serverRectangle.y,serverRectangle.width,serverRectangle.height,serverRectangle.encoding);
       
       /* Sanity check values */
       if (serverRectangle.x>vnc->serverFormat.width) {
        DBMESSAGE("Bad rectangle: x=%u setting to 0\n",serverRectangle.x);
        serverRectangle.x=0;
       }
       if (serverRectangle.y>vnc->serverFormat.height) {
        DBMESSAGE("Bad rectangle: y=%u setting to 0\n",serverRectangle.y);
        serverRectangle.y=0;
       }
       if ((serverRectangle.width<=0) || (serverRectangle.width>vnc->serverFormat.width)) {
        DBMESSAGE("Bad rectangle: width=%u setting to 1\n",serverRectangle.width);
        serverRectangle.width=1;
       }
       if ((serverRectangle.height<=0) || (serverRectangle.height>vnc->serverFormat.height)) {
        DBMESSAGE("Bad rectangle: height=%u setting to 1\n",serverRectangle.height);
        serverRectangle.height=1;
       }
       
       /* Do we have a scratchbuffer */
       if (vnc->scratchbuffer) {
        /* Check size */
        if ( (!(vnc->scratchbuffer->w == serverRectangle.width)) || (!(vnc->scratchbuffer->h == serverRectangle.height)) ) {
         /* Clean out existing scratchbuffer */
         SDL_FreeSurface(vnc->scratchbuffer);
         vnc->scratchbuffer=NULL;
         DBMESSAGE ("Deleted existing scratchbuffer.\n");
        }
       }
       if (!(vnc->scratchbuffer)) {
        /* Create new scratchbuffer */
        vnc->scratchbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE,serverRectangle.width,serverRectangle.height,32,
                                         vnc->rmask,vnc->gmask,vnc->bmask,0);
        if (vnc->scratchbuffer) {                                  
         SDL_SetAlpha(vnc->scratchbuffer,0,0);
         DBMESSAGE ("Created new scratchbuffer.\n");
        } else {
         DBERROR ("Error creating scratchbuffer.\n");
         return 0;
        }
       }
       
       /* Rectangle Data */
       switch (serverRectangle.encoding) {

        case 0:
          DBMESSAGE ("RAW encoding.\n");
          bytes_to_read = serverRectangle.width*serverRectangle.height*4;
          result = Recv(vnc->socket,(unsigned char *)vnc->scratchbuffer->pixels,bytes_to_read,0);
          if (result==bytes_to_read) {
           DBMESSAGE ("Blitting %i bytes of raw pixel data.\n",bytes_to_read);
           trec.x=serverRectangle.x;
           trec.y=serverRectangle.y;
           trec.w=serverRectangle.width;
           trec.h=serverRectangle.height;
  	   SDL_LockMutex(vnc->mutex);
           SDL_BlitSurface(vnc->scratchbuffer, NULL, vnc->framebuffer, &trec);
           GrowUpdateRegion(vnc,&trec);
  	   SDL_UnlockMutex(vnc->mutex);
           DBMESSAGE ("Blitted raw pixel data.\n");
          } else {
           DBERROR ("Error on pixel data. Got %i of %i bytes.\n",result,bytes_to_read);
           return 0;
          }
         break;

        case 1:
          DBMESSAGE ("CopyRect encoding.\n");
          result = Recv(vnc->socket,&serverCopyrect,4,0);
          if (result==4) {    
           serverCopyrect.x=swap_16(serverCopyrect.x);
           serverCopyrect.y=swap_16(serverCopyrect.y);
           //
           DBMESSAGE ("Copyrect from %u,%u\n",serverCopyrect.x,serverCopyrect.y);
           //
           srec.x=serverCopyrect.x;
           srec.y=serverCopyrect.y;
           srec.w=serverRectangle.width;
           srec.h=serverRectangle.height;
           trec.x=serverRectangle.x;
           trec.y=serverRectangle.y;
           trec.w=serverRectangle.width;
           trec.h=serverRectangle.height;
    	   SDL_LockMutex(vnc->mutex);
           SDL_BlitSurface(vnc->framebuffer, &srec, vnc->scratchbuffer, NULL);
           SDL_BlitSurface(vnc->scratchbuffer, NULL, vnc->framebuffer, &trec);
           GrowUpdateRegion(vnc,&trec);
  	   SDL_UnlockMutex(vnc->mutex);
           DBMESSAGE ("Blitted copyrect pixels.\n");
          } else {
           DBERROR ("Error on copyrect data. Got %i of %i bytes.\n",result,4);
           return 0;
          }
         break;

        case 2:         
          DBMESSAGE ("RRE encoding.\n");
          result = Recv(vnc->socket,&serverRRE,8,0);
          if (result==8) {    
           serverRRE.number=swap_32(serverRRE.number);
           //
           DBMESSAGE ("RRE of %u rectangles. Background color 0x%06x\n",serverRRE.number,serverRRE.background);
           SDL_FillRect(vnc->scratchbuffer, NULL, serverRRE.background);
           /* Draw subrectangles */
           num_subrectangles=0;
           while (num_subrectangles<serverRRE.number) {
            num_subrectangles++;
            result = Recv(vnc->socket,&serverRREdata,12,0);
            if (result==12) {
             serverRREdata.x=swap_16(serverRREdata.x);
             serverRREdata.y=swap_16(serverRREdata.y);
             serverRREdata.width=swap_16(serverRREdata.width);
             serverRREdata.height=swap_16(serverRREdata.height);
             srec.x=serverRREdata.x;
             srec.y=serverRREdata.y;
             srec.w=serverRREdata.width;
             srec.h=serverRREdata.height;
	     SDL_FillRect(vnc->scratchbuffer,&srec,serverRREdata.color);
            } else {
             DBERROR ("Error on RRE data. Got %i of %i bytes.\n",result,12);
             return 0;
            } 
           }
           DBMESSAGE ("Drawn %i subrectangles.\n", num_subrectangles);
           trec.x=serverRectangle.x;
           trec.y=serverRectangle.y;
           trec.w=serverRectangle.width;
           trec.h=serverRectangle.height;
    	   SDL_LockMutex(vnc->mutex);
           SDL_BlitSurface(vnc->scratchbuffer, NULL, vnc->framebuffer, &trec);
           GrowUpdateRegion(vnc,&trec);
           SDL_UnlockMutex(vnc->mutex);
           DBMESSAGE ("Blitted RRE pixels.\n");
          } else {
           DBERROR ("Error on RRE header. Got %i of %i bytes.\n",result,8);
           return 0;
          }          
         break;

        case 4:         
          DBMESSAGE ("CoRRE encoding.\n");
          result = Recv(vnc->socket,&serverCoRRE,8,0);
          if (result==8) {    
           serverCoRRE.number=swap_32(serverCoRRE.number);
           //
           DBMESSAGE ("CoRRE of %u rectangles. Background color 0x%06x\n",serverCoRRE.number,serverCoRRE.background);
           SDL_FillRect(vnc->scratchbuffer, NULL, serverCoRRE.background);
           /* Draw subrectangles */
           num_subrectangles=0;
           while (num_subrectangles<serverCoRRE.number) {
            num_subrectangles++;
            result = Recv(vnc->socket,&serverCoRREdata,8,0);
            if (result==8) {
             srec.x=serverCoRREdata.x;
             srec.y=serverCoRREdata.y;
             srec.w=serverCoRREdata.width;
             srec.h=serverCoRREdata.height;
	     SDL_FillRect(vnc->scratchbuffer,&srec,serverCoRREdata.color);
            } else {
             DBERROR ("Error on CoRRE data. Got %i of %i bytes.\n",result,8);
             return 0;
            } 
           }
           DBMESSAGE ("Drawn %i subrectangles.\n", num_subrectangles);
           trec.x=serverRectangle.x;
           trec.y=serverRectangle.y;
           trec.w=serverRectangle.width;
           trec.h=serverRectangle.height;
    	   SDL_LockMutex(vnc->mutex);
           SDL_BlitSurface(vnc->scratchbuffer, NULL, vnc->framebuffer, &trec);
           GrowUpdateRegion(vnc,&trec);
           SDL_UnlockMutex(vnc->mutex);
           DBMESSAGE ("Blitted CoRRE pixels.\n");
          } else {
           DBERROR ("Error on CoRRE header. Got %i of %i bytes.\n",result,8);
           return 0;
          }          
         break;

        case 5:
          DBMESSAGE ("Hextile encoding.\n");
          //
          if (!(vnc->tilebuffer)) {
           /* Create new tilebuffer */
           vnc->tilebuffer = SDL_CreateRGBSurface(SDL_SWSURFACE,16,16,32,
                                                   vnc->rmask,vnc->gmask,vnc->bmask,0);
           if (vnc->tilebuffer) {                                  
            SDL_SetAlpha(vnc->tilebuffer,0,0);
            DBMESSAGE ("Created new tilebuffer.\n");
           } else {
            DBERROR ("Error creating tilebuffer.\n");
            return 0;
           }
          }
          //
          /* Iterate over all tiles */
          // row loop
          for (hy=0; hy<serverRectangle.height; hy += 16) {
           /* Determine height of tile */
           if ((hy+16)>serverRectangle.height) {
            by=serverRectangle.height % 16;
           } else {
            by=16;
           }
           // column loop
           for (hx=0; hx<serverRectangle.width; hx += 16) {
            /* Determine width of tile */
            if ((hx+16)>serverRectangle.width) {
             bx=serverRectangle.width % 16;
            } else {
             bx=16;
            }
            result = Recv(vnc->socket,&serverHextile,1,0);
            if (result==1) {    
             if (serverHextile.mode & 1) {
              /* Read raw data for tile in lines */
              bytes_to_read = bx*by*4;
              if ((bx==16) && (by==16)) {
               // complete tile
               result = Recv(vnc->socket,(unsigned char *)vnc->tilebuffer->pixels,bytes_to_read,0);
              } else {
               // partial tile
               result = 0;
               target=(unsigned char *)vnc->tilebuffer->pixels;
               rowindex=by;
               while (rowindex) {
                result +=  Recv(vnc->socket,target,bx*4,0);
                target += 16*4;
                rowindex--;
               }
              }
              if (result==bytes_to_read) {
               trec.x=hx;
               trec.y=hy;
               trec.w=16;
               trec.h=16;
               SDL_BlitSurface(vnc->tilebuffer, NULL, vnc->scratchbuffer, &trec);
              } else {
               DBERROR ("Error on pixel data. Got %i of %i bytes.\n",result,bytes_to_read);
               return 0;
              }            
             } else {
              /* no raw data */
              if (serverHextile.mode & 2) {
               /* Read background */
               result = Recv(vnc->socket,&serverHextileBg,4,0);
               if (result==4) {
                /* All OK */
               } else {
                DBERROR ("Error on Hextile background. Got %i of %i bytes.\n",result,4);
                return 0;
               }    
              }
              SDL_FillRect(vnc->tilebuffer,NULL,serverHextileBg.color);              
              if (serverHextile.mode & 4) {
               /* Read foreground */
               result = Recv(vnc->socket,&serverHextileFg,4,0);
               if (result==4) {
                /* All OK */
               } else {
                DBERROR ("Error on Hextile foreground. Got %i of %i bytes.\n",result,4);
                return 0;
               }    
              }
              if (serverHextile.mode & 8) {
               result = Recv(vnc->socket,&serverHextileSubrects,1,0);
               if (result==1) {
                /* All OK */
               } else {
                DBERROR ("Error on Hextile subrects. Got %i of %i bytes.\n",result,1);
                return 0;
               }
               /* Read subrects */
               num_subrectangles=0;
               while (num_subrectangles<serverHextileSubrects.number) {
                num_subrectangles++;
                // 
                /* Check color mode */
                if (serverHextile.mode & 16) {
                 /* Colored subrect */
                 result = Recv(vnc->socket,&serverHextileColored,6,0);
                 if (result==6) {
                  /* Render colored subrect */
                  srec.x=(serverHextileColored.xy >> 4) & 0x0f;
                  srec.y=serverHextileColored.xy & 0x0f;
                  srec.w=((serverHextileColored.wh >> 4) & 0x0f)+1;
                  srec.h=(serverHextileColored.wh & 0x0f)+1;
                  SDL_FillRect(vnc->tilebuffer,&srec,serverHextileColored.color);
                 } else {
                  DBERROR ("Error on Hextile color subrect data. Got %i of %i bytes.\n",result,6);
                  return 0;
                 }
                } else {
                 /* Non-colored Subrect */
                 result = Recv(vnc->socket,&serverHextileRect,2,0);
                 if (result==2) {
                  /* Render colored subrect */
                  srec.x=(serverHextileRect.xy >> 4) & 0x0f;
                  srec.y=serverHextileRect.xy & 0x0f;
                  srec.w=((serverHextileRect.wh >> 4) & 0x0f)+1;
                  srec.h=(serverHextileRect.wh & 0x0f)+1;
                  SDL_FillRect(vnc->tilebuffer,&srec,serverHextileFg.color);
                 } else {
                  DBERROR ("Error on Hextile subrect data. Got %i of %i bytes.\n",result,2);
                  return 0;
                 }
                } // color mode check
               } // subrect loop
               //
              } // have subrects
              /* Draw tile */
              trec.x=hx;
              trec.y=hy;
              trec.w=16;
              trec.h=16;
              SDL_BlitSurface(vnc->tilebuffer, NULL, vnc->scratchbuffer, &trec);
             } // raw data check
            } else {