Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4666 → Rev 4667

/branches/dd/uspace/srv/pci/serial.c
0,0 → 1,127
#include <unistd.h>
#include <ddi.h>
#include <libarch/ddi.h>
#include <stdio.h>
 
#include "isa.h"
#include "serial.h"
 
#define NAME "serial"
 
#define REG_COUNT 7
#define COM1 0x3F8
#define COM2 0x2F8
 
static ioport8_t *com1 = 0, *com2 = 0;
 
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);
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 isa_drv_ops_t serial_isa_ops = {
.probe = serial_probe
};
 
static isa_drv_t serial_isa_drv = {
.name = NAME,
.ops = &serial_isa_ops
};
 
int serial_init()
{
// TODO: register this driver by generic isa bus driver
isa_register_driver(&serial_isa_drv);
return 1;
}
 
static bool serial_received(ioport8_t *port)
{
return (pio_read_8(port + 5) & 1) != 0;
}
 
static uint8_t serial_read_8(ioport8_t *port)
{
while (!serial_received(port))
;
 
uint8_t c = pio_read_8(port);
return c;
}
 
static bool is_transmit_empty(ioport8_t *port)
{
return (pio_read_8(port + 5) & 0x20) != 0;
}
 
static void serial_write_8(ioport8_t *port, uint8_t c)
{
while (!is_transmit_empty(port))
;
pio_write_8(port, c);
}
 
static void serial_init_port(ioport8_t *port)
{
pio_write_8(port + 1, 0x00); // Disable all interrupts
pio_write_8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
pio_write_8(port + 0, 0x60); // Set divisor to 96 (lo byte) 1200 baud
pio_write_8(port + 1, 0x00); // (hi byte)
pio_write_8(port + 3, 0x07); // 8 bits, no parity, two stop bits
pio_write_8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
pio_write_8(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
}
 
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");
}
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");
}
}
 
// 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)
{
ioport8_t *port_addr = NULL;
if (pio_enable(phys_addr, REG_COUNT, (void **)(&port_addr))) { // Gain control over port's registers.
printf(NAME ": Error - cannot gain the port %lx.\n", phys_addr);
return NULL;
}
uint8_t olddata;
olddata = pio_read_8(port_addr + 4);
pio_write_8(port_addr + 4, 0x10);
if ((pio_read_8(port_addr + 6) & 0xf0)) {
return NULL;
}
pio_write_8(port_addr + 4, 0x1f);
if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0) {
return 0;
}
pio_write_8(port_addr + 4, olddata);
return port_addr;
}
/branches/dd/uspace/srv/pci/pci.h
1,7 → 1,6
#ifndef PCI_H
#define PCI_H
 
//#include <arch/types.h>
#include <adt/list.h>
#include <stdio.h>
#include <stdlib.h>
18,6 → 17,7
typedef struct pci_drv_ops pci_drv_ops_t;
 
struct pci_drv {
const char *name;
link_t link;
int vendor_id;
int device_id;
/branches/dd/uspace/srv/pci/isa.h
0,0 → 1,60
#ifndef ISA_H
#define ISA_H
 
#include <adt/list.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int isa_bus_init();
 
struct bridge_to_isa;
struct bridge_to_isa_ops;
struct isa_drv_ops;
struct isa_drv;
 
typedef struct bridge_to_isa bridge_to_isa_t;
typedef struct bridge_to_isa_ops bridge_to_isa_ops_t;
typedef struct isa_drv_ops isa_drv_ops_t;
typedef struct isa_drv isa_drv_t;
 
 
struct isa_drv_ops {
void (*probe)(bridge_to_isa_t *parent);
};
 
struct isa_drv {
const char *name;
link_t link;
isa_drv_ops_t *ops;
};
 
struct bridge_to_isa {
link_t link;
void *data;
bridge_to_isa_ops_t *ops;
};
 
struct bridge_to_isa_ops {
void * (*absolutize)(void *phys_addr);
};
 
static inline bridge_to_isa_t * isa_alloc_bridge()
{
bridge_to_isa_t *bridge = (bridge_to_isa_t *)malloc(sizeof(bridge_to_isa_t));
link_initialize(&bridge->link);
bridge->data = NULL;
bridge->ops = NULL;
return bridge;
}
 
static inline void isa_init_bridge(bridge_to_isa_t *bridge, bridge_to_isa_ops_t *ops, void *data)
{
bridge->data = data;
bridge->ops = ops;
}
 
void isa_register_bridge(bridge_to_isa_t *bridge);
void isa_register_driver(isa_drv_t *drv);
 
#endif
/branches/dd/uspace/srv/pci/main.c
1,9 → 1,13
#include <stdio.h>
#include <stdlib.h>
 
#include "intel_piix3.h"
#include "pci.h"
#include "pci_bus.h"
#include "isa.h"
#include "serial.h"
 
 
int main(int argc, char **argv)
{
printf("PCI bus driver\n");
13,7 → 17,17
return 1;
}
// TODO: write driver of some device and initialize it here
if (!isa_bus_init()) {
printf("ISA bus initialization failed.\n");
return 1;
}
// pci-to-isa bridge device
intel_piix3_init();
// TODO: write driver of some device (serial port) and initialize it here
serial_init();
return 0;
}
/branches/dd/uspace/srv/pci/serial.h
0,0 → 1,8
#ifndef SERIAL_H
#define SERIAL_H
 
int serial_init();
 
 
#endif
 
/branches/dd/uspace/srv/pci/intel_piix3.c
0,0 → 1,54
#include "pci.h"
#include "intel_piix3.h"
#include "isa.h"
 
#define NAME "Intel PIIX3"
 
 
static int piix3_add_device(pci_dev_t *dev);
static void * piix3_absolutize(void *phys_addr);
 
static pci_drv_ops_t piix3_pci_ops = {
.add_device = piix3_add_device
};
 
static pci_drv_t piix3_drv = {
.name = NAME,
.link = { NULL, NULL },
.vendor_id = 0x8086,
.device_id = 0x7010,
.ops = &piix3_pci_ops
};
 
static bridge_to_isa_ops_t piix3_bridge_ops = {
.absolutize = piix3_absolutize
};
 
int intel_piix3_init()
{
pci_driver_register(&piix3_drv);
return 0;
}
 
 
static int piix3_add_device(pci_dev_t *dev)
{
printf(NAME " driver: new device %3d : %2d : %2d was added.\n", dev->bus->num, dev->dev, dev->fn);
// register this device as a pci-to-isa bridge by the isa bus driver
bridge_to_isa_t *bridge_dev = isa_alloc_bridge();
isa_init_bridge(bridge_dev, &piix3_bridge_ops, dev);
isa_register_bridge(bridge_dev);
return 1;
}
 
// this might be more usable at different architectures
static void * piix3_absolutize(void *phys_addr)
{
return phys_addr;
}
 
 
 
 
/branches/dd/uspace/srv/pci/pci.c
6,6 → 6,8
#include "pci_regs.h"
#include "pci_conf.h"
 
#define NAME "PCI"
 
LIST_INITIALIZE(devices_list);
LIST_INITIALIZE(buses_list);
LIST_INITIALIZE(drivers_list);
45,13 → 47,13
}
header_type = header_type & 0x7F; // clear the multifunction bit
printf("PCI: adding new device %d : %d : %d", dev->bus->num, dnum, fnum);
printf(NAME ": adding new device %3d : %2d : %2d", dev->bus->num, dnum, fnum);
printf(" - vendor = 0x%04X, device = 0x%04X.\n", dev->vendor_id, dev->device_id);
pci_device_register(dev);
if (header_type == PCI_HEADER_TYPE_BRIDGE || header_type == PCI_HEADER_TYPE_CARDBUS ) {
bus_num = pci_conf_read_8(dev, PCI_BRIDGE_SEC_BUS_NUM);
printf("PCI: device is pci-to-pci bridge, secondary bus number = %d.\n", bus_num);
printf(NAME ": device is pci-to-pci bridge, secondary bus number = %d.\n", bus_num);
if(bus_num > bus->num) {
child_bus = pci_alloc_bus();
pci_init_bus(child_bus, bus, bus_num);
75,8 → 77,10
static int pci_pass_dev(pci_drv_t *drv, pci_dev_t *dev)
{
assert(dev->driver == NULL);
assert(drv->name != NULL);
if (drv->ops->add_device(dev)) {
printf(NAME ": passing device to driver '%s'.\n", drv->name);
if (drv->ops->add_device != NULL && drv->ops->add_device(dev)) {
dev->driver = drv;
return 1;
}
95,7 → 99,7
while (item != &drivers_list) {
drv = list_get_instance(item, pci_drv_t, link);
if (pci_match(drv, dev) && pci_pass_dev(drv, dev)) {
break;
return;
}
item = item->next;
}
109,6 → 113,8
link_t *item = devices_list.next;
pci_dev_t *dev = NULL;
printf(NAME ": looking up devices for a newly added driver '%s'.\n", drv->name);
while (item != &devices_list) {
dev = list_get_instance(item, pci_dev_t, link);
if (dev->driver == NULL && pci_match(drv, dev)) {
120,7 → 126,7
 
static int pci_match(pci_drv_t *drv, pci_dev_t *dev)
{
return drv->vendor_id == dev->vendor_id && drv->device_id == dev->vendor_id;
return drv->vendor_id == dev->vendor_id && drv->device_id == dev->device_id;
}
 
void pci_bus_register(pci_bus_t *bus)
147,8 → 153,11
}
 
void pci_driver_register(pci_drv_t *drv)
{
{
assert(drv->name != NULL);
futex_down(&pci_bus_futex);
printf(NAME ": registering new driver '%s'.\n", drv->name);
list_append(&(drv->link), &drivers_list);
// try to find compatible devices
/branches/dd/uspace/srv/pci/Makefile
44,7 → 44,10
OUTPUT = pci
SOURCES = \
main.c \
pci.c
pci.c \
intel_piix3.c \
isa.c \
serial.c
 
ifeq ($(PROCESSOR), us)
SOURCES += psycho.c
/branches/dd/uspace/srv/pci/intel_piix3.h
0,0 → 1,8
#ifndef INTEL_PIIX3
#define INTEL_PIIX3
 
int intel_piix3_init();
 
 
 
#endif
/branches/dd/uspace/srv/pci/isa.c
0,0 → 1,79
#include <futex.h>
#include <assert.h>
 
#include "isa.h"
 
LIST_INITIALIZE(isa_bridges_list);
LIST_INITIALIZE(isa_drivers_list);
 
static atomic_t isa_bus_futex = FUTEX_INITIALIZER;
 
static void isa_probe_all(bridge_to_isa_t *bridge);
static void isa_drv_probe(isa_drv_t *drv);
 
int isa_bus_init()
{
return 1;
}
 
void isa_register_bridge(bridge_to_isa_t *bridge)
{
futex_down(&isa_bus_futex);
printf("ISA: registering new sth-to-isa bridge.\n");
// add bridge to the list
list_append(&(bridge->link), &isa_bridges_list);
// call probe function of all registered drivers of isa devices
isa_probe_all(bridge);
futex_up(&isa_bus_futex);
}
 
void isa_register_driver(isa_drv_t *drv)
{
assert(drv->name != NULL);
futex_down(&isa_bus_futex);
printf("ISA: registering new driver '%s'.\n", drv->name);
// add bridge to the list
list_append(&(drv->link), &isa_drivers_list);
// call driver's probe function on all registered bridges
isa_drv_probe(drv);
futex_up(&isa_bus_futex);
}
 
static void isa_probe_all(bridge_to_isa_t *bridge)
{
link_t *item = isa_drivers_list.next;
isa_drv_t *drv = NULL;
while (item != &isa_drivers_list) {
drv = list_get_instance(item, isa_drv_t, link);
if (drv->ops != NULL && drv->ops->probe != NULL) {
drv->ops->probe(bridge);
}
item = item->next;
}
}
 
static void isa_drv_probe(isa_drv_t *drv)
{
link_t *item = isa_bridges_list.next;
bridge_to_isa_t *bridge = NULL;
if (drv->ops != NULL && drv->ops->probe != NULL) {
while (item != &isa_bridges_list) {
bridge = list_get_instance(item, bridge_to_isa_t, link);
{
drv->ops->probe(bridge);
}
item = item->next;
}
}
}