From 4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 27 Mar 2012 11:51:08 +0200 Subject: reorganize file structure to match the upstream requirements --- pintos-progos/devices/block.c | 223 ---------------- pintos-progos/devices/block.h | 74 ------ pintos-progos/devices/ide.c | 527 -------------------------------------- pintos-progos/devices/ide.h | 6 - pintos-progos/devices/input.c | 52 ---- pintos-progos/devices/input.h | 12 - pintos-progos/devices/intq.c | 114 --------- pintos-progos/devices/intq.h | 43 ---- pintos-progos/devices/kbd.c | 213 --------------- pintos-progos/devices/kbd.h | 9 - pintos-progos/devices/partition.c | 324 ----------------------- pintos-progos/devices/partition.h | 8 - pintos-progos/devices/pit.c | 83 ------ pintos-progos/devices/pit.h | 8 - pintos-progos/devices/rtc.c | 112 -------- pintos-progos/devices/rtc.h | 8 - pintos-progos/devices/serial.c | 228 ----------------- pintos-progos/devices/serial.h | 11 - pintos-progos/devices/shutdown.c | 131 ---------- pintos-progos/devices/shutdown.h | 19 -- pintos-progos/devices/speaker.c | 68 ----- pintos-progos/devices/speaker.h | 8 - pintos-progos/devices/timer.c | 297 --------------------- pintos-progos/devices/timer.h | 29 --- pintos-progos/devices/vga.c | 172 ------------- pintos-progos/devices/vga.h | 6 - 26 files changed, 2785 deletions(-) delete mode 100644 pintos-progos/devices/block.c delete mode 100644 pintos-progos/devices/block.h delete mode 100644 pintos-progos/devices/ide.c delete mode 100644 pintos-progos/devices/ide.h delete mode 100644 pintos-progos/devices/input.c delete mode 100644 pintos-progos/devices/input.h delete mode 100644 pintos-progos/devices/intq.c delete mode 100644 pintos-progos/devices/intq.h delete mode 100644 pintos-progos/devices/kbd.c delete mode 100644 pintos-progos/devices/kbd.h delete mode 100644 pintos-progos/devices/partition.c delete mode 100644 pintos-progos/devices/partition.h delete mode 100644 pintos-progos/devices/pit.c delete mode 100644 pintos-progos/devices/pit.h delete mode 100644 pintos-progos/devices/rtc.c delete mode 100644 pintos-progos/devices/rtc.h delete mode 100644 pintos-progos/devices/serial.c delete mode 100644 pintos-progos/devices/serial.h delete mode 100644 pintos-progos/devices/shutdown.c delete mode 100644 pintos-progos/devices/shutdown.h delete mode 100644 pintos-progos/devices/speaker.c delete mode 100644 pintos-progos/devices/speaker.h delete mode 100644 pintos-progos/devices/timer.c delete mode 100644 pintos-progos/devices/timer.h delete mode 100644 pintos-progos/devices/vga.c delete mode 100644 pintos-progos/devices/vga.h (limited to 'pintos-progos/devices') diff --git a/pintos-progos/devices/block.c b/pintos-progos/devices/block.c deleted file mode 100644 index a3acec1..0000000 --- a/pintos-progos/devices/block.c +++ /dev/null @@ -1,223 +0,0 @@ -#include "devices/block.h" -#include -#include -#include -#include "devices/ide.h" -#include "threads/malloc.h" - -/* A block device. */ -struct block - { - struct list_elem list_elem; /* Element in all_blocks. */ - - char name[16]; /* Block device name. */ - enum block_type type; /* Type of block device. */ - block_sector_t size; /* Size in sectors. */ - - const struct block_operations *ops; /* Driver operations. */ - void *aux; /* Extra data owned by driver. */ - - unsigned long long read_cnt; /* Number of sectors read. */ - unsigned long long write_cnt; /* Number of sectors written. */ - }; - -/* List of all block devices. */ -static struct list all_blocks = LIST_INITIALIZER (all_blocks); - -/* The block block assigned to each Pintos role. */ -static struct block *block_by_role[BLOCK_ROLE_CNT]; - -static struct block *list_elem_to_block (struct list_elem *); - -/* Returns a human-readable name for the given block device - TYPE. */ -const char * -block_type_name (enum block_type type) -{ - static const char *block_type_names[BLOCK_CNT] = - { - "kernel", - "filesys", - "scratch", - "swap", - "raw", - "foreign", - }; - - ASSERT (type < BLOCK_CNT); - return block_type_names[type]; -} - -/* Returns the block device fulfilling the given ROLE, or a null - pointer if no block device has been assigned that role. */ -struct block * -block_get_role (enum block_type role) -{ - ASSERT (role < BLOCK_ROLE_CNT); - return block_by_role[role]; -} - -/* Assigns BLOCK the given ROLE. */ -void -block_set_role (enum block_type role, struct block *block) -{ - ASSERT (role < BLOCK_ROLE_CNT); - block_by_role[role] = block; -} - -/* Returns the first block device in kernel probe order, or a - null pointer if no block devices are registered. */ -struct block * -block_first (void) -{ - return list_elem_to_block (list_begin (&all_blocks)); -} - -/* Returns the block device following BLOCK in kernel probe - order, or a null pointer if BLOCK is the last block device. */ -struct block * -block_next (struct block *block) -{ - return list_elem_to_block (list_next (&block->list_elem)); -} - -/* Returns the block device with the given NAME, or a null - pointer if no block device has that name. */ -struct block * -block_get_by_name (const char *name) -{ - struct list_elem *e; - - for (e = list_begin (&all_blocks); e != list_end (&all_blocks); - e = list_next (e)) - { - struct block *block = list_entry (e, struct block, list_elem); - if (!strcmp (name, block->name)) - return block; - } - - return NULL; -} - -/* Verifies that SECTOR is a valid offset within BLOCK. - Panics if not. */ -static void -check_sector (struct block *block, block_sector_t sector) -{ - if (sector >= block->size) - { - /* We do not use ASSERT because we want to panic here - regardless of whether NDEBUG is defined. */ - PANIC ("Access past end of device %s (sector=%"PRDSNu", " - "size=%"PRDSNu")\n", block_name (block), sector, block->size); - } -} - -/* Reads sector SECTOR from BLOCK into BUFFER, which must - have room for BLOCK_SECTOR_SIZE bytes. - Internally synchronizes accesses to block devices, so external - per-block device locking is unneeded. */ -void -block_read (struct block *block, block_sector_t sector, void *buffer) -{ - check_sector (block, sector); - block->ops->read (block->aux, sector, buffer); - block->read_cnt++; -} - -/* Write sector SECTOR to BLOCK from BUFFER, which must contain - BLOCK_SECTOR_SIZE bytes. Returns after the block device has - acknowledged receiving the data. - Internally synchronizes accesses to block devices, so external - per-block device locking is unneeded. */ -void -block_write (struct block *block, block_sector_t sector, const void *buffer) -{ - check_sector (block, sector); - ASSERT (block->type != BLOCK_FOREIGN); - block->ops->write (block->aux, sector, buffer); - block->write_cnt++; -} - -/* Returns the number of sectors in BLOCK. */ -block_sector_t -block_size (struct block *block) -{ - return block->size; -} - -/* Returns BLOCK's name (e.g. "hda"). */ -const char * -block_name (struct block *block) -{ - return block->name; -} - -/* Returns BLOCK's type. */ -enum block_type -block_type (struct block *block) -{ - return block->type; -} - -/* Prints statistics for each block device used for a Pintos role. */ -void -block_print_stats (void) -{ - int i; - - for (i = 0; i < BLOCK_ROLE_CNT; i++) - { - struct block *block = block_by_role[i]; - if (block != NULL) - { - printf ("%s (%s): %llu reads, %llu writes\n", - block->name, block_type_name (block->type), - block->read_cnt, block->write_cnt); - } - } -} - -/* Registers a new block device with the given NAME. If - EXTRA_INFO is non-null, it is printed as part of a user - message. The block device's SIZE in sectors and its TYPE must - be provided, as well as the it operation functions OPS, which - will be passed AUX in each function call. */ -struct block * -block_register (const char *name, enum block_type type, - const char *extra_info, block_sector_t size, - const struct block_operations *ops, void *aux) -{ - struct block *block = malloc (sizeof *block); - if (block == NULL) - PANIC ("Failed to allocate memory for block device descriptor"); - - list_push_back (&all_blocks, &block->list_elem); - strlcpy (block->name, name, sizeof block->name); - block->type = type; - block->size = size; - block->ops = ops; - block->aux = aux; - block->read_cnt = 0; - block->write_cnt = 0; - - printf ("%s: %'"PRDSNu" sectors (", block->name, block->size); - print_human_readable_size ((uint64_t) block->size * BLOCK_SECTOR_SIZE); - printf (")"); - if (extra_info != NULL) - printf (", %s", extra_info); - printf ("\n"); - - return block; -} - -/* Returns the block device corresponding to LIST_ELEM, or a null - pointer if LIST_ELEM is the list end of all_blocks. */ -static struct block * -list_elem_to_block (struct list_elem *list_elem) -{ - return (list_elem != list_end (&all_blocks) - ? list_entry (list_elem, struct block, list_elem) - : NULL); -} - diff --git a/pintos-progos/devices/block.h b/pintos-progos/devices/block.h deleted file mode 100644 index 21732d6..0000000 --- a/pintos-progos/devices/block.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef DEVICES_BLOCK_H -#define DEVICES_BLOCK_H - -#include -#include - -/* Size of a block device sector in bytes. - All IDE disks use this sector size, as do most USB and SCSI - disks. It's not worth it to try to cater to other sector - sizes in Pintos (yet). */ -#define BLOCK_SECTOR_SIZE 512 - -/* Index of a block device sector. - Good enough for devices up to 2 TB. */ -typedef uint32_t block_sector_t; - -/* Format specifier for printf(), e.g.: - printf ("sector=%"PRDSNu"\n", sector); */ -#define PRDSNu PRIu32 - -/* Higher-level interface for file systems, etc. */ - -struct block; - -/* Type of a block device. */ -enum block_type - { - /* Block device types that play a role in Pintos. */ - BLOCK_KERNEL, /* Pintos OS kernel. */ - BLOCK_FILESYS, /* File system. */ - BLOCK_SCRATCH, /* Scratch. */ - BLOCK_SWAP, /* Swap. */ - BLOCK_ROLE_CNT, - - /* Other kinds of block devices that Pintos may see but does - not interact with. */ - BLOCK_RAW = BLOCK_ROLE_CNT, /* "Raw" device with unidentified contents. */ - BLOCK_FOREIGN, /* Owned by non-Pintos operating system. */ - BLOCK_CNT /* Number of Pintos block types. */ - }; - -const char *block_type_name (enum block_type); - -/* Finding block devices. */ -struct block *block_get_role (enum block_type); -void block_set_role (enum block_type, struct block *); -struct block *block_get_by_name (const char *name); - -struct block *block_first (void); -struct block *block_next (struct block *); - -/* Block device operations. */ -block_sector_t block_size (struct block *); -void block_read (struct block *, block_sector_t, void *); -void block_write (struct block *, block_sector_t, const void *); -const char *block_name (struct block *); -enum block_type block_type (struct block *); - -/* Statistics. */ -void block_print_stats (void); - -/* Lower-level interface to block device drivers. */ - -struct block_operations - { - void (*read) (void *aux, block_sector_t, void *buffer); - void (*write) (void *aux, block_sector_t, const void *buffer); - }; - -struct block *block_register (const char *name, enum block_type, - const char *extra_info, block_sector_t size, - const struct block_operations *, void *aux); - -#endif /* devices/block.h */ diff --git a/pintos-progos/devices/ide.c b/pintos-progos/devices/ide.c deleted file mode 100644 index 2cc0292..0000000 --- a/pintos-progos/devices/ide.c +++ /dev/null @@ -1,527 +0,0 @@ -#include "devices/ide.h" -#include -#include -#include -#include -#include "devices/block.h" -#include "devices/partition.h" -#include "devices/timer.h" -#include "threads/io.h" -#include "threads/interrupt.h" -#include "threads/synch.h" - -/* The code in this file is an interface to an ATA (IDE) - controller. It attempts to comply to [ATA-3]. */ - -/* ATA command block port addresses. */ -#define reg_data(CHANNEL) ((CHANNEL)->reg_base + 0) /* Data. */ -#define reg_error(CHANNEL) ((CHANNEL)->reg_base + 1) /* Error. */ -#define reg_nsect(CHANNEL) ((CHANNEL)->reg_base + 2) /* Sector Count. */ -#define reg_lbal(CHANNEL) ((CHANNEL)->reg_base + 3) /* LBA 0:7. */ -#define reg_lbam(CHANNEL) ((CHANNEL)->reg_base + 4) /* LBA 15:8. */ -#define reg_lbah(CHANNEL) ((CHANNEL)->reg_base + 5) /* LBA 23:16. */ -#define reg_device(CHANNEL) ((CHANNEL)->reg_base + 6) /* Device/LBA 27:24. */ -#define reg_status(CHANNEL) ((CHANNEL)->reg_base + 7) /* Status (r/o). */ -#define reg_command(CHANNEL) reg_status (CHANNEL) /* Command (w/o). */ - -/* ATA control block port addresses. - (If we supported non-legacy ATA controllers this would not be - flexible enough, but it's fine for what we do.) */ -#define reg_ctl(CHANNEL) ((CHANNEL)->reg_base + 0x206) /* Control (w/o). */ -#define reg_alt_status(CHANNEL) reg_ctl (CHANNEL) /* Alt Status (r/o). */ - -/* Alternate Status Register bits. */ -#define STA_BSY 0x80 /* Busy. */ -#define STA_DRDY 0x40 /* Device Ready. */ -#define STA_DRQ 0x08 /* Data Request. */ - -/* Control Register bits. */ -#define CTL_SRST 0x04 /* Software Reset. */ - -/* Device Register bits. */ -#define DEV_MBS 0xa0 /* Must be set. */ -#define DEV_LBA 0x40 /* Linear based addressing. */ -#define DEV_DEV 0x10 /* Select device: 0=master, 1=slave. */ - -/* Commands. - Many more are defined but this is the small subset that we - use. */ -#define CMD_IDENTIFY_DEVICE 0xec /* IDENTIFY DEVICE. */ -#define CMD_READ_SECTOR_RETRY 0x20 /* READ SECTOR with retries. */ -#define CMD_WRITE_SECTOR_RETRY 0x30 /* WRITE SECTOR with retries. */ - -/* An ATA device. */ -struct ata_disk - { - char name[8]; /* Name, e.g. "hda". */ - struct channel *channel; /* Channel that disk is attached to. */ - int dev_no; /* Device 0 or 1 for master or slave. */ - bool is_ata; /* Is device an ATA disk? */ - }; - -/* An ATA channel (aka controller). - Each channel can control up to two disks. */ -struct channel - { - char name[8]; /* Name, e.g. "ide0". */ - uint16_t reg_base; /* Base I/O port. */ - uint8_t irq; /* Interrupt in use. */ - - struct lock lock; /* Must acquire to access the controller. */ - bool expecting_interrupt; /* True if an interrupt is expected, false if - any interrupt would be spurious. */ - struct semaphore completion_wait; /* Up'd by interrupt handler. */ - - struct ata_disk devices[2]; /* The devices on this channel. */ - }; - -/* We support the two "legacy" ATA channels found in a standard PC. */ -#define CHANNEL_CNT 2 -static struct channel channels[CHANNEL_CNT]; - -static struct block_operations ide_operations; - -static void reset_channel (struct channel *); -static bool check_device_type (struct ata_disk *); -static void identify_ata_device (struct ata_disk *); - -static void select_sector (struct ata_disk *, block_sector_t); -static void issue_pio_command (struct channel *, uint8_t command); -static void input_sector (struct channel *, void *); -static void output_sector (struct channel *, const void *); - -static void wait_until_idle (const struct ata_disk *); -static bool wait_while_busy (const struct ata_disk *); -static void select_device (const struct ata_disk *); -static void select_device_wait (const struct ata_disk *); - -static void interrupt_handler (struct intr_frame *); - -/* Initialize the disk subsystem and detect disks. */ -void -ide_init (void) -{ - size_t chan_no; - - for (chan_no = 0; chan_no < CHANNEL_CNT; chan_no++) - { - struct channel *c = &channels[chan_no]; - int dev_no; - - /* Initialize channel. */ - snprintf (c->name, sizeof c->name, "ide%zu", chan_no); - switch (chan_no) - { - case 0: - c->reg_base = 0x1f0; - c->irq = 14 + 0x20; - break; - case 1: - c->reg_base = 0x170; - c->irq = 15 + 0x20; - break; - default: - NOT_REACHED (); - } - lock_init (&c->lock); - c->expecting_interrupt = false; - sema_init (&c->completion_wait, 0); - - /* Initialize devices. */ - for (dev_no = 0; dev_no < 2; dev_no++) - { - struct ata_disk *d = &c->devices[dev_no]; - snprintf (d->name, sizeof d->name, - "hd%c", 'a' + chan_no * 2 + dev_no); - d->channel = c; - d->dev_no = dev_no; - d->is_ata = false; - } - - /* Register interrupt handler. */ - intr_register_ext (c->irq, interrupt_handler, c->name); - - /* Reset hardware. */ - reset_channel (c); - - /* Distinguish ATA hard disks from other devices. */ - if (check_device_type (&c->devices[0])) - check_device_type (&c->devices[1]); - - /* Read hard disk identity information. */ - for (dev_no = 0; dev_no < 2; dev_no++) - if (c->devices[dev_no].is_ata) - identify_ata_device (&c->devices[dev_no]); - } -} - -/* Disk detection and identification. */ - -static char *descramble_ata_string (char *, int size); - -/* Resets an ATA channel and waits for any devices present on it - to finish the reset. */ -static void -reset_channel (struct channel *c) -{ - bool present[2]; - int dev_no; - - /* The ATA reset sequence depends on which devices are present, - so we start by detecting device presence. */ - for (dev_no = 0; dev_no < 2; dev_no++) - { - struct ata_disk *d = &c->devices[dev_no]; - - select_device (d); - - outb (reg_nsect (c), 0x55); - outb (reg_lbal (c), 0xaa); - - outb (reg_nsect (c), 0xaa); - outb (reg_lbal (c), 0x55); - - outb (reg_nsect (c), 0x55); - outb (reg_lbal (c), 0xaa); - - present[dev_no] = (inb (reg_nsect (c)) == 0x55 - && inb (reg_lbal (c)) == 0xaa); - } - - /* Issue soft reset sequence, which selects device 0 as a side effect. - Also enable interrupts. */ - outb (reg_ctl (c), 0); - timer_usleep (10); - outb (reg_ctl (c), CTL_SRST); - timer_usleep (10); - outb (reg_ctl (c), 0); - - timer_msleep (150); - - /* Wait for device 0 to clear BSY. */ - if (present[0]) - { - select_device (&c->devices[0]); - wait_while_busy (&c->devices[0]); - } - - /* Wait for device 1 to clear BSY. */ - if (present[1]) - { - int i; - - select_device (&c->devices[1]); - for (i = 0; i < 3000; i++) - { - if (inb (reg_nsect (c)) == 1 && inb (reg_lbal (c)) == 1) - break; - timer_msleep (10); - } - wait_while_busy (&c->devices[1]); - } -} - -/* Checks whether device D is an ATA disk and sets D's is_ata - member appropriately. If D is device 0 (master), returns true - if it's possible that a slave (device 1) exists on this - channel. If D is device 1 (slave), the return value is not - meaningful. */ -static bool -check_device_type (struct ata_disk *d) -{ - struct channel *c = d->channel; - uint8_t error, lbam, lbah, status; - - select_device (d); - - error = inb (reg_error (c)); - lbam = inb (reg_lbam (c)); - lbah = inb (reg_lbah (c)); - status = inb (reg_status (c)); - - if ((error != 1 && (error != 0x81 || d->dev_no == 1)) - || (status & STA_DRDY) == 0 - || (status & STA_BSY) != 0) - { - d->is_ata = false; - return error != 0x81; - } - else - { - d->is_ata = (lbam == 0 && lbah == 0) || (lbam == 0x3c && lbah == 0xc3); - return true; - } -} - -/* Sends an IDENTIFY DEVICE command to disk D and reads the - response. Registers the disk with the block device - layer. */ -static void -identify_ata_device (struct ata_disk *d) -{ - struct channel *c = d->channel; - char id[BLOCK_SECTOR_SIZE]; - block_sector_t capacity; - char *model, *serial; - char extra_info[128]; - struct block *block; - - ASSERT (d->is_ata); - - /* Send the IDENTIFY DEVICE command, wait for an interrupt - indicating the device's response is ready, and read the data - into our buffer. */ - select_device_wait (d); - issue_pio_command (c, CMD_IDENTIFY_DEVICE); - sema_down (&c->completion_wait); - if (!wait_while_busy (d)) - { - d->is_ata = false; - return; - } - input_sector (c, id); - - /* Calculate capacity. - Read model name and serial number. */ - capacity = *(uint32_t *) &id[60 * 2]; - model = descramble_ata_string (&id[10 * 2], 20); - serial = descramble_ata_string (&id[27 * 2], 40); - snprintf (extra_info, sizeof extra_info, - "model \"%s\", serial \"%s\"", model, serial); - - /* Disable access to IDE disks over 1 GB, which are likely - physical IDE disks rather than virtual ones. If we don't - allow access to those, we're less likely to scribble on - someone's important data. You can disable this check by - hand if you really want to do so. */ - if (capacity >= 1024 * 1024 * 1024 / BLOCK_SECTOR_SIZE) - { - printf ("%s: ignoring ", d->name); - print_human_readable_size (capacity * 512); - printf ("disk for safety\n"); - d->is_ata = false; - return; - } - - /* Register. */ - block = block_register (d->name, BLOCK_RAW, extra_info, capacity, - &ide_operations, d); - partition_scan (block); -} - -/* Translates STRING, which consists of SIZE bytes in a funky - format, into a null-terminated string in-place. Drops - trailing whitespace and null bytes. Returns STRING. */ -static char * -descramble_ata_string (char *string, int size) -{ - int i; - - /* Swap all pairs of bytes. */ - for (i = 0; i + 1 < size; i += 2) - { - char tmp = string[i]; - string[i] = string[i + 1]; - string[i + 1] = tmp; - } - - /* Find the last non-white, non-null character. */ - for (size--; size > 0; size--) - { - int c = string[size - 1]; - if (c != '\0' && !isspace (c)) - break; - } - string[size] = '\0'; - - return string; -} - -/* Reads sector SEC_NO from disk D into BUFFER, which must have - room for BLOCK_SECTOR_SIZE bytes. - Internally synchronizes accesses to disks, so external - per-disk locking is unneeded. */ -static void -ide_read (void *d_, block_sector_t sec_no, void *buffer) -{ - struct ata_disk *d = d_; - struct channel *c = d->channel; - lock_acquire (&c->lock); - select_sector (d, sec_no); - issue_pio_command (c, CMD_READ_SECTOR_RETRY); - sema_down (&c->completion_wait); - if (!wait_while_busy (d)) - PANIC ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no); - input_sector (c, buffer); - lock_release (&c->lock); -} - -/* Write sector SEC_NO to disk D from BUFFER, which must contain - BLOCK_SECTOR_SIZE bytes. Returns after the disk has - acknowledged receiving the data. - Internally synchronizes accesses to disks, so external - per-disk locking is unneeded. */ -static void -ide_write (void *d_, block_sector_t sec_no, const void *buffer) -{ - struct ata_disk *d = d_; - struct channel *c = d->channel; - lock_acquire (&c->lock); - select_sector (d, sec_no); - issue_pio_command (c, CMD_WRITE_SECTOR_RETRY); - if (!wait_while_busy (d)) - PANIC ("%s: disk write failed, sector=%"PRDSNu, d->name, sec_no); - output_sector (c, buffer); - sema_down (&c->completion_wait); - lock_release (&c->lock); -} - -static struct block_operations ide_operations = - { - ide_read, - ide_write - }; - -/* Selects device D, waiting for it to become ready, and then - writes SEC_NO to the disk's sector selection registers. (We - use LBA mode.) */ -static void -select_sector (struct ata_disk *d, block_sector_t sec_no) -{ - struct channel *c = d->channel; - - ASSERT (sec_no < (1UL << 28)); - - select_device_wait (d); - outb (reg_nsect (c), 1); - outb (reg_lbal (c), sec_no); - outb (reg_lbam (c), sec_no >> 8); - outb (reg_lbah (c), (sec_no >> 16)); - outb (reg_device (c), - DEV_MBS | DEV_LBA | (d->dev_no == 1 ? DEV_DEV : 0) | (sec_no >> 24)); -} - -/* Writes COMMAND to channel C and prepares for receiving a - completion interrupt. */ -static void -issue_pio_command (struct channel *c, uint8_t command) -{ - /* Interrupts must be enabled or our semaphore will never be - up'd by the completion handler. */ - ASSERT (intr_get_level () == INTR_ON); - - c->expecting_interrupt = true; - outb (reg_command (c), command); -} - -/* Reads a sector from channel C's data register in PIO mode into - SECTOR, which must have room for BLOCK_SECTOR_SIZE bytes. */ -static void -input_sector (struct channel *c, void *sector) -{ - insw (reg_data (c), sector, BLOCK_SECTOR_SIZE / 2); -} - -/* Writes SECTOR to channel C's data register in PIO mode. - SECTOR must contain BLOCK_SECTOR_SIZE bytes. */ -static void -output_sector (struct channel *c, const void *sector) -{ - outsw (reg_data (c), sector, BLOCK_SECTOR_SIZE / 2); -} - -/* Low-level ATA primitives. */ - -/* Wait up to 10 seconds for the controller to become idle, that - is, for the BSY and DRQ bits to clear in the status register. - - As a side effect, reading the status register clears any - pending interrupt. */ -static void -wait_until_idle (const struct ata_disk *d) -{ - int i; - - for (i = 0; i < 1000; i++) - { - if ((inb (reg_status (d->channel)) & (STA_BSY | STA_DRQ)) == 0) - return; - timer_usleep (10); - } - - printf ("%s: idle timeout\n", d->name); -} - -/* Wait up to 30 seconds for disk D to clear BSY, - and then return the status of the DRQ bit. - The ATA standards say that a disk may take as long as that to - complete its reset. */ -static bool -wait_while_busy (const struct ata_disk *d) -{ - struct channel *c = d->channel; - int i; - - for (i = 0; i < 3000; i++) - { - if (i == 700) - printf ("%s: busy, waiting...", d->name); - if (!(inb (reg_alt_status (c)) & STA_BSY)) - { - if (i >= 700) - printf ("ok\n"); - return (inb (reg_alt_status (c)) & STA_DRQ) != 0; - } - timer_msleep (10); - } - - printf ("failed\n"); - return false; -} - -/* Program D's channel so that D is now the selected disk. */ -static void -select_device (const struct ata_disk *d) -{ - struct channel *c = d->channel; - uint8_t dev = DEV_MBS; - if (d->dev_no == 1) - dev |= DEV_DEV; - outb (reg_device (c), dev); - inb (reg_alt_status (c)); - timer_nsleep (400); -} - -/* Select disk D in its channel, as select_device(), but wait for - the channel to become idle before and after. */ -static void -select_device_wait (const struct ata_disk *d) -{ - wait_until_idle (d); - select_device (d); - wait_until_idle (d); -} - -/* ATA interrupt handler. */ -static void -interrupt_handler (struct intr_frame *f) -{ - struct channel *c; - - for (c = channels; c < channels + CHANNEL_CNT; c++) - if (f->vec_no == c->irq) - { - if (c->expecting_interrupt) - { - inb (reg_status (c)); /* Acknowledge interrupt. */ - sema_up (&c->completion_wait); /* Wake up waiter. */ - } - else - printf ("%s: unexpected interrupt\n", c->name); - return; - } - - NOT_REACHED (); -} - - diff --git a/pintos-progos/devices/ide.h b/pintos-progos/devices/ide.h deleted file mode 100644 index b35da5e..0000000 --- a/pintos-progos/devices/ide.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DEVICES_IDE_H -#define DEVICES_IDE_H - -void ide_init (void); - -#endif /* devices/ide.h */ diff --git a/pintos-progos/devices/input.c b/pintos-progos/devices/input.c deleted file mode 100644 index 4a12160..0000000 --- a/pintos-progos/devices/input.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "devices/input.h" -#include -#include "devices/intq.h" -#include "devices/serial.h" - -/* Stores keys from the keyboard and serial port. */ -static struct intq buffer; - -/* Initializes the input buffer. */ -void -input_init (void) -{ - intq_init (&buffer); -} - -/* Adds a key to the input buffer. - Interrupts must be off and the buffer must not be full. */ -void -input_putc (uint8_t key) -{ - ASSERT (intr_get_level () == INTR_OFF); - ASSERT (!intq_full (&buffer)); - - intq_putc (&buffer, key); - serial_notify (); -} - -/* Retrieves a key from the input buffer. - If the buffer is empty, waits for a key to be pressed. */ -uint8_t -input_getc (void) -{ - enum intr_level old_level; - uint8_t key; - - old_level = intr_disable (); - key = intq_getc (&buffer); - serial_notify (); - intr_set_level (old_level); - - return key; -} - -/* Returns true if the input buffer is full, - false otherwise. - Interrupts must be off. */ -bool -input_full (void) -{ - ASSERT (intr_get_level () == INTR_OFF); - return intq_full (&buffer); -} diff --git a/pintos-progos/devices/input.h b/pintos-progos/devices/input.h deleted file mode 100644 index a2f50e9..0000000 --- a/pintos-progos/devices/input.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef DEVICES_INPUT_H -#define DEVICES_INPUT_H - -#include -#include - -void input_init (void); -void input_putc (uint8_t); -uint8_t input_getc (void); -bool input_full (void); - -#endif /* devices/input.h */ diff --git a/pintos-progos/devices/intq.c b/pintos-progos/devices/intq.c deleted file mode 100644 index 40b23ae..0000000 --- a/pintos-progos/devices/intq.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "devices/intq.h" -#include -#include "threads/thread.h" - -static int next (int pos); -static void wait (struct intq *q, struct thread **waiter); -static void signal (struct intq *q, struct thread **waiter); - -/* Initializes interrupt queue Q. */ -void -intq_init (struct intq *q) -{ - lock_init (&q->lock); - q->not_full = q->not_empty = NULL; - q->head = q->tail = 0; -} - -/* Returns true if Q is empty, false otherwise. */ -bool -intq_empty (const struct intq *q) -{ - ASSERT (intr_get_level () == INTR_OFF); - return q->head == q->tail; -} - -/* Returns true if Q is full, false otherwise. */ -bool -intq_full (const struct intq *q) -{ - ASSERT (intr_get_level () == INTR_OFF); - return next (q->head) == q->tail; -} - -/* Removes a byte from Q and returns it. - If Q is empty, sleeps until a byte is added. - When called from an interrupt handler, Q must not be empty. */ -uint8_t -intq_getc (struct intq *q) -{ - uint8_t byte; - - ASSERT (intr_get_level () == INTR_OFF); - while (intq_empty (q)) - { - ASSERT (!intr_context ()); - lock_acquire (&q->lock); - wait (q, &q->not_empty); - lock_release (&q->lock); - } - - byte = q->buf[q->tail]; - q->tail = next (q->tail); - signal (q, &q->not_full); - return byte; -} - -/* Adds BYTE to the end of Q. - If Q is full, sleeps until a byte is removed. - When called from an interrupt handler, Q must not be full. */ -void -intq_putc (struct intq *q, uint8_t byte) -{ - ASSERT (intr_get_level () == INTR_OFF); - while (intq_full (q)) - { - ASSERT (!intr_context ()); - lock_acquire (&q->lock); - wait (q, &q->not_full); - lock_release (&q->lock); - } - - q->buf[q->head] = byte; - q->head = next (q->head); - signal (q, &q->not_empty); -} - -/* Returns the position after POS within an intq. */ -static int -next (int pos) -{ - return (pos + 1) % INTQ_BUFSIZE; -} - -/* WAITER must be the address of Q's not_empty or not_full - member. Waits until the given condition is true. */ -static void -wait (struct intq *q UNUSED, struct thread **waiter) -{ - ASSERT (!intr_context ()); - ASSERT (intr_get_level () == INTR_OFF); - ASSERT ((waiter == &q->not_empty && intq_empty (q)) - || (waiter == &q->not_full && intq_full (q))); - - *waiter = thread_current (); - thread_block (); -} - -/* WAITER must be the address of Q's not_empty or not_full - member, and the associated condition must be true. If a - thread is waiting for the condition, wakes it up and resets - the waiting thread. */ -static void -signal (struct intq *q UNUSED, struct thread **waiter) -{ - ASSERT (intr_get_level () == INTR_OFF); - ASSERT ((waiter == &q->not_empty && !intq_empty (q)) - || (waiter == &q->not_full && !intq_full (q))); - - if (*waiter != NULL) - { - thread_unblock (*waiter); - *waiter = NULL; - } -} diff --git a/pintos-progos/devices/intq.h b/pintos-progos/devices/intq.h deleted file mode 100644 index 2312b12..0000000 --- a/pintos-progos/devices/intq.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef DEVICES_INTQ_H -#define DEVICES_INTQ_H - -#include "threads/interrupt.h" -#include "threads/synch.h" - -/* An "interrupt queue", a circular buffer shared between - kernel threads and external interrupt handlers. - - Interrupt queue functions can be called from kernel threads or - from external interrupt handlers. Except for intq_init(), - interrupts must be off in either case. - - The interrupt queue has the structure of a "monitor". Locks - and condition variables from threads/synch.h cannot be used in - this case, as they normally would, because they can only - protect kernel threads from one another, not from interrupt - handlers. */ - -/* Queue buffer size, in bytes. */ -#define INTQ_BUFSIZE 64 - -/* A circular queue of bytes. */ -struct intq - { - /* Waiting threads. */ - struct lock lock; /* Only one thread may wait at once. */ - struct thread *not_full; /* Thread waiting for not-full condition. */ - struct thread *not_empty; /* Thread waiting for not-empty condition. */ - - /* Queue. */ - uint8_t buf[INTQ_BUFSIZE]; /* Buffer. */ - int head; /* New data is written here. */ - int tail; /* Old data is read here. */ - }; - -void intq_init (struct intq *); -bool intq_empty (const struct intq *); -bool intq_full (const struct intq *); -uint8_t intq_getc (struct intq *); -void intq_putc (struct intq *, uint8_t); - -#endif /* devices/intq.h */ diff --git a/pintos-progos/devices/kbd.c b/pintos-progos/devices/kbd.c deleted file mode 100644 index fcc82be..0000000 --- a/pintos-progos/devices/kbd.c +++ /dev/null @@ -1,213 +0,0 @@ -#include "devices/kbd.h" -#include -#include -#include -#include -#include "devices/input.h" -#include "devices/shutdown.h" -#include "threads/interrupt.h" -#include "threads/io.h" - -/* Keyboard data register port. */ -#define DATA_REG 0x60 - -/* Current state of shift keys. - True if depressed, false otherwise. */ -static bool left_shift, right_shift; /* Left and right Shift keys. */ -static bool left_alt, right_alt; /* Left and right Alt keys. */ -static bool left_ctrl, right_ctrl; /* Left and right Ctl keys. */ - -/* Status of Caps Lock. - True when on, false when off. */ -static bool caps_lock; - -/* Number of keys pressed. */ -static int64_t key_cnt; - -static intr_handler_func keyboard_interrupt; - -/* Initializes the keyboard. */ -void -kbd_init (void) -{ - intr_register_ext (0x21, keyboard_interrupt, "8042 Keyboard"); -} - -/* Prints keyboard statistics. */ -void -kbd_print_stats (void) -{ - printf ("Keyboard: %lld keys pressed\n", key_cnt); -} - -/* Maps a set of contiguous scancodes into characters. */ -struct keymap - { - uint8_t first_scancode; /* First scancode. */ - const char *chars; /* chars[0] has scancode first_scancode, - chars[1] has scancode first_scancode + 1, - and so on to the end of the string. */ - }; - -/* Keys that produce the same characters regardless of whether - the Shift keys are down. Case of letters is an exception - that we handle elsewhere. */ -static const struct keymap invariant_keymap[] = - { - {0x01, "\033"}, /* Escape. */ - {0x0e, "\b"}, - {0x0f, "\tQWERTYUIOP"}, - {0x1c, "\r"}, - {0x1e, "ASDFGHJKL"}, - {0x2c, "ZXCVBNM"}, - {0x37, "*"}, - {0x39, " "}, - {0x53, "\177"}, /* Delete. */ - {0, NULL}, - }; - -/* Characters for keys pressed without Shift, for those keys - where it matters. */ -static const struct keymap unshifted_keymap[] = - { - {0x02, "1234567890-="}, - {0x1a, "[]"}, - {0x27, ";'`"}, - {0x2b, "\\"}, - {0x33, ",./"}, - {0, NULL}, - }; - -/* Characters for keys pressed with Shift, for those keys where - it matters. */ -static const struct keymap shifted_keymap[] = - { - {0x02, "!@#$%^&*()_+"}, - {0x1a, "{}"}, - {0x27, ":\"~"}, - {0x2b, "|"}, - {0x33, "<>?"}, - {0, NULL}, - }; - -static bool map_key (const struct keymap[], unsigned scancode, uint8_t *); - -static void -keyboard_interrupt (struct intr_frame *args UNUSED) -{ - /* Status of shift keys. */ - bool shift = left_shift || right_shift; - bool alt = left_alt || right_alt; - bool ctrl = left_ctrl || right_ctrl; - - /* Keyboard scancode. */ - unsigned code; - - /* False if key pressed, true if key released. */ - bool release; - - /* Character that corresponds to `code'. */ - uint8_t c; - - /* Read scancode, including second byte if prefix code. */ - code = inb (DATA_REG); - if (code == 0xe0) - code = (code << 8) | inb (DATA_REG); - - /* Bit 0x80 distinguishes key press from key release - (even if there's a prefix). */ - release = (code & 0x80) != 0; - code &= ~0x80u; - - /* Interpret key. */ - if (code == 0x3a) - { - /* Caps Lock. */ - if (!release) - caps_lock = !caps_lock; - } - else if (map_key (invariant_keymap, code, &c) - || (!shift && map_key (unshifted_keymap, code, &c)) - || (shift && map_key (shifted_keymap, code, &c))) - { - /* Ordinary character. */ - if (!release) - { - /* Reboot if Ctrl+Alt+Del pressed. */ - if (c == 0177 && ctrl && alt) - shutdown_reboot (); - - /* Handle Ctrl, Shift. - Note that Ctrl overrides Shift. */ - if (ctrl && c >= 0x40 && c < 0x60) - { - /* A is 0x41, Ctrl+A is 0x01, etc. */ - c -= 0x40; - } - else if (shift == caps_lock) - c = tolower (c); - - /* Handle Alt by setting the high bit. - This 0x80 is unrelated to the one used to - distinguish key press from key release. */ - if (alt) - c += 0x80; - - /* Append to keyboard buffer. */ - if (!input_full ()) - { - key_cnt++; - input_putc (c); - } - } - } - else - { - /* Maps a keycode into a shift state variable. */ - struct shift_key - { - unsigned scancode; - bool *state_var; - }; - - /* Table of shift keys. */ - static const struct shift_key shift_keys[] = - { - { 0x2a, &left_shift}, - { 0x36, &right_shift}, - { 0x38, &left_alt}, - {0xe038, &right_alt}, - { 0x1d, &left_ctrl}, - {0xe01d, &right_ctrl}, - {0, NULL}, - }; - - const struct shift_key *key; - - /* Scan the table. */ - for (key = shift_keys; key->scancode != 0; key++) - if (key->scancode == code) - { - *key->state_var = !release; - break; - } - } -} - -/* Scans the array of keymaps K for SCANCODE. - If found, sets *C to the corresponding character and returns - true. - If not found, returns false and C is ignored. */ -static bool -map_key (const struct keymap k[], unsigned scancode, uint8_t *c) -{ - for (; k->first_scancode != 0; k++) - if (scancode >= k->first_scancode - && scancode < k->first_scancode + strlen (k->chars)) - { - *c = k->chars[scancode - k->first_scancode]; - return true; - } - - return false; -} diff --git a/pintos-progos/devices/kbd.h b/pintos-progos/devices/kbd.h deleted file mode 100644 index ed9c06b..0000000 --- a/pintos-progos/devices/kbd.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef DEVICES_KBD_H -#define DEVICES_KBD_H - -#include - -void kbd_init (void); -void kbd_print_stats (void); - -#endif /* devices/kbd.h */ diff --git a/pintos-progos/devices/partition.c b/pintos-progos/devices/partition.c deleted file mode 100644 index 7e97332..0000000 --- a/pintos-progos/devices/partition.c +++ /dev/null @@ -1,324 +0,0 @@ -#include "devices/partition.h" -#include -#include -#include -#include -#include "devices/block.h" -#include "threads/malloc.h" - -/* A partition of a block device. */ -struct partition - { - struct block *block; /* Underlying block device. */ - block_sector_t start; /* First sector within device. */ - }; - -static struct block_operations partition_operations; - -static void read_partition_table (struct block *, block_sector_t sector, - block_sector_t primary_extended_sector, - int *part_nr); -static void found_partition (struct block *, uint8_t type, - block_sector_t start, block_sector_t size, - int part_nr); -static const char *partition_type_name (uint8_t); - -/* Scans BLOCK for partitions of interest to Pintos. */ -void -partition_scan (struct block *block) -{ - int part_nr = 0; - read_partition_table (block, 0, 0, &part_nr); - if (part_nr == 0) - printf ("%s: Device contains no partitions\n", block_name (block)); -} - -/* Reads the partition table in the given SECTOR of BLOCK and - scans it for partitions of interest to Pintos. - - If SECTOR is 0, so that this is the top-level partition table - on BLOCK, then PRIMARY_EXTENDED_SECTOR is not meaningful; - otherwise, it should designate the sector of the top-level - extended partition table that was traversed to arrive at - SECTOR, for use in finding logical partitions (see the large - comment below). - - PART_NR points to the number of non-empty primary or logical - partitions already encountered on BLOCK. It is incremented as - partitions are found. */ -static void -read_partition_table (struct block *block, block_sector_t sector, - block_sector_t primary_extended_sector, - int *part_nr) -{ - /* Format of a partition table entry. See [Partitions]. */ - struct partition_table_entry - { - uint8_t bootable; /* 0x00=not bootable, 0x80=bootable. */ - uint8_t start_chs[3]; /* Encoded starting cylinder, head, sector. */ - uint8_t type; /* Partition type (see partition_type_name). */ - uint8_t end_chs[3]; /* Encoded ending cylinder, head, sector. */ - uint32_t offset; /* Start sector offset from partition table. */ - uint32_t size; /* Number of sectors. */ - } - PACKED; - - /* Partition table sector. */ - struct partition_table - { - uint8_t loader[446]; /* Loader, in top-level partition table. */ - struct partition_table_entry partitions[4]; /* Table entries. */ - uint16_t signature; /* Should be 0xaa55. */ - } - PACKED; - - struct partition_table *pt; - size_t i; - - /* Check SECTOR validity. */ - if (sector >= block_size (block)) - { - printf ("%s: Partition table at sector %"PRDSNu" past end of device.\n", - block_name (block), sector); - return; - } - - /* Read sector. */ - ASSERT (sizeof *pt == BLOCK_SECTOR_SIZE); - pt = malloc (sizeof *pt); - if (pt == NULL) - PANIC ("Failed to allocate memory for partition table."); - block_read (block, 0, pt); - - /* Check signature. */ - if (pt->signature != 0xaa55) - { - if (primary_extended_sector == 0) - printf ("%s: Invalid partition table signature\n", block_name (block)); - else - printf ("%s: Invalid extended partition table in sector %"PRDSNu"\n", - block_name (block), sector); - free (pt); - return; - } - - /* Parse partitions. */ - for (i = 0; i < sizeof pt->partitions / sizeof *pt->partitions; i++) - { - struct partition_table_entry *e = &pt->partitions[i]; - - if (e->size == 0 || e->type == 0) - { - /* Ignore empty partition. */ - } - else if (e->type == 0x05 /* Extended partition. */ - || e->type == 0x0f /* Windows 98 extended partition. */ - || e->type == 0x85 /* Linux extended partition. */ - || e->type == 0xc5) /* DR-DOS extended partition. */ - { - printf ("%s: Extended partition in sector %"PRDSNu"\n", - block_name (block), sector); - - /* The interpretation of the offset field for extended - partitions is bizarre. When the extended partition - table entry is in the master boot record, that is, - the device's primary partition table in sector 0, then - the offset is an absolute sector number. Otherwise, - no matter how deep the partition table we're reading - is nested, the offset is relative to the start of - the extended partition that the MBR points to. */ - if (sector == 0) - read_partition_table (block, e->offset, e->offset, part_nr); - else - read_partition_table (block, e->offset + primary_extended_sector, - primary_extended_sector, part_nr); - } - else - { - ++*part_nr; - - found_partition (block, e->type, e->offset + sector, - e->size, *part_nr); - } - } - - free (pt); -} - -/* We have found a primary or logical partition of the given TYPE - on BLOCK, starting at sector START and continuing for SIZE - sectors, which we are giving the partition number PART_NR. - Check whether this is a partition of interest to Pintos, and - if so then add it to the proper element of partitions[]. */ -static void -found_partition (struct block *block, uint8_t part_type, - block_sector_t start, block_sector_t size, - int part_nr) -{ - if (start >= block_size (block)) - printf ("%s%d: Partition starts past end of device (sector %"PRDSNu")\n", - block_name (block), part_nr, start); - else if (start + size < start || start + size > block_size (block)) - printf ("%s%d: Partition end (%"PRDSNu") past end of device (%"PRDSNu")\n", - block_name (block), part_nr, start + size, block_size (block)); - else - { - enum block_type type = (part_type == 0x20 ? BLOCK_KERNEL - : part_type == 0x21 ? BLOCK_FILESYS - : part_type == 0x22 ? BLOCK_SCRATCH - : part_type == 0x23 ? BLOCK_SWAP - : BLOCK_FOREIGN); - struct partition *p; - char extra_info[128]; - char name[16]; - - p = malloc (sizeof *p); - if (p == NULL) - PANIC ("Failed to allocate memory for partition descriptor"); - p->block = block; - p->start = start; - - snprintf (name, sizeof name, "%s%d", block_name (block), part_nr); - snprintf (extra_info, sizeof extra_info, "%s (%02x)", - partition_type_name (part_type), part_type); - block_register (name, type, extra_info, size, &partition_operations, p); - } -} - -/* Returns a human-readable name for the given partition TYPE. */ -static const char * -partition_type_name (uint8_t type) -{ - /* Name of each known type of partition. - From util-linux-2.12r/fdisk/i386_sys_types.c. - This initializer makes use of a C99 feature that allows - array elements to be initialized by index. */ - static const char *type_names[256] = - { - [0x00] = "Empty", - [0x01] = "FAT12", - [0x02] = "XENIX root", - [0x03] = "XENIX usr", - [0x04] = "FAT16 <32M", - [0x05] = "Extended", - [0x06] = "FAT16", - [0x07] = "HPFS/NTFS", - [0x08] = "AIX", - [0x09] = "AIX bootable", - [0x0a] = "OS/2 Boot Manager", - [0x0b] = "W95 FAT32", - [0x0c] = "W95 FAT32 (LBA)", - [0x0e] = "W95 FAT16 (LBA)", - [0x0f] = "W95 Ext'd (LBA)", - [0x10] = "OPUS", - [0x11] = "Hidden FAT12", - [0x12] = "Compaq diagnostics", - [0x14] = "Hidden FAT16 <32M", - [0x16] = "Hidden FAT16", - [0x17] = "Hidden HPFS/NTFS", - [0x18] = "AST SmartSleep", - [0x1b] = "Hidden W95 FAT32", - [0x1c] = "Hidden W95 FAT32 (LBA)", - [0x1e] = "Hidden W95 FAT16 (LBA)", - [0x20] = "Pintos OS kernel", - [0x21] = "Pintos file system", - [0x22] = "Pintos scratch", - [0x23] = "Pintos swap", - [0x24] = "NEC DOS", - [0x39] = "Plan 9", - [0x3c] = "PartitionMagic recovery", - [0x40] = "Venix 80286", - [0x41] = "PPC PReP Boot", - [0x42] = "SFS", - [0x4d] = "QNX4.x", - [0x4e] = "QNX4.x 2nd part", - [0x4f] = "QNX4.x 3rd part", - [0x50] = "OnTrack DM", - [0x51] = "OnTrack DM6 Aux1", - [0x52] = "CP/M", - [0x53] = "OnTrack DM6 Aux3", - [0x54] = "OnTrackDM6", - [0x55] = "EZ-Drive", - [0x56] = "Golden Bow", - [0x5c] = "Priam Edisk", - [0x61] = "SpeedStor", - [0x63] = "GNU HURD or SysV", - [0x64] = "Novell Netware 286", - [0x65] = "Novell Netware 386", - [0x70] = "DiskSecure Multi-Boot", - [0x75] = "PC/IX", - [0x80] = "Old Minix", - [0x81] = "Minix / old Linux", - [0x82] = "Linux swap / Solaris", - [0x83] = "Linux", - [0x84] = "OS/2 hidden C: drive", - [0x85] = "Linux extended", - [0x86] = "NTFS volume set", - [0x87] = "NTFS volume set", - [0x88] = "Linux plaintext", - [0x8e] = "Linux LVM", - [0x93] = "Amoeba", - [0x94] = "Amoeba BBT", - [0x9f] = "BSD/OS", - [0xa0] = "IBM Thinkpad hibernation", - [0xa5] = "FreeBSD", - [0xa6] = "OpenBSD", - [0xa7] = "NeXTSTEP", - [0xa8] = "Darwin UFS", - [0xa9] = "NetBSD", - [0xab] = "Darwin boot", - [0xb7] = "BSDI fs", - [0xb8] = "BSDI swap", - [0xbb] = "Boot Wizard hidden", - [0xbe] = "Solaris boot", - [0xbf] = "Solaris", - [0xc1] = "DRDOS/sec (FAT-12)", - [0xc4] = "DRDOS/sec (FAT-16 < 32M)", - [0xc6] = "DRDOS/sec (FAT-16)", - [0xc7] = "Syrinx", - [0xda] = "Non-FS data", - [0xdb] = "CP/M / CTOS / ...", - [0xde] = "Dell Utility", - [0xdf] = "BootIt", - [0xe1] = "DOS access", - [0xe3] = "DOS R/O", - [0xe4] = "SpeedStor", - [0xeb] = "BeOS fs", - [0xee] = "EFI GPT", - [0xef] = "EFI (FAT-12/16/32)", - [0xf0] = "Linux/PA-RISC boot", - [0xf1] = "SpeedStor", - [0xf4] = "SpeedStor", - [0xf2] = "DOS secondary", - [0xfd] = "Linux raid autodetect", - [0xfe] = "LANstep", - [0xff] = "BBT", - }; - - return type_names[type] != NULL ? type_names[type] : "Unknown"; -} - -/* Reads sector SECTOR from partition P into BUFFER, which must - have room for BLOCK_SECTOR_SIZE bytes. */ -static void -partition_read (void *p_, block_sector_t sector, void *buffer) -{ - struct partition *p = p_; - block_read (p->block, p->start + sector, buffer); -} - -/* Write sector SECTOR to partition P from BUFFER, which must - contain BLOCK_SECTOR_SIZE bytes. Returns after the block has - acknowledged receiving the data. */ -static void -partition_write (void *p_, block_sector_t sector, const void *buffer) -{ - struct partition *p = p_; - block_write (p->block, p->start + sector, buffer); -} - -static struct block_operations partition_operations = - { - partition_read, - partition_write - }; diff --git a/pintos-progos/devices/partition.h b/pintos-progos/devices/partition.h deleted file mode 100644 index 47fea4d..0000000 --- a/pintos-progos/devices/partition.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DEVICES_PARTITION_H -#define DEVICES_PARTITION_H - -struct block; - -void partition_scan (struct block *); - -#endif /* devices/partition.h */ diff --git a/pintos-progos/devices/pit.c b/pintos-progos/devices/pit.c deleted file mode 100644 index bfb1889..0000000 --- a/pintos-progos/devices/pit.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "devices/pit.h" -#include -#include -#include "threads/interrupt.h" -#include "threads/io.h" - -/* Interface to 8254 Programmable Interrupt Timer (PIT). - Refer to [8254] for details. */ - -/* 8254 registers. */ -#define PIT_PORT_CONTROL 0x43 /* Control port. */ -#define PIT_PORT_COUNTER(CHANNEL) (0x40 + (CHANNEL)) /* Counter port. */ - -/* PIT cycles per second. */ -#define PIT_HZ 1193180 - -/* Configure the given CHANNEL in the PIT. In a PC, the PIT's - three output channels are hooked up like this: - - - Channel 0 is connected to interrupt line 0, so that it can - be used as a periodic timer interrupt, as implemented in - Pintos in devices/timer.c. - - - Channel 1 is used for dynamic RAM refresh (in older PCs). - No good can come of messing with this. - - - Channel 2 is connected to the PC speaker, so that it can - be used to play a tone, as implemented in Pintos in - devices/speaker.c. - - MODE specifies the form of output: - - - Mode 2 is a periodic pulse: the channel's output is 1 for - most of the period, but drops to 0 briefly toward the end - of the period. This is useful for hooking up to an - interrupt controller to generate a periodic interrupt. - - - Mode 3 is a square wave: for the first half of the period - it is 1, for the second half it is 0. This is useful for - generating a tone on a speaker. - - - Other modes are less useful. - - FREQUENCY is the number of periods per second, in Hz. */ -void -pit_configure_channel (int channel, int mode, int frequency) -{ - uint16_t count; - enum intr_level old_level; - - ASSERT (channel == 0 || channel == 2); - ASSERT (mode == 2 || mode == 3); - - /* Convert FREQUENCY to a PIT counter value. The PIT has a - clock that runs at PIT_HZ cycles per second. We must - translate FREQUENCY into a number of these cycles. */ - if (frequency < 19) - { - /* Frequency is too low: the quotient would overflow the - 16-bit counter. Force it to 0, which the PIT treats as - 65536, the highest possible count. This yields a 18.2 - Hz timer, approximately. */ - count = 0; - } - else if (frequency > PIT_HZ) - { - /* Frequency is too high: the quotient would underflow to - 0, which the PIT would interpret as 65536. A count of 1 - is illegal in mode 2, so we force it to 2, which yields - a 596.590 kHz timer, approximately. (This timer rate is - probably too fast to be useful anyhow.) */ - count = 2; - } - else - count = (PIT_HZ + frequency / 2) / frequency; - - /* Configure the PIT mode and load its counters. */ - old_level = intr_disable (); - outb (PIT_PORT_CONTROL, (channel << 6) | 0x30 | (mode << 1)); - outb (PIT_PORT_COUNTER (channel), count); - outb (PIT_PORT_COUNTER (channel), count >> 8); - intr_set_level (old_level); -} diff --git a/pintos-progos/devices/pit.h b/pintos-progos/devices/pit.h deleted file mode 100644 index dff36ae..0000000 --- a/pintos-progos/devices/pit.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DEVICES_PIT_H -#define DEVICES_PIT_H - -#include - -void pit_configure_channel (int channel, int mode, int frequency); - -#endif /* devices/pit.h */ diff --git a/pintos-progos/devices/rtc.c b/pintos-progos/devices/rtc.c deleted file mode 100644 index d99eb46..0000000 --- a/pintos-progos/devices/rtc.c +++ /dev/null @@ -1,112 +0,0 @@ -#include "devices/rtc.h" -#include -#include "threads/io.h" - -/* This code is an interface to the MC146818A-compatible real - time clock found on PC motherboards. See [MC146818A] for - hardware details. */ - -/* I/O register addresses. */ -#define CMOS_REG_SET 0x70 /* Selects CMOS register exposed by REG_IO. */ -#define CMOS_REG_IO 0x71 /* Contains the selected data byte. */ - -/* Indexes of CMOS registers with real-time clock functions. - Note that all of these registers are in BCD format, - so that 0x59 means 59, not 89. */ -#define RTC_REG_SEC 0 /* Second: 0x00...0x59. */ -#define RTC_REG_MIN 2 /* Minute: 0x00...0x59. */ -#define RTC_REG_HOUR 4 /* Hour: 0x00...0x23. */ -#define RTC_REG_MDAY 7 /* Day of the month: 0x01...0x31. */ -#define RTC_REG_MON 8 /* Month: 0x01...0x12. */ -#define RTC_REG_YEAR 9 /* Year: 0x00...0x99. */ - -/* Indexes of CMOS control registers. */ -#define RTC_REG_A 0x0a /* Register A: update-in-progress. */ -#define RTC_REG_B 0x0b /* Register B: 24/12 hour time, irq enables. */ -#define RTC_REG_C 0x0c /* Register C: pending interrupts. */ -#define RTC_REG_D 0x0d /* Register D: valid time? */ - -/* Register A. */ -#define RTCSA_UIP 0x80 /* Set while time update in progress. */ - -/* Register B. */ -#define RTCSB_SET 0x80 /* Disables update to let time be set. */ -#define RTCSB_DM 0x04 /* 0 = BCD time format, 1 = binary format. */ -#define RTCSB_24HR 0x02 /* 0 = 12-hour format, 1 = 24-hour format. */ - -static int bcd_to_bin (uint8_t); -static uint8_t cmos_read (uint8_t index); - -/* Returns number of seconds since Unix epoch of January 1, - 1970. */ -time_t -rtc_get_time (void) -{ - static const int days_per_month[12] = - { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - int sec, min, hour, mday, mon, year; - time_t time; - int i; - - /* Get time components. - - We repeatedly read the time until it is stable from one read - to another, in case we start our initial read in the middle - of an update. This strategy is not recommended by the - MC146818A datasheet, but it is simpler than any of their - suggestions and, furthermore, it is also used by Linux. - - The MC146818A can be configured for BCD or binary format, - but for historical reasons everyone always uses BCD format - except on obscure non-PC platforms, so we don't bother - trying to detect the format in use. */ - do - { - sec = bcd_to_bin (cmos_read (RTC_REG_SEC)); - min = bcd_to_bin (cmos_read (RTC_REG_MIN)); - hour = bcd_to_bin (cmos_read (RTC_REG_HOUR)); - mday = bcd_to_bin (cmos_read (RTC_REG_MDAY)); - mon = bcd_to_bin (cmos_read (RTC_REG_MON)); - year = bcd_to_bin (cmos_read (RTC_REG_YEAR)); - } - while (sec != bcd_to_bin (cmos_read (RTC_REG_SEC))); - - /* Translate years-since-1900 into years-since-1970. - If it's before the epoch, assume that it has passed 2000. - This will break at 2070, but that's long after our 31-bit - time_t breaks in 2038. */ - if (year < 70) - year += 100; - year -= 70; - - /* Break down all components into seconds. */ - time = (year * 365 + (year - 1) / 4) * 24 * 60 * 60; - for (i = 1; i <= mon; i++) - time += days_per_month[i - 1] * 24 * 60 * 60; - if (mon > 2 && year % 4 == 0) - time += 24 * 60 * 60; - time += (mday - 1) * 24 * 60 * 60; - time += hour * 60 * 60; - time += min * 60; - time += sec; - - return time; -} - -/* Returns the integer value of the given BCD byte. */ -static int -bcd_to_bin (uint8_t x) -{ - return (x & 0x0f) + ((x >> 4) * 10); -} - -/* Reads a byte from the CMOS register with the given INDEX and - returns the byte read. */ -static uint8_t -cmos_read (uint8_t index) -{ - outb (CMOS_REG_SET, index); - return inb (CMOS_REG_IO); -} diff --git a/pintos-progos/devices/rtc.h b/pintos-progos/devices/rtc.h deleted file mode 100644 index 96a822f..0000000 --- a/pintos-progos/devices/rtc.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RTC_H -#define RTC_H - -typedef unsigned long time_t; - -time_t rtc_get_time (void); - -#endif diff --git a/pintos-progos/devices/serial.c b/pintos-progos/devices/serial.c deleted file mode 100644 index df770a7..0000000 --- a/pintos-progos/devices/serial.c +++ /dev/null @@ -1,228 +0,0 @@ -#include "devices/serial.h" -#include -#include "devices/input.h" -#include "devices/intq.h" -#include "devices/timer.h" -#include "threads/io.h" -#include "threads/interrupt.h" -#include "threads/synch.h" -#include "threads/thread.h" - -/* Register definitions for the 16550A UART used in PCs. - The 16550A has a lot more going on than shown here, but this - is all we need. - - Refer to [PC16650D] for hardware information. */ - -/* I/O port base address for the first serial port. */ -#define IO_BASE 0x3f8 - -/* DLAB=0 registers. */ -#define RBR_REG (IO_BASE + 0) /* Receiver Buffer Reg. (read-only). */ -#define THR_REG (IO_BASE + 0) /* Transmitter Holding Reg. (write-only). */ -#define IER_REG (IO_BASE + 1) /* Interrupt Enable Reg.. */ - -/* DLAB=1 registers. */ -#define LS_REG (IO_BASE + 0) /* Divisor Latch (LSB). */ -#define MS_REG (IO_BASE + 1) /* Divisor Latch (MSB). */ - -/* DLAB-insensitive registers. */ -#define IIR_REG (IO_BASE + 2) /* Interrupt Identification Reg. (read-only) */ -#define FCR_REG (IO_BASE + 2) /* FIFO Control Reg. (write-only). */ -#define LCR_REG (IO_BASE + 3) /* Line Control Register. */ -#define MCR_REG (IO_BASE + 4) /* MODEM Control Register. */ -#define LSR_REG (IO_BASE + 5) /* Line Status Register (read-only). */ - -/* Interrupt Enable Register bits. */ -#define IER_RECV 0x01 /* Interrupt when data received. */ -#define IER_XMIT 0x02 /* Interrupt when transmit finishes. */ - -/* Line Control Register bits. */ -#define LCR_N81 0x03 /* No parity, 8 data bits, 1 stop bit. */ -#define LCR_DLAB 0x80 /* Divisor Latch Access Bit (DLAB). */ - -/* MODEM Control Register. */ -#define MCR_OUT2 0x08 /* Output line 2. */ - -/* Line Status Register. */ -#define LSR_DR 0x01 /* Data Ready: received data byte is in RBR. */ -#define LSR_THRE 0x20 /* THR Empty. */ - -/* Transmission mode. */ -static enum { UNINIT, POLL, QUEUE } mode; - -/* Data to be transmitted. */ -static struct intq txq; - -static void set_serial (int bps); -static void putc_poll (uint8_t); -static void write_ier (void); -static intr_handler_func serial_interrupt; - -/* Initializes the serial port device for polling mode. - Polling mode busy-waits for the serial port to become free - before writing to it. It's slow, but until interrupts have - been initialized it's all we can do. */ -static void -init_poll (void) -{ - ASSERT (mode == UNINIT); - outb (IER_REG, 0); /* Turn off all interrupts. */ - outb (FCR_REG, 0); /* Disable FIFO. */ - set_serial (9600); /* 9.6 kbps, N-8-1. */ - outb (MCR_REG, MCR_OUT2); /* Required to enable interrupts. */ - intq_init (&txq); - mode = POLL; -} - -/* Initializes the serial port device for queued interrupt-driven - I/O. With interrupt-driven I/O we don't waste CPU time - waiting for the serial device to become ready. */ -void -serial_init_queue (void) -{ - enum intr_level old_level; - - if (mode == UNINIT) - init_poll (); - ASSERT (mode == POLL); - - intr_register_ext (0x20 + 4, serial_interrupt, "serial"); - mode = QUEUE; - old_level = intr_disable (); - write_ier (); - intr_set_level (old_level); -} - -/* Sends BYTE to the serial port. */ -void -serial_putc (uint8_t byte) -{ - enum intr_level old_level = intr_disable (); - - if (mode != QUEUE) - { - /* If we're not set up for interrupt-driven I/O yet, - use dumb polling to transmit a byte. */ - if (mode == UNINIT) - init_poll (); - putc_poll (byte); - } - else - { - /* Otherwise, queue a byte and update the interrupt enable - register. */ - if (old_level == INTR_OFF && intq_full (&txq)) - { - /* Interrupts are off and the transmit queue is full. - If we wanted to wait for the queue to empty, - we'd have to reenable interrupts. - That's impolite, so we'll send a character via - polling instead. */ - putc_poll (intq_getc (&txq)); - } - - intq_putc (&txq, byte); - write_ier (); - } - - intr_set_level (old_level); -} - -/* Flushes anything in the serial buffer out the port in polling - mode. */ -void -serial_flush (void) -{ - enum intr_level old_level = intr_disable (); - while (!intq_empty (&txq)) - putc_poll (intq_getc (&txq)); - intr_set_level (old_level); -} - -/* The fullness of the input buffer may have changed. Reassess - whether we should block receive interrupts. - Called by the input buffer routines when characters are added - to or removed from the buffer. */ -void -serial_notify (void) -{ - ASSERT (intr_get_level () == INTR_OFF); - if (mode == QUEUE) - write_ier (); -} - -/* Configures the serial port for BPS bits per second. */ -static void -set_serial (int bps) -{ - int base_rate = 1843200 / 16; /* Base rate of 16550A, in Hz. */ - uint16_t divisor = base_rate / bps; /* Clock rate divisor. */ - - ASSERT (bps >= 300 && bps <= 115200); - - /* Enable DLAB. */ - outb (LCR_REG, LCR_N81 | LCR_DLAB); - - /* Set data rate. */ - outb (LS_REG, divisor & 0xff); - outb (MS_REG, divisor >> 8); - - /* Reset DLAB. */ - outb (LCR_REG, LCR_N81); -} - -/* Update interrupt enable register. */ -static void -write_ier (void) -{ - uint8_t ier = 0; - - ASSERT (intr_get_level () == INTR_OFF); - - /* Enable transmit interrupt if we have any characters to - transmit. */ - if (!intq_empty (&txq)) - ier |= IER_XMIT; - - /* Enable receive interrupt if we have room to store any - characters we receive. */ - if (!input_full ()) - ier |= IER_RECV; - - outb (IER_REG, ier); -} - -/* Polls the serial port until it's ready, - and then transmits BYTE. */ -static void -putc_poll (uint8_t byte) -{ - ASSERT (intr_get_level () == INTR_OFF); - - while ((inb (LSR_REG) & LSR_THRE) == 0) - continue; - outb (THR_REG, byte); -} - -/* Serial interrupt handler. */ -static void -serial_interrupt (struct intr_frame *f UNUSED) -{ - /* Inquire about interrupt in UART. Without this, we can - occasionally miss an interrupt running under QEMU. */ - inb (IIR_REG); - - /* As long as we have room to receive a byte, and the hardware - has a byte for us, receive a byte. */ - while (!input_full () && (inb (LSR_REG) & LSR_DR) != 0) - input_putc (inb (RBR_REG)); - - /* As long as we have a byte to transmit, and the hardware is - ready to accept a byte for transmission, transmit a byte. */ - while (!intq_empty (&txq) && (inb (LSR_REG) & LSR_THRE) != 0) - outb (THR_REG, intq_getc (&txq)); - - /* Update interrupt enable register based on queue status. */ - write_ier (); -} diff --git a/pintos-progos/devices/serial.h b/pintos-progos/devices/serial.h deleted file mode 100644 index 6e04778..0000000 --- a/pintos-progos/devices/serial.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef DEVICES_SERIAL_H -#define DEVICES_SERIAL_H - -#include - -void serial_init_queue (void); -void serial_putc (uint8_t); -void serial_flush (void); -void serial_notify (void); - -#endif /* devices/serial.h */ diff --git a/pintos-progos/devices/shutdown.c b/pintos-progos/devices/shutdown.c deleted file mode 100644 index 7ff9a95..0000000 --- a/pintos-progos/devices/shutdown.c +++ /dev/null @@ -1,131 +0,0 @@ -#include "devices/shutdown.h" -#include -#include -#include "devices/kbd.h" -#include "devices/serial.h" -#include "devices/timer.h" -#include "threads/io.h" -#include "threads/thread.h" -#ifdef USERPROG -#include "userprog/exception.h" -#endif -#ifdef FILESYS -#include "devices/block.h" -#include "filesys/filesys.h" -#endif - -/* Keyboard control register port. */ -#define CONTROL_REG 0x64 - -/* How to shut down when shutdown() is called. */ -static enum shutdown_type how = SHUTDOWN_NONE; - -static void print_stats (void); - -/* Shuts down the machine in the way configured by - shutdown_configure(). If the shutdown type is SHUTDOWN_NONE - (which is the default), returns without doing anything. */ -void -shutdown (void) -{ - switch (how) - { - case SHUTDOWN_POWER_OFF: - shutdown_power_off (); - break; - - case SHUTDOWN_REBOOT: - shutdown_reboot (); - break; - - default: - /* Nothing to do. */ - break; - } -} - -/* Sets TYPE as the way that machine will shut down when Pintos - execution is complete. */ -void -shutdown_configure (enum shutdown_type type) -{ - how = type; -} - -/* Reboots the machine via the keyboard controller. */ -void -shutdown_reboot (void) -{ - printf ("Rebooting...\n"); - - /* See [kbd] for details on how to program the keyboard - * controller. */ - for (;;) - { - int i; - - /* Poll keyboard controller's status byte until - * 'input buffer empty' is reported. */ - for (i = 0; i < 0x10000; i++) - { - if ((inb (CONTROL_REG) & 0x02) == 0) - break; - timer_udelay (2); - } - - timer_udelay (50); - - /* Pulse bit 0 of the output port P2 of the keyboard controller. - * This will reset the CPU. */ - outb (CONTROL_REG, 0xfe); - timer_udelay (50); - } -} - -/* Powers down the machine we're running on, - as long as we're running on Bochs or QEMU. */ -void -shutdown_power_off (void) -{ - const char s[] = "Shutdown"; - const char *p; - -#ifdef FILESYS - filesys_done (); -#endif - - print_stats (); - - printf ("Powering off...\n"); - serial_flush (); - - /* This is a special power-off sequence supported by Bochs and - QEMU, but not by physical hardware. */ - for (p = s; *p != '\0'; p++) - outb (0x8900, *p); - - /* This will power off a VMware VM if "gui.exitOnCLIHLT = TRUE" - is set in its configuration file. (The "pintos" script does - that automatically.) */ - asm volatile ("cli; hlt" : : : "memory"); - - /* None of those worked. */ - printf ("still running...\n"); - for (;;); -} - -/* Print statistics about Pintos execution. */ -static void -print_stats (void) -{ - timer_print_stats (); - thread_print_stats (); -#ifdef FILESYS - block_print_stats (); -#endif - console_print_stats (); - kbd_print_stats (); -#ifdef USERPROG - exception_print_stats (); -#endif -} diff --git a/pintos-progos/devices/shutdown.h b/pintos-progos/devices/shutdown.h deleted file mode 100644 index dc4f942..0000000 --- a/pintos-progos/devices/shutdown.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef DEVICES_SHUTDOWN_H -#define DEVICES_SHUTDOWN_H - -#include - -/* How to shut down when Pintos has nothing left to do. */ -enum shutdown_type - { - SHUTDOWN_NONE, /* Loop forever. */ - SHUTDOWN_POWER_OFF, /* Power off the machine (if possible). */ - SHUTDOWN_REBOOT, /* Reboot the machine (if possible). */ - }; - -void shutdown (void); -void shutdown_configure (enum shutdown_type); -void shutdown_reboot (void) NO_RETURN; -void shutdown_power_off (void) NO_RETURN; - -#endif /* devices/shutdown.h */ diff --git a/pintos-progos/devices/speaker.c b/pintos-progos/devices/speaker.c deleted file mode 100644 index 5052005..0000000 --- a/pintos-progos/devices/speaker.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "devices/speaker.h" -#include "devices/pit.h" -#include "threads/io.h" -#include "threads/interrupt.h" -#include "devices/timer.h" - -/* Speaker port enable I/O register. */ -#define SPEAKER_PORT_GATE 0x61 - -/* Speaker port enable bits. */ -#define SPEAKER_GATE_ENABLE 0x03 - -/* Sets the PC speaker to emit a tone at the given FREQUENCY, in - Hz. */ -void -speaker_on (int frequency) -{ - if (frequency >= 20 && frequency <= 20000) - { - /* Set the timer channel that's connected to the speaker to - output a square wave at the given FREQUENCY, then - connect the timer channel output to the speaker. */ - enum intr_level old_level = intr_disable (); - pit_configure_channel (2, 3, frequency); - outb (SPEAKER_PORT_GATE, inb (SPEAKER_PORT_GATE) | SPEAKER_GATE_ENABLE); - intr_set_level (old_level); - } - else - { - /* FREQUENCY is outside the range of normal human hearing. - Just turn off the speaker. */ - speaker_off (); - } -} - -/* Turn off the PC speaker, by disconnecting the timer channel's - output from the speaker. */ -void -speaker_off (void) -{ - enum intr_level old_level = intr_disable (); - outb (SPEAKER_PORT_GATE, inb (SPEAKER_PORT_GATE) & ~SPEAKER_GATE_ENABLE); - intr_set_level (old_level); -} - -/* Briefly beep the PC speaker. */ -void -speaker_beep (void) -{ - /* Only attempt to beep the speaker if interrupts are enabled, - because we don't want to freeze the machine during the beep. - We could add a hook to the timer interrupt to avoid that - problem, but then we'd risk failing to ever stop the beep if - Pintos crashes for some unrelated reason. There's nothing - more annoying than a machine whose beeping you can't stop - without a power cycle. - - We can't just enable interrupts while we sleep. For one - thing, we get called (indirectly) from printf, which should - always work, even during boot before we're ready to enable - interrupts. */ - if (intr_get_level () == INTR_ON) - { - speaker_on (440); - timer_msleep (250); - speaker_off (); - } -} diff --git a/pintos-progos/devices/speaker.h b/pintos-progos/devices/speaker.h deleted file mode 100644 index 98cef7b..0000000 --- a/pintos-progos/devices/speaker.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DEVICES_SPEAKER_H -#define DEVICES_SPEAKER_H - -void speaker_on (int frequency); -void speaker_off (void); -void speaker_beep (void); - -#endif /* devices/speaker.h */ diff --git a/pintos-progos/devices/timer.c b/pintos-progos/devices/timer.c deleted file mode 100644 index 3533fe7..0000000 --- a/pintos-progos/devices/timer.c +++ /dev/null @@ -1,297 +0,0 @@ -#include "devices/timer.h" -#include -#include -#include -#include -#include "devices/pit.h" -#include "threads/interrupt.h" -#include "threads/synch.h" -#include "threads/thread.h" - -/* See [8254] for hardware details of the 8254 timer chip. */ - -#if TIMER_FREQ < 19 -#error 8254 timer requires TIMER_FREQ >= 19 -#endif -#if TIMER_FREQ > 1000 -#error TIMER_FREQ <= 1000 recommended -#endif - -/* Number of timer ticks since OS booted. */ -static int64_t ticks; - -/* Number of loops per timer tick. - Initialized by timer_calibrate(). */ -static unsigned loops_per_tick; - -static intr_handler_func timer_interrupt; -static bool too_many_loops (unsigned loops); -static void busy_wait (int64_t loops); -static void real_time_sleep (int64_t num, int32_t denom); -static void real_time_delay (int64_t num, int32_t denom); - -/* list of processes waiting for an wakeup event - * and currently put to sleep */ -static struct list wakeup_list; - -/* Sets up the timer to interrupt TIMER_FREQ times per second, - and registers the corresponding interrupt. */ -void -timer_init (void) -{ - list_init (&wakeup_list); - pit_configure_channel (0, 2, TIMER_FREQ); - intr_register_ext (0x20, timer_interrupt, "8254 Timer"); -} - -/* Calibrates loops_per_tick, used to implement brief delays. */ -void -timer_calibrate (void) -{ - unsigned high_bit, test_bit; - - ASSERT (intr_get_level () == INTR_ON); - printf ("Calibrating timer... "); - - /* Approximate loops_per_tick as the largest power-of-two - still less than one timer tick. */ - loops_per_tick = 1u << 10; - while (!too_many_loops (loops_per_tick << 1)) - { - loops_per_tick <<= 1; - ASSERT (loops_per_tick != 0); - } - - /* Refine the next 8 bits of loops_per_tick. */ - high_bit = loops_per_tick; - for (test_bit = high_bit >> 1; test_bit != high_bit >> 10; test_bit >>= 1) - if (!too_many_loops (high_bit | test_bit)) - loops_per_tick |= test_bit; - - printf ("%'"PRIu64" loops/s.\n", (uint64_t) loops_per_tick * TIMER_FREQ); -} - -/* Returns the number of timer ticks since the OS booted. */ -int64_t -timer_ticks (void) -{ - enum intr_level old_level = intr_disable (); - int64_t t = ticks; - intr_set_level (old_level); - return t; -} - -/* Returns the number of timer ticks elapsed since THEN, which - should be a value once returned by timer_ticks(). */ -int64_t -timer_elapsed (int64_t then) -{ - return timer_ticks () - then; -} - -/* Comparison function for our ascending ordered wakeup list. */ -static bool -wakeup_list_cmp_less(const struct list_elem *a, const struct list_elem *b, - void *AUX UNUSED) -{ - struct thread *t1 = list_entry (a, struct thread, elem); - struct thread *t2 = list_entry (b, struct thread, elem); - return (t1->wakeup_tick < t2->wakeup_tick); -} - -/* Sleeps for approximately TICKS timer ticks. Interrupts must - be turned on. */ -void -timer_sleep (int64_t ticks) -{ - struct thread *t = thread_current (); - enum intr_level old_level; - - ASSERT (intr_get_level () == INTR_ON); - - /* nothing to sleep here */ - if (ticks <= 0) - return; - - t->wakeup_tick = timer_ticks () + ticks; - - /* add thread to sorted wakeup list - * disable interrupts as this is critical */ - old_level = intr_disable (); - ASSERT (t->status == THREAD_RUNNING); - list_insert_ordered (&wakeup_list, &t->elem, &wakeup_list_cmp_less, NULL); - - /* block the thread */ - thread_block (); - - /* restore interrupt */ - intr_set_level (old_level); -} - -/* Sleeps for approximately MS milliseconds. Interrupts must be - turned on. */ -void -timer_msleep (int64_t ms) -{ - real_time_sleep (ms, 1000); -} - -/* Sleeps for approximately US microseconds. Interrupts must be - turned on. */ -void -timer_usleep (int64_t us) -{ - real_time_sleep (us, 1000 * 1000); -} - -/* Sleeps for approximately NS nanoseconds. Interrupts must be - turned on. */ -void -timer_nsleep (int64_t ns) -{ - real_time_sleep (ns, 1000 * 1000 * 1000); -} - -/* Busy-waits for approximately MS milliseconds. Interrupts need - not be turned on. - - Busy waiting wastes CPU cycles, and busy waiting with - interrupts off for the interval between timer ticks or longer - will cause timer ticks to be lost. Thus, use timer_msleep() - instead if interrupts are enabled. */ -void -timer_mdelay (int64_t ms) -{ - real_time_delay (ms, 1000); -} - -/* Sleeps for approximately US microseconds. Interrupts need not - be turned on. - - Busy waiting wastes CPU cycles, and busy waiting with - interrupts off for the interval between timer ticks or longer - will cause timer ticks to be lost. Thus, use timer_usleep() - instead if interrupts are enabled. */ -void -timer_udelay (int64_t us) -{ - real_time_delay (us, 1000 * 1000); -} - -/* Sleeps execution for approximately NS nanoseconds. Interrupts - need not be turned on. - - Busy waiting wastes CPU cycles, and busy waiting with - interrupts off for the interval between timer ticks or longer - will cause timer ticks to be lost. Thus, use timer_nsleep() - instead if interrupts are enabled.*/ -void -timer_ndelay (int64_t ns) -{ - real_time_delay (ns, 1000 * 1000 * 1000); -} - -/* Prints timer statistics. */ -void -timer_print_stats (void) -{ - printf ("Timer: %"PRId64" ticks\n", timer_ticks ()); -} - -/* Timer interrupt handler. */ -static void -timer_interrupt (struct intr_frame *args UNUSED) -{ - struct list_elem *el, *next; - - ticks++; - thread_tick (); - - /* Check threads waiting to get woken up/unblocked. - * Since this is an ordered list we can bail out as soon - * as the first element doesn't need to get unblocked. */ - for (el = list_begin (&wakeup_list); el != list_end (&wakeup_list); el = next) - { - struct thread *t = list_entry (el, struct thread, elem); - if (t->wakeup_tick == timer_ticks ()) - { - next = list_remove (el); - /* unblock must be called AFTER removing, - * as thread_unblock() will reuse t.elem */ - thread_unblock (t); - continue; - } - break; - } -} - -/* Returns true if LOOPS iterations waits for more than one timer - tick, otherwise false. */ -static bool -too_many_loops (unsigned loops) -{ - /* Wait for a timer tick. */ - int64_t start = ticks; - while (ticks == start) - barrier (); - - /* Run LOOPS loops. */ - start = ticks; - busy_wait (loops); - - /* If the tick count changed, we iterated too long. */ - barrier (); - return start != ticks; -} - -/* Iterates through a simple loop LOOPS times, for implementing - brief delays. - - Marked NO_INLINE because code alignment can significantly - affect timings, so that if this function was inlined - differently in different places the results would be difficult - to predict. */ -static void NO_INLINE -busy_wait (int64_t loops) -{ - while (loops-- > 0) - barrier (); -} - -/* Sleep for approximately NUM/DENOM seconds. */ -static void -real_time_sleep (int64_t num, int32_t denom) -{ - /* Convert NUM/DENOM seconds into timer ticks, rounding down. - - (NUM / DENOM) s - ---------------------- = NUM * TIMER_FREQ / DENOM ticks. - 1 s / TIMER_FREQ ticks - */ - int64_t ticks = num * TIMER_FREQ / denom; - - ASSERT (intr_get_level () == INTR_ON); - if (ticks > 0) - { - /* We're waiting for at least one full timer tick. Use - timer_sleep() because it will yield the CPU to other - processes. */ - timer_sleep (ticks); - } - else - { - /* Otherwise, use a busy-wait loop for more accurate - sub-tick timing. */ - real_time_delay (num, denom); - } -} - -/* Busy-wait for approximately NUM/DENOM seconds. */ -static void -real_time_delay (int64_t num, int32_t denom) -{ - /* Scale the numerator and denominator down by 1000 to avoid - the possibility of overflow. */ - ASSERT (denom % 1000 == 0); - busy_wait (loops_per_tick * num / 1000 * TIMER_FREQ / (denom / 1000)); -} diff --git a/pintos-progos/devices/timer.h b/pintos-progos/devices/timer.h deleted file mode 100644 index cd3d6bb..0000000 --- a/pintos-progos/devices/timer.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef DEVICES_TIMER_H -#define DEVICES_TIMER_H - -#include -#include - -/* Number of timer interrupts per second. */ -#define TIMER_FREQ 100 - -void timer_init (void); -void timer_calibrate (void); - -int64_t timer_ticks (void); -int64_t timer_elapsed (int64_t); - -/* Sleep and yield the CPU to other threads. */ -void timer_sleep (int64_t ticks); -void timer_msleep (int64_t milliseconds); -void timer_usleep (int64_t microseconds); -void timer_nsleep (int64_t nanoseconds); - -/* Busy waits. */ -void timer_mdelay (int64_t milliseconds); -void timer_udelay (int64_t microseconds); -void timer_ndelay (int64_t nanoseconds); - -void timer_print_stats (void); - -#endif /* devices/timer.h */ diff --git a/pintos-progos/devices/vga.c b/pintos-progos/devices/vga.c deleted file mode 100644 index f421b61..0000000 --- a/pintos-progos/devices/vga.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "devices/vga.h" -#include -#include -#include -#include -#include "devices/speaker.h" -#include "threads/io.h" -#include "threads/interrupt.h" -#include "threads/vaddr.h" - -/* VGA text screen support. See [FREEVGA] for more information. */ - -/* Number of columns and rows on the text display. */ -#define COL_CNT 80 -#define ROW_CNT 25 - -/* Current cursor position. (0,0) is in the upper left corner of - the display. */ -static size_t cx, cy; - -/* Attribute value for gray text on a black background. */ -#define GRAY_ON_BLACK 0x07 - -/* Framebuffer. See [FREEVGA] under "VGA Text Mode Operation". - The character at (x,y) is fb[y][x][0]. - The attribute at (x,y) is fb[y][x][1]. */ -static uint8_t (*fb)[COL_CNT][2]; - -static void clear_row (size_t y); -static void cls (void); -static void newline (void); -static void move_cursor (void); -static void find_cursor (size_t *x, size_t *y); - -/* Initializes the VGA text display. */ -static void -init (void) -{ - /* Already initialized? */ - static bool inited; - if (!inited) - { - fb = ptov (0xb8000); - find_cursor (&cx, &cy); - inited = true; - } -} - -/* Writes C to the VGA text display, interpreting control - characters in the conventional ways. */ -void -vga_putc (int c) -{ - /* Disable interrupts to lock out interrupt handlers - that might write to the console. */ - enum intr_level old_level = intr_disable (); - - init (); - - switch (c) - { - case '\n': - newline (); - break; - - case '\f': - cls (); - break; - - case '\b': - if (cx > 0) - cx--; - break; - - case '\r': - cx = 0; - break; - - case '\t': - cx = ROUND_UP (cx + 1, 8); - if (cx >= COL_CNT) - newline (); - break; - - case '\a': - intr_set_level (old_level); - speaker_beep (); - intr_disable (); - break; - - default: - fb[cy][cx][0] = c; - fb[cy][cx][1] = GRAY_ON_BLACK; - if (++cx >= COL_CNT) - newline (); - break; - } - - /* Update cursor position. */ - move_cursor (); - - intr_set_level (old_level); -} - -/* Clears the screen and moves the cursor to the upper left. */ -static void -cls (void) -{ - size_t y; - - for (y = 0; y < ROW_CNT; y++) - clear_row (y); - - cx = cy = 0; - move_cursor (); -} - -/* Clears row Y to spaces. */ -static void -clear_row (size_t y) -{ - size_t x; - - for (x = 0; x < COL_CNT; x++) - { - fb[y][x][0] = ' '; - fb[y][x][1] = GRAY_ON_BLACK; - } -} - -/* Advances the cursor to the first column in the next line on - the screen. If the cursor is already on the last line on the - screen, scrolls the screen upward one line. */ -static void -newline (void) -{ - cx = 0; - cy++; - if (cy >= ROW_CNT) - { - cy = ROW_CNT - 1; - memmove (&fb[0], &fb[1], sizeof fb[0] * (ROW_CNT - 1)); - clear_row (ROW_CNT - 1); - } -} - -/* Moves the hardware cursor to (cx,cy). */ -static void -move_cursor (void) -{ - /* See [FREEVGA] under "Manipulating the Text-mode Cursor". */ - uint16_t cp = cx + COL_CNT * cy; - outw (0x3d4, 0x0e | (cp & 0xff00)); - outw (0x3d4, 0x0f | (cp << 8)); -} - -/* Reads the current hardware cursor position into (*X,*Y). */ -static void -find_cursor (size_t *x, size_t *y) -{ - /* See [FREEVGA] under "Manipulating the Text-mode Cursor". */ - uint16_t cp; - - outb (0x3d4, 0x0e); - cp = inb (0x3d5) << 8; - - outb (0x3d4, 0x0f); - cp |= inb (0x3d5); - - *x = cp % COL_CNT; - *y = cp / COL_CNT; -} diff --git a/pintos-progos/devices/vga.h b/pintos-progos/devices/vga.h deleted file mode 100644 index 59690fb..0000000 --- a/pintos-progos/devices/vga.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DEVICES_VGA_H -#define DEVICES_VGA_H - -void vga_putc (int); - -#endif /* devices/vga.h */ -- cgit v1.2.3