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