From 673d2fe8805d24559336baf1fdd94d67d93174a5 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 11 Nov 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-11-11 --- bitsy/clock.c | 24 +++- bitsy/devflash.c | 127 +++++++++++++++++-- bitsy/devuda1341.c | 146 +++++++++++---------- bitsy/fns.h | 4 + bitsy/io.h | 26 ++++ bitsy/main.c | 3 + bitsy/sa1110dma.c | 33 +++-- bitsy/sa1110dma.h | 5 +- ip/bootp.c | 191 ---------------------------- ip/{dial.c => chandial.c} | 52 +++----- ip/ethermedium.c | 28 +---- ip/ihbootp.c | 259 -------------------------------------- ip/ip.c | 2 +- ip/ip.h | 5 + ip/ipaux.c | 1 - ip/ipifc.c | 2 - ip/kernel.h | 15 --- ip/kio.c | 199 ----------------------------- ip/netdevmedium.c | 9 +- ip/nullmedium.c | 1 - ip/pktmedium.c | 1 - ip/plan9.c | 35 ------ ip/ptclbsum.c | 1 - ip/tripmedium.c | 1 - mpc/fns.h | 4 +- pc/devi82365.c | 2 +- port/lib.h | 1 + 27 files changed, 312 insertions(+), 865 deletions(-) delete mode 100644 ip/bootp.c rename ip/{dial.c => chandial.c} (74%) delete mode 100644 ip/ihbootp.c delete mode 100644 ip/kernel.h delete mode 100644 ip/kio.c delete mode 100644 ip/plan9.c diff --git a/bitsy/clock.c b/bitsy/clock.c index c032b1d3df228794882ef1b4f09e7c6b576edb84..df4f4dbaed525839f49e6936fe5e40cc29bb0520 100644 --- a/bitsy/clock.c +++ b/bitsy/clock.c @@ -7,6 +7,19 @@ #include "ureg.h" #include "../port/error.h" +typedef struct OSTimer +{ + ulong osmr[4]; /* match registers */ + ulong oscr; /* counter register */ + ulong ossr; /* status register */ + ulong ower; /* watchdog enable register */ + ulong oier; /* timer interrupt enable register */ +} OSTimer; + +static OSTimer *timerregs = (OSTimer*)OSTIMERREGS; +static int clockinited; + +static void clockintr(Ureg*, void*); void clockinit(void) @@ -36,16 +49,13 @@ fastticks(uvlong *hz) static void clockintr(Ureg *ureg, void*) { - Clock0link *lp; - static int inclockintr; - /* reset previous interrupt */ timerregs->ossr |= 1<<0; /* post interrupt 1/HZ secs from now */ timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ; - portclock(); + portclock(ureg); } void @@ -57,7 +67,8 @@ delay(int ms) if(clockinited){ while(ms-- > 0){ start = timerregs->oscr; - while(timerregs->oscr-start < ClockFreq/1000); + while(timerregs->oscr-start < ClockFreq/1000) + ; } } else { while(ms-- > 0){ @@ -75,7 +86,8 @@ void if(clockinited){ start = timerregs->oscr; - while(timerregs->oscr - start < µs∗ClockFreq/1000000); + while(timerregs->oscr - start < (µs*ClockFreq)/1000000) + ; } else { while(µs-- > 0){ for(i = 0; i < 10; i++) diff --git a/bitsy/devflash.c b/bitsy/devflash.c index a2014e46cd3ac05f878a8e30053dbf6efe864fb2..a1cc58bdbc6223e8698b62093fec2967570b1073 100644 --- a/bitsy/devflash.c +++ b/bitsy/devflash.c @@ -30,13 +30,6 @@ static ulong *flash = (ulong*)FLASHZERO; /* * common flash memory interface */ -enum -{ - CFIidoff= 0x10, - CFIsysoff= 0x1B, - CFIgeomoff= 0x27, -}; - struct CFIid { ulong q; @@ -70,5 +63,123 @@ struct CFIsys struct CFIgeom { ulong size; /* 2**n bytes */ - ulong + ulong dev_code; /* ??? */ + ulong max_multi; /* max bytes in a multibyte write */ + ulong nregion; /* number of erase regions */ + ulong region[1]; /* erase region info */ +}; + +#define mirror(x) (((x)<<16)|(x)) + +void +cfiquery(void) +{ + struct CFIid *id; + + flash[0x55] = mirror(0x98); + id = (struct CFIid*)&flash[0x10]; + if(id.q != 'q' || id.r != 'r' || id.y != 'y') + print("CFI not supported by flash\n"); + + flash[0x55] = mirror(0xFF); +} + +void +cfigeom(void) +{ +} + +/* + * flash device interface + */ + +enum +{ + Qf0=1, + Qf1, + Qf2, + Qf3, +}; + +Dirtab flashdir[]={ + "f0", { Qf0, 0 }, 0, 0664, + "f1", { Qf1, 0 }, 0, 0664, + "f2", { Qf2, 0 }, 0, 0664, + "f3", { Qf3, 0 }, 0, 0664, +}; + +void +flashinit(void) +{ + cfiquery(); + cfigeom(); +} + +static Chan* +flashattach(char* spec) +{ + return devattach('r', spec); +} + +static int +flashwalk(Chan* c, char* name) +{ + return devwalk(c, name, flashdir, nelem(flashdir), devgen); +} + +static void +flashstat(Chan* c, char* dp) +{ + devstat(c, dp, flashdir, nelem(flashdir), devgen); +} + +static Chan* +flashopen(Chan* c, int omode) +{ + omode = openmode(omode); + if(strcmp(up->user, eve)!=0) + error(Eperm); + return devopen(c, omode, flashdir, nelem(flashdir), devgen); +} + +static void +flashclose(Chan*) +{ +} + +static long +flashread(Chan* c, void* a, long n, vlong off) +{ + USED(c, a, off); + error("UUO"); + return n; +} + +static long +flashwrite(Chan* c, void* a, long n, vlong) +{ + USED(c, a, off); + error("UUO"); + return n; +} + +Dev flashdevtab = { + 'F', + "flash", + + devreset, + flashinit, + flashattach, + devclone, + flashwalk, + flashstat, + flashopen, + devcreate, + flashclose, + flashread, + devbread, + flashwrite, + devbwrite, + devremove, + devwstat, }; diff --git a/bitsy/devuda1341.c b/bitsy/devuda1341.c index 59a354814430cb15b903561cf462a6837a971060..d4b0cc71a07fefbaf862d0fb10cbee5470da352f 100644 --- a/bitsy/devuda1341.c +++ b/bitsy/devuda1341.c @@ -71,10 +71,10 @@ enum { /* * UDA1341 L3 address and command types */ -#define UDA1341_L3Addr 5 #define UDA1341_DATA0 0 #define UDA1341_DATA1 1 #define UDA1341_STATUS 2 +#define UDA1341_L3Addr 5 typedef struct AQueue AQueue; typedef struct Buf Buf; @@ -135,7 +135,7 @@ struct IOstate int dma; /* dma chan, alloc on open, free on close */ int bufinit; /* boolean, if buffers allocated */ Buf buf[Nbuf]; /* buffers and queues */ - int active; /* # of dmas in progress */ + Ref active; /* # of dmas in progress */ volatile Buf *current; /* next dma to finish */ volatile Buf *next; /* next candidate for dma */ volatile Buf *filling; /* buffer being filled */ @@ -336,7 +336,7 @@ L3_getbyte(int mode) * in the upper 6 bits). */ static int -L3_write(char addr, char *data, int len) +L3_write(uchar addr, uchar *data, int len) { int mode = 0; int bytes = len; @@ -355,7 +355,7 @@ L3_write(char addr, char *data, int len) * in the upper 6 bits). */ static int -L3_read(char addr, char * data, int len) +L3_read(uchar addr, uchar *data, int len) { int mode = 0; int bytes = len; @@ -387,7 +387,6 @@ setempty(IOstate *b) for (i = 0; i < Nbuf; i++) { b->buf[i].nbytes = 0; - b->buf[i].active = 0; } b->filling = b->buf; b->current = b->buf; @@ -395,10 +394,12 @@ setempty(IOstate *b) } static int -audioqnotfull(IOstate *s) +audioqnotfull(void *x) { + IOstate *s = x; + /* called with lock */ - return s->active == 0 || s->filling != s->current; + return s->active.ref == 0 || s->filling != s->current; } static int @@ -409,10 +410,11 @@ audioqnotempty(IOstate *s) } static int -audioidle(IOstate *s) +audioidle(void *x) { + IOstate *s = x; /* called with lock */ - return s->active == 0; + return s->active.ref == 0; } static void @@ -424,61 +426,77 @@ audioinit(void) static void audioenable(void) { - int err; + uchar data[2]; L3_init(); /* Setup the uarts */ ppcregs->assignment &= ~(1<<18); /* Could be the other way round! */ - gpioregs->altfunc &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM); - gpioregs->altfunc |= (GPIO_SSP_CLK); - gpioregs->direction &= ~(GPIO_SSP_CLK); + gpioregs->altfunc &= ~(GPIO_SSP_TXD_o | GPIO_SSP_RXD_i | GPIO_SSP_SCLK_o | GPIO_SSP_SFRM_o); + gpioregs->altfunc |= (GPIO_SSP_CLK_i); + gpioregs->direction &= ~(GPIO_SSP_CLK_i); sspregs->control0 = 0x10<<0 | 0x1<<4 | 1<<7 | 0x8<<8; sspregs->control1 = 0<<3 + 0<<4 + 1<<5; /* Enable the audio power */ - set_bitsy_egpio(EGPIO_BITSY_CODEC_NRESET|EGPIO_BITSY_AUD_AMP_ON|EGPIO_BITSY_AUD_PWR_ON); - clr_bitsy_egpio(EGPIO_BITSY_QMUTE); - gpioregs->direction |= (GPIO_BITSY_CLK_SET0|GPIO_BITSY_CLK_SET1); - /* external clock configured for 44100 samples/sec */ - GPSR = GPIO_BITSY_CLK_SET0; - GPCR = GPIO_BITSY_CLK_SET1; + audiopower(1); + amplifierpower(1); + audiomute(0); + gpioregs->direction |= (GPIO_CLK_SET0_o|GPIO_CLK_SET1_o); + /* external clock configured for 44100 samples/sec */ + gpioregs->set = GPIO_CLK_SET0_o; + gpioregs->clear = GPIO_CLK_SET1_o; - printk("gpioregs->altfunc=%08x gpioregs->direction=%08x GPLR=%08x\n", gpioregs->altfunc, gpioregs->direction, GPLR); - printk("PPDR=%08x PPSR=%08x PPAR=%08x PPFR=%08x\n", PPDR, PPSR, PPAR, PPFR); - /* Wait for the UDA1341 to wake up */ - mdelay(100); - printk("Ser4SSSR=%08x\n", Ser4SSSR); - - audio_uda1341_reset(); - - /* Set some default mixer values... */ - STATUS_1.DAC_gain = 1; - STATUS_1.ADC_gain = 1; - L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, (char*)&STATUS_1, 1 ); - DATA0_0.volume = 15; - L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_0, 1 ); - DATA0_2.mode = 3; - L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_2, 1 ); - DATA0_ext2.mixer_mode = 2; - DATA0_ext2.mic_level = 4; - L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_ext2, 2 ); - DATA0_ext4.AGC_ctrl = 1; - L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_ext4, 2 ); - DATA0_ext6.AGC_level = 3; - L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_ext6, 2 ); + delay(100); + print("Ser4SSSR=0x%lux\n", sspregs->status); - print("audio enabled\n"); + /* Reset the chip */ + data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */; + L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 ); - return 0; + gpioregs->clear = EGPIO_codec_reset; + gpioregs->set = EGPIO_codec_reset; + + data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */; + L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, data, 1 ); + /* Reset done */ + + /* write uda 1341 status[1] */ + data[0] = 0x80 | 0x3<next != b->filling) { assert(b->next->nbytes); @@ -487,12 +505,12 @@ sendaudio(IOstat *b) { incref(&b->active); b->next++; if (b->next == &b->buf[Nbuf]) - b->next == &b->buf[0]; + b->next = &b->buf[0]; } } static void -audiointr(void *x, ulong state) { +audiointr(void *x, ulong) { IOstate *s = x; if (s == &audio.o) { @@ -500,14 +518,14 @@ audiointr(void *x, ulong state) { /* Only interrupt routine touches s->current */ s->current->nbytes = 0; s->current++; - if (b->current == &b->buf[Nbuf]) - b->current == &b->buf[0]; - if (canlock(s)) { + if (s->current == &s->buf[Nbuf]) + s->current = &s->buf[0]; + if (canlock((Lock*)s)) { sendaudio(s); - unlock(s); + unlock((Lock*)s); } } - wakeup(s->vous); + wakeup(&s->vous); } static Chan* @@ -554,7 +572,7 @@ audioopen(Chan *c, int omode) qunlock(&audio); error(Einuse); } - audiopower(1); + audioenable(); if (omode & Aread) { /* read */ audio.amode |= Aread; @@ -565,14 +583,14 @@ audioopen(Chan *c, int omode) } if (omode & 0x2) { /* write */ - amplifierpower(1); - audiomute(0); +// amplifierpower(1); +// audiomute(0); audio.amode |= Awrite; if(audio.o.bufinit == 0) bufinit(&audio.o); setempty(&audio.o); audio.o.chan = c; - &audio.o.dma = dmaalloc(0, 0, 8, 2, AudioDMA, void *port, void (*f)(int, ulong)) + audio.o.dma = dmaalloc(0, 0, 8, 2, AudioDMA, Port4MCP, audiointr, (void*)&audio.o); } qunlock(&audio); // mxvolume(); @@ -589,7 +607,6 @@ audioopen(Chan *c, int omode) static void audioclose(Chan *c) { - IOstate *b; switch(c->qid.path & ~CHDIR) { default: @@ -622,7 +639,7 @@ audioclose(Chan *c) } while(!audioidle(&audio.o)) sleep(&audio.o.vous, audioidle, &audio.o); - audioamplifier(0); + amplifierpower(0); setempty(&audio.o); } if (audio.i.chan == c) { @@ -648,7 +665,6 @@ audioread(Chan *c, void *v, long n, vlong off) int liv, riv, lov, rov; long m, n0; char buf[300]; - Buf *b; int j; ulong offset = off; char *a; @@ -722,7 +738,6 @@ audiowrite(Chan *c, void *vp, long n, vlong) long m, n0; int i, nf, v, left, right, in, out; char buf[255], *field[Ncmd]; - Buf *b; char *p; IOstate *a; @@ -759,7 +774,6 @@ audiowrite(Chan *c, void *vp, long n, vlong) audio.rovol[v] = m; if(right && in) audio.rivol[v] = m; - mxvolume(); goto cont0; } @@ -775,8 +789,8 @@ audiowrite(Chan *c, void *vp, long n, vlong) } if(strcmp(field[i], "reset") == 0) { - resetlevel(); - mxvolume(); +// resetlevel(); +// mxvolume(); goto cont0; } if(strcmp(field[i], "in") == 0) { @@ -816,13 +830,13 @@ audiowrite(Chan *c, void *vp, long n, vlong) } while(n > 0) { /* wait if dma in progress */ - while (a->active && a->filling == a->current) + while (a->active.ref && a->filling == a->current) sleep(&a->vous, audioqnotfull, a); m = Bufsize - a->filling->nbytes; if(m > n) m = n; - memmove(a->filling->buf + a->filling->nbytes, p, m); + memmove(a->filling->virt + a->filling->nbytes, p, m); a->filling->nbytes += m; n -= m; @@ -841,7 +855,7 @@ audiowrite(Chan *c, void *vp, long n, vlong) return n0 - n; } -Dev audiodevtab = { +Dev uda1341devtab = { 'A', "audio", diff --git a/bitsy/fns.h b/bitsy/fns.h index 81eaab1fde6a4cc80f05d6652bd310f880049a14..91f57f2bfa8440f97bdc28d859b55898a7007d4a 100644 --- a/bitsy/fns.h +++ b/bitsy/fns.h @@ -1,5 +1,8 @@ #include "../port/portfns.h" +void amplifierpower(int); +void audiopower(int); +void audiomute(int); void cacheflush(void); void cachewb(void); void cachewbaddr(void*); @@ -11,6 +14,7 @@ void clockinit(void); #define coherence() void delay(int); void µdelay(int); +void dmainit(void); void evenaddr(ulong); void flushmmu(void); int fpiarm(Ureg *ur); diff --git a/bitsy/io.h b/bitsy/io.h index 499bd3c033a100439c50ac64eb9d024fe2da7aeb..90044d97f0d7d994c6d6d206717e493e0a1e2e4f 100644 --- a/bitsy/io.h +++ b/bitsy/io.h @@ -76,6 +76,32 @@ enum GPIO_COM_CTS_i= 1<<25, /* CTS from UART3 */ GPIO_COM_RTS_o= 1<<26, /* RTS to UART3 */ GPIO_OPT_IND_i= 1<<27, /* expansion pack inserted */ +/* Peripheral Unit GPIO pin assignments: */ + GPIO_SSP_TXD_o= 1<<10, /* SSP Transmit Data */ + GPIO_SSP_RXD_i= 1<<11, /* SSP Receive Data */ + GPIO_SSP_SCLK_o= 1<<12, /* SSP Sample CLocK */ + GPIO_SSP_SFRM_o= 1<<13, /* SSP Sample FRaMe */ + /* ser. port 1: */ + GPIO_UART_TXD_o= 1<<14, /* UART Transmit Data */ + GPIO_UART_RXD_i= 1<<15, /* UART Receive Data */ + GPIO_SDLC_SCLK_io= 1<<16, /* SDLC Sample CLocK (I/O) */ + GPIO_SDLC_AAF_o= 1<<17, /* SDLC Abort After Frame */ + GPIO_UART_SCLK1_i= 1<<18, /* UART Sample CLocK 1 */ + /* ser. port 4: */ + GPIO_SSP_CLK_i= 1<<19, /* SSP external CLocK */ + /* ser. port 3: */ + GPIO_UART_SCLK3_i= 1<<20, /* UART Sample CLocK 3 */ + /* ser. port 4: */ + GPIO_MCP_CLK_i= 1<<21, /* MCP CLocK */ + /* test controller: */ + GPIO_TIC_ACK_o= 1<<21, /* TIC ACKnowledge */ + GPIO_MBGNT_o= 1<<21, /* Memory Bus GraNT */ + GPIO_TREQA_i= 1<<22, /* TIC REQuest A */ + GPIO_MBREQ_i= 1<<22, /* Memory Bus REQuest */ + GPIO_TREQB_i= 1<<23, /* TIC REQuest B */ + GPIO_1Hz_o= 1<<25, /* 1 Hz clock */ + GPIO_RCLK_o= 1<<26, /* internal (R) CLocK (O, fcpu/2) */ + GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */ }; enum diff --git a/bitsy/main.c b/bitsy/main.c index 819d74fabe12011b3eb6af10d41a05056fdd9d68..7883678ed20b1c17bbc12bfa7b9c3dccfc0146b2 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -14,6 +14,8 @@ Conf conf; int noprint; static void gpioinit(void); +static void ppcinit(void); +static void sspinit(void); void main(void) @@ -41,6 +43,7 @@ main(void) trapinit(); sa1100_uartsetup(1); rs232power(1); + dmainit(); screeninit(); printinit(); /* from here on, print works, before this we need iprint */ clockinit(); diff --git a/bitsy/sa1110dma.c b/bitsy/sa1110dma.c index 140300ddfcb607a4f196ecf6b6bbb1801f2646f1..368c3863d3a6ce00062e604a0b7385e651206ee1 100644 --- a/bitsy/sa1110dma.c +++ b/bitsy/sa1110dma.c @@ -38,16 +38,16 @@ enum { BIU = 7 }; -typedef struct Chan { +typedef struct DMAchan { int inuse; Rendez r; - void (*intr)(int, ulong); + void (*intr)(void*, ulong); void *param; -} Chan; +} DMAchan; struct { Lock; - Chan chan[6]; + DMAchan chan[6]; } dma; struct dmaregs { @@ -61,14 +61,21 @@ struct dmaregs { ulong dxcntB; } *dmaregs; +static void dmaintr(Ureg*, void *); + void dmainit(void) { + int i; + /* map the lcd regs into the kernel's virtual space */ dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));; + for (i = 0; i < NDMA; i++) { + intrenable(IRQdma0+i, dmaintr, &dmaregs[i], "DMA"); + } } int -dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *port, void (*intr)(int, ulong), void *param) { +dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong port, void (*intr)(void*, ulong), void *param) { int i; lock(&dma); @@ -110,7 +117,7 @@ dmastart(int chan, void *addr, int count) { if (((status = dmaregs[chan].dcsr_rd) & ((1<dcsr_rd) & (1<chaddr, 6) == 0 - && rp->htype == 1 && rp->hlen == 6 - && getfields((char*)rp->vend+4, field, 4, 1, " ") == 4 - && strncmp((char*)rp->vend, "p9 ", 4) == 0){ - if(ipaddr == 0) - ipaddr = nhgetl(rp->yiaddr); - if(ipmask == 0) - ipmask = parseip(ip, field[0]); - if(fsip == 0) - fsip = parseip(ip, field[1]); - if(auip == 0) - auip = parseip(ip, field[2]); - if(gwip == 0) - gwip = parseip(ip, field[3]); - break; - } - } - - recv = 1; - wakeup(&bootpr); - pexit("", 0); -} - -char* -bootp(Ipifc *ifc) -{ - int fd, tries, n; - char ia[5+3*16], im[16], *av[3]; - char nipaddr[4], ngwip[4], nipmask[4]; - - av[1] = "0.0.0.0"; - av[2] = "0.0.0.0"; - ipifcadd(ifc, av, 3); - - fd = kdial("udp!255.255.255.255!67", "68", nil, nil); - if(fd < 0) - return "bootp dial failed"; - - /* create request */ - memset(&req, 0, sizeof(req)); - req.op = Bootrequest; - req.htype = 1; /* ethernet (all we know) */ - req.hlen = 6; /* ethernet (all we know) */ - - /* Hardware MAC address */ - memmove(req.chaddr, ifc->mac, 6); - /* Fill in the local IP address if we know it */ - ipv4local(ifc, req.ciaddr); - memset(req.file, 0, sizeof(req.file)); - strcpy((char*)req.vend, "p9 "); - - kproc("rcvbootp", rcvbootp, (void*)fd); - - /* - * broadcast bootp's till we get a reply, - * or fixed number of tries - */ - tries = 0; - while(recv == 0) { - if(kwrite(fd, &req, sizeof(req)) < 0) - print("bootp: write: %r"); - - tsleep(&bootpr, return0, 0, 1000); - if(++tries > 10) { - print("bootp: timed out\n"); - break; - } - } - kclose(fd); - done = 1; - - av[1] = "0.0.0.0"; - av[2] = "0.0.0.0"; - ipifcrem(ifc, av, 3, 1); - - hnputl(nipaddr, ipaddr); - sprint(ia, "%V", nipaddr); - hnputl(nipmask, ipmask); - sprint(im, "%V", nipmask); - av[1] = ia; - av[2] = im; - ipifcadd(ifc, av, 3); - - if(gwip != 0) { - hnputl(ngwip, gwip); - n = sprint(ia, "add 0.0.0.0 0.0.0.0 %V", ngwip); - routewrite(ifc->conv->p->f, nil, ia, n); - } - return nil; -} - -int -bootpread(char *bp, ulong offset, int len) -{ - int n; - char buf[bootpreadlen], a[4]; - - hnputl(a, fsip); - n = sprint(buf, "fsip %15V\n", a); - hnputl(a, auip); - n += sprint(buf + n, "auip %15V\n", a); - hnputl(a, gwip); - n += sprint(buf + n, "gwip %15V\n", a); - hnputl(a, ipmask); - n += sprint(buf + n, "ipmask %15V\n", a); - hnputl(a, ipaddr); - sprint(buf + n, "ipaddr %15V\n", a); - - return readstr(offset, bp, len, buf); -} diff --git a/ip/dial.c b/ip/chandial.c similarity index 74% rename from ip/dial.c rename to ip/chandial.c index 7e1b6d1f05c6ff4f140be70d2875a6e1d0e67c1e..f14c1c7e4ab1245c2a5f76edb3b48ce53ce50508 100644 --- a/ip/dial.c +++ b/ip/chandial.c @@ -4,10 +4,9 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" -#include "kernel.h" typedef struct DS DS; -static int call(char*, char*, DS*); +static Chan* call(char*, char*, DS*); static void _dial_string_parse(char*, DS*); enum @@ -24,21 +23,21 @@ struct DS char *rem; char *local; /* other args */ char *dir; - int *cfdp; + Chan **ctlp; }; /* * the dialstring is of the form '[/net/]proto!dest' */ -int -kdial(char *dest, char *local, char *dir, int *cfdp) +Chan* +chandial(char *dest, char *local, char *dir, Chan **ctlp) { DS ds; char clone[Maxpath]; ds.local = local; ds.dir = dir; - ds.cfdp = cfdp; + ds.ctlp = ctlp; _dial_string_parse(dest, &ds); if(ds.netdir == 0) @@ -49,24 +48,21 @@ kdial(char *dest, char *local, char *dir, int *cfdp) return call(clone, ds.rem, &ds); } -static int +static Chan* call(char *clone, char *dest, DS *ds) { - int fd, cfd, n; + int n; + Chan *dchan, *cchan; char name[3*NAMELEN+5], data[3*NAMELEN+10], *p; - cfd = kopen(clone, ORDWR); - if(cfd < 0){ - kwerrstr("%s: %r", clone); - return -1; - } + cchan = namec(clone, Aopen, ORDWR, 0); /* get directory name */ - n = kread(cfd, name, sizeof(name)-1); - if(n < 0){ - kclose(cfd); - return -1; + if(waserror()){ + cclose(cchan); + nexterror(); } + n = devtab[cchan->type]->read(cchan, name, sizeof(name)-1, 0); name[n] = 0; for(p = name; *p == ' '; p++) ; @@ -82,24 +78,16 @@ call(char *clone, char *dest, DS *ds) snprint(name, sizeof(name), "connect %s %s", dest, ds->local); else snprint(name, sizeof(name), "connect %s", dest); - if(kwrite(cfd, name, strlen(name)) < 0){ - kwerrstr("%s failed: %r", name); - kclose(cfd); - return -1; - } + devtab[cchan->type]->write(cchan, name, strlen(name), 0); /* open data connection */ - fd = kopen(data, ORDWR); - if(fd < 0){ - kwerrstr("can't open %s: %r", data); - kclose(cfd); - return -1; - } - if(ds->cfdp) - *ds->cfdp = cfd; + dchan = namec(data, Aopen, ORDWR, 0); + if(ds->ctlp) + *ds->ctlp = cchan; else - kclose(cfd); - return fd; + cclose(cchan); + poperror(); + return dchan; } diff --git a/ip/ethermedium.c b/ip/ethermedium.c index dc3870a27e6a54ed80dcb176f7a228e2929976ed..96ba2fe367f12c04461c35bd71619e2b343066d4 100644 --- a/ip/ethermedium.c +++ b/ip/ethermedium.c @@ -6,7 +6,6 @@ #include "../port/error.h" #include "ip.h" -#include "kernel.h" typedef struct Etherhdr Etherhdr; struct Etherhdr @@ -110,7 +109,7 @@ etherbind(Ipifc *ifc, int argc, char **argv) char addr[2*NAMELEN]; char dir[2*NAMELEN]; char *buf; - int fd, cfd, n; + int n; char *ptr; Etherrock *er; @@ -138,27 +137,16 @@ etherbind(Ipifc *ifc, int argc, char **argv) * this device. */ snprint(addr, sizeof(addr), "%s!0x800", argv[2]); - fd = kdial(addr, nil, dir, &cfd); - if(fd < 0) - error("dial 0x800 failed"); - mchan = commonfdtochan(fd, ORDWR, 0, 1); - cchan = commonfdtochan(cfd, ORDWR, 0, 1); - kclose(fd); - kclose(cfd); + mchan = chandial(addr, nil, dir, &cchan); /* * get mac address */ snprint(addr, sizeof(addr), "%s/stats", dir); - fd = kopen(addr, OREAD); - if(fd < 0) - error("can't read ether stats"); - buf = smalloc(512); - n = kread(fd, buf, 511); - kclose(fd); - if(n <= 0) - error(Eio); + achan = namec(addr, Aopen, OREAD, 0); + n = devtab[achan->type]->read(achan, buf, 511, 0); + cclose(achan); buf[n] = 0; ptr = strstr(buf, "addr: "); @@ -172,11 +160,7 @@ etherbind(Ipifc *ifc, int argc, char **argv) * open arp conversation */ snprint(addr, sizeof(addr), "%s!0x806", argv[2]); - fd = kdial(addr, nil, nil, nil); - if(fd < 0) - error("dial 0x806 failed"); - achan = commonfdtochan(fd, ORDWR, 0, 1); - kclose(fd); + achan = chandial(addr, nil, nil, nil); er = smalloc(sizeof(*er)); er->mchan = mchan; diff --git a/ip/ihbootp.c b/ip/ihbootp.c deleted file mode 100644 index 9a275940471a4586b971f032197a7a0c4fc3ca05..0000000000000000000000000000000000000000 --- a/ip/ihbootp.c +++ /dev/null @@ -1,259 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "kernel.h" -#include "ip.h" - -static ulong fsip; -static ulong auip; -static ulong gwip; -static ulong ipmask; -static ulong ipaddr; - -uchar sys[NAMELEN]; - -enum -{ - Bootrequest = 1, - Bootreply = 2, -}; - -typedef struct Bootp -{ - uchar op; /* opcode */ - uchar htype; /* hardware type */ - uchar hlen; /* hardware address len */ - uchar hops; /* hops */ - uchar xid[4]; /* a random number */ - uchar secs[2]; /* elapsed snce client started booting */ - uchar pad[2]; - uchar ciaddr[4]; /* client IP address (client tells server) */ - uchar yiaddr[4]; /* client IP address (server tells client) */ - uchar siaddr[4]; /* server IP address */ - uchar giaddr[4]; /* gateway IP address */ - uchar chaddr[16]; /* client hardware address */ - uchar sname[64]; /* server host name (optional) */ - uchar file[128]; /* boot file name */ - uchar vend[128]; /* vendor-specific goo */ -} Bootp; - -/* - * bootp returns: - * - * "fsip d.d.d.d - * auip d.d.d.d - * gwip d.d.d.d - * ipmask d.d.d.d - * ipaddr d.d.d.d" - * - * where d.d.d.d is the IP address in dotted decimal notation, and each - * address is followed by a newline. - */ -enum -{ - bootpreadlen = sizeof("fsip") + sizeof("auip") + sizeof("gwip") - + sizeof("ipmask") + sizeof("ipaddr") - + 5 * sizeof("000.000.000.000") + sizeof("") -}; - -static Bootp req; -static int recv; -static int done; -static Rendez bootpr; -static char rcvbuf[512]; - - -/* - * Parse the vendor specific fields according to RFC 1084. - * We are overloading the "cookie server" to be the Inferno - * authentication server and the "resource location server" - * to be the Inferno file server. - * - * If the vendor specific field is formatted properly, it - * will being with the four bytes 99.130.83.99 and end with - * an 0xFF byte. - */ -static void -parsevend(uchar* vend) -{ - /* The field must start with 99.130.83.99 to be compliant */ - if ((vend[0] != 99) || (vend[1] != 130) || - (vend[2] != 83) || (vend[3] != 99)) - return; - - /* Skip over the magic cookie */ - vend += 4; - - while ((vend[0] != 0) && (vend[0] != 0xFF)) { - switch (vend[0]) { - case 1: /* Subnet mask field */ - /* There must be only on subnet mask */ - if (vend[1] != 4) - return; - - ipmask = (vend[2]<<24)| - (vend[3]<<16)| - (vend[4]<<8)| - vend[5]; - break; - - case 3: /* Gateway/router field */ - /* We are only concerned with first address */ - if (vend[1] < 4) - return; - - gwip = (vend[2]<<24)| - (vend[3]<<16)| - (vend[4]<<8)| - vend[5]; - break; - - case 8: /* "Cookie server" (auth server) field */ - /* We are only concerned with first address */ - if (vend[1] < 4) - return; - - auip = (vend[2]<<24)| - (vend[3]<<16)| - (vend[4]<<8)| - vend[5]; - break; - - case 11: /* "Resource loc server" (file server) field */ - /* We are only concerned with first address */ - if (vend[1] < 4) - return; - - fsip = (vend[2]<<24)| - (vend[3]<<16)| - (vend[4]<<8)| - vend[5]; - break; - - default: /* Everything else stops us */ - return; - } - - /* Skip over the field */ - vend += vend[1] + 2; - } -} - -void -rcvbootp(void *a) -{ - int n, fd; - Bootp *rp; - - fd = (int)a; - while(done == 0) { - n = kread(fd, rcvbuf, sizeof(rcvbuf)); - if(n <= 0) - break; - rp = (Bootp*)rcvbuf; - if (memcmp(req.chaddr, rp->chaddr, 6) == 0 && - rp->htype == 1 && rp->hlen == 6) { - ipaddr = (rp->yiaddr[0]<<24)| - (rp->yiaddr[1]<<16)| - (rp->yiaddr[2]<<8)| - rp->yiaddr[3]; - parsevend(rp->vend); - break; - } - } - - recv = 1; - wakeup(&bootpr); - pexit("", 0); -} - -char* -bootp(Ipifc *ifc) -{ - int fd, tries, n; - char ia[5+3*16], im[16], *av[3]; - char nipaddr[4], ngwip[4], nipmask[4]; - - av[1] = "0.0.0.0"; - av[2] = "0.0.0.0"; - ipifcadd(ifc, av, 3); - - fd = kdial("udp!255.255.255.255!67", "68", nil, nil); - if(fd < 0) - return "bootp dial failed"; - - /* create request */ - memset(&req, 0, sizeof(req)); - req.op = Bootrequest; - req.htype = 1; /* ethernet (all we know) */ - req.hlen = 6; /* ethernet (all we know) */ - - /* Hardware MAC address */ - memmove(req.chaddr, ifc->mac, 6); - /* Fill in the local IP address if we know it */ - ipv4local(ifc, req.ciaddr); - memset(req.file, 0, sizeof(req.file)); - strcpy((char*)req.vend, "p9 "); - - kproc("rcvbootp", rcvbootp, (void*)fd); - - /* - * broadcast bootp's till we get a reply, - * or fixed number of tries - */ - tries = 0; - while(recv == 0) { - if(kwrite(fd, &req, sizeof(req)) < 0) - print("bootp: write: %r"); - - tsleep(&bootpr, return0, 0, 1000); - if(++tries > 10) { - print("bootp: timed out\n"); - break; - } - } - kclose(fd); - done = 1; - - av[1] = "0.0.0.0"; - av[2] = "0.0.0.0"; - ipifcrem(ifc, av, 3, 1); - - hnputl(nipaddr, ipaddr); - sprint(ia, "%V", nipaddr); - hnputl(nipmask, ipmask); - sprint(im, "%V", nipmask); - av[1] = ia; - av[2] = im; - ipifcadd(ifc, av, 3); - - if(gwip != 0) { - hnputl(ngwip, gwip); - n = sprint(ia, "add 0.0.0.0 0.0.0.0 %V", ngwip); - routewrite(ifc->conv->p->f, nil, ia, n); - } - return nil; -} - -int -bootpread(char *bp, ulong offset, int len) -{ - int n; - char buf[bootpreadlen], a[4]; - - hnputl(a, fsip); - n = sprint(buf, "fsip %15V\n", a); - hnputl(a, auip); - n += sprint(buf + n, "auip %15V\n", a); - hnputl(a, gwip); - n += sprint(buf + n, "gwip %15V\n", a); - hnputl(a, ipmask); - n += sprint(buf + n, "ipmask %15V\n", a); - hnputl(a, ipaddr); - sprint(buf + n, "ipaddr %15V\n", a); - - return readstr(offset, bp, len, buf); -} diff --git a/ip/ip.c b/ip/ip.c index 07d7c6f6aab3a5df62e9cabbd262a075d22266e9..c06261eb1360d5dc924e06c6f44133df21248502 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -5,7 +5,7 @@ #include "fns.h" #include "../port/error.h" -#include "ip.h" +#include "../ip/ip.h" typedef struct Iphdr Iphdr; typedef struct Fragment Fragment; diff --git a/ip/ip.h b/ip/ip.h index ef1b2f8887d5a75aa63c2437bf44e6048af48923..f6cc73df1d13403f925d8fa9f061486736ffef72 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -504,6 +504,11 @@ Chan* commonfdtochan(int, int, int, int); char* commonuser(void); char* commonerror(void); +/* + * chandial.c + */ +extern Chan* chandial(char*, char*, char*, Chan**); + /* * global to all of the stack */ diff --git a/ip/ipaux.c b/ip/ipaux.c index 3021fe60130fbb92977692a8991f81cf0eef3fca..480fd08056a726f02c81f07cae637c8212502ed9 100644 --- a/ip/ipaux.c +++ b/ip/ipaux.c @@ -4,7 +4,6 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" -#include "kernel.h" #include "ip.h" /* diff --git a/ip/ipifc.c b/ip/ipifc.c index 85464b69eda08bc0b93e8a882720e2bf630364e9..a4dc34097654f33d45a08d5281df692d2a4591f0 100644 --- a/ip/ipifc.c +++ b/ip/ipifc.c @@ -630,8 +630,6 @@ ipifcctl(Conv* c, char**argv, int argc) ifc = (Ipifc*)c->ptcl; if(strcmp(argv[0], "add") == 0) return ipifcadd(ifc, argv, argc); - else if(strcmp(argv[0], "bootp") == 0) - return bootp(ifc); else if(strcmp(argv[0], "remove") == 0) return ipifcrem(ifc, argv, argc, 1); else if(strcmp(argv[0], "unbind") == 0) diff --git a/ip/kernel.h b/ip/kernel.h deleted file mode 100644 index 82e3cbfb3e49a2585cae04a3982cc018335622e0..0000000000000000000000000000000000000000 --- a/ip/kernel.h +++ /dev/null @@ -1,15 +0,0 @@ -extern long kclose(int); -extern int kdial(char*, char*, char*, int*); -extern void kerrstr(char*); -extern void kgerrstr(char*); -extern long kopen(char*, int); -extern long kread(int, void*, long); -extern long kseek(int, vlong, int); -extern long kwrite(int, void*, long); -extern void kwerrstr(char *, ...); - -extern char* strdup(char*); -extern char* strrchr(char*, char); -extern char* strstr(char*, char*); - -extern int newfd(Chan*); diff --git a/ip/kio.c b/ip/kio.c deleted file mode 100644 index a80352cba034650f50a1c5410bb409554afb0e3f..0000000000000000000000000000000000000000 --- a/ip/kio.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "kernel.h" - -#define validaddr(a, b, c) - -long -kclose(int fd) -{ - if(waserror()) - return -1; - /* - * Take no reference on the chan because we don't really need the - * data structure, and are calling fdtochan only for error checks. - * fdclose takes care of processes racing through here. - */ - fdtochan(fd, -1, 0, 0); - fdclose(fd, 0); - - poperror(); - return 0; -} - -long -kopen(char *path, int mode) -{ - int fd; - Chan *c = 0; - - if(waserror()) { - if(c) - cclose(c); - return -1; - } - - openmode(mode); - validaddr((ulong)path, 1, 0); - c = namec(path, Aopen, mode, 0); - fd = newfd(c); - - poperror(); - return fd; -} - -long -kread(int fd, void *va, long n) -{ - int dir; - Chan *c; - - if(waserror()) - return -1; - - validaddr((ulong)va, n, 1); - c = fdtochan(fd, OREAD, 1, 1); - if(waserror()) { - cclose(c); - nexterror(); - } - - dir = c->qid.path&CHDIR; - if(dir) { - n -= n%DIRLEN; - if(c->offset%DIRLEN || n==0) - error(Etoosmall); - } - - if(dir && c->mh) - n = unionread(c, va, n); - else if(devtab[c->type]->dc != L'M') - n = devtab[c->type]->read(c, va, n, c->offset); - else - n = mntread9p(c, va, n, c->offset); - - lock(c); - c->offset += n; - unlock(c); - - poperror(); - cclose(c); - - poperror(); - return n; -} - -long -kseek(int fd, vlong offset, int whence) -{ - Chan *c; - char buf[DIRLEN]; - Dir dir; - long off; - - if(waserror()) - return -1; - - c = fdtochan(fd, -1, 1, 1); - if(waserror()) { - cclose(c); - nexterror(); - } - if(c->qid.path & CHDIR) - error(Eisdir); - - if(devtab[c->type]->dc == '|') - error(Eisstream); - - off = 0; - switch(whence) { - case 0: - off = offset; - c->offset = offset; - break; - case 1: - lock(c); /* lock for read/write update */ - c->offset += offset; - off = c->offset; - unlock(c); - break; - case 2: - devtab[c->type]->stat(c, buf); - convM2D(buf, &dir); - c->offset = dir.length + offset; - off = c->offset; - break; - } - poperror(); - cclose(c); - poperror(); - return off; -} - -long -kwrite(int fd, void *va, long n) -{ - Chan *c; - - if(waserror()) - return -1; - - validaddr((ulong)va, n, 0); - c = fdtochan(fd, OWRITE, 1, 1); - if(waserror()) { - cclose(c); - nexterror(); - } - - if(c->qid.path & CHDIR) - error(Eisdir); - - n = devtab[c->type]->write(c, va, n, c->offset); - - lock(c); - c->offset += n; - unlock(c); - - poperror(); - cclose(c); - - poperror(); - return n; -} - -/* Set kernel error string */ -void -kerrstr(char *err) -{ - if(up != nil) - strncpy(up->error, err, ERRLEN); -} - -/* Get kernel error string */ -void -kgerrstr(char *err) -{ - char *s; - - s = ""; - if(up != nil) - s = up->error; - strncpy(err, s, ERRLEN); -} - -/* Set kernel error string, using formatted print */ -void -kwerrstr(char *fmt, ...) -{ - va_list arg; - char buf[256]; - - va_start(arg, fmt); - doprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - strncpy(up->error, buf, ERRLEN); -} diff --git a/ip/netdevmedium.c b/ip/netdevmedium.c index e80007f4c08cb20cde04bf189b8c4f6d7c91566f..aa2539bb24e7346ad4dfea1cc973d34ba529a91f 100644 --- a/ip/netdevmedium.c +++ b/ip/netdevmedium.c @@ -6,7 +6,6 @@ #include "../port/error.h" #include "ip.h" -#include "kernel.h" static void netdevbind(Ipifc *ifc, int argc, char **argv); static void netdevunbind(Ipifc *ifc); @@ -41,19 +40,13 @@ Medium netdevmedium = static void netdevbind(Ipifc *ifc, int argc, char **argv) { - int fd; Chan *mchan; Netdevrock *er; if(argc < 2) error(Ebadarg); - fd = kopen(argv[2], ORDWR); - if(fd < 0) - error("fd open failed"); - - mchan = commonfdtochan(fd, ORDWR, 0, 1); - kclose(fd); + mchan = namec(argv[2], Aopen, ORDWR, 0); er = smalloc(sizeof(*er)); er->mchan = mchan; diff --git a/ip/nullmedium.c b/ip/nullmedium.c index 7795a2f1b16bae874ba3f1945fe77dfa1eb74302..1f39da3ba45d62ab303589d8dd663959f23cbd69 100644 --- a/ip/nullmedium.c +++ b/ip/nullmedium.c @@ -6,7 +6,6 @@ #include "../port/error.h" #include "ip.h" -#include "kernel.h" static void nullbind(Ipifc*, int, char**) diff --git a/ip/pktmedium.c b/ip/pktmedium.c index f044c1c868e31c0320a9b59f1b19949cad62828b..7a92e5601355eb41a60858059112263b0b883172 100644 --- a/ip/pktmedium.c +++ b/ip/pktmedium.c @@ -6,7 +6,6 @@ #include "../port/error.h" #include "ip.h" -#include "kernel.h" static void pktbind(Ipifc *ifc, int argc, char **argv); diff --git a/ip/plan9.c b/ip/plan9.c deleted file mode 100644 index 6c5b3492631ad4ac271da41aea7a204c8de50e3a..0000000000000000000000000000000000000000 --- a/ip/plan9.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "ip.h" - -/* - * some hacks for commonality twixt inferno and plan9 - */ - -char* -commonuser(void) -{ - return up->env->user; -} - -Chan* -commonfdtochan(int fd, int mode, int a, int b) -{ - return fdtochan(up->env->fgrp, fd, mode, a, b); -} - -char* -commonerror(void) -{ - return up->env->error; -} - -int -postnote(Proc*, char*) -{ - return -1; -} diff --git a/ip/ptclbsum.c b/ip/ptclbsum.c index 8f822e5f54279739ddf68fcadc117faa1e9a7be7..4b895ecff13b446623fbe40ee45649e46e1b7762 100644 --- a/ip/ptclbsum.c +++ b/ip/ptclbsum.c @@ -4,7 +4,6 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" -#include "kernel.h" #include "ip.h" static short endian = 1; diff --git a/ip/tripmedium.c b/ip/tripmedium.c index c96f9bdaef36235886d127d7a4b3f3fd514d0490..ec96661fde78918d8ae7c9b1f4059ea87ea5092e 100644 --- a/ip/tripmedium.c +++ b/ip/tripmedium.c @@ -7,7 +7,6 @@ #include "ip.h" #include "trip.h" -#include "kernel.h" static void tripread(void *a); static void tripbind(Ipifc *ifc, int argc, char **argv); diff --git a/mpc/fns.h b/mpc/fns.h index 3f7e9237786ffd38ce52982c8940188294ed14ca..fcfa7ad6071ef71b56f6977b609df0b6e7c93169 100644 --- a/mpc/fns.h +++ b/mpc/fns.h @@ -10,7 +10,7 @@ void clockcheck(void); void clockinit(void); void clockintr(Ureg*); void clrfptrap(void); -#define coherence() // not need on single processor machines +#define coherence() void cpminit(void); int cpuidentify(void); void cpuidprint(void); @@ -88,7 +88,7 @@ ulong rmapalloc(RMap*, ulong, int, int); void screeninit(void); void setpanic(void); int screenprint(char*, ...); /* debugging */ -#define screenputs(x, y) // no screen +#define screenputs(x, y) ulong sdraminit(ulong*); int segflush(void*, ulong); void spireset(void); diff --git a/pc/devi82365.c b/pc/devi82365.c index 520218dd110554eb2cb8ac0cfb57ed2dd6b623a6..4ca157561087fc99c4f86d668a101ed9dd81b801 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -1027,7 +1027,7 @@ pcmio(int slotno, ISAConf *isa) /* route interrupts */ isa->irq = irq; wrreg(pp, Rigc, irq | Fnotreset | Fiocard); - + /* set power and enable device */ x = vcode(ct->vpp1); wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); diff --git a/port/lib.h b/port/lib.h index a5ac58e6c3450e958e62c5931c3724cfccf9a6e1..b376ada795293c2da680ff9ca950a0c483d3c5c5 100644 --- a/port/lib.h +++ b/port/lib.h @@ -23,6 +23,7 @@ extern char *strncat(char*, char*, long); extern char *strncpy(char*, char*, long); extern int strncmp(char*, char*, long); extern long strlen(char*); +extern char* strstr(char*, char*); extern int atoi(char*); enum