예제 #1
0
static uint8_t
ioWrite2Loop(Write2Fn_t writeFn, uint16_t len)
{
    uint8_t data[2];

    usbInitIo(len, ENDPOINT_DIR_OUT);
    while (len != 0) {
        if (usbRecvByte(&data[0]) != 0 || usbRecvByte(&data[1]) != 0)
            break;
        writeFn(data);
        len -= 2;
    }
    usbIoDone();
    return 0;
}
예제 #2
0
static uint8_t
ioWriteLoop(WriteFn_t writeFn, uint16_t len)
{
    uint8_t data;

    usbInitIo(len, ENDPOINT_DIR_OUT);
    while (len-- != 0) {
        if (usbRecvByte(&data) != 0)
            break;
        writeFn(data);
    }
    usbIoDone();
    return 0;
}
예제 #3
0
static uint8_t
ioWriteNibLoop(uint16_t len)
{
    uint16_t i;
    uint8_t data, *ptr;

    // Probably an error, but handle it anyway.
    if (len == 0)
        return 0;

    suppressNibCmd = false;
    usbInitIo(len, ENDPOINT_DIR_OUT);
    iec_release(IO_DATA);

    /*
     * We're ready to go, kick off the actual data transfer by writing
     * all saved writes. We keep a queue because the 1541 and 1571 drive
     * code may send different numbers of bytes here.
     */
    for (ptr = savedNibWrites; ptr != savedNibWritePtr; ptr++)
        nib_parburst_write(*ptr);
    savedNibWritePtr = savedNibWrites;

    for (i = 0; i < len; i++) {
        // Get the byte via USB
        if (usbRecvByte(&data) != 0)
            break;

        // Write a byte to the parport
        if (nib_write_handshaked(data, i & 1) < 0) {
            DEBUGF(DBG_ERROR, "nbwrh1 to\n");
            return -1;
        }
    }

    /*
     * All bytes written ok, so write a final zero byte and read back the
     * dummy result.
     */
    nib_write_handshaked(0, i & 1);
    nib_parburst_read();

    usbIoDone();
    return 0;
}
예제 #4
0
static uint8_t
ioWriteNibSrqLoop(uint16_t len)
{
    uint16_t i;
    uint8_t data, *ptr;

    // nibtools drive code requires at least one data byte.
    if (len == 0)
        return 0;

    suppressNibCmd = false;
    usbInitIo(len, ENDPOINT_DIR_OUT);
    iec_release(IO_SRQ | IO_CLK | IO_DATA | IO_ATN);

    /*
     * We're ready to go, kick off the actual data transfer by writing
     * all saved writes. We keep a queue because the 1541 and 1571 drive
     * code may send different numbers of bytes here.
     */
    for (ptr = savedNibWrites; ptr != savedNibWritePtr; ptr++)
        nib_srqburst_write(*ptr);
    savedNibWritePtr = savedNibWrites;

    for (i = 0; i < len; i++) {
        // Get data byte from USB.
        if (usbRecvByte(&data) != 0)
            break;

        // Write data byte via SRQ, break if timeout error.
        if (nib_srq_write_handshaked(data, i & 1) != 0) {
            DEBUGF(DBG_ERROR, "nbwrh1 to\n");
            return -1;
        }
    }

    // Read back the dummy result.
    nib_srqburst_read();

    usbIoDone();
    return 0;
}
예제 #5
0
파일: usart.c 프로젝트: kulp/libfpgalink
// Execute pending USART read/write operations
void usartExecute(void) {
	usbSelectEndpoint(OUT_ENDPOINT_ADDR);
	if ( usbOutPacketReady() ) {
		uint8 byte, chan;
		uint16 count;
		do {
			// Read/write flag & channel
			chan = usbRecvByte(); usartSendByte(chan);
			
			// Count high byte
			byte = usbRecvByte(); usartSendByte(byte);
			count = byte;
			
			// Count low byte
			byte = usbRecvByte(); usartSendByte(byte);
			count <<= 8;
			count |= byte;
			
			// Check to see if it's a read or a write
			if ( chan & 0x80 ) {
				// The host is reading a channel
				usbAckPacket();                        // acknowledge the OUT packet
				usbSelectEndpoint(IN_ENDPOINT_ADDR);   // switch to the IN endpoint
				#if USART_DEBUG == 1
					debugSendFlashString(PSTR("READ("));
					debugSendByteHex(count);
					debugSendByte(')');
					debugSendByte('\r');
				#endif
				while ( !(UCSR1A & (1<<TXC1)) );       // wait for send complete
				__asm volatile(
					"nop\nnop\nnop\nnop\n"              // give things a chance to settle
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					"nop\nnop\nnop\nnop\n"
					::);
				UCSR1B = (1<<RXEN1);                   // TX disabled, RX enabled
				while ( !usbInPacketReady() );
				USART_OUT &= ~bmTX;                 // TX low says "I'm ready"
				do {
					byte = usartRecvByte();
					if ( !usbReadWriteAllowed() ) {
						USART_OUT |= bmTX;            // TX high says "I'm not ready"
						usbFlushPacket();
						while ( !usbInPacketReady() );
						USART_OUT &= ~bmTX;           // TX low says "OK I'm ready now"
					}
					usbPutByte(byte);
					count--;
				} while ( count );
				UCSR1B = (1<<TXEN1);                   // TX enabled, RX disabled
				USART_OUT |= bmTX;                  // TX high says "I acknowledge receipt of your data"
				usbFlushPacket();                      // flush final packet
				usbSelectEndpoint(OUT_ENDPOINT_ADDR);  // ready for next command
				return;                                // there cannot be any more work to do
			} else {
				// The host is writing a channel
				#if USART_DEBUG == 1
					debugSendFlashString(PSTR("WRITE("));
					debugSendByteHex(count);
					debugSendByte(')');
					debugSendByte('\r');
				#endif
				do {
					byte = usbRecvByte();
					while ( PIND & bmRX );          // ensure RX is still low
					usartSendByte(byte);
					count--;
				} while ( count );
			}
		} while ( usbReadWriteAllowed() );
		usbAckPacket();
	}
예제 #6
0
파일: iec.c 프로젝트: Flaviowebit/openCBM
/*
 * Write bytes to the drive via the CBM default protocol.
 * Returns number of successful written bytes or 0 on error.
 */
static uint16_t
iec_raw_write(uint16_t len, uint8_t flags)
{
    uint8_t atn, talk, data;
    uint16_t rv;

    rv = len;
    atn = flags & XUM_WRITE_ATN;
    talk = flags & XUM_WRITE_TALK;
    eoi = 0;

    DEBUGF(DBG_INFO, "cwr %d, atn %d, talk %d\n", len, atn, talk);
    if (len == 0)
        return 0;

    usbInitIo(len, ENDPOINT_DIR_OUT);

    /*
     * First, check if any device is present on the bus.
     * If ATN and RST are both low (active), we know that at least one
     * drive is attached but none are powered up. In this case, we
     * bail out early. Otherwise, we'd get stuck in wait_for_listener().
     */
    if (!iec_wait_timeout_2ms(IO_ATN|IO_RESET, 0)) {
        DEBUGF(DBG_ERROR, "write: no devs on bus\n");
        usbIoDone();
        return 0;
    }

    iec_release(IO_DATA);
    iec_set(IO_CLK | (atn ? IO_ATN : 0));
    IEC_DELAY();

    // Wait for any device to pull data after we set CLK. This is actually
    // IEC_T_AT (1 ms) but we allow a bit longer.
    if (!iec_wait_timeout_2ms(IO_DATA, IO_DATA)) {
        DEBUGF(DBG_ERROR, "write: no devs\n");
        iec_release(IO_CLK | IO_ATN);
        usbIoDone();
        return 0;
    }

    /*
     * Wait a short while for drive to be ready for us to release CLK.
     * This uses the typical value for IEC_T_NE. Even though it has no
     * minimum, the transfer starts to be unreliable for Tne somewhere
     * below 10 us.
     */
    DELAY_US(IEC_T_NE);

    // Respond with data as soon as device is ready (max time Tne, 200 us).
    while (len != 0) {
        // Be sure DATA line has been pulled by device. If not, we timed
        // out without a device being ready.
        if (!iec_get(IO_DATA)) {
            DEBUGF(DBG_ERROR, "write: dev not pres\n");
            rv = 0;
            break;
        }

        // Release CLK and wait forever for listener to release data.
        if (!wait_for_listener()) {
            DEBUGF(DBG_ERROR, "write: w4l abrt\n");
            rv = 0;
            break;
        }

        /*
         * Signal EOI by waiting so long (IEC_T_YE, > 200 us) that
         * listener pulls DATA, then wait for it to be released.
         * The device will do so in IEC_T_EI, >= 60 us.
         *
         * If we're not signalling EOI, we must set CLK (below) in less
         * than 200 us after wait_for_listener() (IEC_T_RY).
         */
        if (len == 1 && !atn) {
            iec_wait_timeout_2ms(IO_DATA, IO_DATA);
            iec_wait_timeout_2ms(IO_DATA, 0);
        }
        iec_set(IO_CLK);

        // Get a data byte from host, quitting if it signalled an abort.
        if (usbRecvByte(&data) != 0) {
            rv = 0;
            break;
        }
        if (send_byte(data)) {
            len--;
            DELAY_US(IEC_T_BB);
        } else {
            DEBUGF(DBG_ERROR, "write: io err\n");
            rv = 0;
            break;
        }

        wdt_reset();
    }
    usbIoDone();

    /*
     * We rely on the per-byte IEC_T_BB delay (above) being more than
     * the minimum time before releasing ATN (IEC_T_R).
     */
    if (rv != 0) {
        // Talk-ATN turn around (talker and listener exchange roles).
        if (talk) {
            // Hold DATA and release ATN, waiting talk-ATN release time.
            iec_set_release(IO_DATA, IO_ATN);
            DELAY_US(IEC_T_TK);

            // Now release CLK and wait for device to grab it.
            iec_release(IO_CLK);
            IEC_DELAY();

            // Wait forever for device (IEC_T_DC).
            while (!iec_get(IO_CLK)) {
                if (!TimerWorker()) {
                    rv = 0;
                    break;
                }
            }
        } else
            iec_release(IO_ATN);
    } else {
        /*
         * If there was an error, release all lines before returning.
         * Delay the minimum time to releasing ATN after frame, just in
         * case the IEC_T_BB delay (above) was skipped. It is only performed
         * if send_byte() succeeded and not in this error case.
         */
        DELAY_US(IEC_T_R);
        iec_release(IO_CLK | IO_ATN);
    }

    DEBUGF(DBG_INFO, "wrv=%d\n", rv);
    return rv;
}
예제 #7
0
파일: ieee.c 프로젝트: Flaviowebit/openCBM
/* 
 * Write bytes to the drive via the CBM default protocol.
 * Returns number of successful written bytes or 0 on error.
 */
static uint16_t 
ieee_raw_write(uint16_t len, uint8_t flags)
{
    uint8_t atn, talk, data, device, sa;
    uint16_t rv;

    rv = len;
    atn = flags & XUM_WRITE_ATN;
    talk = flags & XUM_WRITE_TALK;

    eoi = 0;
    ieee_status = 0;

    usbInitIo(len, ENDPOINT_DIR_OUT);

    if(atn && len >= 1)
    {
        // get device# from USB 
        if (usbRecvByte(&device) != 0) 
        {
            return 0;
        }
        len--;
        if(len == 0 || ((device & 0x1f) == 0x1f))
        {
            // unlisten, untalk
            if (device & 0x40) 
            {
                IeeeUntalk();
            }
            if (device & 0x20) 
            {
                IeeeUnlisten();
            }
        }
        else
        {
            // get secondary-address from USB
            if (usbRecvByte(&sa) != 0) 
            {
                return 0;
            }
            len--;

            if (talk) 
            {
                IeeeTalk(device, sa);
                len = 0;
            }
            else if(len > 2)
            {
                // open
            }
            else switch(sa & 0xf0)
            {
              case 0xE0:
                // close
                IeeeClose(device, sa);
                break;
              case 0xF0:
                // open
                IeeeOpen(device, sa, NULL);
                break;
              case 0x60:
                // listen
                IeeeListen(device, sa);
                break;
              default:
                // error????
                break;
            }
        }
    }


    // send data
    //
    while (len != 0) {
        // Get a data byte from host, quitting if it signalled an abort.
        if (usbRecvByte(&data) != 0) 
        {
            rv = 0;
            break;
        }
        if (IeeeBsout(data)) 
        {
            rv = 0;
            break;
        } 
        len--;

        // watchdog
        wdt_reset();
    }
    usbIoDone();

    return rv;
}