Exemplo n.º 1
0
kmain() {
	terminal_init();

	setup_IDT_entry (&idt[0x08], 0x08, (dword)&_int_08_hand, ACS_INT, 0);
	setup_IDT_entry (&idt[0x09], 0x08, (dword)&_int_09_hand, ACS_INT, 0);
	setup_IDT_entry (&idt[0x74], 0x08, (dword)&_int_74_hand, ACS_INT, 0);
	setup_IDT_entry (&idt[0x80], 0x08, (dword)&_int_80_hand, ACS_INT, 0);
	

	/* IDTR Setting */ 

	idtr.base = 0;  
	idtr.base +=(dword) &idt;
	idtr.limit = sizeof(idt)-1;
	
	_lidt(&idtr);

	/* Interrupt unmasking */
	
	_cli();

	_maskPIC1(0xF8);           /*0XF8*/
	_maskPIC2(0xEF);		/*0XEF*/
	
	_sti();

	video_init();
	timertick_init();
	rtc_init();
	mouse_init();
	shell_run();
}
Exemplo n.º 2
0
PUBLIC void _expandStack() {
    _cli();
    PROCESS *proc = scheduler_getCurrentProcess();
    proc->stack -= PAGE_SIZE;
    proc->stacksize += PAGE_SIZE;
    // FIXME: check for used pages.
    get_page(proc->stack, true, current_directory);
    log(L_DEBUG, "EXPANDED: %s starts at 0x%x to 0x%x", proc->name, proc->stack, proc->stack + proc->stacksize - 1);
    printf("STACK EXPANDED: %s starts at 0x%x to 0x%x (esp: 0x%x)\n", proc->name, proc->stack, proc->stack + proc->stacksize - 1, proc->ESP);
}
Exemplo n.º 3
0
static int soundblaster_stop_playback(soundcard_t sc) {
    struct sndsb_ctx *card = soundblaster_get_sndsb_ctx(sc);

    if (card == NULL) return -1;
    if (!sc->wav_state.playing) return 0;

    _cli();
    soundblaster_update_wav_dma_position(sc,card);
    soundblaster_update_wav_play_delay(sc,card);
    _sti();

    sndsb_stop_dsp_playback(card);

    _cli();
    sc->wav_state.playing = 0;
    _sti();

    return 0;
}
Exemplo n.º 4
0
int probe_8259() {
	unsigned char om,cm,c2;
	unsigned int flags;

	if (p8259_probed < 0)
		return (int)p8259_probed;

	/* don't let the BIOS fiddle with the mask during
	   the test. Fixes: Pentium machine where 1 out of
	   100 times programs fail with "cannot init PIC" */
	flags = get_cpu_flags(); _cli();
	om = p8259_read_mask(0);
	p8259_write_mask(0,0xFF);
	cm = p8259_read_mask(0);
	p8259_write_mask(0,0x00);
	c2 = p8259_read_mask(0);
	p8259_write_mask(0,om);
	set_cpu_flags(flags);

	if (cm != 0xFF || c2 != 0x00)
		return (p8259_probed=0);

	/* is a slave present too? */
	flags = get_cpu_flags(); _cli();
	om = p8259_read_mask(8);
	p8259_write_mask(8,0xFF);
	cm = p8259_read_mask(8);
	p8259_write_mask(8,0x00);
	c2 = p8259_read_mask(8);
	p8259_write_mask(8,om);
	set_cpu_flags(flags);

	if (cm == 0xFF && c2 == 0x00)
		p8259_slave_present = 1;

	return (p8259_probed=1);
}
Exemplo n.º 5
0
void keDoSched()
{
	uint32 i;
	uint32 j;

	_cli();
	i=keSchedNextTask();
	while(i==0xFFFFFFFF)
	{
		_sti();
		_hlt();
		_cli();
		i=keSchedNextTask();
	}						// not any task can be sched

	if(i==currentTaskId)
	{
		_sti();
		return;				// only the current task can be sched
	}
	j=currentTaskId;
	currentTaskId=i;
	_switch(&(tasks[i]->esp), &(tasks[j]->esp));
}
Exemplo n.º 6
0
void _stdcall main(unsigned long p1, unsigned long p2, unsigned long p3)
{
	uint32 *oldesp;
	struct taskblock *task;
	_cli();
	cpuInit();
	_ISRVECT[17]=(uint32)keDoSched;
	_ISRVECT[32]=(uint32)keTimerIsr;

	keKernelHeapInit();
	keInitTaskSystem();

	task=keNewTask("main", keEntryMain, 0, 8, 0x4000);
	currentTaskId=0;
	_switch(&(task->esp), &oldesp);
}
Exemplo n.º 7
0
static int soundblaster_start_playback(soundcard_t sc) {
    struct sndsb_ctx *card = soundblaster_get_sndsb_ctx(sc);

    if (card == NULL) return -1;
    if (!sc->wav_state.prepared) return -1;
    if (sc->wav_state.playing) return 0;

    if (!sndsb_begin_dsp_playback(card))
        return -1;

    _cli();
    sc->wav_state.playing = 1;
    _sti();

    return 0;
}
Exemplo n.º 8
0
void generalprotectintr(uint32 edi, uint32 esi, uint32 ebp, uint32 esp,
		   uint32 ebx, uint32 edx, uint32 ecx, uint32 eax, 
		   uint32 code, uint32 eip, uint32 cs)
{
	int i;
	_cli();
	printf("\nGeneral Protect Error\n");
	printf("tid=%d\n", currentTaskId);
	printf("eip=%08x ecs=%08x code=%08x\n", eip, cs, code);
	printf("eax=%08x ebx=%08x ecx=%08x edx=%08x\n", eax, ebx, ecx, edx);
	printf("esp=%08x ebp=%08x esi=%08x edi=%08x\n", esp, ebp, esi, edi);
	printf("Dump Stack:\n");
	for(i=0;i<16;i++)
		printf("%08X  ", ((uint32*)esp)[i+3]); 
	printf("Dump TCB:\n");
	for(i=0;i<16;i++)
		printf("%08X  ", ((uint32*)tasks[currentTaskId])[i]); 
	while(1);
}
Exemplo n.º 9
0
void direct_dac_test(void) {
    unsigned long time,bytes;
    unsigned char FAR *ptr;
    unsigned int i,count;
    unsigned int pc,c;

    doubleprintf("Direct DAC playback test.\n");

    /* FIXME: Why is the final rate SLOWER in DOSBox-X in 386 protected mode? */

    sndsb_reset_dsp(sb_card);
    sndsb_write_dsp(sb_card,0xD1); /* speaker on */

    _cli();
    time = 0;
    bytes = 0;
    c = read_8254(T8254_TIMER_INTERRUPT_TICK);
    for (count=0;count < 3;count++) {
        ptr = sb_dma->lin;
        for (i=0;i < sb_dma->length;i++) {
            sndsb_write_dsp(sb_card,SNDSB_DSPCMD_DIRECT_DAC_OUT); /* 0x10 */
            sndsb_write_dsp(sb_card,*ptr++);

            pc = c;
            c = read_8254(T8254_TIMER_INTERRUPT_TICK);
            time += (unsigned long)((pc - c) & 0xFFFFU); /* remember: it counts DOWN. assumes full 16-bit count */
        }
        bytes += sb_dma->length;
    }
    _sti();

    if (time == 0UL) time = 1;

    {
        double t = (double)time / T8254_REF_CLOCK_HZ;
        double rate = (double)bytes / t;

        doubleprintf(" - %lu bytes played in %.3f seconds\n",(unsigned long)bytes,t);
        doubleprintf(" - Sample rate is %.3fHz\n",rate);
    }
}
Exemplo n.º 10
0
void kernel_main(multiboot_info_t *mbi)
{		
	_cli();
	init_video();
	printk("=== Arcanum kernel ===\n");

	printk("Chargement de la GDT... ");
	gdt_init();
	__pok();
	
	printk("Chargement de l'IDT... ");
	idt_init();
	pic_init();
	_clock = 0;

	__pok();

	printk("Activation des interruptions. \n");
	_sti();
	

	for(;;) {}
}
Exemplo n.º 11
0
/* private */
static void soundblaster_update_wav_dma_position(soundcard_t sc,struct sndsb_ctx *card) {
    _cli();
    sc->wav_state.dma_position = sndsb_read_dma_buffer_position(card);
    _sti();
}
Exemplo n.º 12
0
int disableInts() {
	int flags = gFlags();
	/* Retorna si el I flag está on o no */
	_cli();
	return (flags & (0x1 << 9));
}
Exemplo n.º 13
0
void pulse_width_test() {
	int fd;
	unsigned char cc;
	unsigned int play;
	unsigned char plan_b=0;
	unsigned int patience = 10000;

	_cli();
	write_8254_system_timer(0xFFFF);	/* BUGFIX: Personal experience tells me BIOSes would fail reading the floppy if the IRQ 0 timer isn't ticking along at 18Hz */
	_sti();

	fd = open("..\\test1_22.wav",O_RDONLY|O_BINARY);
	if (fd < 0) fd = open("test1_22.wav",O_RDONLY|O_BINARY);
	if (fd < 0) {
		fprintf(stderr,"Cannot open test WAV\n");
		return;
	}
	lseek(fd,44,SEEK_SET);
	read(fd,tmp,sizeof(tmp));
	for (play=0;play < sizeof(tmp);play++) tmp[play] = (((tmp[play]) * 53) / 255) + 1; /* add "noise" to dither */
	close(fd);

	/* set timer 0 to 54 ticks (1.191MHz / 54 ~ 22050Hz) */
	_cli();
	t8254_pc_speaker_set_gate(0);
	write_8254_pc_speaker(1);
	write_8254_system_timer(54);
	_sti();

	_cli();
	{
		outp(T8254_CONTROL_PORT,(0 << 6) | (0 << 4) | 0);	/* latch counter N, counter latch read */
		do {
			if (--patience == 1) break;
			cc = inp(T8254_TIMER_PORT(0));
			inp(T8254_TIMER_PORT(0));
		} while (cc < (54/2));
		do {
			if (--patience == 0) break;
			cc = inp(T8254_TIMER_PORT(0));
			inp(T8254_TIMER_PORT(0));
		} while (cc >= (54/2));
		if (patience <= 2) {
			write_8254_system_timer(0xFFFF);	/* BUGFIX: on very old slow machines, the 54-count tick can easily cause the printf() below to absolutely CRAWL... */
			_sti();
			fprintf(stderr,"Oops! Either your CPU is too fast or the timer countdown trick doesn't work.\n");
			_cli();
			write_8254_system_timer(54);
			plan_b = 1;
		}
	}
	_sti();

	while (1) {
		if (kbhit()) {
			int c = getch();
			if (c == 27) break;
		}

		if (plan_b) {
			/* run with interrupts enabled, use IRQ0 to know when to tick */
			_cli();
			counter = 0;
			t8254_pc_speaker_set_gate(3);
			for (play=0;play < sizeof(tmp);) {
				outp(T8254_CONTROL_PORT,(2 << 6) | (1 << 4) | (T8254_MODE_0_INT_ON_TERMINAL_COUNT << 1)); /* MODE 0, low byte only, counter 2 */
				outp(T8254_TIMER_PORT(2),tmp[play]);
				_sti();
				while (counter == 0);
				_cli();
				play += counter;
				counter = 0;
			}
			_sti();
		}
		else {
			_cli();
			t8254_pc_speaker_set_gate(3);
			outp(T8254_CONTROL_PORT,(0 << 6) | (0 << 4) | 0);	/* latch counter N, counter latch read */
			for (play=0;play < sizeof(tmp);play++) {
				outp(T8254_CONTROL_PORT,(2 << 6) | (1 << 4) | (T8254_MODE_0_INT_ON_TERMINAL_COUNT << 1)); /* MODE 0, low byte only, counter 2 */
				outp(T8254_TIMER_PORT(2),tmp[play]);

				do {
					cc = inp(T8254_TIMER_PORT(0));
					inp(T8254_TIMER_PORT(0));
				} while (cc < (54/2));

				do {
					cc = inp(T8254_TIMER_PORT(0));
					inp(T8254_TIMER_PORT(0));
				} while (cc >= (54/2));
			}
			_sti();
		}
	}

	t8254_pc_speaker_set_gate(0);
}
Exemplo n.º 14
0
int main() {
	struct t8254_readback_t readback;
	t8254_time_t tick[3];
	unsigned int i;

	printf("8254 library test program\n");
	if (!probe_8254()) {
		printf("Chip not present. Your computer might be 2010-era hardware that dropped support for it.\n");
		return 1;
	}
	if (!probe_8259()) {
		printf("8259 interrupt controller not present. Your computer might be 2010-era hardware that dropped support for it.\n");
		return 1;
	}

	printf("8254 base clock: %luHz\n",T8254_REF_CLOCK_HZ);

	speaker_rate = T8254_REF_CLOCK_HZ / 400UL;	/* 400Hz */

	prev_irq0 = _dos_getvect(T8254_IRQ+0x08);
	_dos_setvect(T8254_IRQ+0x8,irq0);

	_cli();
	write_8254_pc_speaker(speaker_rate);
	write_8254_system_timer(max);
	_sti();

#ifdef TARGET_PC98
	/* PC-98 does not have IRQ0 running by default */
	p8259_unmask(T8254_IRQ);
#endif

	while (1) {
		if (kbhit()) {
			int c = getch();
			if (c == 27)
				break;
			else if (c == '-') {
				max -= 80;
				if (max > (0xFFFF-80))
					max = 0xFFFF;

				_cli();
				write_8254_system_timer(max);
				_sti();
			}
			else if (c == '=') {
				max += 110;
				if (max < 110 || max > (0xFFFF-110))
					max = 0xFFFF;
	
				_cli();
				write_8254_system_timer(max);
				_sti();
			}
			/* play with timer 2 and the PC speaker gate */
			else if (c == 'p') {
				unsigned char on = (t8254_pc_speaker_read_gate() != 0) ? 1 : 0;
				if (on) t8254_pc_speaker_set_gate(0);
				else t8254_pc_speaker_set_gate(3);
			}
			else if (c == '1') {
#ifndef TARGET_PC98
				unsigned char v = t8254_pc_speaker_read_gate();
				t8254_pc_speaker_set_gate(v ^ PC_SPEAKER_OUTPUT_TTL_AND_GATE);
#endif
			}
			else if (c == '2') {
#ifndef TARGET_PC98
				unsigned char v = t8254_pc_speaker_read_gate();
				t8254_pc_speaker_set_gate(v ^ PC_SPEAKER_COUNTER_2_GATE);
#endif
			}
			else if (c == '[') {
				speaker_rate += 110;
				if (speaker_rate > (0xFFFF-110) || speaker_rate < 110)
					speaker_rate = 0xFFFF;

				write_8254_pc_speaker(speaker_rate);
			}
			else if (c == ']') {
				speaker_rate -= 110;
				if (speaker_rate > (0xFFFF-110))
					speaker_rate = 0;

				write_8254_pc_speaker(speaker_rate);
			}
			else if (c == 'w') {
				printf("\n");
				pulse_width_test();
				_cli();
				write_8254_system_timer(max);
				_sti();
				printf("\n");
			}
			else if (c == 'z') {
				/* sleep-wait loop test */
				unsigned long delay_ticks;
				unsigned long z;
				unsigned int c,cmax;

				printf("\nDelay interval in us? ");
				z = 1000000; scanf("%lu",&z);

				delay_ticks = t8254_us2ticks(z);
				printf("  %lu = %lu ticks\n",z,delay_ticks);

				if (delay_ticks == 0UL)	cmax = (unsigned int)(T8254_REF_CLOCK_HZ / 20UL);
				else			cmax = (unsigned int)(T8254_REF_CLOCK_HZ / 20UL / (unsigned long)delay_ticks);
				if (cmax == 0) cmax = 1;

				write_8254_pc_speaker(T8254_REF_CLOCK_HZ / 400UL); /* tick as fast as possible */
				while (1) {
					if (kbhit()) {
						if (getch() == 27) break;
					}

					for (c=0;c < cmax;c++) {
						t8254_pc_speaker_set_gate(3);
						t8254_wait(delay_ticks);
						t8254_pc_speaker_set_gate(0);
						t8254_wait(delay_ticks);
					}
				}
			}
			else if (c == 'd') {
				printf("\n                                    \nDetail mode, hit 'd' again to exit: [WARNING: 8254 only]\n");
				while (1) {
					if (kbhit()) {
						int c = getch();
						if (c == 'd') {
							break;
						}
					}

					_cli();
					readback_8254(T8254_READBACK_ALL,&readback);
					_sti();
					printf("\x0D");
					for (i=0;i <= 2;i++) {
						printf("[%u] stat=%02x count=%04x  ",i,
							readback.timer[i].status,
							readback.timer[i].count);
					}
					fflush(stdout);
				}
				printf("\n");
			}
		}

		for (i=0;i <= 2;i++) tick[i] = read_8254(i);

		/* BUG: DOSBox/DOSBox-X appear to have a bug where the PC speaker readback toggles
		 *      regardless of the GATE input to Counter 2. Bring GATE low (setting bit 1
		 *      of port 61h to 0) is supposed to cause Counter 2 to stop. The AND gate
		 *      after the output (bit 0 of port 61h) is not supposed to affect the readback. */
		printf("\x0D %04x %04x %04x max=%04x count=%04x SPKR=%u",tick[0],tick[1],tick[2],
			max,counter,read_8254_pc_speaker_output()!=0?1:0);
		fflush(stdout);
	}
	printf("\n");

#ifdef TARGET_PC98
	/* PC-98 does not have IRQ0 running by default */
	p8259_mask(T8254_IRQ);
#endif

	_cli();
	write_8254_pc_speaker(0);
	t8254_pc_speaker_set_gate(0);
	_dos_setvect(T8254_IRQ+0x8,prev_irq0);
	_sti();

	write_8254_system_timer(0xFFFF); /* restore normal function to prevent BIOS from going crazy */
	return 0;
}
Exemplo n.º 15
0
/* this is used to probe for ports in standard locations, when we really don't know if it's there */
int probe_8250(uint16_t port) {
    unsigned char ier,dlab1,dlab2,c,fcr;
    struct info_8250 *inf;

    if (already_got_8250_port(port))
        return 0;
    if (base_8250_full())
        return 0;

    inf = &info_8250_port[base_8250_ports];
    inf->type = TYPE_8250_IS_8250;
    inf->port = port;
    inf->irq = -1;
    if (windows_mode == WINDOWS_NONE || windows_mode == WINDOWS_REAL) {
        /* in real-mode DOS we can play with the UART to our heart's content. so we play with the
         * DLAB select and interrupt enable registers to detect the UART in a manner non-destructive
         * to the hardware state. */

        /* there's no way to autodetect the COM port's IRQ, we have to guess */
        if (port == 0x3F8 || port == 0x3E8)
            inf->irq = 4;
        else if (port == 0x2F8 || port == 0x2E8)
            inf->irq = 3;

        /* switch registers 0+1 back to RX/TX and interrupt enable, and then test the Interrupt Enable register */
        _cli();
        outp(port+3,inp(port+3) & 0x7F);
        if (inp(port+3) == 0xFF) { _sti(); return 0; }
        ier = inp(port+1);
        outp(port+1,0);
        if (inp(port+1) == 0xFF) { _sti(); return 0; }
        outp(port+1,ier);
        if ((inp(port+1) & 0xF) != (ier & 0xF)) { _sti(); return 0; }
        /* then switch 0+1 to DLAB (divisor registers) and see if values differ from what we read the first time */
        outp(port+3,inp(port+3) | 0x80);
        dlab1 = inp(port+0);
        dlab2 = inp(port+1);
        outp(port+0,ier ^ 0xAA);
        outp(port+1,ier ^ 0x55);
        if (inp(port+1) == ier || inp(port+0) != (ier ^ 0xAA) || inp(port+1) != (ier ^ 0x55)) {
            outp(port+0,dlab1);
            outp(port+1,dlab2);
            outp(port+3,inp(port+3) & 0x7F);
            _sti();
            return 0;
        }
        outp(port+0,dlab1);
        outp(port+1,dlab2);
        outp(port+3,inp(port+3) & 0x7F);

        /* now figure out what type */
        fcr = inp(port+2);
        outp(port+2,0xE7);  /* write FCR */
        c = inp(port+2);    /* read IIR */
        if (c & 0x40) { /* if FIFO */
            if (c & 0x80) {
                if (c & 0x20) inf->type = TYPE_8250_IS_16750;
                else inf->type = TYPE_8250_IS_16550A;
            }
            else {
                inf->type = TYPE_8250_IS_16550;
            }
        }
        else {
            unsigned char oscratch = inp(port+7);

            /* no FIFO. try the scratch register */
            outp(port+7,0x55);
            if (inp(port+7) == 0x55) {
                outp(port+7,0xAA);
                if (inp(port+7) == 0xAA) {
                    outp(port+7,0x00);
                    if (inp(port+7) == 0x00) {
                        inf->type = TYPE_8250_IS_16450;
                    }
                }
            }

            outp(port+7,oscratch);
        }

        outp(port+2,fcr);
        _sti();
    }
    else {
        unsigned int i;

        /* if we were to actually do our self-test in a VM, Windows would mistakingly assume we
         * were trying to use it and would allocate the port. we're just enumerating at this point.
         * play it safe and assume it works if the port is listed as one of the BIOS ports.
         * we also don't use interrupts. */
        for (i=0;i < bios_8250_ports && port != get_8250_bios_port(i);) i++;
        if (i >= bios_8250_ports) return 0;
    }

    base_8250_port[base_8250_ports++] = port;
    return 1;
}
Exemplo n.º 16
0
qword sys_addTimerEvent(qword timerEventFunc, qword interval, qword rcx, qword r8, qword r9){
    _cli();
    addTimerListener((timerEventT) timerEventFunc,interval);
    _sti();
    return 0;
}
Exemplo n.º 17
0
void ess_sc_play_test(void) {
    unsigned char bytespersample = wav_16bit ? 2 : 1;
    unsigned long time,bytes,expect,tlen,timeout;
    unsigned long count;
    unsigned int pc,c;
    unsigned long d;
    uint32_t irqc;

    if (!sb_card->ess_extensions || sb_card->ess_chipset == 0)
        return;

    doubleprintf("ESS688 single cycle DSP playback test (%u bit).\n",wav_16bit?16:8);

    timeout = T8254_REF_CLOCK_HZ * 2UL;

    for (count=0;count < 256;count++) {
        if (count >= 128)
            expect = 795500UL / (256 - count);
        else
            expect = 397700UL / (128 - count);

        _cli();
        if (sb_card->irq >= 8) {
            p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (sb_card->irq & 7));
            p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | 2);
        }
        else if (sb_card->irq >= 0) {
            p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | sb_card->irq);
        }
        _sti();

        tlen = expect; // 1 sec
        if (tlen > (sb_card->buffer_size / (unsigned long)bytespersample)) tlen = sb_card->buffer_size / (unsigned long)bytespersample;

        /* NTS: We ask the card to use demand ISA, 4 bytes at a time.
         *      Behavior observed on real hardware, is that if you set up
         *      DMA this way and then set up a non-auto-init DMA transfer
         *      that isn't a multiple of 4, the DMA will stop short of
         *      the full transfer and the IRQ will never fire. Therefore
         *      the transfer length must be a multiple of 4! */
        tlen -= tlen & 3;
        if (tlen == 0) tlen = 4;

        sb_card->buffer_dma_started_length = tlen * (unsigned long)bytespersample;
        sb_card->buffer_dma_started = 0;

        sndsb_reset_dsp(sb_card);
        sndsb_write_dsp(sb_card,0xD1); /* speaker on */
        sndsb_ess_set_extended_mode(sb_card,1/*enable*/);
        sndsb_setup_dma(sb_card);
        irqc = sb_card->irq_counter;

        {
            /* ESS 688/1869 chipset specific DSP playback.
               using this mode bypasses a lot of the Sound Blaster Pro emulation
               and restrictions and allows us to run up to 48KHz 16-bit stereo */
            unsigned short t16;
            int b;

            _cli();

            /* clear IRQ */
            sndsb_interrupt_ack(sb_card,3);

            b = 0x00; /* DMA disable */
            b |= 0x00; /* no auto-init */
            b |= 0x00; /* [3]=DMA converter in ADC mode [1]=DMA read for ADC playback mode */
            sndsb_ess_write_controller(sb_card,0xB8,b);

            b = sndsb_ess_read_controller(sb_card,0xA8);
            b &= ~0xB; /* clear mono/stereo and record monitor (bits 3, 1, and 0) */
            b |= 2;	/* mono 10=mono 01=stereo */
            sndsb_ess_write_controller(sb_card,0xA8,b);

            /* NTS: The meaning of bits 1:0 in register 0xB9
             *
             *      00 single DMA transfer mode
             *      01 demand DMA transfer mode, 2 bytes/request
             *      10 demand DMA transfer mode, 4 bytes/request
             *      11 reserved
             *
             * NOTES on what happens if you set bits 1:0 (DMA transfer type) to the "reserved" 11 value:
             *
             *      ESS 688 (Sharp laptop)          Nothing, apparently. Treated the same as 4 bytes/request
             *
             *      ESS 1887 (Compaq Presario)      Triggers a hardware bug where the chip appears to fetch
             *                                      3 bytes per demand transfer but then only handle 1 byte,
             *                                      which translates to audio playing at 3x the sample rate
             *                                      it should be. NOT because the DAC is running any faster,
             *                                      but because the chip is only playing back every 3rd sample!
             *                                      This play only 3rds behavior is consistent across 8/16-bit
             *                                      PCM and mono/stereo.
             */

            b = 2;  /* demand transfer DMA 4 bytes per request */
            sndsb_ess_write_controller(sb_card,0xB9,b);

            sndsb_ess_write_controller(sb_card,0xA1,count);

            /* effectively disable the lowpass filter (NTS: 0xFF mutes the audio, apparently) */
            sndsb_ess_write_controller(sb_card,0xA2,0xFE);

            t16 = -(tlen * (uint16_t)bytespersample); /* DMA transfer count reload register value is 2's complement of length */
            sndsb_ess_write_controller(sb_card,0xA4,t16); /* DMA transfer count low */
            sndsb_ess_write_controller(sb_card,0xA5,t16>>8); /* DMA transfer count high */

            b = sndsb_ess_read_controller(sb_card,0xB1);
            b &= ~0xA0; /* clear compat game IRQ, fifo half-empty IRQs */
            b |= 0x50; /* set overflow IRQ, and "no function" */
            sndsb_ess_write_controller(sb_card,0xB1,b);

            b = sndsb_ess_read_controller(sb_card,0xB2);
            b &= ~0xA0; /* clear compat */
            b |= 0x50; /* set DRQ/DACKB inputs for DMA */
            sndsb_ess_write_controller(sb_card,0xB2,b);

            b = 0x51; /* enable FIFO+DMA, reserved, load signal */
	        b |= wav_16bit ? 0x20 : 0x00; /* signed complement mode or not */
            sndsb_ess_write_controller(sb_card,0xB7,b);

            b = 0x90; /* enable FIFO+DMA, reserved, load signal */
	        b |= wav_16bit ? 0x20 : 0x00; /* signed complement mode or not */
            b |= 0x40; /* [3]=stereo [6]=!stereo */
            b |= wav_16bit ? 0x04 : 0x00; /* [2]=16bit */
            sndsb_ess_write_controller(sb_card,0xB7,b);

            b = sndsb_ess_read_controller(sb_card,0xB8);
            sndsb_ess_write_controller(sb_card,0xB8,b | 1);
        }

        _cli();
        c = read_8254(T8254_TIMER_INTERRUPT_TICK);
        bytes = tlen;
        time = 0;
        _sti();

        while (1) {
            if (irqc != sb_card->irq_counter)
                break;

            _cli();
            pc = c;
            c = read_8254(T8254_TIMER_INTERRUPT_TICK);
            time += (unsigned long)((pc - c) & 0xFFFFU); /* remember: it counts DOWN. assumes full 16-bit count */
            _sti();

            if (time >= timeout) goto x_timeout;
        }

x_complete:
        if (time == 0UL) time = 1;

        {
            int b;

            b = sndsb_ess_read_controller(sb_card,0xB8);
            if (b != -1) {
                b &= ~0x01; /* stop DMA */
                sndsb_ess_write_controller(sb_card,0xB8,b);
            }
        }

        {
            double t = (double)time / T8254_REF_CLOCK_HZ;
            double rate = (double)bytes / t;

            doubleprintf(" - TC 0x%02lX: expecting %luHz, %lu%c/%.3fs @ %.3fHz\n",count,expect,(unsigned long)bytes,wav_16bit?'w':'b',t,rate);
        }

        if (kbhit()) {
            if (getch() == 27)
                break;
        }

        continue;
x_timeout:
        d = d8237_read_count(sb_card->dma8) / (unsigned long)bytespersample; /* counts DOWNWARD */
        if (d > tlen) d = 0; /* terminal count */
        d = tlen - d;

        if (irqc == sb_card->irq_counter && d == 0) bytes = 0; /* nothing happened if no IRQ and counter never changed */
        else if (bytes > d) bytes = d;
        goto x_complete;
    }

    _cli();
    if (sb_card->irq >= 8) {
        p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (sb_card->irq & 7));
        p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | 2);
    }
    else if (sb_card->irq >= 0) {
        p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | sb_card->irq);
    }
    _sti();

    sndsb_reset_dsp(sb_card);
}
Exemplo n.º 18
0
void sb16_sc_play_test(void) {
    unsigned char bytespersample = wav_16bit ? 2 : 1;
    unsigned long time,bytes,expect,tlen,timeout;
    unsigned long count;
    unsigned int pc,c;
    unsigned long d;
    uint32_t irqc;
    int dma;

    if (wav_16bit && sb_card->dma16 >= 4)
        dma = sb_card->dma16;
    else
        dma = sb_card->dma8;

    if (sb_card->dsp_vmaj >= 4) /* Sound Blaster 16 */
        { }
    else if (sb_card->is_gallant_sc6600) /* Reveal SC-4000 / Gallant SC-6600 */
        { }
    else 
        return;

    doubleprintf("SB16 4.x single cycle DSP playback test (%u bit).\n",wav_16bit?16:8);

    timeout = T8254_REF_CLOCK_HZ * 2UL;

    count = 0;
    do {
        expect = count;

        _cli();
        if (sb_card->irq >= 8) {
            p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (sb_card->irq & 7));
            p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | 2);
        }
        else if (sb_card->irq >= 0) {
            p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | sb_card->irq);
        }
        _sti();

        tlen = expect; // 1 sec
        if (tlen < 4000UL) tlen = 4000UL;
        if (tlen > (sb_card->buffer_size / (unsigned long)bytespersample)) tlen = sb_card->buffer_size / (unsigned long)bytespersample;

        sb_card->buffer_dma_started_length = tlen * (unsigned long)bytespersample;
        sb_card->buffer_dma_started = 0;

        sndsb_reset_dsp(sb_card);
        sndsb_write_dsp(sb_card,0xD1); /* speaker on */
        sndsb_setup_dma(sb_card);
        irqc = sb_card->irq_counter;

        sndsb_write_dsp_outrate(sb_card,count);

        _cli();
        c = read_8254(T8254_TIMER_INTERRUPT_TICK);
        bytes = tlen;
        time = 0;
        _sti();

        {
            unsigned int lv = (unsigned int)(tlen - 1UL);

            /* NTS: Reveal SC-4000 (Gallant 6600) cards DO support SB16 but only specific commands.
             *      Command 0xC0 is not recognized, but command 0xC6 works. */
            if (wav_16bit) {
                if (sb_card->is_gallant_sc6600)
                    sndsb_write_dsp(sb_card,SNDSB_DSPCMD_SB16_AUTOINIT_DMA_DAC_OUT_16BIT); /* 0xB6 */
                else
                    sndsb_write_dsp(sb_card,SNDSB_DSPCMD_SB16_DMA_DAC_OUT_16BIT); /* 0xB0 */

                sndsb_write_dsp(sb_card,0x10); /* mode (16-bit signed PCM) */
            }
            else {
                if (sb_card->is_gallant_sc6600)
                    sndsb_write_dsp(sb_card,SNDSB_DSPCMD_SB16_AUTOINIT_DMA_DAC_OUT_8BIT); /* 0xC6 */
                else
                    sndsb_write_dsp(sb_card,SNDSB_DSPCMD_SB16_DMA_DAC_OUT_8BIT); /* 0xC0 */

                sndsb_write_dsp(sb_card,0x00); /* mode (8-bit unsigned PCM) */
            }

            sndsb_write_dsp(sb_card,lv);
            sndsb_write_dsp(sb_card,lv >> 8);
        }

        while (1) {
            if (irqc != sb_card->irq_counter)
                break;

            _cli();
            pc = c;
            c = read_8254(T8254_TIMER_INTERRUPT_TICK);
            time += (unsigned long)((pc - c) & 0xFFFFU); /* remember: it counts DOWN. assumes full 16-bit count */
            _sti();

            if (time >= timeout) goto x_timeout;
        }

x_complete:
        if (time == 0UL) time = 1;

        {
            double t = (double)time / T8254_REF_CLOCK_HZ;
            double rate = (double)bytes / t;

            doubleprintf(" - Rate 0x%04lX: expecting %luHz, %lu%c/%.3fs @ %.3fHz\n",count,expect,(unsigned long)bytes,wav_16bit?'w':'b',t,rate);
        }

        if (kbhit()) {
            if (getch() == 27)
                break;
        }

        count += 0x80; /* count by 128 because enumerating all would take too long */
        if (count > 0xFFFFUL) break;

        continue;
x_timeout:
        d = d8237_read_count(dma) / (unsigned long)bytespersample; /* counts DOWNWARD */
        if (d > tlen) d = 0; /* terminal count */
        d = tlen - d;

        if (irqc == sb_card->irq_counter && d == 0) bytes = 0; /* nothing happened if no IRQ and counter never changed */
        else if (bytes > d) bytes = d;
        goto x_complete;
    } while (1);

    _cli();
    if (sb_card->irq >= 8) {
        p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (sb_card->irq & 7));
        p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | 2);
    }
    else if (sb_card->irq >= 0) {
        p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | sb_card->irq);
    }
    _sti();

    sndsb_reset_dsp(sb_card);

    sndsb_write_dsp_outrate(sb_card,8000U);
}
Exemplo n.º 19
0
int main(int argc,char *argv[],char *envp[]) {
	rdtsc_t start,measure,ticks_per_sec;
    unsigned char force = 0;
	double t;
	int c;

    {
        int i = 1;
        char *a;

        while (i < argc) {
            a = argv[i++];

            if (*a == '-') {
                do { a++; } while (*a == '-');

                if (!strcmp(a,"f") || !strcmp(a,"force"))
                    force = 1;
                else
                    return 1;
            }
            else {
                return 1;
            }
        }
    }

	cpu_probe();
	printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level));
	if (cpu_v86_active)
		printf(" - Your CPU is currently running me in virtual 8086 mode\n");

    if (force) {
        printf(" - You're forcing me to use RDTSC. I may crash if your CPU doesn't\n");
        printf("   support it or the environment doesn't enable it.\n");
        printf("   OK! Here we go....!\n");
    }
    else {
        if (!(cpu_flags & CPU_FLAG_CPUID)) {
            printf(" - Your CPU doesn't support CPUID, how can it support RDTSC?\n");
            return 1;
        }

        if (!(cpu_cpuid_features.a.raw[2] & 0x10)) {
            printf(" - Your CPU does not support RDTSC\n");
            return 1;
        }

        if (cpu_flags & CPU_FLAG_DONT_USE_RDTSC) {
            printf(" - Your CPU does support RDTSC but it's not recommended in this environment.\n");
            printf("   This is usually due to running a 16-bit build in pure DOS under EMM386.EXE.\n");
            return 1;
        }
    }

#if defined(TARGET_OS2)
# if TARGET_MSDOS == 32
	/* OS/2 32-bit: We can use DosQuerySysInfo() */
	printf("Measuring CPU speed, using DosQuerySysInfo(), over 3 seconds\n");
	{
		ULONG startTick,tmp;
		start = cpu_rdtsc();
		startTick = GetMsCount();
		do { tmp = GetMsCount();
		} while ((tmp - startTick) < 3000); /* NTS: <- I know this rolls over in 49 days,
		the math though should overflow the 32-bit integer and produce correct results anyway */
		measure = cpu_rdtsc();

		/* use the precise tick count to better compute ticks_per_sec */
		ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick));
		printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec);
		printf("             From 0x%llX to 0x%llX\n",start,measure);
	}
# else
	/* OS/2 16-bit: There is no API (that I know of) to get tick count. Use system clock. */
	printf("Measuring CPU speed, using system clock with 1-second resolution, across 3 seconds\n");
	{
		time_t startTick,tmp;

		/* wait for the immediate start of a one-second tick, then record RDTSC and count until 3 seconds */
		startTick = time(NULL);
		do { tmp = time(NULL); } while (tmp == startTick);
		start = cpu_rdtsc(); startTick = tmp;

		/* NOW! Count 3 seconds and measure CPU ticks */
		do { tmp = time(NULL);
		} while ((tmp - startTick) < 3);
		measure = cpu_rdtsc();

		/* use the precise tick count to better compute ticks_per_sec */
		ticks_per_sec = ((measure - start) * 1ULL) / ((rdtsc_t)(tmp - startTick));
		printf("Measurement: %lu seconds = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec);
		printf("             From 0x%llX to 0x%llX\n",start,measure);
	}
# endif
#elif defined(TARGET_WINDOWS)
# if TARGET_MSDOS == 16
	/* Windows 2.x/3.0/3.1: Use GetTickCount() or
	 * Windows 3.1: Use TOOLHELP.DLL TimerCount() which is more accurate (really?) */
	if (ToolHelpInit()) {
		TIMERINFO ti;

		ti.dwSize = sizeof(ti);
		printf("Measuring CPU speed, using TOOLHELP TimerCount() over 1 second\n");
		{
			DWORD startTick,tmp;
			start = cpu_rdtsc();
			if (!__TimerCount(&ti)) {
				printf("TimerCount() failed\n");
				return 1;
			}
			startTick = ti.dwmsSinceStart;
			do {
#  if defined(WIN_STDOUT_CONSOLE)
				_win_pump(); /* <- you MUST call this. The message pump must run, or else the timer won't advance and this loop will run forever.
			                           The fact that GetTickCount() depends on a working message pump under Windows 3.1 seems to be a rather serious
						   oversight on Microsoft's part. Note that the problem described here does not apply to Windows 9x/ME. Also note
						   the Toolhelp function TimerCount() relies on GetTickCount() as a basic for time (though Toolhelp uses VxD services
						   or direct I/O port hackery to refine the timer count) */
#  endif

				if (!__TimerCount(&ti)) {
					printf("TimerCount() failed\n");
					return 1;
				}

				tmp = ti.dwmsSinceStart;
			} while ((tmp - startTick) < 1000); /* NTS: <- I know this rolls over in 49 days,
			the math though should overflow the 32-bit integer and produce correct results anyway */
			measure = cpu_rdtsc();

			/* use the precise tick count to better compute ticks_per_sec */
			ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick));
			printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec);
			printf("             From 0x%llX to 0x%llX\n",start,measure);
		}
	}
	else {
# else
	{
# endif
		printf("Measuring CPU speed, using GetTickCount() over 3 second\n");
		{
			DWORD startTick,tmp;
			start = cpu_rdtsc();
			startTick = GetTickCount();
			/* NTS: Dunno yet about Windows 3.1, but Windows 95 seems to require we Yield(). If we don't, the GetTickCount() return
			 *      value never updates and we're forever stuck in a loop. */
			do {
#  if defined(WIN_STDOUT_CONSOLE)
				_win_pump(); /* <- you MUST call this. The message pump must run, or else the timer won't advance and this loop will run forever.
			                           The fact that GetTickCount() depends on a working message pump under Windows 3.1 seems to be a rather serious
						   oversight on Microsoft's part. Note that the problem described here does not apply to Windows 9x/ME */
#  endif
				tmp = GetTickCount();
			} while ((tmp - startTick) < 3000); /* NTS: <- I know this rolls over in 49 days,
			the math though should overflow the 32-bit integer and produce correct results anyway */
			measure = cpu_rdtsc();

			/* use the precise tick count to better compute ticks_per_sec */
			ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick));
			printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec);
			printf("             From 0x%llX to 0x%llX\n",start,measure);
		}
	}
#else
	/* MS-DOS: Init the 8254 timer library for precise measurement */
	if (!probe_8254()) {
		printf("Cannot init 8254 timer\n");
		return 1;
	}

    /* DOSBox-X and most motherboards leave the PIT in a mode that counts down by 2.
     * Our code sets the counter and puts it in a mode that counts down by 1.
     * We have to do this or our wait functions exit in half the time (which explains
     * why testing this code in DOSBox-X often comes up with RDTSC running at 2x
     * normal speed. */
    write_8254_system_timer(0); /* 18.2 tick/sec on our terms (proper PIT mode) */

	printf("Measuring CPU speed (relative to 8254 timer)\n");

	_cli();
	start = cpu_rdtsc();
	t8254_wait(t8254_us2ticks(1000000));
	measure = cpu_rdtsc();
	_sti();

	printf("Measurement: 1 sec = %lld ticks\n",(int64_t)(measure - start));
	printf("             From 0x%llX to 0x%llX\n",start,measure);
	ticks_per_sec = (measure - start);
#endif

	if ((int64_t)ticks_per_sec < 0) {
		printf("Cannot determine CPU cycle count\n");
		ticks_per_sec = 100000ULL;
	}

	while (1) {
		measure = cpu_rdtsc();
		t = (double)((int64_t)(measure - start));
		t /= ticks_per_sec;

		printf("\x0D" "0x%llX = %.3f   ",measure,t);
#if !defined(WINFCON_STOCK_WIN_MAIN)
		fflush(stdout); /* FIXME: The fake console code should intercept fflush() too */
#endif

		if (kbhit()) {
			c = getch();
			if (c == 0) c = getch() << 8;

			if (c == 27)
				break;
			else if (c == 'r' || c == 'R') {
				if (c == 'r' || (cpu_flags & CPU_FLAG_DONT_WRITE_RDTSC)) {
					printf("\nI am not able to write the TSC register within this environment\nYou can force me by typing SHIFT+R, don't blame me when I crash...\n");
				}
				else {
					printf("\nUsing MSR to reset TSC to 0\n");
					/* demonstrating WRMSR to write the TSC (yes, you can!) */
					cpu_rdtsc_write(start = 0ULL);
					printf("Result: 0x%llX\n",cpu_rdtsc());
				}
			}
			else if (c == 's') {
				if (c == 's' && (cpu_flags & CPU_FLAG_DONT_WRITE_RDTSC)) {
					printf("\nI am not able to write the TSC register within this environment\nYou can force me by typing SHIFT+S, don't blame me when I crash...\n");
				}
				else {
					printf("\nUsing MSR to reset TSC to 0x123456789ABCDEF\n");
					/* demonstrating WRMSR to write the TSC (yes, you can!) */
					cpu_rdtsc_write(start = 0x123456789ABCDEFULL);
					printf("Result: 0x%llX\n",cpu_rdtsc());
				}
			}
		}
	}
	printf("\n");

	return 0;
}
Exemplo n.º 20
0
void sb1_sc_play_adpcm2_test(void) {
    unsigned long time,bytes,expect,tlen,timeout;
    unsigned int count;
    unsigned int pc,c;
    unsigned long d;
    uint32_t irqc;

    doubleprintf("SB 1.x ADPCM 2-bit single cycle DSP playback test.\n");

    timeout = T8254_REF_CLOCK_HZ * 4UL;

    for (count=0;count < 256;count++) {
        expect = 1000000UL / (unsigned long)(256 - count);

        _cli();
        if (sb_card->irq >= 8) {
            p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (sb_card->irq & 7));
            p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | 2);
        }
        else if (sb_card->irq >= 0) {
            p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | sb_card->irq);
        }
        _sti();

        tlen = (expect / 4UL) + 1; // 1 sec
        if (tlen > sb_card->buffer_size) tlen = sb_card->buffer_size;

        sb_card->buffer_dma_started_length = tlen;
        sb_card->buffer_dma_started = 0;

        sndsb_reset_dsp(sb_card);
        sndsb_write_dsp(sb_card,0xD1); /* speaker on */
        sndsb_setup_dma(sb_card);
        irqc = sb_card->irq_counter;

        sndsb_write_dsp_timeconst(sb_card,count);

        _cli();
        c = read_8254(T8254_TIMER_INTERRUPT_TICK);
        bytes = tlen;
        time = 0;
        _sti();

        {
            unsigned int lv = (unsigned int)(tlen - 1UL);

            sndsb_write_dsp(sb_card,SNDSB_DSPCMD_DMA_DAC_OUT_ADPCM_2BIT_REF); /* 0x17 */
            sndsb_write_dsp(sb_card,lv);
            sndsb_write_dsp(sb_card,lv >> 8);
        }

        while (1) {
            if (irqc != sb_card->irq_counter)
                break;

            _cli();
            pc = c;
            c = read_8254(T8254_TIMER_INTERRUPT_TICK);
            time += (unsigned long)((pc - c) & 0xFFFFU); /* remember: it counts DOWN. assumes full 16-bit count */
            _sti();

            if (time >= timeout) goto x_timeout;
        }

x_complete:
        if (time == 0UL) time = 1;

        {
            double t = (double)time / T8254_REF_CLOCK_HZ;
            double rate = (double)(((bytes - 1UL) * 4UL) + 1UL) / t; /* 4 samples/byte + 1 reference */

            doubleprintf(" - TC 0x%02X: expecting %luHz, %lub/%.3fs @ %.3fHz\n",count,expect,(unsigned long)bytes,t,rate);
        }

        if (kbhit()) {
            if (getch() == 27)
                break;
        }

        continue;
x_timeout:
        d = d8237_read_count(sb_card->dma8); /* counts DOWNWARD */
        if (d > tlen) d = 0; /* terminal count */
        d = tlen - d;

        if (irqc == sb_card->irq_counter && d == 0) bytes = 0; /* nothing happened if no IRQ and counter never changed */
        else if (bytes > d) bytes = d;
        goto x_complete;
    }

    _cli();
    if (sb_card->irq >= 8) {
        p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (sb_card->irq & 7));
        p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | 2);
    }
    else if (sb_card->irq >= 0) {
        p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | sb_card->irq);
    }
    _sti();

    sndsb_write_dsp_timeconst(sb_card,0x83); /* 8000Hz */

    sndsb_reset_dsp(sb_card);
}
Exemplo n.º 21
0
qword sys_removeTimerEvent(qword timerEventFunc, qword rdx, qword rcx, qword r8, qword r9) {
    _cli();
    deleteTimerListener((timerEventT) timerEventFunc);
    _sti();
    return 0;
}