Annotation of researchv9/sys/boot/stand/nd.c, revision 1.1.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.