Print statistics at power off.
[pintos-anon] / src / devices / disk.c
1 #include "devices/disk.h"
2 #include <ctype.h>
3 #include <debug.h>
4 #include <stdbool.h>
5 #include <stdio.h>
6 #include "devices/timer.h"
7 #include "threads/io.h"
8 #include "threads/interrupt.h"
9 #include "threads/synch.h"
10
11 /* ATA command block port addresses. */
12 #define reg_data(CHANNEL) ((CHANNEL)->reg_base + 0)     /* Data. */
13 #define reg_error(CHANNEL) ((CHANNEL)->reg_base + 1)    /* Error. */
14 #define reg_nsect(CHANNEL) ((CHANNEL)->reg_base + 2)    /* Sector Count. */
15 #define reg_lbal(CHANNEL) ((CHANNEL)->reg_base + 3)     /* LBA 0:7. */
16 #define reg_lbam(CHANNEL) ((CHANNEL)->reg_base + 4)     /* LBA 15:8. */
17 #define reg_lbah(CHANNEL) ((CHANNEL)->reg_base + 5)     /* LBA 23:16. */
18 #define reg_device(CHANNEL) ((CHANNEL)->reg_base + 6)   /* Device/LBA 27:24. */
19 #define reg_status(CHANNEL) ((CHANNEL)->reg_base + 7)   /* Status (r/o). */
20 #define reg_command(CHANNEL) reg_status (CHANNEL)       /* Command (w/o). */
21
22 /* ATA control block port addresses.
23    (If we supported non-legacy ATA controllers this would not be
24    flexible enough, but it's fine for what we do.) */
25 #define reg_ctl(CHANNEL) ((CHANNEL)->reg_base + 0x206)  /* Control (w/o). */
26 #define reg_alt_status(CHANNEL) reg_ctl (CHANNEL)       /* Alt Status (r/o). */
27
28 /* Alternate Status Register bits. */
29 #define STA_BSY 0x80            /* Busy. */
30 #define STA_DRQ 0x08            /* Data Request. */
31
32 /* Control Register bits. */
33 #define CTL_SRST 0x04           /* Software Reset. */
34
35 /* Device Register bits. */
36 #define DEV_MBS 0xa0            /* Must be set. */
37 #define DEV_LBA 0x40            /* Linear based addressing. */
38 #define DEV_DEV 0x10            /* Select device: 0=master, 1=slave. */
39
40 /* Commands.
41    Many more are defined but this is the small subset that we
42    use. */
43 #define CMD_IDENTIFY_DEVICE 0xec        /* IDENTIFY DEVICE. */
44 #define CMD_READ_SECTOR_RETRY 0x20      /* READ SECTOR with retries. */
45 #define CMD_WRITE_SECTOR_RETRY 0x30     /* WRITE SECTOR with retries. */
46
47 /* An ATA device. */
48 struct disk 
49   {
50     char name[8];               /* Name, e.g. "hd0:1". */
51     struct channel *channel;    /* Channel disk is on. */
52     int dev_no;                 /* Device 0 or 1 for master or slave. */
53
54     bool is_ata;                /* 1=This device is an ATA disk. */
55     disk_sector_t capacity;     /* Capacity in sectors (if is_ata). */
56
57     long long read_cnt;         /* Number of sectors read. */
58     long long write_cnt;        /* Number of sectors written. */
59   };
60
61 /* An ATA channel (aka controller).
62    Each channel can control up to two disks. */
63 struct channel 
64   {
65     char name[8];               /* Name, e.g. "hd0". */
66     uint16_t reg_base;          /* Base I/O port. */
67     uint8_t irq;                /* Interrupt in use. */
68
69     struct lock lock;           /* Must acquire to access the controller. */
70     bool expecting_interrupt;   /* True if an interrupt is expected, false if
71                                    any interrupt would be spurious. */
72     struct semaphore completion_wait;   /* Up'd by interrupt handler. */
73
74     struct disk devices[2];     /* The devices on this channel. */
75   };
76
77 /* We support the two "legacy" ATA channels found in a standard PC. */
78 #define CHANNEL_CNT 2
79 static struct channel channels[CHANNEL_CNT];
80
81 static void reset_channel (struct channel *);
82 static bool check_device_type (struct disk *);
83 static void identify_ata_device (struct disk *);
84
85 static void select_sector (struct disk *, disk_sector_t);
86 static void issue_pio_command (struct channel *, uint8_t command);
87 static void input_sector (struct channel *, void *);
88 static void output_sector (struct channel *, const void *);
89
90 static void wait_until_idle (const struct disk *);
91 static bool wait_while_busy (const struct disk *);
92 static void select_device (const struct disk *);
93 static void select_device_wait (const struct disk *);
94
95 static void interrupt_handler (struct intr_frame *);
96
97 /* Initialize the disk subsystem and detect disks. */
98 void
99 disk_init (void) 
100 {
101   size_t chan_no;
102
103   for (chan_no = 0; chan_no < CHANNEL_CNT; chan_no++)
104     {
105       struct channel *c = &channels[chan_no];
106       int dev_no;
107
108       /* Initialize channel. */
109       snprintf (c->name, sizeof c->name, "hd%zd", chan_no);
110       switch (chan_no) 
111         {
112         case 0:
113           c->reg_base = 0x1f0;
114           c->irq = 14 + 0x20;
115           break;
116         case 1:
117           c->reg_base = 0x170;
118           c->irq = 15 + 0x20;
119           break;
120         default:
121           NOT_REACHED ();
122         }
123       lock_init (&c->lock, c->name);
124       c->expecting_interrupt = false;
125       sema_init (&c->completion_wait, 0, c->name);
126  
127       /* Initialize devices. */
128       for (dev_no = 0; dev_no < 2; dev_no++)
129         {
130           struct disk *d = &c->devices[dev_no];
131           snprintf (d->name, sizeof d->name, "%s:%d", c->name, dev_no);
132           d->channel = c;
133           d->dev_no = dev_no;
134
135           d->is_ata = false;
136           d->capacity = 0;
137
138           d->read_cnt = d->write_cnt = 0;
139         }
140
141       /* Register interrupt handler. */
142       intr_register (c->irq, 0, INTR_OFF, interrupt_handler, c->name);
143
144       /* Reset hardware. */
145       reset_channel (c);
146
147       /* Distinguish ATA hard disks from other devices. */
148       if (check_device_type (&c->devices[0]))
149         check_device_type (&c->devices[1]);
150
151       /* Read hard disk identity information. */
152       for (dev_no = 0; dev_no < 2; dev_no++)
153         if (c->devices[dev_no].is_ata)
154           identify_ata_device (&c->devices[dev_no]);
155     }
156 }
157
158 /* Prints disk statistics. */
159 void
160 disk_print_stats (void) 
161 {
162   int chan_no;
163
164   for (chan_no = 0; chan_no < CHANNEL_CNT; chan_no++) 
165     {
166       int dev_no;
167
168       for (dev_no = 0; dev_no < 2; dev_no++) 
169         {
170           struct disk *d = disk_get (chan_no, dev_no);
171           if (d != NULL && d->is_ata) 
172             printf ("%s: %lld reads, %lld writes\n",
173                     d->name, d->read_cnt, d->write_cnt);
174         }
175     }
176 }
177
178 /* Returns the disk numbered DEV_NO--either 0 or 1 for master or
179    slave, respectively--within the channel numbered CHAN_NO. */
180 struct disk *
181 disk_get (int chan_no, int dev_no) 
182 {
183   ASSERT (dev_no == 0 || dev_no == 1);
184
185   if (chan_no < (int) CHANNEL_CNT) 
186     {
187       struct disk *d = &channels[chan_no].devices[dev_no];
188       if (d->is_ata)
189         return d; 
190     }
191   return NULL;
192 }
193
194 /* Returns the size of disk D, measured in DISK_SECTOR_SIZE-byte
195    sectors. */
196 disk_sector_t
197 disk_size (struct disk *d) 
198 {
199   ASSERT (d != NULL);
200   
201   return d->capacity;
202 }
203
204 /* Reads sector SEC_NO from disk D into BUFFER, which must have
205    room for DISK_SECTOR_SIZE bytes. */
206 void
207 disk_read (struct disk *d, disk_sector_t sec_no, void *buffer) 
208 {
209   struct channel *c;
210   
211   ASSERT (d != NULL);
212   ASSERT (buffer != NULL);
213
214   c = d->channel;
215   lock_acquire (&c->lock);
216   select_sector (d, sec_no);
217   issue_pio_command (c, CMD_READ_SECTOR_RETRY);
218   sema_down (&c->completion_wait);
219   if (!wait_while_busy (d))
220     PANIC ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no);
221   input_sector (c, buffer);
222   d->read_cnt++;
223   lock_release (&c->lock);
224 }
225
226 /* Write sector SEC_NO to disk D from BUFFER, which must contain
227    DISK_SECTOR_SIZE bytes.  Returns after the disk has
228    acknowledged receiving the data. */
229 void
230 disk_write (struct disk *d, disk_sector_t sec_no, const void *buffer)
231 {
232   struct channel *c;
233   
234   ASSERT (d != NULL);
235   ASSERT (buffer != NULL);
236
237   c = d->channel;
238   lock_acquire (&c->lock);
239   select_sector (d, sec_no);
240   issue_pio_command (c, CMD_WRITE_SECTOR_RETRY);
241   if (!wait_while_busy (d))
242     PANIC ("%s: disk write failed, sector=%"PRDSNu, d->name, sec_no);
243   output_sector (c, buffer);
244   sema_down (&c->completion_wait);
245   d->write_cnt++;
246   lock_release (&c->lock);
247 }
248 \f
249 /* Disk detection and identification. */
250
251 static void print_ata_string (char *string, size_t size);
252
253 /* Resets an ATA channel and waits for any devices present on it
254    to finish the reset. */
255 static void
256 reset_channel (struct channel *c) 
257 {
258   bool present[2];
259   int dev_no;
260
261   /* The ATA reset sequence depends on which devices are present,
262      so we start by detecting device presence. */
263   for (dev_no = 0; dev_no < 2; dev_no++)
264     {
265       struct disk *d = &c->devices[dev_no];
266
267       select_device (d);
268
269       outb (reg_nsect (c), 0x55);
270       outb (reg_lbal (c), 0xaa);
271
272       outb (reg_nsect (c), 0xaa);
273       outb (reg_lbal (c), 0x55);
274
275       outb (reg_nsect (c), 0x55);
276       outb (reg_lbal (c), 0xaa);
277
278       present[dev_no] = (inb (reg_nsect (c)) == 0x55
279                          && inb (reg_lbal (c)) == 0xaa);
280     }
281
282   /* Issue soft reset sequence, which selects device 0 as a side effect.
283      Also enable interrupts. */
284   outb (reg_ctl (c), 0);
285   timer_sleep (timer_us2ticks (10));
286   outb (reg_ctl (c), CTL_SRST);
287   timer_sleep (timer_us2ticks (10));
288   outb (reg_ctl (c), 0);
289
290   timer_sleep (timer_ms2ticks (150));
291
292   /* Wait for device 0 to clear BSY. */
293   if (present[0]) 
294     {
295       select_device (&c->devices[0]);
296       wait_while_busy (&c->devices[0]); 
297     }
298
299   /* Wait for device 1 to clear BSY. */
300   if (present[1])
301     {
302       int i;
303
304       select_device (&c->devices[1]);
305       for (i = 0; i < 3000; i++) 
306         {
307           if (inb (reg_nsect (c)) == 1 && inb (reg_lbal (c)) == 1)
308             break;
309           timer_sleep (timer_ms2ticks (10));
310         }
311       wait_while_busy (&c->devices[1]);
312     }
313 }
314
315 /* Checks whether device D is an ATA disk and sets D's is_ata
316    member appropriately.  If D is device 0 (master), returns true
317    if it's possible that a slave (device 1) exists on this
318    channel.  If D is device 1 (slave), the return value is not
319    meaningful. */
320 static bool
321 check_device_type (struct disk *d) 
322 {
323   struct channel *c = d->channel;
324   uint8_t error, lbam, lbah;
325
326   select_device (d);
327
328   error = inb (reg_error (c));
329   lbam = inb (reg_lbam (c));
330   lbah = inb (reg_lbah (c));
331
332   if (error != 1 && (error != 0x81 || d->dev_no == 1)) 
333     {
334       d->is_ata = false;
335       return error != 0x81;      
336     }
337   else 
338     {
339       d->is_ata = (lbam == 0 && lbah == 0) || (lbam == 0x3c && lbah == 0xc3);
340       return true; 
341     }
342 }
343
344 /* Sends an IDENTIFY DEVICE command to disk D and reads the
345    response.  Initializes D's capacity member based on the result
346    and prints a message describing the disk to the console. */
347 static void
348 identify_ata_device (struct disk *d) 
349 {
350   struct channel *c = d->channel;
351   uint16_t id[DISK_SECTOR_SIZE / 2];
352
353   ASSERT (d->is_ata);
354
355   /* Send the IDENTIFY DEVICE command, wait for an interrupt
356      indicating the device's response is ready, and read the data
357      into our buffer. */
358   select_device_wait (d);
359   issue_pio_command (c, CMD_IDENTIFY_DEVICE);
360   sema_down (&c->completion_wait);
361   if (!wait_while_busy (d))
362     {
363       d->is_ata = false;
364       return;
365     }
366   input_sector (c, id);
367
368   /* Calculate capacity. */
369   d->capacity = id[60] | ((uint32_t) id[61] << 16);
370
371   /* Print identification message. */
372   printf ("%s: detected %'"PRDSNu" sector (", d->name, d->capacity);
373   if (d->capacity > 1024 / DISK_SECTOR_SIZE * 1024 * 1024)
374     printf ("%"PRDSNu" GB",
375             d->capacity / (1024 / DISK_SECTOR_SIZE * 1024 * 1024));
376   else if (d->capacity > 1024 / DISK_SECTOR_SIZE * 1024)
377     printf ("%"PRDSNu" MB", d->capacity / (1024 / DISK_SECTOR_SIZE * 1024));
378   else if (d->capacity > 1024 / DISK_SECTOR_SIZE)
379     printf ("%"PRDSNu" kB", d->capacity / (1024 / DISK_SECTOR_SIZE));
380   else
381     printf ("%"PRDSNu" byte", d->capacity * DISK_SECTOR_SIZE);
382   printf (") disk, model \"");
383   print_ata_string ((char *) &id[27], 40);
384   printf ("\", serial \"");
385   print_ata_string ((char *) &id[10], 20);
386   printf ("\"\n");
387 }
388
389 /* Prints STRING, which consists of SIZE bytes in a funky format:
390    each pair of bytes is in reverse order.  Does not print
391    trailing whitespace and/or nulls. */
392 static void
393 print_ata_string (char *string, size_t size) 
394 {
395   size_t i;
396
397   /* Find the last non-white, non-null character. */
398   for (; size > 0; size--)
399     {
400       int c = string[(size - 1) ^ 1];
401       if (c != '\0' && !isspace (c))
402         break; 
403     }
404
405   /* Print. */
406   for (i = 0; i < size; i++)
407     printf ("%c", string[i ^ 1]);
408 }
409 \f
410 /* Selects device D, waiting for it to become ready, and then
411    writes SEC_NO to the disk's sector selection registers.  (We
412    use LBA mode.) */
413 static void
414 select_sector (struct disk *d, disk_sector_t sec_no) 
415 {
416   struct channel *c = d->channel;
417
418   ASSERT (sec_no < d->capacity);
419   ASSERT (sec_no < (1UL << 28));
420   
421   select_device_wait (d);
422   outb (reg_nsect (c), 1);
423   outb (reg_lbal (c), sec_no);
424   outb (reg_lbam (c), sec_no >> 8);
425   outb (reg_lbah (c), (sec_no >> 16));
426   outb (reg_device (c),
427         DEV_MBS | DEV_LBA | (d->dev_no == 1 ? DEV_DEV : 0) | (sec_no >> 24));
428 }
429
430 /* Writes COMMAND to channel C and prepares for receiving a
431    completion interrupt. */
432 static void
433 issue_pio_command (struct channel *c, uint8_t command) 
434 {
435   /* Interrupts must be enabled or our semaphore will never be
436      up'd by the completion handler. */
437   ASSERT (intr_get_level () == INTR_ON);
438
439   c->expecting_interrupt = true;
440   outb (reg_command (c), command);
441 }
442
443 /* Reads a sector from channel C's data register in PIO mode into
444    SECTOR, which must have room for DISK_SECTOR_SIZE bytes. */
445 static void
446 input_sector (struct channel *c, void *sector) 
447 {
448   insw (reg_data (c), sector, DISK_SECTOR_SIZE / 2);
449 }
450
451 /* Writes SECTOR to channel C's data register in PIO mode.
452    SECTOR must contain DISK_SECTOR_SIZE bytes. */
453 static void
454 output_sector (struct channel *c, const void *sector) 
455 {
456   outsw (reg_data (c), sector, DISK_SECTOR_SIZE / 2);
457 }
458 \f
459 /* Low-level ATA primitives. */
460
461 /* Wait up to 10 seconds for the controller to become idle, that
462    is, for the BSY and DRQ bits to clear in the status register.
463
464    As a side effect, reading the status register clears any
465    pending interrupt. */
466 static void
467 wait_until_idle (const struct disk *d) 
468 {
469   int i;
470
471   for (i = 0; i < 1000; i++) 
472     {
473       if ((inb (reg_status (d->channel)) & (STA_BSY | STA_DRQ)) == 0)
474         return;
475       timer_sleep (timer_us2ticks (10));
476     }
477
478   printf ("%s: idle timeout\n", d->name);
479 }
480
481 /* Wait up to 30 seconds for disk D to clear BSY,
482    and then return the status of the DRQ bit.
483    The ATA standards say that a disk may take as long as that to
484    complete its reset. */
485 static bool
486 wait_while_busy (const struct disk *d) 
487 {
488   struct channel *c = d->channel;
489   int i;
490   
491   for (i = 0; i < 3000; i++)
492     {
493       if (i == 700)
494         printf ("%s: busy, waiting...", d->name);
495       if (!(inb (reg_alt_status (c)) & STA_BSY)) 
496         {
497           if (i >= 700)
498             printf ("ok\n");
499           return (inb (reg_alt_status (c)) & STA_DRQ) != 0;
500         }
501       timer_sleep (timer_ms2ticks (10));
502     }
503
504   printf ("failed\n");
505   return false;
506 }
507
508 /* Program D's channel so that D is now the selected disk. */
509 static void
510 select_device (const struct disk *d)
511 {
512   struct channel *c = d->channel;
513   uint8_t dev = DEV_MBS;
514   if (d->dev_no == 1)
515     dev |= DEV_DEV;
516   outb (reg_device (c), dev);
517   inb (reg_alt_status (c));
518   timer_sleep (timer_ns2ticks (400));
519 }
520
521 /* Select disk D in its channel, as select_device(), but wait for
522    the channel to become idle before and after. */
523 static void
524 select_device_wait (const struct disk *d) 
525 {
526   wait_until_idle (d);
527   select_device (d);
528   wait_until_idle (d);
529 }
530 \f
531 /* ATA interrupt handler. */
532 static void
533 interrupt_handler (struct intr_frame *f) 
534 {
535   struct channel *c;
536
537   for (c = channels; c < channels + CHANNEL_CNT; c++)
538     if (f->vec_no == c->irq)
539       {
540         if (c->expecting_interrupt) 
541           {
542             inb (reg_status (c));               /* Acknowledge interrupt. */
543             sema_up (&c->completion_wait);      /* Wake up waiter. */
544           }
545         else
546           printf ("%s: unexpected interrupt\n", c->name);
547         return;
548       }
549
550   NOT_REACHED ();
551 }
552
553