Root/userspace/nanonote/udc.ccp

1#pypp 0
2// vim: set filetype=cpp : //
3// Iris: micro-kernel for a capability-based operating system.
4// boot-programs/udc.ccp: USB device controller driver.
5// Copyright 2009 Bas Wijnen <wijnen@debian.org>
6//
7// This program is free software: you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation, either version 3 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20#include "iris.hh"
21#include "devices.hh"
22#define ARCH
23#include "arch.hh"
24
25class Udc:
26    typedef unsigned char u8
27    typedef unsigned short u16
28    typedef unsigned int u32
29    typedef u8 string
30    // The ugly stuff is because pypp doesn't support __attribute__.
31    /**/struct Setup {
32        u8 request_type;
33        u8 request;
34        u16 value;
35        u16 index;
36        u16 length;
37     } __attribute__ ((packed))
38    /**/struct Device {
39        static u8 const Type = 1;
40        u8 length;
41        u8 type;
42        u16 usb_version;
43        u8 dev_class;
44        u8 subclass;
45        u8 protocol;
46        u8 max_packet_size0;
47        u16 vendor;
48        u16 product;
49        u16 dev_version;
50        string s_manufacturer;
51        string s_product;
52        string s_serial;
53        u8 num_configurations;
54     } __attribute__ ((packed))
55    /**/struct Configuration {
56        static u8 const Type = 2;
57        u8 length;
58        u8 type;
59        u16 total_length;
60        u8 num_interfaces;
61        u8 configuration_value;
62        u8 configuration;
63        u8 attributes;
64        u8 max_power;
65     } __attribute__ ((packed))
66    /**/struct Interface {
67        static u8 const Type = 4;
68        u8 length;
69        u8 type;
70        u8 interface;
71        u8 alternate;
72        u8 num_endpoints;
73        u8 iface_class;
74        u8 subclass;
75        u8 protocol;
76        string name;
77     } __attribute__ ((packed))
78    /**/struct Endpoint {
79        static u8 const Type = 5;
80        u8 length;
81        u8 type;
82        u8 address;
83        u8 attributes;
84        u16 max_packet_size;
85        u8 interval;
86     } __attribute__ ((packed))
87    /**/struct Device_Qualifier {
88        static u8 const Type = 6;
89        u8 length;
90        u8 type;
91        u16 version;
92        u8 dev_class;
93        u8 subclass;
94        u8 protocol;
95        u8 max_packet_size0;
96        u8 num_configurations;
97        u8 reserved;
98     } __attribute__ ((packed))
99    /**/struct Langs {
100        static u8 const Type = 3;
101        u8 length;
102        u8 type;
103        u8 lang;
104     } __attribute__ ((packed))
105    template <unsigned size> struct String {
106        static u8 const Type = 3;
107        u8 length;
108        u8 type;
109        u16 data[size];
110     } __attribute__ ((packed))
111    static unsigned const max_packet_size0 = 64
112    static unsigned const max_packet_size_bulk = 64
113    enum Requests:
114        GET_STATUS = 0
115        CLEAR_FEATURE = 1
116        SET_FEATURE = 3
117        SET_ADDRESS = 5
118        GET_DESCRIPTOR = 6
119        SET_DESCRIPTOR = 7
120        GET_CONFIGURATION = 8
121        SET_CONFIGURATION = 9
122        GET_INTERFACE = 10
123        SET_INTERFACE = 11
124        SYNCH_FRAME = 12
125    enum Request_types:
126        STANDARD_TO_DEVICE = 0
127        VENDOR_TO_DEVICE = 0x40
128        STANDARD_FROM_DEVICE = 0x80
129        VENDOR_FROM_DEVICE = 0xc0
130    enum Endpoint_types:
131        CONTROL = 0
132        ISOCHRONOUS = 1
133        BULK = 2
134        INTERRUPT = 3
135    /**/struct my_config {
136        Configuration config;
137        Interface interface;
138        Endpoint endpoint[2];
139     } __attribute__ ((packed))
140    static Device device_descriptor
141    //static Device_Qualifier device_qualifier_descriptor
142    static my_config config_descriptor; //, other_config_descriptor
143    static String <1> s_langs
144    static String <6> s_manufacturer
145    static String <16> s_product
146    enum State:
147        IDLE
148        TX
149        RX
150    State state
151    char configuration
152    unsigned size
153    unsigned rx_request
154    char const *ptr
155    unsigned cmd_code, cmd_arg
156    bool rebooting
157    bool vendor (Setup *s, unsigned cmd)
158    bool get_descriptor (unsigned type, unsigned idx, unsigned len)
159    bool handle_setup (Setup *s, unsigned cmd)
160    void irq_usb (unsigned cmd)
161    void irq_in (unsigned cmd)
162    void irq_out (unsigned cmd)
163    char log_buffer[1000]
164    unsigned log_buffer_size
165    unsigned log_buffer_start
166    Iris::Cap caller, caller_arg
167    bool have_caller
168    unsigned *page
169    unsigned *p
170    Iris::Page buffer_page
171    public:
172    void init ()
173    void log (unsigned c)
174    void interrupt (unsigned cmd)
175    void send (unsigned code, unsigned narg, Iris::Cap reply, Iris::Cap arg)
176
177Udc::Device Udc::device_descriptor = { sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 }
178Udc::my_config Udc::config_descriptor = {
179    (Configuration){ sizeof (Configuration), Configuration::Type, sizeof (my_config), 1, 1, 0, 0xc0, 1 },
180    (Interface){ sizeof (Interface), Interface::Type, 0, 0, 2, 0xff, 0, 0x80, 0 }, {
181        (Endpoint){ sizeof (Endpoint), Endpoint::Type, 1, BULK, max_packet_size_bulk, 0 },
182        (Endpoint){ sizeof (Endpoint), Endpoint::Type, 0x81, BULK, max_packet_size_bulk, 0 }
183    }
184 }
185Udc::String <1> Udc::s_langs = { sizeof (String <1>), String <1>::Type, { 0x0409 } }
186Udc::String <6> Udc::s_manufacturer = { sizeof (String <6>), String <6>::Type, { 's', 'h', 'e', 'v', 'e', 'k' } }
187Udc::String <16> Udc::s_product = { sizeof (String <16>), String <16>::Type, { 'I', 'r', 'i', 's', ' ', 'o', 'n', ' ', 'N', 'a', 'n', 'o', 'N', 'o', 't', 'e' } }
188
189//Udc::Device_Qualifier const Udc::device_qualifier_descriptor = { sizeof (Device_Qualifier), Device_Qualifier::Type, 0x200, 0, 0, 0, max_packet_size0, 1, 0 }
190//Udc::my_config const Udc::other_config_descriptor = {
191// (Configuration){ sizeof (Configuration), 7, sizeof (my_config), 1, 1, 0, 0xc0, 1 },
192// (Interface){ sizeof (Interface), Interface::Type, 0, 0, 2, 0xff, 0, 0x80, 0 }, {
193// (Endpoint){ sizeof (Endpoint), Endpoint::Type, 1, BULK, max_packet_size_bulk, 0 },
194// (Endpoint){ sizeof (Endpoint), Endpoint::Type, 0x81, BULK, max_packet_size_bulk, 0 }
195// }
196// }
197
198void Udc::init ():
199    // Initialize the globals. My method of compiling doesn't do that properly.
200    device_descriptor = (Device){ sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 }
201    config_descriptor = (my_config){
202        (Configuration){ sizeof (Configuration), Configuration::Type, sizeof (my_config), 1, 1, 0, 0xc0, 1 },
203        (Interface){ sizeof (Interface), Interface::Type, 0, 0, 2, 0xff, 0, 0x80, 0 }, {
204            (Endpoint){ sizeof (Endpoint), Endpoint::Type, 1, BULK, max_packet_size_bulk, 0 },
205            (Endpoint){ sizeof (Endpoint), Endpoint::Type, 0x81, BULK, max_packet_size_bulk, 0 }
206        }
207     }
208    s_langs = (String <1>){ sizeof (String <1>), String <1>::Type, { 0x0409 } }
209    s_manufacturer = (String <6>){ sizeof (String <6>), String <6>::Type, { 's', 'h', 'e', 'v', 'e', 'k' } }
210    s_product = (String <16>){ sizeof (String <16>), String <16>::Type, { 'I', 'r', 'i', 's', ' ', 'o', 'n', ' ', 'N', 'a', 'n', 'o', 'N', 'o', 't', 'e' } }
211    have_caller = false
212    log_buffer_size = 0
213    log_buffer_start = 0
214    cmd_code = ~0
215    cmd_arg = 0
216
217    // Use the space which is reserved for the framebuffer, because it will not be in use.
218    // Normally a normal new page should be allocated here, but new isn't implemented at this point.
219    page = (unsigned *)LCD_FRAMEBUFFER_BASE
220    p = page
221    buffer_page = Iris::my_memory.create_page ()
222    buffer_page.set_flags (Iris::Page::FRAME | Iris::Page::PAYING)
223    Iris::my_memory.map (buffer_page, (unsigned)page)
224
225    // Disconnect from the bus and don't try to get high-speed.
226    UDC_POWER = 0
227    UDC_TESTMODE = 0
228    UDC_INDEX = 0
229    state = IDLE
230    configuration = 0
231    size = 0
232    // exit suspend mode by reading the interrupt register.
233    cpm_start_udc ()
234    // reset all pending endpoint interrupts.
235    unsigned i = UDC_INTRUSB
236    i = UDC_INTRIN
237    i = UDC_INTROUT
238    // enable interrupt on bus reset.
239    UDC_INTRUSBE = UDC_INTR_RESET
240    // enable interrupts on endpoint 0.
241    UDC_INTRINE = 1 << 0
242    // and on out endpoint 1.
243    UDC_INTROUTE = 1 << 1
244    // Wait a while.
245    for unsigned w = 0; w < 10000; ++w:
246        Iris::schedule ()
247    // Connect to the host.
248    UDC_POWER = UDC_POWER_SOFTCONN
249
250bool Udc::vendor (Setup *s, unsigned cmd):
251    if !(s->request_type & 0x80):
252        kdebug ("data to device without size\n")
253        Iris::panic (0)
254        return true
255    if s->request == 10:
256        static unsigned b[2]
257        ptr = (char *)b
258        size = s->length < 8 ? s->length : 8
259        if cmd_code != ~0:
260            b[0] = cmd_code
261            b[1] = cmd_arg
262            if cmd_code == Iris::Directory::LOCK_RO || cmd_code == Iris::Directory::UNLOCK_RO:
263                caller.invoke ()
264                Iris::free_cap (caller)
265                Iris::free_cap (caller_arg)
266                have_caller = false
267                //kdebug ("(un)lock response\n")
268            cmd_code = ~0
269        else:
270            if log_buffer_start == log_buffer_size:
271                b[0] = ~1
272                b[1] = 0
273            else:
274                b[0] = ~0
275                b[1] = (log_buffer[log_buffer_start++] & 0xff) * 0x01010101
276            if log_buffer_start == log_buffer_size:
277                log_buffer_start = 0
278                log_buffer_size = 0
279    else:
280        static char const *name = "Reboot"
281        ptr = name
282        size = s->length < 6 ? s->length : 6
283        rebooting = true
284    state = TX
285    return true
286
287void Udc::send (unsigned code, unsigned narg, Iris::Cap reply, Iris::Cap arg):
288    if cmd_code != ~0:
289        kdebug ("new code sent while old one wasn't finished.\n")
290        Iris::panic (0)
291    cmd_code = code
292    cmd_arg = narg
293    caller = reply
294    caller_arg = arg
295    have_caller = true
296
297bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
298    switch type:
299        case Configuration::Type:
300            if idx != 0:
301                return false
302            ptr = reinterpret_cast <char const *> (&config_descriptor)
303            size = (len < sizeof (config_descriptor) ? len : sizeof (config_descriptor))
304            break
305        case Device::Type:
306            if idx != 0:
307                return false
308            ptr = reinterpret_cast <char const *> (&device_descriptor)
309            size = (len < sizeof (device_descriptor) ? len : sizeof (device_descriptor))
310            break
311        case Device_Qualifier::Type:
312            //if idx != 0:
313            // return false
314            //ptr = reinterpret_cast <char const *> (&device_qualifier_descriptor)
315            //size = (len < sizeof (device_qualifier_descriptor) ? len : sizeof (device_qualifier_descriptor))
316            //break
317            return false
318        // The 6 is an arbitrary number, except that String <6> is instantiated already.
319        case String <6>::Type:
320            switch idx:
321                case 0:
322                    ptr = reinterpret_cast <char const *> (&s_langs)
323                    size = (len < sizeof (s_langs) ? len : sizeof (s_langs))
324                    break
325                case 1:
326                    ptr = reinterpret_cast <char const *> (&s_manufacturer)
327                    size = (len < sizeof (s_manufacturer) ? len : sizeof (s_manufacturer))
328                    break
329                case 2:
330                    ptr = reinterpret_cast <char const *> (&s_product)
331                    size = (len < sizeof (s_product) ? len : sizeof (s_product))
332                    break
333                default:
334                    return false
335            break
336        default:
337            return false
338    state = TX
339    return true
340
341bool Udc::handle_setup (Setup *s, unsigned cmd):
342    switch s->request_type:
343        case STANDARD_TO_DEVICE:
344            switch s->request:
345                case SET_ADDRESS:
346                    UDC_FADDR = s->value
347                    break
348                case SET_CONFIGURATION:
349                    if s->value >= 2:
350                        return false
351                    configuration = s->value
352                    break
353                case SET_INTERFACE:
354                    if s->value != 0:
355                        return false
356                    break
357                default:
358                    return false
359            UDC_OUTMAXP = 64
360            UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
361            UDC_OUTCSR = UDC_OUTCSR_CDT | UDC_OUTCSR_FF
362            break
363        case STANDARD_FROM_DEVICE:
364            switch s->request:
365                case GET_STATUS:
366                    ptr = "\0\0"
367                    size = (s->length < 2 ? s->length : 2)
368                    state = TX
369                    break
370                case GET_DESCRIPTOR:
371                    return get_descriptor ((s->value >> 8) & 0xff, s->value & 0xff, s->length)
372                case GET_CONFIGURATION:
373                    ptr = &configuration
374                    size = (s->length < 1 ? s->length : 1)
375                    state = TX
376                    break
377                case GET_INTERFACE:
378                    ptr = "\0"
379                    size = (s->length < 1 ? s->length : 1)
380                    state = TX
381                    break
382                default:
383                    return false
384            break
385        case VENDOR_TO_DEVICE:
386        case VENDOR_FROM_DEVICE:
387            return vendor (s, cmd)
388        default:
389            return false
390    return true
391
392void Udc::irq_usb (unsigned cmd):
393    // Reset.
394    //Iris::debug ("usb reset\n")
395    state = IDLE
396
397void Udc::irq_in (unsigned cmd):
398    // Interrupt on endpoint 0.
399    unsigned csr = UDC_CSR0
400    if csr & UDC_CSR0_SENTSTALL:
401        csr &= ~(UDC_CSR0_SENTSTALL | UDC_CSR0_SENDSTALL)
402        state = IDLE
403    if csr & UDC_CSR0_SETUPEND:
404        csr |= UDC_CSR0_SVDSETUPEND
405        state = IDLE
406    switch state:
407        case IDLE:
408            if rebooting:
409                Iris::reboot ()
410            if !(csr & UDC_CSR0_OUTPKTRDY):
411                return
412            union { unsigned d[2]; Setup s; } packet
413            packet.d[0] = UDC_FIFO (0)
414            packet.d[1] = UDC_FIFO (0)
415            if !(packet.s.request_type & 0x80) && packet.s.length > 0:
416                // More data will follow; delay handling of packet.
417                state = RX
418                UDC_CSR0 = csr | UDC_CSR0_SVDOUTPKTRDY
419                rx_request = packet.s.request
420                return
421            UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
422            if !handle_setup (&packet.s, cmd):
423                csr |= UDC_CSR0_SENDSTALL
424                break
425            if size == 0:
426                return
427            // Fall through.
428        case TX:
429            unsigned i
430            for i = 0; (size & ~3) > 0 && i < max_packet_size0; i += 4, size -= 4:
431                UDC_FIFO (0) = *(unsigned *)ptr
432                ptr += 4
433            for ; size > 0 && i < max_packet_size0; ++i, --size:
434                UDC_FIFO8 (0) = *ptr++
435            if i == max_packet_size0:
436                csr |= UDC_CSR0_INPKTRDY
437            else:
438                state = IDLE
439                csr |= UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
440            break
441        case RX:
442            // The protocol that is used doesn't allow large packets, so being here always means the entire packet is received.
443            switch rx_request & 0xff:
444                case Iris::Directory::GET_SIZE & 0xff:
445                    if !have_caller:
446                        kdebug ("received dir size from server without a caller waiting\n")
447                        Iris::panic (0)
448                    unsigned size_l = UDC_FIFO (0)
449                    unsigned size_h = UDC_FIFO (0)
450                    caller.invoke (Iris::Num (size_l, size_h))
451                    Iris::free_cap (caller)
452                    Iris::free_cap (caller_arg)
453                    have_caller = false
454                    //kdebug ("get_size response\n")
455                    break
456                case Iris::Directory::GET_NAME & 0xff:
457                    if !have_caller:
458                        kdebug ("received filename from server without a caller waiting\n")
459                        Iris::panic (0)
460                    unsigned n[4]
461                    for unsigned i = 0; i < 4; ++i:
462                        n[i] = UDC_FIFO (0)
463                    caller.invoke (Iris::Num (n[0], n[1]), Iris::Num (n[2], n[3]))
464                    Iris::free_cap (caller)
465                    Iris::free_cap (caller_arg)
466                    //kdebug ("get_name response\n")
467                    have_caller = false
468                    break
469                case Iris::String::GET_SIZE & 0xff:
470                    if !have_caller:
471                        kdebug ("received string size from server without a caller waiting\n")
472                        Iris::panic (0)
473                    unsigned size_l = UDC_FIFO (0)
474                    unsigned size_h = UDC_FIFO (0)
475                    caller.invoke (Iris::Num (size_l, size_h))
476                    Iris::free_cap (caller)
477                    Iris::free_cap (caller_arg)
478                    have_caller = false
479                    //kdebug ("get_filesize response\n")
480                    break
481                case Iris::String::GET_CHARS & 0xff:
482                    if !have_caller:
483                        kdebug ("received string char data from server without a caller waiting\n")
484                        Iris::panic (0)
485                    unsigned n[4]
486                    for unsigned i = 0; i < 4; ++i:
487                        n[i] = UDC_FIFO (0)
488                    caller.invoke (Iris::Num (n[0], n[1]), Iris::Num (n[2], n[3]))
489                    Iris::free_cap (caller)
490                    Iris::free_cap (caller_arg)
491                    have_caller = false
492                    //kdebug ("get_chars response\n")
493                    break
494                default:
495                    kdebug ("invalid vendor request: ")
496                    kdebug_num (rx_request)
497                    kdebug ("\n")
498                    Iris::panic (0)
499            UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
500            state = IDLE
501            break
502    UDC_CSR0 = csr
503
504void Udc::irq_out (unsigned cmd):
505    // Interrupt on OUT endpoint 1.
506    UDC_INDEX = 1
507    if !have_caller:
508        kdebug ("received bulk data from server without a caller waiting\n")
509        Iris::panic (0)
510    unsigned size = UDC_OUTCOUNT
511    unsigned csr = UDC_OUTCSR
512    //Iris::debug ("handling bulk interrupt for %x with %d bytes.\n", csr, size)
513    csr &= ~UDC_OUTCSR_OUTPKTRDY
514    for unsigned i = 0; i < size; i += 4:
515        *p++ = UDC_FIFO (1)
516    if p - page == PAGE_SIZE >> 2:
517        buffer_page.share (caller_arg, Iris::Page::FORGET)
518        buffer_page.set_flags (Iris::Page::FRAME)
519        caller.invoke ()
520        Iris::free_cap (caller)
521        Iris::free_cap (caller_arg)
522        have_caller = false
523        //kdebug ("bulk response\n")
524        p = page
525    UDC_OUTCSR = csr
526    UDC_INDEX = 0
527
528void Udc::interrupt (unsigned cmd):
529    while true:
530        unsigned usb = UDC_INTRUSB
531        unsigned in = UDC_INTRIN
532        unsigned out = UDC_INTROUT
533        if !(usb & 4) && !(in & 1) && !(out & 2):
534            break
535        //Iris::debug ("interrupt: %d/%d/%d\n", usb, in, out)
536        if usb & 4:
537            irq_usb (cmd)
538        if in & 1:
539            irq_in (cmd)
540        if out & 2:
541            irq_out (cmd)
542
543void Udc::log (unsigned c):
544    if log_buffer_size >= sizeof (log_buffer):
545        return
546    log_buffer[log_buffer_size++] = c
547
548enum pdata:
549    LOG = 1
550    DIRECTORY
551    FILE
552    NAME
553
554Iris::Num start ():
555    map_udc ()
556    map_gpio ()
557    map_cpm ()
558    Udc udc
559
560    //Iris::Cap logcap = Iris::my_receiver.create_capability (LOG)
561    //__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1")
562    Iris::Directory dir = Iris::my_receiver.create_capability (DIRECTORY)
563    Iris::my_parent.provide_capability <Iris::Directory> (dir.copy ())
564    Iris::free_cap (dir)
565    udc.init ()
566    Iris::register_interrupt (IRQ_UDC)
567    // Don't call init_done, because this can be used as bootthread and without a parent this call will not be answered.
568    //Iris::my_parent.init_done ()
569    unsigned state = 0
570    while true:
571        Iris::wait ()
572        Iris::Cap reply = Iris::get_reply ()
573        Iris::Cap arg = Iris::get_arg ()
574        //Iris::debug ("udc event, protected: %x\n", Iris::recv.protected_data.l)
575        switch Iris::recv.protected_data.l:
576            case 0:
577                udc.interrupt (state)
578                Iris::register_interrupt (IRQ_UDC)
579                break
580            case LOG:
581                udc.log (Iris::recv.data[0].l)
582                break
583            case DIRECTORY:
584                //Iris::debug ("dir request %d\n", Iris::recv.data[0].l)
585                switch Iris::recv.data[0].l:
586                    case Iris::Directory::GET_NAME:
587                        Iris::Cap name = Iris::my_receiver.create_capability (Iris::Num (NAME, Iris::recv.data[1].l))
588                        reply.invoke (0, 0, name.copy ())
589                        Iris::free_cap (name)
590                        Iris::free_cap (reply)
591                        Iris::free_cap (arg)
592                        continue
593                    case Iris::Directory::GET_SIZE:
594                    case Iris::Directory::LOCK_RO:
595                    case Iris::Directory::UNLOCK_RO:
596                        state = Iris::recv.data[0].l
597                        if Iris::recv.data[1].h != 0:
598                            Iris::panic (0, "index out of supported range")
599                        udc.send (Iris::recv.data[0].l, Iris::recv.data[1].l, reply, arg)
600                        continue
601                    case Iris::Directory::GET_FILE_RO:
602                        if Iris::recv.data[1].h != 0:
603                            kdebug ("index out of supported range\n")
604                            Iris::panic (0)
605                        //kdebug ("sending file\n")
606                        Iris::Cap file = Iris::my_receiver.create_capability (Iris::Num (FILE, Iris::recv.data[1].l))
607                        reply.invoke (0, 0, file.copy ())
608                        Iris::free_cap (file)
609                        Iris::free_cap (reply)
610                        Iris::free_cap (arg)
611                        continue
612                    case Iris::Directory::GET_FILE_INFO:
613                    default:
614                        reply.invoke (Iris::ERR_INVALID_OPERATION)
615                        Iris::free_cap (reply)
616                        Iris::free_cap (arg)
617                        continue
618                break
619            case FILE:
620                //Iris::debug ("file request %d\n", Iris::recv.data[0].l)
621                switch Iris::recv.data[0].l:
622                    case Iris::Block::GET_BLOCK:
623                        if Iris::recv.data[0].h != PAGE_SIZE << 16:
624                            Iris::panic (0, "unsupported get_block arguments for boot usb device driver")
625                        // Fall through.
626                    case Iris::Block::GET_SIZE:
627                        udc.send (Iris::recv.data[0].l | ((Iris::recv.data[1].l >> PAGE_BITS) << 16), Iris::recv.protected_data.h, reply, arg)
628                        continue
629                    default:
630                        reply.invoke (Iris::ERR_INVALID_OPERATION)
631                        Iris::free_cap (reply)
632                        Iris::free_cap (arg)
633                        continue
634                break
635            case NAME:
636                //Iris::debug ("name request %d\n", Iris::recv.data[0].l)
637                switch Iris::recv.data[0].l:
638                    case Iris::String::GET_SIZE:
639                        reply.invoke (16)
640                        Iris::free_cap (reply)
641                        Iris::free_cap (arg)
642                        continue
643                    case Iris::String::GET_CHARS:
644                        state = Iris::recv.data[0].l
645                        udc.send (Iris::Directory::GET_NAME, Iris::recv.protected_data.h, reply, arg)
646                        continue
647                    default:
648                        reply.invoke (Iris::ERR_INVALID_OPERATION)
649                        Iris::free_cap (reply)
650                        Iris::free_cap (arg)
651                        continue
652            default:
653                kdebug ("other request:")
654                kdebug_num (Iris::recv.protected_data.l)
655                kdebug ("\n")
656                udc.log ('~')
657                char digit[] = "0123456789abcdef"
658                for unsigned i = 0; i < 8; ++i:
659                    udc.log (digit[(Iris::recv.protected_data.l >> (4 * (7 - i))) & 0xf])
660                udc.log ('\n')
661                break
662        reply.invoke ()
663        Iris::free_cap (reply)
664        Iris::free_cap (arg)
665

Archive Download this file

Branches:
master



interactive