Subversion Repositories freemyipod

Rev

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