PKUOS - Pintos
Pintos source browser for PKU Operating System 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. */
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. */
64struct 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
81
83
84static void reset_channel (struct channel *);
85static bool check_device_type (struct ata_disk *);
86static void identify_ata_device (struct ata_disk *);
87
88static void select_sector (struct ata_disk *, block_sector_t);
89static void issue_pio_command (struct channel *, uint8_t command);
90static void input_sector (struct channel *, void *);
91static void output_sector (struct channel *, const void *);
92
93static void wait_until_idle (const struct ata_disk *);
94static bool wait_while_busy (const struct ata_disk *);
95static void select_device (const struct ata_disk *);
96static void select_device_wait (const struct ata_disk *);
97
98static void interrupt_handler (struct intr_frame *);
99
100/** Initialize the disk subsystem and detect disks. */
101void
102ide_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
160static 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. */
164static void
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. */
229static 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. */
259static 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. */
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. */
315static char *
316descramble_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. */
344static void
345ide_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. */
364static void
365ide_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);
376 lock_release (&c->lock);
377}
378
379static struct block_operations ide_operations =
380 {
381 ide_read,
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.) */
388static void
390{
391 struct channel *c = d->channel;
392
393 ASSERT (sec_no < (1UL << 28));
394
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. */
406static void
407issue_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. */
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. */
419static void
420input_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. */
427static void
428output_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. */
440static void
441wait_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. */
459static bool
460wait_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. */
483static void
484select_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. */
497static void
498select_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. */
506static 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
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
uint32_t block_sector_t
Index of a block device sector.
Definition: block.h:15
#define BLOCK_SECTOR_SIZE
Size of a block device sector in bytes.
Definition: block.h:11
#define PRDSNu
Format specifier for printf(), e.g.
Definition: block.h:19
@ BLOCK_RAW
"Raw" device with unidentified contents.
Definition: block.h:37
static int isspace(int c)
Definition: ctype.h:12
#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
#define NOT_REACHED()
lib/debug.h
Definition: debug.h:35
#define PANIC(...)
Halts the OS, printing the source file name, line number, and function name, plus a user-specific mes...
Definition: debug.h:14
static struct block_operations ide_operations
Definition: ide.c:82
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
#define reg_ctl(CHANNEL)
ATA control block port addresses.
Definition: ide.c:30
#define reg_device(CHANNEL)
Device/LBA 27:24.
Definition: ide.c:23
#define CTL_SRST
Control Register bits.
Definition: ide.c:39
#define DEV_DEV
Select device: 0=master, 1=slave.
Definition: ide.c:44
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
#define CMD_IDENTIFY_DEVICE
Commands.
Definition: ide.c:49
#define DEV_LBA
Linear based addressing.
Definition: ide.c:43
#define reg_data(CHANNEL)
The code in this file is an interface to an ATA (IDE) controller.
Definition: ide.c:17
#define reg_lbal(CHANNEL)
LBA 0:7.
Definition: ide.c:20
#define reg_nsect(CHANNEL)
Sector Count.
Definition: ide.c:19
#define reg_lbah(CHANNEL)
LBA 23:16.
Definition: ide.c:22
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
void ide_init(void)
Initialize the disk subsystem and detect disks.
Definition: ide.c:102
static char * descramble_ata_string(char *, int size)
Disk detection and identification.
Definition: ide.c:316
static void select_device(const struct ata_disk *)
Program D's channel so that D is now the selected disk.
Definition: ide.c:484
#define reg_status(CHANNEL)
Status (r/o).
Definition: ide.c:24
static void output_sector(struct channel *, const void *)
Writes SECTOR to channel C's data register in PIO mode.
Definition: ide.c:428
#define reg_alt_status(CHANNEL)
Alt Status (r/o).
Definition: ide.c:31
#define STA_DRDY
Device Ready.
Definition: ide.c:35
#define STA_DRQ
Data Request.
Definition: ide.c:36
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
static void interrupt_handler(struct intr_frame *)
ATA interrupt handler.
Definition: ide.c:507
#define DEV_MBS
Device Register bits.
Definition: ide.c:42
#define STA_BSY
Alternate Status Register bits.
Definition: ide.c:34
#define reg_error(CHANNEL)
Error.
Definition: ide.c:18
#define CMD_WRITE_SECTOR_RETRY
WRITE SECTOR with retries.
Definition: ide.c:51
#define reg_command(CHANNEL)
Command (w/o).
Definition: ide.c:25
#define CMD_READ_SECTOR_RETRY
READ SECTOR with retries.
Definition: ide.c:50
static void wait_until_idle(const struct ata_disk *)
Low-level ATA primitives.
Definition: ide.c:441
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
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
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
static struct channel channels[CHANNEL_CNT]
Definition: ide.c:80
#define CHANNEL_CNT
We support the two "legacy" ATA channels found in a standard PC.
Definition: ide.c:79
#define reg_lbam(CHANNEL)
LBA 15:8.
Definition: ide.c:21
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
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
static void identify_ata_device(struct ata_disk *)
Sends an IDENTIFY DEVICE command to disk D and reads the response.
Definition: ide.c:260
static struct intq buffer
Stores keys from the keyboard and serial port.
Definition: input.c:7
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
enum intr_level intr_get_level(void)
Returns the current interrupt status.
Definition: interrupt.c:65
@ INTR_ON
Interrupts enabled.
Definition: interrupt.h:11
static uint8_t inb(uint16_t port)
Reads and returns a byte from PORT.
Definition: io.h:9
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
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
static void outb(uint16_t port, uint8_t data)
Writes byte DATA to PORT.
Definition: io.h:66
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
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
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
void partition_scan(struct block *block)
Scans BLOCK for partitions of interest to Pintos.
Definition: partition.c:28
unsigned int uint32_t
Definition: stdint.h:26
unsigned char uint8_t
Definition: stdint.h:20
unsigned short int uint16_t
Definition: stdint.h:23
An ATA device.
Definition: ide.c:55
bool is_ata
Is device an ATA disk?
Definition: ide.c:59
char name[8]
Name, e.g.
Definition: ide.c:56
int dev_no
Device 0 or 1 for master or slave.
Definition: ide.c:58
struct channel * channel
Channel that disk is attached to.
Definition: ide.c:57
Lower-level interface to block device drivers.
Definition: block.h:65
A block device.
Definition: block.c:10
block_sector_t size
Size in sectors.
Definition: block.c:15
An ATA channel (aka controller).
Definition: ide.c:65
struct ata_disk devices[2]
The devices on this channel.
Definition: ide.c:75
bool expecting_interrupt
True if an interrupt is expected, false if any interrupt would be spurious.
Definition: ide.c:71
struct semaphore completion_wait
Up'd by interrupt handler.
Definition: ide.c:73
char name[8]
Name, e.g.
Definition: ide.c:66
uint16_t reg_base
Base I/O port.
Definition: ide.c:67
uint8_t irq
Interrupt in use.
Definition: ide.c:68
struct lock lock
Must acquire to access the controller.
Definition: ide.c:70
Interrupt stack frame.
Definition: interrupt.h:21
uint16_t uint16_t uint16_t uint16_t uint32_t vec_no
Saved DS segment register.
Definition: interrupt.h:35
Lock.
Definition: synch.h:22
A counting semaphore.
Definition: synch.h:9
void lock_release(struct lock *lock)
Releases LOCK, which must be owned by the current thread.
Definition: synch.c:229
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
void sema_up(struct semaphore *sema)
Up or "V" operation on a semaphore.
Definition: synch.c:109
void lock_init(struct lock *lock)
Initializes LOCK.
Definition: synch.c:176
void lock_acquire(struct lock *lock)
Acquires LOCK, sleeping until it becomes available if necessary.
Definition: synch.c:193
void sema_down(struct semaphore *sema)
Down or "P" operation on a semaphore.
Definition: synch.c:61
void timer_msleep(int64_t ms)
Sleeps for approximately MS milliseconds.
Definition: timer.c:102
void timer_nsleep(int64_t ns)
Sleeps for approximately NS nanoseconds.
Definition: timer.c:118
void timer_usleep(int64_t us)
Sleeps for approximately US microseconds.
Definition: timer.c:110