- Add a workaround for the fact that OFW doesn't guarantee that
devices can be opened multiple times simultaneously but we're expected to be able to do so by the rest of the loader. This fixes booting from disks attached to the on-board SCSI controller of Sun Ultra 1 (previously this triggered a trap) and probably also of AX1115 boards. - While here, remove unused variables and add empty lines where style(9) requires such. Tested on: powerpc (grehan), sparc64 MFC after: 1 month
This commit is contained in:
parent
79aae78c89
commit
3727af6a8b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=151650
@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
@ -60,9 +61,18 @@ struct devsw ofwdisk = {
|
||||
ofwd_print
|
||||
};
|
||||
|
||||
struct opened_dev {
|
||||
ihandle_t handle;
|
||||
u_int count;
|
||||
SLIST_ENTRY(opened_dev) link;
|
||||
};
|
||||
|
||||
SLIST_HEAD(, opened_dev) opened_devs = SLIST_HEAD_INITIALIZER(opened_dev);
|
||||
|
||||
static int
|
||||
ofwd_init(void)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -73,7 +83,6 @@ ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf,
|
||||
struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata;
|
||||
daddr_t pos;
|
||||
int n;
|
||||
int i, j;
|
||||
|
||||
pos = dblk * 512;
|
||||
do {
|
||||
@ -90,18 +99,47 @@ ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf,
|
||||
static int
|
||||
ofwd_open(struct open_file *f, ...)
|
||||
{
|
||||
char path[256];
|
||||
struct ofw_devdesc *dp;
|
||||
phandle_t handle;
|
||||
struct opened_dev *odp;
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, f);
|
||||
dp = va_arg(vl, struct ofw_devdesc *);
|
||||
va_end(vl);
|
||||
if ((handle = OF_open(dp->d_path)) == -1) {
|
||||
printf("ofwd_open: Could not open %s\n", dp->d_path);
|
||||
return 1;
|
||||
/*
|
||||
* We're not guaranteed to be able to open a device more than once
|
||||
* simultaneously and there is no OFW standard method to determine
|
||||
* whether a device is already opened. Opening a device more than
|
||||
* once happens to work with most OFW block device drivers but
|
||||
* triggers a trap with at least the driver for the on-board SCSI
|
||||
* controller in Sun Ultra 1. Upper layers and MI code expect to
|
||||
* be able to open a device more than once however. As a workaround
|
||||
* keep track of the opened devices and reuse the instance handle
|
||||
* when asked to open an already opened device.
|
||||
*/
|
||||
SLIST_FOREACH(odp, &opened_devs, link) {
|
||||
if (OF_instance_to_path(odp->handle, path, sizeof(path)) == -1)
|
||||
continue;
|
||||
if (strcmp(path, dp->d_path) == 0) {
|
||||
odp->count++;
|
||||
dp->d_handle = odp->handle;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
dp->d_handle = handle;
|
||||
odp = malloc(sizeof(struct opened_dev));
|
||||
if (odp == NULL) {
|
||||
printf("ofwd_open: malloc failed\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
if ((odp->handle = OF_open(dp->d_path)) == -1) {
|
||||
printf("ofwd_open: Could not open %s\n", dp->d_path);
|
||||
free(odp);
|
||||
return ENOENT;
|
||||
}
|
||||
odp->count = 1;
|
||||
SLIST_INSERT_HEAD(&opened_devs, odp, link);
|
||||
dp->d_handle = odp->handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -109,8 +147,20 @@ static int
|
||||
ofwd_close(struct open_file *f)
|
||||
{
|
||||
struct ofw_devdesc *dev = f->f_devdata;
|
||||
struct opened_dev *odp;
|
||||
|
||||
OF_close(dev->d_handle);
|
||||
SLIST_FOREACH(odp, &opened_devs, link) {
|
||||
if (odp->handle == dev->d_handle) {
|
||||
odp->count--;
|
||||
if (odp->count == 0) {
|
||||
SLIST_REMOVE(&opened_devs, odp, opened_dev,
|
||||
link);
|
||||
OF_close(odp->handle);
|
||||
free(odp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -124,4 +174,5 @@ ofwd_ioctl(struct open_file *f, u_long cmd, void *data)
|
||||
static void
|
||||
ofwd_print(int verbose)
|
||||
{
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user