Example #1
0
static void write_p64(Bitu port,Bitu val,Bitu iolen) {
	switch (val) {
	case 0xae:		/* Activate keyboard */
		keyb.active=true;
		if (keyb.used && !keyb.scheduled && !keyb.p60changed) {
			keyb.scheduled=true;
			PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
		}
		LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated");
		break;
	case 0xad:		/* Deactivate keyboard */
		keyb.active=false;
		LOG(LOG_KEYBOARD,LOG_NORMAL)("De-Activated");
		break;
	case 0xd0:		/* Outport on buffer */
		KEYBOARD_SetPort60(MEM_A20_Enabled() ? 0x02 : 0);
		break;
	case 0xd1:		/* Write to outport */
		keyb.command=CMD_SETOUTPORT;
		break;
	default:
		LOG(LOG_KEYBOARD,LOG_ERROR)("Port 64 write with val %d",val);
		break;
	}
}
Example #2
0
void Mouse_AddEvent(Bit8u type)
	{
	if (mouse.events < QUEUE_SIZE)
		{
		if (mouse.events > 0)
			{
			if (type == MOUSE_HAS_MOVED)			// Skip duplicate events
				return;
			/* Always put the newest element in the front as that the events are 
			 * handled backwards (prevents doubleclicks while moving)
			 */
			for (Bitu i = mouse.events; i; i--)
				mouse.event_queue[i] = mouse.event_queue[i-1];
			}
		mouse.event_queue[0].type = type;
		mouse.event_queue[0].buttons = mouse.buttons;
		mouse.events++;
		}
	if (!mouse.timer_in_progress)
		{
		mouse.timer_in_progress = true;
		PIC_AddEvent(MOUSE_Limit_Events, MOUSE_DELAY);
		PIC_ActivateIRQ(MOUSE_IRQ);
		}
	}
Example #3
0
static void MPU401_EOIHandlerDispatch(void) {
	if (mpu.state.send_now) {
		mpu.state.eoi_scheduled=true;
                PIC_AddEvent(EOI_HANDLER,1); // Possible a bit longer
	}
	else if (!mpu.state.eoi_scheduled) MPU401_EOIHandler();
}
static void cmos_timerevent(Bitu val) {
	PIC_ActivateIRQ(8); 
	if (cmos.timer.enabled) {
		PIC_AddEvent(cmos_timerevent,cmos.timer.delay);
		cmos.regs[0xc] = 0xC0;//Contraption Zack (music)
	}
}
Example #5
0
void MPU401_Event(void) {
	/* SOFTMPU */
	Bit8u i;
	Bitu new_time;
	if (mpu.mode==M_UART) return;
	if (mpu.state.irq_pending) goto next_event;
	for (i=0;i<8;i++) { /* Decrease counters */
		if (mpu.state.amask&(1<<i)) {
			mpu.playbuf[i].counter--;
			if (mpu.playbuf[i].counter<=0) UpdateTrack(i);
		}
	}               
	if (mpu.state.conductor) {
		mpu.condbuf.counter--;
		if (mpu.condbuf.counter<=0) UpdateConductor();
	}
	if (mpu.clock.clock_to_host) {
		mpu.clock.cth_counter++;
		if (mpu.clock.cth_counter >= mpu.clock.cth_rate) {
			mpu.clock.cth_counter=0;
			mpu.state.req_mask|=(1<<13);
		}
	}
	if (!mpu.state.irq_pending && mpu.state.req_mask) MPU401_EOIHandler();
next_event:
	PIC_RemoveEvents(MPU_EVENT);
	if ((new_time=mpu.clock.tempo*mpu.clock.timebase)==0) return;
        PIC_AddEvent(MPU_EVENT,(Bitu)MPU401_TIMECONSTANT/new_time);
}
static void cmos_checktimer(void) {
	PIC_RemoveEvents(cmos_timerevent);	
	if (cmos.timer.div<=2) cmos.timer.div+=7;
	cmos.timer.delay=(1000.0f/(32768.0f / (1 << (cmos.timer.div - 1))));
	if (!cmos.timer.div || !cmos.timer.enabled) return;
	LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %.2f hz",1000.0/cmos.timer.delay);
	PIC_AddEvent(cmos_timerevent,cmos.timer.delay);
}
Example #7
0
static Bitu read_p60(Bitu port,Bitu iolen) {
	keyb.p60changed=false;
	if (!keyb.scheduled && keyb.used) {
		keyb.scheduled=true;
		PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
	}
	return keyb.p60data;
}	
Example #8
0
void MOUSE_Limit_Events(Bitu /*val*/) {
	mouse.timer_in_progress = false;
	if (mouse.events) {
		mouse.timer_in_progress = true;
		PIC_AddEvent(MOUSE_Limit_Events,MOUSE_DELAY);
		PIC_ActivateIRQ(MOUSE_IRQ);
	}
}
Example #9
0
Bitu MOUSE_UserInt_CB_Handler(void) {
	mouse.in_UIR = false;
	if (mouse.events) {
		if (!mouse.timer_in_progress) {
			mouse.timer_in_progress = true;
			PIC_AddEvent(MOUSE_Limit_Events,MOUSE_DELAY);
		}
	}
	return CBRET_NONE;
}
Example #10
0
static void cmos_checktimer(void) {
	PIC_RemoveEvents(cmos_timerevent);	
	if (cmos.timer.div<=2) cmos.timer.div+=7;
	cmos.timer.delay=(1000.0f/(32768.0f / (1 << (cmos.timer.div - 1))));
	if (!cmos.timer.div || !cmos.timer.enabled) return;
	LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %.2f hz",1000.0/cmos.timer.delay);
//	PIC_AddEvent(cmos_timerevent,cmos.timer.delay);
	/* A rtc is always running */
	double remd=fmod(PIC_FullIndex(),(double)cmos.timer.delay);
	PIC_AddEvent(cmos_timerevent,(float)((double)cmos.timer.delay-remd)); //Should be more like a real pc. Check
//	status reg A reading with this (and with other delays actually)
}
Example #11
0
static void KEYBOARD_AddBuffer(Bit16u data) {
	if (keyb.used>=KEYBUFSIZE) {
		LOG(LOG_KEYBOARD,LOG_NORMAL)("Buffer full, dropping code");
		KEYBOARD_ClrBuffer(); return;
	}
	Bitu start=keyb.pos+keyb.used;
	if (start>=KEYBUFSIZE) start-=KEYBUFSIZE;
	keyb.buffer[start]=data;
	keyb.used++;
	/* Start up an event to start the first IRQ */
	if (!keyb.scheduled && !keyb.p60changed) {
		keyb.scheduled=true;
		PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
	}
}
Example #12
0
static void KEYBOARD_Add8042Response(Bit8u data) {
	if(!keyb.enable_aux) return;
	if (keyb.buf8042_pos >= keyb.buf8042_len)
		keyb.buf8042_pos = keyb.buf8042_len = 0;
	else if (keyb.buf8042_len == 0)
		keyb.buf8042_pos = 0;

	if (keyb.buf8042_pos >= sizeof(keyb.buf8042)) {
		LOG(LOG_KEYBOARD,LOG_NORMAL)("8042 Buffer full, dropping code");
		KEYBOARD_ClrBuffer(); return;
	}

	keyb.buf8042[keyb.buf8042_len++] = data;
	PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
}
Example #13
0
static void write_p60(Bitu port,Bitu val,Bitu iolen) {
	switch (keyb.command) {
	case CMD_NONE:	/* None */
		if (keyb.reset)
			return;

		/* No active command this would normally get sent to the keyboard then */
		KEYBOARD_ClrBuffer();
		switch (val) {
		case 0xed:	/* Set Leds */
			keyb.command=CMD_SETLEDS;
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
			break;
		case 0xee:	/* Echo */
			KEYBOARD_AddBuffer(0xee);	/* JC: The correct response is 0xEE, not 0xFA */
			break;
		case 0xf0:	/* set scancode set */
			keyb.command=CMD_SETSCANSET;
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
			break;
		case 0xf2:	/* Identify keyboard */
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
			KEYBOARD_AddBuffer(0xab);	/* ID */
			KEYBOARD_AddBuffer(0x83);
			break;
		case 0xf3: /* Typematic rate programming */
			keyb.command=CMD_SETTYPERATE;
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
			break;
		case 0xf4:	/* Enable keyboard,clear buffer, start scanning */
			LOG(LOG_KEYBOARD,LOG_NORMAL)("Clear buffer, enable scanning");
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
			keyb.scanning=true;
			break;
		case 0xf5:	 /* Reset keyboard and disable scanning */
			LOG(LOG_KEYBOARD,LOG_NORMAL)("Reset, disable scanning");			
			keyb.scanning=false;
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
			break;
		case 0xf6:	/* Reset keyboard and enable scanning */
			LOG(LOG_KEYBOARD,LOG_NORMAL)("Reset, enable scanning");
			keyb.scanning=true;		/* JC: Original DOSBox code was wrong, this command enables scanning */
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
			break;
		case 0xff:		/* keyboard resets take a long time (about 250ms), most keyboards flash the LEDs during reset */
			KEYBOARD_Reset();
			KEYBOARD_Add8042Response(0xFA);	/* ACK */
			KEYBOARD_Add8042Response(0xAA); /* SELF TEST OK (TODO: Need delay!) */
			keyb.reset=true;
			KEYBOARD_SetLEDs(7); /* most keyboard I test with tend to flash the LEDs during reset */
			PIC_AddEvent(KEYBOARD_ResetDelay,RESETDELAY);
			break;
		default:
			/* Just always acknowledge strange commands */
			LOG(LOG_KEYBOARD,LOG_ERROR)("60:Unhandled command %X",(int)val);
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
		}
		return;
	case CMD_SETSCANSET:
		keyb.command=CMD_NONE;
		if (val == 0) { /* just asking */
			if (keyb.cb_xlat) {
				switch (keyb.scanset) {
					case 1:	KEYBOARD_AddBuffer(0x43); break;
					case 2:	KEYBOARD_AddBuffer(0x41); break;
					case 3:	KEYBOARD_AddBuffer(0x3F); break;
				}
			}
			else {
				KEYBOARD_AddBuffer(keyb.scanset);
			}
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
		}
		else {
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge again */
			if (val > 3) val = 3;
			keyb.scanset = val;
		}
		break;
	case CMD_WRITEAUX:
		keyb.command=CMD_NONE;
		KEYBOARD_AUX_Write(val);
		break;
	case CMD_WRITEOUTPUT:
		keyb.command=CMD_NONE;
		KEYBOARD_ClrBuffer();
		KEYBOARD_AddBuffer(val);	/* and now you return the byte as if it were typed in */
		break;
	case CMD_WRITEAUXOUT:
		KEYBOARD_AddBuffer(AUX|val); /* stuff into AUX output */
		break;
	case CMD_SETOUTPORT:
		if (!(val & 1)) {
			if (allow_keyb_reset) {
				LOG_MSG("Restart by keyboard controller requested\n");
				On_Software_CPU_Reset();
			}
			else {
				LOG_MSG("WARNING: Keyboard output port written with bit 1 clear. Is the guest OS or application attempting to reset the system?\n");
			}
		}
		MEM_A20_Enable((val & 2)>0);
		keyb.command = CMD_NONE;
		break;
	case CMD_SETTYPERATE: 
		if (keyb.reset)
			return;

		{
			static const int delay[] = { 250, 500, 750, 1000 };
			static const int repeat[] =
			{ 33,37,42,46,50,54,58,63,67,75,83,92,100,
			  109,118,125,133,149,167,182,200,217,233,
			  250,270,303,333,370,400,435,476,500 };
			keyb.repeat.pause = delay[(val >> 5) & 3];
			keyb.repeat.rate = repeat[val & 0x1f];
			keyb.command = CMD_NONE;
			KEYBOARD_ClrBuffer();
			KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
		}
		break;
	case CMD_SETLEDS:
		if (keyb.reset)
			return;

		keyb.command=CMD_NONE;
		KEYBOARD_ClrBuffer();
		KEYBOARD_AddBuffer(0xfa);	/* Acknowledge */
		KEYBOARD_SetLEDs(val&7);
		break;
	case CMD_SETCOMMAND: /* 8042 command, not keyboard */
		/* TODO: If biosps2=true and aux=false, disallow the guest OS from changing AUX port parameters including IRQ */
		keyb.command=CMD_NONE;
		keyb.cb_xlat = (val >> 6) & 1;
		keyb.auxactive = !((val >> 5) & 1);
		keyb.active = !((val >> 4) & 1);
		keyb.cb_sys = (val >> 2) & 1;
		keyb.cb_irq12 = (val >> 1) & 1;
		keyb.cb_irq1 = (val >> 0) & 1;
		if (keyb.used && !keyb.scheduled && !keyb.p60changed && keyb.active) {
			keyb.scheduled=true;
			PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
		}
		break;
	}
}
Example #14
0
static void DISNEY_CallBack(Bitu len) {
	if (!len) return;

	// get the smaller used
	Bitu real_used;
	if(disney.stereo) {
		real_used = disney.da[0].used;
		if(disney.da[1].used < real_used) real_used = disney.da[1].used;
	} else
		real_used = disney.leader->used;

	if (real_used >= len) { // enough data for now
		if(disney.stereo) DISNEY_PlayStereo(len, disney.da[0].buffer, disney.da[1].buffer);
		else disney.chan->AddSamples_m8(len,disney.leader->buffer);

		// put the rest back to start
		for(int i = 0; i < 2; i++) {
			// TODO for mono only one 
			memmove(disney.da[i].buffer,&disney.da[i].buffer[len],DISNEY_SIZE/*real_used*/-len);
			disney.da[i].used -= len;
		}
	// TODO: len > DISNEY
	} else { // not enough data
		if(disney.stereo) {
			Bit8u gapfiller0 = 128;
			Bit8u gapfiller1 = 128;
			if(real_used) {
				gapfiller0 = disney.da[0].buffer[real_used-1];
				gapfiller1 = disney.da[1].buffer[real_used-1];
			};

			memset(disney.da[0].buffer+real_used,
				gapfiller0,len-real_used);
			memset(disney.da[1].buffer+real_used,
				gapfiller1,len-real_used);

			DISNEY_PlayStereo(len, disney.da[0].buffer, disney.da[1].buffer);
			len -= real_used;

		} else { // mono
			Bit8u gapfiller = 128; //Keep the middle
			if(real_used) {
				// fix for some stupid game; it outputs 0 at the end of the stream
				// causing a click. So if we have at least two bytes availible in the
				// buffer and the last one is a 0 then ignore that.
				if(disney.leader->buffer[real_used-1]==0)
					real_used--;
			}
			// do it this way because AddSilence sounds like a gnawing mouse
			if(real_used)
				gapfiller = disney.leader->buffer[real_used-1];
			//LOG_MSG("gapfiller %x, fill len %d, realused %d",gapfiller,len-real_used,real_used);
			memset(disney.leader->buffer+real_used,	gapfiller, len-real_used);
			disney.chan->AddSamples_m8(len, disney.leader->buffer);
		}
		disney.da[0].used =0;
		disney.da[1].used =0;

		//LOG_MSG("disney underflow %d",len - real_used);
	}
	if (disney.last_used+100<PIC_Ticks) {
		// disable sound output
		PIC_AddEvent(DISNEY_disable,0.0001f);	// I think we shouldn't delete the 
												// mixer while we are inside it
	}
}
Example #15
0
static void write_p64(Bitu port,Bitu val,Bitu iolen) {
	if (keyb.reset)
		return;

	switch (val) {
	case 0x20:		/* read command byte */
		/* TODO: If biosps2=true and aux=false, mask AUX port bits as if AUX isn't there */
		KEYBOARD_Add8042Response(
			(keyb.cb_xlat << 6)      | ((!keyb.auxactive) << 5) |
			((!keyb.active) << 4)    | (keyb.cb_sys << 2) |
			(keyb.cb_irq12 << 1)     | (keyb.cb_irq1?1:0));
		break;
	case 0x60:
		keyb.command=CMD_SETCOMMAND;
		break;
	case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
	case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
		/* TODO: If bit 0 == 0, trigger system reset */
		break;
	case 0xa7:		/* disable aux */
		/* TODO: If biosps2=true and aux=false do not respond */
		if (keyb.enable_aux) {
			//keyb.auxactive=false;
			//LOG(LOG_KEYBOARD,LOG_NORMAL)("AUX De-Activated");
		}
		break;
	case 0xa8:		/* enable aux */
		/* TODO: If biosps2=true and aux=false do not respond */
		if (keyb.enable_aux) {
			keyb.auxactive=true;
			if (keyb.used && !keyb.scheduled && !keyb.p60changed) {
				keyb.scheduled=true;
				PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
			}
			LOG(LOG_KEYBOARD,LOG_NORMAL)("AUX Activated");
		}
		break;
	case 0xa9:		/* mouse interface test */
		/* TODO: If biosps2=true and aux=false do not respond */
		KEYBOARD_Add8042Response(0x00); /* OK */
		break;
	case 0xaa:		/* Self test */
		keyb.active=false; /* on real h/w it also seems to disable the keyboard */
		KEYBOARD_Add8042Response(0xaa); /* OK */
		break;
	case 0xab:		/* interface test */
		keyb.active=false; /* on real h/w it also seems to disable the keyboard */
		KEYBOARD_Add8042Response(0x00); /* no error */
		break;
	case 0xae:		/* Activate keyboard */
		keyb.active=true;
		if (keyb.used && !keyb.scheduled && !keyb.p60changed) {
			keyb.scheduled=true;
			PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY);
		}
		LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated");
		break;
	case 0xad:		/* Deactivate keyboard */
		keyb.active=false;
		LOG(LOG_KEYBOARD,LOG_NORMAL)("De-Activated");
		break;
	case 0xc0:		/* read input buffer */
		KEYBOARD_Add8042Response(0x40);
		break;
	case 0xd0:		/* Outport on buffer */
		KEYBOARD_SetPort60((MEM_A20_Enabled() ? 0x02 : 0) | 0x01/*some programs read the output port then write it back*/);
		break;
	case 0xd1:		/* Write to outport */
		keyb.command=CMD_SETOUTPORT;
		break;
	case 0xd2:		/* write output register */
		keyb.command=CMD_WRITEOUTPUT;
		break;
	case 0xd3:		/* write AUX output */
		if (keyb.enable_aux)
			keyb.command=CMD_WRITEAUXOUT;
		else if (aux_warning++ == 0)
			LOG(LOG_KEYBOARD,LOG_ERROR)("Program is writing 8042 AUX. If you intend to use PS/2 mouse emulation you may consider adding aux=1 to your dosbox.conf");
		break;
	case 0xd4:		/* send byte to AUX */
		if (keyb.enable_aux)
			keyb.command=CMD_WRITEAUX;
		else if (aux_warning++ == 0)
			LOG(LOG_KEYBOARD,LOG_ERROR)("Program is writing 8042 AUX. If you intend to use PS/2 mouse emulation you may consider adding aux=1 to your dosbox.conf");
		break;
	case 0xe0:		/* read test port */
		KEYBOARD_Add8042Response(0x00);
		break;
	case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
	case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
		/* pulse output register */
		if (!(val & 1)) {
			if (allow_keyb_reset) {
				LOG_MSG("Restart by keyboard controller requested\n");
				On_Software_CPU_Reset();
			}
			else {
				LOG_MSG("WARNING: Keyboard output port written (pulsed) with bit 1 clear. Is the guest OS or application attempting to reset the system?\n");
			}
		}
		break;
	default:
		LOG(LOG_KEYBOARD,LOG_ERROR)("Port 64 write with val %d",(int)val);
		break;
	}
}
Example #16
0
void MPU401_WriteCommand(Bit8u val) { /* SOFTMPU */
	Bit8u i; /* SOFTMPU */
	if (mpu.state.reset) {
		if (mpu.state.cmd_pending || (val!=0x3f && val!=0xff)) {
			mpu.state.cmd_pending=val+1;
			return;
		}
		PIC_RemoveEvents(RESET_DONE);
		mpu.state.reset=false;
	}
	if (val<=0x2f) {
		switch (val&3) { /* MIDI stop, start, continue */
			case 1: {MIDI_RawOutByte(0xfc);break;}
			case 2: {MIDI_RawOutByte(0xfa);break;}
			case 3: {MIDI_RawOutByte(0xfb);break;}
		}
		/*if (val&0x20) LOG(LOG_MISC,LOG_ERROR)("MPU-401:Unhandled Recording Command %x",val);*/ /* SOFTMPU */
		switch (val&0xc) {
			case  0x4:      /* Stop */
				PIC_RemoveEvents(MPU_EVENT);
				mpu.state.playing=false;
				for (i=0xb0;i<0xbf;i++) {  /* All notes off */
					MIDI_RawOutByte(i);
					MIDI_RawOutByte(0x7b);
					MIDI_RawOutByte(0);
				}
				break;
			case 0x8:       /* Play */
				/*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Intelligent mode playback started");*/ /* SOFTMPU */
				mpu.state.playing=true;
				PIC_RemoveEvents(MPU_EVENT);
                PIC_AddEvent(MPU_EVENT,(Bitu)MPU401_TIMECONSTANT/(mpu.clock.tempo*mpu.clock.timebase));
				ClrQueue();
				break;
		}
	}
	else if (val>=0xa0 && val<=0xa7) {      /* Request play counter */
		if (mpu.state.cmask&(1<<(val&7))) QueueByte((Bit8u)mpu.playbuf[val&7].counter);
	}
	else if (val>=0xd0 && val<=0xd7) {      /* Send data */
		mpu.state.old_chan=mpu.state.channel;
		mpu.state.channel=val&7;
		mpu.state.wsd=true;
		mpu.state.wsm=false;
		mpu.state.wsd_start=true;
	}
	else
	switch (val) {
		case 0xdf:      /* Send system message */
			mpu.state.wsd=false;
			mpu.state.wsm=true;
			mpu.state.wsd_start=true;
			break;
		case 0x8e:      /* Conductor */
			mpu.state.cond_set=false;
			break;
		case 0x8f:
			mpu.state.cond_set=true;
			break;
		case 0x94: /* Clock to host */
			mpu.clock.clock_to_host=false;
			break;
		case 0x95:
			mpu.clock.clock_to_host=true;
			break;
		case 0xc2: /* Internal timebase */
                        mpu.clock.timebase=48/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc3:
                        mpu.clock.timebase=72/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc4:
                        mpu.clock.timebase=96/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc5:
                        mpu.clock.timebase=120/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc6:
                        mpu.clock.timebase=144/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc7:
                        mpu.clock.timebase=168/(RTCFREQ/1000); /* SOFTMPU */
			break;
		case 0xc8:
                        mpu.clock.timebase=192/(RTCFREQ/1000); /* SOFTMPU */
			break;
		/* Commands with data byte */
		case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: 
		case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef:
			mpu.state.command_byte=val;
			break;
		/* Commands 0xa# returning data */
		case 0xab:      /* Request and clear recording counter */
			QueueByte(MSG_MPU_ACK);
			QueueByte(0);
			return;
		case 0xac:      /* Request version */
                        if (CONFIG_VERSIONFIX)
                        {
                                /* SOFTMPU: Fix missing music in Gateway by reversing version and ACK */
                                QueueByte(MPU401_VERSION);
                                QueueByte(MSG_MPU_ACK);
                        }
                        else
                        {
                                QueueByte(MSG_MPU_ACK);
                                QueueByte(MPU401_VERSION);
                        }
			return;
		case 0xad:      /* Request revision */
			QueueByte(MSG_MPU_ACK);
			QueueByte(MPU401_REVISION);
			return;
		case 0xae:		/* HardMPU: Request config */
			QueueByte(MSG_MPU_ACK);
			QueueByte(mpu.config);
			return;
		case 0xaf:      /* Request tempo */
			QueueByte(MSG_MPU_ACK);
			QueueByte(mpu.clock.tempo);
			return;
		case 0xb1:      /* Reset relative tempo */
			mpu.clock.tempo_rel=40;
			break;
		case 0xb9:      /* Clear play map */
		case 0xb8:      /* Clear play counters */
			for (i=0xb0;i<0xbf;i++) {  /* All notes off */
				MIDI_RawOutByte((Bit8u)i);
				MIDI_RawOutByte(0x7b);
				MIDI_RawOutByte(0);
			}
			for (i=0;i<8;i++) {
				mpu.playbuf[i].counter=0;
				mpu.playbuf[i].type=T_OVERFLOW;
			}
			mpu.condbuf.counter=0;
			mpu.condbuf.type=T_OVERFLOW;
			if (!(mpu.state.conductor=mpu.state.cond_set)) mpu.state.cond_req=0;
			mpu.state.amask=mpu.state.tmask;
			mpu.state.req_mask=0;
			mpu.state.irq_pending=true;
			break;
		case 0xfe:		/* HardMPU: Reset with config byte */
			mpu.state.command_byte=val;
			break;
		case 0xff:      /* Reset MPU-401 */
			/*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Reset %X",val);*/ /* SOFTMPU */
            PIC_AddEvent(RESET_DONE,MPU401_RESETBUSY);
			mpu.state.reset=true;
			MPU401_Reset();
			if (mpu.mode==M_UART) return;//do not send ack in UART mode
			break;
		case 0x3f:      /* UART mode */
			/*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Set UART mode %X",val);*/ /* SOFTMPU */
			mpu.mode=M_UART;
			break;
		default:
			/*LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Unhandled command %X",val);*/
			break;
	}
	QueueByte(MSG_MPU_ACK);
}
Example #17
0
void
bx_ne2k_c::write_cr(Bit32u value)
{
  BX_DEBUG ("wrote 0x%02x to CR", value);

  // Validate remote-DMA
  if ((value & 0x38) == 0x00) {
    BX_DEBUG("CR write - invalid rDMA value 0");
    value |= 0x20; /* dma_cmd == 4 is a safe default */
	//value = 0x22; /* dma_cmd == 4 is a safe default */
  }

  // Check for s/w reset
  if (value & 0x01) {
    BX_NE2K_THIS s.ISR.reset = 1;
    BX_NE2K_THIS s.CR.stop   = 1;
  } else {
    BX_NE2K_THIS s.CR.stop = 0;
  }

  BX_NE2K_THIS s.CR.rdma_cmd = (value & 0x38) >> 3;
  
  // If start command issued, the RST bit in the ISR
  // must be cleared
  if ((value & 0x02) && !BX_NE2K_THIS s.CR.start) {
    BX_NE2K_THIS s.ISR.reset = 0;
  }

  BX_NE2K_THIS s.CR.start = ((value & 0x02) == 0x02);
  BX_NE2K_THIS s.CR.pgsel = (value & 0xc0) >> 6;

    // Check for send-packet command
    if (BX_NE2K_THIS s.CR.rdma_cmd == 3) {
	// Set up DMA read from receive ring
		BX_NE2K_THIS s.remote_start = BX_NE2K_THIS s.remote_dma =
			BX_NE2K_THIS s.bound_ptr * 256;
		BX_NE2K_THIS s.remote_bytes = *((Bit16u*) &
			BX_NE2K_THIS s.mem[BX_NE2K_THIS s.bound_ptr * 256 + 2 - BX_NE2K_MEMSTART]);
		BX_INFO("Sending buffer #x%x length %d",
			BX_NE2K_THIS s.remote_start,
			BX_NE2K_THIS s.remote_bytes);
    }

  // Check for start-tx
    if ((value & 0x04) && BX_NE2K_THIS s.TCR.loop_cntl) {
		// loopback mode
		if (BX_NE2K_THIS s.TCR.loop_cntl != 1) {
			BX_INFO("Loop mode %d not supported.", BX_NE2K_THIS s.TCR.loop_cntl);
		} else {
			rx_frame (& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 -
				BX_NE2K_MEMSTART],
				BX_NE2K_THIS s.tx_bytes);

			// do a TX interrupt
			// Generate an interrupt if not masked and not one in progress
			if (BX_NE2K_THIS s.IMR.tx_inte && !BX_NE2K_THIS s.ISR.pkt_tx) {
				//LOG_MSG("tx complete interrupt");
				PIC_ActivateIRQ(s.base_irq);
			}
			BX_NE2K_THIS s.ISR.pkt_tx = 1;
		}
    } else if (value & 0x04) {
		// start-tx and no loopback
		if (BX_NE2K_THIS s.CR.stop || !BX_NE2K_THIS s.CR.start)
			BX_PANIC(("CR write - tx start, dev in reset"));
	    
		if (BX_NE2K_THIS s.tx_bytes == 0)
			BX_PANIC(("CR write - tx start, tx bytes == 0"));

#ifdef notdef    
    // XXX debug stuff
    printf("packet tx (%d bytes):\t", BX_NE2K_THIS s.tx_bytes);
    for (int i = 0; i < BX_NE2K_THIS s.tx_bytes; i++) {
      printf("%02x ", BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - 
				BX_NE2K_MEMSTART + i]);
      if (i && (((i+1) % 16) == 0)) 
	printf("\t");
    }
    printf("");
#endif    

    // Send the packet to the system driver
	/* TODO: Transmit packet */
    //BX_NE2K_THIS ethdev->sendpkt(& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], BX_NE2K_THIS s.tx_bytes);
        NE2000_PrivelegeEscalate();
	pcap_sendpacket(adhandle,&s.mem[s.tx_page_start*256 - BX_NE2K_MEMSTART], s.tx_bytes);
        NE2000_PrivelegeDrop();

	// some more debug
	if (BX_NE2K_THIS s.tx_timer_active) {
      BX_PANIC(("CR write, tx timer still active"));
	  PIC_RemoveEvents(NE2000_TX_Event);
	}
	//LOG_MSG("send packet command");
	//s.tx_timer_index = (64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10;
	s.tx_timer_active = 1;
	PIC_AddEvent(NE2000_TX_Event,(float)((64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10000.0),0);
    // Schedule a timer to trigger a tx-complete interrupt
    // The number of microseconds is the bit-time / 10.
    // The bit-time is the preamble+sfd (64 bits), the
    // inter-frame gap (96 bits), the CRC (4 bytes), and the
    // the number of bits in the frame (s.tx_bytes * 8).
    //

	/* TODO: Code transmit timer */
	/*
    bx_pc_system.activate_timer(BX_NE2K_THIS s.tx_timer_index,
				(64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10,
				0); // not continuous
	*/
  } // end transmit-start branch

  // Linux probes for an interrupt by setting up a remote-DMA read
  // of 0 bytes with remote-DMA completion interrupts enabled.
  // Detect this here
  if (BX_NE2K_THIS s.CR.rdma_cmd == 0x01 &&
      BX_NE2K_THIS s.CR.start &&
      BX_NE2K_THIS s.remote_bytes == 0) {
    BX_NE2K_THIS s.ISR.rdma_done = 1;
    if (BX_NE2K_THIS s.IMR.rdma_inte) {
		PIC_ActivateIRQ(s.base_irq);
      //DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
    }
  }
}