Merge remote-tracking branch 'haiku/master' into package-management

Conflicts:
	build/jam/BuildSetup
	build/jam/HaikuImage
	build/jam/board/sam460ex/BoardSetup
	build/jam/board/verdex/BoardSetup
	data/catalogs/apps/icon-o-matic/fr.catkeys
	src/add-ons/kernel/drivers/audio/hda/hda_codec.cpp
	src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp
	src/apps/debugger/files/FileManager.cpp
	src/apps/debugger/files/FileManager.h
	src/apps/debugger/user_interface/gui/inspector_window/MemoryView.cpp
	src/apps/haiku-depot/MainWindow.cpp
	src/apps/haiku-depot/MainWindow.h
	src/apps/haiku-depot/Model.cpp
	src/apps/haiku-depot/PackageInfo.h
	src/apps/haiku-depot/PackageInfoListener.h
	src/apps/haiku-depot/PackageInfoView.cpp
	src/apps/haiku-depot/PackageInfoView.h
	src/apps/haiku-depot/PackageListView.cpp
	src/apps/haiku-depot/PackageListView.h
	src/system/kernel/arch/arm/arch_timer.cpp
	src/system/libroot/os/arch/arm/atomic.S
	src/tools/translation/bitsinfo/Jamfile
	src/tools/translation/bmpinfo/Jamfile
	src/tools/translation/tgainfo/Jamfile
This commit is contained in:
Ingo Weinhold
2013-09-27 01:55:45 +02:00
91 changed files with 7806 additions and 550 deletions
+8 -12
View File
@@ -611,8 +611,8 @@ display_dce45_crtc_load_lut(uint8 crtcID)
if (info.dceMajor >= 5) {
Write32(OUT, NI_INPUT_CSC_CONTROL + regs->crtcOffset,
(NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) |
NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS)));
(NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS)
| NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS)));
Write32(OUT, NI_PRESCALE_GRPH_CONTROL + regs->crtcOffset,
NI_GRPH_PRESCALE_BYPASS);
Write32(OUT, NI_PRESCALE_OVL_CONTROL + regs->crtcOffset,
@@ -638,17 +638,15 @@ display_dce45_crtc_load_lut(uint8 crtcID)
Write32(OUT, EVERGREEN_DC_LUT_RW_INDEX, 0);
for (int i = 0; i < 256; i++) {
Write32(OUT, EVERGREEN_DC_LUT_30_COLOR + regs->crtcOffset,
(r[i] << 20) |
(g[i] << 10) |
(b[i] << 0));
(r[i] << 20) | (g[i] << 10) | (b[i] << 0));
}
if (info.dceMajor >= 5) {
Write32(OUT, NI_DEGAMMA_CONTROL + regs->crtcOffset,
(NI_GRPH_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
NI_OVL_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
NI_ICON_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
NI_CURSOR_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)));
(NI_GRPH_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)
| NI_OVL_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)
| NI_ICON_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)
| NI_CURSOR_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)));
Write32(OUT, NI_GAMUT_REMAP_CONTROL + regs->crtcOffset,
(NI_GRPH_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS) |
NI_OVL_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS)));
@@ -693,9 +691,7 @@ display_avivo_crtc_load_lut(uint8 crtcID)
Write32(OUT, AVIVO_DC_LUT_RW_INDEX, 0);
for (int i = 0; i < 256; i++) {
Write32(OUT, AVIVO_DC_LUT_30_COLOR,
(r[i] << 20) |
(g[i] << 10) |
(b[i] << 0));
(r[i] << 20) | (g[i] << 10) | (b[i] << 0));
}
Write32(OUT, AVIVO_D1GRPH_LUT_SEL + regs->crtcOffset, crtcID);
@@ -772,7 +772,7 @@ dp_link_train(uint8 crtcID)
{
TRACE("%s\n", __func__);
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
display_mode* mode = &gDisplay[crtcID]->currentMode;
@@ -5,6 +5,7 @@ UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ]
[ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) openfirmware ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) u-boot ] ;
KernelStaticLibrary pci_arch_bus_manager :
pci_controller.cpp
@@ -14,4 +15,7 @@ KernelStaticLibrary pci_arch_bus_manager :
pci_openfirmware.cpp
uninorth.cpp
grackle.cpp
# U-Boot
pci_u-boot.cpp
;
@@ -11,6 +11,7 @@
#include "pci_private.h"
#include "openfirmware/pci_openfirmware.h"
#include "u-boot/pci_u-boot.h"
status_t
@@ -19,9 +20,12 @@ pci_controller_init(void)
switch (PPCPlatform::Default()->PlatformType()) {
case PPC_PLATFORM_OPEN_FIRMWARE:
return ppc_openfirmware_pci_controller_init();
break;
case PPC_PLATFORM_U_BOOT:
return ppc_uboot_pci_controller_init();
default:
panic("pci: unknown platform");
}
return B_OK;
return B_ERROR;
}
@@ -0,0 +1,24 @@
/*
* Copyright 2006, Ingo Weinhold <[email protected]>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "pci_u-boot.h"
#include <stdlib.h>
#include <string.h>
#include <KernelExport.h>
//#include <platform/openfirmware/devices.h>
//#include <platform/openfirmware/openfirmware.h>
//#include <platform/openfirmware/pci.h>
status_t
ppc_uboot_pci_controller_init(void)
{
return B_ERROR;
}
@@ -0,0 +1,13 @@
/*
* Copyright 2012, François Revol <[email protected]>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef PCI_BUS_MANAGER_PPC_U_BOOT_H
#define PCI_BUS_MANAGER_PPC_U_BOOT_H
#include <SupportDefs.h>
status_t ppc_uboot_pci_controller_init(void);
#endif // PCI_BUS_MANAGER_PPC_U_BOOT_H
@@ -8,6 +8,7 @@ KernelAddon ps2 :
ps2_alps.cpp
ps2_common.cpp
ps2_dev.cpp
ps2_elantech.cpp
ps2_keyboard.cpp
ps2_module.cpp
ps2_standard_mouse.cpp
@@ -67,8 +67,8 @@ public:
private:
bool fFired;
uint8 fLastPackage[PS2_PACKET_ALPS];
timer fEventTimer;
alps_cookie* fCookie;
timer fEventTimer;
alps_cookie* fCookie;
};
@@ -112,7 +112,7 @@ typedef struct alps_model_info {
static const struct alps_model_info gALPSModelInfos[] = {
{{0x32, 0x02, 0x14}, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT},
// Toshiba Salellite Pro M10
// Toshiba Salellite Pro M10
// {{0x33, 0x02, 0x0a}, 0x88, 0xf8, ALPS_OLDPROTO},
// UMAX-530T
{{0x53, 0x02, 0x0a}, 0xf8, 0xf8, 0},
@@ -155,15 +155,6 @@ static const struct alps_model_info gALPSModelInfos[] = {
static alps_model_info* sFoundModel = NULL;
#define PS2_MOUSE_CMD_SET_SCALE11 0xe6
#define PS2_MOUSE_CMD_SET_SCALE21 0xe7
#define PS2_MOUSE_CMD_SET_RES 0xe8
#define PS2_MOUSE_CMD_GET_INFO 0xe9
#define PS2_MOUSE_CMD_SET_STREAM 0xea
#define PS2_MOUSE_CMD_SET_POLL 0xf0
#define PS2_MOUSE_CMD_SET_RATE 0xf3
// touchpad proportions
#define EDGE_MOTION_WIDTH 55
// increase the touchpad size a little bit
@@ -279,16 +270,16 @@ probe_alps(ps2_dev* dev)
TRACE("ALPS: probe\n");
val[0] = 0;
if (ps2_dev_command(dev, PS2_MOUSE_CMD_SET_RES, val, 1, NULL, 0) != B_OK
|| ps2_dev_command(dev, PS2_MOUSE_CMD_SET_SCALE11, NULL, 0, NULL, 0)
if (ps2_dev_command(dev, PS2_CMD_MOUSE_SET_RES, val, 1, NULL, 0) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11, NULL, 0, NULL, 0)
!= B_OK
|| ps2_dev_command(dev, PS2_MOUSE_CMD_SET_SCALE11, NULL, 0, NULL, 0)
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11, NULL, 0, NULL, 0)
!= B_OK
|| ps2_dev_command(dev, PS2_MOUSE_CMD_SET_SCALE11, NULL, 0, NULL, 0)
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11, NULL, 0, NULL, 0)
!= B_OK)
return B_ERROR;
if (ps2_dev_command(dev, PS2_MOUSE_CMD_GET_INFO, NULL, 0, val, 3)
if (ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, val, 3)
!= B_OK)
return B_ERROR;
@@ -296,16 +287,16 @@ probe_alps(ps2_dev* dev)
return B_ERROR;
val[0] = 0;
if (ps2_dev_command(dev, PS2_MOUSE_CMD_SET_RES, val, 1, NULL, 0) != B_OK
|| ps2_dev_command(dev, PS2_MOUSE_CMD_SET_SCALE21, NULL, 0, NULL, 0)
if (ps2_dev_command(dev, PS2_CMD_MOUSE_SET_RES, val, 1, NULL, 0) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE21, NULL, 0, NULL, 0)
!= B_OK
|| ps2_dev_command(dev, PS2_MOUSE_CMD_SET_SCALE21, NULL, 0, NULL, 0)
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE21, NULL, 0, NULL, 0)
!= B_OK
|| ps2_dev_command(dev, PS2_MOUSE_CMD_SET_SCALE21, NULL, 0, NULL, 0)
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE21, NULL, 0, NULL, 0)
!= B_OK)
return B_ERROR;
if (ps2_dev_command(dev, PS2_MOUSE_CMD_GET_INFO, NULL, 0, val, 3)
if (ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, val, 3)
!= B_OK)
return B_ERROR;
@@ -337,12 +328,12 @@ switch_hardware_tab(ps2_dev* dev, bool on)
{
uint8 val[3];
uint8 arg = 0x00;
uint8 command = PS2_MOUSE_CMD_SET_RES;
uint8 command = PS2_CMD_MOUSE_SET_RES;
if (on) {
arg = 0x0A;
command = PS2_MOUSE_CMD_SET_RATE;
command = PS2_CMD_KEYBOARD_SET_TYPEMATIC;
}
if (ps2_dev_command(dev, PS2_MOUSE_CMD_GET_INFO, NULL, 0, val, 3) != B_OK
if (ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, val, 3) != B_OK
|| ps2_dev_command(dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0) != B_OK
|| ps2_dev_command(dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0) != B_OK
|| ps2_dev_command(dev, command, &arg, 1, NULL, 0) != B_OK)
@@ -355,9 +346,9 @@ switch_hardware_tab(ps2_dev* dev, bool on)
status_t
enable_passthrough(ps2_dev* dev, bool on)
{
uint8 command = PS2_MOUSE_CMD_SET_SCALE11;
uint8 command = PS2_CMD_MOUSE_SET_SCALE11;
if (on)
command = PS2_MOUSE_CMD_SET_SCALE21;
command = PS2_CMD_MOUSE_SET_SCALE21;
if (ps2_dev_command(dev, command, NULL, 0, NULL, 0) != B_OK
|| ps2_dev_command(dev, command, NULL, 0, NULL, 0) != B_OK
@@ -438,7 +429,7 @@ alps_open(const char *name, uint32 flags, void **_cookie)
if ((sFoundModel->flags & ALPS_PASS) != 0
&& enable_passthrough(dev, true) != B_OK)
goto err4;
// switch tap mode off
if (switch_hardware_tab(dev, false) != B_OK)
goto err4;
@@ -455,7 +446,7 @@ alps_open(const char *name, uint32 flags, void **_cookie)
&& enable_passthrough(dev, false) != B_OK)
goto err4;
if (ps2_dev_command(dev, PS2_MOUSE_CMD_SET_STREAM, NULL, 0, NULL, 0) != B_OK)
if (ps2_dev_command(dev, PS2_CMD_MOUSE_SET_STREAM, NULL, 0, NULL, 0) != B_OK)
goto err4;
if (ps2_dev_command(dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0) != B_OK)
@@ -633,4 +624,3 @@ device_hooks gALPSDeviceHooks = {
alps_read,
alps_write,
};
@@ -1,3 +1,10 @@
/*
* Copyright 2011, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler ([email protected])
*/
#ifndef ALPS_H
#define ALPS_H
@@ -369,7 +369,7 @@ ps2_init(void)
//ps2_selftest();
// Setup the command byte with disabled keyboard and AUX interrupts
// to prevent interrupts storm on some KBCs during active multiplexing
// to prevent interrupts storm on some KBCs during active multiplexing
// activation procedure. Fixes #7635.
status = ps2_setup_command_byte(false);
if (status) {
@@ -391,8 +391,9 @@ ps2_init(void)
}
if (gActiveMultiplexingEnabled) {
if (ps2_dev_command_timeout(&ps2_device[PS2_DEVICE_MOUSE], 0xe6,
NULL, 0, NULL, 0, 100000) == B_TIMED_OUT) {
if (ps2_dev_command_timeout(&ps2_device[PS2_DEVICE_MOUSE],
PS2_CMD_MOUSE_SET_SCALE11, NULL, 0, NULL, 0, 100000)
== B_TIMED_OUT) {
INFO("ps2: accessing multiplexed mouse port 0 timed out, ignoring it!\n");
} else {
ps2_service_notify_device_added(&ps2_device[PS2_DEVICE_MOUSE]);
@@ -28,6 +28,7 @@
#else
# define INFO(x...)
#endif
#define ERROR(x...) dprintf(x)
//#define TRACE_PS2
#ifdef TRACE_PS2
@@ -48,7 +48,13 @@
#define PS2_BITS_TRANSLATE_SCANCODES 0x40
// data words
#define PS2_CMD_MOUSE_SET_SCALE11 0xe6
#define PS2_CMD_MOUSE_SET_SCALE21 0xe7
#define PS2_CMD_MOUSE_SET_RES 0xe8
#define PS2_CMD_MOUSE_GET_INFO 0xe9
#define PS2_CMD_MOUSE_SET_STREAM 0xea
#define PS2_CMD_KEYBOARD_SET_LEDS 0xed
#define PS2_CMD_MOUSE_SET_POLL 0xf0
#define PS2_CMD_KEYBOARD_SET_TYPEMATIC 0xf3
#define PS2_CMD_ECHO 0xee
#define PS2_CMD_TEST_PASSED 0xaa
@@ -56,6 +62,7 @@
#define PS2_CMD_SET_SAMPLE_RATE 0xf3
#define PS2_CMD_ENABLE 0xf4
#define PS2_CMD_DISABLE 0xf5
#define PS2_CMD_MOUSE_RESET_DIS 0xf6
#define PS2_CMD_RESET 0xff
#define PS2_CMD_RESEND 0xfe
@@ -79,6 +86,7 @@
#define PS2_PACKET_INTELLIMOUSE 4
#define PS2_PACKET_SYNAPTICS 6
#define PS2_PACKET_ALPS 6
#define PS2_PACKET_ELANTECH 6 // version 1 is only 4
#define PS2_MAX_PACKET_SIZE 6
// Should be equal to the biggest packet size
@@ -14,6 +14,7 @@
#include "ps2_service.h"
#include "ps2_alps.h"
#include "ps2_elantech.h"
#include "ps2_standard_mouse.h"
#include "ps2_synaptics.h"
#include "ps2_trackpoint.h"
@@ -88,6 +89,12 @@ ps2_dev_detect_pointing(ps2_dev *dev, device_hooks **hooks)
goto dev_found;
}
status = probe_elantech(dev);
if (status == B_OK) {
*hooks = &gElantechDeviceHooks;
goto dev_found;
}
// reset the mouse for the case that the previous probes leaf the mouse in
// a undefined state
status = ps2_reset_mouse(dev);
@@ -190,7 +197,7 @@ ps2_dev_publish(ps2_dev *dev)
if (atomic_get(&dev->flags) & PS2_FLAG_KEYB) {
status = devfs_publish_device(dev->name, &gKeyboardDeviceHooks);
} else {
// Check if this is the "pass-through" device and wait until
// Check if this is the "pass-through" device and wait until
// the parent_dev goes to enabled state. It is required to prevent
// from messing up the Synaptics command sequences in synaptics_open.
if (dev->parent_dev) {
@@ -204,7 +211,7 @@ ps2_dev_publish(ps2_dev *dev)
snooze(timeout / 20);
}
TRACE("ps2: publishing %s: parent %s is %s; wait time %" B_PRId64
"\n", dev->name, dev->parent_dev->name,
"\n", dev->name, dev->parent_dev->name,
status == B_OK ? "enabled" : "busy", system_time() - start);
}
@@ -490,3 +497,23 @@ ps2_dev_command_timeout(ps2_dev *dev, uint8 cmd, const uint8 *out,
return dev->command(dev, cmd, out, out_count, in, in_count, timeout);
}
status_t
ps2_dev_sliced_command(ps2_dev *dev, uint8 cmd)
{
if (ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11) != B_OK)
return B_ERROR;
uint8 val = (cmd >> 6) & 3;
if (ps2_dev_command(dev, PS2_CMD_MOUSE_SET_RES, &val, 1) != B_OK)
return B_ERROR;
val = (cmd >> 4) & 3;
if (ps2_dev_command(dev, PS2_CMD_MOUSE_SET_RES, &val, 1) != B_OK)
return B_ERROR;
val = (cmd >> 2) & 3;
if (ps2_dev_command(dev, PS2_CMD_MOUSE_SET_RES, &val, 1) != B_OK)
return B_ERROR;
val = cmd & 3;
if (ps2_dev_command(dev, PS2_CMD_MOUSE_SET_RES, &val, 1) != B_OK)
return B_ERROR;
return B_OK;
}
@@ -76,10 +76,12 @@ void ps2_dev_exit(void);
status_t standard_command_timeout(ps2_dev *dev, uint8 cmd, const uint8 *out,
int out_count, uint8 *in, int in_count, bigtime_t timeout);
status_t ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out,
int out_count, uint8 *in, int in_count);
status_t ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out = NULL,
int out_count = 0, uint8 *in = NULL, int in_count = 0);
status_t ps2_dev_command_timeout(ps2_dev *dev, uint8 cmd, const uint8 *out,
int out_count, uint8 *in, int in_count, bigtime_t timeout);
status_t ps2_dev_sliced_command(ps2_dev *dev, uint8 cmd);
status_t ps2_reset_mouse(ps2_dev *dev);
@@ -0,0 +1,801 @@
/*
* Copyright 2013, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Hardware specs taken from the linux driver, thanks a lot!
* Based on ps2_alps.c
*
* Authors:
* Jérôme Duval <[email protected]>
*/
#include "ps2_elantech.h"
#include <stdlib.h>
#include <string.h>
#include "ps2_service.h"
static int32 generate_event(timer* timer);
const bigtime_t kEventInterval = 1000 * 50;
class EventProducer {
public:
EventProducer()
{
fFired = false;
}
status_t
FireEvent(elantech_cookie* cookie, uint8* package)
{
fCookie = cookie;
memcpy(fLastPackage, package, sizeof(uint8) * PS2_PACKET_ELANTECH);
status_t status = add_timer(&fEventTimer, &generate_event,
kEventInterval, B_ONE_SHOT_RELATIVE_TIMER);
if (status == B_OK)
fFired = true;
return status;
}
bool
CancelEvent()
{
if (!fFired)
return false;
fFired = false;
return cancel_timer(&fEventTimer);
}
void
InjectEvent()
{
if (packet_buffer_write(fCookie->ring_buffer, fLastPackage,
PS2_PACKET_ELANTECH) != PS2_PACKET_ELANTECH) {
// buffer is full, drop new data
return;
}
release_sem_etc(fCookie->sem, 1, B_DO_NOT_RESCHEDULE);
}
private:
bool fFired;
uint8 fLastPackage[PS2_PACKET_ELANTECH];
timer fEventTimer;
elantech_cookie* fCookie;
};
static EventProducer gEventProducer;
static int32
generate_event(timer* timer)
{
gEventProducer.InjectEvent();
return 0;
}
const char* kElantechPath[4] = {
"input/touchpad/ps2/elantech_0",
"input/touchpad/ps2/elantech_1",
"input/touchpad/ps2/elantech_2",
"input/touchpad/ps2/elantech_3"
};
#define ELANTECH_CMD_GET_ID 0x00
#define ELANTECH_CMD_GET_VERSION 0x01
#define ELANTECH_CMD_GET_CAPABILITIES 0x02
#define ELANTECH_CMD_GET_SAMPLE 0x03
#define ELANTECH_CMD_GET_RESOLUTION 0x04
#define ELANTECH_CMD_REGISTER_READ 0x10
#define ELANTECH_CMD_REGISTER_WRITE 0x11
#define ELANTECH_CMD_REGISTER_READWRITE 0x00
#define ELANTECH_CMD_PS2_CUSTOM_CMD 0xf8
// touchpad proportions
#define EDGE_MOTION_WIDTH 55
#define MIN_PRESSURE 0
#define REAL_MAX_PRESSURE 50
#define MAX_PRESSURE 255
#define ELANTECH_HISTORY_SIZE 256
static hardware_specs gHardwareSpecs;
static status_t
get_elantech_movement(elantech_cookie *cookie, mouse_movement *movement)
{
touch_event event;
uint8 event_buffer[PS2_PACKET_ELANTECH];
status_t status = acquire_sem_etc(cookie->sem, 1, B_CAN_INTERRUPT, 0);
if (status < B_OK)
return status;
if (!cookie->dev->active) {
TRACE("ELANTECH: read_event: Error device no longer active\n");
return B_ERROR;
}
if (packet_buffer_read(cookie->ring_buffer, event_buffer,
cookie->dev->packet_size) != cookie->dev->packet_size) {
TRACE("ELANTECH: error copying buffer\n");
return B_ERROR;
}
if (cookie->crcEnabled && (event_buffer[3] & 0x08) != 0) {
TRACE("ELANTECH: bad crc buffer\n");
return B_ERROR;
} else if (!cookie->crcEnabled && ((event_buffer[0] & 0x0c) != 0x04
|| (event_buffer[3] & 0x1c) != 0x10)) {
TRACE("ELANTECH: bad crc buffer\n");
return B_ERROR;
}
uint8 type = event_buffer[3] & 3;
TRACE("ELANTECH: packet type %d\n", type);
TRACE("ELANTECH: packet content 0x%02x%02x%02x%02x%02x%02x\n",
event_buffer[0], event_buffer[1], event_buffer[2], event_buffer[3],
event_buffer[4], event_buffer[5]);
switch (type) {
case 0:
// fingers
cookie->fingers = event_buffer[1] & 0x1f;
break;
case 1:
if ((((event_buffer[3] & 0xe0) >> 5) - 1) != 0) {
// only process first finger
return B_OK;
}
event.zPressure = (event_buffer[1] & 0xf0)
| ((event_buffer[4] & 0xf0) >> 4);
cookie->previousZ = event.zPressure;
event.xPosition = ((event_buffer[1] & 0xf) << 8) | event_buffer[2];
event.yPosition = (((event_buffer[4] & 0xf) << 8)
| event_buffer[5]);
TRACE("ELANTECH: buttons 0x%x x %ld y %ld z %d\n",
event.buttons, event.xPosition, event.yPosition,
event.zPressure);
break;
case 2:
TRACE("ELANTECH: packet type motion\n");
// TODO
return B_OK;
default:
TRACE("ELANTECH: unknown packet type %d\n", type);
return B_ERROR;
}
event.buttons = 0;
// finger on touchpad
if ((cookie->fingers & 1) != 0) {
// finger with normal width
event.wValue = 4;
} else {
event.wValue = 3;
}
status = cookie->movementMaker.EventToMovement(&event, movement);
if (cookie->movementMaker.WasEdgeMotion()
|| cookie->movementMaker.TapDragStarted()) {
gEventProducer.FireEvent(cookie, event_buffer);
}
return status;
}
static void
default_settings(touchpad_settings *set)
{
memcpy(set, &kDefaultTouchpadSettings, sizeof(touchpad_settings));
}
static status_t
synaptics_dev_send_command(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count)
{
uint8 val;
if (ps2_dev_sliced_command(dev, cmd) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, in, in_count)
!= B_OK) {
TRACE("ELANTECH: synaptics_dev_send_command failed\n");
return B_ERROR;
}
return B_OK;
}
static status_t
elantech_dev_send_command(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count)
{
uint8 val;
if (ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, cmd) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, in, in_count)
!= B_OK) {
TRACE("ELANTECH: elantech_dev_send_command failed\n");
return B_ERROR;
}
return B_OK;
}
status_t
probe_elantech(ps2_dev* dev)
{
int i;
uint8 val[3];
TRACE("ELANTECH: probe\n");
ps2_dev_command(dev, PS2_CMD_MOUSE_RESET_DIS);
if (ps2_dev_command(dev, PS2_CMD_DISABLE) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11) != B_OK) {
TRACE("ELANTECH: not found (1)\n");
return B_ERROR;
}
if (ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, val, 3)
!= B_OK) {
TRACE("ELANTECH: not found (2)\n");
return B_ERROR;
}
if (val[0] != 0x3c || val[1] != 0x3 || (val[2] != 0xc8 && val[2] != 0x0)) {
TRACE("ELANTECH: not found (3)\n");
return B_ERROR;
}
val[0] = 0;
if (synaptics_dev_send_command(dev, ELANTECH_CMD_GET_VERSION, val, 3)
!= B_OK) {
TRACE("ELANTECH: not found (4)\n");
return B_ERROR;
}
if (val[0] == 0x0 || val[2] == 10 || val[2] == 20 || val[2] == 40
|| val[2] == 60 || val[2] == 80 || val[2] == 100 || val[2] == 200) {
TRACE("ELANTECH: not found (5)\n");
return B_ERROR;
}
INFO("Elantech found\n");
dev->name = kElantechPath[dev->idx];
dev->packet_size = PS2_PACKET_ELANTECH;
return B_OK;
}
static status_t
elantech_write_reg(elantech_cookie* cookie, uint8 reg, uint8 value)
{
if (reg < 0x7 || reg > 0x26)
return B_BAD_VALUE;
if (reg > 0x11 && reg < 0x20)
return B_BAD_VALUE;
ps2_dev* dev = cookie->dev;
switch (cookie->version) {
case 1:
// TODO
return B_ERROR;
break;
case 2:
if (ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_REGISTER_WRITE) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, reg) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, value) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11) != B_OK)
return B_ERROR;
break;
case 3:
if (ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_REGISTER_READWRITE) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, reg) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, value) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11) != B_OK)
return B_ERROR;
break;
case 4:
if (ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_REGISTER_READWRITE) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, reg) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_REGISTER_READWRITE) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, value) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_SET_SCALE11) != B_OK)
return B_ERROR;
break;
default:
TRACE("ELANTECH: read_write_reg: unknown version\n");
return B_ERROR;
}
return B_OK;
}
static status_t
elantech_read_reg(elantech_cookie* cookie, uint8 reg, uint8 *value)
{
if (reg < 0x7 || reg > 0x26)
return B_BAD_VALUE;
if (reg > 0x11 && reg < 0x20)
return B_BAD_VALUE;
ps2_dev* dev = cookie->dev;
uint8 val[3];
switch (cookie->version) {
case 1:
// TODO
return B_ERROR;
break;
case 2:
if (ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_REGISTER_READ) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, reg) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, val,
3) != B_OK)
return B_ERROR;
break;
case 3:
case 4:
if (ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_REGISTER_READWRITE)
!= B_OK
|| ps2_dev_command(dev, ELANTECH_CMD_PS2_CUSTOM_CMD) != B_OK
|| ps2_dev_command(dev, reg) != B_OK
|| ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, val,
3) != B_OK)
return B_ERROR;
break;
default:
TRACE("ELANTECH: read_write_reg: unknown version\n");
return B_ERROR;
}
if (cookie->version == 4)
*value = val[1];
else
*value = val[0];
return B_OK;
}
static status_t
switch_hardware_tab(ps2_dev* dev, bool on)
{
uint8 val[3];
uint8 arg = 0x00;
uint8 command = PS2_CMD_MOUSE_SET_RES;
if (on) {
arg = 0x0A;
command = PS2_CMD_SET_SAMPLE_RATE;
}
if (ps2_dev_command(dev, PS2_CMD_MOUSE_GET_INFO, NULL, 0, val, 3) != B_OK
|| ps2_dev_command(dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0) != B_OK
|| ps2_dev_command(dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0) != B_OK
|| ps2_dev_command(dev, command, &arg, 1, NULL, 0) != B_OK)
return B_ERROR;
return B_OK;
}
static status_t
get_resolution_v4(elantech_cookie* cookie, uint32* x, uint32* y)
{
uint8 val[3];
if (elantech_dev_send_command(cookie->dev, ELANTECH_CMD_GET_RESOLUTION,
val, 3) != B_OK)
return B_ERROR;
*x = (val[1] & 0xf) * 10 + 790;
*y = ((val[1] & 0xf) >> 4) * 10 + 790;
return B_OK;
}
static status_t
get_range(elantech_cookie* cookie, uint32* x_min, uint32* y_min, uint32* x_max,
uint32* y_max, uint32 *width)
{
status_t status = B_OK;
uint8 val[3];
switch (cookie->version) {
case 1:
*x_min = 32;
*y_min = 32;
*x_max = 544;
*y_max = 344;
*width = 0;
break;
case 2:
// TODO
break;
case 3:
if ((cookie->send_command)(cookie->dev, ELANTECH_CMD_GET_ID, val, 3)
!= B_OK) {
return B_ERROR;
}
*x_min = 0;
*y_min = 0;
*x_max = ((val[0] & 0xf) << 8) | val[1];
*y_max = ((val[0] & 0xf0) << 4) | val[2];
*width = 0;
break;
case 4:
if ((cookie->send_command)(cookie->dev, ELANTECH_CMD_GET_ID, val, 3)
!= B_OK) {
return B_ERROR;
}
*x_min = 0;
*y_min = 0;
*x_max = ((val[0] & 0xf) << 8) | val[1];
*y_max = ((val[0] & 0xf0) << 4) | val[2];
if (cookie->capabilities[1] < 2 || cookie->capabilities[1] > *x_max)
return B_ERROR;
*width = *x_max / (cookie->capabilities[1] - 1);
break;
}
return B_OK;
}
static status_t
enable_absolute_mode(elantech_cookie* cookie)
{
status_t status = B_OK;
switch (cookie->version) {
case 1:
status = elantech_write_reg(cookie, 0x10, 0x16);
if (status == B_OK)
status = elantech_write_reg(cookie, 0x11, 0x8f);
break;
case 2:
status = elantech_write_reg(cookie, 0x10, 0x54);
if (status == B_OK)
status = elantech_write_reg(cookie, 0x11, 0x88);
if (status == B_OK)
status = elantech_write_reg(cookie, 0x12, 0x60);
break;
case 3:
status = elantech_write_reg(cookie, 0x10, 0xb);
break;
case 4:
status = elantech_write_reg(cookie, 0x7, 0x1);
break;
}
if (cookie->version < 4) {
uint8 val;
for (uint8 retry = 0; retry < 5; retry++) {
status = elantech_read_reg(cookie, 0x10, &val);
if (status != B_OK)
break;
snooze(100);
}
}
return status;
}
status_t
elantech_open(const char *name, uint32 flags, void **_cookie)
{
TRACE("ELANTECH: open %s\n", name);
ps2_dev* dev;
int i;
for (dev = NULL, i = 0; i < PS2_DEVICE_COUNT; i++) {
if (0 == strcmp(ps2_device[i].name, name)) {
dev = &ps2_device[i];
break;
}
}
if (dev == NULL) {
TRACE("ps2: dev = NULL\n");
return B_ERROR;
}
if (atomic_or(&dev->flags, PS2_FLAG_OPEN) & PS2_FLAG_OPEN)
return B_BUSY;
elantech_cookie* cookie = (elantech_cookie*)malloc(
sizeof(elantech_cookie));
if (cookie == NULL)
goto err1;
memset(cookie, 0, sizeof(*cookie));
cookie->movementMaker.Init();
cookie->previousZ = 0;
*_cookie = cookie;
cookie->dev = dev;
dev->cookie = cookie;
dev->disconnect = &elantech_disconnect;
dev->handle_int = &elantech_handle_int;
default_settings(&cookie->settings);
dev->packet_size = PS2_PACKET_ELANTECH;
cookie->ring_buffer = create_packet_buffer(
ELANTECH_HISTORY_SIZE * dev->packet_size);
if (cookie->ring_buffer == NULL) {
TRACE("ELANTECH: can't allocate mouse actions buffer\n");
goto err2;
}
// create the mouse semaphore, used for synchronization between
// the interrupt handler and the read operation
cookie->sem = create_sem(0, "ps2_elantech_sem");
if (cookie->sem < 0) {
TRACE("ELANTECH: failed creating semaphore!\n");
goto err3;
}
uint8 val[3];
if (synaptics_dev_send_command(dev, ELANTECH_CMD_GET_VERSION, val, 3)
!= B_OK) {
TRACE("ELANTECH: get version failed!\n");
goto err4;
}
cookie->fwVersion = (val[0] << 16) | (val[1] << 8) | val[2];
if (cookie->fwVersion < 0x020030 || cookie->fwVersion == 0x020600)
cookie->version = 1;
else {
switch (val[0] & 0xf) {
case 2:
case 4:
cookie->version = 2;
break;
case 5:
cookie->version = 3;
case 6:
case 7:
cookie->version = 4;
break;
default:
TRACE("ELANTECH: unknown version!\n");
goto err4;
}
}
TRACE("ELANTECH: version 0x%lx (0x%lx)\n", cookie->version,
cookie->fwVersion);
if (cookie->version >= 3)
cookie->send_command = &elantech_dev_send_command;
else
cookie->send_command = &synaptics_dev_send_command;
cookie->crcEnabled = (cookie->fwVersion & 0x4000) == 0x4000;
if ((cookie->send_command)(cookie->dev, ELANTECH_CMD_GET_CAPABILITIES,
cookie->capabilities, 3) != B_OK) {
TRACE("ELANTECH: get capabilities failed!\n");
return B_ERROR;
}
if (enable_absolute_mode(cookie) != B_OK) {
TRACE("ELANTECH: failed enabling absolute mode!\n");
goto err4;
}
TRACE("ELANTECH: enabled absolute mode!\n");
uint32 x_min, x_max, y_min, y_max, width;
if (get_range(cookie, &x_min, &y_min, &x_max, &y_max, &width) != B_OK) {
TRACE("ELANTECH: get range failed!\n");
goto err4;
}
TRACE("ELANTECH: range x %ld-%ld y %ld-%ld (%ld)\n", x_min, x_max,
y_min, y_max, width);
uint32 x_res, y_res;
if (get_resolution_v4(cookie, &x_res, &y_res) != B_OK) {
TRACE("ELANTECH: get resolution failed!\n");
goto err4;
}
TRACE("ELANTECH: resolution x %ld y %ld (dpi)\n", x_res, y_res);
gHardwareSpecs.edgeMotionWidth = EDGE_MOTION_WIDTH;
gHardwareSpecs.areaStartX = x_min;
gHardwareSpecs.areaEndX = x_max;
gHardwareSpecs.areaStartY = y_min;
gHardwareSpecs.areaEndY = y_max;
gHardwareSpecs.minPressure = MIN_PRESSURE;
gHardwareSpecs.realMaxPressure = REAL_MAX_PRESSURE;
gHardwareSpecs.maxPressure = MAX_PRESSURE;
cookie->movementMaker.SetSettings(&cookie->settings);
cookie->movementMaker.SetSpecs(&gHardwareSpecs);
if (ps2_dev_command(dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0) != B_OK)
goto err4;
atomic_or(&dev->flags, PS2_FLAG_ENABLED);
TRACE("ELANTECH: open %s success\n", name);
return B_OK;
err4:
delete_sem(cookie->sem);
err3:
delete_packet_buffer(cookie->ring_buffer);
err2:
free(cookie);
err1:
atomic_and(&dev->flags, ~PS2_FLAG_OPEN);
TRACE("ELANTECH: open %s failed\n", name);
return B_ERROR;
}
status_t
elantech_close(void *_cookie)
{
gEventProducer.CancelEvent();
elantech_cookie *cookie = (elantech_cookie*)_cookie;
ps2_dev_command_timeout(cookie->dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0,
150000);
delete_packet_buffer(cookie->ring_buffer);
delete_sem(cookie->sem);
atomic_and(&cookie->dev->flags, ~PS2_FLAG_OPEN);
atomic_and(&cookie->dev->flags, ~PS2_FLAG_ENABLED);
// Reset the touchpad so it generate standard ps2 packets instead of
// extended ones. If not, BeOS is confused with such packets when rebooting
// without a complete shutdown.
status_t status = ps2_reset_mouse(cookie->dev);
if (status != B_OK) {
INFO("ps2: reset failed\n");
return B_ERROR;
}
TRACE("ELANTECH: close %s done\n", cookie->dev->name);
return B_OK;
}
status_t
elantech_freecookie(void *_cookie)
{
free(_cookie);
return B_OK;
}
status_t
elantech_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
{
elantech_cookie *cookie = (elantech_cookie*)_cookie;
mouse_movement movement;
status_t status;
switch (op) {
case MS_READ:
TRACE("ELANTECH: MS_READ get event\n");
if ((status = get_elantech_movement(cookie, &movement)) != B_OK)
return status;
return user_memcpy(buffer, &movement, sizeof(movement));
case MS_IS_TOUCHPAD:
TRACE("ELANTECH: MS_IS_TOUCHPAD\n");
return B_OK;
case MS_SET_TOUCHPAD_SETTINGS:
TRACE("ELANTECH: MS_SET_TOUCHPAD_SETTINGS");
user_memcpy(&cookie->settings, buffer, sizeof(touchpad_settings));
return B_OK;
case MS_SET_CLICKSPEED:
TRACE("ELANTECH: ioctl MS_SETCLICK (set click speed)\n");
return user_memcpy(&cookie->movementMaker.click_speed, buffer,
sizeof(bigtime_t));
default:
TRACE("ELANTECH: unknown opcode: %ld\n", op);
return B_BAD_VALUE;
}
}
static status_t
elantech_read(void* cookie, off_t pos, void* buffer, size_t* _length)
{
*_length = 0;
return B_NOT_ALLOWED;
}
static status_t
elantech_write(void* cookie, off_t pos, const void* buffer, size_t* _length)
{
*_length = 0;
return B_NOT_ALLOWED;
}
int32
elantech_handle_int(ps2_dev* dev)
{
elantech_cookie* cookie = (elantech_cookie*)dev->cookie;
// we got a real event cancel the fake event
gEventProducer.CancelEvent();
uint8 val;
val = cookie->dev->history[0].data;
cookie->buffer[cookie->packet_index] = val;
cookie->packet_index++;
if (cookie->packet_index < PS2_PACKET_ELANTECH)
return B_HANDLED_INTERRUPT;
cookie->packet_index = 0;
if (packet_buffer_write(cookie->ring_buffer,
cookie->buffer, cookie->dev->packet_size)
!= cookie->dev->packet_size) {
// buffer is full, drop new data
return B_HANDLED_INTERRUPT;
}
release_sem_etc(cookie->sem, 1, B_DO_NOT_RESCHEDULE);
return B_INVOKE_SCHEDULER;
}
void
elantech_disconnect(ps2_dev *dev)
{
elantech_cookie *cookie = (elantech_cookie*)dev->cookie;
// the mouse device might not be opened at this point
INFO("ELANTECH: elantech_disconnect %s\n", dev->name);
if ((dev->flags & PS2_FLAG_OPEN) != 0)
release_sem(cookie->sem);
}
device_hooks gElantechDeviceHooks = {
elantech_open,
elantech_close,
elantech_freecookie,
elantech_ioctl,
elantech_read,
elantech_write,
};
@@ -0,0 +1,59 @@
/*
* Copyright 2013, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* The elantech_model_info struct and all the hardware specs are taken from the
* linux driver, thanks a lot!
*
* Authors:
* Jérôme Duval <[email protected]>
*/
#ifndef _PS2_ELANTECH_H
#define _PS2_ELANTECH_H
#include <KernelExport.h>
#include <touchpad_settings.h>
#include "movement_maker.h"
#include "packet_buffer.h"
#include "ps2_dev.h"
typedef struct {
ps2_dev* dev;
sem_id sem;
struct packet_buffer* ring_buffer;
size_t packet_index;
uint8 buffer[PS2_PACKET_ELANTECH];
uint8 mode;
uint8 previousZ;
TouchpadMovement movementMaker;
touchpad_settings settings;
uint32 version;
uint32 fwVersion;
uint8 capabilities[3];
bool crcEnabled;
uint32 fingers;
status_t (*send_command)(ps2_dev* dev, uint8 cmd, uint8 *in, int in_count);
} elantech_cookie;
status_t probe_elantech(ps2_dev *dev);
status_t elantech_open(const char *name, uint32 flags, void **_cookie);
status_t elantech_close(void *_cookie);
status_t elantech_freecookie(void *_cookie);
status_t elantech_ioctl(void *_cookie, uint32 op, void *buffer, size_t length);
int32 elantech_handle_int(ps2_dev *dev);
void elantech_disconnect(ps2_dev *dev);
extern device_hooks gElantechDeviceHooks;
#endif /* _PS2_ELANTECH_H */
@@ -134,6 +134,31 @@ virtio_queue_request(virtio_queue cookie, const physical_entry *readEntry,
}
bool
virtio_queue_is_full(virtio_queue cookie)
{
VirtioQueue *queue = (VirtioQueue *)cookie;
return queue->IsFull();
}
bool
virtio_queue_is_empty(virtio_queue cookie)
{
VirtioQueue *queue = (VirtioQueue *)cookie;
return queue->IsEmpty();
}
uint16
virtio_queue_size(virtio_queue cookie)
{
VirtioQueue *queue = (VirtioQueue *)cookie;
return queue->Size();
}
// #pragma mark -
@@ -222,7 +247,10 @@ virtio_device_interface virtio_device_module = {
virtio_alloc_queues,
virtio_setup_interrupt,
virtio_queue_request,
virtio_queue_request_v
virtio_queue_request_v,
virtio_queue_is_full,
virtio_queue_is_empty,
virtio_queue_size
};
virtio_for_controller_interface virtio_for_controller_module = {
@@ -107,6 +107,7 @@ public:
bool IsFull() const { return fRingFree == 0; }
bool IsEmpty() const { return fRingFree == fRingSize; }
uint16 Size() const { return fRingSize; }
VirtioDevice* Device() { return fDevice; }
@@ -1154,7 +1154,7 @@ TRACE("build tree!\n");
static void
hda_codec_switch_init(hda_audio_group* audioGroup)
hda_audio_group_switch_init(hda_audio_group* audioGroup)
{
for (uint32 i = 0; i < audioGroup->widget_count; i++) {
hda_widget& widget = audioGroup->widgets[i];
@@ -1175,10 +1175,8 @@ hda_codec_switch_init(hda_audio_group* audioGroup)
static void
hda_codec_check_sense(hda_codec* codec, bool disable)
hda_audio_group_check_sense(hda_audio_group* audioGroup, bool disable)
{
hda_audio_group* audioGroup = codec->audio_groups[0];
for (uint32 i = 0; i < audioGroup->widget_count; i++) {
hda_widget& widget = audioGroup->widgets[i];
@@ -1233,7 +1231,8 @@ hda_codec_switch_handler(hda_codec* codec)
codec->unsol_response_read %= MAX_CODEC_UNSOL_RESPONSES;
bool disable = response & 1;
hda_codec_check_sense(codec, disable);
hda_audio_group* audioGroup = codec->audio_groups[0];
hda_audio_group_check_sense(audioGroup, disable);
}
return B_OK;
}
@@ -1285,8 +1284,8 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID)
if (hda_audio_group_build_tree(audioGroup) != B_OK)
goto err;
hda_codec_switch_init(audioGroup);
hda_audio_group_switch_init(audioGroup);
audioGroup->playback_stream = hda_stream_new(audioGroup, STREAM_PLAYBACK);
audioGroup->record_stream = hda_stream_new(audioGroup, STREAM_RECORD);
TRACE("hda: streams playback %p, record %p\n", audioGroup->playback_stream,
@@ -1295,6 +1294,7 @@ hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID)
if (audioGroup->playback_stream != NULL
|| audioGroup->record_stream != NULL) {
codec->audio_groups[codec->num_audio_groups++] = audioGroup;
hda_audio_group_check_sense(audioGroup, false);
return B_OK;
}
@@ -1527,8 +1527,6 @@ hda_codec_new(hda_controller* controller, uint32 codecAddress)
}
}
hda_codec_check_sense(codec, false);
codec->unsol_response_thread = spawn_kernel_thread(
(status_t(*)(void*))hda_codec_switch_handler,
"hda_codec_unsol_thread", B_LOW_PRIORITY, codec);
@@ -63,6 +63,9 @@ nor_init_device(void *_info, void **_cookie)
if (info->id < 0)
return info->id;
info->mapped += HIDDEN_BLOCKS * info->blocksize;
*_cookie = info;
return B_OK;
}
@@ -1,7 +1,7 @@
SubDir HAIKU_TOP src add-ons kernel drivers disk usb usb_disk ;
SubDirSysHdrs $(HAIKU_TOP) src add-ons kernel bus_managers usb ;
UsePrivateHeaders kernel ;
UsePrivateHeaders drivers kernel ;
KernelAddon usb_disk :
usb_disk.cpp
@@ -18,6 +18,7 @@
#include <fs/devfs.h>
#include "scsi_sense.h"
#include "usb_disk_scsi.h"
@@ -136,11 +137,11 @@ status_t usb_disk_receive_csw(disk_device *device,
status_t usb_disk_operation(device_lun *lun, uint8 operation,
uint8 opLength, uint32 logicalBlockAddress,
uint16 transferLength, void *data, size_t *dataLength,
bool directionIn);
bool directionIn, err_act *action = NULL);
status_t usb_disk_request_sense(device_lun *lun);
status_t usb_disk_request_sense(device_lun *lun, err_act *action);
status_t usb_disk_mode_sense(device_lun *lun);
status_t usb_disk_test_unit_ready(device_lun *lun);
status_t usb_disk_test_unit_ready(device_lun *lun, err_act *action = NULL);
status_t usb_disk_inquiry(device_lun *lun);
status_t usb_disk_reset_capacity(device_lun *lun);
status_t usb_disk_update_capacity(device_lun *lun);
@@ -265,7 +266,7 @@ usb_disk_receive_csw(disk_device *device, command_status_wrapper *status)
status_t
usb_disk_operation(device_lun *lun, uint8 operation, uint8 opLength,
uint32 logicalBlockAddress, uint16 transferLength, void *data,
size_t *dataLength, bool directionIn)
size_t *dataLength, bool directionIn, err_act *_action)
{
TRACE("operation: lun: %u; op: %u; oplen: %u; lba: %" B_PRIu32
"; tlen: %u; data: %p; dlen: %p (%lu); in: %c\n",
@@ -407,7 +408,7 @@ usb_disk_operation(device_lun *lun, uint8 operation, uint8 opLength,
" failed at the SCSI level\n", operation);
}
result = usb_disk_request_sense(lun);
result = usb_disk_request_sense(lun, _action);
return result == B_OK ? B_ERROR : result;
}
}
@@ -437,7 +438,7 @@ usb_disk_operation(device_lun *lun, uint8 operation, uint8 opLength,
status_t
usb_disk_request_sense(device_lun *lun)
usb_disk_request_sense(device_lun *lun, err_act *_action)
{
size_t dataLength = sizeof(scsi_request_sense_6_parameter);
scsi_request_sense_6_parameter parameter;
@@ -449,56 +450,42 @@ usb_disk_request_sense(device_lun *lun)
return result;
}
const char *label = NULL;
err_act action = err_act_fail;
status_t status = B_ERROR;
scsi_get_sense_asc_info((parameter.additional_sense_code << 8)
| parameter.additional_sense_code_qualifier, &label, &action,
&status);
if (parameter.sense_key > SCSI_SENSE_KEY_NOT_READY
&& parameter.sense_key != SCSI_SENSE_KEY_UNIT_ATTENTION) {
TRACE_ALWAYS("request_sense: key: 0x%02x; asc: 0x%02x; ascq: "
"0x%02x;\n", parameter.sense_key, parameter.additional_sense_code,
parameter.additional_sense_code_qualifier);
"0x%02x; %s\n", parameter.sense_key, parameter.additional_sense_code,
parameter.additional_sense_code_qualifier,
label ? label : "(unknown)");
}
switch (parameter.sense_key) {
case SCSI_SENSE_KEY_NO_SENSE:
case SCSI_SENSE_KEY_RECOVERED_ERROR:
return B_OK;
case SCSI_SENSE_KEY_HARDWARE_ERROR:
case SCSI_SENSE_KEY_MEDIUM_ERROR:
TRACE_ALWAYS("request_sense: media or hardware error\n");
return B_DEV_UNREADABLE;
case SCSI_SENSE_KEY_ILLEGAL_REQUEST:
TRACE_ALWAYS("request_sense: illegal request\n");
return B_DEV_INVALID_IOCTL;
case SCSI_SENSE_KEY_UNIT_ATTENTION:
if (parameter.additional_sense_code
!= SCSI_ASC_MEDIUM_NOT_PRESENT) {
TRACE_ALWAYS("request_sense: media changed\n");
lun->media_changed = true;
lun->media_present = true;
return B_DEV_MEDIA_CHANGED;
}
// fall through
case SCSI_SENSE_KEY_NOT_READY:
TRACE("request_sense: device not ready (asc 0x%02x ascq 0x%02x)\n",
parameter.additional_sense_code,
parameter.additional_sense_code_qualifier);
lun->media_present = false;
usb_disk_reset_capacity(lun);
return B_DEV_NOT_READY;
case SCSI_SENSE_KEY_DATA_PROTECT:
TRACE_ALWAYS("request_sense: write protected\n");
return B_READ_ONLY_DEVICE;
case SCSI_SENSE_KEY_ABORTED_COMMAND:
TRACE_ALWAYS("request_sense: command aborted\n");
return B_CANCELED;
if ((parameter.additional_sense_code == 0
&& parameter.additional_sense_code_qualifier == 0)
|| label == NULL) {
scsi_get_sense_key_info(parameter.sense_key, &label, &action, &status);
}
return B_ERROR;
if (status == B_DEV_MEDIA_CHANGED) {
lun->media_changed = true;
lun->media_present = true;
} else if (parameter.sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION
&& status != B_DEV_NO_MEDIA) {
lun->media_present = true;
} else if (status == B_DEV_NOT_READY) {
lun->media_present = false;
usb_disk_reset_capacity(lun);
}
if (_action != NULL)
*_action = action;
return status;
}
@@ -524,7 +511,7 @@ usb_disk_mode_sense(device_lun *lun)
status_t
usb_disk_test_unit_ready(device_lun *lun)
usb_disk_test_unit_ready(device_lun *lun, err_act *_action)
{
// if unsupported we assume the unit is fixed and therefore always ok
if (!lun->device->tur_supported)
@@ -533,10 +520,10 @@ usb_disk_test_unit_ready(device_lun *lun)
status_t result;
if (lun->device->is_atapi) {
result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 1,
NULL, NULL, false);
NULL, NULL, false, _action);
} else {
result = usb_disk_operation(lun, SCSI_TEST_UNIT_READY_6, 6, 0, 0,
NULL, NULL, true);
NULL, NULL, true, _action);
}
if (result == B_DEV_INVALID_IOCTL) {
@@ -554,11 +541,14 @@ usb_disk_inquiry(device_lun *lun)
size_t dataLength = sizeof(scsi_inquiry_6_parameter);
scsi_inquiry_6_parameter parameter;
status_t result = B_ERROR;
err_act action = err_act_ok;
for (uint32 tries = 0; tries < 3; tries++) {
result = usb_disk_operation(lun, SCSI_INQUIRY_6, 6, 0, dataLength,
&parameter, &dataLength, true);
if (result == B_OK)
&parameter, &dataLength, true, &action);
if (result == B_OK || (action != err_act_retry
&& action != err_act_many_retries)) {
break;
}
}
if (result != B_OK) {
TRACE_ALWAYS("getting inquiry data failed: %s\n", strerror(result));
@@ -612,6 +602,7 @@ usb_disk_update_capacity(device_lun *lun)
size_t dataLength = sizeof(scsi_read_capacity_10_parameter);
scsi_read_capacity_10_parameter parameter;
status_t result = B_ERROR;
err_act action = err_act_ok;
// Retry reading the capacity up to three times. The first try might only
// yield a unit attention telling us that the device or media status
@@ -620,9 +611,11 @@ usb_disk_update_capacity(device_lun *lun)
// reads.
for (int32 i = 0; i < 3; i++) {
result = usb_disk_operation(lun, SCSI_READ_CAPACITY_10, 10, 0, 0,
&parameter, &dataLength, true);
if (result == B_OK)
&parameter, &dataLength, true, &action);
if (result == B_OK || (action != err_act_retry
&& action != err_act_many_retries)) {
break;
}
}
if (result != B_OK) {
@@ -801,10 +794,11 @@ usb_disk_device_added(usb_device newDevice, void **cookie)
// initialize this lun
result = usb_disk_inquiry(lun);
err_act action = err_act_ok;
for (uint32 tries = 0; tries < 8; tries++) {
TRACE("usb lun %"B_PRIu8" inquiry attempt %"B_PRIu32" begin\n",
i, tries);
status_t ready = usb_disk_test_unit_ready(lun);
status_t ready = usb_disk_test_unit_ready(lun, &action);
if (ready == B_OK || ready == B_DEV_NO_MEDIA) {
if (lun->device_type == B_CD)
lun->write_protected = true;
@@ -821,7 +815,8 @@ usb_disk_device_added(usb_device newDevice, void **cookie)
}
TRACE("usb lun %"B_PRIu8" inquiry attempt %"B_PRIu32" failed\n",
i, tries);
if (action != err_act_retry && action != err_act_many_retries)
break;
bigtime_t snoozeTime = 1000000 * tries;
TRACE("snoozing %"B_PRIu64" microseconds for usb lun\n",
snoozeTime);
@@ -1095,7 +1090,17 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
switch (op) {
case B_GET_MEDIA_STATUS:
{
*(status_t *)buffer = usb_disk_test_unit_ready(lun);
err_act action = err_act_ok;
for (uint32 tries = 0; tries < 3; tries++) {
status_t ready = usb_disk_test_unit_ready(lun, &action);
if (ready == B_OK || ready == B_DEV_NO_MEDIA
|| (action != err_act_retry
&& action != err_act_many_retries)) {
*(status_t *)buffer = ready;
break;
}
snooze(500000);
}
TRACE("B_GET_MEDIA_STATUS: 0x%08" B_PRIx32 "\n",
*(status_t *)buffer);
result = B_OK;
@@ -173,6 +173,7 @@ const struct supported_device {
// Redwood
{0x68da, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5500"},
{0x68d9, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5570"},
{0x675f, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5570"},
{0x68b9, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5600"},
{0x68c1, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5650"},
{0x68d8, 4, 0, RADEON_REDWOOD, CHIP_STD, "Radeon HD 5670"},
@@ -125,8 +125,8 @@ GetInodeNames(const char** root, const char* _path)
status_t
FileSystem::Mount(FileSystem** _fs, RPC::Server* serv, const char* fsPath,
dev_t id, const MountConfiguration& configuration)
FileSystem::Mount(FileSystem** _fs, RPC::Server* serv, const char* serverName,
const char* fsPath, dev_t id, const MountConfiguration& configuration)
{
ASSERT(_fs != NULL);
ASSERT(serv != NULL);
@@ -222,23 +222,23 @@ FileSystem::Mount(FileSystem** _fs, RPC::Server* serv, const char* fsPath,
result = Inode::CreateInode(fs, fi, &inode);
if (result != B_OK)
return result;
RootInode* rootInode = reinterpret_cast<RootInode*>(inode);
fs->fRoot = rootInode;
char* name = strrchr(fsPath, '/');
if (name != NULL) {
name++;
reinterpret_cast<RootInode*>(inode)->SetName(name);
} else if (fsPath[0] != '\0')
reinterpret_cast<RootInode*>(inode)->SetName(fsPath);
else {
char* address = serv->ID().UniversalAddress();
if (address != NULL)
reinterpret_cast<RootInode*>(inode)->SetName(address);
else
reinterpret_cast<RootInode*>(inode)->SetName("NFS4 Share");
free(address);
}
char* fsName = strdup(fsPath);
if (fsName == NULL)
return B_NO_MEMORY;
for (int i = strlen(fsName) - 1; i >= 0 && fsName[i] == '/'; i--)
fsName[i] = '\0';
fs->fRoot = reinterpret_cast<RootInode*>(inode);
char* name = strrchr(fsName, '/');
if (name != NULL)
rootInode->SetName(name + 1);
else if (fsName[0] != '\0')
rootInode->SetName(fsName);
else
rootInode->SetName(serverName);
free(fsName);
fs->NFSServer()->AddFileSystem(fs);
*_fs = fs;
@@ -32,7 +32,8 @@ struct MountConfiguration {
class FileSystem : public DoublyLinkedListLinkImpl<FileSystem> {
public:
static status_t Mount(FileSystem** pfs, RPC::Server* serv,
const char* path, dev_t id,
const char* path, const char* serverName,
dev_t id,
const MountConfiguration& configuration);
~FileSystem();
@@ -74,8 +74,8 @@ CreateNFS4Server(RPC::Server* serv)
// dirtime=X - attempt revalidate directory cache not more often than each X
// seconds
static status_t
ParseArguments(const char* _args, AddressResolver** address, char** _path,
MountConfiguration* conf)
ParseArguments(const char* _args, AddressResolver** address, char** _server,
char** _path, MountConfiguration* conf)
{
if (_args == NULL)
return B_BAD_VALUE;
@@ -94,12 +94,18 @@ ParseArguments(const char* _args, AddressResolver** address, char** _path,
return B_MISMATCHED_VALUES;
*path++ = '\0';
*address = new AddressResolver(args);
if (*address == NULL)
*_server = strdup(args);
if (*_server == NULL)
return B_NO_MEMORY;
*address = new AddressResolver(args);
if (*address == NULL) {
delete *_server;
return B_NO_MEMORY;
}
*_path = strdup(path);
if (*_path == NULL) {
delete *_server;
delete *address;
return B_NO_MEMORY;
}
@@ -176,7 +182,8 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
AddressResolver* resolver;
MountConfiguration config;
char* path;
result = ParseArguments(args, &resolver, &path, &config);
char* serverName;
result = ParseArguments(args, &resolver, &serverName, &path, &config);
if (result != B_OK)
return result;
MemoryDeleter pathDeleter(path);
@@ -188,7 +195,9 @@ nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
return result;
FileSystem* fs;
result = FileSystem::Mount(&fs, server, path, volume->id, config);
result = FileSystem::Mount(&fs, server, serverName, path, volume->id,
config);
free(serverName);
if (result != B_OK) {
gRPCServerManager->Release(server);
return result;
+7 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2006-2012, Haiku, Inc. All rights reserved.
* Copyright 2006-2013, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -288,10 +288,12 @@ NetworkStatusView::MessageReceived(BMessage* message)
{
const char* deviceName;
const char* name;
BNetworkAddress address;
if (message->FindString("device", &deviceName) == B_OK
&& message->FindString("name", &name) == B_OK) {
&& message->FindString("name", &name) == B_OK
&& message->FindFlat("address", &address) == B_OK) {
BNetworkDevice device(deviceName);
status_t status = device.JoinNetwork(name);
status_t status = device.JoinNetwork(address);
if (status != B_OK) {
BString text
= B_TRANSLATE("Could not join wireless network:\n");
@@ -467,6 +469,7 @@ NetworkStatusView::MouseDown(BPoint point)
BMessage* message = new BMessage(kMsgJoinNetwork);
message->AddString("device", wifiInterface);
message->AddString("name", network.name);
message->AddFlat("address", &network.address);
BMenuItem* item = new WirelessNetworkMenuItem(network.name,
network.signal_strength,
@@ -506,7 +509,7 @@ NetworkStatusView::_AboutRequested()
{
BAboutWindow* window = new BAboutWindow(
B_TRANSLATE_SYSTEM_NAME("NetworkStatus"), kSignature);
const char* authors[] = {
"Axel Dörfler",
"Hugo Santos",
+21
View File
@@ -50,6 +50,10 @@
# include <mach-o/arch.h>
#endif
#ifdef __HAIKU__
# include <OS.h>
#endif
#include "system.h"
#include "error.h"
#include "quote.h"
@@ -339,6 +343,23 @@ main (int argc, char **argv)
# endif
}
#endif
#ifdef __HAIKU__
{
system_info sysinfo;
get_system_info(&sysinfo);
switch (sysinfo.platform_type) {
case B_AT_CLONE_PLATFORM:
element = "x86";
break;
case B_64_BIT_PC_PLATFORM:
element = "x86_64";
break;
}
}
#endif
if (! (toprint == UINT_MAX && element == unknown))
print_element (element);
}
+468
View File
@@ -0,0 +1,468 @@
/*
* Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@bluezbox.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/ {
#address-cells = <1>;
#size-cells = <1>;
cpus {
cpu@0 {
compatible = "arm,1176jzf-s";
};
};
SOC: axi {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x20000000 0x01000000>;
ranges = <0 0x20000000 0x01000000>;
intc: interrupt-controller {
compatible = "broadcom,bcm2835-armctrl-ic",
"broadcom,bcm2708-armctrl-ic";
reg = <0xB200 0x200>;
interrupt-controller;
#interrupt-cells = <1>;
/* Bank 0
* 0: ARM_TIMER
* 1: ARM_MAILBOX
* 2: ARM_DOORBELL_0
* 3: ARM_DOORBELL_1
* 4: VPU0_HALTED
* 5: VPU1_HALTED
* 6: ILLEGAL_TYPE0
* 7: ILLEGAL_TYPE1
*/
/* Bank 1
* 0: TIMER0 16: DMA0
* 1: TIMER1 17: DMA1
* 2: TIMER2 18: VC_DMA2
* 3: TIMER3 19: VC_DMA3
* 4: CODEC0 20: DMA4
* 5: CODEC1 21: DMA5
* 6: CODEC2 22: DMA6
* 7: VC_JPEG 23: DMA7
* 8: ISP 24: DMA8
* 9: VC_USB 25: DMA9
* 10: VC_3D 26: DMA10
* 11: TRANSPOSER 27: DMA11
* 12: MULTICORESYNC0 28: DMA12
* 13: MULTICORESYNC1 29: AUX
* 14: MULTICORESYNC2 30: ARM
* 15: MULTICORESYNC3 31: VPUDMA
*/
/* Bank 2
* 0: HOSTPORT 16: SMI
* 1: VIDEOSCALER 17: GPIO0
* 2: CCP2TX 18: GPIO1
* 3: SDC 19: GPIO2
* 4: DSI0 20: GPIO3
* 5: AVE 21: VC_I2C
* 6: CAM0 22: VC_SPI
* 7: CAM1 23: VC_I2SPCM
* 8: HDMI0 24: VC_SDIO
* 9: HDMI1 25: VC_UART
* 10: PIXELVALVE1 26: SLIMBUS
* 11: I2CSPISLV 27: VEC
* 12: DSI1 28: CPG
* 13: PWA0 29: RNG
* 14: PWA1 30: VC_ARASANSDIO
* 15: CPR 31: AVSPMON
*/
};
timer {
compatible = "broadcom,bcm2835-system-timer",
"broadcom,bcm2708-system-timer";
reg = <0x3000 0x1000>;
interrupts = <8 9 10 11>;
interrupt-parent = <&intc>;
clock-frequency = <1000000>;
};
armtimer {
/* Not AMBA compatible */
compatible = "broadcom,bcm2835-sp804", "arm,sp804";
reg = <0xB400 0x24>;
interrupts = <0>;
interrupt-parent = <&intc>;
};
watchdog0 {
compatible = "broadcom,bcm2835-wdt",
"broadcom,bcm2708-wdt";
reg = <0x10001c 0x0c>; /* 0x1c, 0x20, 0x24 */
};
gpio: gpio {
compatible = "broadcom,bcm2835-gpio",
"broadcom,bcm2708-gpio";
reg = <0x200000 0xb0>;
/* Unusual arrangement of interrupts
* (determined by testing)
* 17: Bank 0 (GPIOs 0-31)
* 19: Bank 1 (GPIOs 32-53)
* 18: Bank 2
* 20: All banks (GPIOs 0-53)
*/
interrupts = <57 59 58 60>;
interrupt-parent = <&intc>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pins_reserved>;
/* Pins that can short 3.3V to GND in output mode: 46-47
* Pins used by VideoCore: 48-53
*/
broadcom,read-only = <46>, <47>, <48>, <49>, <50>,
<51>, <52>, <53>;
/* BSC0 */
pins_bsc0_a: bsc0_a {
broadcom,pins = <0>, <1>;
};
pins_bsc0_b: bsc0_b {
broadcom,pins = <28>, <29>;
};
pins_bsc0_c: bsc0_c {
broadcom,pins = <44>, <45>;
};
/* BSC1 */
pins_bsc1_a: bsc1_a {
broadcom,pins = <2>, <3>;
};
pins_bsc1_b: bsc1_b {
broadcom,pins = <44>, <45>;
};
/* GPCLK0 */
pins_gpclk0_a: gpclk0_a {
broadcom,pins = <4>;
};
pins_gpclk0_b: gpclk0_b {
broadcom,pins = <20>;
};
pins_gpclk0_c: gpclk0_c {
broadcom,pins = <32>;
};
pins_gpclk0_d: gpclk0_d {
broadcom,pins = <34>;
};
/* GPCLK1 */
pins_gpclk1_a: gpclk1_a {
broadcom,pins = <5>;
};
pins_gpclk1_b: gpclk1_b {
broadcom,pins = <21>;
};
pins_gpclk1_c: gpclk1_c {
broadcom,pins = <42>;
};
pins_gpclk1_d: gpclk1_d {
broadcom,pins = <44>;
};
/* GPCLK2 */
pins_gpclk2_a: gpclk2_a {
broadcom,pins = <6>;
};
pins_gpclk2_b: gpclk2_b {
broadcom,pins = <43>;
};
/* SPI0 */
pins_spi0_a: spi0_a {
broadcom,pins = <7>, <8>, <9>, <10>, <11>;
};
pins_spi0_b: spi0_b {
broadcom,pins = <35>, <36>, <37>, <38>, <39>;
};
/* PWM */
pins_pwm0_a: pwm0_a {
broadcom,pins = <12>;
};
pins_pwm0_b: pwm0_b {
broadcom,pins = <18>;
};
pins_pwm0_c: pwm0_c {
broadcom,pins = <40>;
};
pins_pwm1_a: pwm1_a {
broadcom,pins = <13>;
};
pins_pwm1_b: pwm1_b {
broadcom,pins = <19>;
};
pins_pwm1_c: pwm1_c {
broadcom,pins = <41>;
};
pins_pwm1_d: pwm1_d {
broadcom,pins = <45>;
};
/* UART0 */
pins_uart0_a: uart0_a {
broadcom,pins = <14>, <15>;
};
pins_uart0_b: uart0_b {
broadcom,pins = <32>, <33>;
};
pins_uart0_c: uart0_c {
broadcom,pins = <36>, <37>;
};
pins_uart0_fc_a: uart0_fc_a {
broadcom,pins = <16>, <17>;
};
pins_uart0_fc_b: uart0_fc_b {
broadcom,pins = <30>, <31>;
};
pins_uart0_fc_c: uart0_fc_c {
broadcom,pins = <39>, <38>;
};
/* PCM */
pins_pcm_a: pcm_a {
broadcom,pins = <18>, <19>, <20>, <21>;
};
pins_pcm_b: pcm_b {
broadcom,pins = <28>, <29>, <30>, <31>;
};
/* Secondary Address Bus */
pins_sm_addr_a: sm_addr_a {
broadcom,pins = <5>, <4>, <3>, <2>, <1>, <0>;
};
pins_sm_addr_b: sm_addr_b {
broadcom,pins = <33>, <32>, <31>, <30>, <29>,
<28>;
};
pins_sm_ctl_a: sm_ctl_a {
broadcom,pins = <6>, <7>;
};
pins_sm_ctl_b: sm_ctl_b {
broadcom,pins = <34>, <35>;
};
pins_sm_data_8bit_a: sm_data_8bit_a {
broadcom,pins = <8>, <9>, <10>, <11>, <12>,
<13>, <14>, <15>;
};
pins_sm_data_8bit_b: sm_data_8bit_b {
broadcom,pins = <36>, <37>, <38>, <39>, <40>,
<41>, <42>, <43>;
};
pins_sm_data_16bit: sm_data_16bit {
broadcom,pins = <16>, <17>, <18>, <19>, <20>,
<21>, <22>, <23>;
};
pins_sm_data_18bit: sm_data_18bit {
broadcom,pins = <24>, <25>;
};
/* BSCSL */
pins_bscsl: bscsl {
broadcom,pins = <18>, <19>;
};
/* SPISL */
pins_spisl: spisl {
broadcom,pins = <18>, <19>, <20>, <21>;
};
/* SPI1 */
pins_spi1: spi1 {
broadcom,pins = <16>, <17>, <18>, <19>, <20>,
<21>;
};
/* UART1 */
pins_uart1_a: uart1_a {
broadcom,pins = <14>, <15>;
};
pins_uart1_b: uart1_b {
broadcom,pins = <32>, <33>;
};
pins_uart1_c: uart1_c {
broadcom,pins = <40>, <41>;
};
pins_uart1_fc_a: uart1_fc_a {
broadcom,pins = <16>, <17>;
};
pins_uart1_fc_b: uart1_fc_b {
broadcom,pins = <30>, <31>;
};
pins_uart1_fc_c: uart1_fc_c {
broadcom,pins = <43>, <42>;
};
/* SPI2 */
pins_spi2: spi2 {
broadcom,pins = <40>, <41>, <42>, <43>, <44>,
<45>;
};
/* ARM JTAG */
pins_arm_jtag_trst: arm_jtag_trst {
broadcom,pins = <22>;
};
pins_arm_jtag_a: arm_jtag_a {
broadcom,pins = <4>, <5>, <6>, <12>, <13>;
};
pins_arm_jtag_b: arm_jtag_b {
broadcom,pins = <23>, <24>, <25>, <26>, <27>;
};
/* Reserved */
pins_reserved: reserved {
broadcom,pins = <48>, <49>, <50>, <51>, <52>,
<53>;
};
};
dma: dma {
compatible = "broadcom,bcm2835-dma",
"broadcom,bcm2708-dma";
reg = <0x7000 0x1000>, <0xE05000 0x1000>;
interrupts = <24 25 26 27 28 29 30 31 32 33 34 35 36>;
interrupt-parent = <&intc>;
broadcom,channels = <0>; /* Set by VideoCore */
};
vc_mbox: mbox {
compatible = "broadcom,bcm2835-mbox",
"broadcom,bcm2708-mbox";
reg = <0xB880 0x40>;
interrupts = <1>;
interrupt-parent = <&intc>;
/* Channels
* 0: Power
* 1: Frame buffer
* 2: Virtual UART
* 3: VCHIQ
* 4: LEDs
* 5: Buttons
* 6: Touch screen
*/
};
sdhci {
compatible = "broadcom,bcm2835-sdhci",
"broadcom,bcm2708-sdhci";
reg = <0x300000 0x100>;
interrupts = <70>;
interrupt-parent = <&intc>;
clock-frequency = <50000000>; /* Set by VideoCore */
};
uart0: uart0 {
compatible = "broadcom,bcm2835-uart",
"broadcom,bcm2708-uart", "arm,pl011",
"arm,primecell";
reg = <0x201000 0x1000>;
interrupts = <65>;
interrupt-parent = <&intc>;
clock-frequency = <3000000>; /* Set by VideoCore */
reg-shift = <2>;
};
vchiq {
compatible = "broadcom,bcm2835-vchiq";
reg = <0xB800 0x50>;
interrupts = <2>;
interrupt-parent = <&intc>;
};
usb {
compatible = "broadcom,bcm2835-usb",
"broadcom,bcm2708-usb",
"synopsys,designware-hs-otg2";
reg = <0x980000 0x20000>;
interrupts = <17>;
interrupt-parent = <&intc>;
#address-cells = <1>;
#size-cells = <0>;
};
};
};
+14
View File
@@ -0,0 +1,14 @@
/* The pxa3xx skeleton simply augments the 2xx version */
/include/ "pxa2xx.dtsi"
/ {
model = "Marvell PXA27x familiy SoC";
compatible = "marvell,pxa27x";
pxabus {
pxairq: interrupt-controller@40d00000 {
marvell,intc-priority;
marvell,intc-nr-irqs = <34>;
};
};
};
+135
View File
@@ -0,0 +1,135 @@
/*
* pxa2xx.dtsi - Device Tree Include file for Marvell PXA2xx family SoC
*
* Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
*
* Licensed under GPLv2 or later.
*/
/include/ "skeleton.dtsi"
/ {
model = "Marvell PXA2xx family SoC";
compatible = "marvell,pxa2xx";
interrupt-parent = <&pxairq>;
aliases {
serial0 = &ffuart;
serial1 = &btuart;
serial2 = &stuart;
serial3 = &hwuart;
/* i2c0 = &pwri2c; */
i2c1 = &pxai2c1;
};
cpus {
#address-cells = <0>;
#size-cells = <0>;
cpu {
compatible = "marvell,xscale";
device_type = "cpu";
};
};
pxabus {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
pxairq: interrupt-controller@40d00000 {
#interrupt-cells = <1>;
compatible = "marvell,pxa-intc";
interrupt-controller;
interrupt-parent;
marvell,intc-nr-irqs = <32>;
reg = <0x40d00000 0xd0>;
};
gpio: gpio@40e00000 {
compatible = "mrvl,pxa-gpio";
#address-cells = <0x1>;
#size-cells = <0x1>;
reg = <0x40e00000 0x10000>;
gpio-controller;
#gpio-cells = <0x2>;
interrupts = <10>;
interrupt-names = "gpio_mux";
interrupt-controller;
#interrupt-cells = <0x2>;
ranges;
gcb0: gpio@40e00000 {
reg = <0x40e00000 0x4>;
};
gcb1: gpio@40e00004 {
reg = <0x40e00004 0x4>;
};
gcb2: gpio@40e00008 {
reg = <0x40e00008 0x4>;
};
gcb3: gpio@40e0000c {
reg = <0x40e0000c 0x4>;
};
};
ffuart: uart@40100000 {
compatible = "mrvl,pxa-uart";
reg = <0x40100000 0x30>;
interrupts = <22>;
status = "disabled";
};
btuart: uart@40200000 {
compatible = "mrvl,pxa-uart";
reg = <0x40200000 0x30>;
interrupts = <21>;
status = "disabled";
};
stuart: uart@40700000 {
compatible = "mrvl,pxa-uart";
reg = <0x40700000 0x30>;
interrupts = <20>;
status = "disabled";
};
hwuart: uart@41100000 {
compatible = "mrvl,pxa-uart";
reg = <0x41100000 0x30>;
interrupts = <7>;
status = "disabled";
};
pxai2c1: i2c@40301680 {
compatible = "mrvl,pxa-i2c";
reg = <0x40301680 0x30>;
interrupts = <18>;
#address-cells = <0x1>;
#size-cells = <0>;
status = "disabled";
};
usb0: ohci@4c000000 {
compatible = "mrvl,pxa-ohci";
reg = <0x4c000000 0x10000>;
interrupts = <3>;
status = "disabled";
};
mmc0: mmc@41100000 {
compatible = "mrvl,pxa-mmc";
reg = <0x41100000 0x1000>;
interrupts = <23>;
status = "disabled";
};
rtc@40900000 {
compatible = "marvell,pxa-rtc";
reg = <0x40900000 0x3c>;
interrupts = <30 31>;
};
};
};
+381
View File
@@ -0,0 +1,381 @@
/*
* Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@bluezbox.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/dts-v1/;
/include/ "bcm2835.dtsi"
/memreserve/ 0x08000000 0x08000000; /* Set by VideoCore */
/ {
model = "Raspberry Pi (BCM2835)";
compatible = "raspberrypi,model-a", "raspberrypi,model-b",
"broadcom,bcm2835-vc", "broadcom,bcm2708-vc";
memory {
device_type = "memory";
reg = <0 0x8000000>; /* 128MB, Set by VideoCore */
};
system {
revision = <0>; /* Set by VideoCore */
serial = <0 0>; /* Set by VideoCore */
};
axi {
gpio: gpio {
/* BSC0 */
pins_bsc0_a: bsc0_a {
broadcom,function = "ALT0";
};
pins_bsc0_b: bsc0_b {
broadcom,function = "ALT0";
};
pins_bsc0_c: bsc0_c {
broadcom,function = "ALT1";
};
/* BSC1 */
pins_bsc1_a: bsc1_a {
broadcom,function = "ALT0";
};
pins_bsc1_b: bsc1_b {
broadcom,function = "ALT2";
};
/* GPCLK0 */
pins_gpclk0_a: gpclk0_a {
broadcom,function = "ALT0";
};
pins_gpclk0_b: gpclk0_b {
broadcom,function = "ALT5";
};
pins_gpclk0_c: gpclk0_c {
broadcom,function = "ALT0";
};
pins_gpclk0_d: gpclk0_d {
broadcom,function = "ALT0";
};
/* GPCLK1 */
pins_gpclk1_a: gpclk1_a {
broadcom,function = "ALT0";
};
pins_gpclk1_b: gpclk1_b {
broadcom,function = "ALT5";
};
pins_gpclk1_c: gpclk1_c {
broadcom,function = "ALT0";
};
pins_gpclk1_d: gpclk1_d {
broadcom,function = "ALT0";
};
/* GPCLK2 */
pins_gpclk2_a: gpclk2_a {
broadcom,function = "ALT0";
};
pins_gpclk2_b: gpclk2_b {
broadcom,function = "ALT0";
};
/* SPI0 */
pins_spi0_a: spi0_a {
broadcom,function = "ALT0";
};
pins_spi0_b: spi0_b {
broadcom,function = "ALT0";
};
/* PWM */
pins_pwm0_a: pwm0_a {
broadcom,function = "ALT0";
};
pins_pwm0_b: pwm0_b {
broadcom,function = "ALT5";
};
pins_pwm0_c: pwm0_c {
broadcom,function = "ALT0";
};
pins_pwm1_a: pwm1_a {
broadcom,function = "ALT0";
};
pins_pwm1_b: pwm1_b {
broadcom,function = "ALT5";
};
pins_pwm1_c: pwm1_c {
broadcom,function = "ALT0";
};
pins_pwm1_d: pwm1_d {
broadcom,function = "ALT0";
};
/* UART0 */
pins_uart0_a: uart0_a {
broadcom,function = "ALT0";
};
pins_uart0_b: uart0_b {
broadcom,function = "ALT3";
};
pins_uart0_c: uart0_c {
broadcom,function = "ALT2";
};
pins_uart0_fc_a: uart0_fc_a {
broadcom,function = "ALT3";
};
pins_uart0_fc_b: uart0_fc_b {
broadcom,function = "ALT3";
};
pins_uart0_fc_c: uart0_fc_c {
broadcom,function = "ALT2";
};
/* PCM */
pins_pcm_a: pcm_a {
broadcom,function = "ALT0";
};
pins_pcm_b: pcm_b {
broadcom,function = "ALT2";
};
/* Secondary Address Bus */
pins_sm_addr_a: sm_addr_a {
broadcom,function = "ALT1";
};
pins_sm_addr_b: sm_addr_b {
broadcom,function = "ALT1";
};
pins_sm_ctl_a: sm_ctl_a {
broadcom,function = "ALT1";
};
pins_sm_ctl_b: sm_ctl_b {
broadcom,function = "ALT1";
};
pins_sm_data_8bit_a: sm_data_8bit_a {
broadcom,function = "ALT1";
};
pins_sm_data_8bit_b: sm_data_8bit_b {
broadcom,function = "ALT1";
};
pins_sm_data_16bit: sm_data_16bit {
broadcom,function = "ALT1";
};
pins_sm_data_18bit: sm_data_18bit {
broadcom,function = "ALT1";
};
/* BSCSL */
pins_bscsl: bscsl {
broadcom,function = "ALT3";
};
/* SPISL */
pins_spisl: spisl {
broadcom,function = "ALT3";
};
/* SPI1 */
pins_spi1: spi1 {
broadcom,function = "ALT4";
};
/* UART1 */
pins_uart1_a: uart1_a {
broadcom,function = "ALT5";
};
pins_uart1_b: uart1_b {
broadcom,function = "ALT5";
};
pins_uart1_c: uart1_c {
broadcom,function = "ALT5";
};
pins_uart1_fc_a: uart1_fc_a {
broadcom,function = "ALT5";
};
pins_uart1_fc_b: uart1_fc_b {
broadcom,function = "ALT5";
};
pins_uart1_fc_c: uart1_fc_c {
broadcom,function = "ALT5";
};
/* SPI2 */
pins_spi2: spi2 {
broadcom,function = "ALT4";
};
/* ARM JTAG */
pins_arm_jtag_trst: arm_jtag_trst {
broadcom,function = "ALT4";
};
pins_arm_jtag_a: arm_jtag_a {
broadcom,function = "ALT5";
};
pins_arm_jtag_b: arm_jtag_b {
broadcom,function = "ALT4";
};
/* Reserved */
pins_reserved: reserved {
broadcom,function = "ALT3";
};
};
usb {
hub {
compatible = "usb,hub", "usb,device";
reg = <0x00000001>;
#address-cells = <1>;
#size-cells = <0>;
ethernet {
compatible = "net,ethernet",
"usb,device";
reg = <0x00000001>;
mac-address = [00 00 00 00 00 00];
};
};
};
};
display {
compatible = "broadcom,bcm2835-fb", "broadcom,bcm2708-fb";
broadcom,vc-mailbox = <&vc_mbox>;
broadcom,vc-channel = <1>;
broadcom,width = <0>; /* Set by VideoCore */
broadcom,height = <0>; /* Set by VideoCore */
broadcom,depth = <0>; /* Set by VideoCore */
};
leds {
compatible = "gpio-leds";
ok {
label = "ok";
gpios = <&gpio 16 1>;
/* Don't change this - it configures
* how the led driver determines if
* the led is on or off when it loads.
*/
default-state = "keep";
/* This is the real default state. */
linux,default-trigger = "default-on";
};
};
power: regulator {
compatible = "broadcom,bcm2835-power-mgr",
"broadcom,bcm2708-power-mgr",
"simple-bus";
#address-cells = <1>;
#size-cells = <0>;
broadcom,vc-mailbox = <&vc_mbox>;
broadcom,vc-channel = <0>;
regulator-name = "VideoCore";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on = <1>;
sd_card_power: regulator@0 {
compatible = "broadcom,bcm2835-power-dev",
"broadcom,bcm2708-power-dev";
reg = <0>;
vin-supply = <&power>;
regulator-name = "SD Card";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
/* This is for the controller itself, not the root port */
usb_hcd_power: regulator@3 {
compatible = "broadcom,bcm2835-power-dev",
"broadcom,bcm2708-power-dev";
reg = <3>;
vin-supply = <&power>;
regulator-name = "USB HCD";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
};
aliases {
uart0 = &uart0;
};
chosen {
bootargs = ""; /* Set by VideoCore */
stdin = "uart0";
stdout = "uart0";
};
};
+13
View File
@@ -0,0 +1,13 @@
/*
* Skeleton device tree; the bare minimum needed to boot; just include and
* add a compatible value. The bootloader will typically populate the memory
* node.
*/
/ {
#address-cells = <1>;
#size-cells = <1>;
chosen { };
aliases { };
memory { device_type = "memory"; reg = <0 0>; };
};
+41
View File
@@ -0,0 +1,41 @@
/dts-v1/;
/include/ "pxa27x.dtsi"
/ {
model = "Gumstix Verdex";
compatible = "gumstix,verdex", "marvell,pxa27x";
chosen {
bootargs = "console=ttyS0,115200 debug";
};
memory {
reg = <0xa0000000 0x10000000>;
};
pxabus {
ffuart: uart@40100000 {
status = "okay";
};
usb0: ohci@4c000000 {
status = "okay";
};
/* The devices below should be in pxa27x.dtsi, but I kept them here
so to keep the files from upstream as clean as possible for now */
lcdc: lcdc@44000000 {
compatible = "mrvl,pxa-lcdc" ;
reg = <0x44000000 0xa0> ;
interrupts = <17> ;
};
timers: timers@40a00000 {
compatible = "mrvl,pxa-timers" ;
reg = <0x40a00000 0xc0> ;
interrupts = <26>, <27>, <28>, <29>, <7> ;
interrupt-names = "OST_0", "OST_1", "OST_2", "OST_3", "OST_4_11" ;
};
};
};
@@ -863,6 +863,7 @@ ScreenSaverWindow::ScreenSaverWindow()
// Create the tab view
fTabView = new BTabView("tab_view", B_WIDTH_FROM_LABEL);
fTabView->SetBorder(B_NO_BORDER);
// Create the controls inside the tabs
fFadeView = new FadeView(B_TRANSLATE("General"), fSettings);
@@ -878,7 +879,7 @@ ScreenSaverWindow::ScreenSaverWindow()
B_ALIGN_USE_FULL_HEIGHT));
topView->SetExplicitMinSize(BSize(fMinWidth, fMinHeight));
BLayoutBuilder::Group<>(topView, B_VERTICAL)
.SetInsets(-1, B_USE_SMALL_SPACING, -1, -1)
.SetInsets(0, B_USE_SMALL_SPACING, 0, 0)
.Add(fTabView)
.End();
@@ -0,0 +1,51 @@
/*
* Copyright 2011-2012 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck IV, kallisti5@unixzen.com
*/
#ifndef _ARCH_FRAMEBUFFER_H
#define _ARCH_FRAMEBUFFER_H
#include <boot/platform.h>
#include <SupportDefs.h>
#define TRACE_VIDEO
#ifdef TRACE_VIDEO
# define TRACE(x...) dprintf(x)
# define CALLED() dprintf("%s()\n", __func__);
#else
# define TRACE(x...) ;
# define CALLED() ;
#endif
#define ERROR(x...) dprintf(x)
class ArchFramebuffer {
public:
ArchFramebuffer(addr_t base)
:
fBase(base) {};
~ArchFramebuffer() {};
virtual status_t Init() { return B_OK; };
virtual status_t Probe() { return B_OK; };
virtual status_t SetDefaultMode() { return B_OK; };
virtual status_t SetVideoMode(int width, int height, int depth)
{ return B_OK; };
virtual addr_t Base() { return fBase; };
protected:
addr_t fBase;
private:
int fCurrentWidth;
int fCurrentHeight;
int fCurrentDepth;
};
#endif /* _ARCH_FRAMEBUFFER_H */
+4
View File
@@ -52,6 +52,7 @@ BootMergeObject boot_platform_u-boot_common.o :
uimage.cpp
video.cpp
fdt_support.cpp
openfirmware.cpp
$(genericPlatformSources)
$(libFDTSources)
@@ -247,6 +248,9 @@ Depends haiku-mmc-image : haiku-$(HAIKU_BOOT_BOARD).mmc ;
SEARCH on [ FGristFiles $(genericPlatformSources) ]
= [ FDirName $(HAIKU_TOP) src system boot platform generic ] ;
SEARCH on [ FGristFiles openfirmware.cpp fdt_support.cpp ]
= [ FDirName $(HAIKU_TOP) src system kernel platform u-boot ] ;
SEARCH on [ FGristFiles $(libFDTSources) ]
= [ FDirName $(HAIKU_TOP) src libs libfdt ] ;
@@ -6,19 +6,27 @@ UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ]
[ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ;
UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ;
UseLibraryHeaders [ FDirName libfdt ] ;
SubDirC++Flags -fno-rtti ;
BootMergeObject boot_platform_u-boot_ppc_amcc440.o :
arch_mmu_amcc440.cpp
: -fno-pic -mcpu=440
;
BootMergeObject boot_platform_u-boot_ppc.o :
# must come first to have _start_* at correct locations
shell.S
#arch_mmu.cpp
arch_mmu.cpp
arch_cpu_asm.S
arch_start_kernel.S
arch_cpu.cpp
#mmu.cpp
: -fno-pic
: boot_platform_u-boot_ppc_amcc440.o
;
SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ]
SEARCH on [ FGristFiles arch_cpu_asm.S ]
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ;
@@ -17,26 +17,142 @@
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <arch/ppc/arch_cpu.h>
#include <arch/ppc/arch_platform.h>
#include <arch_kernel.h>
#include <arch_system_info.h>
#include <platform/openfirmware/devices.h>
#include <platform/openfirmware/openfirmware.h>
#include <string.h>
// TODO: try to move remaining FDT code to OF calls
extern "C" {
#include <fdt.h>
#include <libfdt.h>
#include <libfdt_env.h>
};
//#define TRACE_CPU
extern void *gFDT;
#define TRACE_CPU
#ifdef TRACE_CPU
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
//uint32 gTimeConversionFactor;
// FIXME: this is ugly; introduce a cpu type in kernel args
bool gIs440 = false;
static void
calculate_cpu_conversion_factor()
static status_t
enumerate_cpus(void)
{
#warning U-Boot:TODO!
// iterate through the "/cpus" node to find all CPUs
int cpus = of_finddevice("/cpus");
if (cpus == OF_FAILED) {
printf("enumerate_cpus(): Failed to open \"/cpus\"!\n");
return B_ERROR;
}
char cpuPath[256];
int cookie = 0;
int cpuCount = 0;
while (of_get_next_device(&cookie, cpus, "cpu", cpuPath,
sizeof(cpuPath)) == B_OK) {
TRACE(("found CPU: %s\n", cpuPath));
// For the first CPU get the frequencies of CPU, bus, and time base.
// We assume they are the same for all CPUs.
if (cpuCount == 0) {
int cpu = of_finddevice(cpuPath);
if (cpu == OF_FAILED) {
printf("enumerate_cpus: Failed get CPU device node!\n");
return B_ERROR;
}
// TODO: Does encode-int really encode quadlet (32 bit numbers)
// only?
int32 clockFrequency;
if (of_getprop(cpu, "clock-frequency", &clockFrequency, 4)
== OF_FAILED) {
printf("enumerate_cpus: Failed to get CPU clock "
"frequency!\n");
return B_ERROR;
}
int32 busFrequency = 0;
if (of_getprop(cpu, "bus-frequency", &busFrequency, 4)
== OF_FAILED) {
//printf("enumerate_cpus: Failed to get bus clock "
// "frequency!\n");
//return B_ERROR;
}
int32 timeBaseFrequency;
if (of_getprop(cpu, "timebase-frequency", &timeBaseFrequency, 4)
== OF_FAILED) {
printf("enumerate_cpus: Failed to get time base "
"frequency!\n");
return B_ERROR;
}
gKernelArgs.arch_args.cpu_frequency = clockFrequency;
gKernelArgs.arch_args.bus_frequency = busFrequency;
gKernelArgs.arch_args.time_base_frequency = timeBaseFrequency;
TRACE((" CPU clock frequency: %ld\n", clockFrequency));
//TRACE((" bus clock frequency: %ld\n", busFrequency));
TRACE((" time base frequency: %ld\n", timeBaseFrequency));
}
cpuCount++;
}
if (cpuCount == 0) {
printf("enumerate_cpus(): Found no CPUs!\n");
return B_ERROR;
}
gKernelArgs.num_cpus = cpuCount;
// FDT doesn't list bus frequency on the cpu node but on the plb node
if (gKernelArgs.arch_args.bus_frequency == 0) {
int plb = of_finddevice("/plb");
int32 busFrequency = 0;
if (of_getprop(plb, "clock-frequency", &busFrequency, 4)
== OF_FAILED) {
printf("enumerate_cpus: Failed to get bus clock "
"frequency!\n");
return B_ERROR;
}
gKernelArgs.arch_args.bus_frequency = busFrequency;
}
TRACE((" bus clock frequency: %Ld\n",
gKernelArgs.arch_args.bus_frequency));
#if 0
//XXX:Classic
// allocate the kernel stacks (the memory stuff is already initialized
// at this point)
addr_t stack = (addr_t)arch_mmu_allocate((void*)0x80000000,
cpuCount * (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE),
B_READ_AREA | B_WRITE_AREA, false);
if (!stack) {
printf("enumerate_cpus(): Failed to allocate kernel stack(s)!\n");
return B_NO_MEMORY;
}
for (int i = 0; i < cpuCount; i++) {
gKernelArgs.cpu_kstack[i].start = stack;
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
stack += KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
}
#endif
return B_OK;
}
@@ -44,17 +160,69 @@ static status_t
check_cpu_features()
{
uint32 msr;
uint32 pvr;
bool is_440 = false;
bool is_460 = false;
bool pvr_unknown = false;
bool fdt_unknown = true;
const char *fdt_model = NULL;
#if BOARD_CPU_TYPE_PPC440
// the FPU is implemented as an Auxiliary Processing Unit,
// so we must enable transfers by setting the DAPUIB bit to 0
asm volatile(
"mfccr0 %%r3\n"
"\tlis %%r4,~(1<<(20-16))\n"
"\tand %%r3,%%r3,%%r4\n"
"\tmtccr0 %%r3"
: : : "r3", "r4");
#endif
// attempt to detect processor version, either from PVR or FDT
// TODO:someday we'll support other things than 440/460...
// read the Processor Version Register
pvr = get_pvr();
uint16 version = (uint16)(pvr >> 16);
uint16 revision = (uint16)(pvr & 0xffff);
switch (version) {
case AMCC440EP:
is_440 = true;
break;
case AMCC460EX:
is_460 = true;
break;
default:
pvr_unknown = true;
}
// if we have an FDT...
// XXX: use it only as fallback?
if (gFDT != NULL/* && pvr_unknown*/) {
// TODO: for MP support we must check /chosen/cpu first
int node = fdt_path_offset(gFDT, "/cpus/cpu@0");
int len;
fdt_model = (const char *)fdt_getprop(gFDT, node, "model", &len);
// TODO: partial match ? "PowerPC,440" && isalpha(next char) ?
if (fdt_model) {
if (!strcmp(fdt_model, "PowerPC,440EP")) {
is_440 = true;
fdt_unknown = false;
} else if (!strcmp(fdt_model, "PowerPC,460EX")) {
is_460 = true;
fdt_unknown = false;
}
}
}
if (is_460)
is_440 = true;
gIs440 = is_440;
// some cpu-dependent tweaking
if (is_440) {
// the FPU is implemented as an Auxiliary Processing Unit,
// so we must enable transfers by setting the DAPUIB bit to 0
asm volatile(
"mfccr0 %%r3\n"
"\tlis %%r4,~(1<<(20-16))\n"
"\tand %%r3,%%r3,%%r4\n"
"\tmtccr0 %%r3"
: : : "r3", "r4");
}
// we do need an FPU for vsnprintf to work
// on Sam460ex at least U-Boot doesn't enable the FPU for us
@@ -68,6 +236,11 @@ check_cpu_features()
return B_ERROR;
}
TRACE(("CPU detection:\n"));
TRACE(("PVR revision %sknown: 0x%8lx\n", pvr_unknown ? "un" : "", pvr));
TRACE(("FDT model %sknown: %s\n", fdt_unknown ? "un" : "", fdt_model));
TRACE(("flags: %s440 %s460\n", is_440 ? "" : "!", is_460 ? "" : "!"));
return B_OK;
}
@@ -92,6 +265,11 @@ arch_spin(bigtime_t microseconds)
extern "C" status_t
boot_arch_cpu_init(void)
{
// This is U-Boot
gKernelArgs.arch_args.platform = PPC_PLATFORM_U_BOOT;
// first check some features
// including some necessary for dprintf()...
status_t err = check_cpu_features();
if (err != B_OK) {
@@ -99,10 +277,8 @@ boot_arch_cpu_init(void)
return err;
}
calculate_cpu_conversion_factor();
gKernelArgs.num_cpus = 1;
// this will eventually be corrected later on
// now enumerate correctly all CPUs and get system frequencies
enumerate_cpus();
return B_OK;
}
@@ -0,0 +1,425 @@
/*
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Based on code written by Travis Geiselbrecht for NewOS.
*
* Distributed under the terms of the MIT License.
*/
#include "mmu.h"
#include <boot/platform.h>
#include <boot/stdio.h>
#include <boot/kernel_args.h>
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <arch_kernel.h>
#include <platform/openfirmware/openfirmware.h>
#ifdef __ARM__
#include <arm_mmu.h>
#endif
#include <kernel.h>
#include <board_config.h>
#include <OS.h>
#include <string.h>
/*! This implements boot loader mmu support for Book-E PowerPC,
which only support a limited number of TLB and no hardware page table walk,
and does not standardize at how to use the mmu, requiring vendor-specific
code.
Like Linux, we pin one of the TLB entries to a fixed translation,
however we use it differently.
cf. http://kernel.org/doc/ols/2003/ols2003-pages-340-350.pdf
This translation uses a single large page (16 or 256MB are possible) which
directly maps the begining of the RAM.
We use it as a linear space to allocate from at boot time,
loading the kernel and modules into it, and other required data.
Near the end we reserve a page table (it doesn't need to be aligned),
but unlike Linux we use the same globally hashed page table that is
implemented by Classic PPC, to allow reusing code if possible, and also
to limit fragmentation which would occur by using a tree-based page table.
However this means we might actually run out of page table entries in case
of too many collisions.
The kernel will then create areas to cover this already-mapped space.
This also means proper permission bits (RWX) will not be applicable to
separate areas which are enclosed by this mapping.
We put the kernel stack at the end of the mapping so that the guard page is
outsite and thus unmapped. (we don't support SMP)
*/
/*! The (physical) memory layout of the boot loader is currently as follows:
0x00000000 kernel
0x00400000 ...modules
(at least on the Sam460ex U-Boot; we'll need to accomodate other setups)
0x01000000 boot loader
0x01800000 Flattened Device Tree
0x01900000 boot.tgz (= ramdisk)
0x02000000 boot loader uimage
boot loader heap (should be discarded later on)
... 256M-Kstack page hash table
... 256M kernel stack
kernel stack guard page
The kernel is mapped at KERNEL_BASE, all other stuff mapped by the
loader (kernel args, modules, driver settings, ...) comes after
0x80040000 which means that there is currently only 4 MB reserved for
the kernel itself (see kMaxKernelSize). FIXME: downsize kernel_ppc
*/
int32 of_address_cells(int package);
int32 of_size_cells(int package);
extern bool gIs440;
// XXX:use a base class for Book-E support?
extern status_t arch_mmu_setup_pinned_tlb_amcc440(phys_addr_t totalRam,
size_t &tableSize, size_t &tlbSize);
#define TRACE_MMU
#ifdef TRACE_MMU
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
#define TRACE_MEMORY_MAP
// Define this to print the memory map to serial debug.
static const size_t kMaxKernelSize = 0x400000; // 4 MB for the kernel
static addr_t sNextPhysicalAddress = kMaxKernelSize; //will be set by mmu_init
static addr_t sNextVirtualAddress = KERNEL_BASE + kMaxKernelSize;
//static addr_t sMaxVirtualAddress = KERNEL_BASE + kMaxKernelSize;
// working page directory and page table
static void *sPageTable = 0 ;
static addr_t
get_next_virtual_address(size_t size)
{
addr_t address = sNextVirtualAddress;
sNextPhysicalAddress += size;
sNextVirtualAddress += size;
return address;
}
static addr_t
get_next_physical_address(size_t size)
{
addr_t address = sNextPhysicalAddress;
sNextPhysicalAddress += size;
sNextVirtualAddress += size;
return address;
}
// #pragma mark -
extern "C" addr_t
mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags)
{
panic("WRITEME");
return 0;
}
/*! Sets up the final and kernel accessible GDT and IDT tables.
BIOS calls won't work any longer after this function has
been called.
*/
extern "C" void
mmu_init_for_kernel(void)
{
TRACE(("mmu_init_for_kernel\n"));
// TODO: remove all U-Boot TLB
#ifdef TRACE_MEMORY_MAP
{
uint32 i;
dprintf("phys memory ranges:\n");
for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) {
dprintf(" base 0x%"B_PRIxPHYSADDR
", length 0x%"B_PRIxPHYSADDR"\n",
gKernelArgs.physical_memory_range[i].start,
gKernelArgs.physical_memory_range[i].size);
}
dprintf("allocated phys memory ranges:\n");
for (i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) {
dprintf(" base 0x%"B_PRIxPHYSADDR
", length 0x%"B_PRIxPHYSADDR"\n",
gKernelArgs.physical_allocated_range[i].start,
gKernelArgs.physical_allocated_range[i].size);
}
dprintf("allocated virt memory ranges:\n");
for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) {
dprintf(" base 0x%"B_PRIxPHYSADDR
", length 0x%"B_PRIxPHYSADDR"\n",
gKernelArgs.virtual_allocated_range[i].start,
gKernelArgs.virtual_allocated_range[i].size);
}
}
#endif
}
//TODO:move this to generic/ ?
static status_t
find_physical_memory_ranges(phys_addr_t &total)
{
int memory = -1;
int package;
dprintf("checking for memory...\n");
if (of_getprop(gChosen, "memory", &memory, sizeof(int)) == OF_FAILED)
package = of_finddevice("/memory");
else
package = of_instance_to_package(memory);
if (package == OF_FAILED)
return B_ERROR;
total = 0;
// Memory base addresses are provided in 32 or 64 bit flavors
// #address-cells and #size-cells matches the number of 32-bit 'cells'
// representing the length of the base address and size fields
int root = of_finddevice("/");
int32 regAddressCells = of_address_cells(root);
int32 regSizeCells = of_size_cells(root);
if (regAddressCells == OF_FAILED || regSizeCells == OF_FAILED) {
dprintf("finding base/size length counts failed, assume 32-bit.\n");
regAddressCells = 1;
regSizeCells = 1;
}
// NOTE : Size Cells of 2 is possible in theory... but I haven't seen it yet.
if (regAddressCells > 2 || regSizeCells > 1) {
panic("%s: Unsupported OpenFirmware cell count detected.\n"
"Address Cells: %" B_PRId32 "; Size Cells: %" B_PRId32
" (CPU > 64bit?).\n", __func__, regAddressCells, regSizeCells);
return B_ERROR;
}
// On 64-bit PowerPC systems (G5), our mem base range address is larger
if (regAddressCells == 2) {
struct of_region<uint64> regions[64];
int count = of_getprop(package, "reg", regions, sizeof(regions));
if (count == OF_FAILED)
count = of_getprop(memory, "reg", regions, sizeof(regions));
if (count == OF_FAILED)
return B_ERROR;
count /= sizeof(regions[0]);
for (int32 i = 0; i < count; i++) {
if (regions[i].size <= 0) {
dprintf("%ld: empty region\n", i);
continue;
}
dprintf("%" B_PRIu32 ": base = %" B_PRIu64 ","
"size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size);
total += regions[i].size;
if (insert_physical_memory_range((addr_t)regions[i].base,
regions[i].size) != B_OK) {
dprintf("cannot map physical memory range "
"(num ranges = %" B_PRIu32 ")!\n",
gKernelArgs.num_physical_memory_ranges);
return B_ERROR;
}
}
return B_OK;
}
// Otherwise, normal 32-bit PowerPC G3 or G4 have a smaller 32-bit one
struct of_region<uint32> regions[64];
int count = of_getprop(package, "reg", regions, sizeof(regions));
if (count == OF_FAILED)
count = of_getprop(memory, "reg", regions, sizeof(regions));
if (count == OF_FAILED)
return B_ERROR;
count /= sizeof(regions[0]);
for (int32 i = 0; i < count; i++) {
if (regions[i].size <= 0) {
dprintf("%ld: empty region\n", i);
continue;
}
dprintf("%" B_PRIu32 ": base = %" B_PRIu32 ","
"size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size);
total += regions[i].size;
if (insert_physical_memory_range((addr_t)regions[i].base,
regions[i].size) != B_OK) {
dprintf("cannot map physical memory range "
"(num ranges = %" B_PRIu32 ")!\n",
gKernelArgs.num_physical_memory_ranges);
return B_ERROR;
}
}
return B_OK;
}
extern "C" void
mmu_init(void)
{
size_t tableSize, tlbSize;
status_t err;
TRACE(("mmu_init\n"));
// get map of physical memory (fill in kernel_args structure)
phys_addr_t total;
if (find_physical_memory_ranges(total) != B_OK) {
dprintf("Error: could not find physical memory ranges!\n");
return /*B_ERROR*/;
}
dprintf("total physical memory = %" B_PRId64 "MB\n", total / (1024 * 1024));
// XXX: ugly, and wrong, there are several 440 mmu types... FIXME
if (gIs440) {
err = arch_mmu_setup_pinned_tlb_amcc440(total, tableSize, tlbSize);
dprintf("setup_pinned_tlb: 0x%08lx table %zdMB tlb %zdMB\n",
err, tableSize / (1024 * 1024), tlbSize / (1024 * 1024));
} else {
panic("Unknown MMU type!");
return;
}
// remember the start of the allocated physical pages
gKernelArgs.physical_allocated_range[0].start
= gKernelArgs.physical_memory_range[0].start;
gKernelArgs.physical_allocated_range[0].size = tlbSize;
gKernelArgs.num_physical_allocated_ranges = 1;
// Save the memory we've virtually allocated (for the kernel and other
// stuff)
gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE;
gKernelArgs.virtual_allocated_range[0].size
= tlbSize + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
gKernelArgs.num_virtual_allocated_ranges = 1;
sPageTable = (void *)(tlbSize - tableSize - KERNEL_STACK_SIZE);
// we put the page table near the end of the pinned TLB
TRACE(("page table at 0x%p to 0x%p\n", sPageTable,
(uint8 *)sPageTable + tableSize));
// map in a kernel stack
gKernelArgs.cpu_kstack[0].start = (addr_t)(tlbSize - KERNEL_STACK_SIZE);
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
TRACE(("kernel stack at 0x%Lx to 0x%Lx\n", gKernelArgs.cpu_kstack[0].start,
gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size));
#ifdef __ARM__
init_page_directory();
// map the page directory on the next vpage
gKernelArgs.arch_args.vir_pgdir = mmu_map_physical_memory(
(addr_t)sPageDirectory, MMU_L1_TABLE_SIZE, kDefaultPageFlags);
#endif
}
// #pragma mark -
extern "C" status_t
platform_allocate_region(void **_address, size_t size, uint8 protection,
bool /*exactAddress*/)
{
TRACE(("platform_allocate_region(&%p, %zd)\n", *_address, size));
//get_next_virtual_address
size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE;
// roundup to page size for clarity
if (*_address != NULL) {
// This special path is almost only useful for loading the
// kernel into memory; it will only allow you to map the
// 'kMaxKernelSize' bytes following the kernel base address.
// Also, it won't check for already mapped addresses, so
// you better know why you are here :)
addr_t address = (addr_t)*_address;
// is the address within the valid range?
if (address < KERNEL_BASE
|| address + size >= KERNEL_BASE + kMaxKernelSize) {
TRACE(("mmu_allocate in illegal range\n address: %lx"
" KERNELBASE: %lx KERNEL_BASE + kMaxKernelSize: %lx"
" address + size : %lx \n", (uint32)address, KERNEL_BASE,
KERNEL_BASE + kMaxKernelSize, (uint32)(address + size)));
return B_ERROR;
}
TRACE(("platform_allocate_region: allocated %zd bytes at %08lx\n", size,
address));
return B_OK;
}
void *address = (void *)get_next_virtual_address(size);
if (address == NULL)
return B_NO_MEMORY;
TRACE(("platform_allocate_region: allocated %zd bytes at %p\n", size,
address));
*_address = address;
return B_OK;
}
extern "C" status_t
platform_free_region(void *address, size_t size)
{
TRACE(("platform_free_region(%p, %zd)\n", address, size));
#ifdef __ARM__
mmu_free(address, size);
#endif
return B_OK;
}
void
platform_release_heap(struct stage2_args *args, void *base)
{
//XXX
// It will be freed automatically, since it is in the
// identity mapped region, and not stored in the kernel's
// page tables.
}
status_t
platform_init_heap(struct stage2_args *args, void **_base, void **_top)
{
// the heap is put right before the pagetable
void *heap = (uint8 *)sPageTable - args->heap_size;
//FIXME: use phys addresses to allow passing args to U-Boot?
*_base = heap;
*_top = (void *)((int8 *)heap + args->heap_size);
TRACE(("boot heap at 0x%p to 0x%p\n", *_base, *_top));
return B_OK;
}
@@ -0,0 +1,180 @@
/*
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Based on code written by Travis Geiselbrecht for NewOS.
*
* Distributed under the terms of the MIT License.
*/
#include "mmu.h"
#include <boot/platform.h>
#include <boot/stdio.h>
#include <boot/kernel_args.h>
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <arch/ppc/arch_mmu_amcc440.h>
#include <arch_kernel.h>
#include <platform/openfirmware/openfirmware.h>
#ifdef __ARM__
#include <arm_mmu.h>
#endif
#include <kernel.h>
#include <board_config.h>
#include <OS.h>
#include <string.h>
int32 of_address_cells(int package);
int32 of_size_cells(int package);
#define TRACE_MMU
#ifdef TRACE_MMU
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
/*! Computes the recommended minimal page table size as
described in table 7-22 of the PowerPC "Programming
Environment for 32-Bit Microprocessors".
The page table size ranges from 64 kB (for 8 MB RAM)
to 32 MB (for 4 GB RAM).
FIXME: account for larger TLB descriptors for Book-E
*/
static size_t
suggested_page_table_size(phys_addr_t total)
{
uint32 max = 23;
// 2^23 == 8 MB
while (max < 32) {
if (total <= (1UL << max))
break;
max++;
}
return 1UL << (max - 7);
// 2^(23 - 7) == 64 kB
}
static void
read_TLB(int i, uint32 tlb[3], uint8 &pid)
{
//FIXME:read pid too
asm volatile(
"tlbre %0,%3,0\n"
"\ttlbre %1,%3,1\n"
"\ttlbre %2,%3,2"
: "=r"(tlb[0]),
"=r"(tlb[1]),
"=r"(tlb[2])
: "r"(i)
);
}
static void
write_TLB(int i, uint32 tlb[3], uint8 pid)
{
//FIXME:write pid too
asm volatile(
"tlbwe %0,%3,0\n"
"\ttlbwe %1,%3,1\n"
"\ttlbwe %2,%3,2"
: : "r"(tlb[0]),
"r"(tlb[1]),
"r"(tlb[2]),
"r"(i)
);
}
static void
dump_TLBs(void)
{
int i;
for (i = 0; i < TLB_COUNT; i++) {
uint32 tlb[3];// = { 0, 0, 0 };
uint8 pid;
read_TLB(i, tlb, pid);
dprintf("TLB[%02d]: %08lx %08lx %08lx %02x\n",
i, tlb[0], tlb[1], tlb[2], pid);
}
}
status_t
arch_mmu_setup_pinned_tlb_amcc440(phys_addr_t totalRam, size_t &tableSize,
size_t &tlbSize)
{
dump_TLBs();
tlb_length tlbLength = TLB_LENGTH_16MB;
//XXX:totalRam = 4LL*1024*1024*1024;
size_t suggestedTableSize = suggested_page_table_size(totalRam);
dprintf("suggested page table size = %" B_PRIuSIZE "\n",
suggestedTableSize);
tableSize = suggestedTableSize;
// add 4MB for kernel and some more for modules...
tlbSize = tableSize + 8 * 1024 * 1024;
// round up to realistic TLB lengths, either 16MB or 256MB
// the unused space will be filled with SLAB areas
if (tlbSize < 16 * 1024 * 1024)
tlbSize = 16 * 1024 * 1024;
else {
tlbSize = 256 * 1024 * 1024;
tlbLength = TLB_LENGTH_256MB;
}
uint32 tlb[3];
uint8 pid;
int i;
// Make sure the last TLB is free, else we are in trouble
// XXX: allow using a different TLB entry?
read_TLB(TLB_COUNT - 1, tlb, pid);
if ((tlb[0] & TLB_V) != 0) {
panic("Last TLB already in use. FIXME.");
return B_ERROR;
}
// TODO: remove existing mapping from U-Boot at KERNEL_BASE !!!
// (on Sam460ex it's pci mem)
// for now we just move it to AS1 which we don't use, until calling
// the kernel.
// we could probably swap it with our own KERNEL_BASE TLB to call U-Boot
// if required, but it'd be quite ugly.
for (i = 0; i < TLB_COUNT; i++) {
read_TLB(i, tlb, pid);
//dprintf("tlb[%d][0] = %08lx\n", i, tlb[0]);
// TODO: make the test more complete and correct
if ((tlb[0] & 0xfffffc00) == KERNEL_BASE) {
tlb[0] |= 0x100; // AS1
write_TLB(i, tlb, pid);
dprintf("Moved existing translation in TLB[%d] to AS1\n", i);
}
}
// pin the last TLB
//XXX:also maybe skip the FDT + initrd + loader ?
phys_addr_t physBase = gKernelArgs.physical_memory_range[0].start;
//TODO:make sure 1st range is large enough?
i = TLB_COUNT - 1; // last one
pid = 0; // the kernel's PID
tlb[0] = (KERNEL_BASE | tlbLength << 4 | TLB_V);
tlb[1] = ((physBase & 0xfffffc00) | (physBase >> 32));
tlb[2] = (0x0000003f); // user:RWX kernel:RWX
write_TLB(i, tlb, pid);
return B_OK;
}
@@ -3,7 +3,8 @@
* All rights reserved. Distributed under the terms of the MIT License.
*/
#define FUNCTION(x) .global x; .type x,@function; x
#include <asm_defs.h>
/* status_t arch_start_kernel(struct kernel_args *kernelArgs,
addr_t kernelEntry, addr_t kernelStackTop);
@@ -46,4 +47,5 @@ FUNCTION(arch_start_kernel):
mtlr %r0
addi %r1, %r1, 32
blr
FUNCTION_END(arch_start_kernel)
@@ -45,10 +45,12 @@ static SerialConsole sSerial;
FILE *stdin, *stdout, *stderr;
/*
static void
scroll_up()
{
}
*/
// #pragma mark -
+1 -1
View File
@@ -30,7 +30,7 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList)
if (!args->platform.boot_tgz_data || !args->platform.boot_tgz_size)
return B_DEVICE_NOT_FOUND;
TRACE("Memory Disk at: %lx size: %lx\n", args->platform.boot_tgz_data,
TRACE("Memory Disk at: %p size: %lx\n", args->platform.boot_tgz_data,
args->platform.boot_tgz_size);
MemoryDisk* disk = new(nothrow) MemoryDisk(
+3 -76
View File
@@ -24,6 +24,8 @@ extern "C" {
};
extern "C" DebugUART *debug_uart_from_fdt(const void *fdt);
DebugUART* gUART;
static int32 sSerialEnabled = 0;
@@ -96,86 +98,11 @@ serial_cleanup(void)
}
static void
serial_init_fdt(const void *fdt)
{
const char *name;
const char *type;
int node;
int len;
phys_addr_t regs;
int32 clock = 0;
int32 speed = 0;
const void *prop;
if (fdt == NULL)
return;
name = fdt_get_alias(fdt, "serial");
if (name == NULL)
name = fdt_get_alias(fdt, "serial0");
if (name == NULL)
name = fdt_get_alias(fdt, "serial1");
// TODO: else use /chosen linux,stdout-path
if (name == NULL)
return;
node = fdt_path_offset(fdt, name);
//dprintf("serial: using '%s', node %d\n", name, node);
if (node < 0)
return;
type = (const char *)fdt_getprop(fdt, node, "device_type", &len);
//dprintf("serial: type: '%s'\n", type);
if (type == NULL || strcmp(type, "serial"))
return;
// determine the MMIO address
// TODO: ppc640 use 64bit addressing, but U-Boot seems to map it below 4G,
// and the FDT is not very clear. libfdt is also getting 64bit addr support.
// so FIXME someday.
prop = fdt_getprop(fdt, node, "virtual-reg", &len);
if (prop && len == 4) {
regs = fdt32_to_cpu(*(uint32_t *)prop);
//dprintf("serial: virtual-reg 0x%08llx\n", (int64)regs);
} else {
prop = fdt_getprop(fdt, node, "reg", &len);
if (prop && len >= 4) {
regs = fdt32_to_cpu(*(uint32_t *)prop);
//dprintf("serial: reg 0x%08llx\n", (int64)regs);
} else
return;
}
// get the UART clock rate
prop = fdt_getprop(fdt, node, "clock-frequency", &len);
if (prop && len == 4) {
clock = fdt32_to_cpu(*(uint32_t *)prop);
//dprintf("serial: clock %ld\n", clock);
}
// get current speed (XXX: not yet passed over)
prop = fdt_getprop(fdt, node, "current-speed", &len);
if (prop && len == 4) {
speed = fdt32_to_cpu(*(uint32_t *)prop);
//dprintf("serial: speed %ld\n", speed);
}
if (fdt_node_check_compatible(fdt, node, "ns16550a") == 1
|| fdt_node_check_compatible(fdt, node, "ns16550") == 1) {
gUART = arch_get_uart_8250(regs, clock);
//dprintf("serial: using 8250\n");
return;
}
}
extern "C" void
serial_init(const void *fdt)
{
// first try with hints from the FDT
serial_init_fdt(fdt);
gUART = debug_uart_from_fdt(fdt);
#ifdef BOARD_UART_DEBUG
// fallback to hardcoded board UART
+11 -1
View File
@@ -18,6 +18,7 @@
#include <boot/stage2.h>
#include <arch/cpu.h>
#include <platform_arch.h>
#include <platform/openfirmware/openfirmware.h>
#include <string.h>
@@ -104,6 +105,12 @@ platform_start_kernel(void)
addr_t stackTop
= gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size;
if (gFDT) {
// clone the Flattened Device Tree blob
gKernelArgs.platform_args.fdt = kernel_args_malloc(fdt_totalsize(gFDT));
memcpy(gKernelArgs.platform_args.fdt, gFDT, fdt_totalsize(gFDT));
}
// smp_init_other_cpus();
serial_cleanup();
mmu_init_for_kernel();
@@ -114,7 +121,7 @@ platform_start_kernel(void)
status_t error = arch_start_kernel(&gKernelArgs, kernelEntry,
stackTop);
panic("kernel returned!\n");
panic("kernel returned %lx!\n", error);
}
@@ -190,6 +197,9 @@ start_raw(int argc, const char **argv)
serial_init(gFDT);
console_init();
// initialize the OpenFirmware wrapper
of_init(NULL);
cpu_init();
if (args.platform.fdt_data) {
+3 -2
View File
@@ -10,10 +10,8 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) paging 32bit ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
KernelMergeObject kernel_arch_arm.o :
# arch_atomic.c
arch_commpage.cpp
arch_cpu.cpp
# arch_cpu_asm.S
arch_debug_console.cpp
arch_debug.cpp
arch_elf.cpp
@@ -33,6 +31,9 @@ KernelMergeObject kernel_arch_arm.o :
arch_uart_8250.cpp
arch_uart_pl011.cpp
arch_atomic64.cpp
arch_atomic32.cpp
# paging
arm_physical_page_mapper.cpp
arm_physical_page_mapper_large_memory.cpp
+34 -26
View File
@@ -82,21 +82,32 @@ FUNCTION(arm_context_switch):
bx lr
FUNCTION_END(arm_context_switch)
/* addr_t arm_get_fsr(void); */
FUNCTION(arm_get_fsr):
mrc p15, 0, r0, c5, c0, 0 @ get FSR
bx lr
FUNCTION_END(arm_get_fsr)
/* addr_t arm_get_far(void); */
FUNCTION(arm_get_far):
mrc p15, 0, r0, c6, c0, 0 @ get FAR
bx lr
FUNCTION_END(arm_get_far)
/* addr_t arm_get_fp(void); */
FUNCTION(arm_get_fp):
mov r0, fp @ get framepointer
bx lr
FUNCTION_END(arm_get_fp);
/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
FUNCTION(arch_cpu_user_memcpy):
stmfd sp!, { r4-r6 }
stmfd sp!, { r4-r6, lr }
ldr r6, [r3]
ldr r4, =.L_user_memcpy_error
str r4, [r3] /* set fault handler */
@@ -106,33 +117,35 @@ FUNCTION(arch_cpu_user_memcpy):
str r5, [r0]
add r1, #4
add r0, #4
sub r4, #1
subs r4, #1
bne 1b
ands r4, r2, #3 /* size % 4 */
beq 3f
2:
and r4, r2, #3 /* size % 4 */
ldrb r5, [r1]
strb r5, [r0]
add r1, #1
add r0, #1
sub r4, #1
subs r4, #1
bne 2b
3:
str r6, [r3] /* restore fault handler */
mov r0, #0
ldmfd sp!, { r4-r6 }
bx lr
ldmfd sp!, { r4-r6, pc }
.L_user_memcpy_error:
str r6, [r3] /* restore fault handler */
mov r0, #-1
ldmfd sp!, { r4-r6 }
bx lr
ldmfd sp!, { r4-r6, pc }
FUNCTION_END(arch_cpu_user_memcpy)
/* status_t arch_cpu_user_memset(void *to, char c, size_t count, addr_t *faultHandler) */
FUNCTION(arch_cpu_user_memset):
stmfd sp!, { r4-r5 }
stmfd sp!, { r4-r5, lr }
ldr r5, [r3]
ldr r4, =.L_user_memset_error
str r4, [r3]
@@ -146,33 +159,31 @@ FUNCTION(arch_cpu_user_memset):
1:
str r1, [r0]
add r0, r0, #4
sub r4, r4, #1
subs r4, r4, #1
bne 1b
and r4, r2, #3 /* count % 4 */
2:
strb r1, [r0]
add r0, r0, #1
sub r4, r4, #1
subs r4, r4, #1
bne 2b
mov r0, #0
str r5, [r3]
ldmfd sp!, { r4-r5 }
bx lr
ldmfd sp!, { r4-r5, pc }
.L_user_memset_error:
mov r0, #-1
str r5, [r3]
ldmfd sp!, { r4-r5 }
bx lr
ldmfd sp!, { r4-r5, pc }
FUNCTION_END(arch_cpu_user_memset)
/* ssize_t arch_cpu_user_strlcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
FUNCTION(arch_cpu_user_strlcpy):
stmfd sp!, { r4-r6 }
stmfd sp!, { r4-r6, lr }
ldr r5, [r3]
ldr r4, =.L_user_strlcpy_error
str r4, [r3]
@@ -181,7 +192,7 @@ FUNCTION(arch_cpu_user_strlcpy):
ldrb r4, [r1, r6]
strb r4, [r0, r6]
add r6, r6, #1
and r4, #0xff /* done yet? */
cmp r4, #0
beq 2f
cmp r6, r2 /* reached max length? */
blt 1b
@@ -189,18 +200,16 @@ FUNCTION(arch_cpu_user_strlcpy):
mov r4, #0
strb r4, [r0, r6]
mov r0, r4 /* return B_OK */
mov r0, r6 /* return length */
str r5, [r3] /* restore fault handler */
ldmfd sp!, { r4-r6 }
bx lr
ldmfd sp!, { r4-r6, pc }
.L_user_strlcpy_error:
mov r0, #-1
str r5, [r3]
ldmfd sp!, { r4-r6 }
bx lr
ldmfd sp!, { r4-r6, pc }
FUNCTION_END(arch_cpu_user_strlcpy)
@@ -236,12 +245,11 @@ FUNCTION(arch_debug_call_with_fault_handler):
blx r2
// regular return
ldmfd sp!, { r4, lr }
bx lr
ldmfd sp!, { r4, pc }
// fault -- return via longjmp(jumpBuffer, 1)
1:
mov r0, r4
mov r0, r1
mov r1, #1
bl longjmp
FUNCTION_END(arch_debug_call_with_fault_handler)
@@ -0,0 +1,177 @@
/*
* Copyright 2013 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema, ithamar@upgrade-android.com
*/
#include <KernelExport.h>
#include <kernel.h>
#include <user_atomic.h>
#include <util/AutoLock.h>
#ifdef ATOMIC_FUNCS_ARE_SYSCALLS
/*
* NOTE: These functions are _intentionally_ not using spinlocks, unlike
* the 64 bit versions. The reason for this is that they are used by the
* spinlock code itself, and therefore would deadlock.
*
* Since these are only really needed for ARMv5, which is not SMP anyway,
* this is an acceptable compromise.
*/
int32
atomic_set(vint32 *value, int32 newValue)
{
InterruptsLocker locker;
int32 oldValue = *value;
*value = newValue;
return oldValue;
}
int32
atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst)
{
InterruptsLocker locker;
int32 oldValue = *value;
if (oldValue == testAgainst)
*value = newValue;
return oldValue;
}
int32
atomic_add(vint32 *value, int32 addValue)
{
InterruptsLocker locker;
int32 oldValue = *value;
*value += addValue;
return oldValue;
}
int32
atomic_and(vint32 *value, int32 andValue)
{
InterruptsLocker locker;
int32 oldValue = *value;
*value &= andValue;
return oldValue;
}
int32
atomic_or(vint32 *value, int32 orValue)
{
InterruptsLocker locker;
int32 oldValue = *value;
*value |= orValue;
return oldValue;
}
int32
atomic_get(vint32 *value)
{
InterruptsLocker locker;
int32 oldValue = *value;
return oldValue;
}
int32
_user_atomic_set(vint32 *value, int32 newValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
int32 oldValue = atomic_set(value, newValue);
unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int32
_user_atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
int32 oldValue = atomic_test_and_set(value, newValue, testAgainst);
unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int32
_user_atomic_add(vint32 *value, int32 addValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
int32 oldValue = atomic_add(value, addValue);
unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int32
_user_atomic_and(vint32 *value, int32 andValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
int32 oldValue = atomic_and(value, andValue);
unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int32
_user_atomic_or(vint32 *value, int32 orValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
int32 oldValue = atomic_or(value, orValue);
unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int32
_user_atomic_get(vint32 *value)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
int32 oldValue = atomic_get(value);
unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
#endif /* ATOMIC_FUNCS_ARE_SYSCALLS */
@@ -0,0 +1,192 @@
/*
* Copyright 2013 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema, ithamar@upgrade-android.com
*/
#include <KernelExport.h>
#include <kernel.h>
#include <user_atomic.h>
#include <util/AutoLock.h>
#ifdef ATOMIC64_FUNCS_ARE_SYSCALLS
/*
* NOTE: Unlike their 32-bit counterparts, these functions can use
* spinlocks safely currently, as no atomic 64-bit operations are
* done in the spinlock code. If this ever changes, this code will
* have to change.
*
* This code is here for ARMv6, which cannot do proper 64-bit atomic
* operations. Anything newer is capable, and does therefore not
* depend on this code.
*/
static spinlock atomic_lock = B_SPINLOCK_INITIALIZER;
int64
atomic_set64(vint64 *value, int64 newValue)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
*value = newValue;
return oldValue;
}
int64
atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
if (oldValue == testAgainst)
*value = newValue;
return oldValue;
}
int64
atomic_add64(vint64 *value, int64 addValue)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
*value += addValue;
return oldValue;
}
int64
atomic_and64(vint64 *value, int64 andValue)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
*value &= andValue;
return oldValue;
}
int64
atomic_or64(vint64 *value, int64 orValue)
{
SpinLocker locker(&atomic_lock);
int64 oldValue = *value;
*value |= orValue;
return oldValue;
}
int64
atomic_get64(vint64 *value)
{
SpinLocker locker(&atomic_lock);
return *value;
}
int64
_user_atomic_set64(vint64 *value, int64 newValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_set64(value, newValue);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int64
_user_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_test_and_set64(value, newValue, testAgainst);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int64
_user_atomic_add64(vint64 *value, int64 addValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_add64(value, addValue);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int64
_user_atomic_and64(vint64 *value, int64 andValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_and64(value, andValue);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int64
_user_atomic_or64(vint64 *value, int64 orValue)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_or64(value, orValue);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
int64
_user_atomic_get64(vint64 *value)
{
if (IS_USER_ADDRESS(value)
&& lock_memory((void *)value, sizeof(int64), B_READ_DEVICE) == B_OK) {
int64 oldValue = atomic_get64(value);
unlock_memory((void *)value, sizeof(int64), B_READ_DEVICE);
return oldValue;
}
access_violation:
// XXX kill application
return -1;
}
#endif /* ATOMIC64_FUNCS_ARE_SYSCALLS */
+328 -108
View File
@@ -6,6 +6,8 @@
* Axel Dörfler <axeld@pinc-software.de>
* Ingo Weinhold <bonefish@cs.tu-berlin.de>
* François Revol <revol@free.fr>
* Ithamar R. Adema <ithamar@upgrade-android.com>
*
*/
@@ -13,25 +15,22 @@
#include <arch_cpu.h>
#include <debug.h>
#include <debug_heap.h>
#include <elf.h>
#include <kernel.h>
#include <kimage.h>
#include <thread.h>
struct stack_frame {
struct stack_frame *previous;
addr_t return_address;
};
#include <vm/vm_types.h>
#include <vm/VMAddressSpace.h>
#include <vm/VMArea.h>
#define NUM_PREVIOUS_LOCATIONS 32
extern struct iframe_stack gBootFrameStack;
/*
static bool
already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 fp)
{
int32 last = *_last;
int32 num = *_num;
@@ -39,13 +38,13 @@ already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
for (i = 0; i < num; i++) {
if (visited[(NUM_PREVIOUS_LOCATIONS + last - i)
% NUM_PREVIOUS_LOCATIONS] == framePointer) {
% NUM_PREVIOUS_LOCATIONS] == fp) {
return true;
}
}
*_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
visited[last] = framePointer;
visited[last] = fp;
if (num < NUM_PREVIOUS_LOCATIONS)
*_num = num + 1;
@@ -54,99 +53,327 @@ already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
}
static inline stack_frame *
get_current_stack_frame()
static status_t
get_next_frame(addr_t fp, addr_t *next, addr_t *ip)
{
stack_frame *frame;
asm volatile("move.l %%fp,%0" : "=r"(frame));
return frame;
if (fp != 0) {
addr_t _fp = *(((addr_t*)fp) -3);
addr_t _sp = *(((addr_t*)fp) -2);
addr_t _lr = *(((addr_t*)fp) -1);
addr_t _pc = *(((addr_t*)fp) -0);
*ip = (_fp != 0) ? _lr : _pc;
*next = _fp;
return B_OK;
}
return B_BAD_VALUE;
}
static status_t
get_next_frame(addr_t framePointer, addr_t *next, addr_t *ip)
lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
const char** _symbolName, const char** _imageName, bool* _exactMatch)
{
Thread *thread = thread_get_current_thread();
addr_t oldFaultHandler = thread->fault_handler;
status_t status = B_ENTRY_NOT_FOUND;
// set fault handler, so that we can safely access user stacks
if (thread) {
if (m68k_set_fault_handler(&thread->fault_handler, (addr_t)&&error))
goto error;
if (IS_KERNEL_ADDRESS(address)) {
// a kernel symbol
status = elf_debug_lookup_symbol_address(address, _baseAddress,
_symbolName, _imageName, _exactMatch);
} else if (thread != NULL && thread->team != NULL) {
// try a lookup using the userland runtime loader structures
status = elf_debug_lookup_user_symbol_address(thread->team, address,
_baseAddress, _symbolName, _imageName, _exactMatch);
if (status != B_OK) {
// try to locate the image in the images loaded into user space
status = image_debug_lookup_user_symbol_address(thread->team,
address, _baseAddress, _symbolName, _imageName, _exactMatch);
}
}
*ip = ((struct stack_frame *)framePointer)->return_address;
*next = (addr_t)((struct stack_frame *)framePointer)->previous;
if (thread)
thread->fault_handler = oldFaultHandler;
return B_OK;
error:
thread->fault_handler = oldFaultHandler;
return B_BAD_ADDRESS;
return status;
}
static void
print_stack_frame(Thread *thread, addr_t ip, addr_t framePointer,
addr_t nextFramePointer)
set_debug_argument_variable(int32 index, uint64 value)
{
addr_t diff = nextFramePointer - framePointer;
// kernel space/user space switch
if (diff & 0x80000000)
diff = 0;
// lookup symbol
const char *symbol, *image;
addr_t baseAddress;
bool exactMatch;
status_t status = elf_debug_lookup_symbol_address(ip, &baseAddress, &symbol,
&image, &exactMatch);
if (status != B_OK && !IS_KERNEL_ADDRESS(ip) && thread) {
// try to locate the image in the images loaded into user space
status = image_debug_lookup_user_symbol_address(thread->team, ip,
&baseAddress, &symbol, &image, &exactMatch);
}
if (status == B_OK) {
if (symbol != NULL) {
kprintf("%08lx (+%4ld) %08lx <%s>:%s + 0x%04lx%s\n", framePointer,
diff, ip, image, symbol, ip - baseAddress,
(exactMatch ? "" : " (nearest)"));
} else {
kprintf("%08lx (+%4ld) %08lx <%s@%p>:unknown + 0x%04lx\n",
framePointer, diff, ip, image, (void *)baseAddress,
ip - baseAddress);
}
} else
kprintf("%08lx (+%4ld) %08lx\n", framePointer, diff, ip);
char name[8];
snprintf(name, sizeof(name), "_arg%ld", index);
set_debug_variable(name, value);
}
template<typename Type>
static Type
read_function_argument_value(void* argument, bool& _valueKnown)
{
Type value;
if (debug_memcpy(B_CURRENT_TEAM, &value, argument, sizeof(Type)) == B_OK) {
_valueKnown = true;
return value;
}
_valueKnown = false;
return 0;
}
static status_t
print_demangled_call(const char* image, const char* symbol, addr_t args,
bool noObjectMethod, bool addDebugVariables)
{
static const size_t kBufferSize = 256;
char* buffer = (char*)debug_malloc(kBufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
bool isObjectMethod;
const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
&isObjectMethod);
if (name == NULL) {
debug_free(buffer);
return B_ERROR;
}
uint32* arg = (uint32*)args;
if (noObjectMethod)
isObjectMethod = false;
if (isObjectMethod) {
const char* lastName = strrchr(name, ':') - 1;
int namespaceLength = lastName - name;
uint32 argValue = 0;
if (debug_memcpy(B_CURRENT_TEAM, &argValue, arg, 4) == B_OK) {
kprintf("<%s> %.*s<\33[32m%#" B_PRIx32 "\33[0m>%s", image,
namespaceLength, name, argValue, lastName);
} else
kprintf("<%s> %.*s<???>%s", image, namespaceLength, name, lastName);
if (addDebugVariables)
set_debug_variable("_this", argValue);
arg++;
} else
kprintf("<%s> %s", image, name);
kprintf("(");
size_t length;
int32 type, i = 0;
uint32 cookie = 0;
while (debug_get_next_demangled_argument(&cookie, symbol, buffer,
kBufferSize, &type, &length) == B_OK) {
if (i++ > 0)
kprintf(", ");
// retrieve value and type identifier
uint64 value;
bool valueKnown = false;
switch (type) {
case B_INT64_TYPE:
value = read_function_argument_value<int64>(arg, valueKnown);
if (valueKnown)
kprintf("int64: \33[34m%Ld\33[0m", value);
break;
case B_INT32_TYPE:
value = read_function_argument_value<int32>(arg, valueKnown);
if (valueKnown)
kprintf("int32: \33[34m%ld\33[0m", (int32)value);
break;
case B_INT16_TYPE:
value = read_function_argument_value<int16>(arg, valueKnown);
if (valueKnown)
kprintf("int16: \33[34m%d\33[0m", (int16)value);
break;
case B_INT8_TYPE:
value = read_function_argument_value<int8>(arg, valueKnown);
if (valueKnown)
kprintf("int8: \33[34m%d\33[0m", (int8)value);
break;
case B_UINT64_TYPE:
value = read_function_argument_value<uint64>(arg, valueKnown);
if (valueKnown) {
kprintf("uint64: \33[34m%#Lx\33[0m", value);
if (value < 0x100000)
kprintf(" (\33[34m%Lu\33[0m)", value);
}
break;
case B_UINT32_TYPE:
value = read_function_argument_value<uint32>(arg, valueKnown);
if (valueKnown) {
kprintf("uint32: \33[34m%#lx\33[0m", (uint32)value);
if (value < 0x100000)
kprintf(" (\33[34m%lu\33[0m)", (uint32)value);
}
break;
case B_UINT16_TYPE:
value = read_function_argument_value<uint16>(arg, valueKnown);
if (valueKnown) {
kprintf("uint16: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
(uint16)value, (uint16)value);
}
break;
case B_UINT8_TYPE:
value = read_function_argument_value<uint8>(arg, valueKnown);
if (valueKnown) {
kprintf("uint8: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
(uint8)value, (uint8)value);
}
break;
case B_BOOL_TYPE:
value = read_function_argument_value<uint8>(arg, valueKnown);
if (valueKnown)
kprintf("\33[34m%s\33[0m", value ? "true" : "false");
break;
default:
if (buffer[0])
kprintf("%s: ", buffer);
if (length == 4) {
value = read_function_argument_value<uint32>(arg,
valueKnown);
if (valueKnown) {
if (value == 0
&& (type == B_POINTER_TYPE || type == B_REF_TYPE))
kprintf("NULL");
else
kprintf("\33[34m%#lx\33[0m", (uint32)value);
}
break;
}
if (length == 8) {
value = read_function_argument_value<uint64>(arg,
valueKnown);
} else
value = (uint64)arg;
if (valueKnown)
kprintf("\33[34m%#Lx\33[0m", value);
break;
}
if (!valueKnown)
kprintf("???");
if (valueKnown && type == B_STRING_TYPE) {
if (value == 0)
kprintf(" \33[31m\"<NULL>\"\33[0m");
else if (debug_strlcpy(B_CURRENT_TEAM, buffer, (char*)(addr_t)value,
kBufferSize) < B_OK) {
kprintf(" \33[31m\"<???>\"\33[0m");
} else
kprintf(" \33[36m\"%s\"\33[0m", buffer);
}
if (addDebugVariables)
set_debug_argument_variable(i, value);
arg = (uint32*)((uint8*)arg + length);
}
debug_free(buffer);
kprintf(")");
return B_OK;
}
static void
print_stack_frame(Thread *thread, addr_t ip, addr_t fp, addr_t next,
int32 callIndex, bool demangle)
{
const char* symbol;
const char* image;
addr_t baseAddress;
bool exactMatch;
status_t status;
addr_t diff;
diff = next - fp;
// MSB set = kernel space/user space switch
if (diff & ~((addr_t)-1 >> 1))
diff = 0;
status = lookup_symbol(thread, ip, &baseAddress, &symbol, &image,
&exactMatch);
kprintf("%2" B_PRId32 " %0*lx (+%4ld) %0*lx ", callIndex,
B_PRINTF_POINTER_WIDTH, fp, diff, B_PRINTF_POINTER_WIDTH, ip);
if (status == B_OK) {
if (exactMatch && demangle) {
status = print_demangled_call(image, symbol,
next, false, false);
}
if (!exactMatch || !demangle || status != B_OK) {
if (symbol != NULL) {
kprintf("<%s> %s%s", image, symbol,
exactMatch ? "" : " (nearest)");
} else
kprintf("<%s@%p> <unknown>", image, (void*)baseAddress);
}
kprintf(" + %#04lx\n", ip - baseAddress);
} else {
VMArea *area = NULL;
if (thread != NULL && thread->team != NULL
&& thread->team->address_space != NULL) {
area = thread->team->address_space->LookupArea(ip);
}
if (area != NULL) {
kprintf("%" B_PRId32 ":%s@%p + %#lx\n", area->id, area->name,
(void*)area->Base(), ip - area->Base());
} else
kprintf("\n");
}
}
static int
stack_trace(int argc, char **argv)
{
uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
struct iframe_stack *frameStack;
Thread *thread;
addr_t framePointer;
int32 i, num = 0, last = 0;
if (argc < 2) {
thread = thread_get_current_thread();
framePointer = (addr_t)get_current_stack_frame();
} else {
kprintf("Stack traces of other threads not supported yet!\n");
return 0;
static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
"Prints a stack trace for the current, respectively the specified\n"
"thread.\n"
" -d - Disables the demangling of the symbols.\n"
" <thread id> - The ID of the thread for which to print the stack\n"
" trace.\n";
bool demangle = true;
int32 threadIndex = 1;
if (argc > 1 && !strcmp(argv[1], "-d")) {
demangle = false;
threadIndex++;
}
if (argc > threadIndex + 1
|| (argc == 2 && strcmp(argv[1], "--help") == 0)) {
kprintf(usage, argv[0]);
return 0;
}
addr_t previousLocations[NUM_PREVIOUS_LOCATIONS];
Thread* thread = NULL;
phys_addr_t oldPageDirectory = 0;
addr_t fp = arm_get_fp();
int32 num = 0, last = 0;
struct iframe_stack *frameStack;
// We don't have a thread pointer early in the boot process
if (thread != NULL)
frameStack = &thread->arch_info.iframes;
else
frameStack = &gBootFrameStack;
int32 i;
for (i = 0; i < frameStack->index; i++) {
kprintf("iframe %p (end = %p)\n",
frameStack->frames[i], frameStack->frames[i] + 1);
@@ -168,11 +395,11 @@ return 0;
kprintf("frame caller <image>:function + offset\n");
for (;;) {
for (int32 callIndex = 0;; callIndex++) {
// see if the frame pointer matches the iframe
struct iframe *frame = NULL;
for (i = 0; i < frameStack->index; i++) {
if (framePointer == (addr_t)frameStack->frames[i]) {
if (fp == (addr_t)frameStack->frames[i]) {
// it's an iframe
frame = frameStack->frames[i];
break;
@@ -181,49 +408,43 @@ return 0;
if (frame) {
kprintf("iframe at %p\n", frame);
kprintf(" d0 0x%08lx d1 0x%08lx d2 0x%08lx d3 0x%08lx\n",
frame->d[0], frame->d[1], frame->d[2], frame->d[3]);
kprintf(" d4 0x%08lx d5 0x%08lx d6 0x%08lx d7 0x%08lx\n",
frame->d[4], frame->d[5], frame->d[6], frame->d[7]);
kprintf(" a0 0x%08lx a1 0x%08lx a2 0x%08lx a3 0x%08lx\n",
frame->a[0], frame->a[1], frame->a[2], frame->a[3]);
kprintf(" a4 0x%08lx a5 0x%08lx a6 0x%08lx a7 0x%08lx (sp)\n",
#warning M68K: a7 in iframe ??
frame->a[4], frame->a[5], frame->a[6], -1L);
kprintf(" pc 0x%08lx sr 0x%04x\n",
frame->cpu.pc, frame->cpu.sr);
#warning M68K: missing regs
kprintf(" r0 0x%08lx r1 0x%08lx r2 0x%08lx r3 0x%08lx\n",
frame->r0, frame->r1, frame->r2, frame->r3);
kprintf(" r4 0x%08lx r5 0x%08lx r6 0x%08lx r7 0x%08lx\n",
frame->r4, frame->r5, frame->r6, frame->r7);
kprintf(" r8 0x%08lx r9 0x%08lx r10 0x%08lx r11 0x%08lx\n",
frame->r8, frame->r9, frame->r10, frame->r11);
kprintf(" r12 0x%08lx sp 0x%08lx lr 0x%08lx pc 0x%08lx\n",
frame->r12, frame->svc_sp, frame->svc_lr, frame->pc);
print_stack_frame(thread, frame->cpu.pc, framePointer, frame->a[6]);
framePointer = frame->a[6];
fp = frame->svc_sp;
print_stack_frame(thread, frame->pc, frame->svc_sp, frame->svc_lr, callIndex, demangle);
} else {
addr_t ip, nextFramePointer;
addr_t ip, next;
if (get_next_frame(framePointer, &nextFramePointer, &ip) != B_OK) {
kprintf("%08lx -- read fault\n", framePointer);
if (get_next_frame(fp, &next, &ip) != B_OK) {
kprintf("%08lx -- read fault\n", fp);
break;
}
if (ip == 0 || framePointer == 0)
if (ip == 0 || fp == 0)
break;
print_stack_frame(thread, ip, framePointer, nextFramePointer);
framePointer = nextFramePointer;
print_stack_frame(thread, ip, fp, next, callIndex, demangle);
fp = next;
}
if (already_visited(previousLocations, &last, &num, framePointer)) {
kprintf("circular stack frame: %p!\n", (void *)framePointer);
if (already_visited(previousLocations, &last, &num, fp)) {
kprintf("circular stack frame: %p!\n", (void *)fp);
break;
}
if (framePointer == 0)
if (fp == 0)
break;
}
return 0;
}
*/
// #pragma mark -
@@ -245,6 +466,7 @@ arch_debug_contains_call(Thread *thread, const char *symbol,
void
arch_debug_stack_trace(void)
{
stack_trace(0, NULL);
}
@@ -261,8 +483,7 @@ int32
arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
int32 skipIframes, int32 skipFrames, uint32 flags)
{
#warning ARM:IMPLEMENT
// TODO: Implement!
return 0;
}
@@ -302,10 +523,9 @@ arch_get_debug_variable(const char* variableName, uint64* value)
status_t
arch_debug_init(kernel_args *args)
{
// add_debugger_command("where", &stack_trace, "Same as \"sc\"");
// add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
// add_debugger_command("sc", &stack_trace, "Stack crawl for current thread");
#warning ARM:IMPLEMENT
add_debugger_command("where", &stack_trace, "Same as \"sc\"");
add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
add_debugger_command("sc", &stack_trace, "Stack crawl for current thread");
return B_NO_ERROR;
}
+39 -3
View File
@@ -31,7 +31,7 @@
#include <string.h>
//#define TRACE_ARCH_INT
#define TRACE_ARCH_INT
#ifdef TRACE_ARCH_INT
# define TRACE(x) dprintf x
#else
@@ -108,9 +108,9 @@ print_iframe(const char *event, struct iframe *frame)
frame->r0, frame->r1, frame->r2, frame->r3,
frame->r4, frame->r5, frame->r6, frame->r7);
dprintf("R08=%08lx R09=%08lx R10=%08lx R11=%08lx\n"
"R12=%08lx R13=%08lx R14=%08lx CPSR=%08lx\n",
"R12=%08lx SP=%08lx LR=%08lx PC=%08lx CPSR=%08lx\n",
frame->r8, frame->r9, frame->r10, frame->r11,
frame->r12, frame->usr_sp, frame->usr_lr, frame->spsr);
frame->r12, frame->svc_sp, frame->svc_lr, frame->pc, frame->spsr);
}
@@ -188,10 +188,36 @@ arch_int_init_post_device_manager(struct kernel_args *args)
}
// Little helper class for handling the
// iframe stack as used by KDL.
class IFrameScope {
public:
IFrameScope(struct iframe *iframe) {
fThread = thread_get_current_thread();
if (fThread)
arm_push_iframe(&fThread->arch_info.iframes, iframe);
else
arm_push_iframe(&gBootFrameStack, iframe);
}
virtual ~IFrameScope() {
// pop iframe
if (fThread)
arm_pop_iframe(&fThread->arch_info.iframes);
else
arm_pop_iframe(&gBootFrameStack);
}
private:
Thread* fThread;
};
extern "C" void
arch_arm_undefined(struct iframe *iframe)
{
print_iframe("Undefined Instruction", iframe);
IFrameScope scope(iframe); // push/pop iframe
panic("not handled!");
}
@@ -200,6 +226,7 @@ extern "C" void
arch_arm_syscall(struct iframe *iframe)
{
print_iframe("Software interrupt", iframe);
IFrameScope scope(iframe); // push/pop iframe
}
@@ -214,8 +241,11 @@ arch_arm_data_abort(struct iframe *frame)
#ifdef TRACE_ARCH_INT
print_iframe("Data Abort", frame);
dprintf("FAR: %08lx, thread: %s\n", far, thread->name);
#endif
IFrameScope scope(frame);
if (debug_debugger_running()) {
// If this CPU or this thread has a fault handler, we're allowed to be
// here.
@@ -291,6 +321,8 @@ extern "C" void
arch_arm_prefetch_abort(struct iframe *iframe)
{
print_iframe("Prefetch Abort", iframe);
IFrameScope scope(iframe);
panic("not handled!");
}
@@ -298,6 +330,8 @@ arch_arm_prefetch_abort(struct iframe *iframe)
extern "C" void
arch_arm_irq(struct iframe *iframe)
{
IFrameScope scope(iframe);
for (int i=0; i < 32; i++) {
if (sPxaInterruptBase[PXA_ICIP] & (1 << i))
int_io_interrupt_handler(i, true);
@@ -308,6 +342,8 @@ arch_arm_irq(struct iframe *iframe)
extern "C" void
arch_arm_fiq(struct iframe *iframe)
{
IFrameScope scope(iframe);
for (int i=0; i < 32; i++) {
if (sPxaInterruptBase[PXA_ICIP] & (1 << i)) {
dprintf("arch_arm_fiq: help me, FIQ %d was triggered but no "
@@ -42,6 +42,23 @@ static struct arch_thread sInitialState;
Thread *gCurrentThread;
void
arm_push_iframe(struct iframe_stack *stack, struct iframe *frame)
{
ASSERT(stack->index < IFRAME_TRACE_DEPTH);
stack->frames[stack->index++] = frame;
}
void
arm_pop_iframe(struct iframe_stack *stack)
{
ASSERT(stack->index > 0);
stack->index--;
}
status_t
arch_thread_init(struct kernel_args *args)
{
+6 -2
View File
@@ -29,7 +29,7 @@
#define PXA_TIMERS_PHYS_BASE 0x40A00000
#define PXA_TIMERS_SIZE 0x000000C0
#define PXA_TIMERS_SIZE B_PAGE_SIZE
#define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */
#define PXA_OSSR 0x05
@@ -48,7 +48,7 @@
#define US2S(bt) ((bt) / 1000000ULL)
#define US2MS(bt) ((bt) / 1000ULL)
static area_id sPxaTimersArea = B_ERROR;
static area_id sPxaTimersArea = -1;
static uint32 *sPxaTimersBase = NULL;
static bigtime_t sSystemTime = 0;
@@ -107,6 +107,7 @@ arch_timer_clear_hardware_timer()
int
arch_init_timer(kernel_args *args)
{
TRACE(("%s\n", __func__));
sPxaTimersArea = map_physical_memory("pxa_timers", PXA_TIMERS_PHYS_BASE,
PXA_TIMERS_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaTimersBase);
@@ -126,6 +127,9 @@ arch_init_timer(kernel_args *args)
bigtime_t
system_time(void)
{
if (sPxaTimersArea < 0)
return 0;
return (sPxaTimersBase != NULL) ?
sSystemTime + sPxaTimersBase[PXA_OSCR5] :
0ULL;
+3
View File
@@ -14,6 +14,7 @@ KernelMergeObject kernel_arch_ppc.o :
arch_debug.cpp
arch_elf.cpp
arch_exceptions.S
arch_exceptions_44x.S
arch_int.cpp
arch_mmu.cpp
arch_platform.cpp
@@ -26,6 +27,8 @@ KernelMergeObject kernel_arch_ppc.o :
arch_vm.cpp
arch_vm_translation_map.cpp
arch_asm.S
debug_uart_8250.cpp
arch_uart_8250.cpp
generic_vm_physical_page_mapper.cpp
generic_vm_physical_page_ops.cpp
+1 -2
View File
@@ -5,8 +5,7 @@
* Copyright 2003, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#define FUNCTION(x) .global x; .type x,@function; x
#define LOCAL_FUNCTION(x) .type x,@function; x
#include <asm_defs.h>
/* General exception handling concept:
@@ -0,0 +1,441 @@
/*
* Copyright 2013, François Revol <revol@free.fr>.
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2003, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include <asm_defs.h>
/* General exception handling concept:
The PPC architecture specifies entry point offsets for the various
exceptions in the first two physical pages. We put a short piece of code
(VEC_ENTRY()) into each exception vector. It calls exception_vector_common,
which is defined in the unused space at the beginning of the first physical
page. It re-enables address translation and calls ppc_exception_tail which
lies in the kernel. It dumps an iframe and invokes ppc_exception_entry()
(arch_int.cpp), which handles the exception and returns eventually.
The registers are restored from the iframe and we return from the
interrupt.
algorithm overview:
* VEC_ENTRY
* ppc_44x_exception_vector_common
* ppc_44x_exception_tail
- dump iframe
- ppc_exception_entry()
- restore registers and return from interrupt
Here we use the following SPRG registers, which are at the disposal of the
operating system:
* SPRG0: Physical address pointer to a struct cpu_exception_context
for the current CPU. The structure contains helpful pointers
as well as some scratch memory for temporarily saving registers.
* SPRG1: Scratch.
struct cpu_exception_context (defined in arch_int.h):
offset 0: virtual address of the exception handler routine in the kernel
offset 4: virtual address of the exception context
offset 8: kernel stack for the current thread
offset 12: start of scratch memory for saving registers etc.
algorithm in detail:
* VEC_ENTRY
- save r1 in SPRG1 and load cpu_exception_context into r1
- save r0, save LR in r0
* ppc_44x_exception_vector_common
- params:
. r0: old LR
. r1: exception context (physical address)
. SPRG1: original r1
- save r0-3
- load virtual exception context address to r1
- turn on BAT for exception vector code
- turn on address translation
- get exception vector offset from LR
* ppc_44x_exception_tail
- params:
. r1: exception context (virtual address)
. r3: exception vector offset
. SPRG1: original r1
- turn off BAT
- get kernel stack pointer
- dump iframe
- ppc_exception_entry()
- restore registers and return from interrupt
*/
/* exception vector definitions */
/* code in each exception vector */
#define VEC_ENTRY() \
mtsprg1 %r1 ; /* temporarily save r1 in SPRG1 */ \
mfsprg0 %r1 ; /* ppc_cpu_exception_context* -> r1 */ \
stw %r0, 16(%r1) ; /* save r0 */ \
mflr %r0 ; /* save LR in r0 */ \
bl ppc_44x_exception_vector_common ; /* continue with the common part */
/* defines an exception vector */
#define DEFINE_VECTOR(offset, name) \
.skip offset - (. - __44x_irqvec_start); \
FUNCTION(ppc_44x_##name): \
VEC_ENTRY()
.global __44x_irqvec_start
__44x_irqvec_start:
.long 0
/* Called by the exception vector code.
* LR: Points to the end of the exception vector code we're coming from.
* r0: original LR
* r1: ppc_cpu_exception_context* (physical address)
* SPRG1: original r1
*/
ppc_44x_exception_vector_common:
stw %r0, 20(%r1) /* save original LR */
stw %r2, 24(%r1) /* save r2 */
stw %r3, 28(%r1) /* save r3 */
/* load the virtual address of the ppc_cpu_exception_context for this CPU */
lwz %r1, 4(%r1)
/* Address translation is turned off. We map this code via BAT, turn on
address translation, and continue in the kernel proper. */
li %r0, 0x10|0x2 /* BATL_MC | BATL_PP_RW */
mtibatl 0, %r0 /* load lower word of the instruction BAT */
li %r0, 0x2 /* BEPI = 0, BL = 0 (128 KB), BATU_VS */
mtibatu 0, %r0 /* load upper word of the instruction BAT */
isync
sync
/* turn on address translation */
mfsrr1 %r0 /* load saved msr */
rlwinm %r0, %r0, 28, 30, 31 /* extract mmu bits */
mfmsr %r3 /* load the current msr */
rlwimi %r3, %r0, 4, 26, 27 /* merge the mmu bits with the current msr */
li %r0, 1
rlwimi %r3, %r0, 13, 18, 18 /* turn on FPU, too */
mtmsr %r3 /* load new msr (turning the mmu back on) */
isync
/* Get LR -- it points to the end of the exception vector code. We adjust it
to point to the beginning and can use it to identify the vector later. */
mflr %r3
subi %r3, %r3, 20 /* 5 instructions */
/* jump to kernel code (ppc_exception_tail) */
lwz %r2, 0(%r1)
mtlr %r2
blr
DEFINE_VECTOR(0x100, system_reset_exception)
DEFINE_VECTOR(0x200, machine_check_exception)
DEFINE_VECTOR(0x300, DSI_exception)
DEFINE_VECTOR(0x400, ISI_exception)
DEFINE_VECTOR(0x500, external_interrupt_exception)
DEFINE_VECTOR(0x600, alignment_exception)
DEFINE_VECTOR(0x700, program_exception)
DEFINE_VECTOR(0x800, FP_unavailable_exception)
DEFINE_VECTOR(0x900, decrementer_exception)
DEFINE_VECTOR(0xc00, system_call_exception)
DEFINE_VECTOR(0xd00, trace_exception)
DEFINE_VECTOR(0xe00, FP_assist_exception)
DEFINE_VECTOR(0xf00, perf_monitor_exception)
DEFINE_VECTOR(0xf20, altivec_unavailable_exception)
DEFINE_VECTOR(0x1000, ITLB_miss_exception)
DEFINE_VECTOR(0x1100, DTLB_miss_on_load_exception)
DEFINE_VECTOR(0x1200, DTLB_miss_on_store_exception)
DEFINE_VECTOR(0x1300, instruction_address_breakpoint_exception)
DEFINE_VECTOR(0x1400, system_management_exception)
DEFINE_VECTOR(0x1600, altivec_assist_exception)
DEFINE_VECTOR(0x1700, thermal_management_exception)
.global __44x_irqvec_end
__44x_irqvec_end:
/* This is where ppc_44x_exception_vector_common continues. We're in the kernel here.
r1: ppc_cpu_exception_context* (virtual address)
r3: exception vector offset
SPRG1: original r1
*/
FUNCTION(ppc_44x_exception_tail):
/* turn off BAT */
li %r2, 0
mtibatu 0, %r2
mtibatl 0, %r2
isync
sync
/* save CR */
mfcr %r0
mfsrr1 %r2 /* load saved msr */
andi. %r2, %r2, (1 << 14) /* see if it was in kernel mode */
beq .kernel /* yep */
/* We come from userland. Load the kernel stack top address for the current
userland thread. */
mr %r2, %r1
lwz %r1, 8(%r1)
b .restore_stack_end
.kernel:
mr %r2, %r1
mfsprg1 %r1
.restore_stack_end:
/* now r2 points to the ppc_cpu_exception_context, r1 to the kernel stack */
/* restore the CR, it was messed up in the previous compare */
mtcrf 0xff, %r0
/* align r1 to 8 bytes, so the iframe will be aligned too */
rlwinm %r1, %r1, 0, 0, 28
/* save the registers */
bl __44x_save_regs
/* iframe pointer to r4 and a backup to r20 */
mr %r4, %r1
mr %r20, %r1
/* adjust the stack pointer for ABI compatibility */
subi %r1, %r1, 8 /* make sure there's space for the previous
frame pointer and the return address */
rlwinm %r1, %r1, 0, 0, 27 /* 16 byte align the stack pointer */
li %r0, 0
stw %r0, 0(%r1) /* previous frame pointer: NULL */
/* 4(%r1) is room for the return address to be filled in by the
called function. */
/* r3: exception vector offset
r4: iframe pointer */
bl ppc_exception_entry
/* move the iframe to r1 */
mr %r1, %r20
b __44x_restore_regs_and_rfi
/* called by ppc_44x_exception_tail
* register expectations:
* r1: stack
* r2: ppc_cpu_exception_context*
* SPRG1: original r1
* r0,r3, LR: scrambled, but saved in scratch memory
* all other regs should have been unmodified by the exception handler,
* and ready to be saved
*/
__44x_save_regs:
/* Note: The iframe must be 8 byte aligned. The stack pointer we are passed
in r1 is aligned. So we store the floating point registers first and
need to take care that an even number of 4 byte registers is stored,
or insert padding respectively. */
/* push f0-f31 */
stfdu %f0, -8(%r1)
stfdu %f1, -8(%r1)
stfdu %f2, -8(%r1)
stfdu %f3, -8(%r1)
stfdu %f4, -8(%r1)
stfdu %f5, -8(%r1)
stfdu %f6, -8(%r1)
stfdu %f7, -8(%r1)
stfdu %f8, -8(%r1)
stfdu %f9, -8(%r1)
stfdu %f10, -8(%r1)
stfdu %f11, -8(%r1)
stfdu %f12, -8(%r1)
stfdu %f13, -8(%r1)
stfdu %f14, -8(%r1)
stfdu %f15, -8(%r1)
stfdu %f16, -8(%r1)
stfdu %f17, -8(%r1)
stfdu %f18, -8(%r1)
stfdu %f19, -8(%r1)
stfdu %f20, -8(%r1)
stfdu %f21, -8(%r1)
stfdu %f22, -8(%r1)
stfdu %f23, -8(%r1)
stfdu %f24, -8(%r1)
stfdu %f25, -8(%r1)
stfdu %f26, -8(%r1)
stfdu %f27, -8(%r1)
stfdu %f28, -8(%r1)
stfdu %f29, -8(%r1)
stfdu %f30, -8(%r1)
stfdu %f31, -8(%r1)
/* push r0-r3 */
lwz %r0, 16(%r2) /* original r0 */
stwu %r0, -4(%r1) /* push r0 */
mfsprg1 %r0 /* original r1 */
stwu %r0, -4(%r1) /* push r1 */
lwz %r0, 24(%r2) /* original r2 */
stwu %r0, -4(%r1) /* push r2 */
lwz %r0, 28(%r2) /* original r3 */
stwu %r0, -4(%r1) /* push r3 */
/* push r4-r31 */
stwu %r4, -4(%r1)
stwu %r5, -4(%r1)
stwu %r6, -4(%r1)
stwu %r7, -4(%r1)
stwu %r8, -4(%r1)
stwu %r9, -4(%r1)
stwu %r10, -4(%r1)
stwu %r11, -4(%r1)
stwu %r12, -4(%r1)
stwu %r13, -4(%r1)
stwu %r14, -4(%r1)
stwu %r15, -4(%r1)
stwu %r16, -4(%r1)
stwu %r17, -4(%r1)
stwu %r18, -4(%r1)
stwu %r19, -4(%r1)
stwu %r20, -4(%r1)
stwu %r21, -4(%r1)
stwu %r22, -4(%r1)
stwu %r23, -4(%r1)
stwu %r24, -4(%r1)
stwu %r25, -4(%r1)
stwu %r26, -4(%r1)
stwu %r27, -4(%r1)
stwu %r28, -4(%r1)
stwu %r29, -4(%r1)
stwu %r30, -4(%r1)
stwu %r31, -4(%r1)
/* save some of the other regs */
mffs %f0
stfsu %f0, -4(%r1) /* push FPSCR */
mfctr %r0
stwu %r0, -4(%r1) /* push CTR */
mfxer %r0
stwu %r0, -4(%r1) /* push XER */
mfcr %r0
stwu %r0, -4(%r1) /* push CR */
lwz %r0, 20(%r2) /* original LR */
stwu %r0, -4(%r1) /* push LR */
mfspr %r0, %dsisr
stwu %r0, -4(%r1) /* push DSISR */
mfspr %r0, %dar
stwu %r0, -4(%r1) /* push DAR */
mfspr %r0, %srr1
stwu %r0, -4(%r1) /* push SRR1 */
mfspr %r0, %srr0
stwu %r0, -4(%r1) /* push SRR0 */
stwu %r3, -4(%r1) /* exception vector offset */
blr
/* called at the tail end of each of the exceptions
* r1: iframe pointer
*/
__44x_restore_regs_and_rfi:
lwzu %r0, 4(%r1) /* SRR0 (skip vector offset) */
mtspr %srr0, %r0
lwzu %r0, 4(%r1) /* SRR1 */
mtspr %srr1, %r0
lwzu %r0, 4(%r1) /* DAR */
mtspr %dar, %r0
lwzu %r0, 4(%r1) /* DSISR */
mtspr %dsisr, %r0
lwzu %r0, 4(%r1) /* LR */
mtlr %r0
lwzu %r0, 4(%r1) /* CR */
mtcr %r0
lwzu %r0, 4(%r1) /* XER */
mtxer %r0
lwzu %r0, 4(%r1) /* CTR */
mtctr %r0
lfsu %f0, 4(%r1) /* FPSCR */
mtfsf 0xff, %f0
lwzu %r31, 4(%r1)
lwzu %r30, 4(%r1)
lwzu %r29, 4(%r1)
lwzu %r28, 4(%r1)
lwzu %r27, 4(%r1)
lwzu %r26, 4(%r1)
lwzu %r25, 4(%r1)
lwzu %r24, 4(%r1)
lwzu %r23, 4(%r1)
lwzu %r22, 4(%r1)
lwzu %r21, 4(%r1)
lwzu %r20, 4(%r1)
lwzu %r19, 4(%r1)
lwzu %r18, 4(%r1)
lwzu %r17, 4(%r1)
lwzu %r16, 4(%r1)
lwzu %r15, 4(%r1)
lwzu %r14, 4(%r1)
lwzu %r13, 4(%r1)
lwzu %r12, 4(%r1)
lwzu %r11, 4(%r1)
lwzu %r10, 4(%r1)
lwzu %r9, 4(%r1)
lwzu %r8, 4(%r1)
lwzu %r7, 4(%r1)
lwzu %r6, 4(%r1)
lwzu %r5, 4(%r1)
lwzu %r4, 4(%r1)
lwzu %r3, 4(%r1)
/* Stop here, before we overwrite r1, and continue with the floating point
registers first. */
addi %r2, %r1, 16 /* skip r3-r0 */
/* f31-f0 */
lfd %f31, 0(%r2)
lfdu %f30, 8(%r2)
lfdu %f29, 8(%r2)
lfdu %f28, 8(%r2)
lfdu %f27, 8(%r2)
lfdu %f26, 8(%r2)
lfdu %f25, 8(%r2)
lfdu %f24, 8(%r2)
lfdu %f23, 8(%r2)
lfdu %f22, 8(%r2)
lfdu %f21, 8(%r2)
lfdu %f20, 8(%r2)
lfdu %f19, 8(%r2)
lfdu %f18, 8(%r2)
lfdu %f17, 8(%r2)
lfdu %f16, 8(%r2)
lfdu %f15, 8(%r2)
lfdu %f14, 8(%r2)
lfdu %f13, 8(%r2)
lfdu %f12, 8(%r2)
lfdu %f11, 8(%r2)
lfdu %f10, 8(%r2)
lfdu %f9, 8(%r2)
lfdu %f8, 8(%r2)
lfdu %f7, 8(%r2)
lfdu %f6, 8(%r2)
lfdu %f5, 8(%r2)
lfdu %f4, 8(%r2)
lfdu %f3, 8(%r2)
lfdu %f2, 8(%r2)
lfdu %f1, 8(%r2)
lfd %f0, 8(%r2)
/* r2-r0 */
lwzu %r2, 4(%r1)
lwz %r0, 8(%r1)
lwz %r1, 4(%r1)
/* return from interrupt */
rfi
+139 -3
View File
@@ -9,12 +9,17 @@
#include <KernelExport.h>
#include <arch/generic/debug_uart.h>
#include <boot/kernel_args.h>
#include <platform/openfirmware/openfirmware.h>
#include <real_time_clock.h>
#include <util/kernel_cpp.h>
// TODO: declare this in some header
extern void *gFDT;
extern "C" DebugUART *debug_uart_from_fdt(const void *fdt);
static PPCPlatform *sPPCPlatform;
@@ -225,18 +230,149 @@ PPCOpenFirmware::ShutDown(bool reboot)
}
// #pragma mark - U-Boot + FDT
namespace BPrivate {
class PPCUBoot : public PPCPlatform {
public:
PPCUBoot();
virtual ~PPCUBoot();
virtual status_t Init(struct kernel_args *kernelArgs);
virtual status_t InitSerialDebug(struct kernel_args *kernelArgs);
virtual status_t InitPostVM(struct kernel_args *kernelArgs);
virtual status_t InitRTC(struct kernel_args *kernelArgs,
struct real_time_data *data);
virtual char SerialDebugGetChar();
virtual void SerialDebugPutChar(char c);
virtual void SetHardwareRTC(uint32 seconds);
virtual uint32 GetHardwareRTC();
virtual void ShutDown(bool reboot);
private:
int fInput;
int fOutput;
int fRTC;
DebugUART *fDebugUART;
};
} // namespace BPrivate
using BPrivate::PPCUBoot;
// constructor
PPCUBoot::PPCUBoot()
: PPCPlatform(PPC_PLATFORM_U_BOOT),
fInput(-1),
fOutput(-1),
fRTC(-1),
fDebugUART(NULL)
{
}
// destructor
PPCUBoot::~PPCUBoot()
{
}
// Init
status_t
PPCUBoot::Init(struct kernel_args *kernelArgs)
{
gFDT = kernelArgs->platform_args.fdt;
// XXX: do we error out if no FDT?
return B_OK;
}
// InitSerialDebug
status_t
PPCUBoot::InitSerialDebug(struct kernel_args *kernelArgs)
{
fDebugUART = debug_uart_from_fdt(gFDT);
if (fDebugUART == NULL)
return B_ERROR;
return B_OK;
}
// InitPostVM
status_t
PPCUBoot::InitPostVM(struct kernel_args *kernelArgs)
{
return B_ERROR;
}
// InitRTC
status_t
PPCUBoot::InitRTC(struct kernel_args *kernelArgs,
struct real_time_data *data)
{
return B_ERROR;
}
// DebugSerialGetChar
char
PPCUBoot::SerialDebugGetChar()
{
if (fDebugUART)
return fDebugUART->GetChar(false);
return 0;
}
// DebugSerialPutChar
void
PPCUBoot::SerialDebugPutChar(char c)
{
if (fDebugUART)
fDebugUART->PutChar(c);
}
// SetHardwareRTC
void
PPCUBoot::SetHardwareRTC(uint32 seconds)
{
}
// GetHardwareRTC
uint32
PPCUBoot::GetHardwareRTC()
{
return 0;
}
// ShutDown
void
PPCUBoot::ShutDown(bool reboot)
{
}
// # pragma mark -
#define PLATFORM_BUFFER_SIZE MAX(sizeof(PPCOpenFirmware),sizeof(PPCUBoot))
// static buffer for constructing the actual PPCPlatform
static char *sPPCPlatformBuffer[sizeof(PPCOpenFirmware)];
static char *sPPCPlatformBuffer[PLATFORM_BUFFER_SIZE];
status_t
arch_platform_init(struct kernel_args *kernelArgs)
{
// only OpenFirmware supported for now
if (true)
sPPCPlatform = new(sPPCPlatformBuffer) PPCOpenFirmware;
switch (kernelArgs->arch_args.platform) {
case PPC_PLATFORM_OPEN_FIRMWARE:
sPPCPlatform = new(sPPCPlatformBuffer) PPCOpenFirmware;
break;
case PPC_PLATFORM_U_BOOT:
sPPCPlatform = new(sPPCPlatformBuffer) PPCUBoot;
break;
default:
return B_ERROR;
}
return sPPCPlatform->Init(kernelArgs);
}
+11 -10
View File
@@ -110,6 +110,15 @@ x86_set_tls_context(Thread *thread)
}
static addr_t
arch_randomize_stack_pointer(addr_t value)
{
STATIC_ASSERT(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1);
value -= random_value() & (B_PAGE_SIZE - 1);
return value & ~addr_t(0xf);
}
static uint8*
get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* action)
{
@@ -119,7 +128,8 @@ get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* action)
&& (frame->user_sp < thread->signal_stack_base
|| frame->user_sp >= thread->signal_stack_base
+ thread->signal_stack_size)) {
return (uint8*)(thread->signal_stack_base + thread->signal_stack_size);
addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size;
return (uint8*)arch_randomize_stack_pointer(stackTop);
}
return (uint8*)frame->user_sp;
@@ -202,15 +212,6 @@ arch_thread_dump_info(void *info)
}
static addr_t
arch_randomize_stack_pointer(addr_t value)
{
STATIC_ASSERT(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1);
value -= random_value() & (B_PAGE_SIZE - 1);
return value & ~addr_t(0xf);
}
/*! Sets up initial thread context and enters user space
*/
status_t
+11 -10
View File
@@ -95,6 +95,15 @@ x86_set_tls_context(Thread* thread)
}
static addr_t
arch_randomize_stack_pointer(addr_t value)
{
STATIC_ASSERT(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1);
value -= random_value() & (B_PAGE_SIZE - 1);
return value & ~addr_t(0xf);
}
static uint8*
get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action)
{
@@ -104,7 +113,8 @@ get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action)
&& (frame->user_sp < thread->signal_stack_base
|| frame->user_sp >= thread->signal_stack_base
+ thread->signal_stack_size)) {
return (uint8*)(thread->signal_stack_base + thread->signal_stack_size);
addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size;
return (uint8*)arch_randomize_stack_pointer(stackTop);
}
// We are going to use the stack that we are already on. We must not touch
@@ -198,15 +208,6 @@ arch_thread_dump_info(void* info)
}
static addr_t
arch_randomize_stack_pointer(addr_t value)
{
STATIC_ASSERT(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1);
value -= random_value() & (B_PAGE_SIZE - 1);
return value & ~addr_t(0xf);
}
/*! Sets up initial thread context and enters user space
*/
status_t
+18
View File
@@ -3,6 +3,24 @@ SubDir HAIKU_TOP src system kernel platform u-boot ;
SubDirCcFlags $(TARGET_KERNEL_PIC_CCFLAGS) ;
SubDirC++Flags $(TARGET_KERNEL_PIC_CCFLAGS) ;
UseLibraryHeaders [ FDirName libfdt ] ;
local libFDTSources =
fdt.c
fdt_ro.c
fdt_rw.c
fdt_strerror.c
fdt_sw.c
fdt_wip.c
;
KernelMergeObject kernel_platform_u-boot.o :
platform.cpp
fdt_support.cpp
openfirmware.cpp
$(libFDTSources)
;
SEARCH on [ FGristFiles $(libFDTSources) ]
= [ FDirName $(HAIKU_TOP) src libs libfdt ] ;
@@ -9,14 +9,22 @@
#include <stdio.h>
#include <sys/cdefs.h>
#include <arch/generic/debug_uart.h>
#include <arch/generic/debug_uart_8250.h>
extern "C" {
#include <fdt.h>
#include <libfdt.h>
#include <libfdt_env.h>
};
#ifndef _BOOT_MODE
/* the bootloader has it in asm code to avoid it ending up in .bss */
void *gFDT;
#endif
extern "C" void dump_fdt(const void *fdt);
extern "C" DebugUART *debug_uart_from_fdt(const void *fdt);
//#define FDT_DUMP_NODES
//#define FDT_DUMP_PROPS
@@ -61,7 +69,7 @@ void dump_fdt(const void *fdt)
int err;
dprintf("FDT @ %p:\n", fdt);
if (!fdt)
return;
@@ -113,3 +121,84 @@ void dump_fdt(const void *fdt)
}
DebugUART *
debug_uart_from_fdt(const void *fdt)
{
const char *name;
const char *type;
int node;
int len;
phys_addr_t regs;
int32 clock = 0;
int32 speed = 0;
const void *prop;
DebugUART *uart = NULL;
if (fdt == NULL)
return NULL;
name = fdt_get_alias(fdt, "serial");
if (name == NULL)
name = fdt_get_alias(fdt, "serial0");
if (name == NULL)
name = fdt_get_alias(fdt, "serial1");
// TODO: else use /chosen linux,stdout-path
if (name == NULL)
return NULL;
node = fdt_path_offset(fdt, name);
//dprintf("serial: using '%s', node %d\n", name, node);
if (node < 0)
return NULL;
type = (const char *)fdt_getprop(fdt, node, "device_type", &len);
//dprintf("serial: type: '%s'\n", type);
if (type == NULL || strcmp(type, "serial"))
return NULL;
// determine the MMIO address
// TODO: ppc460 use 64bit addressing, but U-Boot seems to map it below 4G,
// and the FDT is not very clear. libfdt is also getting 64bit addr support.
// so FIXME someday.
prop = fdt_getprop(fdt, node, "virtual-reg", &len);
if (prop && len == 4) {
regs = fdt32_to_cpu(*(uint32_t *)prop);
//dprintf("serial: virtual-reg 0x%08llx\n", (int64)regs);
} else {
prop = fdt_getprop(fdt, node, "reg", &len);
if (prop && len >= 4) {
regs = fdt32_to_cpu(*(uint32_t *)prop);
//dprintf("serial: reg 0x%08llx\n", (int64)regs);
} else
return NULL;
}
// get the UART clock rate
prop = fdt_getprop(fdt, node, "clock-frequency", &len);
if (prop && len == 4) {
clock = fdt32_to_cpu(*(uint32_t *)prop);
//dprintf("serial: clock %ld\n", clock);
}
// get current speed (XXX: not yet passed over)
prop = fdt_getprop(fdt, node, "current-speed", &len);
if (prop && len == 4) {
speed = fdt32_to_cpu(*(uint32_t *)prop);
//dprintf("serial: speed %ld\n", speed);
}
if (fdt_node_check_compatible(fdt, node, "ns16550a") == 1
|| fdt_node_check_compatible(fdt, node, "ns16550") == 1) {
uart = arch_get_uart_8250(regs, clock);
//dprintf("serial: using 8250\n");
// XXX:assume speed is already set
(void)speed;
} else {
// TODO: handle more UART types
// for when we can use U-Boot's console
panic("Unknown UART type %s", type);
}
return uart;
}
@@ -0,0 +1,344 @@
/*
* Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <platform/openfirmware/devices.h>
#include <platform/openfirmware/openfirmware.h>
#include <stdarg.h>
#include <KernelExport.h>
extern "C" {
#include <fdt.h>
#include <libfdt.h>
#include <libfdt_env.h>
};
#define TRACE_OF
#ifdef TRACE_OF
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
// FIXME: HACK: until we support multiple platforms at once in the kernel.
extern void *gFDT;
int gChosen;
static int fdt2of(int err)
{
if (err >= 0)
return err;
switch (err) {
case -FDT_ERR_NOTFOUND:
case -FDT_ERR_EXISTS:
case -FDT_ERR_NOSPACE:
case -FDT_ERR_BADOFFSET:
case -FDT_ERR_BADPATH:
case -FDT_ERR_BADPHANDLE:
case -FDT_ERR_BADSTATE:
case -FDT_ERR_TRUNCATED:
case -FDT_ERR_BADMAGIC:
case -FDT_ERR_BADVERSION:
case -FDT_ERR_BADSTRUCTURE:
case -FDT_ERR_BADLAYOUT:
case -FDT_ERR_INTERNAL:
default:
return OF_FAILED;
}
}
status_t
of_init(int (*openFirmwareEntry)(void *))
{
if (gFDT == NULL)
return OF_FAILED;
gChosen = fdt2of(fdt_path_offset(gFDT, "/chosen"));
if (gChosen == OF_FAILED)
return B_ERROR;
return B_OK;
}
int
of_call_client_function(const char *method, int numArgs, int numReturns, ...)
{
return OF_FAILED;
}
int
of_interpret(const char *command, int numArgs, int numReturns, ...)
{
return OF_FAILED;
}
int
of_call_method(int handle, const char *method, int numArgs, int numReturns, ...)
{
return OF_FAILED;
}
int
of_finddevice(const char *device)
{
const char *name = device;
int node;
if (device == NULL)
return OF_FAILED;
if (device[0] != '/' && fdt_get_alias(gFDT, device))
name = fdt_get_alias(gFDT, device);
node = fdt_path_offset(gFDT, name);
TRACE(("of_finddevice('%s') name='%s' node=%d ret=%d\n", device, name, node,
fdt2of(node)));
return fdt2of(node);
}
status_t
of_get_next_device(int *_cookie, int root, const char *type, char *path,
size_t pathSize)
{
int next;
int err;
int startoffset = *_cookie ? *_cookie : -1;
// iterate by property value
next = fdt_node_offset_by_prop_value(gFDT, startoffset, "device_type",
type, strlen(type) + 1);
TRACE(("of_get_next_device(c:%d, %d, '%s', %p, %zd) soffset=%d next=%d\n",
*_cookie, root, type, path, pathSize, startoffset, fdt2of(next)));
if (next < 0)
return B_ENTRY_NOT_FOUND;
// make sure root is the parent
int parent = next;
while (root && parent) {
parent = fdt_parent_offset(gFDT, parent);
if (parent == root)
break;
if (parent <= 0)
return B_ENTRY_NOT_FOUND;
}
*_cookie = next;
err = fdt_get_path(gFDT, next, path, pathSize);
if (err < 0)
return B_ERROR;
return B_OK;
}
/** Returns the first child of the given node
*/
int
of_child(int node)
{
return OF_FAILED;
}
/** Returns the next sibling of the given node
*/
int
of_peer(int node)
{
return OF_FAILED;
}
/** Returns the parent of the given node
*/
int
of_parent(int node)
{
return OF_FAILED;
}
int
of_instance_to_path(int instance, char *pathBuffer, int bufferSize)
{
return OF_FAILED;
}
int
of_instance_to_package(int instance)
{
return OF_FAILED;
}
int
of_getprop(int package, const char *property, void *buffer, int bufferSize)
{
int oldSize = bufferSize;
const void *p = fdt_getprop(gFDT, package, property, &bufferSize);
TRACE(("of_getprop(%d, '%s', , %d) =%p sz=%d ret=%d\n", package, property,
oldSize, p, bufferSize, fdt2of(bufferSize)));
if (p == NULL)
return fdt2of(bufferSize);
memcpy(buffer, p, bufferSize);
return bufferSize;
}
int
of_setprop(int package, const char *property, const void *buffer, int bufferSize)
{
return OF_FAILED;
}
int
of_getproplen(int package, const char *property)
{
return OF_FAILED;
}
int
of_nextprop(int package, const char *previousProperty, char *nextProperty)
{
return OF_FAILED;
}
int
of_package_to_path(int package, char *pathBuffer, int bufferSize)
{
return OF_FAILED;
}
/** given the package provided, get the number of cells
+ in the reg property
+ */
int32
of_address_cells(int package) {
uint32 address_cells;
if (of_getprop(package, "#address-cells",
&address_cells, sizeof(address_cells)) == OF_FAILED)
return OF_FAILED;
return address_cells;
}
int32
of_size_cells(int package) {
uint32 size_cells;
if (of_getprop(package, "#size-cells",
&size_cells, sizeof(size_cells)) == OF_FAILED)
return OF_FAILED;
return size_cells;
}
// I/O functions
int
of_open(const char *nodeName)
{
return OF_FAILED;
}
void
of_close(int handle)
{
}
int
of_read(int handle, void *buffer, int bufferSize)
{
return OF_FAILED;
}
int
of_write(int handle, const void *buffer, int bufferSize)
{
return OF_FAILED;
}
int
of_seek(int handle, long long pos)
{
return OF_FAILED;
}
// memory functions
int
of_release(void *virtualAddress, int size)
{
return OF_FAILED;
}
void *
of_claim(void *virtualAddress, int size, int align)
{
return NULL;
}
// misc functions
/** tests if the given service is missing
*/
int
of_test(const char *service)
{
return OF_FAILED;
}
/** Returns the millisecond counter
*/
int
of_milliseconds(void)
{
return OF_FAILED;
}
void
of_exit(void)
{
}
+30
View File
@@ -91,6 +91,36 @@ SECTIONS
_end = . ;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note .eh_frame .dtors .debug_*) }
+9 -86
View File
@@ -4,14 +4,15 @@
*/
#include <asm_defs.h>
#include <arch_config.h>
.text
#ifndef ATOMIC_FUNCS_ARE_SYSCALLS
/* int atomic_add(int *value, int increment)
*/
FUNCTION(atomic_add):
#if __ARM_ARCH__ >= 6
miss1: ldrex r12, [r0]
add r2, r12, r1
strex r3, r2, [r0]
@@ -19,25 +20,6 @@ miss1: ldrex r12, [r0]
bne miss1
mov r0, r12
bx lr
#else
/* disable interrupts, do the add, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the add, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
add r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
FUNCTION_END(atomic_add)
@@ -46,7 +28,6 @@ FUNCTION_END(atomic_add)
/* int atomic_and(int *value, int andValue)
*/
FUNCTION(atomic_and):
#if __ARM_ARCH__ >= 6
miss2: ldrex r12, [r0]
and r2, r12, r1
strex r3, r2, [r0]
@@ -54,33 +35,11 @@ miss2: ldrex r12, [r0]
bne miss2
mov r0, r12
bx lr
#else
/* disable interrupts, do the and, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the and, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
and r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
FUNCTION_END(atomic_and)
/* int atomic_or(int *value, int orValue)
*/
FUNCTION(atomic_or):
#if __ARM_ARCH__ >= 6
miss3: ldrex r12, [r0]
eor r2, r12, r1
strex r3, r2, [r0]
@@ -88,48 +47,21 @@ miss3: ldrex r12, [r0]
bne miss3
mov r0, r12
bx lr
#else
/* disable interrupts, do the or, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the or, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
orr r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
FUNCTION_END(atomic_or)
/* int atomic_set(int *value, int setTo)
*/
FUNCTION(atomic_set):
#if __ARM_ARCH__ >= 6
miss4: ldrex r12, [r0]
strex r3, r1, [r0]
teq r3, #0
bne miss4
bx lr
#else
mov r3, r0
swp r0, r1, [r3]
bx lr
#endif
FUNCTION_END(atomic_set)
/* int atomic_test_and_set(int *value, int setTo, int testValue)
*/
FUNCTION(atomic_test_and_set):
#if __ARM_ARCH__ >= 6
miss5: ldrex r12, [r0] @ load from the address and mark it exclusive
cmp r12, r2 @ compare the value with the comperand(r2)
strexeq r3, r1, [r0] @ if they were equal, attempt to store the new value (r1)
@@ -139,21 +71,6 @@ miss5: ldrex r12, [r0] @ load from the address and
bne same @ if it succeeded, jump to (same) and return. there is no need to clrex if strex succeeded
differ: clrex @ clrex
same: mov r0, r12
#else
/* disable interrupts, and save state */
mrs r3, cpsr
mov r12, r3
orr r3, r3, #(3<<6)
msr cpsr_c, r3
mov r3, r0
ldr r0, [r3]
cmp r0, r2
streq r1, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
#endif
bx lr
FUNCTION_END(atomic_test_and_set)
@@ -168,6 +85,10 @@ FUNCTION(__sync_fetch_and_add_4):
bx lr
FUNCTION_END(__sync_fetch_and_add_4)
#endif
#ifndef ATOMIC64_FUNCS_ARE_SYSCALLS
/* int64 atomic_add64(vint64 *value, int64 addValue) */
FUNCTION(atomic_add64):
bx lr
@@ -197,3 +118,5 @@ FUNCTION_END(atomic_test_and_set64)
FUNCTION(atomic_get64):
bx lr
FUNCTION_END(atomic_get64)
#endif /* ATOMIC64_FUNCS_ARE_SYSCALLS */
+1 -1
View File
@@ -110,6 +110,7 @@ spawn_thread(thread_func entry, const char *name, int32 priority, void *data)
__pthread_init_creation_attributes(NULL, thread, &thread_entry, entry,
thread, name, &attributes);
thread->flags |= THREAD_DETACHED;
attributes.priority = priority;
@@ -256,4 +257,3 @@ snooze_until(bigtime_t timeout, int timeBase)
{
return _kern_snooze_etc(timeout, timeBase, B_ABSOLUTE_TIMEOUT, NULL);
}
@@ -5,16 +5,13 @@
#include <asm_defs.h>
//#include "setjmp_internal.h"
/* int __siglongjmp(jmp_buf buffer, int value) */
FUNCTION(siglongjmp):
FUNCTION(longjmp):
FUNCTION(_longjmp):
str r1,[r0]
ldmia r0,{r0-r14}
bx lr
// bl __longjmp_return
str r1, [r0, #4]
ldmia r0, {r0-r14}
b __longjmp_return
FUNCTION_END(siglongjmp)
FUNCTION_END(longjmp)
FUNCTION_END(_longjmp)
+11 -19
View File
@@ -5,33 +5,25 @@
#include <asm_defs.h>
//#include "setjmp_internal.h"
/* int sigsetjmp(jmp_buf buffer, int saveMask) */
FUNCTION(__sigsetjmp):
FUNCTION(sigsetjmp):
stmdb sp!, {r4, lr}
stmia r0, {r0-r14}
str lr,[r0, #60]
mrs r1,cpsr
str r1,[r0,#64]
ldr r1,[r0,#4]
mov r0, #0
bl __setjmp_save_sigs
ldmia sp!, {r4, pc}
FUNCTION_END(__sigsetjmp)
stmia r0, {r0-r14}
mrs r1, cpsr
str r1, [r0, #64]
ldr r1, [r0, #4]
b __setjmp_save_sigs
FUNCTION_END(sigsetjmp)
FUNCTION_END(__sigsetjmp)
/* int setjmp(jmp_buf buffer) */
FUNCTION(setjmp):
stmia r0, {r0-r14}
str lr,[r0, #60]
mrs r1,cpsr
str r1,[r0,#64]
ldr r1,[r0,#4]
mov r0, #0
stmia r0, {r0-r14}
mrs r1, cpsr
str r1, [r0, #64]
ldr r1, [r0, #4]
mov r0, #0
bx lr
FUNCTION_END(setjmp)