handle_t handle_alloc (void *table) { HandleTable_t *ht = (HandleTable_t *) table; HandleBlock_t *bp; unsigned long *wp; unsigned h; h_printf ("handle_alloc (t): "); if (!ht || !ht->free_handles) { h_printf ("0\r\n"); return (0); } bp = ht->blocks [ht->first_free]; wp = &bp->bitmap [bp->first_free]; h = clz (*wp); h |= bp->first_free << WORD_SHIFT; h |= bp->offset << BLOCK_SHIFT; *wp &= ~(1UL << (WORDSIZE - 1UL - h)); if (--bp->free_bits) { while (*wp == 0UL) { bp->first_free++; wp++; } } else while (!ht->blocks [++ht->first_free]->free_bits) ; ht->free_handles--; h_printf1 ("%u\r\n", h + 1); return (h + 1); }
void dma_assert_DREQ(int channel) { int controller, ch; Bit8u mask; #ifdef EXCESSIVE_DEBUG h_printf("DMA: Asserting DREQ on channel %d\n", channel); #endif /* EXCESSIVE_DEBUG */ controller = (channel & 4) >> 2; ch = channel & DMA_CH_SELECT; mask = 1 << (ch + 4); #ifdef EXCESSIVE_DEBUG h_printf("DMA: ... mask = %d, status = %d\n", mask, dma[controller].i[ch].mask); #endif /* EXCESSIVE_DEBUG */ /* * Must assert DREQ before activating the channel, otherwise it ignores the * the request - AM */ dma[controller].status |= mask; if (!dma[controller].i[ch].mask) activate_channel(controller, ch); }
void *handle_extend (void *table, unsigned nhandles) { HandleTable_t *nht, *ht = (HandleTable_t *) table; unsigned i, n; h_printf1 ("handle_extend (t, %u): ", nhandles); n = ht->nelements + nhandles; if (n < 2 || n >= 0xffff) { h_printf ("0\r\n"); return (NULL); } nht = xrealloc (ht, HANDLE_TABLE_SIZE (n)); if (!nht) { h_printf ("0\r\n"); return (NULL); } ht = nht; for (i = ht->nelements + 2; i <= n; i++) { ht->elem [i - 1].next = i; ht->elem [i].prev = i - 1; } if (ht->elem [0].prev) { ht->elem [ht->elem [0].prev].next = ht->nelements + 1; ht->elem [ht->nelements + 1].prev = ht->elem [0].prev; } else { ht->elem [0].next = ht->nelements + 1; ht->elem [ht->nelements + 1].prev = 0; } ht->elem [0].prev = n; ht->elem [n].next = 0; ht->nelements = n; h_printf1 ("%p\r\n", (void *) ht); return (ht); }
static void rtc_alarm_check (void) { static u_char last_sec = 0xff; /* any invalid value to begin with */ u_char h0,m0,s0,h,m,s; s0=GET_CMOS(CMOS_SEC); m0=GET_CMOS(CMOS_MIN); h0=GET_CMOS(CMOS_HOUR); /* this is a test for equality - we can't just call a lib time * function because a second could be skipped */ h = GET_CMOS(CMOS_HOURALRM); if (h>=0xc0 || h0==h) { /* Eric: all c0-ff are don't care */ m = GET_CMOS(CMOS_MINALRM); if (m>=0xc0 || m0==m) { s = GET_CMOS(CMOS_SECALRM); if (s>=0xc0 || (s0==s && s0!=last_sec)) { last_sec = s0; h_printf("RTC: got alarm at %02d:%02d:%02d\n",h,m,s); SET_CMOS(CMOS_STATUSC, GET_CMOS(CMOS_STATUSC) | 0x20); if ((GET_CMOS(CMOS_STATUSB) & 0x20) && !(GET_CMOS(CMOS_STATUSC) & 0x80)) { SET_CMOS(CMOS_STATUSC, GET_CMOS(CMOS_STATUSC) | 0x80); h_printf("RTC: alarm IRQ\n"); pic_request(PIC_IRQ8); } } } } }
void rtc_run(void) { static hitimer_t last_time = -1; int rate; hitimer_t ticks_m, cur_time = GETusTIME(0); if (last_time == -1 || last_time > cur_time) { last_time = cur_time; return; } rate = rtc_get_rate(GET_CMOS(CMOS_STATUSA) & 0x0f); ticks_m = (cur_time - last_time) * rate; q_ticks_m += ticks_m; last_time = cur_time; if (debug_level('h') > 8) h_printf("RTC: A=%hhx B=%hhx C=%hhx rate=%i queued=%lli added=%lli\n", GET_CMOS(CMOS_STATUSA), GET_CMOS(CMOS_STATUSB), GET_CMOS(CMOS_STATUSC), rate, (long long)q_ticks_m, (long long)ticks_m); if (q_ticks_m >= 1000000) { Bit8u old_c = GET_CMOS(CMOS_STATUSC); SET_CMOS(CMOS_STATUSC, old_c | 0x40); if ((GET_CMOS(CMOS_STATUSB) & 0x40) && !(GET_CMOS(CMOS_STATUSC) & 0x80)) { SET_CMOS(CMOS_STATUSC, GET_CMOS(CMOS_STATUSC) | 0x80); if (debug_level('h') > 7) h_printf("RTC: periodic IRQ, queued=%lli, added=%lli\n", (long long)q_ticks_m, (long long)ticks_m); pic_request(PIC_IRQ8); } if (!(old_c & 0x40)) q_ticks_m -= 1000000; } }
/* write to port 64h (8042 command register) */ static void write_port64(Bit8u value) { k_printf("8042: write port64h, =%02x\n",value); switch(value) { case 0x20: /* read 8042 command byte */ output_byte_8042(keyb_ctrl_command); break; case 0x60: /* write 8042 command byte */ wstate=0x60; break; #if 0 /* not sure if these are ok and/or needed. */ case 0xa4: /* passwort installed test */ output_byte_8042(0xfa); /* no password */ break; case 0xa5: /* load password */ /* XXX ... we should read bytes from port60 until 0 is found */ break; case 0xa9: /* aux interface test */ output_byte_8042(0x00); /* ok */ break; case 0xaa: /* 8042 self test */ output_byte_8042(0x55); /* ok */ break; case 0xab: /* keyboard interface test */ output_byte_8042(0x00); /* ok */ break; case 0xc0: /* read 8042 input port */ output_byte_8042(0xff); /* just send _something_... */ break; #endif case 0xd1: /* next write to port 0x60 drives hardware port */ wstate=0xd1; break; case 0xf0 ... 0xff: /* produce 6ms pulse on hardware port */ wstate=0; port60_ready=0; if (!(value & RESET_LINE_MASK)) { h_printf("8042: produce 6ms pulse on cpu reset line\n"); cpu_reset(); } else h_printf("8042: produce 6ms pulse on hardware port, ignored\n"); break; default: h_printf("8042: write port 0x64 unsupported command 0x%02x, ignored\n", value); /* various other commands... ignore */ break; } }
static Bit8u read_port60(void) { Bit8u r = port60_buffer; port60_ready = 0; h_printf("8042: read port 0x60 = 0x%02x\n", r); #if KEYB_CMD switch (rstate) { case 0xf2: /* get keyboard type, MSB */ h_printf("8042: read port 0x60, getting keyboard type (MSB)\n"); output_byte_8042(0x83); rstate = 0x72; break; case 0x72: /* get keyboard type, LSB */ h_printf("8042: read port 0x60, getting keyboard type (LSB)\n"); output_byte_8042(0xab); rstate = 0; break; case 0xff: /* reset keyboard */ h_printf("8042: read port 0x60, resetting\n"); output_byte_8042(0xaa); /* BAT completion code */ rstate = 0; break; default: /* invalid state ?! */ rstate = 0; break; } #endif return r; }
int cmos_date(int reg) { unsigned long ticks; struct timeval tp; struct timezone tzp; struct tm *tm; /* get the time */ gettimeofday(&tp, &tzp); ticks = tp.tv_sec - (tzp.tz_minuteswest*60); tm = localtime((time_t *)&ticks); #if 0 h_printf("CMOS: get time %d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); h_printf("CMOS: get date %d.%d.%d\n", tm->tm_mday, tm->tm_mon, tm->tm_year); #endif /* is any of this correct?? */ switch(reg) { case 0: /* RTC seconds */ return tm->tm_sec; case 2: /* RTC minutes */ return tm->tm_min; case 4: /* RTC hour */ return tm->tm_hour; case 6: /* RTC weekday */ return tm->tm_wday; case 7: /* RTC day of month */ return tm->tm_mday; /* day of month */ case 8: /* RTC month */ if (cmos.flag[8]) return cmos.subst[8]; else return tm->tm_mon; case 9: /* RTC year */ if (cmos.flag[9]) return cmos.subst[9]; else return tm->tm_year; default: h_printf("CMOS: cmos_time() register 0x%02x defaulted to 0\n",reg); return 0; } /* the reason for month and year I return the substituted valus is this: * Norton Sysinfo checks the CMOS operation by reading the year, writing * a new year, reading THAT year, and then rewriting the old year, * apparently assuming that the CMOS year can be written to, and only * changes if the year changes, which is not likely between the 2 writes. * Since I personally know that dosemu won't stay uncrashed for 2 hours, * much less a year, I let it work that way. */ }
void cmos_write(int port, int byte) { if (port == 0x70) cmos.address=byte & ~0xc0; /* get true address */ else { if ((cmos.address != 0xc) && (cmos.address != 0xd)) { h_printf("CMOS: set address 0x%02x to 0x%02x\n", cmos.address,byte); cmos.subst[cmos.address]=byte; cmos.flag[cmos.address]=1; } else h_printf("CMOS: write to ref 0x%x blocked\n", cmos.address); } }
/* * This is the default HLT handler for the HLT block -- assume that * someone did a CALLF to get to us. */ static void hlt_default(Bit32u addr) { /* Assume someone callf'd to get here and do a return far */ h_printf("HLT: hlt_default(0x%04x) called, attemping a retf\n", addr); fake_retf(0); }
void handle_final (void *table) { HandleTable_t *ht = (HandleTable_t *) table; h_printf ("handle_final (t);\r\n"); ht->nelements = 0xfffff; xfree (ht); }
int cmos_read(int port) { unsigned char holder; h_printf("CMOS read. from add: 0x%02x\n", cmos.address); switch(cmos.address) { case 0: /* RTC seconds */ case 2: /* minutes */ case 4: /* hours */ case 6: /* day of week */ case 7: /* day of month */ case 8: /* month */ case 9: /* year */ return (cmos_date(cmos.address)); case 1: /* RTC seconds alarm */ case 3: /* minutes alarm */ case 5: /* hours alarm */ h_printf("CMOS alarm read %d...UNIMPLEMENTED!\n", cmos.address); return cmos.subst[cmos.address]; } /* date functions return, so hereafter all values should be static * after boot time... */ if (cmos.flag[cmos.address]) /* this reg has been written to */ { holder=cmos.subst[cmos.address]; h_printf("CMOS: substituting written value 0x%02x for read\n",holder); } #ifdef DANGEROUS_CMOS else if (!ioperm(0x70,2,1)) { h_printf("CMOS: really reading!\n"); port_out((cmos.address & ~0xc0)|0x80, 0x70); holder=port_in(0x71); ioperm(0x70,2,0); } #endif else error("CMOS: Can't get permissions for true I/O to 0x70, 0x71\n"); h_printf("CMOS read. add: 0x%02x = 0x%02x\n", cmos.address, holder); return holder; }
void *handle_init (unsigned nhandles) { HandleTable_t *ht; h_printf1 ("handle_init (%u): ", nhandles); if (nhandles < 2 || nhandles >= 0xffff) { h_printf ("0\r\n"); return (NULL); } ht = xmalloc (HANDLE_TABLE_SIZE (nhandles)); if (!ht) { h_printf ("0\r\n"); return (NULL); } ht->nelements = nhandles; h_printf1 ("%p\r\n", (void *) ht); handle_reset (ht); return (ht); }
static inline int process_interrupt(SillyG_t *sg) { int irq, ret=0; if ((irq = sg->irq) != 0) { h_printf("INTERRUPT: 0x%02x\n", irq); ret=(pic_request(pic_irq_list[irq])!=PIC_REQ_LOST); } return ret; }
void *handle_init (unsigned nhandles) { HandleTable_t *ht; HandleBlock_t *bp; unsigned nb, i; if (!nhandles) return (NULL); h_printf1 ("handle_init (%u): ", nhandles); ht = xmalloc (sizeof (HandleTable_t)); if (!ht) { h_printf ("0\r\n"); return (NULL); } nb = (nhandles + BITSPBLOCK - 1) >> BLOCK_SHIFT; ht->blocks = xmalloc (nb * sizeof (HandleBlock_t *)); if (!ht->blocks) { xfree (ht); h_printf ("0\r\n"); return (NULL); } for (i = 0; i < nb; i++) { ht->blocks [i] = bp = xmalloc (sizeof (HandleBlock_t)); if (!bp) { while (i) xfree (ht->blocks [--i]); xfree (ht->blocks); xfree (ht); h_printf ("0\r\n"); return (NULL); } bp->offset = i; bp->free_bits = BITSPBLOCK; bp->first_free = 0; memset (bp->bitmap, ~0U, sizeof (bp->bitmap)); } ht->nblocks = ht->free_blocks = nb; ht->first_free = 0; ht->free_handles = ht->max_handles = nhandles; h_printf1 ("%p\r\n", (void *) ht); return (ht); }
handle_t handle_alloc (void *table) { HandleTable_t *ht = (HandleTable_t *) table; Index_t *np, *pp, *p; unsigned index; h_printf ("handle_alloc (t): "); if ((index = ht->elem [0].next) == 0) { h_printf ("0\r\n"); return (0); } p = &ht->elem [index]; np = &ht->elem [p->next]; pp = &ht->elem [p->prev]; pp->next = p->next; np->prev = p->prev; p->next = p->prev = 0; h_printf1 ("%u\r\n", index); return (index); }
void rtc_write(Bit8u reg, Bit8u byte) { switch (reg) { case CMOS_SEC: case CMOS_MIN: case CMOS_HOUR: case CMOS_SECALRM: case CMOS_MINALRM: case CMOS_HOURALRM: case CMOS_DOW: case CMOS_DOM: case CMOS_MONTH: case CMOS_YEAR: case CMOS_CENTURY: SET_CMOS(reg, BIN(byte)); break; /* b7=r/o and unused * b4-6=always 010 (AT standard 32.768kHz) * b0-3=rate [65536/2^v], default 6, min 3, 0=disable */ case CMOS_STATUSA: h_printf("RTC: Write %hhx to A\n", byte); SET_CMOS(reg, byte & 0x7f); break; case CMOS_STATUSB: h_printf("RTC: Write %hhx to B\n", byte); SET_CMOS(reg, byte); break; case CMOS_STATUSC: case CMOS_STATUSD: h_printf("RTC: attempt to write %hhx to %hhx\n", byte, reg); break; default: SET_CMOS(reg, byte); } q_ticks_m = 0; }
void *handle_extend (void *table, unsigned nhandles) { HandleTable_t *ht = (HandleTable_t *) table; HandleBlock_t **p, *bp; unsigned nb, i; h_printf1 ("handle_extend (t, %u): ", nhandles); if (!ht) { h_printf ("0\r\n"); return (NULL); } nb = (ht->max_handles + nhandles + BITSPBLOCK - 1) >> BLOCK_SHIFT; if (nb > ht->nblocks) { p = xrealloc (ht->blocks, nb & sizeof (HandleBlock_t *)); if (!p) { h_printf ("0\r\n"); return (NULL); } ht->blocks = p; for (i = ht->nblocks; i < nb; i++) { ht->blocks [i] = bp = xmalloc (sizeof (HandleBlock_t)); if (!bp) { while (i > ht->nblocks) xfree (ht->blocks [--i]); h_printf ("0\r\n"); return (NULL); } bp->offset = i; bp->free_bits = BITSPBLOCK; bp->first_free = 0; memset (bp->bitmap, ~0U, sizeof (bp->bitmap)); } ht->free_blocks += nb; ht->nblocks = nb; } ht->free_handles += nhandles; ht->max_handles += nhandles; h_printf1 ("%p\r\n", (void *) ht); return (ht); }
inline void add_value(multi_t * data, Bit16u value) { Bit16u tmp; #ifdef EXCESSIVE_DEBUG h_printf("DMA: MSB %u, LSB %u\n", data->bits.msb, data->bits.lsb); #endif /* EXCESSIVE_DEBUG */ tmp = get_value(*data); #ifdef EXCESSIVE_DEBUG h_printf("DMA: Adding %u to %u gives ", value, tmp); #endif /* EXCESSIVE_DEBUG */ set_value(data, tmp + value); if (get_value(*data) < tmp) data->bits.underflow = 1; else data->bits.underflow = 0; #ifdef EXCESSIVE_DEBUG h_printf("%u ", get_value(*data)); if (data->bits.underflow) h_printf("(overflow)"); h_printf("\n"); h_printf("DMA: MSB %u, LSB %u\n", data->bits.msb, data->bits.lsb); #endif /* EXCESSIVE_DEBUG */ }
inline void sub_value(multi_t * data, Bit16u value) { Bit16u tmp; #ifdef EXCESSIVE_DEBUG h_printf("DMA: MSB %u, LSB %u\n", data->bits.msb, data->bits.lsb); #endif /* EXCESSIVE_DEBUG */ tmp = get_value(*data); #ifdef EXCESSIVE_DEBUG h_printf("DMA: Subtracting %u from %u gives ", value, tmp); #endif /* EXCESSIVE_DEBUG */ set_value(data, tmp - value); if (tmp < value) data->bits.underflow = 1; else data->bits.underflow = 0; #ifdef EXCESSIVE_DEBUG h_printf("%u ", get_value(*data)); if (data->bits.underflow) h_printf("(underflow)"); h_printf("\n"); h_printf("DMA: MSB %u, LSB %u\n", data->bits.msb, data->bits.lsb); #endif /* EXCESSIVE_DEBUG */ }
void handle_reset (void *table) { HandleTable_t *ht = (HandleTable_t *) table; unsigned i; h_printf ("handle_reset (t);\r\n"); for (i = 1; i <= ht->nelements; i++) { ht->elem [i - 1].next = i; ht->elem [i].prev = i - 1; } ht->elem [ht->nelements].next = 0; ht->elem [0].prev = ht->nelements; }
void dma_drop_eop(int channel) { int controller, ch; #ifdef EXCESSIVE_DEBUG h_printf("DMA: Dropping EOP on channel %d\n", channel); #endif /* EXCESSIVE_DEBUG */ controller = (channel & 4) >> 2; ch = channel & DMA_CH_SELECT; dma[controller].i[ch].eop = 0; }
int dma_test_eop(int channel) { int controller, ch; #ifdef EXCESSIVE_DEBUG h_printf("DMA: Testing EOP on channel %d\n", channel); #endif /* EXCESSIVE_DEBUG */ controller = (channel & 4) >> 2; ch = channel & DMA_CH_SELECT; return dma[controller].i[ch].eop; }
void dma_assert_DACK(int channel) { int controller, ch; #ifdef EXCESSIVE_DEBUG h_printf("DMA: Asserting DACK on channel %d\n", channel); #endif /* EXCESSIVE_DEBUG */ controller = (channel & 4) >> 2; ch = channel & DMA_CH_SELECT; dma[controller].i[ch].dack = 1; }
void handle_final (void *table) { HandleTable_t *ht = (HandleTable_t *) table; unsigned i; h_printf ("handle_final (t);\r\n"); if (!ht) return; for (i = 0; i < ht->nblocks; i++) xfree (ht->blocks [i]); xfree (ht->blocks); xfree (ht); }
int dma_test_DREQ(int channel) { int controller, ch; Bit8u mask; #ifdef EXCESSIVE_DEBUG h_printf("DMA: Testing DREQ on channel %d\n", channel); #endif /* EXCESSIVE_DEBUG */ controller = (channel & 4) >> 2; ch = channel & DMA_CH_SELECT; mask = 1 << (ch + 4); return dma[controller].status & mask; }
void dma_drop_DREQ(int channel) { int controller, ch; Bit8u mask; #ifdef EXCESSIVE_DEBUG h_printf("DMA: Dropping DREQ on channel %d\n", channel); #endif /* EXCESSIVE_DEBUG */ controller = (channel & 4) >> 2; ch = channel & DMA_CH_SELECT; mask = 1 << (ch + 4); is_dma &= ~get_mask(channel); dma[controller].status &= ~mask; }
static inline void irq_select(void) { if (SillyG) { int irq_bits = vm86_plus(VM86_GET_IRQ_BITS, 0); if (irq_bits) { SillyG_t *sg=SillyG; while (sg->fd) { if (irq_bits & (1 << sg->irq)) { if (process_interrupt(sg)) { vm86_plus(VM86_GET_AND_RESET_IRQ,sg->irq); h_printf("SIG: We have an interrupt\n"); } } sg++; } } } }
void handle_reset (void *table) { HandleTable_t *ht = (HandleTable_t *) table; HandleBlock_t *bp; unsigned i; h_printf ("handle_reset (t);\r\n"); if (!ht) return; for (i = 0; i < ht->nblocks; i++) { bp = ht->blocks [i]; bp->free_bits = BITSPBLOCK; bp->first_free = 0; memset (bp->bitmap, ~0U, sizeof (bp->bitmap)); } ht->free_blocks = ht->nblocks; ht->first_free = 0; ht->free_handles = ht->max_handles; }
Bit8u rtc_read(Bit8u reg) { Bit8u ret = GET_CMOS(reg); switch (reg) { case CMOS_SEC: case CMOS_SECALRM: case CMOS_MIN: case CMOS_MINALRM: case CMOS_DOW: case CMOS_DOM: case CMOS_MONTH: case CMOS_YEAR: case CMOS_CENTURY: /* Note - the inline function BCD() in cmos.h will check bit 2 of * status reg B for proper output format */ ret = BCD(ret); break; case CMOS_HOUR: /* RTC hour...bit 1 of 0xb set=24 hour mode, clear 12 hour */ case CMOS_HOURALRM: if (!(GET_CMOS(CMOS_STATUSB) & 2)) { /* 12-hour mode */ if (ret == 0) ret = 12; else if (ret > 12) ret -= 12; } ret = BCD(ret); break; case CMOS_STATUSC: if (debug_level('h') > 8) h_printf("RTC: Read C=%hhx\n", ret); SET_CMOS(CMOS_STATUSC, 0); pic_untrigger(PIC_IRQ8); rtc_run(); break; } return ret; }