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