summaryrefslogtreecommitdiff
path: root/package/aboot/src/tools/bio.c
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2017-12-31 18:47:16 +0100
committerWaldemar Brodkorb <wbx@openadk.org>2017-12-31 18:47:25 +0100
commit3a96085b999220c4da0c5ef7d1f7ba26b9ddfb98 (patch)
tree77f1445aae2e6be5135594e95986b3278bbc061c /package/aboot/src/tools/bio.c
parentcc28479164b8dc8afd4310716da32f16022f5974 (diff)
dec-multia: make netboot possible, add aboot bootloader
Diffstat (limited to 'package/aboot/src/tools/bio.c')
-rw-r--r--package/aboot/src/tools/bio.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/package/aboot/src/tools/bio.c b/package/aboot/src/tools/bio.c
new file mode 100644
index 000000000..c82161e62
--- /dev/null
+++ b/package/aboot/src/tools/bio.c
@@ -0,0 +1,178 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Buffered I/O functions. By cacheing the most recently used blocks,
+ * we can cut WAAY down on disk traffic...
+ */
+
+static int bio_fd = -1;
+static int bio_counter = 0;
+static int bio_blocksize = 0;
+
+struct bio_buf {
+ int blkno;
+ int last_access;
+ int dirty;
+ char * data;
+};
+
+#define NBUFS 32
+struct bio_buf buflist[NBUFS];
+
+/* initialize the buffer cache. Blow away anything that may
+ * have been previously cached...
+ */
+void
+binit(int fd, int blocksize)
+{
+ int i;
+
+ bio_fd = fd;
+ bio_blocksize = blocksize;
+
+ for(i = 0; i < NBUFS; i++) {
+ buflist[i].blkno = 0;
+ if(buflist[i].data) {
+ free(buflist[i].data);
+ }
+ buflist[i].data = 0;
+ buflist[i].last_access = 0;
+ buflist[i].dirty = 0;
+ }
+}
+
+/* Flush out any dirty blocks */
+void
+bflush(void)
+{
+ int i;
+
+ for(i = 0; i < NBUFS; i++) {
+ if(buflist[i].dirty) {
+#ifdef BIO_DEBUG
+ printf("bflush: writing block %d\n", buflist[i].blkno);
+#endif
+ lseek(bio_fd, buflist[i].blkno * bio_blocksize, 0);
+ write(bio_fd, buflist[i].data, bio_blocksize);
+ buflist[i].dirty = 0;
+ }
+ }
+}
+
+/* Read a block. */
+void
+bread(int blkno, void * blkbuf)
+{
+ int i;
+ int lowcount;
+ int lowcount_buf;
+
+ /* First, see if the block is already in memory... */
+ for(i = 0; i < NBUFS; i++) {
+ if(buflist[i].blkno == blkno) {
+ /* Got it! Bump the access count and return. */
+ buflist[i].last_access = ++bio_counter;
+#ifdef BIO_DEBUG
+ printf("bread: buffer hit on block %d\n", blkno);
+#endif
+ memcpy(blkbuf, buflist[i].data, bio_blocksize);
+ return;
+ }
+ }
+
+ /* Not in memory; need to find a buffer and read it in. */
+ lowcount = buflist[0].last_access;
+ lowcount_buf = 0;
+ for(i = 1; i < NBUFS; i++) {
+ if(buflist[i].last_access < lowcount) {
+ lowcount = buflist[i].last_access;
+ lowcount_buf = i;
+ }
+ }
+
+ /* If the buffer is dirty, we need to write it out... */
+ if(buflist[lowcount_buf].dirty) {
+#ifdef BIO_DEBUG
+ printf("bread: recycling dirty buffer %d for block %d\n",
+ lowcount_buf, buflist[lowcount_buf].blkno);
+#endif
+ lseek(bio_fd, buflist[lowcount_buf].blkno * bio_blocksize, 0);
+ write(bio_fd, buflist[lowcount_buf].data, bio_blocksize);
+ buflist[lowcount_buf].dirty = 0;
+ }
+
+#ifdef BIO_DEBUG
+ printf("bread: Using buffer %d for block %d\n", lowcount_buf, blkno);
+#endif
+
+ buflist[lowcount_buf].blkno = blkno;
+ if(!buflist[lowcount_buf].data) {
+ buflist[lowcount_buf].data = (char *)malloc(bio_blocksize);
+ }
+ lseek(bio_fd, blkno * bio_blocksize, 0);
+ if(read(bio_fd,buflist[lowcount_buf].data,bio_blocksize)!=bio_blocksize) {
+ perror("bread: I/O error");
+ }
+
+ buflist[lowcount_buf].last_access = ++bio_counter;
+ memcpy(blkbuf, buflist[lowcount_buf].data, bio_blocksize);
+}
+
+
+/* Write a block */
+void
+bwrite(int blkno, void * blkbuf)
+{
+ int i;
+ int lowcount;
+ int lowcount_buf;
+
+ /* First, see if the block is already in memory... */
+ for(i = 0; i < NBUFS; i++) {
+ if(buflist[i].blkno == blkno) {
+ /* Got it! Bump the access count and return. */
+#ifdef BIO_DEBUG
+ printf("bwrite: buffer hit on block %d\n", blkno);
+#endif
+ buflist[i].last_access = ++bio_counter;
+ memcpy(buflist[i].data, blkbuf, bio_blocksize);
+ buflist[i].dirty = 1;
+ return;
+ }
+ }
+
+ /* Not in memory; need to find a buffer and stuff it. */
+ lowcount = buflist[0].last_access;
+ lowcount_buf = 0;
+ for(i = 1; i < NBUFS; i++) {
+ if(buflist[i].last_access < lowcount) {
+ lowcount = buflist[i].last_access;
+ lowcount_buf = i;
+ }
+ }
+
+ /* If the buffer is dirty, we need to write it out... */
+ if(buflist[lowcount_buf].dirty) {
+#ifdef BIO_DEBUG
+ printf("bwrite: recycling dirty buffer %d for block %d\n",
+ lowcount_buf, buflist[lowcount_buf].blkno);
+#endif
+ lseek(bio_fd, buflist[lowcount_buf].blkno * bio_blocksize, 0);
+ write(bio_fd, buflist[lowcount_buf].data, bio_blocksize);
+ buflist[lowcount_buf].dirty = 0;
+ }
+
+#ifdef BIO_DEBUG
+ printf("bwrite: Using buffer %d for block %d\n", lowcount_buf, blkno);
+#endif
+
+ buflist[lowcount_buf].blkno = blkno;
+ if(!buflist[lowcount_buf].data) {
+ buflist[lowcount_buf].data = (char *)malloc(bio_blocksize);
+ }
+ buflist[lowcount_buf].last_access = ++bio_counter;
+ memcpy(buflist[lowcount_buf].data, blkbuf, bio_blocksize);
+ buflist[lowcount_buf].dirty = 1;
+}