commit 5ed8c2c199adc81a754b82e42b635d928082f6f3
parent 6955a5907f087d6fb6184c004e26825cb6f245a8
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Thu, 2 May 2019 10:31:47 +0100
[dev] Add seek function pointer to Dev
There are cases where drivers may need to take special actions
when a seek is done. In the same way, there are devices where
seek doesn't kmake sense (for example uart devices) and it is
better to signal an error in such devices instead of ignoring
seek value.
Change-Id: If22a17bfa55dda1236178ab39069c6d985ef2243
Diffstat:
8 files changed, 66 insertions(+), 46 deletions(-)
diff --git a/drivers/dev.c b/drivers/dev.c
@@ -121,7 +121,7 @@ chanclose(Chan *c)
}
int
-buf2chan(Chan *c, void *dst, void *src, int nbytes, unsigned long long len)
+buf2chan(Chan *c, void *dst, void *src, int nbytes, long len)
{
char *addr = src;
@@ -295,7 +295,7 @@ dirread(Chan *c,
void
mkentry(Chan *c, Dir *dir,
- const char *name, unsigned long long length, Qid qid, unsigned mode)
+ const char *name, long length, Qid qid, unsigned mode)
{
strcpy(dir->name, name);
dir->length = length;
@@ -375,22 +375,44 @@ write(int fd, void *buf, int n)
return devtab[c->type]->write(c, buf, n);
}
+int
+seek(int fd, long off, int whence)
+{
+ Chan *c;
+
+ if ((c = fd2chan(fd)) == NULL)
+ return -1;
+
+ if (c->qid & CHDIR) {
+ errno = EISDIR;
+ return -1;
+ }
+
+ return devtab[c->type]->seek(c, off, whence);
+}
+
Chan *
-devmount(Chan *c, char *spec)
+deverrmount(Chan *c, char *spec)
{
errno = EINVAL;
return NULL;
}
int
-devwrite(Chan *c, void *buf, int n)
+deverrwrite(Chan *c, void *buf, int n)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+int deverrseek(Chan *c, long off, int whence)
{
errno = EINVAL;
return -1;
}
int
-devseek(Chan *c, long long off, int whence)
+devseek(Chan *c, long off, int whence)
{
switch (whence) {
case RSEEK_SET:
@@ -407,22 +429,6 @@ devseek(Chan *c, long long off, int whence)
return 0;
}
-int
-seek(int fd, long long off, int whence)
-{
- Chan *c;
-
- if ((c = fd2chan(fd)) == NULL)
- return -1;
-
- if (c->qid & CHDIR) {
- errno = EISDIR;
- return -1;
- }
-
- return devseek(c, off,whence);
-}
-
static int
addmntpoint(Chan *c, char *new)
{
diff --git a/drivers/dev.h b/drivers/dev.h
@@ -17,7 +17,7 @@ typedef struct attr Attr;
struct dirtab {
char name[NAMELEN];
Qid qid;
- unsigned long long length;
+ long length;
unsigned char perm;
void *data;
};
@@ -27,11 +27,12 @@ struct dev {
int (*walk)(Chan *c, const char *name);
int (*read)(Chan *c, void *buf, int n);
int (*write)(Chan *c, void *buf, int n);
+ int (*seek)(Chan *c, long off, int whence);
Chan *(*mount)(Chan *c, char *spec);
};
struct chan {
- unsigned long long offset;
+ long offset;
Qid qid;
unsigned char type;
unsigned char dev;
@@ -45,20 +46,17 @@ struct attr {
extern Chan *devattach(int id, int dev);
-extern int devseek(Chan *c, long long off, int whence);
+extern int devseek(Chan *c, long off, int whence);
extern Chan * namec(const char *name, int mode);
extern Chan *clone(Chan *c, Chan *nc);
extern void chanclose(Chan *c);
extern int buf2chan(Chan *c,
void *dst, void *src,
- int nbytes, unsigned long long len);
+ int nbytes, long len);
extern void mkentry(Chan *c, Dir *dir,
const char *name,
- unsigned long long length, Qid qid, unsigned mode);
-
-extern Chan *devmount(Chan *c, char *spec);
+ long length, Qid qid, unsigned mode);
extern void devlink(void);
-extern int devwrite(Chan *c, void *buf, int n);
extern int devgen(Chan *c,
const Dirtab *tab, int ntab,
int n,
@@ -72,4 +70,8 @@ extern int dirread(Chan *c,
const Dirtab *tab, int ntab,
Devgen *gen);
+extern Chan *deverrmount(Chan *c, char *spec);
+extern int deverrwrite(Chan *c, void *buf, int n);
+extern int deverrseek(Chan *c, long off, int whence);
+
extern Dev *const devtab[];
diff --git a/drivers/devar.c b/drivers/devar.c
@@ -63,6 +63,7 @@ static int
argen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
{
int i, r, len;
+ long off;
Chan nc;
struct ar_hdr hdr;
struct arfile *ar;
@@ -75,7 +76,8 @@ argen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
for (i = 0; i <= n; i++) {
if (ar->offset[i] == -1)
return 0;
- if (devseek(&nc, ar->offset[i], RSEEK_SET) < 0)
+ off = ar->offset[i];
+ if (devtab[c->type]->seek(&nc, off, RSEEK_SET) < 0)
return -1;
if ((r = gethdr(&nc, &hdr)) <= 0)
return r;
@@ -119,7 +121,7 @@ arread(Chan *c, void *buf, int n)
return 0;
off = ar->offset[c->qid] + c->offset + sizeof(struct ar_hdr);
- if (devseek(&cs, off, RSEEK_SET) < 0)
+ if (devtab[cs.type]->seek(&cs, off, RSEEK_SET) < 0)
return -1;
n = devtab[cs.type]->read(&cs, buf, n);
@@ -132,7 +134,7 @@ arread(Chan *c, void *buf, int n)
static Chan *
armount(Chan *c, char *spec)
{
- int r, n;
+ int r, n, t;
long len, offhdr;
Chan *cspec;
char buf[SARMAG];
@@ -174,7 +176,8 @@ armount(Chan *c, char *spec)
if ((len % 2) != 0)
len++;
- if (devseek(cspec, len, RSEEK_CUR) < 0)
+ t = cspec->type;
+ if (devtab[t]->seek(cspec, len, RSEEK_CUR) < 0)
goto err;
break;
}
@@ -190,6 +193,7 @@ const Dev ardevtab = {
.id = 'R',
.walk = arwalk,
.read = arread,
- .write = devwrite,
+ .write = deverrwrite,
.mount = armount,
+ .seek = devseek,
};
diff --git a/drivers/devcons.c b/drivers/devcons.c
@@ -376,4 +376,5 @@ const Dev consdevtab = {
.walk = conswalk,
.read = consread,
.write = conswrite,
+ .seek = deverrseek,
};
diff --git a/drivers/devfip.c b/drivers/devfip.c
@@ -71,10 +71,11 @@ static int
fipgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
{
int i, r;
- static char unk[NAMELEN];
+ long off;
Chan nc;
struct fip_toc_entry ntry;
struct fipfile *fip;
+ static char unk[NAMELEN];
struct uuidnames {
const char name[NAMELEN];
@@ -118,13 +119,15 @@ fipgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
clone(archives[c->dev].c, &nc);
fip = &archives[nc.dev];
+ off = sizeof(struct fip_toc_header);
for (i = 0; i <= n; i++) {
if (fip->offset[i] == -1)
return 0;
- if (devseek(&nc, sizeof(struct fip_toc_header) + i * sizeof(ntry), RSEEK_SET) < 0)
+ if (devtab[nc.type]->devseek(&nc, off, RSEEK_SET) < 0)
return -1;
if ((r = getntry(&nc, &ntry)) <= 0)
return r;
+ off += sizeof(ntry);
}
for (i = 0; i < NELEM(uuidnames); i++) {
@@ -170,7 +173,7 @@ fipread(Chan *c, void *buf, int n)
return 0;
off = fip->offset[c->qid] + c->offset;
- if (devseek(&cs, off, RSEEK_SET) < 0)
+ if (devtab[cs.type]->seek(&cs, off, RSEEK_SET) < 0)
return -1;
n = devtab[cs.type]->read(&cs, buf, n);
@@ -183,7 +186,7 @@ fipread(Chan *c, void *buf, int n)
static Chan *
fipmount(Chan *c, char *spec)
{
- int r, n;
+ int r, n, t;
Chan *cspec;
char buf[STOC_HEADER_NAME];
struct fip_toc_entry ntry;
@@ -212,7 +215,8 @@ fipmount(Chan *c, char *spec)
goto err;
}
- if (devseek(cspec, sizeof(hdr), RSEEK_SET) < 0)
+ t = cspec->type;
+ if (devtab[t]->seek(cspec, sizeof(hdr), RSEEK_SET) < 0)
goto err;
for (n = 0; n < NR_FILES; n++) {
switch (getntry(cspec, &ntry)) {
@@ -237,6 +241,7 @@ const Dev fipdevtab = {
.id = 'F',
.walk = fipwalk,
.read = fipread,
- .write = devwrite,
+ .write = deverrwrite,
.mount = fipmount,
+ .seek = devseek,
};
diff --git a/drivers/devroot.c b/drivers/devroot.c
@@ -72,7 +72,7 @@ static int
blobstatus(Chan *c, void *buf, int n)
{
int i, len;
- Dirtab *dp;
+ const Dirtab *dp;
char info[NELEM(blobtab) * (NAMELEN + 20)];
len = 0;
@@ -80,7 +80,7 @@ blobstatus(Chan *c, void *buf, int n)
dp = &blobtab[i];
len += ksnprint(info+len,
sizeof(info) - len,
- "%s 0x%p %llu\n",
+ "%s 0x%p %lu\n",
dp->name,
dp->data,
dp->length);
@@ -110,6 +110,7 @@ const Dev rootdevtab = {
.id = '/',
.walk = rootwalk,
.read = rootread,
- .write = devwrite,
- .mount = devmount,
+ .write = deverrwrite,
+ .mount = deverrmount,
+ .seek = devseek,
};
diff --git a/drivers/devuart.c b/drivers/devuart.c
@@ -246,5 +246,6 @@ const Dev uartdevtab = {
.walk = uartwalk,
.read = uartread,
.write = uartwrite,
- .mount = devmount,
+ .mount = deverrmount,
+ .seek = deverrseek,
};
diff --git a/include/rcode/io.h b/include/rcode/io.h
@@ -54,7 +54,7 @@ extern int open(const char *name, int flags);
extern int close(int fd);
extern int read(int fd, void *buf, int n);
extern int write(int fd, void *buf, int n);
-extern int seek(int fd, long long off, int whence);
+extern int seek(int fd, long off, int whence);
extern int bind(char *path, char *where);
#endif /* IO_H */