Home | History | Annotate | Download | only in goldfish
      1 /* Copyright (C) 2011 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 #include "android/utils/panic.h"
     13 #include "android/utils/system.h"
     14 #include "hw/android/goldfish/pipe.h"
     15 #include "hw/android/goldfish/device.h"
     16 #include "hw/android/goldfish/vmem.h"
     17 #include "qemu/timer.h"
     18 
     19 #define  DEBUG 0
     20 
     21 /* Set to 1 to debug i/o register reads/writes */
     22 #define DEBUG_REGS  0
     23 
     24 #if DEBUG >= 1
     25 #  define D(...)  fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n")
     26 #else
     27 #  define D(...)  (void)0
     28 #endif
     29 
     30 #if DEBUG >= 2
     31 #  define DD(...)  fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n")
     32 #else
     33 #  define DD(...)  (void)0
     34 #endif
     35 
     36 #if DEBUG_REGS >= 1
     37 #  define DR(...)   D(__VA_ARGS__)
     38 #else
     39 #  define DR(...)   (void)0
     40 #endif
     41 
     42 #define E(...)  fprintf(stderr, "ERROR:" __VA_ARGS__), fprintf(stderr, "\n")
     43 
     44 /* Set to 1 to enable the 'zero' pipe type, useful for debugging */
     45 #define DEBUG_ZERO_PIPE  1
     46 
     47 /* Set to 1 to enable the 'pingpong' pipe type, useful for debugging */
     48 #define DEBUG_PINGPONG_PIPE 1
     49 
     50 /* Set to 1 to enable the 'throttle' pipe type, useful for debugging */
     51 #define DEBUG_THROTTLE_PIPE 1
     52 
     53 /* Maximum length of pipe service name, in characters (excluding final 0) */
     54 #define MAX_PIPE_SERVICE_NAME_SIZE  255
     55 
     56 #define GOLDFISH_PIPE_SAVE_VERSION  3
     57 
     58 // Up to Tools r22.6, the emulator saved with this version number.
     59 #define GOLDFISH_PIPE_SAVE_VERSION_LEGACY  2
     60 
     61 /***********************************************************************
     62  ***********************************************************************
     63  *****
     64  *****   P I P E   S E R V I C E   R E G I S T R A T I O N
     65  *****
     66  *****/
     67 
     68 #define MAX_PIPE_SERVICES  8
     69 typedef struct {
     70     const char*        name;
     71     void*              opaque;
     72     GoldfishPipeFuncs  funcs;
     73 } PipeService;
     74 
     75 typedef struct {
     76     int          count;
     77     PipeService  services[MAX_PIPE_SERVICES];
     78 } PipeServices;
     79 
     80 static PipeServices  _pipeServices[1];
     81 
     82 void
     83 goldfish_pipe_add_type(const char*               pipeName,
     84                        void*                     pipeOpaque,
     85                        const GoldfishPipeFuncs*  pipeFuncs )
     86 {
     87     PipeServices* list = _pipeServices;
     88     int           count = list->count;
     89 
     90     if (count >= MAX_PIPE_SERVICES) {
     91         APANIC("Too many goldfish pipe services (%d)", count);
     92     }
     93 
     94     if (strlen(pipeName) > MAX_PIPE_SERVICE_NAME_SIZE) {
     95         APANIC("Pipe service name too long: '%s'", pipeName);
     96     }
     97 
     98     list->services[count].name   = pipeName;
     99     list->services[count].opaque = pipeOpaque;
    100     list->services[count].funcs  = pipeFuncs[0];
    101 
    102     list->count++;
    103 }
    104 
    105 static const PipeService*
    106 goldfish_pipe_find_type(const char*  pipeName)
    107 {
    108     PipeServices* list = _pipeServices;
    109     int           count = list->count;
    110     int           nn;
    111 
    112     for (nn = 0; nn < count; nn++) {
    113         if (!strcmp(list->services[nn].name, pipeName)) {
    114             return &list->services[nn];
    115         }
    116     }
    117     return NULL;
    118 }
    119 
    120 
    121 /***********************************************************************
    122  ***********************************************************************
    123  *****
    124  *****    P I P E   C O N N E C T I O N S
    125  *****
    126  *****/
    127 
    128 typedef struct PipeDevice  PipeDevice;
    129 
    130 typedef struct Pipe {
    131     struct Pipe*              next;
    132     struct Pipe*              next_waked;
    133     PipeDevice*                device;
    134     uint64_t                   channel;
    135     void*                      opaque;
    136     const GoldfishPipeFuncs*   funcs;
    137     const PipeService*         service;
    138     char*                      args;
    139     unsigned char              wanted;
    140     char                       closed;
    141 } Pipe;
    142 
    143 /* Forward */
    144 static void*  pipeConnector_new(Pipe*  pipe);
    145 
    146 static Pipe*
    147 pipe_new0(PipeDevice* dev)
    148 {
    149     Pipe*  pipe;
    150     ANEW0(pipe);
    151     pipe->device = dev;
    152     return pipe;
    153 }
    154 
    155 static Pipe*
    156 pipe_new(uint64_t channel, PipeDevice* dev)
    157 {
    158     Pipe*  pipe = pipe_new0(dev);
    159     pipe->channel = channel;
    160     pipe->opaque  = pipeConnector_new(pipe);
    161     return pipe;
    162 }
    163 
    164 static Pipe**
    165 pipe_list_findp_channel( Pipe** list, uint64_t channel )
    166 {
    167     Pipe** pnode = list;
    168     for (;;) {
    169         Pipe* node = *pnode;
    170         if (node == NULL || node->channel == channel) {
    171             break;
    172         }
    173         pnode = &node->next;
    174     }
    175     return pnode;
    176 }
    177 
    178 #if 0
    179 static Pipe**
    180 pipe_list_findp_opaque( Pipe** list, void* opaque )
    181 {
    182     Pipe** pnode = list;
    183     for (;;) {
    184         Pipe* node = *pnode;
    185         if (node == NULL || node->opaque == opaque) {
    186             break;
    187         }
    188         pnode = &node->next;
    189     }
    190     return pnode;
    191 }
    192 #endif
    193 
    194 static Pipe**
    195 pipe_list_findp_waked( Pipe** list, Pipe* pipe )
    196 {
    197     Pipe** pnode = list;
    198     for (;;) {
    199         Pipe* node = *pnode;
    200         if (node == NULL || node == pipe) {
    201             break;
    202         }
    203         pnode = &node->next_waked;
    204     }
    205     return pnode;
    206 }
    207 
    208 
    209 static void
    210 pipe_list_remove_waked( Pipe** list, Pipe*  pipe )
    211 {
    212     Pipe** lookup = pipe_list_findp_waked(list, pipe);
    213     Pipe*  node   = *lookup;
    214 
    215     if (node != NULL) {
    216         (*lookup) = node->next_waked;
    217         node->next_waked = NULL;
    218     }
    219 }
    220 
    221 static void
    222 pipe_save( Pipe* pipe, QEMUFile* file )
    223 {
    224     if (pipe->service == NULL) {
    225         /* pipe->service == NULL means we're still using a PipeConnector */
    226         /* Write a zero to indicate this condition */
    227         qemu_put_byte(file, 0);
    228     } else {
    229         /* Otherwise, write a '1' then the service name */
    230         qemu_put_byte(file, 1);
    231         qemu_put_string(file, pipe->service->name);
    232     }
    233 
    234     /* Now save other common data */
    235     qemu_put_be64(file, pipe->channel);
    236     qemu_put_byte(file, (int)pipe->wanted);
    237     qemu_put_byte(file, (int)pipe->closed);
    238 
    239     /* Write 1 + args, if any, or simply 0 otherwise */
    240     if (pipe->args != NULL) {
    241         qemu_put_byte(file, 1);
    242         qemu_put_string(file, pipe->args);
    243     } else {
    244         qemu_put_byte(file, 0);
    245     }
    246 
    247     if (pipe->funcs->save) {
    248         pipe->funcs->save(pipe->opaque, file);
    249     }
    250 }
    251 
    252 static Pipe*
    253 pipe_load( PipeDevice* dev, QEMUFile* file, int version_id )
    254 {
    255     Pipe*              pipe;
    256     const PipeService* service = NULL;
    257     int   state = qemu_get_byte(file);
    258     uint64_t channel;
    259 
    260     if (state != 0) {
    261         /* Pipe is associated with a service. */
    262         char* name = qemu_get_string(file);
    263         if (name == NULL)
    264             return NULL;
    265 
    266         service = goldfish_pipe_find_type(name);
    267         if (service == NULL) {
    268             D("No QEMU pipe service named '%s'", name);
    269             AFREE(name);
    270             return NULL;
    271         }
    272     }
    273 
    274     if (version_id == GOLDFISH_PIPE_SAVE_VERSION_LEGACY) {
    275         channel = qemu_get_be32(file);
    276     } else {
    277         channel = qemu_get_be64(file);
    278     }
    279     pipe = pipe_new(channel, dev);
    280     pipe->wanted  = qemu_get_byte(file);
    281     pipe->closed  = qemu_get_byte(file);
    282     if (qemu_get_byte(file) != 0) {
    283         pipe->args = qemu_get_string(file);
    284     }
    285 
    286     pipe->service = service;
    287     if (service != NULL) {
    288         pipe->funcs = &service->funcs;
    289     }
    290 
    291     if (pipe->funcs->load) {
    292         pipe->opaque = pipe->funcs->load(pipe, service ? service->opaque : NULL, pipe->args, file);
    293         if (pipe->opaque == NULL) {
    294             AFREE(pipe);
    295             return NULL;
    296         }
    297     } else {
    298         /* Force-close the pipe on load */
    299         pipe->closed = 1;
    300     }
    301     return pipe;
    302 }
    303 
    304 static void
    305 pipe_free( Pipe* pipe )
    306 {
    307     /* Call close callback */
    308     if (pipe->funcs->close) {
    309         pipe->funcs->close(pipe->opaque);
    310     }
    311     /* Free stuff */
    312     AFREE(pipe->args);
    313     AFREE(pipe);
    314 }
    315 
    316 /***********************************************************************
    317  ***********************************************************************
    318  *****
    319  *****    P I P E   C O N N E C T O R S
    320  *****
    321  *****/
    322 
    323 /* These are used to handle the initial connection attempt, where the
    324  * client is going to write the name of the pipe service it wants to
    325  * connect to, followed by a terminating zero.
    326  */
    327 typedef struct {
    328     Pipe*  pipe;
    329     char   buffer[128];
    330     int    buffpos;
    331 } PipeConnector;
    332 
    333 static const GoldfishPipeFuncs  pipeConnector_funcs;  // forward
    334 
    335 void*
    336 pipeConnector_new(Pipe*  pipe)
    337 {
    338     PipeConnector*  pcon;
    339 
    340     ANEW0(pcon);
    341     pcon->pipe  = pipe;
    342     pipe->funcs = &pipeConnector_funcs;
    343     return pcon;
    344 }
    345 
    346 static void
    347 pipeConnector_close( void* opaque )
    348 {
    349     PipeConnector*  pcon = opaque;
    350     AFREE(pcon);
    351 }
    352 
    353 static int
    354 pipeConnector_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers )
    355 {
    356     PipeConnector* pcon = opaque;
    357     const GoldfishPipeBuffer*  buffers_limit = buffers + numBuffers;
    358     int ret = 0;
    359 
    360     DD("%s: channel=0x%llx numBuffers=%d", __FUNCTION__,
    361        (unsigned long long)pcon->pipe->channel,
    362        numBuffers);
    363 
    364     while (buffers < buffers_limit) {
    365         int  avail;
    366 
    367         DD("%s: buffer data (%3d bytes): '%.*s'", __FUNCTION__,
    368            buffers[0].size, buffers[0].size, buffers[0].data);
    369 
    370         if (buffers[0].size == 0) {
    371             buffers++;
    372             continue;
    373         }
    374 
    375         avail = sizeof(pcon->buffer) - pcon->buffpos;
    376         if (avail > buffers[0].size)
    377             avail = buffers[0].size;
    378 
    379         if (avail > 0) {
    380             memcpy(pcon->buffer + pcon->buffpos, buffers[0].data, avail);
    381             pcon->buffpos += avail;
    382             ret += avail;
    383         }
    384         buffers++;
    385     }
    386 
    387     /* Now check that our buffer contains a zero-terminated string */
    388     if (memchr(pcon->buffer, '\0', pcon->buffpos) != NULL) {
    389         /* Acceptable formats for the connection string are:
    390          *
    391          *   pipe:<name>
    392          *   pipe:<name>:<arguments>
    393          */
    394         char* pipeName;
    395         char* pipeArgs;
    396 
    397         D("%s: connector: '%s'", __FUNCTION__, pcon->buffer);
    398 
    399         if (memcmp(pcon->buffer, "pipe:", 5) != 0) {
    400             /* Nope, we don't handle these for now. */
    401             D("%s: Unknown pipe connection: '%s'", __FUNCTION__, pcon->buffer);
    402             return PIPE_ERROR_INVAL;
    403         }
    404 
    405         pipeName = pcon->buffer + 5;
    406         pipeArgs = strchr(pipeName, ':');
    407 
    408         if (pipeArgs != NULL) {
    409             *pipeArgs++ = '\0';
    410             if (!*pipeArgs)
    411                 pipeArgs = NULL;
    412         }
    413 
    414         Pipe* pipe = pcon->pipe;
    415         const PipeService* svc = goldfish_pipe_find_type(pipeName);
    416         if (svc == NULL) {
    417             D("%s: Unknown server!", __FUNCTION__);
    418             return PIPE_ERROR_INVAL;
    419         }
    420 
    421         void*  peer = svc->funcs.init(pipe, svc->opaque, pipeArgs);
    422         if (peer == NULL) {
    423             D("%s: Initialization failed!", __FUNCTION__);
    424             return PIPE_ERROR_INVAL;
    425         }
    426 
    427         /* Do the evil switch now */
    428         pipe->opaque = peer;
    429         pipe->service = svc;
    430         pipe->funcs  = &svc->funcs;
    431         pipe->args   = ASTRDUP(pipeArgs);
    432         AFREE(pcon);
    433     }
    434 
    435     return ret;
    436 }
    437 
    438 static int
    439 pipeConnector_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers )
    440 {
    441     return PIPE_ERROR_IO;
    442 }
    443 
    444 static unsigned
    445 pipeConnector_poll( void* opaque )
    446 {
    447     return PIPE_POLL_OUT;
    448 }
    449 
    450 static void
    451 pipeConnector_wakeOn( void* opaque, int flags )
    452 {
    453     /* nothing, really should never happen */
    454 }
    455 
    456 static void
    457 pipeConnector_save( void* pipe, QEMUFile* file )
    458 {
    459     PipeConnector*  pcon = pipe;
    460     qemu_put_sbe32(file, pcon->buffpos);
    461     qemu_put_sbuffer(file, (const int8_t*)pcon->buffer, pcon->buffpos);
    462 }
    463 
    464 static void*
    465 pipeConnector_load( void* hwpipe, void* pipeOpaque, const char* args, QEMUFile* file )
    466 {
    467     PipeConnector*  pcon;
    468 
    469     int len = qemu_get_sbe32(file);
    470     if (len < 0 || len > sizeof(pcon->buffer)) {
    471         return NULL;
    472     }
    473     pcon = pipeConnector_new(hwpipe);
    474     pcon->buffpos = len;
    475     if (qemu_get_buffer(file, (uint8_t*)pcon->buffer, pcon->buffpos) != pcon->buffpos) {
    476         AFREE(pcon);
    477         return NULL;
    478     }
    479     return pcon;
    480 }
    481 
    482 static const GoldfishPipeFuncs  pipeConnector_funcs = {
    483     NULL,  /* init */
    484     pipeConnector_close,        /* should rarely happen */
    485     pipeConnector_sendBuffers,  /* the interesting stuff */
    486     pipeConnector_recvBuffers,  /* should not happen */
    487     pipeConnector_poll,         /* should not happen */
    488     pipeConnector_wakeOn,       /* should not happen */
    489     pipeConnector_save,
    490     pipeConnector_load,
    491 };
    492 
    493 /***********************************************************************
    494  ***********************************************************************
    495  *****
    496  *****    Z E R O   P I P E S
    497  *****
    498  *****/
    499 
    500 /* A simple pipe service that mimics /dev/zero, you can write anything to
    501  * it, and you can always read any number of zeros from it. Useful for debugging
    502  * the kernel driver.
    503  */
    504 #if DEBUG_ZERO_PIPE
    505 
    506 typedef struct {
    507     void* hwpipe;
    508 } ZeroPipe;
    509 
    510 static void*
    511 zeroPipe_init( void* hwpipe, void* svcOpaque, const char* args )
    512 {
    513     ZeroPipe*  zpipe;
    514 
    515     D("%s: hwpipe=%p", __FUNCTION__, hwpipe);
    516     ANEW0(zpipe);
    517     zpipe->hwpipe = hwpipe;
    518     return zpipe;
    519 }
    520 
    521 static void
    522 zeroPipe_close( void* opaque )
    523 {
    524     ZeroPipe*  zpipe = opaque;
    525 
    526     D("%s: hwpipe=%p", __FUNCTION__, zpipe->hwpipe);
    527     AFREE(zpipe);
    528 }
    529 
    530 static int
    531 zeroPipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers )
    532 {
    533     int  ret = 0;
    534     while (numBuffers > 0) {
    535         ret += buffers[0].size;
    536         buffers++;
    537         numBuffers--;
    538     }
    539     return ret;
    540 }
    541 
    542 static int
    543 zeroPipe_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers )
    544 {
    545     int  ret = 0;
    546     while (numBuffers > 0) {
    547         ret += buffers[0].size;
    548         memset(buffers[0].data, 0, buffers[0].size);
    549         buffers++;
    550         numBuffers--;
    551     }
    552     return ret;
    553 }
    554 
    555 static unsigned
    556 zeroPipe_poll( void* opaque )
    557 {
    558     return PIPE_POLL_IN | PIPE_POLL_OUT;
    559 }
    560 
    561 static void
    562 zeroPipe_wakeOn( void* opaque, int flags )
    563 {
    564     /* nothing to do here */
    565 }
    566 
    567 static const GoldfishPipeFuncs  zeroPipe_funcs = {
    568     zeroPipe_init,
    569     zeroPipe_close,
    570     zeroPipe_sendBuffers,
    571     zeroPipe_recvBuffers,
    572     zeroPipe_poll,
    573     zeroPipe_wakeOn,
    574 };
    575 
    576 #endif /* DEBUG_ZERO */
    577 
    578 /***********************************************************************
    579  ***********************************************************************
    580  *****
    581  *****    P I N G   P O N G   P I P E S
    582  *****
    583  *****/
    584 
    585 /* Similar debug service that sends back anything it receives */
    586 /* All data is kept in a circular dynamic buffer */
    587 
    588 #if DEBUG_PINGPONG_PIPE
    589 
    590 /* Initial buffer size */
    591 #define PINGPONG_SIZE  1024
    592 
    593 typedef struct {
    594     void*     hwpipe;
    595     uint8_t*  buffer;
    596     size_t    size;
    597     size_t    pos;
    598     size_t    count;
    599     unsigned  flags;
    600 } PingPongPipe;
    601 
    602 static void
    603 pingPongPipe_init0( PingPongPipe* pipe, void* hwpipe, void* svcOpaque )
    604 {
    605     pipe->hwpipe = hwpipe;
    606     pipe->size = PINGPONG_SIZE;
    607     pipe->buffer = malloc(pipe->size);
    608     pipe->pos = 0;
    609     pipe->count = 0;
    610 }
    611 
    612 static void*
    613 pingPongPipe_init( void* hwpipe, void* svcOpaque, const char* args )
    614 {
    615     PingPongPipe*  ppipe;
    616 
    617     D("%s: hwpipe=%p", __FUNCTION__, hwpipe);
    618     ANEW0(ppipe);
    619     pingPongPipe_init0(ppipe, hwpipe, svcOpaque);
    620     return ppipe;
    621 }
    622 
    623 static void
    624 pingPongPipe_close( void* opaque )
    625 {
    626     PingPongPipe*  ppipe = opaque;
    627 
    628     D("%s: hwpipe=%p (pos=%d count=%d size=%d)", __FUNCTION__,
    629       ppipe->hwpipe, ppipe->pos, ppipe->count, ppipe->size);
    630     free(ppipe->buffer);
    631     AFREE(ppipe);
    632 }
    633 
    634 static int
    635 pingPongPipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers )
    636 {
    637     PingPongPipe*  pipe = opaque;
    638     int  ret = 0;
    639     int  count;
    640     const GoldfishPipeBuffer* buff = buffers;
    641     const GoldfishPipeBuffer* buffEnd = buff + numBuffers;
    642 
    643     count = 0;
    644     for ( ; buff < buffEnd; buff++ )
    645         count += buff->size;
    646 
    647     /* Do we need to grow the pingpong buffer? */
    648     while (count > pipe->size - pipe->count) {
    649         size_t    newsize = pipe->size*2;
    650         uint8_t*  newbuff = realloc(pipe->buffer, newsize);
    651         int       wpos    = pipe->pos + pipe->count;
    652         if (newbuff == NULL) {
    653             break;
    654         }
    655         if (wpos > pipe->size) {
    656             wpos -= pipe->size;
    657             memcpy(newbuff + pipe->size, newbuff, wpos);
    658         }
    659         pipe->buffer = newbuff;
    660         pipe->size   = newsize;
    661         D("pingpong buffer is now %d bytes", newsize);
    662     }
    663 
    664     for ( buff = buffers; buff < buffEnd; buff++ ) {
    665         int avail = pipe->size - pipe->count;
    666         if (avail <= 0) {
    667             if (ret == 0)
    668                 ret = PIPE_ERROR_AGAIN;
    669             break;
    670         }
    671         if (avail > buff->size) {
    672             avail = buff->size;
    673         }
    674 
    675         int wpos = pipe->pos + pipe->count;
    676         if (wpos >= pipe->size) {
    677             wpos -= pipe->size;
    678         }
    679         if (wpos + avail <= pipe->size) {
    680             memcpy(pipe->buffer + wpos, buff->data, avail);
    681         } else {
    682             int  avail2 = pipe->size - wpos;
    683             memcpy(pipe->buffer + wpos, buff->data, avail2);
    684             memcpy(pipe->buffer, buff->data + avail2, avail - avail2);
    685         }
    686         pipe->count += avail;
    687         ret += avail;
    688     }
    689 
    690     /* Wake up any waiting readers if we wrote something */
    691     if (pipe->count > 0 && (pipe->flags & PIPE_WAKE_READ)) {
    692         goldfish_pipe_wake(pipe->hwpipe, PIPE_WAKE_READ);
    693     }
    694 
    695     return ret;
    696 }
    697 
    698 static int
    699 pingPongPipe_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers )
    700 {
    701     PingPongPipe*  pipe = opaque;
    702     int  ret = 0;
    703 
    704     while (numBuffers > 0) {
    705         int avail = pipe->count;
    706         if (avail <= 0) {
    707             if (ret == 0)
    708                 ret = PIPE_ERROR_AGAIN;
    709             break;
    710         }
    711         if (avail > buffers[0].size) {
    712             avail = buffers[0].size;
    713         }
    714 
    715         int rpos = pipe->pos;
    716 
    717         if (rpos + avail <= pipe->size) {
    718             memcpy(buffers[0].data, pipe->buffer + rpos, avail);
    719         } else {
    720             int  avail2 = pipe->size - rpos;
    721             memcpy(buffers[0].data, pipe->buffer + rpos, avail2);
    722             memcpy(buffers[0].data + avail2, pipe->buffer, avail - avail2);
    723         }
    724         pipe->count -= avail;
    725         pipe->pos   += avail;
    726         if (pipe->pos >= pipe->size) {
    727             pipe->pos -= pipe->size;
    728         }
    729         ret += avail;
    730         numBuffers--;
    731         buffers++;
    732     }
    733 
    734     /* Wake up any waiting readers if we wrote something */
    735     if (pipe->count < PINGPONG_SIZE && (pipe->flags & PIPE_WAKE_WRITE)) {
    736         goldfish_pipe_wake(pipe->hwpipe, PIPE_WAKE_WRITE);
    737     }
    738 
    739     return ret;
    740 }
    741 
    742 static unsigned
    743 pingPongPipe_poll( void* opaque )
    744 {
    745     PingPongPipe*  pipe = opaque;
    746     unsigned       ret = 0;
    747 
    748     if (pipe->count < pipe->size)
    749         ret |= PIPE_POLL_OUT;
    750 
    751     if (pipe->count > 0)
    752         ret |= PIPE_POLL_IN;
    753 
    754     return ret;
    755 }
    756 
    757 static void
    758 pingPongPipe_wakeOn( void* opaque, int flags )
    759 {
    760     PingPongPipe* pipe = opaque;
    761     pipe->flags |= (unsigned)flags;
    762 }
    763 
    764 static const GoldfishPipeFuncs  pingPongPipe_funcs = {
    765     pingPongPipe_init,
    766     pingPongPipe_close,
    767     pingPongPipe_sendBuffers,
    768     pingPongPipe_recvBuffers,
    769     pingPongPipe_poll,
    770     pingPongPipe_wakeOn,
    771 };
    772 
    773 #endif /* DEBUG_PINGPONG_PIPE */
    774 
    775 /***********************************************************************
    776  ***********************************************************************
    777  *****
    778  *****    T H R O T T L E   P I P E S
    779  *****
    780  *****/
    781 
    782 /* Similar to PingPongPipe, but will throttle the bandwidth to test
    783  * blocking I/O.
    784  */
    785 
    786 #ifdef DEBUG_THROTTLE_PIPE
    787 
    788 typedef struct {
    789     PingPongPipe  pingpong;
    790     double        sendRate;
    791     int64_t       sendExpiration;
    792     double        recvRate;
    793     int64_t       recvExpiration;
    794     QEMUTimer*    timer;
    795 } ThrottlePipe;
    796 
    797 /* forward declaration */
    798 static void throttlePipe_timerFunc( void* opaque );
    799 
    800 static void*
    801 throttlePipe_init( void* hwpipe, void* svcOpaque, const char* args )
    802 {
    803     ThrottlePipe* pipe;
    804 
    805     ANEW0(pipe);
    806     pingPongPipe_init0(&pipe->pingpong, hwpipe, svcOpaque);
    807     pipe->timer = timer_new(QEMU_CLOCK_VIRTUAL, SCALE_NS, throttlePipe_timerFunc, pipe);
    808     /* For now, limit to 500 KB/s in both directions */
    809     pipe->sendRate = 1e9 / (500*1024*8);
    810     pipe->recvRate = pipe->sendRate;
    811     return pipe;
    812 }
    813 
    814 static void
    815 throttlePipe_close( void* opaque )
    816 {
    817     ThrottlePipe* pipe = opaque;
    818 
    819     timer_del(pipe->timer);
    820     timer_free(pipe->timer);
    821     pingPongPipe_close(&pipe->pingpong);
    822 }
    823 
    824 static void
    825 throttlePipe_rearm( ThrottlePipe* pipe )
    826 {
    827     int64_t  minExpiration = 0;
    828 
    829     DD("%s: sendExpiration=%lld recvExpiration=%lld\n", __FUNCTION__, pipe->sendExpiration, pipe->recvExpiration);
    830 
    831     if (pipe->sendExpiration) {
    832         if (minExpiration == 0 || pipe->sendExpiration < minExpiration)
    833             minExpiration = pipe->sendExpiration;
    834     }
    835 
    836     if (pipe->recvExpiration) {
    837         if (minExpiration == 0 || pipe->recvExpiration < minExpiration)
    838             minExpiration = pipe->recvExpiration;
    839     }
    840 
    841     if (minExpiration != 0) {
    842         DD("%s: Arming for %lld\n", __FUNCTION__, minExpiration);
    843         timer_mod(pipe->timer, minExpiration);
    844     }
    845 }
    846 
    847 static void
    848 throttlePipe_timerFunc( void* opaque )
    849 {
    850     ThrottlePipe* pipe = opaque;
    851     int64_t  now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    852 
    853     DD("%s: TICK! now=%lld sendExpiration=%lld recvExpiration=%lld\n",
    854        __FUNCTION__, now, pipe->sendExpiration, pipe->recvExpiration);
    855 
    856     /* Timer has expired, signal wake up if needed */
    857     int      flags = 0;
    858 
    859     if (pipe->sendExpiration && now > pipe->sendExpiration) {
    860         flags |= PIPE_WAKE_WRITE;
    861         pipe->sendExpiration = 0;
    862     }
    863     if (pipe->recvExpiration && now > pipe->recvExpiration) {
    864         flags |= PIPE_WAKE_READ;
    865         pipe->recvExpiration = 0;
    866     }
    867     flags &= pipe->pingpong.flags;
    868     if (flags != 0) {
    869         DD("%s: WAKE %d\n", __FUNCTION__, flags);
    870         goldfish_pipe_wake(pipe->pingpong.hwpipe, flags);
    871     }
    872 
    873     throttlePipe_rearm(pipe);
    874 }
    875 
    876 static int
    877 throttlePipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers )
    878 {
    879     ThrottlePipe*  pipe = opaque;
    880     int            ret;
    881 
    882     if (pipe->sendExpiration > 0) {
    883         return PIPE_ERROR_AGAIN;
    884     }
    885 
    886     ret = pingPongPipe_sendBuffers(&pipe->pingpong, buffers, numBuffers);
    887     if (ret > 0) {
    888         /* Compute next send expiration time */
    889         pipe->sendExpiration = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ret*pipe->sendRate;
    890         throttlePipe_rearm(pipe);
    891     }
    892     return ret;
    893 }
    894 
    895 static int
    896 throttlePipe_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers )
    897 {
    898     ThrottlePipe* pipe = opaque;
    899     int           ret;
    900 
    901     if (pipe->recvExpiration > 0) {
    902         return PIPE_ERROR_AGAIN;
    903     }
    904 
    905     ret = pingPongPipe_recvBuffers(&pipe->pingpong, buffers, numBuffers);
    906     if (ret > 0) {
    907         pipe->recvExpiration = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ret*pipe->recvRate;
    908         throttlePipe_rearm(pipe);
    909     }
    910     return ret;
    911 }
    912 
    913 static unsigned
    914 throttlePipe_poll( void* opaque )
    915 {
    916     ThrottlePipe*  pipe = opaque;
    917     unsigned       ret  = pingPongPipe_poll(&pipe->pingpong);
    918 
    919     if (pipe->sendExpiration > 0)
    920         ret &= ~PIPE_POLL_OUT;
    921 
    922     if (pipe->recvExpiration > 0)
    923         ret &= ~PIPE_POLL_IN;
    924 
    925     return ret;
    926 }
    927 
    928 static void
    929 throttlePipe_wakeOn( void* opaque, int flags )
    930 {
    931     ThrottlePipe* pipe = opaque;
    932     pingPongPipe_wakeOn(&pipe->pingpong, flags);
    933 }
    934 
    935 static const GoldfishPipeFuncs  throttlePipe_funcs = {
    936     throttlePipe_init,
    937     throttlePipe_close,
    938     throttlePipe_sendBuffers,
    939     throttlePipe_recvBuffers,
    940     throttlePipe_poll,
    941     throttlePipe_wakeOn,
    942 };
    943 
    944 #endif /* DEBUG_THROTTLE_PIPE */
    945 
    946 /***********************************************************************
    947  ***********************************************************************
    948  *****
    949  *****    G O L D F I S H   P I P E   D E V I C E
    950  *****
    951  *****/
    952 
    953 struct PipeDevice {
    954     struct goldfish_device dev;
    955 
    956     /* the list of all pipes */
    957     Pipe*  pipes;
    958 
    959     /* the list of signalled pipes */
    960     Pipe*  signaled_pipes;
    961 
    962     /* i/o registers */
    963     uint64_t  address;
    964     uint32_t  size;
    965     uint32_t  status;
    966     uint64_t  channel;
    967     uint32_t  wakes;
    968     uint64_t  params_addr;
    969 };
    970 
    971 static void
    972 pipeDevice_doCommand( PipeDevice* dev, uint32_t command )
    973 {
    974     Pipe** lookup = pipe_list_findp_channel(&dev->pipes, dev->channel);
    975     Pipe*  pipe   = *lookup;
    976     CPUOldState* env = cpu_single_env;
    977 
    978     /* Check that we're referring a known pipe channel */
    979     if (command != PIPE_CMD_OPEN && pipe == NULL) {
    980         dev->status = PIPE_ERROR_INVAL;
    981         return;
    982     }
    983 
    984     /* If the pipe is closed by the host, return an error */
    985     if (pipe != NULL && pipe->closed && command != PIPE_CMD_CLOSE) {
    986         dev->status = PIPE_ERROR_IO;
    987         return;
    988     }
    989 
    990     switch (command) {
    991     case PIPE_CMD_OPEN:
    992         DD("%s: CMD_OPEN channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel);
    993         if (pipe != NULL) {
    994             dev->status = PIPE_ERROR_INVAL;
    995             break;
    996         }
    997         pipe = pipe_new(dev->channel, dev);
    998         pipe->next = dev->pipes;
    999         dev->pipes = pipe;
   1000         dev->status = 0;
   1001         break;
   1002 
   1003     case PIPE_CMD_CLOSE:
   1004         DD("%s: CMD_CLOSE channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel);
   1005         /* Remove from device's lists */
   1006         *lookup = pipe->next;
   1007         pipe->next = NULL;
   1008         pipe_list_remove_waked(&dev->signaled_pipes, pipe);
   1009         pipe_free(pipe);
   1010         break;
   1011 
   1012     case PIPE_CMD_POLL:
   1013         dev->status = pipe->funcs->poll(pipe->opaque);
   1014         DD("%s: CMD_POLL > status=%d", __FUNCTION__, dev->status);
   1015         break;
   1016 
   1017     case PIPE_CMD_READ_BUFFER: {
   1018         /* Translate virtual address into physical one, into emulator memory. */
   1019         GoldfishPipeBuffer  buffer;
   1020         target_ulong        address = dev->address;
   1021         target_ulong        page    = address & TARGET_PAGE_MASK;
   1022         hwaddr  phys;
   1023         phys = safe_get_phys_page_debug(ENV_GET_CPU(env), page);
   1024 #ifdef TARGET_X86_64
   1025         phys = phys & TARGET_PTE_MASK;
   1026 #endif
   1027         buffer.data = qemu_get_ram_ptr(phys) + (address - page);
   1028         buffer.size = dev->size;
   1029         dev->status = pipe->funcs->recvBuffers(pipe->opaque, &buffer, 1);
   1030         DD("%s: CMD_READ_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d",
   1031            __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address,
   1032            dev->size, dev->status);
   1033         break;
   1034     }
   1035 
   1036     case PIPE_CMD_WRITE_BUFFER: {
   1037         /* Translate virtual address into physical one, into emulator memory. */
   1038         GoldfishPipeBuffer  buffer;
   1039         target_ulong        address = dev->address;
   1040         target_ulong        page    = address & TARGET_PAGE_MASK;
   1041         hwaddr  phys;
   1042         phys = safe_get_phys_page_debug(ENV_GET_CPU(env), page);
   1043 #ifdef TARGET_X86_64
   1044         phys = phys & TARGET_PTE_MASK;
   1045 #endif
   1046         buffer.data = qemu_get_ram_ptr(phys) + (address - page);
   1047         buffer.size = dev->size;
   1048         dev->status = pipe->funcs->sendBuffers(pipe->opaque, &buffer, 1);
   1049         DD("%s: CMD_WRITE_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d",
   1050            __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address,
   1051            dev->size, dev->status);
   1052         break;
   1053     }
   1054 
   1055     case PIPE_CMD_WAKE_ON_READ:
   1056         DD("%s: CMD_WAKE_ON_READ channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel);
   1057         if ((pipe->wanted & PIPE_WAKE_READ) == 0) {
   1058             pipe->wanted |= PIPE_WAKE_READ;
   1059             pipe->funcs->wakeOn(pipe->opaque, pipe->wanted);
   1060         }
   1061         dev->status = 0;
   1062         break;
   1063 
   1064     case PIPE_CMD_WAKE_ON_WRITE:
   1065         DD("%s: CMD_WAKE_ON_WRITE channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel);
   1066         if ((pipe->wanted & PIPE_WAKE_WRITE) == 0) {
   1067             pipe->wanted |= PIPE_WAKE_WRITE;
   1068             pipe->funcs->wakeOn(pipe->opaque, pipe->wanted);
   1069         }
   1070         dev->status = 0;
   1071         break;
   1072 
   1073     default:
   1074         D("%s: command=%d (0x%x)\n", __FUNCTION__, command, command);
   1075     }
   1076 }
   1077 
   1078 static void pipe_dev_write(void *opaque, hwaddr offset, uint32_t value)
   1079 {
   1080     PipeDevice *s = (PipeDevice *)opaque;
   1081 
   1082     switch (offset) {
   1083     case PIPE_REG_COMMAND:
   1084         DR("%s: command=%d (0x%x)", __FUNCTION__, value, value);
   1085         pipeDevice_doCommand(s, value);
   1086         break;
   1087 
   1088     case PIPE_REG_SIZE:
   1089         DR("%s: size=%d (0x%x)", __FUNCTION__, value, value);
   1090         s->size = value;
   1091         break;
   1092 
   1093     case PIPE_REG_ADDRESS:
   1094         DR("%s: address=%d (0x%x)", __FUNCTION__, value, value);
   1095         uint64_set_low(&s->address, value);
   1096         break;
   1097 
   1098     case PIPE_REG_ADDRESS_HIGH:
   1099         DR("%s: address_high=%d (0x%x)", __FUNCTION__, value, value);
   1100         uint64_set_high(&s->address, value);
   1101         break;
   1102 
   1103     case PIPE_REG_CHANNEL:
   1104         DR("%s: channel=%d (0x%x)", __FUNCTION__, value, value);
   1105         uint64_set_low(&s->channel, value);
   1106         break;
   1107 
   1108     case PIPE_REG_CHANNEL_HIGH:
   1109         DR("%s: channel_high=%d (0x%x)", __FUNCTION__, value, value);
   1110         uint64_set_high(&s->channel, value);
   1111         break;
   1112 
   1113     case PIPE_REG_PARAMS_ADDR_HIGH:
   1114         s->params_addr = (s->params_addr & ~(0xFFFFFFFFULL << 32) ) |
   1115                           ((uint64_t)value << 32);
   1116         break;
   1117 
   1118     case PIPE_REG_PARAMS_ADDR_LOW:
   1119         s->params_addr = (s->params_addr & ~(0xFFFFFFFFULL) ) | value;
   1120         break;
   1121 
   1122     case PIPE_REG_ACCESS_PARAMS:
   1123     {
   1124         struct access_params aps;
   1125         struct access_params_64 aps64;
   1126         uint32_t cmd;
   1127 
   1128         /* Don't touch aps.result if anything wrong */
   1129         if (s->params_addr == 0)
   1130             break;
   1131 
   1132         if (goldfish_guest_is_64bit()) {
   1133             cpu_physical_memory_read(s->params_addr, (void*)&aps64,
   1134                                      sizeof(aps64));
   1135         } else {
   1136             cpu_physical_memory_read(s->params_addr, (void*)&aps,
   1137                                      sizeof(aps));
   1138         }
   1139         /* sync pipe device state from batch buffer */
   1140         if (goldfish_guest_is_64bit()) {
   1141             s->channel = aps64.channel;
   1142             s->size = aps64.size;
   1143             s->address = aps64.address;
   1144             cmd = aps64.cmd;
   1145         } else {
   1146             s->channel = aps.channel;
   1147             s->size = aps.size;
   1148             s->address = aps.address;
   1149             cmd = aps.cmd;
   1150         }
   1151         if ((cmd != PIPE_CMD_READ_BUFFER) && (cmd != PIPE_CMD_WRITE_BUFFER))
   1152             break;
   1153 
   1154         pipeDevice_doCommand(s, cmd);
   1155         if (goldfish_guest_is_64bit()) {
   1156             aps64.result = s->status;
   1157             cpu_physical_memory_write(s->params_addr, (void*)&aps64,
   1158                                       sizeof(aps64));
   1159         } else {
   1160             aps.result = s->status;
   1161             cpu_physical_memory_write(s->params_addr, (void*)&aps,
   1162                                       sizeof(aps));
   1163         }
   1164     }
   1165     break;
   1166 
   1167     default:
   1168         D("%s: offset=%d (0x%x) value=%d (0x%x)\n", __FUNCTION__, offset,
   1169             offset, value, value);
   1170         break;
   1171     }
   1172 }
   1173 
   1174 /* I/O read */
   1175 static uint32_t pipe_dev_read(void *opaque, hwaddr offset)
   1176 {
   1177     PipeDevice *dev = (PipeDevice *)opaque;
   1178 
   1179     switch (offset) {
   1180     case PIPE_REG_STATUS:
   1181         DR("%s: REG_STATUS status=%d (0x%x)", __FUNCTION__, dev->status, dev->status);
   1182         return dev->status;
   1183 
   1184     case PIPE_REG_CHANNEL:
   1185         if (dev->signaled_pipes != NULL) {
   1186             Pipe* pipe = dev->signaled_pipes;
   1187             DR("%s: channel=0x%llx wanted=%d", __FUNCTION__,
   1188                (unsigned long long)pipe->channel, pipe->wanted);
   1189             dev->wakes = pipe->wanted;
   1190             pipe->wanted = 0;
   1191             dev->signaled_pipes = pipe->next_waked;
   1192             pipe->next_waked = NULL;
   1193             if (dev->signaled_pipes == NULL) {
   1194                 goldfish_device_set_irq(&dev->dev, 0, 0);
   1195                 DD("%s: lowering IRQ", __FUNCTION__);
   1196             }
   1197             return (uint32_t)(pipe->channel & 0xFFFFFFFFUL);
   1198         }
   1199         DR("%s: no signaled channels", __FUNCTION__);
   1200         return 0;
   1201 
   1202     case PIPE_REG_CHANNEL_HIGH:
   1203         if (dev->signaled_pipes != NULL) {
   1204             Pipe* pipe = dev->signaled_pipes;
   1205             DR("%s: channel_high=0x%llx wanted=%d", __FUNCTION__,
   1206                (unsigned long long)pipe->channel, pipe->wanted);
   1207             return (uint32_t)(pipe->channel >> 32);
   1208         }
   1209         DR("%s: no signaled channels", __FUNCTION__);
   1210         return 0;
   1211 
   1212     case PIPE_REG_WAKES:
   1213         DR("%s: wakes %d", __FUNCTION__, dev->wakes);
   1214         return dev->wakes;
   1215 
   1216     case PIPE_REG_PARAMS_ADDR_HIGH:
   1217         return (uint32_t)(dev->params_addr >> 32);
   1218 
   1219     case PIPE_REG_PARAMS_ADDR_LOW:
   1220         return (uint32_t)(dev->params_addr & 0xFFFFFFFFUL);
   1221 
   1222     default:
   1223         D("%s: offset=%d (0x%x)\n", __FUNCTION__, offset, offset);
   1224     }
   1225     return 0;
   1226 }
   1227 
   1228 static CPUReadMemoryFunc *pipe_dev_readfn[] = {
   1229    pipe_dev_read,
   1230    pipe_dev_read,
   1231    pipe_dev_read
   1232 };
   1233 
   1234 static CPUWriteMemoryFunc *pipe_dev_writefn[] = {
   1235    pipe_dev_write,
   1236    pipe_dev_write,
   1237    pipe_dev_write
   1238 };
   1239 
   1240 static void
   1241 goldfish_pipe_save( QEMUFile* file, void* opaque )
   1242 {
   1243     PipeDevice* dev = opaque;
   1244     Pipe* pipe;
   1245 
   1246     qemu_put_be64(file, dev->address);
   1247     qemu_put_be32(file, dev->size);
   1248     qemu_put_be32(file, dev->status);
   1249     qemu_put_be64(file, dev->channel);
   1250     qemu_put_be32(file, dev->wakes);
   1251     qemu_put_be64(file, dev->params_addr);
   1252 
   1253     /* Count the number of pipe connections */
   1254     int count = 0;
   1255     for ( pipe = dev->pipes; pipe; pipe = pipe->next )
   1256         count++;
   1257 
   1258     qemu_put_sbe32(file, count);
   1259 
   1260     /* Now save each pipe one after the other */
   1261     for ( pipe = dev->pipes; pipe; pipe = pipe->next ) {
   1262         pipe_save(pipe, file);
   1263     }
   1264 }
   1265 
   1266 static int
   1267 goldfish_pipe_load( QEMUFile* file, void* opaque, int version_id )
   1268 {
   1269     PipeDevice* dev = opaque;
   1270     Pipe*       pipe;
   1271 
   1272     if ((version_id != GOLDFISH_PIPE_SAVE_VERSION) &&
   1273         (version_id != GOLDFISH_PIPE_SAVE_VERSION_LEGACY)) {
   1274         return -EINVAL;
   1275     }
   1276     if (version_id == GOLDFISH_PIPE_SAVE_VERSION_LEGACY) {
   1277         dev->address = (uint64_t)qemu_get_be32(file);
   1278     } else {
   1279         dev->address = qemu_get_be64(file);
   1280     }
   1281     dev->size    = qemu_get_be32(file);
   1282     dev->status  = qemu_get_be32(file);
   1283     if (version_id == GOLDFISH_PIPE_SAVE_VERSION_LEGACY) {
   1284         dev->channel = (uint64_t)qemu_get_be32(file);
   1285     } else {
   1286         dev->channel = qemu_get_be64(file);
   1287     }
   1288     dev->wakes   = qemu_get_be32(file);
   1289     dev->params_addr   = qemu_get_be64(file);
   1290 
   1291     /* Count the number of pipe connections */
   1292     int count = qemu_get_sbe32(file);
   1293 
   1294     /* Load all pipe connections */
   1295     for ( ; count > 0; count-- ) {
   1296         pipe = pipe_load(dev, file, version_id);
   1297         if (pipe == NULL) {
   1298             return -EIO;
   1299         }
   1300         pipe->next = dev->pipes;
   1301         dev->pipes = pipe;
   1302     }
   1303 
   1304     /* Now we need to wake/close all relevant pipes */
   1305     for ( pipe = dev->pipes; pipe; pipe = pipe->next ) {
   1306         if (pipe->wanted != 0)
   1307             goldfish_pipe_wake(pipe, pipe->wanted);
   1308         if (pipe->closed != 0)
   1309             goldfish_pipe_close(pipe);
   1310     }
   1311     return 0;
   1312 }
   1313 
   1314 /* initialize the trace device */
   1315 void pipe_dev_init(bool newDeviceNaming)
   1316 {
   1317     PipeDevice *s;
   1318 
   1319     s = (PipeDevice *) g_malloc0(sizeof(*s));
   1320 
   1321     s->dev.name = newDeviceNaming ? "goldfish_pipe" : "qemu_pipe";
   1322     s->dev.id = -1;
   1323     s->dev.base = 0;       // will be allocated dynamically
   1324     s->dev.size = 0x2000;
   1325     s->dev.irq = 0;
   1326     s->dev.irq_count = 1;
   1327 
   1328     goldfish_device_add(&s->dev, pipe_dev_readfn, pipe_dev_writefn, s);
   1329 
   1330     register_savevm(NULL,
   1331                     "goldfish_pipe",
   1332                     0,
   1333                     GOLDFISH_PIPE_SAVE_VERSION,
   1334                     goldfish_pipe_save,
   1335                     goldfish_pipe_load,
   1336                     s);
   1337 
   1338 #if DEBUG_ZERO_PIPE
   1339     goldfish_pipe_add_type("zero", NULL, &zeroPipe_funcs);
   1340 #endif
   1341 #if DEBUG_PINGPONG_PIPE
   1342     goldfish_pipe_add_type("pingpong", NULL, &pingPongPipe_funcs);
   1343 #endif
   1344 #if DEBUG_THROTTLE_PIPE
   1345     goldfish_pipe_add_type("throttle", NULL, &throttlePipe_funcs);
   1346 #endif
   1347 }
   1348 
   1349 void
   1350 goldfish_pipe_wake( void* hwpipe, unsigned flags )
   1351 {
   1352     Pipe*  pipe = hwpipe;
   1353     Pipe** lookup;
   1354     PipeDevice*  dev = pipe->device;
   1355 
   1356     DD("%s: channel=0x%llx flags=%d", __FUNCTION__, (unsigned long long)pipe->channel, flags);
   1357 
   1358     /* If not already there, add to the list of signaled pipes */
   1359     lookup = pipe_list_findp_waked(&dev->signaled_pipes, pipe);
   1360     if (!*lookup) {
   1361         pipe->next_waked = dev->signaled_pipes;
   1362         dev->signaled_pipes = pipe;
   1363     }
   1364     pipe->wanted |= (unsigned)flags;
   1365 
   1366     /* Raise IRQ to indicate there are items on our list ! */
   1367     goldfish_device_set_irq(&dev->dev, 0, 1);
   1368     DD("%s: raising IRQ", __FUNCTION__);
   1369 }
   1370 
   1371 void
   1372 goldfish_pipe_close( void* hwpipe )
   1373 {
   1374     Pipe* pipe = hwpipe;
   1375 
   1376     D("%s: channel=0x%llx (closed=%d)", __FUNCTION__, (unsigned long long)pipe->channel, pipe->closed);
   1377 
   1378     if (!pipe->closed) {
   1379         pipe->closed = 1;
   1380         goldfish_pipe_wake( hwpipe, PIPE_WAKE_CLOSED );
   1381     }
   1382 }
   1383