2 * USRP - Universal Software Radio Peripheral
4 * Copyright (C) 2003,2004 Free Software Foundation, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA
21 #include "usrp_common.h"
22 #include "usrp_commands.h"
24 #include "usrp_gpif_inline.h"
28 #include "usb_common.h"
30 #include "usrp_globals.h"
31 #include "usrp_i2c_addr.h"
34 #include "eeprom_io.h"
35 #include "usb_descriptors.h"
38 * offsets into boot eeprom for configuration values
40 #define HW_REV_OFFSET 5
41 #define SERIAL_NO_OFFSET 248
42 #define SERIAL_NO_LEN 8
45 #define bRequestType SETUPDAT[0]
46 #define bRequest SETUPDAT[1]
47 #define wValueL SETUPDAT[2]
48 #define wValueH SETUPDAT[3]
49 #define wIndexL SETUPDAT[4]
50 #define wIndexH SETUPDAT[5]
51 #define wLengthL SETUPDAT[6]
52 #define wLengthH SETUPDAT[7]
55 unsigned char g_tx_enable = 0;
56 unsigned char g_rx_enable = 0;
57 unsigned char g_rx_overrun = 0;
58 unsigned char g_tx_underrun = 0;
61 * the host side fpga loader code pushes an MD5 hash of the bitstream
64 #define USRP_HASH_SIZE 16
65 xdata at USRP_HASH_SLOT_1_ADDR unsigned char hash1[USRP_HASH_SIZE];
70 EP0BCL = 0; // arm EP0 for OUT xfer. This sets the busy bit
72 while (EP0CS & bmEPBUSY) // wait for busy to clear
77 * Handle our "Vendor Extension" commands on endpoint 0.
78 * If we handle this one, return non-zero.
83 if (bRequestType == VRT_VENDOR_IN){
85 /////////////////////////////////
86 // handle the IN requests
87 /////////////////////////////////
95 EP0BUF[0] = g_tx_underrun;
102 EP0BUF[0] = g_rx_overrun;
114 if (!i2c_read (wValueL, EP0BUF, wLengthL))
122 if (!spi_read (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, wLengthL))
134 else if (bRequestType == VRT_VENDOR_OUT){
136 /////////////////////////////////
137 // handle the OUT requests
138 /////////////////////////////////
158 switch (wIndexL){ // sub-command
160 return fpga_load_begin ();
164 return fpga_load_xfer (EP0BUF, EP0BCL);
167 return fpga_load_end ();
175 case VRQ_FPGA_SET_RESET:
176 fpga_set_reset (wValueL);
179 case VRQ_FPGA_SET_TX_ENABLE:
180 fpga_set_tx_enable (wValueL);
183 case VRQ_FPGA_SET_RX_ENABLE:
184 fpga_set_rx_enable (wValueL);
187 case VRQ_FPGA_SET_TX_RESET:
188 fpga_set_tx_reset (wValueL);
191 case VRQ_FPGA_SET_RX_RESET:
192 fpga_set_rx_reset (wValueL);
197 if (!i2c_write (wValueL, EP0BUF, EP0BCL))
203 if (!spi_write (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, EP0BCL))
213 return 0; // invalid bRequestType
223 setup_flowstate_common ();
227 if (usb_setup_packet_avail ())
228 usb_handle_setup_packet ();
231 if (GPIFTRIG & bmGPIF_IDLE){
233 // OK, GPIF is idle. Let's try to give it some work.
235 // First check for underruns and overruns
237 if (UC_BOARD_HAS_FPGA && (USRP_PA & (bmPA_TX_UNDERRUN | bmPA_RX_OVERRUN))){
239 // record the under/over run
240 if (USRP_PA & bmPA_TX_UNDERRUN)
243 if (USRP_PA & bmPA_RX_OVERRUN)
246 // tell the FPGA to clear the flags
250 // Next see if there are any "OUT" packets waiting for our attention,
251 // and if so, if there's room in the FPGA's FIFO for them.
253 if (g_tx_enable && !(EP24FIFOFLGS & 0x02)){ // USB end point fifo is not empty...
255 if (fpga_has_room_for_packet ()){ // ... and FPGA has room for packet
257 GPIFTCB1 = 0x01; SYNCDELAY;
258 GPIFTCB0 = 0x00; SYNCDELAY;
260 setup_flowstate_write ();
263 GPIFTRIG = bmGPIF_EP2_START | bmGPIF_WRITE; // start the xfer
266 while (!(GPIFTRIG & bmGPIF_IDLE)){
267 // wait for the transaction to complete
272 // See if there are any requests for "IN" packets, and if so
273 // whether the FPGA's got any packets for us.
275 if (g_rx_enable && !(EP6CS & bmEPFULL)){ // USB end point fifo is not full...
277 if (fpga_has_packet_avail ()){ // ... and FPGA has packet available
279 GPIFTCB1 = 0x01; SYNCDELAY;
280 GPIFTCB0 = 0x00; SYNCDELAY;
282 setup_flowstate_read ();
285 GPIFTRIG = bmGPIF_EP6_START | bmGPIF_READ; // start the xfer
288 while (!(GPIFTRIG & bmGPIF_IDLE)){
289 // wait for the transaction to complete
293 INPKTEND = 6; // tell USB we filled buffer (6 is our endpoint num)
302 * called at 100 Hz from timer2 interrupt
307 isr_tick (void) interrupt
309 static unsigned char count = 1;
313 USRP_LED_REG ^= bmLED0;
320 * Read h/w rev code and serial number out of boot eeprom and
321 * patch the usb descriptors with the values.
324 patch_usb_descriptors(void)
326 static xdata unsigned char hw_rev;
327 static xdata unsigned char serial_no[8];
330 eeprom_read(I2C_ADDR_BOOT, HW_REV_OFFSET, &hw_rev, 1); // LSB of device id
331 usb_desc_hw_rev_binary_patch_location_0[0] = hw_rev;
332 usb_desc_hw_rev_binary_patch_location_1[0] = hw_rev;
333 usb_desc_hw_rev_ascii_patch_location_0[0] = hw_rev + '0'; // FIXME if we get > 9
335 eeprom_read(I2C_ADDR_BOOT, SERIAL_NO_OFFSET, serial_no, SERIAL_NO_LEN);
337 for (i = 0; i < SERIAL_NO_LEN; i++){
338 unsigned char ch = serial_no[i];
339 if (ch == 0xff) // make unprogrammed EEPROM default to '0'
341 usb_desc_serial_number_ascii[i << 1] = ch;
349 g_rx_enable = 0; // FIXME (work around initialization bug)
355 memset (hash1, 0, USRP_HASH_SIZE); // zero fpga bitstream hash. This forces reload
360 // if (UC_START_WITH_GSTATE_OUTPUT_ENABLED)
361 IFCONFIG |= bmGSTATE; // no conflict, start with it on
366 EA = 0; // disable all interrupts
368 patch_usb_descriptors();
370 setup_autovectors ();
371 usb_install_handlers ();
372 hook_timer_tick ((unsigned short) isr_tick);
374 EIEX4 = 1; // disable INT4 FIXME
375 EA = 1; // global interrupt enable
377 fx2_renumerate (); // simulates disconnect / reconnect