#include #include #include #include /* memory dedicated to the block cache */ #define BSTART 0x80000 #define BEND 0xA0000 static struct buffer *lru; static struct buffer *mru; struct buffer *buffer_get_block(uint16_t device, uint16_t block); void buffer_init(void) { int c = 0; struct buffer *last = NULL; struct buffer *b = (struct buffer*) BSTART; void *d = (void*) (BEND - BLOCK_SIZE); while(d > (void*) b) { memset(b, 0, sizeof(struct buffer)); b->b_data = d; b->b_prev = last; if(last) last->b_next = b; last = b; b = (struct buffer*) ((void*) b + sizeof(struct buffer)); d = (void*) (d - (void*) BLOCK_SIZE); c++; } lru = (struct buffer*) BSTART; mru = last; printk("[buf] Buffers initialized (0x%x buffers in pool)\n", c); } struct buffer *buffer_get_block(uint16_t device, uint16_t block) { int ret; struct buffer **p = &mru; struct buffer *b; /* check if the requested block is already in the cache */ while(*p) { if((*p)->b_device == device && (*p)->b_block == block) { /* put the buffer back at the MRU end of the list */ (*p)->b_next = NULL; (*p)->b_prev = mru; mru = *p; return *p; } p = &(*p)->b_prev; } /* find a buffer at the end of the LRU list */ b = lru; lru = lru->b_next; lru->b_prev = NULL; ret = block_read(b->b_data, block); /* abort if we failed to read in the block */ if(ret < 0) { /* release the allocated buffer to the pool */ lru->b_prev = b; b->b_next = lru; b->b_prev = NULL; lru = b; return NULL; } b->b_device = device; b->b_block = block; /* put the buffer back at the MRU end of the list */ b->b_next = NULL; b->b_prev = mru; mru = b; return b; }