- 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:
Marius Strobl 2005-10-25 12:51:49 +00:00
parent 79aae78c89
commit 3727af6a8b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=151650

View File

@ -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)
{
}