To verify that spkmodem.c is not the source of the issue. I decided I would try to part off the code from the console, and then compile it. Producing a wav file that I could then manually interpret, certify as good, and use to fix or replace spkmodem-recv. My efforts however were once again stumped when I realized the paired off code accessing the low level hardware with the OS still loaded, will just cause a segmentation fault.

Is there an easy way to run the executable under say QEMU, but emulating just the PC hardware rather than a whole OS?


On 7/12/21 12:46 am, Keith Emery wrote:
I've looked at the wave forms in audacity, and tried to manually figure out if it made any sense. I think at one point I got a 'S.P.K.' which now having located and read the code that actually generates the tones. Is consistent with it's startup sequence of trying to say 'SPEAKER'. However spkmodem-recv still just prints illegible symbols.

On 6/12/21 11:59 pm, Peter Stuge wrote:
Keith Emery wrote:
When I enable spkmodem in the coreboot config, I get output from the PC
speaker. But spkmodem-recv interprets the tones as consistent gibberish.
The output is consistent with a mismatch in the baud rates, but there
appears no apparent way to select anything different in the
spkmodem-recv software.
spkmodem uses a fixed baudrate, IIRC 1200.

Did you look at a recording in a spectrum analyzer software? Maybe
that would help identify modulation timing issues.

Because coreboot isn't being loaded from the SPI chip one instruction at a time. It's using the CPU cache as ram and executing from there... derp.

More sleep, more coffee. Those are basically the same thing, right!

If the CPU is running coreboot as fast as possible while receiving
those instructions from a relatively slow SPI bus. Is it possible
that I've somehow overclocked the SPI bus, leading to a mismatch in
the baud rates?
SPI isn't involved in tone timing, I think only the (emulated) legacy
timer is used for that.


//Peter
_______________________________________________
coreboot mailing list -- coreboot@coreboot.org
To unsubscribe send an email to coreboot-le...@coreboot.org
_______________________________________________
coreboot mailing list -- coreboot@coreboot.org
To unsubscribe send an email to coreboot-le...@coreboot.org
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include "io.h"

#define SPEAKER_PIT_FREQUENCY		0x1234dd

enum {
	PIT_COUNTER_0 = 0x40,
	PIT_COUNTER_1 = 0x41,
	PIT_COUNTER_2 = 0x42,
	PIT_CTRL = 0x43,
	PIT_SPEAKER_PORT = 0x61,
};

enum {
	PIT_SPK_TMR2 = 0x01,
	PIT_SPK_DATA = 0x02,
	PIT_SPK_TMR2_LATCH = 0x20
};

enum {
	PIT_CTRL_SELECT_MASK = 0xc0,
	PIT_CTRL_SELECT_0 = 0x00,
	PIT_CTRL_SELECT_1 = 0x40,
	PIT_CTRL_SELECT_2 = 0x80,

	PIT_CTRL_READLOAD_MASK = 0x30,
	PIT_CTRL_COUNTER_LATCH = 0x00,
	PIT_CTRL_READLOAD_LSB = 0x10,
	PIT_CTRL_READLOAD_MSB = 0x20,
	PIT_CTRL_READLOAD_WORD = 0x30,

	PIT_CTRL_MODE_MASK = 0x0e,
	PIT_CTRL_INTR_ON_TERM = 0x00,
	PIT_CTRL_PROGR_ONE_SHOT = 0x02,

	PIT_CTRL_RATE_GEN = 0x04,

	PIT_CTRL_SQUAREWAVE_GEN = 0x06,
	PIT_CTRL_SOFTSTROBE = 0x08,

	PIT_CTRL_HARDSTROBE = 0x0a,

	PIT_CTRL_COUNT_MASK = 0x01,
	PIT_CTRL_COUNT_BINARY = 0x00,
	PIT_CTRL_COUNT_BCD = 0x01
};

static void
make_tone(uint16_t freq_count, unsigned int duration)
{
	outb(PIT_CTRL_SELECT_2
		   | PIT_CTRL_READLOAD_WORD
		   | PIT_CTRL_SQUAREWAVE_GEN
		   | PIT_CTRL_COUNT_BINARY, PIT_CTRL);

	outb(freq_count & 0xff, PIT_COUNTER_2);

	outb((freq_count >> 8) & 0xff, PIT_COUNTER_2);

	outb(inb(PIT_SPEAKER_PORT)
		   | PIT_SPK_TMR2 | PIT_SPK_DATA,
		   PIT_SPEAKER_PORT);

	for (; duration; duration--) {
		unsigned short counter, previous_counter = 0xffff;

		while (1) {
			counter = inb(PIT_COUNTER_2);
			counter |= ((uint16_t)inb(PIT_COUNTER_2)) << 8;
			if (counter > previous_counter) {
				previous_counter = counter;
				break;
			}
			previous_counter = counter;
		}
	}
}

void spkmodem_tx_byte(unsigned char c)
{
	int i;

	make_tone(SPEAKER_PIT_FREQUENCY / 200, 4);
	for (i = 7; i >= 0; i--) {
		if ((c >> i) & 1)
			make_tone(SPEAKER_PIT_FREQUENCY / 2000, 20);
		else
			make_tone(SPEAKER_PIT_FREQUENCY / 4000, 40);
		make_tone(SPEAKER_PIT_FREQUENCY / 1000, 10);
	}
	make_tone(SPEAKER_PIT_FREQUENCY / 200, 0);
}

void main()
{
	/*
	 * A message for the ages.
	 */
	spkmodem_tx_byte('T');
	spkmodem_tx_byte('e');
        spkmodem_tx_byte('s');
        spkmodem_tx_byte('t');
        spkmodem_tx_byte('i');
        spkmodem_tx_byte('c');
        spkmodem_tx_byte('l');
	spkmodem_tx_byte('s');
	spkmodem_tx_byte('\r');
	spkmodem_tx_byte('\n');
}
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __ARCH_IO_H__
#define __ARCH_IO_H__

#include <stdint.h>

/*
 * This file contains the definitions for the x86 IO instructions
 * inb/inw/inl/outb/outw/outl and the "string versions" of the same
 * (insb/insw/insl/outsb/outsw/outsl).
 */
static inline void outb(uint8_t value, uint16_t port)
{
	__asm__ __volatile__ ("outb %b0, %w1" : : "a" (value), "Nd" (port));
}

static inline void outw(uint16_t value, uint16_t port)
{
	__asm__ __volatile__ ("outw %w0, %w1" : : "a" (value), "Nd" (port));
}

static inline void outl(uint32_t value, uint16_t port)
{
	__asm__ __volatile__ ("outl %0, %w1" : : "a" (value), "Nd" (port));
}

static inline uint8_t inb(uint16_t port)
{
	uint8_t value;
	__asm__ __volatile__ ("inb %w1, %b0" : "=a"(value) : "Nd" (port));
	return value;
}

static inline uint16_t inw(uint16_t port)
{
	uint16_t value;
	__asm__ __volatile__ ("inw %w1, %w0" : "=a"(value) : "Nd" (port));
	return value;
}

static inline uint32_t inl(uint16_t port)
{
	uint32_t value;
	__asm__ __volatile__ ("inl %w1, %0" : "=a"(value) : "Nd" (port));
	return value;
}

static inline void outsb(uint16_t port, const void *addr, unsigned long count)
{
	__asm__ __volatile__ (
		"cld ; rep ; outsb "
		: "=S" (addr), "=c" (count)
		: "d"(port), "0"(addr), "1" (count)
		);
}

static inline void outsw(uint16_t port, const void *addr, unsigned long count)
{
	__asm__ __volatile__ (
		"cld ; rep ; outsw "
		: "=S" (addr), "=c" (count)
		: "d"(port), "0"(addr), "1" (count)
		);
}

static inline void outsl(uint16_t port, const void *addr, unsigned long count)
{
	__asm__ __volatile__ (
		"cld ; rep ; outsl "
		: "=S" (addr), "=c" (count)
		: "d"(port), "0"(addr), "1" (count)
		);
}

static inline void insb(uint16_t port, void *addr, unsigned long count)
{
	__asm__ __volatile__ (
		"cld ; rep ; insb "
		: "=D" (addr), "=c" (count)
		: "d"(port), "0"(addr), "1" (count)
		: "memory"
		);
}

static inline void insw(uint16_t port, void *addr, unsigned long count)
{
	__asm__ __volatile__ (
		"cld ; rep ; insw "
		: "=D" (addr), "=c" (count)
		: "d"(port), "0"(addr), "1" (count)
		: "memory"
		);
}

static inline void insl(uint16_t port, void *addr, unsigned long count)
{
	__asm__ __volatile__ (
		"cld ; rep ; insl "
		: "=D" (addr), "=c" (count)
		: "d"(port), "0"(addr), "1" (count)
		: "memory"
		);
}

#endif
_______________________________________________
coreboot mailing list -- coreboot@coreboot.org
To unsubscribe send an email to coreboot-le...@coreboot.org

Reply via email to