Print statistics at power off.
[pintos-anon] / src / devices / disk.c
index 2381c57a045284762d29652efd7896e02f0b829a..baf120864399f11a8c33ae27f37a41992b413cab 100644 (file)
@@ -1,11 +1,12 @@
-#include "disk.h"
+#include "devices/disk.h"
+#include <ctype.h>
+#include <debug.h>
 #include <stdbool.h>
-#include "debug.h"
-#include "io.h"
-#include "interrupt.h"
-#include "lib.h"
-#include "synch.h"
-#include "timer.h"
+#include <stdio.h>
+#include "devices/timer.h"
+#include "threads/io.h"
+#include "threads/interrupt.h"
+#include "threads/synch.h"
 
 /* ATA command block port addresses. */
 #define reg_data(CHANNEL) ((CHANNEL)->reg_base + 0)     /* Data. */
@@ -51,7 +52,10 @@ struct disk
     int dev_no;                 /* Device 0 or 1 for master or slave. */
 
     bool is_ata;                /* 1=This device is an ATA disk. */
-    disk_sector_no capacity;    /* Capacity in sectors (if is_ata is true). */
+    disk_sector_t capacity;     /* Capacity in sectors (if is_ata). */
+
+    long long read_cnt;         /* Number of sectors read. */
+    long long write_cnt;        /* Number of sectors written. */
   };
 
 /* An ATA channel (aka controller).
@@ -78,7 +82,7 @@ static void reset_channel (struct channel *);
 static bool check_device_type (struct disk *);
 static void identify_ata_device (struct disk *);
 
-static void select_sector (struct disk *, disk_sector_no);
+static void select_sector (struct disk *, disk_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 *);
@@ -102,7 +106,7 @@ disk_init (void)
       int dev_no;
 
       /* Initialize channel. */
-      snprintf (c->name, sizeof c->name, "hd%d", chan_no);
+      snprintf (c->name, sizeof c->name, "hd%zd", chan_no);
       switch (chan_no) 
         {
         case 0:
@@ -130,10 +134,12 @@ disk_init (void)
 
           d->is_ata = false;
           d->capacity = 0;
+
+          d->read_cnt = d->write_cnt = 0;
         }
 
       /* Register interrupt handler. */
-      intr_register (c->irq, 0, IF_OFF, interrupt_handler, c->name);
+      intr_register (c->irq, 0, INTR_OFF, interrupt_handler, c->name);
 
       /* Reset hardware. */
       reset_channel (c);
@@ -149,6 +155,26 @@ disk_init (void)
     }
 }
 
+/* Prints disk statistics. */
+void
+disk_print_stats (void) 
+{
+  int chan_no;
+
+  for (chan_no = 0; chan_no < CHANNEL_CNT; chan_no++) 
+    {
+      int dev_no;
+
+      for (dev_no = 0; dev_no < 2; dev_no++) 
+        {
+          struct disk *d = disk_get (chan_no, dev_no);
+          if (d != NULL && d->is_ata) 
+            printf ("%s: %lld reads, %lld writes\n",
+                    d->name, d->read_cnt, d->write_cnt);
+        }
+    }
+}
+
 /* Returns the disk numbered DEV_NO--either 0 or 1 for master or
    slave, respectively--within the channel numbered CHAN_NO. */
 struct disk *
@@ -167,7 +193,7 @@ disk_get (int chan_no, int dev_no)
 
 /* Returns the size of disk D, measured in DISK_SECTOR_SIZE-byte
    sectors. */
-disk_sector_no
+disk_sector_t
 disk_size (struct disk *d) 
 {
   ASSERT (d != NULL);
@@ -178,7 +204,7 @@ disk_size (struct disk *d)
 /* Reads sector SEC_NO from disk D into BUFFER, which must have
    room for DISK_SECTOR_SIZE bytes. */
 void
-disk_read (struct disk *d, disk_sector_no sec_no, void *buffer) 
+disk_read (struct disk *d, disk_sector_t sec_no, void *buffer) 
 {
   struct channel *c;
   
@@ -193,6 +219,7 @@ disk_read (struct disk *d, disk_sector_no sec_no, void *buffer)
   if (!wait_while_busy (d))
     PANIC ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no);
   input_sector (c, buffer);
+  d->read_cnt++;
   lock_release (&c->lock);
 }
 
@@ -200,7 +227,7 @@ disk_read (struct disk *d, disk_sector_no sec_no, void *buffer)
    DISK_SECTOR_SIZE bytes.  Returns after the disk has
    acknowledged receiving the data. */
 void
-disk_write (struct disk *d, disk_sector_no sec_no, const void *buffer)
+disk_write (struct disk *d, disk_sector_t sec_no, const void *buffer)
 {
   struct channel *c;
   
@@ -215,12 +242,13 @@ disk_write (struct disk *d, disk_sector_no sec_no, const void *buffer)
     PANIC ("%s: disk write failed, sector=%"PRDSNu, d->name, sec_no);
   output_sector (c, buffer);
   sema_down (&c->completion_wait);
+  d->write_cnt++;
   lock_release (&c->lock);
 }
 \f
 /* Disk detection and identification. */
 
-static void printk_ata_string (char *string, size_t size);
+static void print_ata_string (char *string, size_t size);
 
 /* Resets an ATA channel and waits for any devices present on it
    to finish the reset. */
@@ -254,12 +282,12 @@ reset_channel (struct channel *c)
   /* Issue soft reset sequence, which selects device 0 as a side effect.
      Also enable interrupts. */
   outb (reg_ctl (c), 0);
-  timer_usleep (10);
+  timer_sleep (timer_us2ticks (10));
   outb (reg_ctl (c), CTL_SRST);
-  timer_usleep (10);
+  timer_sleep (timer_us2ticks (10));
   outb (reg_ctl (c), 0);
 
-  timer_msleep (150);
+  timer_sleep (timer_ms2ticks (150));
 
   /* Wait for device 0 to clear BSY. */
   if (present[0]) 
@@ -278,7 +306,7 @@ reset_channel (struct channel *c)
         {
           if (inb (reg_nsect (c)) == 1 && inb (reg_lbal (c)) == 1)
             break;
-          timer_msleep (10);
+          timer_sleep (timer_ms2ticks (10));
         }
       wait_while_busy (&c->devices[1]);
     }
@@ -341,28 +369,28 @@ identify_ata_device (struct disk *d)
   d->capacity = id[60] | ((uint32_t) id[61] << 16);
 
   /* Print identification message. */
-  printk ("%s: detected %'"PRDSNu" sector (", d->name, d->capacity);
+  printf ("%s: detected %'"PRDSNu" sector (", d->name, d->capacity);
   if (d->capacity > 1024 / DISK_SECTOR_SIZE * 1024 * 1024)
-    printk ("%"PRDSNu" GB",
+    printf ("%"PRDSNu" GB",
             d->capacity / (1024 / DISK_SECTOR_SIZE * 1024 * 1024));
   else if (d->capacity > 1024 / DISK_SECTOR_SIZE * 1024)
-    printk ("%"PRDSNu" MB", d->capacity / (1024 / DISK_SECTOR_SIZE * 1024));
+    printf ("%"PRDSNu" MB", d->capacity / (1024 / DISK_SECTOR_SIZE * 1024));
   else if (d->capacity > 1024 / DISK_SECTOR_SIZE)
-    printk ("%"PRDSNu" kB", d->capacity / (1024 / DISK_SECTOR_SIZE));
+    printf ("%"PRDSNu" kB", d->capacity / (1024 / DISK_SECTOR_SIZE));
   else
-    printk ("%"PRDSNu" byte", d->capacity * DISK_SECTOR_SIZE);
-  printk (") disk, model \"");
-  printk_ata_string ((char *) &id[27], 40);
-  printk ("\", serial \"");
-  printk_ata_string ((char *) &id[10], 20);
-  printk ("\"\n");
+    printf ("%"PRDSNu" byte", d->capacity * DISK_SECTOR_SIZE);
+  printf (") disk, model \"");
+  print_ata_string ((char *) &id[27], 40);
+  printf ("\", serial \"");
+  print_ata_string ((char *) &id[10], 20);
+  printf ("\"\n");
 }
 
 /* Prints STRING, which consists of SIZE bytes in a funky format:
    each pair of bytes is in reverse order.  Does not print
    trailing whitespace and/or nulls. */
 static void
-printk_ata_string (char *string, size_t size) 
+print_ata_string (char *string, size_t size) 
 {
   size_t i;
 
@@ -376,14 +404,14 @@ printk_ata_string (char *string, size_t size)
 
   /* Print. */
   for (i = 0; i < size; i++)
-    printk ("%c", string[i ^ 1]);
+    printf ("%c", string[i ^ 1]);
 }
 \f
 /* 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 disk *d, disk_sector_no sec_no) 
+select_sector (struct disk *d, disk_sector_t sec_no) 
 {
   struct channel *c = d->channel;
 
@@ -406,7 +434,7 @@ 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 () == IF_ON);
+  ASSERT (intr_get_level () == INTR_ON);
 
   c->expecting_interrupt = true;
   outb (reg_command (c), command);
@@ -444,10 +472,10 @@ wait_until_idle (const struct disk *d)
     {
       if ((inb (reg_status (d->channel)) & (STA_BSY | STA_DRQ)) == 0)
         return;
-      timer_usleep (10);
+      timer_sleep (timer_us2ticks (10));
     }
 
-  printk ("%s: idle timeout\n", d->name);
+  printf ("%s: idle timeout\n", d->name);
 }
 
 /* Wait up to 30 seconds for disk D to clear BSY,
@@ -463,17 +491,17 @@ wait_while_busy (const struct disk *d)
   for (i = 0; i < 3000; i++)
     {
       if (i == 700)
-        printk ("%s: busy, waiting...", d->name);
+        printf ("%s: busy, waiting...", d->name);
       if (!(inb (reg_alt_status (c)) & STA_BSY)) 
         {
           if (i >= 700)
-            printk ("ok\n");
+            printf ("ok\n");
           return (inb (reg_alt_status (c)) & STA_DRQ) != 0;
         }
-      timer_msleep (10);
+      timer_sleep (timer_ms2ticks (10));
     }
 
-  printk ("failed\n");
+  printf ("failed\n");
   return false;
 }
 
@@ -487,7 +515,7 @@ select_device (const struct disk *d)
     dev |= DEV_DEV;
   outb (reg_device (c), dev);
   inb (reg_alt_status (c));
-  timer_nsleep (400);
+  timer_sleep (timer_ns2ticks (400));
 }
 
 /* Select disk D in its channel, as select_device(), but wait for
@@ -515,7 +543,7 @@ interrupt_handler (struct intr_frame *f)
             sema_up (&c->completion_wait);      /* Wake up waiter. */
           }
         else
-          printk ("%s: unexpected interrupt\n", c->name);
+          printf ("%s: unexpected interrupt\n", c->name);
         return;
       }