White Papers
8
.base_port = 0xE0,
},
{
.device_num = 7,
.base_port = 0xF4,
},
};
void enter_extended_function_mode()
{
outb(0x87, LPC_ADDR_PORT);
outb(0x87, LPC_ADDR_PORT);
}
void leave_extended_function_mode()
{
outb(0xAA, LPC_ADDR_PORT);
}
void lpc_reg_write(int reg, int val)
{
outb(reg, LPC_ADDR_PORT);
outb(val, LPC_DATA_PORT);
}
int lpc_reg_read(int reg)
{
outb(reg, LPC_ADDR_PORT);
return inb(LPC_DATA_PORT);
}
gpio_controller *gpio_initialize()
{
int i, rc;
gpio_controller *gc;
gc = malloc(sizeof(*gc));
if ( gc == NULL ) {
fprintf(stderr, "%s: no memory error\n", __FUNCTION__);
return NULL;
}
rc = ioperm(LPC_ADDR_PORT, 2, 1);
if ( rc ) {
fprintf(stderr, "%s: failed to reserve IO ports: %s\n",
__FUNCTION__, strerror(errno));
free(gc);
return NULL;
}
// The caller of ioperm() needs root privilege to get the permission of
// IO ports. In order to allow a normal user (non-root) running this program,
// "setuid" could be used for this purpose:
// 1. Change the owner of executable file to root:root
// 2. Change the mode of executable file to 4755
// After the call of ioperm(), change the effective uid of current process
// from root uid to the real uid, which is returned from getuid(), i.e. uid
// of the user who actually runs this process), to drop the root privilege.
setuid(getuid());
// Apply board-level contraints to pins