CS318 - Pintos
Pintos source browser for JHU CS318 course
ide.c
Go to the documentation of this file.
1 #include "devices/ide.h"
2 #include <ctype.h>
3 #include <debug.h>
4 #include <stdbool.h>
5 #include <stdio.h>
6 #include "devices/block.h"
7 #include "devices/partition.h"
8 #include "devices/timer.h"
9 #include "threads/io.h"
10 #include "threads/interrupt.h"
11 #include "threads/synch.h"
12 
13 /** The code in this file is an interface to an ATA (IDE)
14  controller. It attempts to comply to [ATA-3]. */
15 
16 /** ATA command block port addresses. */
17 #define reg_data(CHANNEL) ((CHANNEL)->reg_base + 0) /**< Data. */
18 #define reg_error(CHANNEL) ((CHANNEL)->reg_base + 1) /**< Error. */
19 #define reg_nsect(CHANNEL) ((CHANNEL)->reg_base + 2) /**< Sector Count. */
20 #define reg_lbal(CHANNEL) ((CHANNEL)->reg_base + 3) /**< LBA 0:7. */
21 #define reg_lbam(CHANNEL) ((CHANNEL)->reg_base + 4) /**< LBA 15:8. */
22 #define reg_lbah(CHANNEL) ((CHANNEL)->reg_base + 5) /**< LBA 23:16. */
23 #define reg_device(CHANNEL) ((CHANNEL)->reg_base + 6) /**< Device/LBA 27:24. */
24 #define reg_status(CHANNEL) ((CHANNEL)->reg_base + 7) /**< Status (r/o). */
25 #define reg_command(CHANNEL) reg_status (CHANNEL) /**< Command (w/o). */
26 
27 /** ATA control block port addresses.
28  (If we supported non-legacy ATA controllers this would not be
29  flexible enough, but it's fine for what we do.) */
30 #define reg_ctl(CHANNEL) ((CHANNEL)->reg_base + 0x206) /**< Control (w/o). */
31 #define reg_alt_status(CHANNEL) reg_ctl (CHANNEL) /**< Alt Status (r/o). */
32 
33 /** Alternate Status Register bits. */
34 #define STA_BSY 0x80 /**< Busy. */
35 #define STA_DRDY 0x40 /**< Device Ready. */
36 #define STA_DRQ 0x08 /**< Data Request. */
37 
38 /** Control Register bits. */
39 #define CTL_SRST 0x04 /**< Software Reset. */
40 
41 /** Device Register bits. */
42 #define DEV_MBS 0xa0 /**< Must be set. */
43 #define DEV_LBA 0x40 /**< Linear based addressing. */
44 #define DEV_DEV 0x10 /**< Select device: 0=master, 1=slave. */
45 
46 /** Commands.
47  Many more are defined but this is the small subset that we
48  use. */
49 #define CMD_IDENTIFY_DEVICE 0xec /**< IDENTIFY DEVICE. */
50 #define CMD_READ_SECTOR_RETRY 0x20 /**< READ SECTOR with retries. */
51 #define CMD_WRITE_SECTOR_RETRY 0x30 /**< WRITE SECTOR with retries. */
52 
53 /** An ATA device. */
54 struct ata_disk
55  {
56  char name[8]; /**< Name, e.g. "hda". */
57  struct channel *channel; /**< Channel that disk is attached to. */
58  int dev_no; /**< Device 0 or 1 for master or slave. */
59  bool is_ata; /**< Is device an ATA disk? */
60  };
61 
62 /** An ATA channel (aka controller).
63  Each channel can control up to two disks. */
64 struct channel
65  {
66  char name[8]; /**< Name, e.g. "ide0". */
67  uint16_t reg_base; /**< Base I/O port. */
68  uint8_t irq; /**< Interrupt in use. */
69 
70  struct lock lock; /**< Must acquire to access the controller. */
71  bool expecting_interrupt; /**< True if an interrupt is expected, false if
72  any interrupt would be spurious. */
73  struct semaphore completion_wait; /**< Up'd by interrupt handler. */
74 
75  struct ata_disk devices[2]; /**< The devices on this channel. */
76  };
77 
78 /** We support the two "legacy" ATA channels found in a standard PC. */
79 #define CHANNEL_CNT 2
80 static struct channel channels[CHANNEL_CNT];
81 
83 
84 static void reset_channel (struct channel *);
85 static bool check_device_type (struct ata_disk *);
86 static void identify_ata_device (struct ata_disk *);
87 
88 static void select_sector (struct ata_disk *, block_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 ata_disk *);
94 static bool wait_while_busy (const struct ata_disk *);
95 static void select_device (const struct ata_disk *);
96 static void select_device_wait (const struct ata_disk *);
97 
98 static void interrupt_handler (struct intr_frame *);
99 
100 /** Initialize the disk subsystem and detect disks. */
101 void
102 ide_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, "ide%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);
127  c->expecting_interrupt = false;
128  sema_init (&c->completion_wait, 0);
129 
130  /* Initialize devices. */
131  for (dev_no = 0; dev_no < 2; dev_no++)
132  {
133  struct ata_disk *d = &c->devices[dev_no];
134  snprintf (d->name, sizeof d->name,
135  "hd%c", 'a' + chan_no * 2 + dev_no);
136  d->channel = c;
137  d->dev_no = dev_no;
138  d->is_ata = false;
139  }
140 
141  /* Register interrupt handler. */
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)
155  }
156 }
157 
158 /** Disk detection and identification. */
159 
160 static char *descramble_ata_string (char *, int size);
161 
162 /** Resets an ATA channel and waits for any devices present on it
163  to finish the reset. */
164 static void
165 reset_channel (struct channel *c)
166 {
167  bool present[2];
168  int dev_no;
169 
170  /* The ATA reset sequence depends on which devices are present,
171  so we start by detecting device presence. */
172  for (dev_no = 0; dev_no < 2; dev_no++)
173  {
174  struct ata_disk *d = &c->devices[dev_no];
175 
176  select_device (d);
177 
178  outb (reg_nsect (c), 0x55);
179  outb (reg_lbal (c), 0xaa);
180 
181  outb (reg_nsect (c), 0xaa);
182  outb (reg_lbal (c), 0x55);
183 
184  outb (reg_nsect (c), 0x55);
185  outb (reg_lbal (c), 0xaa);
186 
187  present[dev_no] = (inb (reg_nsect (c)) == 0x55
188  && inb (reg_lbal (c)) == 0xaa);
189  }
190 
191  /* Issue soft reset sequence, which selects device 0 as a side effect.
192  Also enable interrupts. */
193  outb (reg_ctl (c), 0);
194  timer_usleep (10);
195  outb (reg_ctl (c), CTL_SRST);
196  timer_usleep (10);
197  outb (reg_ctl (c), 0);
198 
199  timer_msleep (150);
200 
201  /* Wait for device 0 to clear BSY. */
202  if (present[0])
203  {
204  select_device (&c->devices[0]);
205  wait_while_busy (&c->devices[0]);
206  }
207 
208  /* Wait for device 1 to clear BSY. */
209  if (present[1])
210  {
211  int i;
212 
213  select_device (&c->devices[1]);
214  for (i = 0; i < 3000; i++)
215  {
216  if (inb (reg_nsect (c)) == 1 && inb (reg_lbal (c)) == 1)
217  break;
218  timer_msleep (10);
219  }
220  wait_while_busy (&c->devices[1]);
221  }
222 }
223 
224 /** Checks whether device D is an ATA disk and sets D's is_ata
225  member appropriately. If D is device 0 (master), returns true
226  if it's possible that a slave (device 1) exists on this
227  channel. If D is device 1 (slave), the return value is not
228  meaningful. */
229 static bool
231 {
232  struct channel *c = d->channel;
233  uint8_t error, lbam, lbah, status;
234 
235  select_device (d);
236 
237  error = inb (reg_error (c));
238  lbam = inb (reg_lbam (c));
239  lbah = inb (reg_lbah (c));
240  status = inb (reg_status (c));
241 
242  if ((error != 1 && (error != 0x81 || d->dev_no == 1))
243  || (status & STA_DRDY) == 0
244  || (status & STA_BSY) != 0)
245  {
246  d->is_ata = false;
247  return error != 0x81;
248  }
249  else
250  {
251  d->is_ata = (lbam == 0 && lbah == 0) || (lbam == 0x3c && lbah == 0xc3);
252  return true;
253  }
254 }
255 
256 /** Sends an IDENTIFY DEVICE command to disk D and reads the
257  response. Registers the disk with the block device
258  layer. */
259 static void
261 {
262  struct channel *c = d->channel;
263  char id[BLOCK_SECTOR_SIZE];
264  block_sector_t capacity;
265  char *model, *serial;
266  char extra_info[128];
267  struct block *block;
268 
269  ASSERT (d->is_ata);
270 
271  /* Send the IDENTIFY DEVICE command, wait for an interrupt
272  indicating the device's response is ready, and read the data
273  into our buffer. */
274  select_device_wait (d);
277  if (!wait_while_busy (d))
278  {
279  d->is_ata = false;
280  return;
281  }
282  input_sector (c, id);
283 
284  /* Calculate capacity.
285  Read model name and serial number. */
286  capacity = *(uint32_t *) &id[60 * 2];
287  model = descramble_ata_string (&id[10 * 2], 20);
288  serial = descramble_ata_string (&id[27 * 2], 40);
289  snprintf (extra_info, sizeof extra_info,
290  "model \"%s\", serial \"%s\"", model, serial);
291 
292  /* Disable access to IDE disks over 1 GB, which are likely
293  physical IDE disks rather than virtual ones. If we don't
294  allow access to those, we're less likely to scribble on
295  someone's important data. You can disable this check by
296  hand if you really want to do so. */
297  if (capacity >= 1024 * 1024 * 1024 / BLOCK_SECTOR_SIZE)
298  {
299  printf ("%s: ignoring ", d->name);
300  print_human_readable_size (capacity * 512);
301  printf ("disk for safety\n");
302  d->is_ata = false;
303  return;
304  }
305 
306  /* Register. */
307  block = block_register (d->name, BLOCK_RAW, extra_info, capacity,
308  &ide_operations, d);
310 }
311 
312 /** Translates STRING, which consists of SIZE bytes in a funky
313  format, into a null-terminated string in-place. Drops
314  trailing whitespace and null bytes. Returns STRING. */
315 static char *
316 descramble_ata_string (char *string, int size)
317 {
318  int i;
319 
320  /* Swap all pairs of bytes. */
321  for (i = 0; i + 1 < size; i += 2)
322  {
323  char tmp = string[i];
324  string[i] = string[i + 1];
325  string[i + 1] = tmp;
326  }
327 
328  /* Find the last non-white, non-null character. */
329  for (size--; size > 0; size--)
330  {
331  int c = string[size - 1];
332  if (c != '\0' && !isspace (c))
333  break;
334  }
335  string[size] = '\0';
336 
337  return string;
338 }
339 
340 /** Reads sector SEC_NO from disk D into BUFFER, which must have
341  room for BLOCK_SECTOR_SIZE bytes.
342  Internally synchronizes accesses to disks, so external
343  per-disk locking is unneeded. */
344 static void
345 ide_read (void *d_, block_sector_t sec_no, void *buffer)
346 {
347  struct ata_disk *d = d_;
348  struct channel *c = d->channel;
349  lock_acquire (&c->lock);
350  select_sector (d, sec_no);
353  if (!wait_while_busy (d))
354  PANIC ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no);
355  input_sector (c, buffer);
356  lock_release (&c->lock);
357 }
358 
359 /** Write sector SEC_NO to disk D from BUFFER, which must contain
360  BLOCK_SECTOR_SIZE bytes. Returns after the disk has
361  acknowledged receiving the data.
362  Internally synchronizes accesses to disks, so external
363  per-disk locking is unneeded. */
364 static void
365 ide_write (void *d_, block_sector_t sec_no, const void *buffer)
366 {
367  struct ata_disk *d = d_;
368  struct channel *c = d->channel;
369  lock_acquire (&c->lock);
370  select_sector (d, sec_no);
372  if (!wait_while_busy (d))
373  PANIC ("%s: disk write failed, sector=%"PRDSNu, d->name, sec_no);
374  output_sector (c, buffer);
376  lock_release (&c->lock);
377 }
378 
379 static struct block_operations ide_operations =
380  {
381  ide_read,
382  ide_write
383  };
384 
385 /** Selects device D, waiting for it to become ready, and then
386  writes SEC_NO to the disk's sector selection registers. (We
387  use LBA mode.) */
388 static void
390 {
391  struct channel *c = d->channel;
392 
393  ASSERT (sec_no < (1UL << 28));
394 
395  select_device_wait (d);
396  outb (reg_nsect (c), 1);
397  outb (reg_lbal (c), sec_no);
398  outb (reg_lbam (c), sec_no >> 8);
399  outb (reg_lbah (c), (sec_no >> 16));
400  outb (reg_device (c),
401  DEV_MBS | DEV_LBA | (d->dev_no == 1 ? DEV_DEV : 0) | (sec_no >> 24));
402 }
403 
404 /** Writes COMMAND to channel C and prepares for receiving a
405  completion interrupt. */
406 static void
407 issue_pio_command (struct channel *c, uint8_t command)
408 {
409  /* Interrupts must be enabled or our semaphore will never be
410  up'd by the completion handler. */
411  ASSERT (intr_get_level () == INTR_ON);
412 
413  c->expecting_interrupt = true;
414  outb (reg_command (c), command);
415 }
416 
417 /** Reads a sector from channel C's data register in PIO mode into
418  SECTOR, which must have room for BLOCK_SECTOR_SIZE bytes. */
419 static void
420 input_sector (struct channel *c, void *sector)
421 {
422  insw (reg_data (c), sector, BLOCK_SECTOR_SIZE / 2);
423 }
424 
425 /** Writes SECTOR to channel C's data register in PIO mode.
426  SECTOR must contain BLOCK_SECTOR_SIZE bytes. */
427 static void
428 output_sector (struct channel *c, const void *sector)
429 {
430  outsw (reg_data (c), sector, BLOCK_SECTOR_SIZE / 2);
431 }
432 
433 /** Low-level ATA primitives. */
434 
435 /** Wait up to 10 seconds for the controller to become idle, that
436  is, for the BSY and DRQ bits to clear in the status register.
437 
438  As a side effect, reading the status register clears any
439  pending interrupt. */
440 static void
441 wait_until_idle (const struct ata_disk *d)
442 {
443  int i;
444 
445  for (i = 0; i < 1000; i++)
446  {
447  if ((inb (reg_status (d->channel)) & (STA_BSY | STA_DRQ)) == 0)
448  return;
449  timer_usleep (10);
450  }
451 
452  printf ("%s: idle timeout\n", d->name);
453 }
454 
455 /** Wait up to 30 seconds for disk D to clear BSY,
456  and then return the status of the DRQ bit.
457  The ATA standards say that a disk may take as long as that to
458  complete its reset. */
459 static bool
460 wait_while_busy (const struct ata_disk *d)
461 {
462  struct channel *c = d->channel;
463  int i;
464 
465  for (i = 0; i < 3000; i++)
466  {
467  if (i == 700)
468  printf ("%s: busy, waiting...", d->name);
469  if (!(inb (reg_alt_status (c)) & STA_BSY))
470  {
471  if (i >= 700)
472  printf ("ok\n");
473  return (inb (reg_alt_status (c)) & STA_DRQ) != 0;
474  }
475  timer_msleep (10);
476  }
477 
478  printf ("failed\n");
479  return false;
480 }
481 
482 /** Program D's channel so that D is now the selected disk. */
483 static void
484 select_device (const struct ata_disk *d)
485 {
486  struct channel *c = d->channel;
487  uint8_t dev = DEV_MBS;
488  if (d->dev_no == 1)
489  dev |= DEV_DEV;
490  outb (reg_device (c), dev);
491  inb (reg_alt_status (c));
492  timer_nsleep (400);
493 }
494 
495 /** Select disk D in its channel, as select_device(), but wait for
496  the channel to become idle before and after. */
497 static void
498 select_device_wait (const struct ata_disk *d)
499 {
500  wait_until_idle (d);
501  select_device (d);
502  wait_until_idle (d);
503 }
504 
505 /** ATA interrupt handler. */
506 static void
508 {
509  struct channel *c;
510 
511  for (c = channels; c < channels + CHANNEL_CNT; c++)
512  if (f->vec_no == c->irq)
513  {
514  if (c->expecting_interrupt)
515  {
516  inb (reg_status (c)); /**< Acknowledge interrupt. */
517  sema_up (&c->completion_wait); /**< Wake up waiter. */
518  }
519  else
520  printf ("%s: unexpected interrupt\n", c->name);
521  return;
522  }
523 
524  NOT_REACHED ();
525 }
526 
527 
interrupt_handler
static void interrupt_handler(struct intr_frame *)
ATA interrupt handler.
Definition: ide.c:507
timer_nsleep
void timer_nsleep(int64_t ns)
Sleeps for approximately NS nanoseconds.
Definition: timer.c:118
block.h
snprintf
int snprintf(char *buffer, size_t buf_size, const char *format,...)
Like printf(), except that output is stored into BUFFER, which must have space for BUF_SIZE character...
Definition: stdio.c:62
uint8_t
unsigned char uint8_t
Definition: stdint.h:20
timer_msleep
void timer_msleep(int64_t ms)
Sleeps for approximately MS milliseconds.
Definition: timer.c:102
issue_pio_command
static void issue_pio_command(struct channel *, uint8_t command)
Writes COMMAND to channel C and prepares for receiving a completion interrupt.
Definition: ide.c:407
lock_release
void lock_release(struct lock *lock)
Releases LOCK, which must be owned by the current thread.
Definition: synch.c:229
reg_lbah
#define reg_lbah(CHANNEL)
LBA 23:16.
Definition: ide.c:22
reg_error
#define reg_error(CHANNEL)
Error.
Definition: ide.c:18
CMD_IDENTIFY_DEVICE
#define CMD_IDENTIFY_DEVICE
Commands.
Definition: ide.c:49
descramble_ata_string
static char * descramble_ata_string(char *, int size)
Disk detection and identification.
Definition: ide.c:316
lock_init
void lock_init(struct lock *lock)
Initializes LOCK.
Definition: synch.c:176
channels
static struct channel channels[CHANNEL_CNT]
Definition: ide.c:80
block_operations
Lower-level interface to block device drivers.
Definition: block.h:64
CTL_SRST
#define CTL_SRST
Control Register bits.
Definition: ide.c:39
semaphore
A counting semaphore.
Definition: synch.h:8
channel::irq
uint8_t irq
Interrupt in use.
Definition: ide.c:68
reg_device
#define reg_device(CHANNEL)
Device/LBA 27:24.
Definition: ide.c:23
insw
static void insw(uint16_t port, void *addr, size_t cnt)
Reads CNT 16-bit (halfword) units from PORT, one after another, and stores them into the buffer start...
Definition: io.h:39
uint16_t
unsigned short int uint16_t
Definition: stdint.h:23
ata_disk::name
char name[8]
Name, e.g.
Definition: ide.c:56
outsw
static void outsw(uint16_t port, const void *addr, size_t cnt)
Writes to PORT each 16-bit unit (halfword) of data in the CNT-halfword buffer starting at ADDR.
Definition: io.h:92
stdbool.h
sema_up
void sema_up(struct semaphore *sema)
Up or "V" operation on a semaphore.
Definition: synch.c:109
select_device
static void select_device(const struct ata_disk *)
Program D's channel so that D is now the selected disk.
Definition: ide.c:484
block::size
block_sector_t size
Size in sectors.
Definition: block.c:15
block_sector_t
uint32_t block_sector_t
Index of a block device sector.
Definition: block.h:15
ata_disk::is_ata
bool is_ata
Is device an ATA disk?
Definition: ide.c:59
NOT_REACHED
#define NOT_REACHED()
lib/debug.h
Definition: debug.h:35
STA_BSY
#define STA_BSY
Alternate Status Register bits.
Definition: ide.c:34
PANIC
#define PANIC(...)
Halts the OS, printing the source file name, line number, and function name, plus a user-specific mes...
Definition: debug.h:14
channel::expecting_interrupt
bool expecting_interrupt
True if an interrupt is expected, false if any interrupt would be spurious.
Definition: ide.c:71
reg_nsect
#define reg_nsect(CHANNEL)
Sector Count.
Definition: ide.c:19
channel::devices
struct ata_disk devices[2]
The devices on this channel.
Definition: ide.c:75
select_device_wait
static void select_device_wait(const struct ata_disk *)
Select disk D in its channel, as select_device(), but wait for the channel to become idle before and ...
Definition: ide.c:498
wait_until_idle
static void wait_until_idle(const struct ata_disk *)
Low-level ATA primitives.
Definition: ide.c:441
BLOCK_RAW
"Raw" device with unidentified contents.
Definition: block.h:37
DEV_MBS
#define DEV_MBS
Device Register bits.
Definition: ide.c:42
channel::name
char name[8]
Name, e.g.
Definition: ide.c:66
STA_DRQ
#define STA_DRQ
Data Request.
Definition: ide.c:36
ctype.h
interrupt.h
uint32_t
unsigned int uint32_t
Definition: stdint.h:26
channel::completion_wait
struct semaphore completion_wait
Up'd by interrupt handler.
Definition: ide.c:73
reg_lbam
#define reg_lbam(CHANNEL)
LBA 15:8.
Definition: ide.c:21
isspace
static int isspace(int c)
Definition: ctype.h:12
reg_status
#define reg_status(CHANNEL)
Status (r/o).
Definition: ide.c:24
buffer
static struct intq buffer
Stores keys from the keyboard and serial port.
Definition: input.c:7
printf
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
CHANNEL_CNT
#define CHANNEL_CNT
We support the two "legacy" ATA channels found in a standard PC.
Definition: ide.c:79
ata_disk
An ATA device.
Definition: ide.c:54
PRDSNu
#define PRDSNu
Format specifier for printf(), e.g.
Definition: block.h:19
intr_get_level
enum intr_level intr_get_level(void)
Returns the current interrupt status.
Definition: interrupt.c:65
DEV_DEV
#define DEV_DEV
Select device: 0=master, 1=slave.
Definition: ide.c:44
ata_disk::dev_no
int dev_no
Device 0 or 1 for master or slave.
Definition: ide.c:58
timer.h
wait_while_busy
static bool wait_while_busy(const struct ata_disk *)
Wait up to 30 seconds for disk D to clear BSY, and then return the status of the DRQ bit.
Definition: ide.c:460
input_sector
static void input_sector(struct channel *, void *)
Reads a sector from channel C's data register in PIO mode into SECTOR, which must have room for BLOCK...
Definition: ide.c:420
reg_ctl
#define reg_ctl(CHANNEL)
ATA control block port addresses.
Definition: ide.c:30
sema_down
void sema_down(struct semaphore *sema)
Down or "P" operation on a semaphore.
Definition: synch.c:61
ide_init
void ide_init(void)
Initialize the disk subsystem and detect disks.
Definition: ide.c:102
DEV_LBA
#define DEV_LBA
Linear based addressing.
Definition: ide.c:43
reg_data
#define reg_data(CHANNEL)
The code in this file is an interface to an ATA (IDE) controller.
Definition: ide.c:17
ide.h
ide_operations
static struct block_operations ide_operations
Definition: ide.c:82
reg_lbal
#define reg_lbal(CHANNEL)
LBA 0:7.
Definition: ide.c:20
identify_ata_device
static void identify_ata_device(struct ata_disk *)
Sends an IDENTIFY DEVICE command to disk D and reads the response.
Definition: ide.c:260
ASSERT
#define ASSERT(CONDITION)
This is outside the header guard so that debug.h may be included multiple times with different settin...
Definition: debug.h:31
sema_init
void sema_init(struct semaphore *sema, unsigned value)
This file is derived from source code for the Nachos instructional operating system.
Definition: synch.c:45
CMD_WRITE_SECTOR_RETRY
#define CMD_WRITE_SECTOR_RETRY
WRITE SECTOR with retries.
Definition: ide.c:51
outb
static void outb(uint16_t port, uint8_t data)
Writes byte DATA to PORT.
Definition: io.h:66
block
A block device.
Definition: block.c:9
partition.h
reg_alt_status
#define reg_alt_status(CHANNEL)
Alt Status (r/o).
Definition: ide.c:31
BLOCK_SECTOR_SIZE
#define BLOCK_SECTOR_SIZE
Size of a block device sector in bytes.
Definition: block.h:11
inb
static uint8_t inb(uint16_t port)
Reads and returns a byte from PORT.
Definition: io.h:9
timer_usleep
void timer_usleep(int64_t us)
Sleeps for approximately US microseconds.
Definition: timer.c:110
io.h
print_human_readable_size
void print_human_readable_size(uint64_t size)
Prints SIZE, which represents a number of bytes, in a human-readable format, e.g.
Definition: stdio.c:642
STA_DRDY
#define STA_DRDY
Device Ready.
Definition: ide.c:35
intr_frame::vec_no
uint16_t uint16_t uint16_t uint16_t uint32_t vec_no
Saved DS segment register.
Definition: interrupt.h:32
intr_register_ext
void intr_register_ext(uint8_t vec_no, intr_handler_func *handler, const char *name)
Registers external interrupt VEC_NO to invoke HANDLER, which is named NAME for debugging purposes.
Definition: interrupt.c:181
intr_frame
Interrupt stack frame.
Definition: interrupt.h:20
lock_acquire
void lock_acquire(struct lock *lock)
Acquires LOCK, sleeping until it becomes available if necessary.
Definition: synch.c:193
channel::reg_base
uint16_t reg_base
Base I/O port.
Definition: ide.c:67
channel::lock
struct lock lock
Must acquire to access the controller.
Definition: ide.c:70
CMD_READ_SECTOR_RETRY
#define CMD_READ_SECTOR_RETRY
READ SECTOR with retries.
Definition: ide.c:50
select_sector
static void select_sector(struct ata_disk *, block_sector_t)
Selects device D, waiting for it to become ready, and then writes SEC_NO to the disk's sector selecti...
Definition: ide.c:389
synch.h
channel
An ATA channel (aka controller).
Definition: ide.c:64
lock
Lock.
Definition: synch.h:21
ata_disk::channel
struct channel * channel
Channel that disk is attached to.
Definition: ide.c:57
ide_write
static void ide_write(void *d_, block_sector_t sec_no, const void *buffer)
Write sector SEC_NO to disk D from BUFFER, which must contain BLOCK_SECTOR_SIZE bytes.
Definition: ide.c:365
reg_command
#define reg_command(CHANNEL)
Command (w/o).
Definition: ide.c:25
partition_scan
void partition_scan(struct block *block)
Scans BLOCK for partitions of interest to Pintos.
Definition: partition.c:28
debug.h
ide_read
static void ide_read(void *d_, block_sector_t sec_no, void *buffer)
Reads sector SEC_NO from disk D into BUFFER, which must have room for BLOCK_SECTOR_SIZE bytes.
Definition: ide.c:345
INTR_ON
Interrupts enabled.
Definition: interrupt.h:11
block_register
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)
Registers a new block device with the given NAME.
Definition: block.c:187
check_device_type
static bool check_device_type(struct ata_disk *)
Checks whether device D is an ATA disk and sets D's is_ata member appropriately.
Definition: ide.c:230
reset_channel
static void reset_channel(struct channel *)
Resets an ATA channel and waits for any devices present on it to finish the reset.
Definition: ide.c:165
output_sector
static void output_sector(struct channel *, const void *)
Writes SECTOR to channel C's data register in PIO mode.
Definition: ide.c:428