int nec78k_cwrite(ASPP *bus, unsigned char *data, int len) { // continuous flash writing int retries,i; unsigned long delayWrite; unsigned char status; time_t start=time(NULL); nec78k_cwrite_top: aspp_LEDcpl(bus); // complement LED output microdelay(nec->TimeAckCom); // wait before start this procedure for (retries=0;retries<16;retries++) { nec_spiwrite(bus,0x44); microdelay(nec->TimeComAck); status=nec_spiread(bus); microdelay(nec->TimeAckData); if (status==0x3c) break; } if (retries==16) return -1; if (debugmsg) fprintf(stderr,"DEBUG: CWRITE: [%02lu] continuous write %d data\n",time(NULL)-start,len); for (i=0;i<len;i++) { // write data.... if (debugmsg) { if ((i%4)==0) fprintf(stderr,"."); } microdelay(nec->TimeDataData); nec_spiwrite(bus,data[i]); } if (debugmsg) fprintf(stderr,"\n"); microdelay(nec->TimeDataAck); status=nec_spiread(bus); // read ack: what can i do if NACK? if (status!=0x3c) { if (debugmsg) fprintf(stderr,"DEBUG: CWRITE: data was written to the SPI, status=0x%02x. Restart cwrite()\n",status); microdelay(1000); goto nec78k_cwrite_top; } delayWrite=nec->TimeWrite+(nec->ClkWrite*len)*1000/cpuclock+10; for (retries=1;retries<=16;retries++) { if (debugmsg) fprintf(stderr,"DEBUG: CWRITE: [%02lu] wait for write time (%luus)\n",time(NULL)-start,delayWrite); microdelay(delayWrite); // Empiric formula similar to the given by Nec Flashprogramming Datasheet nec_spiwrite(bus,0x70); //Request status microdelay(nec->TimeComAck); nec_spiread(bus); microdelay(nec->TimeAckData); status=nec_spiread(bus); // status microdelay(nec->TimeDataAck); nec_spiread(bus); if (status&0x40) { if (debugmsg) fprintf(stderr,"DEBUG: CWRITE: [%02lu] continuous write in progress (status=0x%02x)\n",time(NULL)-start,status); continue; // write in progress.... } else if (status&0x04) { if (debugmsg) fprintf(stderr,"DEBUG: CWRITE: [%02lu] continuous write error (status=0x%02x)\n",time(NULL)-start,status); return -1; // write error } else break; } return (retries==17); }
// Start additional processor running entry code at addr. // See Appendix B of MultiProcessor Specification. void lapicstartap(uchar apicid, uint addr) { int i; ushort *wrv; // "The BSP must initialize CMOS shutdown code to 0AH // and the warm reset vector (DWORD based at 40:67) to point at // the AP startup code prior to the [universal startup algorithm]." outb(CMOS_PORT, 0xF); // offset 0xF is shutdown code outb(CMOS_PORT+1, 0x0A); wrv = (ushort*)P2V((0x40<<4 | 0x67)); // Warm reset vector wrv[0] = 0; wrv[1] = addr >> 4; // "Universal startup algorithm." // Send INIT (level-triggered) interrupt to reset other CPU. lapicw(ICRHI, apicid<<24); lapicw(ICRLO, INIT | LEVEL | ASSERT); microdelay(200); lapicw(ICRLO, INIT | LEVEL); microdelay(100); // should be 10ms, but too slow in Bochs! // Send startup IPI (twice!) to enter code. // Regular hardware is supposed to only accept a STARTUP // when it is in the halted state due to an INIT. So the second // should be ignored, but it is part of the official Intel algorithm. // Bochs complains about the second one. Too bad for Bochs. for(i = 0; i < 2; i++){ lapicw(ICRHI, apicid<<24); lapicw(ICRLO, STARTUP | (addr>>12)); microdelay(200); } }
int nec78k_setosc(ASPP *bus) { // set target oscillator frequency int retries; unsigned char status; printf("Set oscillator frequency...\n"); aspp_LEDcpl(bus); // complement LED output microdelay(nec->TimeAckCom); // wait before start this procedure for (retries=0;retries<16;retries++) { microdelay(1000); nec_spiwrite(bus,0x90); microdelay(nec->TimeComAck); if (nec_spiread(bus)!=0x3c) continue; microdelay(nec->TimeAckData); nec_spiwrite(bus,(cpuclock/1000)%10); microdelay(nec->TimeDataData); nec_spiwrite(bus,(cpuclock/100)%10); microdelay(nec->TimeDataData); nec_spiwrite(bus,(cpuclock/10)%10); microdelay(nec->TimeDataData); nec_spiwrite(bus,4); microdelay(nec->TimeFrqCalc); status=nec_spiread(bus); microdelay(nec->TimeAckData); if (status==0x3c) break; } return (retries==16); }
void nec_spiwrite(ASPP *bus, unsigned char data) { // write 8 bit to 3-wire serial interface at half speed (500Kbps) int i; for (i=0;i<8;i++) { aspp_SCK(bus,0); aspp_MOSI(bus,data&0x80); microdelay(1); aspp_SCK(bus,1); microdelay(3); data<<=1; } }
static unsigned char eeprom_pulse(unsigned char di) { unsigned char buf; EEPROM_DI = di; EEPROM_SK = EEPROM_HIGH; microdelay(); buf = EEPROM_DO; EEPROM_SK = EEPROM_LOW; EEPROM_DI = EEPROM_LOW; microdelay(); return buf; }
void nec78k_poweron(ASPP *bus) { // Enable power supply to Nec 78k0 and 78k0S printf("Turn on power supply...\n"); aspp_VCC(bus,1); aspp_LED(bus,1); // turn on LED microdelay(200000); // Let external reset turn off pull-down aspp_VPP5(bus,1); aspp_VPP10(bus,1); aspp_SCK(bus,1); microdelay(2000); aspp_RESET(bus,1); microdelay(2000); // No VPP pulses for 3-wire interface }
unsigned char nec_spiread(ASPP *bus) { // read 8 bit from 3-wire serial interface at half speed (500Kbps) int i; unsigned char data; for (i=0;i<8;i++) { data<<=1; aspp_SCK(bus,0); microdelay(1); aspp_SCK(bus,1); microdelay(1); data|=aspp_MISO(bus); } return data; }
void gpiopulloff(uint pin) { u32int *gp, *reg; u32int mask; gp = (u32int*)GPIOREGS; reg = &gp[PUDclk0 + pin/32]; mask = 1 << (pin % 32); gp[PUD] = Off; microdelay(1); *reg = mask; microdelay(1); *reg = 0; }
void gpiopullset(uint pin, int state) { u32int *gp, *reg; u32int mask; gp = (u32int*)GPIOREGS; reg = &gp[PUDclk0 + pin/32]; mask = 1 << (pin % 32); gp[PUD] = state; microdelay(1); *reg = mask; microdelay(1); *reg = 0; }
/* * send a command to the floppy */ static int floppycmd(void) { int i; int tries; fl.nstat = 0; for(i = 0; i < fl.ncmd; i++) { for(tries = 0; ; tries++) { if((inb(Pmsr)&(Ffrom|Fready)) == Fready) break; if(tries > 1000) { DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i); fldump(); /* empty fifo, might have been a bad command */ floppyresult(); return -1; } microdelay(1); } outb(Pfdata, fl.cmd[i]); } return 0; }
/* * get a command result from the floppy * * when the controller goes ready waiting for a command * (instead of sending results), we're done * */ static int floppyresult(void) { int i, s; int tries; /* get the result of the operation */ for(i = 0; i < sizeof(fl.stat); i++) { /* wait for status byte */ for(tries = 0; ; tries++) { s = inb(Pmsr)&(Ffrom|Fready); if(s == Fready) { fl.nstat = i; return fl.nstat; } if(s == (Ffrom|Fready)) break; if(tries > 1000) { DPRINT("floppyresult: %d stats\n", i); fldump(); fl.confused = 1; return -1; } microdelay(1); } fl.stat[i] = inb(Pfdata); } fl.nstat = sizeof(fl.stat); return fl.nstat; }
static void squidboy(Apic* apic) { // iprint("Hello Squidboy\n"); machinit(); mmuinit(); cpuidentify(); cpuidprint(); checkmtrr(); lock(&mprdthilock); mprdthi |= (1<<apic->apicno)<<24; unlock(&mprdthilock); lapicinit(apic); lapiconline(); syncclock(); timersinit(); fpoff(); lock(&active); active.machs |= 1<<m->machno; unlock(&active); while(!active.thunderbirdsarego) microdelay(100); schedinit(); }
void uartputc(int c) { int i; if(!uart) return; for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++) microdelay(10); if (c==KEY_LF) { outb(COM1+0, 27); outb(COM1+0, 91); outb(COM1+0, 68); } else if (c==KEY_RT) { outb(COM1+0, 27); outb(COM1+0, 91); outb(COM1+0, 67); } else if (c==0x100) { outb(COM1+0, '\b'); outb(COM1+0, 27); outb(COM1+0, 91); outb(COM1+0, 80); } else { outb(COM1+0, c); } }
static uint cmos_read(uint reg) { outb(CMOS_PORT, reg); microdelay(200); return inb(CMOS_RETURN); }
static void squidboy(Apic* apic) { // iprint("Hello Squidboy\n"); machinit(); fpsavealloc(); mmuinit(); cpuidentify(); cpuidprint(); checkmtrr(); apic->online = 1; coherence(); lapicinit(apic); lapiconline(); syncclock(); timersinit(); fpoff(); lock(&active); active.machs |= 1<<m->machno; unlock(&active); while(!active.thunderbirdsarego) microdelay(100); schedinit(); }
static void axpcc(Cc* cc, int cmd) { Ccb *ccb; int timeo; u16int cs; ccb = cc->ccb; ccb->cc = cmd; if(!cc->ctlr->im) for(timeo = 0; timeo < 1000000; timeo++){ if(!ccb->cc) break; microdelay(1); } else tsleep(cc, axpccdone, ccb, 1000); cs = ccb->cs; if(ccb->cc || cs){ print("%s: cmd %#ux didn't terminate: %#ux %#ux\n", cc->name, cmd, ccb->cc, cs); if(cc->ctlr->im) error(Eio); } }
static void greset(Dwcregs *r, int bits) { r->grstctl |= bits; while(r->grstctl & bits) ; microdelay(10); }
int nec78k_sync(ASPP *bus) { // send reset command to syncronyze communication int retries; unsigned int delayComAck=1240000/cpuclock+40; printf("Syncing device...\n"); aspp_LEDcpl(bus); // complement LED output for (retries=0;retries<16; retries++) { nec_spiwrite(bus,0); microdelay(delayComAck); if (nec_spiread(bus)==0x3c) break; microdelay(delayComAck); } microdelay(delayComAck); return (retries==16); // return 1 if i got acknowledge (ERROR) }
void halt(void) { print("cpu halted\n"); microdelay(1000); for(;;) ; }
void halt(void) { spllo(); print("cpu halted\n"); microdelay(500); for(;;); }
int nec78k_seterase(ASPP *bus) { // set target erase time int retries; printf("Set erase time...\n"); aspp_LEDcpl(bus); // complement LED output microdelay(nec->TimeAckCom); // wait before start this procedure for (retries=0;retries<16;retries++) { nec_spiwrite(bus,0x95); microdelay(nec->TimeComAck); if (nec_spiread(bus)==0x3c) { break; } } if (retries==16) { if (debugmsg) fprintf(stderr,"Error sending SETERASE command\n"); return -1; } microdelay(nec->TimeAckData); for (retries=0;retries<16;retries++) { nec_spiwrite(bus,((NEC_ERASETIME/1000000)%10)); microdelay(nec->TimeDataData); nec_spiwrite(bus,((NEC_ERASETIME/100000)%10)); microdelay(nec->TimeDataData); nec_spiwrite(bus,((NEC_ERASETIME/10000)%10)); microdelay(nec->TimeDataData); nec_spiwrite(bus,1); microdelay(nec->TimeEraseCalc); if (nec_spiread(bus)==0x3c) break; } return (retries==16); }
static void WR(int reg, u32int val) { u32int *r = (u32int*)EMMCREGS; if(0)print("WR %2.2ux %ux\n", reg<<2, val); microdelay(emmc.fastclock? 2 : 20); r[reg] = val; }
void uartputc(int c) { int i; if (!uart) return; for (i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++) microdelay(10); outb(COM1+0, c); }
/// Sleeps for a certain amount of microseconds /// /// @param microseconds Number of microseconds to sleep /// @param ignoreinput If true, allow a SIGINT to interrupt us void os_microdelay(uint64_t microseconds, bool ignoreinput) { int old_tmode; if (ignoreinput) { // Go to cooked mode without echo, to allow SIGINT interrupting us // here old_tmode = curr_tmode; if (curr_tmode == TMODE_RAW) settmode(TMODE_SLEEP); microdelay(microseconds); settmode(old_tmode); } else { microdelay(microseconds); } }
int nec78k_prewrite(ASPP *bus) { // start prewriting (write 00 to all flash) int retries; unsigned char status; printf("Prewrite device...\n"); aspp_LEDcpl(bus); // complement LED output microdelay(nec->TimeAckCom); // wait before start this procedure for (retries=0;retries<16;retries++) { nec_spiwrite(bus,0x48); microdelay(nec->TimeComAck); if (nec_spiread(bus)==0x3c) break; } if (retries==16) return -1; for (retries=0;retries<16;retries++) { if (debugmsg) fprintf(stderr,"prewrite: wait for prewritetime (%luuS)\n",nec->TimePreWrite); microdelay(nec->TimePreWrite); nec_spiwrite(bus,0x70); // Read status microdelay(nec->TimeComAck); if (nec_spiread(bus)!=0x3c) continue; microdelay(nec->TimeAckData); status=nec_spiread(bus); microdelay(nec->TimeDataData); if ((nec_spiread(bus)==0x3c && (status&0x40)==0 && (status&0x4)==0)) break; // Ok, prewrite success } return (retries==16); }
int w_cmd(Ctlr *ctlr, ushort cmd, ushort arg) { int i, rc; for(i=0; i<WTmOut; i++) if((csr_ins(ctlr, WR_Cmd)&WCmdBusy) == 0) break; if(i==WTmOut){ print("#l%d: issuing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_Cmd)); return -1; } csr_outs(ctlr, WR_Parm0, arg); csr_outs(ctlr, WR_Cmd, cmd); for(i=0; i<WTmOut; i++) if(csr_ins(ctlr, WR_EvSts)&WCmdEv) break; if(i==WTmOut){ /* * WCmdIni can take a really long time. */ enum { IniTmOut = 2000 }; for(i=0; i<IniTmOut; i++){ if(csr_ins(ctlr, WR_EvSts)&WCmdEv) break; microdelay(100); } if(i < IniTmOut) if(0) print("#l%d: long cmd %.4ux %d\n", ctlr->ctlrno, cmd, i); if(i == IniTmOut){ print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts)); return -1; } } rc = csr_ins(ctlr, WR_Sts); csr_ack(ctlr, WCmdEv); if((rc&WCmdMsk) != (cmd&WCmdMsk)){ print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc); return -1; } if(rc&WResSts){ /* * Don't print; this happens on every WCmdAccWr for some reason. */ if(0) print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc); return -1; } return 0; }
int nec78k_erase(ASPP *bus) { // start erasing flash int retries; unsigned char status; time_t start=time(NULL); // store start time in seconds printf("Erase device...\n"); aspp_LEDcpl(bus); // complement LED output microdelay(nec->TimeAckCom); // wait before start this procedure while (1) { if ((time(NULL)-start)>25) return -1; usleep(1000); if (debugmsg) fprintf(stderr,"DEBUG: ERASE: [%02lu] sending 0x20 command...\n",time(NULL)-start); nec_spiwrite(bus,0x20); // Erase command microdelay(nec->TimeComAck); if (nec_spiread(bus)!=0x3c) // Get command ack continue; if (debugmsg) fprintf(stderr,"DEBUG: ERASE: [%02lu] wait for erase time...\n",(time(NULL)-start)); microdelay(NEC_ERASETIME); // wait erase time for (retries=0;retries<16;retries++) { // blank check if (debugmsg) fprintf(stderr,"DEBUG: ERASE: [%02lu] waiting BlankCheckTime (%lduS)..\n",time(NULL)-start,nec->TimeBlankCheck); microdelay(nec->TimeBlankCheck); // wait blank check time if (debugmsg) fprintf(stderr,"DEBUG: ERASE: [%02lu] sending 0x70 command...\n",time(NULL)-start); nec_spiwrite(bus,0x70); microdelay(nec->TimeComAck); status=nec_spiread(bus); microdelay(nec->TimeAckData); if (status!=0x3C) { if (debugmsg) fprintf(stderr,"DEBUG: ERASE: [%02lu] first ACK: NO\n",time(NULL)-start); continue; } status=nec_spiread(bus);// status microdelay(nec->TimeDataAck); nec_spiread(bus); // get ACK if (status&0x90) { if (debugmsg) fprintf(stderr,"DEBUG: ERASE: [%02lu] status=0x%02x\n",time(NULL)-start,status); continue; // erasing in progress } else { if (debugmsg) fprintf(stderr,"DEBUG: ERASE: [%02lu] status=0x%02x\n",time(NULL)-start,status); break; } } if ((status&0x09)==0) // neither blank error nor erase error: exit break; else if ((time(NULL)-start)>30) { if (debugmsg) fprintf(stderr,"DEBUG: ERASE: [%02lu] timeout (>30seconds). Status=0x%02x\n",time(NULL)-start,status); return -1; } } return 0; }
void exit(int ispanic) { USED(ispanic); spllo(); print("cpu exiting\n"); /* Shutdown running devices */ chandevshutdown(); microdelay(500); systemreset(); }
int miireset(Mii* mii) { int bmcr; if(mii == nil || mii->ctlr == nil || mii->curphy == nil) return -1; bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr); bmcr |= BmcrR; mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr); microdelay(1); return 0; }
static int iprintcanlock(Lock *l) { int i; for(i=0; i<1000; i++){ if(canlock(l)) return 1; if(l->m == machp()) return 0; microdelay(100); } return 0; }