Annotation of OSKit-Mach/ipc/fipc.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1996-1994 The University of Utah and
                      3:  * the Computer Systems Laboratory (CSL).  All rights reserved.
                      4:  *
                      5:  * Permission to use, copy, modify and distribute this software is hereby
                      6:  * granted provided that (1) source code retains these copyright, permission,
                      7:  * and disclaimer notices, and (2) redistributions including binaries
                      8:  * reproduce the notices in supporting documentation, and (3) all advertising
                      9:  * materials mentioning features or use of this software display the following
                     10:  * acknowledgement: ``This product includes software developed by the
                     11:  * Computer Systems Laboratory at the University of Utah.''
                     12:  *
                     13:  * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
                     14:  * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
                     15:  * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     16:  *
                     17:  * CSL requests users of this software to return to [email protected] any
                     18:  * improvements that they make and grant CSL redistribution rights.
                     19:  *
                     20:  *  Utah $Hdr: fipc.c 1.1 96/2/29$
                     21:  *  Author: Linus Kamb
                     22:  */
                     23: 
                     24: #ifdef FIPC
                     25: 
                     26: #include <mach/kern_return.h>
                     27: 
                     28: #include <device/device_types.h>
                     29: #include <device/device.h>
                     30: #include <device/dev_hdr.h>
                     31: #include <device/device_port.h>
                     32: #include <device/io_req.h>
                     33: #include <device/if_ether.h>
                     34: #include <net_io.h>
                     35: #include <spl.h>
                     36: #include <kern/lock.h>
                     37: 
                     38: #include "fipc.h"
                     39: 
                     40: void fipc_packet();
                     41: void allocate_fipc_buffers(boolean_t);
                     42: int fipc_lookup(unsigned short port);
                     43: int fipc_lookup_table_enter(unsigned short port);
                     44: int fipc_lookup_table_remove(unsigned short port);
                     45: int f_lookup_hash(unsigned short port);
                     46: int fipc_done(io_req_t ior);
                     47: 
                     48: 
                     49: /********************************************************************
                     50:  * fipc variables
                     51:  ********************************************************************/
                     52: 
                     53: fipc_port_t fports[N_MAX_OPEN_FIPC_PORTS];
                     54: fipc_lookup_table_ent fipc_lookup_table[N_MAX_OPEN_FIPC_PORTS];
                     55: 
                     56: int n_free_recv_bufs = 0;
                     57: int n_free_send_bufs = 0;
                     58: int n_fipc_recv_ports_used = 0;
                     59: 
                     60: int fipc_sends = 0;
                     61: int fipc_recvs =0;
                     62: 
                     63: fipc_stat_t fipc_stats;
                     64: 
                     65: char *fipc_recv_free_list = NULL;
                     66: char *fipc_recv_free_list_tail = NULL;
                     67: char *fipc_send_free_list = NULL;
                     68: char *fipc_send_free_list_tail = NULL;
                     69: 
                     70: /* fipc locks */
                     71: decl_simple_lock_data(, fipc_lock);
                     72: decl_simple_lock_data(, fipc_buf_q_lock);
                     73: 
                     74: 
                     75: /*
                     76:  * Routine: fipc_init(): initializes the fipc data structures.
                     77:  */
                     78: 
                     79: void fipc_init(void)
                     80: {
                     81:        int i;
                     82: 
                     83:        allocate_fipc_buffers(TRUE);    /* recv buffers */
                     84:        allocate_fipc_buffers(FALSE);   /* send buffers */
                     85: 
                     86:        fipc_stats.dropped_msgs = 0;
                     87: 
                     88:        bzero (&fports, sizeof(fports));
                     89:        for (i=0; i<N_MAX_OPEN_FIPC_PORTS; i++)
                     90:        {
                     91:                simple_lock_init(&(fports[i].lock));
                     92:                fipc_lookup_table[i].fpt_num = INVALID;
                     93:                fipc_lookup_table[i].fipc_port = INVALID;
                     94:        }
                     95: }
                     96: 
                     97: 
                     98: /*
                     99:  * Routine: allocate_fipc_buffers(): allocate more buffers
                    100:  * Currently we are only allocating 1500 byte (ETHERMTU) buffers.
                    101:  * We use the first word in the buffer as the pointer to the next.
                    102:  */
                    103: 
                    104: void allocate_fipc_buffers(boolean_t r_buf)
                    105: {
                    106:        char *new_pg;
                    107:        char **free_list, **free_list_tail;
                    108:        int *free_count, min_count, max_count;
                    109:        int total_buffer_size;
                    110: 
                    111:        if (r_buf)
                    112:        {
                    113:                free_count = &n_free_recv_bufs;
                    114:                min_count = N_MIN_RECV_BUFS;
                    115:                max_count = N_MAX_RECV_BUFS;
                    116:                free_list = &fipc_recv_free_list;
                    117:                free_list_tail = &fipc_recv_free_list_tail;
                    118:                total_buffer_size = (N_MAX_RECV_BUFS * FIPC_BUFFER_SIZE);
                    119:                total_buffer_size = round_page(total_buffer_size);
                    120:        }
                    121:        else
                    122:        {
                    123:                free_count = &n_free_send_bufs;
                    124:                min_count = N_MIN_SEND_BUFS;
                    125:                max_count = N_MAX_SEND_BUFS;
                    126:                free_list = &fipc_send_free_list;
                    127:                free_list_tail = &fipc_send_free_list_tail;
                    128:                total_buffer_size = (N_MAX_SEND_BUFS * FIPC_BUFFER_SIZE);
                    129:                total_buffer_size = round_page(total_buffer_size);
                    130:        }
                    131: 
                    132:        if (!(*free_count))  /* empty buffer pool */
                    133:        {
                    134: #ifdef FI_DEBUG
                    135:                printf ("Allocating new fipc ");
                    136:                if (r_buf)
                    137:                        printf ("recv buffer pool.\n");
                    138:                else
                    139:                        printf ("send buffer pool.\n");
                    140: #endif
                    141:                *free_list = (char*)kalloc (total_buffer_size);
                    142:                if (!*free_list)        /* bummer */
                    143:                        panic("allocate_fipc_buffers: no memory");
                    144:                *free_list_tail = *free_list;
                    145:                for (*free_count=1; *free_count<max_count; (*free_count)++)
                    146:                {
                    147:                        *(char**)*free_list_tail = *free_list_tail + FIPC_BUFFER_SIZE;
                    148:                        *free_list_tail += FIPC_BUFFER_SIZE;
                    149:                }
                    150:                *(char**)*free_list_tail = NULL;
                    151:        }
                    152:        else  /* Request to grow the buffer pool. */
                    153:        {
                    154: #ifdef FI_DEBUG
                    155:                printf ("Growing fipc ");
                    156:                if (r_buf)
                    157:                        printf ("recv buffer pool.\n");
                    158:                else
                    159:                        printf ("send buffer pool.\n");
                    160: #endif
                    161: 
                    162: #define GROW_SIZE 8192
                    163:                new_pg = (char*)kalloc (round_page(GROW_SIZE));
                    164:                if (new_pg)
                    165:                {
                    166:                        int new_cnt, n_new = GROW_SIZE / FIPC_BUFFER_SIZE;
                    167: 
                    168:                        if (*free_list_tail != NULL)
                    169:                                *(char**)*free_list_tail = new_pg;
                    170:                        for ( new_cnt =0; new_cnt<n_new; new_cnt++)
                    171:                        {
                    172:                                *(char**)*free_list_tail = *free_list_tail + FIPC_BUFFER_SIZE;
                    173:                                *free_list_tail += FIPC_BUFFER_SIZE;
                    174:                        }
                    175:                        *(char**)*free_list_tail = NULL;
                    176:                        *free_count +=new_cnt;
                    177:                }
                    178: #ifdef FI_DEBUG
                    179:                else
                    180:                        printf ("### kalloc failed in allocate_fipc_buffers()\n");
                    181: #endif
                    182: 
                    183:        }
                    184: }
                    185: 
                    186: 
                    187: /*
                    188:  * Routine: get_fipc_buffer (): returns a free buffer
                    189:  * Takes a size (currently not used), a boolean flag to tell if it is a
                    190:  * receive buffer, and a boolean flag if the request is coming at interrupt
                    191:  * level.
                    192:  */
                    193: 
                    194: inline
                    195: char* get_fipc_buffer(int size, boolean_t r_buf, boolean_t at_int_lvl)
                    196: {
                    197:        /* we currently don't care about size, since there is only one
                    198:         * buffer pool. */
                    199: 
                    200:        char* head;
                    201:        char **free_list;
                    202:        int *free_count, min_count;
                    203: 
                    204:        if (r_buf)
                    205:        {
                    206:                free_count = &n_free_recv_bufs;
                    207:                free_list = &fipc_recv_free_list;
                    208:                min_count = N_MIN_RECV_BUFS;
                    209:        }
                    210:        else
                    211:        {
                    212:                free_count = &n_free_send_bufs;
                    213:                free_list = &fipc_send_free_list;
                    214:                min_count = N_MIN_SEND_BUFS;
                    215:        }
                    216: 
                    217:        /*
                    218:         * Since we currently allocate a full complement of receive buffers,
                    219:         * there is no need to allocate more receive buffers.  But that is likely
                    220:         * to change, I'm sure.
                    221:         */
                    222: 
                    223:        if (*free_count < min_count)
                    224:        {
                    225:                if (!at_int_lvl)
                    226:                        allocate_fipc_buffers(r_buf);
                    227:        }
                    228: 
                    229:        if (*free_count)
                    230:        {
                    231:                head = *free_list;
                    232:                *free_list = *(char**)*free_list;
                    233:                (*free_count)--;
                    234:                return head;
                    235:        }
                    236:        else
                    237:                return NULL;
                    238: }
                    239: 
                    240: 
                    241: /*
                    242:  * Routine: return_fipc_buffer (): puts a used buffer back in the pool.
                    243:  */
                    244: 
                    245: inline
                    246: void return_fipc_buffer(char* buf, int size,
                    247:                        boolean_t r_buf, boolean_t at_int_lvl)
                    248: {
                    249:        /* return the buffer to the free pool */
                    250:        char **free_list, **free_list_tail;
                    251:        int *free_count, min_count;
                    252: 
                    253:        if (r_buf)
                    254:        {
                    255:                free_count = &n_free_recv_bufs;
                    256:                free_list = &fipc_recv_free_list;
                    257:                free_list_tail = &fipc_recv_free_list_tail;
                    258:                min_count = N_MIN_RECV_BUFS;
                    259:        }
                    260:        else
                    261:        {
                    262:                free_count = &n_free_send_bufs;
                    263:                free_list = &fipc_send_free_list;
                    264:                free_list_tail = &fipc_send_free_list_tail;
                    265:                min_count = N_MIN_SEND_BUFS;
                    266:        }
                    267: 
                    268: #ifdef FI_SECURE
                    269:        bzero(buf, FIPC_BUFFER_SIZE);
                    270: #endif
                    271: 
                    272:        if (*free_list_tail != NULL)
                    273:                *(char**)*free_list_tail = buf;
                    274:        *free_list_tail = buf;
                    275:        (*free_count)++;
                    276:        *(char**)buf = NULL;
                    277: 
                    278:        if (!at_int_lvl)
                    279:                if (*free_count < min_count)
                    280:                        allocate_fipc_buffers(r_buf);
                    281: 
                    282:        return;
                    283: }
                    284: 
                    285: inline
                    286: int f_lookup_hash(unsigned short port)
                    287: {
                    288:        /* Ok, so it's not really a hash function */
                    289:        int bail=0;
                    290:        int chk=0;
                    291: 
                    292:        if (n_fipc_recv_ports_used == N_MAX_OPEN_FIPC_PORTS ||
                    293:                port > MAX_FIPC_PORT_NUM)
                    294:                        return INVALID;
                    295: 
                    296:        while (fipc_lookup_table[chk].fipc_port != port &&
                    297:                        fipc_lookup_table[chk].fpt_num != INVALID &&
                    298:                        bail < N_MAX_OPEN_FIPC_PORTS)
                    299:        {
                    300:                chk = (chk+1) % N_MAX_OPEN_FIPC_PORTS;
                    301:                bail++;
                    302:        }
                    303: 
                    304:        /* This is redundent, but better safe then sorry */
                    305:        if (bail<N_MAX_OPEN_FIPC_PORTS)
                    306:                return chk;
                    307:        else
                    308:                return INVALID;
                    309: }
                    310: 
                    311: inline
                    312: int fipc_lookup_table_enter(unsigned short port)
                    313: {
                    314:        int cfpn = n_fipc_recv_ports_used;
                    315:        int lu_tbl_num = f_lookup_hash(port);
                    316: 
                    317:        if (lu_tbl_num == INVALID)
                    318:                return INVALID;
                    319: 
                    320:        fipc_lookup_table[lu_tbl_num].fipc_port = port;
                    321:        fipc_lookup_table[lu_tbl_num].fpt_num = cfpn;
                    322:        n_fipc_recv_ports_used += 1;
                    323:        return cfpn;
                    324: }
                    325: 
                    326: inline
                    327: int fipc_lookup(unsigned short port)
                    328: {
                    329:        int chk = f_lookup_hash(port);
                    330: 
                    331:        if (chk == INVALID)
                    332:                return INVALID;
                    333: 
                    334:        if (fipc_lookup_table[chk].fpt_num == INVALID)
                    335:                return fipc_lookup_table_enter(port);
                    336:        else
                    337:                return fipc_lookup_table[chk].fpt_num;
                    338: }
                    339: 
                    340: inline
                    341: int fipc_lookup_table_remove(unsigned short port)
                    342: {
                    343:        int chk = f_lookup_hash(port);
                    344: 
                    345:        if (chk == INVALID)
                    346:                return 0;
                    347: 
                    348:        if (fipc_lookup_table[chk].fipc_port == port)
                    349:        {
                    350:                fports[fipc_lookup_table[chk].fpt_num].valid_msg = 0;
                    351:                fports[fipc_lookup_table[chk].fpt_num].bound = FALSE;
                    352:                fipc_lookup_table[chk].fpt_num = INVALID;
                    353:                fipc_lookup_table[chk].fipc_port = INVALID;
                    354:                n_fipc_recv_ports_used -=1;
                    355:                return 1;
                    356:        }
                    357:        return 0;
                    358: }
                    359: 
                    360: /*
                    361:  * Routine: fipc_packet(): handles incoming fipc packets.
                    362:  * does some simple packet handling and wakes up receiving thread, if any.
                    363:  * called by device controller (currently, nerecv only.)
                    364:  * called at interrupt level and splimp.
                    365:  * Messages are dropped if the recv queue is full.
                    366:  */
                    367: 
                    368:  void fipc_packet( char* msg_buf, struct ether_header sender)
                    369:  {
                    370:        int to_port = ((fipc_header_t*)msg_buf)->dest_port;
                    371:        int from_port = ((fipc_header_t*)msg_buf)->send_port;
                    372:        int f_tbl_num;
                    373:        fipc_port_t *cfp;
                    374:        fipc_buffer_q_ent *crqe;
                    375:        int *tail;
                    376: 
                    377: #ifdef FI_DEBUG
                    378:        printf  ("fipc_packet :(0x%x) %s", msg_buf,
                    379:                                msg_buf+sizeof(fipc_header_t));
                    380: #endif
                    381: 
                    382:        f_tbl_num = fipc_lookup(to_port);
                    383:        if (f_tbl_num == INVALID)
                    384:        {
                    385: #ifdef FI_DEBUG
                    386:                printf ("Lookup failed.\n");
                    387: #endif
                    388:                fipc_stats.dropped_msgs += 1;
                    389:                return_fipc_buffer (msg_buf, FIPC_BUFFER_SIZE, TRUE, TRUE);
                    390:                return;
                    391:        }
                    392: 
                    393:        cfp = &fports[f_tbl_num];
                    394:        tail = &cfp->rq_tail;
                    395:        crqe = &cfp->recv_q[*tail];
                    396: 
                    397:        if (cfp->valid_msg == FIPC_RECV_Q_SIZE)
                    398:        {
                    399:                /* Queue full.
                    400:                 * Drop packet, return buffer, and return. */
                    401: #ifdef FI_DEBUG
                    402:                printf ("Port %d queue is full: valid_msg count: %d\n",
                    403:                                to_port, cfp->valid_msg);
                    404: #endif
                    405:                fipc_stats.dropped_msgs += 1;
                    406:                return_fipc_buffer (msg_buf, FIPC_BUFFER_SIZE, TRUE, TRUE);
                    407:                return;
                    408:        }
                    409: 
                    410:        /* "enqueue" at "tail" */
                    411:        crqe->buffer = msg_buf;
                    412:        crqe->size = ((fipc_header_t*)msg_buf)->msg_size;
                    413:     /* This could certainly be done faster... */
                    414:     bcopy(&(sender.ether_shost), &(crqe->sender.hwaddr), ETHER_HWADDR_SIZE);
                    415:     /* This is actually useless, since there _is_ no sender port.. duh.  */
                    416:     crqe->sender.port = from_port;
                    417: 
                    418:        *tail = ((*tail)+1) % FIPC_RECV_Q_SIZE;
                    419: 
                    420:        if (cfp->bound)
                    421:                thread_wakeup(&(cfp->valid_msg));
                    422:        cfp->valid_msg++;
                    423: #ifdef FI_DEBUG
                    424:        printf ("valid_msg: %d\n", cfp->valid_msg);
                    425: #endif
                    426: 
                    427:        return;
                    428:  }
                    429: 
                    430: 
                    431: /*
                    432:  * loopback(): for fipc_sends to the local host.
                    433:  */
                    434: 
                    435: inline
                    436: kern_return_t loopback(char *packet)
                    437: {
                    438:        fipc_packet(packet+sizeof(struct ether_header),
                    439:                *(struct ether_header*)packet);
                    440:        return KERN_SUCCESS;
                    441: }
                    442: 
                    443: 
                    444: /********************************************************************
                    445:  * Routine: fipc_send
                    446:  ********************************************************************/
                    447: 
                    448: kern_return_t syscall_fipc_send(fipc_endpoint_t dest,
                    449:                char *user_buffer, int len)
                    450: {
                    451: #ifdef i386
                    452:        static mach_device_t    eth_device = 0;
                    453: #else
                    454:        static device_t         eth_device = 0;
                    455: #endif
                    456:        static unsigned char    hwaddr[ETHER_HWADDR_SIZE+2];
                    457: 
                    458:        io_return_t rc;
                    459:        kern_return_t open_res, kr;
                    460:        dev_mode_t mode = D_WRITE;
                    461:        /* register */ io_req_t ior = NULL;
                    462:        struct ether_header *ehdr;
                    463:        fipc_header_t *fhdr;
                    464:        int *d_addr;
                    465:        int data_count;
                    466:        char *fipc_buf, *data_buffer;
                    467: #ifdef FIPC_LOOPBACK
                    468:        boolean_t local_send = FALSE;
                    469: #endif
                    470: 
                    471: #ifdef FI_DEBUG
                    472:        printf("fipc_send(dest: %s, port:%d, len:%d, buf:x%x) !!!\n",
                    473:                ether_sprintf(dest.hwaddr), dest.port, len, user_buffer);
                    474: #endif
                    475: 
                    476:        if (dest.port > MAX_FIPC_PORT_NUM ||
                    477:                len > FIPC_MSG_SIZE)
                    478:        {
                    479: #ifdef FI_DEBUG
                    480:                        printf ("len: %d, dest.port: %u\n", len, dest.port);
                    481: #endif
                    482:                        return KERN_INVALID_ARGUMENT;
                    483:        }
                    484: 
                    485:        /* We should only need to probe the device once. */
                    486: 
                    487:        if (!eth_device)
                    488:        {
                    489:                unsigned char net_hwaddr[ETHER_HWADDR_SIZE+2];
                    490:                int stat_count = sizeof(net_hwaddr)/sizeof(int);
                    491: 
                    492:                /* XXX Automatic lookup for ne0 or ne1 was failing... */
                    493:                eth_device = device_lookup(ETHER_DEVICE_NAME);
                    494: #ifdef i386
                    495:                if (eth_device == (mach_device_t) DEVICE_NULL ||
                    496:                        eth_device == (mach_device_t)D_NO_SUCH_DEVICE)
                    497: #else
                    498:                if (eth_device == DEVICE_NULL ||
                    499:                        eth_device == (device_t)D_NO_SUCH_DEVICE)
                    500: #endif
                    501:                        {
                    502: #ifdef FI_DEBUG
                    503:                                printf ("FIPC: Couldn't find ethernet device %s.\n",
                    504:                                        ETHER_DEVICE_NAME);
                    505: #endif
                    506:                                return (KERN_FAILURE);
                    507:                        }
                    508: 
                    509:                /* The device should be open! */
                    510:                if (eth_device->state != DEV_STATE_OPEN)
                    511:                {
                    512: #ifdef FI_DEBUG
                    513:                        printf ("Opening ethernet device.\n");
                    514: #endif
                    515: 
                    516:                        io_req_alloc (ior, 0);
                    517: 
                    518:                        io_req_alloc (ior, 0);
                    519: 
                    520:                        ior->io_device = eth_device;
                    521:                        ior->io_unit = eth_device->dev_number;
                    522:                        ior->io_op = IO_OPEN | IO_CALL;
                    523:                        ior->io_mode = mode;
                    524:                        ior->io_error = 0;
                    525:                        ior->io_done = 0;
                    526:                        ior->io_reply_port = MACH_PORT_NULL;
                    527:                        ior->io_reply_port_type = 0;
                    528: 
                    529:                        /* open the device */
                    530:                        open_res =
                    531:                                (*eth_device->dev_ops->d_open)
                    532:                                        (eth_device->dev_number,
                    533:                                        (int)mode, ior);
                    534:                        if (ior->io_error != D_SUCCESS)
                    535:                        {
                    536: #ifdef FI_DEBUG
                    537:                                printf ("Failed to open device ne0\n");
                    538: #endif
                    539:                                return open_res;
                    540:                        }
                    541:                }
                    542: #ifdef i386
                    543:                rc = mach_device_get_status(eth_device, NET_ADDRESS,
                    544:                                            net_hwaddr, &stat_count);
                    545: #else
                    546:                rc = ds_device_get_status(eth_device, NET_ADDRESS, net_hwaddr,
                    547:                                          &stat_count);
                    548: #endif
                    549:                if (rc != D_SUCCESS)
                    550:                {
                    551: #ifdef FI_DEBUG
                    552:                        printf("FIPC: Couldn't determine hardware ethernet address: %d\n",
                    553:                                        rc);
                    554: #endif
                    555:                        return KERN_FAILURE;
                    556:                }
                    557:                *(int*)hwaddr = ntohl(*(int*)net_hwaddr);
                    558:                *(int*)(hwaddr+4) = ntohl(*(int*)(net_hwaddr+4));
                    559: #ifdef FI_DEBUG
                    560:                printf ("host: %s\n", ether_sprintf(hwaddr));
                    561: #endif
                    562:        }
                    563: 
                    564: #ifdef FIPC_LOOPBACK
                    565:        if (!memcmp(dest.hwaddr, hwaddr, ETHER_HWADDR_SIZE))
                    566: /*
                    567:        if ((*(int*)dest.hwaddr == *(int*)hwaddr) &&
                    568:                ((*(int*)(((char*)dest.hwaddr+4) >> 16)) ==
                    569:                ((*(int*)(((char*)hwaddr+4) >> 16)))))
                    570: */
                    571:        {
                    572:                local_send = TRUE;
                    573: #ifdef FI_DEBUG
                    574:                printf ("loopback: \n");
                    575:                printf ("host: %s, ", ether_sprintf(hwaddr));
                    576:                printf ("dest: %s\n", ether_sprintf(dest.hwaddr));
                    577: #endif
                    578:        }
                    579: #endif
                    580: 
                    581:        data_count = len + sizeof (struct ether_header)
                    582:                                 + sizeof (fipc_header_t);
                    583: 
                    584: #ifdef FIPC_LOOPBACK
                    585:        fipc_buf = get_fipc_buffer(data_count, local_send, FALSE) ;
                    586: #else
                    587:        fipc_buf = get_fipc_buffer(data_count, FALSE, FALSE) ;
                    588: #endif
                    589: 
                    590:        if (fipc_buf == NULL)
                    591:                return KERN_RESOURCE_SHORTAGE;
                    592: 
                    593:        ehdr = (struct ether_header *)fipc_buf;
                    594:        d_addr = (int *)ehdr->ether_dhost;
                    595: 
                    596:        *(int *)ehdr->ether_dhost = *(int*)dest.hwaddr;
                    597:        *(int *)(ehdr->ether_dhost+4) = *(int*)(dest.hwaddr+4);
                    598:        *(int *)ehdr->ether_shost = *(int *)hwaddr;
                    599:        *(int *)(ehdr->ether_shost+4) = *(int *)(hwaddr+4);
                    600:        ehdr->ether_type = 0x1234;                /* Yep. */
                    601: 
                    602: #ifdef FIPC_LOOPBACK
                    603:        if (!local_send)
                    604:        {
                    605: #endif
                    606:                if (!ior)
                    607:                        io_req_alloc (ior, 0);
                    608: 
                    609:                /* Set up the device information. */
                    610:                ior->io_device      = eth_device;
                    611:                ior->io_unit        = eth_device->dev_number;
                    612:                ior->io_op          = IO_WRITE | IO_INBAND | IO_INTERNAL;
                    613:                ior->io_mode        = D_WRITE;
                    614:                ior->io_recnum      = 0;
                    615:                ior->io_data        = fipc_buf;
                    616:                ior->io_count       = data_count;
                    617:                ior->io_total       = data_count;
                    618:                ior->io_alloc_size  = 0;
                    619:                ior->io_residual    = 0;
                    620:                ior->io_error       = 0;
                    621:                ior->io_done        = fipc_done;
                    622:                ior->io_reply_port  = MACH_PORT_NULL;
                    623:                ior->io_reply_port_type = 0;
                    624:                ior->io_copy        = VM_MAP_COPY_NULL;
                    625: #ifdef FIPC_LOOPBACK
                    626:        }
                    627: #endif
                    628: 
                    629: #ifdef FI_DEBUG
                    630:        printf("sending from %s ", ether_sprintf(ehdr->ether_shost));
                    631:        printf("to %s, type x%x, user_port x%x\n",
                    632:                ether_sprintf(ehdr->ether_dhost),
                    633:                (int)ehdr->ether_type,
                    634:                (int)dest.port);
                    635: #endif
                    636: 
                    637:        if (len <= FIPC_MSG_SIZE)
                    638:        {
                    639:                fhdr = (fipc_header_t*)(fipc_buf+sizeof(struct ether_header));
                    640:                fhdr->dest_port = dest.port;
                    641:                fhdr->msg_size = len;
                    642:                data_buffer = (char*)fhdr+sizeof(fipc_header_t);
                    643: 
                    644:                copyin (user_buffer, data_buffer,
                    645:                        min (FIPC_BUFFER_SIZE-sizeof(fipc_header_t), len));
                    646: 
                    647: #ifdef FIPC_LOOPBACK
                    648:                /*
                    649:                * Sending to same node.  Queue on dest.port of this node.
                    650:                * We just call fipc_packet after setting up the necessary info
                    651:                * and return.  fipc_packet queues the packet on the receive
                    652:                * queue for the destination port.
                    653:                */
                    654:                if (local_send)
                    655:                        return (loopback(fipc_buf));
                    656: #endif
                    657: 
                    658:                /* Now write to the device */
                    659:                /* d_port_death has been co-opted for fipc stuff.
                    660:                 * It maps to nefoutput(). */
                    661: 
                    662:                rc = (*eth_device->dev_ops->d_port_death) /* that's the one */
                    663:                                (eth_device->dev_number, ior);
                    664:        }
                    665: #ifdef FI_DEBUG
                    666:        else    /* len > ETHERMTU: multi-packet request */
                    667:                printf  ("### multi-packet messages are not supported.\n");
                    668: #endif
                    669: 
                    670:        if (rc == D_IO_QUEUED)
                    671:                return KERN_SUCCESS;
                    672:        else
                    673:                return KERN_FAILURE;
                    674: }
                    675: 
                    676: #ifdef FIPC_LOOPBACK
                    677:        if (!local_send)
                    678:        {
                    679: #endif
                    680:                if (!ior)
                    681:                        io_req_alloc (ior, 0);
                    682: 
                    683:                /* Set up the device information. */
                    684:                ior->io_device      = eth_device;
                    685:                ior->io_unit        = eth_device->dev_number;
                    686:                ior->io_op          = IO_WRITE | IO_INBAND | IO_INTERNAL;
                    687:                ior->io_mode        = D_WRITE;
                    688:                ior->io_recnum      = 0;
                    689:                ior->io_data        = fipc_buf;
                    690:                ior->io_count       = data_count;
                    691:                ior->io_total       = data_count;
                    692:                ior->io_alloc_size  = 0;
                    693:                ior->io_residual    = 0;
                    694:                ior->io_error       = 0;
                    695:                ior->io_done        = fipc_done;
                    696:                ior->io_reply_port  = MACH_PORT_NULL;
                    697:                ior->io_reply_port_type = 0;
                    698:                ior->io_copy        = VM_MAP_COPY_NULL;
                    699: #ifdef FIPC_LOOPBACK
                    700:        }
                    701: #endif
                    702: 
                    703: /********************************************************************
                    704:  * syscall_fipc_recv()
                    705:  *
                    706:  ********************************************************************/
                    707: 
                    708: kern_return_t syscall_fipc_recv(unsigned short user_port,
                    709:        char *user_buffer, int *user_size, fipc_endpoint_t *user_sender)
                    710: {
                    711:        char* f_buffer;
                    712:        fipc_port_t *cfp;
                    713:        fipc_buffer_q_ent *crqe;
                    714:        int *head;
                    715:        int msg_size;
                    716:        int fport_num = fipc_lookup(user_port);
                    717:        spl_t spl;
                    718: 
                    719: #ifdef FI_DEBUG
                    720:        printf("fipc_recv(0x%x, 0x%x) !!!\n", user_port, user_buffer);
                    721: #endif
                    722: 
                    723:        if (user_port > MAX_FIPC_PORT_NUM)
                    724:        {
                    725: #ifdef FI_DEBUG
                    726:                printf ("Invalid FIPC port: %u\n", user_port);
                    727: #endif
                    728:                return KERN_INVALID_ARGUMENT;
                    729:        }
                    730: 
                    731:        if (fport_num == INVALID)
                    732:                return KERN_RESOURCE_SHORTAGE;
                    733: 
                    734:        cfp = &fports[fport_num];
                    735:        head = &cfp->rq_head;
                    736:        crqe = &cfp->recv_q[*head];
                    737: 
                    738:        if (cfp->bound != FALSE)
                    739:        {
                    740: #ifdef FI_DEBUG
                    741:                printf ("FIPC Port %u is currently bound.\n", user_port);
                    742: #endif
                    743:                return KERN_RESOURCE_SHORTAGE;
                    744:        }
                    745: 
                    746:        copyin(user_size, &msg_size, sizeof(int));
                    747: 
                    748:        spl = splimp();
                    749: 
                    750:        cfp->bound = TRUE;
                    751:        while (!(cfp->valid_msg))
                    752:        {
                    753:                assert_wait(&(cfp->valid_msg), TRUE);
                    754:                splx(spl);
                    755:                thread_block ((void(*)())0);
                    756:                if (current_thread()->wait_result != THREAD_AWAKENED)
                    757:                {
                    758:                        cfp->bound = FALSE;
                    759:                        return KERN_FAILURE;
                    760:                }
                    761:                spl = splimp();
                    762:        }
                    763: 
                    764:        cfp->valid_msg--;
                    765:        f_buffer = crqe->buffer;
                    766:        msg_size = min (crqe->size, msg_size);
                    767: 
                    768:        crqe->buffer = NULL;
                    769:        crqe->size = 0;
                    770:        *head = ((*head)+1) % FIPC_RECV_Q_SIZE;
                    771:        cfp->bound = FALSE;
                    772: 
                    773:        splx(spl);
                    774: 
                    775:        copyout(f_buffer+sizeof(fipc_header_t), user_buffer, msg_size);
                    776:        copyout(&(crqe->sender), user_sender, sizeof(fipc_endpoint_t));
                    777:        copyout(&msg_size, user_size, sizeof(msg_size));
                    778: 
                    779:        return_fipc_buffer(f_buffer, FIPC_BUFFER_SIZE, TRUE, FALSE);
                    780: 
                    781:        return KERN_SUCCESS;
                    782: }
                    783: 
                    784: 
                    785: /*
                    786:  * Final clean-up after the packet has been sent off.
                    787:  */
                    788: int fipc_done(io_req_t ior)
                    789: {
                    790:     return_fipc_buffer(ior->io_data, FIPC_BUFFER_SIZE, FALSE, FALSE);
                    791: 
                    792:        return 1;
                    793: }
                    794: 
                    795: #endif /* FIPC */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.