Exemple #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 %lu\n", dev->act_len, dev->status);

	return stat;
}
Exemple #2
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;

        if (device > BX_MAX_ATA_DEVICES)
            status = ahci_cmd_packet(device, 12, (char __far *)&atapicmd, 0, count*2048L, ATA_DATA_IN, MK_FP(segment,offset));
        else
            status = ata_cmd_packet(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
            options |= (mode==ATA_MODE_PIO32?1:0<<7);

            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;
}
Exemple #3
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()) {

    // 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 */  // 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   = elba - slba + 1;
        bios_dsk->drqp.sect_sz = 512;

        bios_dsk->drqp.skip_b = before * 512;
        bios_dsk->drqp.skip_a = 2048 - nbsectors * 512UL % 2048 - bios_dsk->drqp.skip_b;

        if (device > BX_MAX_ATA_DEVICES)
            status = ahci_cmd_packet(device, 12, (char __far *)&atapicmd, before*512, nbsectors*512L, ATA_DATA_IN, MK_FP(segment,offset));
        else
            status = ata_cmd_packet(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;
        case 0x02: SET_BL( 0x04 ); break;
        case 0x03: SET_BL( 0x06 ); break;
        }

        DI = (uint16_t)&diskette_param_table;   // @todo: or really DPT2?
        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;
}
Exemple #4
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)
    {
        //@todo: Use indirect calls instead?
        if (device > BX_MAX_ATA_DEVICES)
            error = ahci_cmd_packet(device, 12, (char __far *)&atapicmd, 0, 2048L, ATA_DATA_IN, &buffer);
        else
            error = ata_cmd_packet(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

    if (device > BX_MAX_ATA_DEVICES)
        error = ahci_cmd_packet(device, 12, (char __far *)&atapicmd, 0, 2048L, ATA_DATA_IN, &buffer);
    else
        error = ata_cmd_packet(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;

    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 * 512UL % 2048;

    if (device > BX_MAX_ATA_DEVICES)
        error = ahci_cmd_packet(device, 12, (char __far *)&atapicmd, 0, nbsectors*512L, ATA_DATA_IN, MK_FP(boot_segment,0));
    else
        error = ata_cmd_packet(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 12;

    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;
}
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 {
Exemple #6
0
int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
{
	int result, retry;
	int dir_in;
	int actlen, data_actlen;
	unsigned int pipe, pipein, pipeout;
	umass_bbb_csw_t csw;
#ifdef BBB_XPORT_TRACE
	unsigned char *ptr;
	int index;
#endif

	dir_in = US_DIRECTION(srb->cmd[0]);

	/* COMMAND phase */
	USB_STOR_PRINTF("COMMAND phase\n");
	result = usb_stor_BBB_comdat(srb, us);
	if (result < 0) {
		USB_STOR_PRINTF("failed to send CBW status %ld\n",
			us->pusb_dev->status);
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	}
	wait_ms(5);
	pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
	pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
	/* DATA phase + error handling */
	data_actlen = 0;
	/* no data, go immediately to the STATUS phase */
	if (srb->datalen == 0)
		goto st;
	USB_STOR_PRINTF("DATA phase\n");
	if (dir_in)
		pipe = pipein;
	else
		pipe = pipeout;
	result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen, &data_actlen, USB_CNTL_TIMEOUT*5);
	/* special handling of STALL in DATA phase */
	if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
		USB_STOR_PRINTF("DATA:stall\n");
		/* clear the STALL on the endpoint */
		result = usb_stor_BBB_clear_endpt_stall(us, dir_in? us->ep_in : us->ep_out);
		if (result >= 0)
			/* continue on to STATUS phase */
			goto st;
	}
	if (result < 0) {
		USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
			us->pusb_dev->status);
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	}
#ifdef BBB_XPORT_TRACE
	for (index = 0; index < data_actlen; index++)
		printf("pdata[%d] %#x ", index, srb->pdata[index]);
	printf("\n");
#endif
	/* STATUS phase + error handling */
   st:
	retry = 0;
   again:
	USB_STOR_PRINTF("STATUS phase\n");
	result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
				&actlen, USB_CNTL_TIMEOUT*5);

	/* special handling of STALL in STATUS phase */
	if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) {
		USB_STOR_PRINTF("STATUS:stall\n");
		/* clear the STALL on the endpoint */
		result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
		if (result >= 0 && (retry++ < 1))
			/* do a retry */
			goto again;
	}
	if (result < 0) {
		USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
			us->pusb_dev->status);
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	}
#ifdef BBB_XPORT_TRACE
	ptr = (unsigned char *)&csw;
	for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
		printf("ptr[%d] %#x ", index, ptr[index]);
	printf("\n");
#endif
	/* misuse pipe to get the residue */
	pipe = swap_32(csw.dCSWDataResidue);
	if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
		pipe = srb->datalen - data_actlen;
	if (CSWSIGNATURE != swap_32(csw.dCSWSignature)) {
		USB_STOR_PRINTF("!CSWSIGNATURE\n");
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if ((CBWTag - 1) != swap_32(csw.dCSWTag)) {
		USB_STOR_PRINTF("!Tag\n");
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
		USB_STOR_PRINTF(">PHASE\n");
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
		USB_STOR_PRINTF("=PHASE\n");
		usb_stor_BBB_reset(us);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (data_actlen > srb->datalen) {
		USB_STOR_PRINTF("transferred %dB instead of %dB\n",
			data_actlen, srb->datalen);
		return USB_STOR_TRANSPORT_FAILED;
	} else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
		USB_STOR_PRINTF("FAILED\n");
		return USB_STOR_TRANSPORT_FAILED;
	}

	return result;
}