Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4676 → Rev 4677

/branches/dd/uspace/app/shutters/shutters.c
0,0 → 1,225
/*
* Copyright (c) 2009 Lenka Trochtova
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
*/
 
/** @addtogroup shutters
* @brief closing/opening shutters
* @{
*/
/**
* @file
*/
 
#include <stdio.h>
#include <ipc/ipc.h>
#include <sys/types.h>
#include <atomic.h>
#include <ipc/devmap.h>
#include <async.h>
#include <ipc/services.h>
#include <ipc/serial.h>
#include <as.h>
#include <sysinfo.h>
#include <errno.h>
 
 
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
 
#include <string.h>
 
#define NAME "shutters"
#define MYROOM 2
#define UpSection1 25
#define DwnSection1 26
#define UpSection2 27
#define DwnSection2 28
 
static int device_get_handle(const char *name, dev_handle_t *handle);
static void print_usage();
static void move_shutters(const char * serial_dev_name, char room, char cmd);
static char getcmd(bool wnd, bool up);
static bool is_com_dev(const char *dev_name);
 
static int device_get_handle(const char *name, dev_handle_t *handle)
{
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
if (phone < 0)
return phone;
ipc_call_t answer;
aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0, &answer);
ipcarg_t retval = ipc_data_write_start(phone, name, str_length(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
ipc_hangup(phone);
return retval;
}
 
async_wait_for(req, &retval);
 
if (handle != NULL)
*handle = -1;
if (retval == EOK) {
if (handle != NULL)
*handle = (dev_handle_t) IPC_GET_ARG1(answer);
}
ipc_hangup(phone);
return retval;
}
 
static void print_usage()
{
printf("Usage: \n shutters comN shutter direction \n where 'comN' is a serial port, 'shutter' is either 'window' or 'door' and direction is 'up' or 'down'.\n");
}
 
static void move_shutters(const char * serial_dev_name, char room, char cmd)
{
dev_handle_t serial_dev_handle = -1;
if (device_get_handle(serial_dev_name, &serial_dev_handle) != EOK) {
printf(NAME ": could not get the handle of %s.\n", serial_dev_name);
return;
}
printf(NAME ": got the handle of %s.\n", serial_dev_name);
int dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CONNECT_TO_DEVICE, serial_dev_handle);
if(dev_phone < 0) {
printf(NAME ": could not connect to %s device.\n", serial_dev_name);
return;
}
async_req_1_0(dev_phone, SERIAL_PUTCHAR, 0x55);
async_req_1_0(dev_phone, SERIAL_PUTCHAR, room);
async_req_1_0(dev_phone, SERIAL_PUTCHAR, cmd);
async_req_1_0(dev_phone, SERIAL_PUTCHAR, 240);
}
 
static char getcmd(bool wnd, bool up)
{
char cmd = 0;
if (wnd) {
if (up) {
cmd = UpSection2;
}
else {
cmd = DwnSection2;
}
} else {
if (up) {
cmd = UpSection1;
}
else {
cmd = DwnSection1;
}
}
return cmd;
}
 
/*
* The name of a serial device must be between 'com0' and 'com9'.
*/
static bool is_com_dev(const char *dev_name)
{
if (str_length(dev_name) != 4) {
return false;
}
if (str_cmp("com0", dev_name) > 0) {
return false;
}
if (str_cmp(dev_name, "com9") > 0) {
return false;
}
return true;
}
 
 
int main(int argc, char *argv[])
{
if (argc != 4) {
printf(NAME ": incorrect number of arguments.\n");
print_usage();
return 0;
}
 
bool wnd, up;
const char *serial_dev = argv[1];
if (!is_com_dev(serial_dev)) {
printf(NAME ": the first argument is not correct.\n");
print_usage();
return 0;
}
if (str_cmp(argv[2], "window") == 0) {
wnd = true;
} else if (str_cmp(argv[2], "door") == 0) {
wnd = false;
} else {
printf(NAME ": the second argument is not correct.\n");
print_usage();
return 0;
}
if (str_cmp(argv[2], "window") == 0) {
wnd = true;
} else if (str_cmp(argv[2], "door") == 0) {
wnd = false;
} else {
printf(NAME ": the third argument is not correct.\n");
print_usage();
return 0;
}
if (str_cmp(argv[3], "up") == 0) {
up = true;
} else if (str_cmp(argv[3], "down") == 0) {
up = false;
} else {
printf(NAME ": the second argument is not correct.\n");
print_usage();
return 0;
}
char cmd = getcmd(wnd, up);
move_shutters(serial_dev, MYROOM, cmd);
return 0;
}
 
/** @}
*/
/branches/dd/uspace/app/shutters/Makefile
0,0 → 1,39
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
 
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBC_PREFIX)/libc.a
 
OUTPUT = shutters
SOURCES = shutters.c
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend *.o
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/dd/uspace/lib/libc/include/ipc/serial.h
0,0 → 1,14
#ifndef LIBC_FB_H_
#define LIBC_FB_H_
 
#include <ipc/ipc.h>
 
typedef enum {
SERIAL_PUTCHAR = IPC_FIRST_USER_METHOD,
SERIAL_GETCHAR,
SERIAL_READ,
SERIAL_WRITE,
} serial_request_t;
 
 
#endif
/branches/dd/uspace/srv/pci/serial.c
1,7 → 1,19
#include <unistd.h>
#include <ddi.h>
#include <libarch/ddi.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/serial.h>
#include <ipc/devmap.h>
#include <ipc/ns.h>
#include <bool.h>
#include <errno.h>
#include <async.h>
#include <stdio.h>
#include <futex.h>
#include <assert.h>
#include <adt/list.h>
#include <string.h>
 
#include "isa.h"
#include "serial.h"
9,11 → 21,33
#define NAME "serial"
 
#define REG_COUNT 7
#define COM1 0x3F8
#define COM2 0x2F8
 
static ioport8_t *com1 = 0, *com2 = 0;
#define MAX_NAME_LEN 8
 
struct serial_dev {
link_t link;
char name[MAX_NAME_LEN];
int handle;
bool client_connected;
ioport8_t *port;
void *phys_addr;
bridge_to_isa_t *parent;
};
 
typedef struct serial_dev serial_dev_t;
 
static void * serial_phys_addresses[] = { (void *)0x3F8, (void *)0x2F8 };
static int serial_phys_addr_cnt = sizeof(serial_phys_addresses)/sizeof(void *);
// number, which should be assigned to a newly found serial device - increment first, then assign to the device
static int serial_idx = 0;
 
static int serial_driver_phone = -1;
 
LIST_INITIALIZE(serial_devices_list);
 
static atomic_t serial_futex = FUTEX_INITIALIZER;
 
 
static void serial_init_port(ioport8_t *port);
static void serial_write_8(ioport8_t *port, uint8_t c);
static bool is_transmit_empty(ioport8_t *port);
20,7 → 54,12
static uint8_t serial_read_8(ioport8_t *port);
static bool serial_received(ioport8_t *port);
static void serial_probe(bridge_to_isa_t *parent);
static void * serial_probe_port(void *phys_addr);
static ioport8_t * serial_probe_port(void *phys_addr);
static int serial_device_register(int driver_phone, char *name, int *handle);
static int serial_driver_register(char *name);
static void serial_putchar(serial_dev_t *dev, ipc_callid_t rid, ipc_call_t *request);
static void serial_getchar(serial_dev_t *dev, ipc_callid_t rid);
static void serial_client_conn(ipc_callid_t iid, ipc_call_t *icall);
 
static isa_drv_ops_t serial_isa_ops = {
.probe = serial_probe
33,8 → 72,14
 
int serial_init()
{
// TODO: register this driver by generic isa bus driver
// register driver by devmapper
serial_driver_phone = serial_driver_register(NAME);
if (serial_driver_phone < 0) {
printf(NAME ": Unable to register driver\n");
return false;
}
// register this driver by generic isa bus driver
isa_register_driver(&serial_isa_drv);
return 1;
}
77,30 → 122,64
pio_write_8(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
}
 
static serial_dev_t * serial_alloc_dev()
{
serial_dev_t *dev = (serial_dev_t *)malloc(sizeof(serial_dev_t));
memset(dev, 0, sizeof(serial_dev_t));
return dev;
}
 
static void serial_init_dev(serial_dev_t *dev, bridge_to_isa_t *parent, int idx)
{
assert(dev != NULL);
memset(dev, 0, sizeof(serial_dev_t));
dev->parent = parent;
dev->phys_addr = dev->parent->ops->absolutize(serial_phys_addresses[idx % serial_phys_addr_cnt]);
snprintf(dev->name, MAX_NAME_LEN, "com%d", idx + 1);
dev->client_connected = false;
}
 
static bool serial_probe_dev(serial_dev_t *dev)
{
assert(dev != NULL);
printf(NAME " driver: probing %s \n", dev->name);
return (dev->port = (ioport8_t *)serial_probe_port(dev->phys_addr)) != NULL;
}
 
static void serial_delete_dev(serial_dev_t *dev) {
free(dev);
}
 
static void serial_probe(bridge_to_isa_t *parent)
{
printf(NAME " driver: probe()\n");
 
printf(NAME " driver: probing com1 \n");
if (com1 = (ioport8_t *)serial_probe_port(parent->ops->absolutize(COM1))) {
printf(NAME " driver: initializing com1 \n");
serial_init_port(com1);
} else {
printf(NAME " driver: com1 is not present \n");
serial_dev_t *dev = serial_alloc_dev();
int i;
for (i = 0; i < serial_phys_addr_cnt; i++) {
serial_init_dev(dev, parent, serial_idx);
if (serial_probe_dev(dev)) {
printf(NAME " driver: initializing %s.\n", dev->name);
serial_init_port(dev->port);
if (EOK != serial_device_register(serial_driver_phone, dev->name, &(dev->handle))) {
printf(NAME ": Unable to register device %s\n", dev->name);
}
list_append(&(dev->link), &serial_devices_list);
dev = serial_alloc_dev();
} else {
printf(NAME " driver: %s is not present \n", dev->name);
}
serial_idx++;
}
printf(NAME " driver: probing com2 \n");
if (com2 = (ioport8_t *)serial_probe_port(parent->ops->absolutize(COM2))) {
printf(NAME " driver: initializing com2 \n");
serial_init_port(com2);
}
else {
printf(NAME " driver: com2 is not present \n");
}
serial_delete_dev(dev);
}
 
// returns virtual address of the serial port, if the serial port is present at this physical address, NULL otherwise
static void * serial_probe_port(void *phys_addr)
static ioport8_t * serial_probe_port(void *phys_addr)
{
ioport8_t *port_addr = NULL;
125,3 → 204,156
return port_addr;
}
 
 
static void serial_putchar(serial_dev_t *dev, ipc_callid_t rid, ipc_call_t *request)
{
int c = IPC_GET_ARG1(*request);
serial_write_8(dev->port, (uint8_t)c);
ipc_answer_0(rid, EOK);
}
 
static void serial_getchar(serial_dev_t *dev, ipc_callid_t rid)
{
uint8_t c = serial_read_8(dev->port);
ipc_answer_1(rid, EOK, c);
}
 
static serial_dev_t * serial_handle_to_dev(int handle) {
futex_down(&serial_futex);
link_t *item = serial_devices_list.next;
serial_dev_t *dev = NULL;
while (item != &serial_devices_list) {
dev = list_get_instance(item, serial_dev_t, link);
if (dev->handle == handle) {
futex_up(&serial_futex);
return dev;
}
item = item->next;
}
futex_up(&serial_futex);
return NULL;
}
 
 
/** Handle one connection to the driver.
*
* @param iid Hash of the request that opened the connection.
* @param icall Call data of the request that opened the connection.
*/
static void serial_client_conn(ipc_callid_t iid, ipc_call_t *icall)
{
/*
* Answer the first IPC_M_CONNECT_ME_TO call and remember the handle of the device to which the client connected.
*/
int handle = IPC_GET_ARG1(*icall);
serial_dev_t *dev = serial_handle_to_dev(handle);
if (dev == NULL) {
ipc_answer_0(iid, ENOENT);
return;
}
if (dev->client_connected) {
ipc_answer_0(iid, ELIMIT);
return;
}
dev->client_connected = true;
ipc_answer_0(iid, EOK);
while (1) {
ipc_callid_t callid;
ipc_call_t call;
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
/*
* The other side has hung up.
* Answer the message and exit the fibril.
*/
ipc_answer_0(callid, EOK);
dev->client_connected = false;
return;
break;
case SERIAL_GETCHAR:
serial_getchar(dev, callid);
break;
case SERIAL_PUTCHAR:
serial_putchar(dev, callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
}
}
}
 
 
/**
* Register the driver with the given name and return its newly created phone.
*/
static int serial_driver_register(char *name)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
int phone;
ipcarg_t callback_phonehash;
 
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
 
while (phone < 0) {
usleep(10000);
phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_DRIVER, 0);
}
req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(phone, (char *) name, str_length(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
return -1;
}
 
async_set_client_connection(serial_client_conn); // set callback function which will serve client connections
 
ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
async_wait_for(req, &retval);
 
return phone;
}
 
static int serial_device_register(int driver_phone, char *name, int *handle)
{
ipcarg_t retval;
aid_t req;
ipc_call_t answer;
 
req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer);
 
retval = ipc_data_write_start(driver_phone, (char *) name, str_length(name) + 1);
 
if (retval != EOK) {
async_wait_for(req, NULL);
return retval;
}
 
async_wait_for(req, &retval);
 
if (handle != NULL)
*handle = -1;
if (EOK == retval) {
if (NULL != handle)
*handle = (int) IPC_GET_ARG1(answer);
}
return retval;
}
/branches/dd/uspace/srv/pci/main.c
1,5 → 1,6
#include <stdio.h>
#include <stdlib.h>
#include <async.h>
 
#include "intel_piix3.h"
#include "pci.h"
26,8 → 27,11
// pci-to-isa bridge device
intel_piix3_init();
// TODO: write driver of some device (serial port) and initialize it here
// serial port driver
serial_init();
printf("PCI + ISA + serial: Accepting connections\n");
async_manager();
return 0;
}
/branches/dd/uspace/Makefile
52,6 → 52,7
srv/vfs \
srv/devmap \
app/tetris \
app/shutters \
app/tester \
app/trace \
app/klog \
/branches/dd/boot/arch/ia32/Makefile.inc
60,7 → 60,8
$(USPACEDIR)/app/trace/trace \
$(USPACEDIR)/app/klog/klog \
$(USPACEDIR)/app/bdsh/bdsh \
$(USPACEDIR)/app/lspci/lspci
$(USPACEDIR)/app/lspci/lspci \
$(USPACEDIR)/app/shutters/shutters
 
build: $(BASE)/image.iso