Use permanent allocation of major indexes for character devices.

This commit is contained in:
Sergey
2015-05-30 18:28:22 -07:00
parent a234dfc7dc
commit e08e51f1b9
7 changed files with 169 additions and 195 deletions

View File

@@ -17,7 +17,13 @@ struct device {
struct device *next;
};
struct nlist nl[] = { {"_bdevsw"}, {"_cdevsw"}, {""}};
struct nlist nl[] = {
{ "_bdevsw" },
{ "_cdevsw" },
{ "_nblkdev" },
{ "_nchrdev" },
{""},
};
struct device *devices = NULL;
@@ -63,8 +69,7 @@ void add_device(char *name, int major, int minor, char class)
{
struct device *dev;
if(!devices)
{
if (! devices) {
devices = malloc(sizeof(struct device));
dev = devices;
} else {
@@ -82,7 +87,7 @@ void add_device(char *name, int major, int minor, char class)
int getstring(int fd, unsigned int offset, char *buffer)
{
char *p = buffer;
lseek(fd,offset,0);
lseek(fd, offset, 0);
read(fd, p, 1);
while (*p != 0) {
@@ -98,22 +103,32 @@ int getdata(int fd, unsigned int offset, void *buffer, int size)
return read(fd, buffer, size);
}
int getbdev(int fd, int num)
int getnblkdev(int fd)
{
getdata(fd, nl[0].n_value + (sizeof(struct bdevsw) * num), &bdevsw, sizeof(struct bdevsw));
if (bdevsw.d_open == 0) {
return 0;
}
return 1;
int value;
getdata(fd, nl[2].n_value, &value, sizeof(value));
return value;
}
int getcdev(int fd, int num)
int getnchrdev(int fd)
{
getdata(fd, nl[1].n_value + (sizeof(struct cdevsw) * num), &cdevsw, sizeof(struct cdevsw));
if (cdevsw.d_open == 0) {
return 0;
}
return 1;
int value;
getdata(fd, nl[3].n_value, &value, sizeof(value));
return value;
}
void getbdev(int fd, int num)
{
getdata(fd, nl[0].n_value + (sizeof(struct bdevsw) * num),
&bdevsw, sizeof(struct bdevsw));
}
void getcdev(int fd, int num)
{
getdata(fd, nl[1].n_value + (sizeof(struct cdevsw) * num),
&cdevsw, sizeof(struct cdevsw));
}
int getdevspec(int fd, unsigned int offset, unsigned int num)
@@ -121,7 +136,7 @@ int getdevspec(int fd, unsigned int offset, unsigned int num)
getdata(fd, offset + (sizeof(struct devspec) * num), &devspec, sizeof(struct devspec));
if (devspec.devname == 0) {
return 0;
}
}
return 1;
}
@@ -140,7 +155,7 @@ struct device *get_device(char *name)
void delete_device(char *filename)
{
//printf("unlink(%s)\n",filename);
//printf("--- unlink(%s)\n", filename);
unlink(filename);
}
@@ -149,15 +164,15 @@ void create_device(struct device *dev)
char buffer[20];
dev_t ds;
mode_t mode;
sprintf(buffer,"/dev/%s", dev->name);
sprintf(buffer, "/dev/%s", dev->name);
ds = makedev(dev->major, dev->minor);
if (dev->class == 'c')
mode = 0666 | S_IFCHR;
else
mode = 0666 | S_IFBLK;
//printf("mknod(%s, %o, %04X)\n", buffer, mode, ds);
//printf("--- mknod(%s, %o, %04X)\n", buffer, mode, ds);
mknod(buffer, mode, ds);
}
@@ -174,19 +189,14 @@ void create_kmem()
int main()
{
int kmem;
int kmem, nblkdev, nchrdev, i, isgood, um, bdevnum, cdevnum;
char buffer[20];
int bdevnum = 0;
int cdevnum = 0;
int specno = 0;
int dnnum = 0;
int i;
DIR *dp;
struct direct *file;
struct device *dev;
struct stat sb;
int isgood;
int um;
dev_t kmd = kmemdev();
knlist(nl);
@@ -194,65 +204,67 @@ int main()
um = umask(0000);
// Does kmem exist, and is it correct?
if (stat("/dev/kmem",&sb) == -1) {
if (stat("/dev/kmem", &sb) == -1) {
create_kmem();
} else if (
(!(sb.st_mode & S_IFCHR)) ||
(major(sb.st_rdev)!=major(kmd)) ||
(!(sb.st_mode & S_IFCHR)) ||
(major(sb.st_rdev)!=major(kmd)) ||
(minor(sb.st_rdev)!=minor(kmd))
) {
delete_device("/dev/kmem");
create_kmem();
}
kmem = open("/dev/kmem",O_RDONLY);
kmem = open("/dev/kmem", O_RDONLY);
if (!kmem) {
printf("devupdate: FATAL - unable to access /dev/kmem\n");
return(10);
}
nblkdev = getnblkdev(kmem);
nchrdev = getnchrdev(kmem);
//printf("Block devices: \n");
while (getbdev(kmem,bdevnum) == 1) {
for (bdevnum = 0; bdevnum < nblkdev; bdevnum++) {
getbdev(kmem, bdevnum);
if (bdevsw.devs == 0)
continue;
specno = 0;
if (bdevsw.devs != 0) {
while (getdevspec(kmem, (unsigned int)bdevsw.devs, specno) == 1) {
getstring(kmem, (unsigned int)devspec.devname, buffer);
specno++;
//printf(" %s (%d,%d)\n", buffer, bdevnum, devspec.unit);
add_device(buffer, bdevnum, devspec.unit, 'b');
}
while (getdevspec(kmem, (unsigned int)bdevsw.devs, specno) == 1) {
getstring(kmem, (unsigned int)devspec.devname, buffer);
specno++;
//printf(" %s (%d,%d)\n", buffer, bdevnum, devspec.unit);
add_device(buffer, bdevnum, devspec.unit, 'b');
}
bdevnum++;
}
//printf("Chatacter devices: \n");
while (getcdev(kmem,cdevnum) == 1) {
specno = 0;
if (cdevsw.devs != 0) {
while (getdevspec(kmem, (unsigned int)cdevsw.devs, specno) == 1) {
getstring(kmem, (unsigned int)devspec.devname, buffer);
specno++;
//printf(" %s (%d,%d)\n", buffer, cdevnum, devspec.unit);
add_device(buffer, cdevnum, devspec.unit, 'c');
}
}
cdevnum++;
}
//printf("Character devices: \n");
for (cdevnum = 0; cdevnum < nchrdev; cdevnum++) {
getcdev(kmem, cdevnum);
if (cdevsw.devs == 0)
continue;
specno = 0;
while (getdevspec(kmem, (unsigned int)cdevsw.devs, specno) == 1) {
getstring(kmem, (unsigned int)devspec.devname, buffer);
specno++;
//printf(" %s (%d,%d)\n", buffer, cdevnum, devspec.unit);
add_device(buffer, cdevnum, devspec.unit, 'c');
}
}
close(kmem);
dp = opendir("/dev");
while(file = readdir(dp))
while (file = readdir(dp))
{
isgood = 0;
if (file->d_name[0] == '.')
if (file->d_name[0] == '.')
continue;
dev = get_device(file->d_name);
sprintf(buffer,"/dev/%s",file->d_name);
sprintf(buffer, "/dev/%s", file->d_name);
if (!dev) {
delete_device(buffer);
@@ -299,4 +311,3 @@ int main()
close(kmem);
return 0;
}

View File

@@ -124,7 +124,6 @@ void remque (void *element);
void startup (void); /* machine-dependent startup code */
int chrtoblk (dev_t dev); /* convert from character to block device number */
int blktochr (dev_t dev); /* convert from block to character device number */
int isdisk (dev_t dev, int type); /* determine if a device is a disk */
int iskmemdev (dev_t dev); /* identify /dev/mem and /dev/kmem */
void boot (dev_t dev, int howto);

View File

@@ -45,8 +45,8 @@ void cninit()
void cnidentify()
{
printf ("console: %s (%d,%d)\n",
cdevname(console_device), major(console_device), minor(console_device));
printf ("console: %s (%d,%d)\n", cdevname(console_device),
major(console_device), minor(console_device));
}
int cnopen(dev_t dev, int flag, int mode)

View File

@@ -25,39 +25,30 @@ extern int strcmp(char *s1, char *s2);
#ifdef UARTUSB_ENABLED
# include "usb_uart.h"
#endif
#ifdef GPIO_ENABLED
# include "gpio.h"
#endif
#ifdef ADC_ENABLED
# include "adc.h"
#endif
#ifdef SPI_ENABLED
# include "spi.h"
#endif
#ifdef GLCD_ENABLED
# include "glcd.h"
#endif
#ifdef PWM_ENABLED
# include "pwm.h"
#endif
#ifdef PICGA_ENABLED
# include "picga.h"
#endif
#ifdef PTY_ENABLED
# include "pty.h"
#endif
#ifdef HX8357_ENABLED
# include "hx8357.h"
#endif
#ifdef SKEL_ENABLED
# include "skel.h"
#endif
@@ -97,65 +88,64 @@ void noroot (csr)
/* Empty. */
}
const struct bdevsw bdevsw[] = {
{
rdopen, rdclose, rdstrategy,
noroot, rdsize, rdioctl, 0, rd0devs },
{
rdopen, rdclose, rdstrategy,
noroot, rdsize, rdioctl, 0, rd1devs },
{
rdopen, rdclose, rdstrategy,
noroot, rdsize, rdioctl, 0, rd2devs },
{
rdopen, rdclose, rdstrategy,
noroot, rdsize, rdioctl, 0, rd3devs },
{
swopen, swclose, swstrategy,
noroot, swsize, swcioctl, 0, swapbdevs },
{
0, 0, 0,
0, 0, 0, 0, 0 },
};
const int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]) - 1;
/*
* The RetroDisks require the same master number as the disk entry in the
* rdisk.c file. A bit of a bind, but it means that the RetroDisk
* devices must be numbered from master 0 upwards.
*/
const struct bdevsw bdevsw[] = {
{ /* 0 - rd0 */
rdopen, rdclose, rdstrategy,
noroot, rdsize, rdioctl, 0, rd0devs
},
{ /* 1 - rd1 */
rdopen, rdclose, rdstrategy,
noroot, rdsize, rdioctl, 0, rd1devs
},
{ /* 2 - rd2 */
rdopen, rdclose, rdstrategy,
noroot, rdsize, rdioctl, 0, rd2devs
},
{ /* 3 - rd3 */
rdopen, rdclose, rdstrategy,
noroot, rdsize, rdioctl, 0, rd3devs
},
{ /* 4 - swap */
swopen, swclose, swstrategy,
noroot, swsize, swcioctl, 0, swapbdevs
},
{ 0 },
};
const int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]) - 1;
const struct cdevsw cdevsw[] = {
/*
* Static drivers - every system has these:
*/
{ /* cn = 0 */
{ /* 0 - console */
cnopen, cnclose, cnread, cnwrite,
cnioctl, nulldev, cnttys, cnselect,
nostrategy, 0, 0, cndevs
},
{ /* mem = 1 */
{ /* 1 - mem, kmem, null, zero */
nulldev, nulldev, mmrw, mmrw,
noioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, mmdevs
},
{ /* tty = 2 */
{ /* 2 - tty */
syopen, nulldev, syread, sywrite,
syioctl, nulldev, 0, syselect,
nostrategy, 0, 0, sydevs
},
{ /* fd = 3 */
{ /* 3 - fd */
fdopen, nulldev, norw, norw,
noioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, fddevs
},
{ /* swap = 4 */
{ /* 4 - temp (temporary allocation in swap space) */
swcopen, swcclose, swcread, swcwrite,
swcioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, swapcdevs
@@ -164,35 +154,37 @@ const struct cdevsw cdevsw[] = {
/*
* Optional drivers from here on:
*/
{ /* 5 - log */
#ifdef LOG_ENABLED
{
logopen, logclose, logread, norw,
logioctl, nulldev, 0, logselect,
nostrategy, 0, 0, logdevs
},
#else
0
#endif
},
{ /* 6 - tty uart */
#if defined(UART1_ENABLED) || defined(UART2_ENABLED) || \
defined(UART3_ENABLED) || defined(UART4_ENABLED) || \
defined(UART5_ENABLED) || defined(UART6_ENABLED)
{
uartopen, uartclose, uartread, uartwrite,
uartioctl, nulldev, uartttys, uartselect,
nostrategy, uartgetc, uartputc, uartdevs
},
#else
0
#endif
},
{ /* 7 - tty usb */
#ifdef UARTUSB_ENABLED
{
usbopen, usbclose, usbread, usbwrite,
usbioctl, nulldev, usbttys, usbselect,
nostrategy, usbgetc, usbputc, usbdevs
},
#else
0
#endif
},
{ /* 8, 9 - pty */
#ifdef PTY_ENABLED
{
ptsopen, ptsclose, ptsread, ptswrite,
ptyioctl, nulldev, pt_tty, ptcselect,
nostrategy, 0, 0, ptsdevs
@@ -200,73 +192,82 @@ const struct cdevsw cdevsw[] = {
ptcopen, ptcclose, ptcread, ptcwrite,
ptyioctl, nulldev, pt_tty, ptcselect,
nostrategy, 0, 0, ptcdevs
},
#else
0 }, { 0
#endif
},
{ /* 10 - gpio */
#ifdef GPIO_ENABLED
{
gpioopen, gpioclose, gpioread, gpiowrite,
gpioioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, gpiodevs
},
#else
0
#endif
},
{ /* 11 - adc */
#ifdef ADC_ENABLED
{
adc_open, adc_close, adc_read, adc_write,
adc_ioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, adcdevs
},
#else
0
#endif
},
{ /* 12 - spi */
#ifdef SPI_ENABLED
{
spidev_open, spidev_close, spidev_read, spidev_write,
spidev_ioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, spidevs
},
#else
0
#endif
},
{ /* 13 - glcd */
#ifdef GLCD_ENABLED
{
glcd_open, glcd_close, glcd_read, glcd_write,
glcd_ioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, glcddevs
},
#else
0
#endif
},
{ /* 14 - pwm */
#ifdef PWM_ENABLED
{
pwm_open, pwm_close, pwm_read, pwm_write,
pwm_ioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, pwmdevs
},
#else
0
#endif
// Ignore this for now - it's WIP.
},
{ /* 15 - picga */ // Ignore this for now - it's WIP.
#ifdef PICGA_ENABLED
{
picga_open, picga_close, picga_read, picga_write,
picga_ioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, picgadevs
},
#else
0
#endif
},
{ /* 16 - tft */
#ifdef HX8357_ENABLED
{
hx8357_open, hx8357_close, hx8357_read, hx8357_write,
hx8357_ioctl, nulldev, hx8357_ttys, hx8357_select,
nostrategy, hx8357_getc, hx8357_putc, hx8357devs
},
#else
0
#endif
},
{ /* 17 - skel */
#ifdef SKEL_ENABLED
{
skeldev_open, skeldev_close, skeldev_read, skeldev_write,
skeldev_ioctl, nulldev, 0, seltrue,
nostrategy, 0, 0, skeldevs
},
#else
0
#endif
},
/*
* End the list with a blank entry
@@ -300,71 +301,30 @@ isdisk(dev, type)
dev_t dev;
register int type;
{
if (type != IFBLK)
return 0;
switch (major(dev)) {
case 0: /* sd */
case 1: /* sw */
case 2:
case 3:
case 4:
if (type == IFBLK)
return (1);
return (0);
case 0: /* rd0 */
case 1: /* rd1 */
case 2: /* rd2 */
case 3: /* rd3 */
case 4: /* sw */
return (1);
default:
return (0);
}
/* NOTREACHED */
}
#define MAXDEV 7
static const char chrtoblktbl[MAXDEV] = {
/* CHR */ /* BLK */
/* 0 */ NODEV,
/* 1 */ NODEV,
/* 2 */ NODEV,
/* 3 */ 0, /* sd */
/* 4 */ NODEV,
/* 5 */ NODEV,
/* 6 */ 1,
};
/*
* Routine to convert from character to block device number.
*
* A minimal stub routine can always return NODEV.
*/
int
chrtoblk(dev)
register dev_t dev;
chrtoblk(dev_t dev)
{
register int blkmaj;
if (major(dev) >= MAXDEV || (blkmaj = chrtoblktbl[major(dev)]) == NODEV)
return (NODEV);
return (makedev(blkmaj, minor(dev)));
}
/*
* This routine returns the cdevsw[] index of the block device
* specified by the input parameter. Used by init_main and ufs_mount to
* find the diskdriver's ioctl entry point so that the label and partition
* information can be obtained for 'block' (instead of 'character') disks.
*
* Rather than create a whole separate table 'chrtoblktbl' is scanned
* looking for a match. This routine is only called a half dozen times during
* a system's life so efficiency isn't a big concern.
*/
int
blktochr(dev)
register dev_t dev;
{
register int maj = major(dev);
register int i;
for (i = 0; i < MAXDEV; i++) {
if (maj == chrtoblktbl[i])
return(i);
}
return(NODEV);
return (NODEV);
}
/*

View File

@@ -173,8 +173,10 @@ static const struct {
{ "_rate", (int) &rate }, /* vmstat */
{ "_sum", (int) &sum }, /* vmstat */
#endif
{ "_bdevsw", (int) &bdevsw },
{ "_cdevsw", (int) &cdevsw },
{ "_bdevsw", (int) &bdevsw }, /* devupdate */
{ "_cdevsw", (int) &cdevsw }, /* devupdate */
{ "_nblkdev", (int) &nblkdev }, /* devupdate */
{ "_nchrdev", (int) &nchrdev }, /* devupdate */
{ 0, 0 },
};

View File

@@ -76,6 +76,7 @@ int cnclose (dev, flag, mode)
{
register struct tty *tp = &cnttys[0];
ttywflush(tp);
ttyclose (tp);
return 0;
}

View File

@@ -110,6 +110,7 @@ int usbclose (dev, flag, mode)
{
register struct tty *tp = &usbttys[0];
ttywflush(tp);
ttyclose (tp);
return 0;
}