make it work on one cpu
make it work on a real machine
release before acquire at end of sleep?
+check 2nd disk (i.e. if not in .bochsrc)
extern struct spinlock ide_lock;
b = getblk(dev, sector);
- if(b->flags & B_VALID){
+ if(b->flags & B_VALID)
return b;
- }
acquire(&ide_lock);
c = ide_start_rw(dev & 0xff, sector, b->data, 1, 1);
struct inode * iget(uint dev, uint inum);
void ilock(struct inode *ip);
void iunlock(struct inode *ip);
+void itrunc(struct inode *ip);
void idecref(struct inode *ip);
void iincref(struct inode *ip);
void iput(struct inode *ip);
initlock(&inode_table_lock, "inode_table");
}
+/*
+ * allocate a disk block
+ */
static uint
balloc(uint dev)
{
}
}
if (b >= size)
- panic("balloc: out of blocks\n");
+ panic("balloc: out of blocks");
bp->data[bi/8] |= 0x1 << (bi % 8);
bwrite (bp, BBLOCK(b, ninodes)); // mark it allocated on disk
brelse(bp);
}
-// returns an inode with busy set and incremented reference count.
+/*
+ * fetch an inode, from the in-core table if it's already
+ * in use, otherwise read from the disk.
+ * returns an inode with busy set and incremented reference count.
+ */
struct inode *
iget(uint dev, uint inum)
{
}
if (inum >= ninodes)
- panic ("ialloc: no inodes left\n");
+ panic ("ialloc: no inodes left");
+ memset(dip, 0, sizeof(*dip));
dip->type = type;
bwrite (bp, IBLOCK(inum)); // mark it allocated on the disk
brelse(bp);
}
void
-iunlink(struct inode *ip)
+itrunc(struct inode *ip)
{
int i, j;
struct buf *inbp;
- // free inode, its blocks, and remove dir entry
for (i = 0; i < NADDRS; i++) {
if (ip->addrs[i] != 0) {
if (i == INDIRECT) {
}
}
ip->size = 0;
- ip->major = 0;
- ip->minor = 0;
iupdate(ip);
- ifree(ip); // is this the right order?
}
// caller is releasing a reference to this inode.
if(ip->count < 1 || ip->busy != 1)
panic("iput");
- if ((ip->count == 1) && (ip->nlink == 0))
- iunlink(ip);
+ if ((ip->count == 1) && (ip->nlink == 0)) {
+ itrunc(ip);
+ ifree(ip);
+ }
acquire(&inode_table_lock);
}
return r;
} else {
- panic ("writei: unknown type\n");
+ panic ("writei: unknown type");
return 0;
}
}
int i, atend;
unsigned ninum;
- if(mode == NAMEI_DELETE && ret_off == 0)
- panic("namei no ret_off");
- if(mode == NAMEI_CREATE && ret_last == 0)
- panic("namei no ret_last");
if(ret_off)
*ret_off = 0xffffffff;
if(ret_last)
struct dirent de;
int i;
- if(name[0] == '\0')
- panic("wdir no name");
-
for(off = 0; off < dp->size; off += sizeof(de)){
if(readi(dp, (char *) &de, off, sizeof(de)) != sizeof(de))
panic("wdir read");
}
de.inum = ino;
- for(i = 0; i < DIRSIZ && name[i]; i++){
- if(name[i] == '/')
- panic("wdir /");
+ for(i = 0; i < DIRSIZ && name[i]; i++)
de.name[i] = name[i];
- }
for( ; i < DIRSIZ; i++)
de.name[i] = '\0';
struct inode *ip;
ip = ialloc(dp->dev, type);
- if (ip == 0) {
- iput(dp);
+ if (ip == 0)
return 0;
- }
ip->major = major;
ip->minor = minor;
ip->size = 0;
/*
- * Minimal PIO-based (non-interrupt-driven) IDE driver code.
- * For information about what all this IDE/ATA magic means,
- * see the materials available on the class references page.
+ * Simple PIO-based (non-DMA) IDE driver code.
*/
#include "types.h"
struct ide_request request[NREQUEST];
int head, tail;
struct spinlock ide_lock;
-
+int disk_1_present;
int disk_channel;
+int ide_probe_disk1(void);
+
static int
ide_wait_ready(int check_error)
{
ide_init(void)
{
initlock(&ide_lock, "ide");
- if (ncpu < 2) {
- panic ("ide_init: disk interrupt is going to the second cpu\n");
- }
- ioapic_enable (IRQ_IDE, 1);
+ ioapic_enable (IRQ_IDE, ncpu - 1);
ide_wait_ready(0);
+ disk_1_present = ide_probe_disk1();
}
void
// switch back to Device 0
outb(0x1F6, 0xE0 | (0<<4));
- cprintf("Device 1 presence: %d\n", (x < 1000));
return (x < 1000);
}
{
struct ide_request *r;
- if(!holding(&ide_lock))
- panic("ide_start_read: not holding ide_lock");
-
- if(nsecs > 1)
- panic("ide_start_read: nsecs too large");
+ if(diskno && !disk_1_present)
+ panic("ide disk 1 not present");
while ((head + 1) % NREQUEST == tail)
sleep (&disk_channel, &ide_lock);
int r;
struct ide_request *req = (struct ide_request *) c;
- if(c != &request[tail])
- panic("ide_finish_read");
-
- if(!holding(&ide_lock))
- panic("ide_start_read: not holding ide_lock");
-
if (req->read) {
if ((r = ide_wait_ready(1)) >= 0)
insl(0x1F0, req->addr, 512/4);
};
struct run *freelist;
-void ktest(void);
-
/*
* initialize free list of physical pages. this code
* cheats by just considering the one megabyte of pages
mem = 256; // XXX
cprintf("mem = %d\n", mem * PAGE);
kfree(start, mem * PAGE);
- ktest();
}
void
rr = &(*rr)->next;
}
release(&kalloc_lock);
+ cprintf("kalloc: out of memory\n");
return 0;
}
-
-void
-ktest(void)
-{
- char *p1, *p2, *p3;
-
- // test coalescing
- p1 = kalloc(4 * PAGE);
- kfree(p1 + 3*PAGE, PAGE);
- kfree(p1 + 2*PAGE, PAGE);
- kfree(p1, PAGE);
- kfree(p1 + PAGE, PAGE);
- p2 = kalloc(4 * PAGE);
- if(p2 != p1)
- panic("ktest");
- kfree(p2, 4 * PAGE);
-
- // test finding first run that fits
- p1 = kalloc(1 * PAGE);
- p2 = kalloc(1 * PAGE);
- kfree(p1, PAGE);
- p3 = kalloc(2 * PAGE);
- kfree(p2, PAGE);
- kfree(p3, 2 * PAGE);
-
- // test running out of memory
- p1 = 0;
- while((p2 = kalloc(PAGE)) != 0){
- *(char**)p2 = p1;
- p1 = p2;
- }
- while(p1){
- p2 = *(char **)p1;
- kfree(p1, PAGE);
- p1 = p2;
- }
- p1 = kalloc(PAGE * 20);
- if(p1 == 0)
- panic("ktest2");
- kfree(p1, PAGE * 20);
-}
// Copy trapframe registers from parent.
np->tf = (struct trapframe*)(np->kstack + KSTACKSIZE) - 1;
- *np->tf = *p->tf;
+ memmove(np->tf, p->tf, sizeof(*np->tf));
// Clear %eax so that fork system call returns 0 in child.
np->tf->eax = 0;
else
return (int) ((uchar) *p - (uchar) *q);
}
-
-// Memcpy is deprecated and should NOT be called.
-// Use memmove instead, which has defined semantics
-// when the two memory ranges overlap.
-// Memcpy is here only because gcc compiles some
-// structure assignments into calls to memcpy.
-void *
-memcpy(void *dst, void *src, uint n)
-{
- char *d = (char *) dst;
- char *s = (char *) src;
-
- while(n-- > 0)
- *d++ = *s++;
-
- return dst;
-}
-
* Arguments on the stack, from the user call to the C
* library system call function. The saved user %esp points
* to a saved program counter, and then the first argument.
- *
- * Return value? Error indication? Errno?
*/
/*
return 0;
}
-// This arg is void* so that both int* and uint* can be passed.
int
fetcharg(int argno, void *ip)
{
if((l = checkstring(arg0)) < 0)
return -1;
- if(l >= DIRSIZ)
- return -1;
-
if ((ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0)) == 0)
return -1;
return -1;
if(cp->fds[fd] == 0)
return -1;
- if (cp->fds[fd]->type != FD_PIPE && cp->fds[fd]->type != FD_FILE)
+ if ((ufd1 = fd_ualloc()) < 0)
return -1;
- if ((ufd1 = fd_ualloc()) < 0) {
- return -1;
- }
cp->fds[ufd1] = cp->fds[fd];
fd_incref(cp->fds[ufd1]);
return ufd1;
# Generate vectors.S, the trap/interrupt entry points.
# There has to be one entry point per interrupt number
-# since otherwise there's no way to tell the interrupt
-# number.
+# since otherwise there's no way for trap() to discover
+# the interrupt number.
print "/* generated by vectors.pl */\n";
print "/* handlers */\n";