Annotation of OSKit-Mach/ipc/fipc.c, revision 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.