/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; |
} |
} |
} |