Annotation of researchv9/sys/boot/stand/nd.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)nd.c       1.1 86/02/03    Copyr 1985 Sun Micro";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: /*
        !            10:  * standalone nd.c
        !            11:  * Used only in /boot after TFTP boot.
        !            12:  * Never in PROM or boot blocks
        !            13:  */
        !            14: 
        !            15: /* This value is used in header files, it must be at least 1 */
        !            16: #define        NND     1
        !            17: 
        !            18: #include "saio.h"
        !            19: #include "param.h"
        !            20: #include "../h/socket.h"
        !            21: #include "../net/if.h"
        !            22: #include "../netinet/in.h"
        !            23: #include "../netinet/if_ether.h"
        !            24: #include "../netinet/in_systm.h"
        !            25: #include "../netinet/ip.h"
        !            26: #include "sainet.h"
        !            27: #include "../sun/ndio.h"
        !            28: #include "../mon/sunromvec.h"
        !            29: #include "../mon/idprom.h"
        !            30: 
        !            31: #define millitime() (*romp->v_nmiclock)
        !            32: 
        !            33: /* 
        !            34:  * Each network device driver must start off their local variables
        !            35:  * structure (pointed to by sip->si_devdata) by a struct nd or a union
        !            36:  * of a struct nd and other protocol structures.  This reserves the
        !            37:  * space needed by the protocol handler(s) without any further ado.
        !            38:  * Therefore, the protocol can simply assume that sip->si_devdata
        !            39:  * points to its parameters.
        !            40:  */
        !            41: #define        NDBASE  (struct nd *)(sip->si_devdata)
        !            42: 
        !            43: /* standalone RAM variables */
        !            44: struct nd {                    
        !            45:        int     nd_seq;                 /* current sequence number */
        !            46:        struct ether_header nd_xh;      /* xmit header and packet */
        !            47:        struct ndpack nd_xp;            /* must be contiguous */
        !            48:        int     nd_block;               /* block number of data in "cache" */
        !            49:        char    nd_data[NDMAXDATA];     /* "cache" of receive data */
        !            50:        char    nd_buf[1600];           /* temp buf for packets */
        !            51:        struct  sainet nd_inet;         /* INET state */
        !            52: };
        !            53: 
        !            54: #define        NDHDRSIZE       (sizeof(struct ether_header) + sizeof(struct ndpack))
        !            55: 
        !            56: /*
        !            57:  * Zap this to indicate ND device from which to boot by default
        !            58:  */
        !            59: short ndbootdev = 0x40;                /* public partition #0 */
        !            60: 
        !            61: /*
        !            62:  * Initialize network disk operation.
        !            63:  * Get server address and partition number from si_unit and si_boff.
        !            64:  */
        !            65: etheropen(sip)
        !            66:        struct saioreq *sip;
        !            67: {
        !            68:        register struct nd *nd = NDBASE;
        !            69:        register i;
        !            70:        char buf[DEV_BSIZE];
        !            71: 
        !            72:        bzero((caddr_t)nd, sizeof *nd);
        !            73: 
        !            74:        /*
        !            75:         * Initialize INET state
        !            76:         */
        !            77:        inet_init(sip, &nd->nd_inet, nd->nd_buf);
        !            78: 
        !            79:        /* 
        !            80:         * Set src and dst host addresses
        !            81:         * Dst host is argument with our net number plugged in
        !            82:         */
        !            83:        nd->nd_xp.np_ip.ip_src = nd->nd_inet.sain_myaddr;
        !            84:        nd->nd_xp.np_ip.ip_dst.s_addr = sip->si_unit;
        !            85:        nd->nd_xp.np_ip.ip_dst.s_addr += nd->nd_xp.np_ip.ip_src.s_addr -
        !            86:                                        in_lnaof(nd->nd_xp.np_ip.ip_src);
        !            87: /* fix for FF broadcast ? */
        !            88:         
        !            89:        nd->nd_block = -10;             /* impossible block number */
        !            90:        nd->nd_seq = millitime();       /* initial sequence number */
        !            91:        /* set ether, ip and ndpack fixed fields */
        !            92:        nd->nd_xp.np_ip.ip_v = IPVERSION;
        !            93:        nd->nd_xp.np_ip.ip_hl = sizeof (struct ip) / 4;
        !            94:        nd->nd_xp.np_ip.ip_len = sizeof (struct ndpack);
        !            95:        nd->nd_xp.np_ip.ip_ttl = NDXTIMER;
        !            96:        nd->nd_xp.np_ip.ip_p = IPPROTO_ND;
        !            97:        nd->nd_xp.np_op = (NDOPREAD | NDOPWAIT);
        !            98:        nd->nd_xp.np_min = (int)sip->si_boff;
        !            99:        /*
        !           100:         * We XOR here to keep similar semantics of bie(,,40)
        !           101:         * to mean private when default is public
        !           102:         */
        !           103:        nd->nd_xp.np_min ^= ndbootdev;
        !           104:        nd->nd_xp.np_bcount = NDMAXDATA;
        !           105: 
        !           106:        /* try to read block 0 */
        !           107:        if (ndread(sip, 0, buf))
        !           108:                return (-1);
        !           109:        return (0);
        !           110: }
        !           111: 
        !           112: /*
        !           113:  * Strategy routine.  User interface to do reads and writes is thru here.
        !           114:  * We currently don't support writes.
        !           115:  */
        !           116: int
        !           117: etherstrategy(sip, rw)
        !           118:        register struct saioreq *sip;
        !           119:        int rw;
        !           120: {
        !           121:        int cnt = sip->si_cc;
        !           122:        int blk = sip->si_bn;
        !           123:        char *ma = sip->si_ma;
        !           124: 
        !           125:        if (rw == WRITE)
        !           126:                return (0);
        !           127:        while (cnt > 0) {
        !           128:                if (ndread(sip, blk, ma))
        !           129:                        break;
        !           130:                blk++;
        !           131:                ma += DEV_BSIZE;
        !           132:                cnt -= DEV_BSIZE;
        !           133:        }
        !           134:        return (sip->si_cc - cnt);
        !           135: }
        !           136: 
        !           137: /*
        !           138:  * Receive packets from an nd server.
        !           139:  * We keep a 1K cache to speed things up
        !           140:  */
        !           141: ndread(sip, block, caddr)
        !           142:        struct saioreq *sip;
        !           143:        int block;
        !           144:        caddr_t caddr;
        !           145: {
        !           146:        register struct nd *nd = NDBASE;
        !           147:        register char *cp;
        !           148:        register short ok, i;
        !           149: 
        !           150:        cp = nd->nd_data;
        !           151:        if (block == nd->nd_block)
        !           152:                goto copy;
        !           153:        if (block == (nd->nd_block+1)) {
        !           154:                cp += DEV_BSIZE;
        !           155:                goto copy;
        !           156:        }
        !           157:        /*
        !           158:         * Fill in the request block
        !           159:         */
        !           160:        nd->nd_xp.np_blkno = block;
        !           161:        nd->nd_xp.np_seq = ++nd->nd_seq;
        !           162: 
        !           163: #define        LIMIT   500
        !           164:        for (i=0 ; i<LIMIT ; i++) {
        !           165:                if (ip_output(sip, (caddr_t)&nd->nd_xh, NDHDRSIZE,
        !           166:                    &nd->nd_inet, nd->nd_buf)) {
        !           167:                        printf("X\010");
        !           168:                        continue;
        !           169:                }
        !           170:                ok = ndrecv(sip);
        !           171:                if (ok >= 0)
        !           172:                        break;
        !           173:                printf("?\b");  /* Indicate there's a problem */
        !           174:        }
        !           175:        if (i == LIMIT) {
        !           176:                printf("nd: no file server, giving up.\n");
        !           177:                return (-1);
        !           178:        }
        !           179:        if (ok == 0)
        !           180:                return (-1);
        !           181:        nd->nd_block = block;
        !           182: copy:
        !           183:        bcopy(cp, caddr, DEV_BSIZE);
        !           184:        return (0);
        !           185: }
        !           186: 
        !           187: #define        NDREPLYTIME     (2*1000)        /* miilliseconds between retransmits */
        !           188: 
        !           189: ndrecv(sip)
        !           190:        struct saioreq *sip;
        !           191: {
        !           192:        register struct nd *nd = NDBASE;
        !           193:        register struct ndpack *np;
        !           194:        register struct ether_header *eh;
        !           195:        register int time;
        !           196:        register short len;
        !           197: 
        !           198:        time = millitime() + NDREPLYTIME;
        !           199:        for (;;) {
        !           200:                if (millitime() > time) {
        !           201:                        (*sip->si_sif->sif_reset)(sip->si_devdata, sip);
        !           202:                        return (-1);
        !           203:                }
        !           204:                len = ip_input(sip, nd->nd_buf, &nd->nd_inet);
        !           205:                if (len < NDHDRSIZE) 
        !           206:                        continue;
        !           207:                eh = (struct ether_header *)nd->nd_buf;
        !           208:                np = (struct ndpack *)&eh[1];
        !           209: 
        !           210:                /*
        !           211:                 * avoid bug in older servers.
        !           212:                 * The problem is that pre-Sun Unix 1.1 servers would
        !           213:                 * respond to ANY directed boot request that they
        !           214:                 * received, whether or not it was directed to their
        !           215:                 * Internet address.  (They assumed that the boot
        !           216:                 * proms knew their Ethernet address.)  We now broadcast
        !           217:                 * all boot requests, directed or otherwise, so we have
        !           218:                 * to filter out replies from ones we don't care about.
        !           219:                 */
        !           220:                if (in_lnaof(nd->nd_xp.np_ip.ip_dst) != 0 &&
        !           221:                    in_lnaof(nd->nd_xp.np_ip.ip_dst) !=
        !           222:                    in_lnaof(np->np_ip.ip_src))
        !           223:                        continue;
        !           224: 
        !           225:                if (np->np_ip.ip_p == IPPROTO_ND && np->np_seq == nd->nd_seq)
        !           226:                        break;
        !           227:        }
        !           228: 
        !           229:        if (np->np_op == NDOPERROR) {
        !           230:                printf("nd: err %x bn %d\n", np->np_error, np->np_blkno);
        !           231:                return (0);
        !           232:        }
        !           233:        if (np->np_op != (NDOPREAD|NDOPDONE|NDOPWAIT) ||
        !           234:            np->np_ccount != NDMAXDATA ||
        !           235:            np->np_ip.ip_len != (sizeof(struct ndpack)+NDMAXDATA)) {
        !           236: #ifdef DEBUG
        !           237:                printf("ND protocol violation\n");
        !           238: #endif DEBUG
        !           239:                return (-1);
        !           240:        }
        !           241:        /* lock onto server if we are still broadcasting */
        !           242:        if (in_broadaddr(nd->nd_xp.np_ip.ip_dst))
        !           243:                nd->nd_xp.np_ip.ip_dst = np->np_ip.ip_src;
        !           244: #ifdef NOREVARP
        !           245:        if ((nd->nd_xp.np_ip.ip_dst.s_addr & 0xFF000000) == 0)
        !           246:                nd->nd_xp.np_ip.ip_dst = np->np_ip.ip_src;
        !           247: #endif
        !           248:        if ((nd->nd_seq & 7) == 0)
        !           249:                printf((nd->nd_seq & 8) ? "-\b" : "=\b");
        !           250:        bcopy(nd->nd_buf + NDHDRSIZE, nd->nd_data, NDMAXDATA);
        !           251:        return (1);
        !           252: }

unix.superglobalmegacorp.com

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