Example #1
0
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);
}
Example #2
0
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);

}
Example #3
0
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);
}
Example #4
0
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);
        }
      }
    }
  }
}
Example #5
0
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;
  }
}
Example #6
0
/* 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;
       }
}
Example #7
0
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;
}
Example #8
0
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.
   */

}
Example #9
0
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);
    }
}
Example #10
0
/*
 * 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);
}
Example #11
0
void handle_final (void *table)
{
	HandleTable_t	*ht = (HandleTable_t *) table;

	h_printf ("handle_final (t);\r\n");
	ht->nelements = 0xfffff;
	xfree (ht);
}
Example #12
0
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;
}
Example #13
0
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);
}
Example #14
0
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;
}
Example #15
0
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);
}
Example #16
0
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);
}
Example #17
0
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;
}
Example #18
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);
}
Example #19
0
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 */
}
Example #20
0
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 */
}
Example #21
0
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;
}
Example #22
0
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;
}
Example #23
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;
}
Example #24
0
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;
}
Example #25
0
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);
}
Example #26
0
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;
}
Example #27
0
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;
}
Example #28
0
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++;
      }
    }
  }
}
Example #29
0
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;
}
Example #30
0
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;
}