Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
15 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
6
//    This file is part of emBIOS.
7
//
8
//    emBIOS is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emBIOS is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "panic.h"
26
#include "usb.h"
27
#include "usb_ch9.h"
28
#include "usbdrv.h"
29
#include "thread.h"
30
#include "console.h"
31
#include "util.h"
25 theseven 32
#include "contextswitch.h"
54 theseven 33
#include "power.h"
35 theseven 34
#include "mmu.h"
29 theseven 35
#include "shutdown.h"
92 theseven 36
#include "execimage.h"
85 theseven 37
#ifdef HAVE_I2C
38
#include "i2c.h"
39
#endif
95 theseven 40
#ifdef HAVE_BOOTFLASH
41
#include "bootflash.h"
42
#endif
15 theseven 43
 
44
 
45
static uint8_t ctrlresp[2] CACHEALIGN_ATTR;
46
static uint32_t dbgrecvbuf[0x80] CACHEALIGN_ATTR;
47
static uint32_t dbgsendbuf[0x80] CACHEALIGN_ATTR;
48
static uint32_t dbgasyncsendbuf[0x80] CACHEALIGN_ATTR;
49
static char dbgendpoints[4] IBSS_ATTR;
50
 
51
enum dbgaction_t
52
{
53
    DBGACTION_IDLE = 0,
54
    DBGACTION_I2CSEND,
55
    DBGACTION_I2CRECV,
29 theseven 56
    DBGACTION_RESET,
57
    DBGACTION_POWEROFF,
58
    DBGACTION_CWRITE,
59
    DBGACTION_CREAD,
92 theseven 60
    DBGACTION_CFLUSH,
95 theseven 61
    DBGACTION_EXECIMAGE,
62
    DBGACTION_READBOOTFLASH,
63
    DBGACTION_WRITEBOOTFLASH
15 theseven 64
};
65
 
66
static uint32_t dbgstack[0x100] STACK_ATTR;
67
struct wakeup dbgwakeup IBSS_ATTR;
68
extern struct scheduler_thread* scheduler_threads;
69
static enum dbgaction_t dbgaction IBSS_ATTR;
29 theseven 70
static int dbgi2cbus;
71
static int dbgi2cslave;
72
static int dbgactionaddr;
95 theseven 73
static int dbgactionoffset;
29 theseven 74
static int dbgactionlength;
75
static int dbgactionconsoles;
76
static int dbgactiontype;
25 theseven 77
static char dbgconsendbuf[4096];
78
static char dbgconrecvbuf[1024];
79
static int dbgconsendreadidx IBSS_ATTR;
80
static int dbgconsendwriteidx IBSS_ATTR;
81
static int dbgconrecvreadidx IBSS_ATTR;
82
static int dbgconrecvwriteidx IBSS_ATTR;
83
static struct wakeup dbgconsendwakeup IBSS_ATTR;
84
static struct wakeup dbgconrecvwakeup IBSS_ATTR;
85
static bool dbgconsoleattached IBSS_ATTR;
15 theseven 86
 
25 theseven 87
static const char dbgconoverflowstr[] = "\n\n[overflowed]\n\n";
15 theseven 88
 
35 theseven 89
extern int _initstart;   // These aren't ints at all, but gcc complains about void types being
90
extern int _sdramstart;  // used here, and we only need the address, so forget about it...
25 theseven 91
 
35 theseven 92
 
15 theseven 93
static struct usb_device_descriptor CACHEALIGN_ATTR device_descriptor =
94
{
95
    .bLength            = sizeof(struct usb_device_descriptor),
96
    .bDescriptorType    = USB_DT_DEVICE,
97
    .bcdUSB             = 0x0200,
98
    .bDeviceClass       = USB_CLASS_VENDOR_SPEC,
99
    .bDeviceSubClass    = 0xff,
100
    .bDeviceProtocol    = 0xff,
101
    .bMaxPacketSize0    = 64,
102
    .idVendor           = 0xffff,
103
    .idProduct          = 0xe000,
104
    .bcdDevice          = 0x0001,
105
    .iManufacturer      = 1,
106
    .iProduct           = 2,
107
    .iSerialNumber      = 0,
108
    .bNumConfigurations = 1
109
};
110
 
111
static struct usb_config_bundle
112
{
113
    struct usb_config_descriptor config_descriptor;
114
    struct usb_interface_descriptor interface_descriptor;
115
    struct usb_endpoint_descriptor endpoint1_descriptor;
116
    struct usb_endpoint_descriptor endpoint2_descriptor;
117
    struct usb_endpoint_descriptor endpoint3_descriptor;
118
    struct usb_endpoint_descriptor endpoint4_descriptor;
119
} __attribute__((packed)) CACHEALIGN_ATTR config_bundle = 
120
{
121
    .config_descriptor =
122
    {
123
        .bLength             = sizeof(struct usb_config_descriptor),
124
        .bDescriptorType     = USB_DT_CONFIG,
125
        .wTotalLength        = sizeof(struct usb_config_descriptor)
126
                             + sizeof(struct usb_interface_descriptor)
127
                             + sizeof(struct usb_endpoint_descriptor) * 4,
128
        .bNumInterfaces      = 1,
129
        .bConfigurationValue = 1,
130
        .iConfiguration      = 0,
131
        .bmAttributes        = USB_CONFIG_ATT_ONE,
132
        .bMaxPower           = 250
133
    },
134
    .interface_descriptor =
135
    {
136
        .bLength             = sizeof(struct usb_interface_descriptor),
137
        .bDescriptorType     = USB_DT_INTERFACE,
138
        .bInterfaceNumber    = 0,
139
        .bAlternateSetting   = 0,
140
        .bNumEndpoints       = 4,
141
        .bInterfaceClass     = USB_CLASS_VENDOR_SPEC,
142
        .bInterfaceSubClass  = 0xff,
143
        .bInterfaceProtocol  = 0xff,
144
        .iInterface          = 0
145
    },
146
    .endpoint1_descriptor =
147
    {
148
        .bLength             = sizeof(struct usb_endpoint_descriptor),
149
        .bDescriptorType     = USB_DT_ENDPOINT,
150
        .bEndpointAddress    = 0,
151
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
152
        .wMaxPacketSize      = 0,
153
        .bInterval           = 1
154
    },
155
    .endpoint2_descriptor =
156
    {
157
        .bLength             = sizeof(struct usb_endpoint_descriptor),
158
        .bDescriptorType     = USB_DT_ENDPOINT,
159
        .bEndpointAddress    = 0,
160
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
161
        .wMaxPacketSize      = 0,
162
        .bInterval           = 1
163
    },
164
    .endpoint3_descriptor =
165
    {
166
        .bLength             = sizeof(struct usb_endpoint_descriptor),
167
        .bDescriptorType     = USB_DT_ENDPOINT,
168
        .bEndpointAddress    = 0,
169
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
170
        .wMaxPacketSize      = 0,
171
        .bInterval           = 1
172
    },
173
    .endpoint4_descriptor =
174
    {
175
        .bLength             = sizeof(struct usb_endpoint_descriptor),
176
        .bDescriptorType     = USB_DT_ENDPOINT,
177
        .bEndpointAddress    = 0,
178
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
179
        .wMaxPacketSize      = 0,
180
        .bInterval           = 1
181
    }
182
};
183
 
184
static struct usb_string_descriptor CACHEALIGN_ATTR string_devicename =
185
{
186
    32,
187
    USB_DT_STRING,
188
    {'e', 'm', 'B', 'I', 'O', 'S', ' ', 'D', 'e', 'b', 'u', 'g', 'g', 'e', 'r'}
189
};
190
 
191
static const struct usb_string_descriptor CACHEALIGN_ATTR lang_descriptor =
192
{
193
    4,
194
    USB_DT_STRING,
195
    {0x0409}
196
};
197
 
198
 
199
void usb_setup_dbg_listener()
200
{
201
    usb_drv_recv(dbgendpoints[0], dbgrecvbuf, usb_drv_port_speed() ? 512 : 64);
202
}
203
 
204
void usb_handle_control_request(struct usb_ctrlrequest* req)
205
{
206
    const void* addr;
207
    int size = -1;
208
    switch (req->bRequest)
209
    {
210
    case USB_REQ_GET_STATUS:
211
        if (req->bRequestType == USB_DIR_IN) ctrlresp[0] = 1;
212
        else ctrlresp[0] = 0;
213
        ctrlresp[1] = 0;
214
        addr = ctrlresp;
215
        size = 2;
216
        break;
217
    case USB_REQ_CLEAR_FEATURE:
218
        if (req->bRequestType == USB_RECIP_ENDPOINT && req->wValue == USB_ENDPOINT_HALT)
219
            usb_drv_stall(req->wIndex & 0xf, false, req->wIndex >> 7);
220
        size = 0;
221
        break;
222
    case USB_REQ_SET_FEATURE:
223
        size = 0;
224
        break;
225
    case USB_REQ_SET_ADDRESS:
226
        size = 0;
227
        usb_drv_cancel_all_transfers();
228
        usb_drv_set_address(req->wValue);
229
        usb_setup_dbg_listener();
230
        break;
231
    case USB_REQ_GET_DESCRIPTOR:
232
        switch (req->wValue >> 8)
233
        {
234
        case USB_DT_DEVICE:
235
            addr = &device_descriptor;
236
            size = sizeof(device_descriptor);
237
            break;
238
        case USB_DT_OTHER_SPEED_CONFIG:
239
        case USB_DT_CONFIG:
240
            if ((req->wValue >> 8) == USB_DT_CONFIG)
241
            {
242
                int maxpacket = usb_drv_port_speed() ? 512 : 64;
243
                config_bundle.endpoint1_descriptor.wMaxPacketSize = maxpacket;
244
                config_bundle.endpoint2_descriptor.wMaxPacketSize = maxpacket;
245
                config_bundle.endpoint3_descriptor.wMaxPacketSize = maxpacket;
246
                config_bundle.endpoint4_descriptor.wMaxPacketSize = maxpacket;
247
                config_bundle.config_descriptor.bDescriptorType = USB_DT_CONFIG;
248
            }
249
            else
250
            {
251
                int maxpacket = usb_drv_port_speed() ? 64 : 512;
252
                config_bundle.endpoint1_descriptor.wMaxPacketSize = maxpacket;
253
                config_bundle.endpoint2_descriptor.wMaxPacketSize = maxpacket;
254
                config_bundle.endpoint3_descriptor.wMaxPacketSize = maxpacket;
255
                config_bundle.endpoint4_descriptor.wMaxPacketSize = maxpacket;
256
                config_bundle.config_descriptor.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
257
            }
258
            addr = &config_bundle;
259
            size = sizeof(config_bundle);
260
            break;
261
        case USB_DT_STRING:
262
            switch (req->wValue & 0xff)
263
            {
264
            case 0:
265
                addr = &lang_descriptor;
266
                size = sizeof(lang_descriptor);
267
                break;
268
            case 1:
269
                string_devicename.bLength = 14;
270
                addr = &string_devicename;
271
                size = 14;
272
            case 2:
273
                string_devicename.bLength = sizeof(string_devicename);
274
                addr = &string_devicename;
275
                size = sizeof(string_devicename);
276
                break;
277
            }
278
            break;
279
        }
280
        break;
281
    case USB_REQ_GET_CONFIGURATION:
282
        ctrlresp[0] = 1;
283
        addr = ctrlresp;
284
        size = 1;
285
        break;
286
    case USB_REQ_SET_CONFIGURATION:
287
        usb_drv_cancel_all_transfers();
288
        usb_setup_dbg_listener();
289
        size = 0;
290
        break;
291
    }
292
    if (!size) usb_drv_send_nonblocking(0, NULL, 0);
293
    else if (size == -1)
294
    {
295
        usb_drv_stall(0, true, true);
296
        usb_drv_stall(0, true, false);
297
    }
298
    else
299
    {
300
        usb_drv_recv(0, NULL, 0);
301
        usb_drv_send_nonblocking(0, addr, size > req->wLength ? req->wLength : size);
302
    }
303
}
304
 
29 theseven 305
bool set_dbgaction(enum dbgaction_t action, int addsize)
15 theseven 306
{
307
    if (dbgaction != DBGACTION_IDLE)
308
    {
309
        dbgsendbuf[0] = 3;
29 theseven 310
        usb_drv_send_nonblocking(dbgendpoints[1], dbgsendbuf, 16 + addsize);
15 theseven 311
        return true;
312
    }
313
    dbgaction = action;
314
    wakeup_signal(&dbgwakeup);
315
    return false;
316
}
317
 
318
void reset() __attribute__((noreturn));
319
 
320
void usb_handle_transfer_complete(int endpoint, int dir, int status, int length)
321
{
322
    void* addr = dbgsendbuf;
323
    int size = 0;
324
    if (endpoint == dbgendpoints[0])
325
    {
326
        switch (dbgrecvbuf[0])
327
        {
28 theseven 328
        case 1:  // GET INFO
15 theseven 329
            dbgsendbuf[0] = 1;
330
            size = 16;
28 theseven 331
            switch (dbgrecvbuf[1])
332
            {
333
            case 0:  // GET VERSION INFO
85 theseven 334
                dbgsendbuf[1] = VERSION_SVN_INT;
335
                dbgsendbuf[2] = VERSION_MAJOR | (VERSION_MINOR << 8)
28 theseven 336
                              | (VERSION_PATCH << 16) | (1 << 24);
85 theseven 337
                dbgsendbuf[3] = PLATFORM_ID;
28 theseven 338
                break;
339
            case 1:  // GET PACKET SIZE INFO
340
                dbgsendbuf[1] = 0x02000200;
341
                dbgsendbuf[2] = usb_drv_get_max_out_size();
342
                dbgsendbuf[3] = usb_drv_get_max_in_size();
343
                break;
35 theseven 344
            case 2:  // GET USER MEMORY INFO
345
                dbgsendbuf[1] = (uint32_t)&_initstart;
346
                dbgsendbuf[2] = (uint32_t)&_sdramstart;
347
                break;
28 theseven 348
            default:
349
                dbgsendbuf[0] = 2;
350
            }
15 theseven 351
            break;
352
        case 2:  // RESET
29 theseven 353
            if (dbgrecvbuf[1])
354
            {
355
                if (set_dbgaction(DBGACTION_RESET, 0)) break;
356
                dbgsendbuf[0] = 1;
357
                size = 16;
358
            }
359
            else reset();
15 theseven 360
            break;
361
        case 3:  // POWER OFF
29 theseven 362
            if (set_dbgaction(DBGACTION_POWEROFF, 0)) break;
363
            dbgactiontype = dbgrecvbuf[1];
364
            dbgsendbuf[0] = 1;
365
            size = 16;
15 theseven 366
            break;
367
        case 4:  // READ MEMORY
368
            dbgsendbuf[0] = 1;
369
            memcpy(&dbgsendbuf[4], (const void*)dbgrecvbuf[1], dbgrecvbuf[2]);
370
            size = dbgrecvbuf[2] + 16;
371
            break;
372
        case 5:  // WRITE MEMORY
373
            dbgsendbuf[0] = 1;
374
            memcpy((void*)dbgrecvbuf[1], &dbgrecvbuf[4], dbgrecvbuf[2]);
375
            size = 16;
376
            break;
377
        case 6:  // READ DMA
378
            dbgsendbuf[0] = 1;
379
            usb_drv_send_nonblocking(dbgendpoints[1], dbgsendbuf, 16);
380
            usb_drv_send_nonblocking(dbgendpoints[3], (const void*)dbgrecvbuf[1], dbgrecvbuf[2]);
381
            break;
382
        case 7:  // WRITE DMA
383
            dbgsendbuf[0] = 1;
384
            size = 16;
385
            usb_drv_recv(dbgendpoints[2], (void*)dbgrecvbuf[1], dbgrecvbuf[2]);
386
            break;
85 theseven 387
#ifdef HAVE_I2C
15 theseven 388
        case 8:  // READ I2C
29 theseven 389
            if (set_dbgaction(DBGACTION_I2CRECV, dbgrecvbuf[1] >> 24)) break;
15 theseven 390
            dbgi2cbus = dbgrecvbuf[1] & 0xff;
391
            dbgi2cslave = (dbgrecvbuf[1] >> 8) & 0xff;
29 theseven 392
            dbgactionaddr = (dbgrecvbuf[1] >> 16) & 0xff;
393
            dbgactionlength = dbgrecvbuf[1] >> 24;
15 theseven 394
            break;
395
        case 9:  // WRITE I2C
29 theseven 396
            if (set_dbgaction(DBGACTION_I2CSEND, 0)) break;
15 theseven 397
            dbgi2cbus = dbgrecvbuf[1] & 0xff;
398
            dbgi2cslave = (dbgrecvbuf[1] >> 8) & 0xff;
29 theseven 399
            dbgactionaddr = (dbgrecvbuf[1] >> 16) & 0xff;
400
            dbgactionlength = dbgrecvbuf[1] >> 24;
401
            memcpy(dbgasyncsendbuf, &dbgsendbuf[4], dbgactionlength);
15 theseven 402
            break;
85 theseven 403
#endif
25 theseven 404
        case 10:  // READ CONSOLE
405
            dbgconsoleattached = true;
406
            int bytes = dbgconsendwriteidx - dbgconsendreadidx;
407
            if (bytes >= sizeof(dbgconsendbuf)) bytes -= sizeof(dbgconsendbuf);
408
            if (bytes)
409
            {
410
                if (bytes < 0) bytes += sizeof(dbgconsendbuf);
411
                if (bytes > dbgrecvbuf[1]) bytes = dbgrecvbuf[1];
412
                int readbytes = bytes;
413
                char* outptr = (char*)&dbgsendbuf[4];
414
                if (dbgconsendreadidx + bytes >= sizeof(dbgconsendbuf))
415
                {
416
                    readbytes = sizeof(dbgconsendbuf) - dbgconsendreadidx;
417
                    memcpy(outptr, &dbgconsendbuf[dbgconsendreadidx], readbytes);
418
                    dbgconsendreadidx = 0;
419
                    outptr = &outptr[readbytes];
420
                    readbytes = bytes - readbytes;
421
                }
422
                if (readbytes) memcpy(outptr, &dbgconsendbuf[dbgconsendreadidx], readbytes);
423
                dbgconsendreadidx += readbytes;
26 theseven 424
                wakeup_signal(&dbgconsendwakeup);
25 theseven 425
            }
426
            dbgsendbuf[0] = 1;
427
            dbgsendbuf[1] = bytes;
428
            dbgsendbuf[2] = sizeof(dbgconsendbuf);
429
            dbgsendbuf[3] = dbgconsendwriteidx - dbgconsendreadidx;
430
            size = 16 + dbgrecvbuf[1];
431
            break;
26 theseven 432
        case 11:  // WRITE CONSOLE
433
            bytes = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
434
            if (bytes < 0) bytes += sizeof(dbgconrecvbuf);
435
            if (bytes)
436
            {
437
                if (bytes > dbgrecvbuf[1]) bytes = dbgrecvbuf[1];
438
                int writebytes = bytes;
439
                char* readptr = (char*)&dbgrecvbuf[4];
440
                if (dbgconrecvwriteidx + bytes >= sizeof(dbgconrecvbuf))
441
                {
442
                    writebytes = sizeof(dbgconrecvbuf) - dbgconrecvwriteidx;
443
                    memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
444
                    dbgconrecvwriteidx = 0;
445
                    readptr = &readptr[writebytes];
446
                    writebytes = bytes - writebytes;
447
                }
448
                if (writebytes) memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
449
                dbgconrecvwriteidx += writebytes;
450
                wakeup_signal(&dbgconrecvwakeup);
451
            }
452
            dbgsendbuf[0] = 1;
453
            dbgsendbuf[1] = bytes;
454
            dbgsendbuf[2] = sizeof(dbgconrecvbuf);
455
            dbgsendbuf[3] = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
456
            size = 16;
457
            break;
29 theseven 458
        case 12:  // CWRITE
459
            if (set_dbgaction(DBGACTION_CWRITE, 0)) break;
460
            dbgactionconsoles = dbgrecvbuf[1];
461
            dbgactionlength = dbgrecvbuf[2];
462
            memcpy(dbgasyncsendbuf, &dbgrecvbuf[4], dbgactionlength);
463
            break;
464
        case 13:  // CREAD
465
            if (set_dbgaction(DBGACTION_CREAD, dbgrecvbuf[2])) break;
466
            dbgactionconsoles = dbgrecvbuf[1];
467
            dbgactionlength = dbgrecvbuf[2];
468
            break;
469
        case 14:  // CFLUSH
470
            if (set_dbgaction(DBGACTION_CFLUSH, 0)) break;
471
            dbgactionconsoles = dbgrecvbuf[1];
472
            break;
31 theseven 473
        case 15:  // GET PROCESS INFO
474
            dbgsendbuf[0] = 1;
475
            dbgsendbuf[1] = SCHEDULER_THREAD_INFO_VERSION;
476
            dbgsendbuf[2] = MAX_THREADS * sizeof(struct scheduler_thread);
57 theseven 477
            memcpy(&dbgsendbuf[4], (void*)((uint32_t)scheduler_threads + dbgrecvbuf[1]),
478
                   dbgrecvbuf[2]);
479
            size = dbgrecvbuf[2] + 16;
31 theseven 480
            break;
34 theseven 481
        case 16:  // FREEZE SCHEDULER
54 theseven 482
            dbgsendbuf[1] = scheduler_freeze(dbgrecvbuf[1]);
34 theseven 483
            dbgsendbuf[0] = 1;
484
            size = 16;
485
            break;
35 theseven 486
        case 17:  // SUSPEND THREAD
54 theseven 487
            if (dbgrecvbuf[1])
488
            {
489
                if (thread_suspend(dbgrecvbuf[2]) == -4) dbgsendbuf[1] = 1;
490
                else dbgsendbuf[1] = 0;
491
            }
492
            else
493
            {
494
                if (thread_resume(dbgrecvbuf[2]) == -5) dbgsendbuf[1] = 0;
495
                else dbgsendbuf[1] = 1;
496
            }
35 theseven 497
            dbgsendbuf[0] = 1;
498
            size = 16;
499
            break;
500
        case 18:  // KILL THREAD
501
            thread_terminate(dbgrecvbuf[1]);
502
            dbgsendbuf[0] = 1;
503
            size = 16;
504
            break;
57 theseven 505
        case 19:  // KILL THREAD
35 theseven 506
            dbgsendbuf[0] = 1;
507
            dbgsendbuf[1] = thread_create((const char*)dbgsendbuf[1], (const void*)dbgsendbuf[2],
508
                                          (char*)dbgsendbuf[3], dbgsendbuf[4], dbgsendbuf[5],
509
                                          dbgsendbuf[6], dbgsendbuf[7]);
510
            size = 16;
511
            break;
512
        case 20:  // FLUSH CACHE
513
            clean_dcache();
514
            invalidate_icache();
515
            dbgsendbuf[0] = 1;
516
            size = 16;
517
            break;
92 theseven 518
        case 21:  // EXECIMAGE
519
            if (set_dbgaction(DBGACTION_EXECIMAGE, 0)) break;
520
            dbgactionaddr = dbgrecvbuf[1];
521
            break;
95 theseven 522
#ifdef HAVE_BOOTFLASH
523
        case 22:  // READ BOOT FLASH
524
            if (set_dbgaction(DBGACTION_READBOOTFLASH, 0)) break;
525
            dbgactionaddr = dbgrecvbuf[1];
526
            dbgactionoffset = dbgrecvbuf[2];
527
            dbgactionlength = dbgrecvbuf[3];
528
            break;
529
        case 23:  // WRITE BOOT FLASH
530
            if (set_dbgaction(DBGACTION_WRITEBOOTFLASH, 0)) break;
531
            dbgactionaddr = dbgrecvbuf[1];
532
            dbgactionoffset = dbgrecvbuf[2];
533
            dbgactionlength = dbgrecvbuf[3];
534
            break;
535
#endif
15 theseven 536
        default:
537
            dbgsendbuf[0] = 2;
538
            size = 16;
539
        }
540
        usb_setup_dbg_listener();
541
        if (size) usb_drv_send_nonblocking(dbgendpoints[1], addr, size);
542
    }
543
}
544
 
545
void usb_handle_bus_reset(void)
546
{
547
    dbgendpoints[0] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
548
    dbgendpoints[1] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
549
    dbgendpoints[2] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
550
    dbgendpoints[3] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
551
    config_bundle.endpoint1_descriptor.bEndpointAddress = dbgendpoints[0];
552
    config_bundle.endpoint2_descriptor.bEndpointAddress = dbgendpoints[1];
553
    config_bundle.endpoint3_descriptor.bEndpointAddress = dbgendpoints[2];
554
    config_bundle.endpoint4_descriptor.bEndpointAddress = dbgendpoints[3];
555
    usb_setup_dbg_listener();
556
}
557
 
558
void dbgthread(void)
559
{
560
    int i;
25 theseven 561
    int t;
15 theseven 562
    while (1)
563
    {
564
        wakeup_wait(&dbgwakeup, TIMEOUT_BLOCK);
565
        for (i = 0; i < MAX_THREADS; i++)
566
            if (scheduler_threads[i].state == THREAD_DEFUNCT)
567
            {
568
                if (scheduler_threads[i].block_type == THREAD_DEFUNCT_STKOV)
35 theseven 569
                {
570
                    if (scheduler_threads[i].name)
571
                        cprintf(1, "\n*PANIC*\nStack overflow! (%s)\n",
572
                                scheduler_threads[i].name);
573
                    else cprintf(1, "\n*PANIC*\nStack overflow! (ID %d)\n", i);
574
                }
15 theseven 575
                scheduler_threads[i].state = THREAD_DEFUNCT_ACK;
576
            }
577
        if (dbgaction != DBGACTION_IDLE)
578
        {
579
            switch (dbgaction)
580
            {
85 theseven 581
#ifdef HAVE_I2C
15 theseven 582
            case DBGACTION_I2CSEND:
29 theseven 583
                i2c_send(dbgi2cbus, dbgi2cslave, dbgactionaddr,
584
                         (uint8_t*)dbgasyncsendbuf, dbgactionlength);
15 theseven 585
                dbgasyncsendbuf[0] = 1;
586
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
587
                break;
588
            case DBGACTION_I2CRECV:
29 theseven 589
                i2c_recv(dbgi2cbus, dbgi2cslave, dbgactionaddr,
590
                         (uint8_t*)(&dbgasyncsendbuf[4]), dbgactionlength);
15 theseven 591
                dbgasyncsendbuf[0] = 1;
29 theseven 592
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16 + dbgactionlength);
15 theseven 593
                break;
85 theseven 594
#endif
15 theseven 595
            case DBGACTION_POWEROFF:
29 theseven 596
                if (dbgactiontype) shutdown();
54 theseven 597
                power_off();
15 theseven 598
                break;
29 theseven 599
            case DBGACTION_RESET:
600
                shutdown();
601
                reset();
602
                break;
603
            case DBGACTION_CWRITE:
604
                cwrite(dbgactionconsoles, (const char*)dbgasyncsendbuf, dbgactionlength);
605
                dbgasyncsendbuf[0] = 1;
606
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
607
                break;
608
            case DBGACTION_CREAD:
609
                dbgasyncsendbuf[0] = 1;
30 theseven 610
                dbgasyncsendbuf[1] = cread(dbgactionconsoles, (char*)&dbgasyncsendbuf[4],
611
                                           dbgactionlength, 0);
29 theseven 612
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
613
                break;
614
            case DBGACTION_CFLUSH:
615
                cflush(dbgactionconsoles);
616
                dbgasyncsendbuf[0] = 1;
617
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
618
                break;
92 theseven 619
            case DBGACTION_EXECIMAGE:
620
                dbgasyncsendbuf[0] = 1;
621
                dbgasyncsendbuf[1] = execimage((void*)dbgactionaddr);
622
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
623
                break;
95 theseven 624
#ifdef HAVE_BOOTFLASH
625
            case DBGACTION_READBOOTFLASH:
626
                bootflash_readraw((void*)dbgactionaddr, dbgactionoffset, dbgactionlength);
627
                dbgasyncsendbuf[0] = 1;
628
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
629
                break;
630
            case DBGACTION_WRITEBOOTFLASH:
631
                bootflash_writeraw((void*)dbgactionaddr, dbgactionoffset, dbgactionlength);
632
                dbgasyncsendbuf[0] = 1;
633
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
634
                break;
635
#endif
15 theseven 636
            }
637
            dbgaction = DBGACTION_IDLE;
638
        }
639
    }
640
}
641
 
642
void usb_init(void)
643
{
644
    dbgaction = DBGACTION_IDLE;
645
    wakeup_init(&dbgwakeup);
25 theseven 646
    dbgconsendreadidx = 0;
647
    dbgconsendwriteidx = 0;
648
    dbgconrecvreadidx = 0;
649
    dbgconrecvwriteidx = 0;
650
    wakeup_init(&dbgconsendwakeup);
651
    wakeup_init(&dbgconrecvwakeup);
85 theseven 652
    dbgconsoleattached = false;
15 theseven 653
    thread_create("Debugger", dbgthread, dbgstack, sizeof(dbgstack), 255, SYSTEM_THREAD, true);
654
    usb_drv_init();
655
}
25 theseven 656
 
657
int dbgconsole_getfree() ICODE_ATTR;
658
int dbgconsole_getfree()
659
{
660
    int free = dbgconsendreadidx - dbgconsendwriteidx - 1;
661
    if (free < 0) free += sizeof(dbgconsendbuf);
662
    return free;
663
}
664
 
665
int dbgconsole_makespace(int length) ICODE_ATTR;
666
int dbgconsole_makespace(int length)
667
{
668
    int free = dbgconsole_getfree();
669
    while (!free && dbgconsoleattached)
670
    {
671
        if (wakeup_wait(&dbgconsendwakeup, 2000000) == THREAD_TIMEOUT)
672
            dbgconsoleattached = false;
673
        free = dbgconsole_getfree();
674
    }
675
    if (free) return free > length ? length : free;
676
    if (length > sizeof(dbgconsendbuf) - 17) length = sizeof(dbgconsendbuf) - 17;
677
    uint32_t mode = enter_critical_section();
678
    dbgconsendreadidx += length;
679
    if (dbgconsendreadidx >= sizeof(dbgconsendbuf))
680
        dbgconsendreadidx -= sizeof(dbgconsendbuf);
681
    int offset = 0;
682
    int idx = dbgconsendreadidx;
683
    if (idx + 16 >= sizeof(dbgconsendbuf))
684
    {
685
        offset = sizeof(dbgconsendbuf) - dbgconsendreadidx;
686
        memcpy(&dbgconsendbuf[dbgconsendreadidx], dbgconoverflowstr, offset);
687
        idx = 0;
688
    }
689
    if (offset != 16) memcpy(&dbgconsendbuf[idx], &dbgconoverflowstr[offset], 16 - offset);
690
    leave_critical_section(mode);
691
    return length;
692
}
693
 
694
void dbgconsole_putc(char string)
695
{
696
    dbgconsole_makespace(1);
697
    dbgconsendbuf[dbgconsendwriteidx++] = string;
698
    if (dbgconsendwriteidx >= sizeof(dbgconsendbuf))
699
        dbgconsendwriteidx -= sizeof(dbgconsendbuf);
700
}
701
 
702
void dbgconsole_write(const char* string, size_t length)
703
{
704
    while (length)
705
    {
706
        int space = dbgconsole_makespace(length);
707
        if (dbgconsendwriteidx + space >= sizeof(dbgconsendbuf))
708
        {
709
            int bytes = sizeof(dbgconsendbuf) - dbgconsendwriteidx;
710
            memcpy(&dbgconsendbuf[dbgconsendwriteidx], string, bytes);
711
            dbgconsendwriteidx = 0;
712
            string = &string[bytes];
713
            space -= bytes;
714
            length -= bytes;
715
        }
716
        if (space) memcpy(&dbgconsendbuf[dbgconsendwriteidx], string, space);
717
        dbgconsendwriteidx += space;
718
        string = &string[space];
719
        length -= space;
720
    }
721
}
722
 
723
void dbgconsole_puts(const char* string)
724
{
725
    dbgconsole_write(string, strlen(string));
726
}
26 theseven 727
 
728
int dbgconsole_getavailable() ICODE_ATTR;
729
int dbgconsole_getavailable()
730
{
731
    int available = dbgconrecvwriteidx - dbgconrecvreadidx;
732
    if (available < 0) available += sizeof(dbgconrecvbuf);
733
    return available;
734
}
735
 
736
int dbgconsole_getc(int timeout)
737
{
738
    if (!dbgconsole_getavailable())
739
    {
740
        wakeup_wait(&dbgconrecvwakeup, TIMEOUT_NONE);
741
        if (!dbgconsole_getavailable())
742
        {
743
            wakeup_wait(&dbgconrecvwakeup, timeout);
744
            if (!dbgconsole_getavailable()) return -1;
745
        }
746
    }
747
    int byte = dbgconrecvbuf[dbgconrecvreadidx++];
748
    if (dbgconrecvreadidx >= sizeof(dbgconrecvbuf))
749
        dbgconrecvreadidx -= sizeof(dbgconrecvbuf);
750
    return byte;
751
}
752
 
753
int dbgconsole_read(char* buffer, size_t length, int timeout)
754
{
755
    if (!length) return 0;
756
    int available = dbgconsole_getavailable();
757
    if (!available)
758
    {
759
        wakeup_wait(&dbgconrecvwakeup, TIMEOUT_NONE);
760
        int available = dbgconsole_getavailable();
761
        if (!available)
762
        {
763
            wakeup_wait(&dbgconrecvwakeup, timeout);
764
            int available = dbgconsole_getavailable();
765
            if (!available) return 0;
766
        }
767
    }
768
    if (available > length) available = length;
769
    int left = available;
770
    if (dbgconrecvreadidx + available >= sizeof(dbgconrecvbuf))
771
    {
772
        int bytes = sizeof(dbgconrecvbuf) - dbgconrecvreadidx;
773
        memcpy(buffer, &dbgconrecvbuf[dbgconrecvreadidx], bytes);
774
        dbgconrecvreadidx = 0;
775
        buffer = &buffer[bytes];
776
        left -= bytes;
777
    }
778
    if (left) memcpy(buffer, &dbgconrecvbuf[dbgconrecvreadidx], left);
779
    dbgconrecvreadidx += left;
780
    return available;
781
}