mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
parent
c17069b35e
commit
b9263a7f4e
@ -18,10 +18,13 @@ which client can access a certain device:
|
||||
! <any-service> <parent /> <any-child /> </any-service>
|
||||
! </route>
|
||||
! <config>
|
||||
! <policy label="test-ahci" device="0" />
|
||||
! <!-- use model and serial number -->
|
||||
! <policy label="test-ahci" model="QEMU HARDDISK" serial="QM00005" />
|
||||
! <!-- use controller port number -->
|
||||
! <policy label="bench" device="1" />
|
||||
! </config>
|
||||
!</start>
|
||||
|
||||
In the example above, a session request labeled with "test-ahci"
|
||||
gains access to device 0, while "bench" gains access to device 1.
|
||||
In the example above, a session request labeled with "test-ahci" gains access to
|
||||
a device with certain model and serial numbers, while "bench" gains access to
|
||||
device at port 1.
|
||||
|
@ -185,6 +185,19 @@ struct Ahci
|
||||
return port_num < MAX_PORTS && ports[port_num] && !port_claimed[port_num] &&
|
||||
ports[port_num]->ready();
|
||||
}
|
||||
|
||||
long device_number(const char *model_num, const char *serial_num)
|
||||
{
|
||||
for (long port_num = 0; port_num < MAX_PORTS; port_num++) {
|
||||
Ata_driver* drv = dynamic_cast<Ata_driver *>(ports[port_num]);
|
||||
if (!drv)
|
||||
continue;
|
||||
|
||||
if (*drv->model == model_num && *drv->serial == serial_num)
|
||||
return port_num;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -220,4 +233,9 @@ bool Ahci_driver::is_avail(long device_num)
|
||||
}
|
||||
|
||||
|
||||
long Ahci_driver::device_number(char const *model_num, char const *serial_num)
|
||||
{
|
||||
return sata_ahci()->device_number(model_num, serial_num);
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,6 +39,7 @@ namespace Ahci_driver {
|
||||
void init(Ahci_root &ep);
|
||||
|
||||
bool is_avail(long device_num);
|
||||
long device_number(char const *model_num, char const *serial_num);
|
||||
|
||||
Block::Driver *claim_port(long device_num);
|
||||
void free_port(long device_num);
|
||||
|
@ -26,6 +26,9 @@ struct Identity : Genode::Mmio
|
||||
{
|
||||
Identity(Genode::addr_t base) : Mmio(base) { }
|
||||
|
||||
struct Serial_number : Register_array<0x14, 8, 20, 8> { };
|
||||
struct Model_number : Register_array<0x36, 8, 40, 8> { };
|
||||
|
||||
struct Queue_depth : Register<0x96, 16>
|
||||
{
|
||||
struct Max_depth : Bitfield<0, 5> { };
|
||||
@ -71,6 +74,40 @@ struct Identity : Genode::Mmio
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 16-bit word big endian device ASCII characters
|
||||
*/
|
||||
template <typename DEVICE_STRING>
|
||||
struct String
|
||||
{
|
||||
char buf[DEVICE_STRING::ITEMS + 1];
|
||||
|
||||
String(Identity & info)
|
||||
{
|
||||
long j = 0;
|
||||
for (unsigned long i = 0; i < DEVICE_STRING::ITEMS; i++) {
|
||||
/* read and swap even and uneven characters */
|
||||
char c = (char)info.read<DEVICE_STRING>(i ^ 1);
|
||||
if (Genode::is_whitespace(c) && j == 0)
|
||||
continue;
|
||||
buf[j++] = c;
|
||||
}
|
||||
|
||||
buf[j] = 0;
|
||||
|
||||
/* remove trailing white spaces */
|
||||
while ((j > 0) && (buf[--j] == ' '))
|
||||
buf[j] = 0;
|
||||
}
|
||||
|
||||
bool operator == (char const *other) const
|
||||
{
|
||||
return strcmp(buf, other) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Commands to distinguish between ncq and non-ncq operation
|
||||
*/
|
||||
@ -135,9 +172,15 @@ struct Dma_ext_command : Io_command
|
||||
*/
|
||||
struct Ata_driver : Port_driver
|
||||
{
|
||||
Genode::Lazy_volatile_object<Identity> info;
|
||||
Io_command *io_cmd = nullptr;
|
||||
Block::Packet_descriptor pending[32];
|
||||
typedef ::String<Identity::Serial_number> Serial_string;
|
||||
typedef ::String<Identity::Model_number> Model_string;
|
||||
|
||||
Genode::Lazy_volatile_object<Identity> info;
|
||||
Genode::Lazy_volatile_object<Serial_string> serial;
|
||||
Genode::Lazy_volatile_object<Model_string> model;
|
||||
|
||||
Io_command *io_cmd = nullptr;
|
||||
Block::Packet_descriptor pending[32];
|
||||
|
||||
Ata_driver(Port &port, Signal_context_capability state_change)
|
||||
: Port_driver(port, state_change)
|
||||
@ -242,8 +285,14 @@ struct Ata_driver : Port_driver
|
||||
|
||||
if (Port::Is::Dss::get(status) || Port::Is::Pss::get(status)) {
|
||||
info.construct(device_info);
|
||||
if (verbose)
|
||||
serial.construct(*info);
|
||||
model.construct(*info);
|
||||
|
||||
if (verbose) {
|
||||
PLOG("\t\tmodel number: %s", model->buf);
|
||||
PLOG("\t\tserial number: %s", serial->buf);
|
||||
info->info();
|
||||
}
|
||||
|
||||
check_device();
|
||||
if (ncq_support())
|
||||
|
@ -61,27 +61,32 @@ class Block::Root_multiple_clients : public Root_component< ::Session_component>
|
||||
|
||||
Server::Entrypoint &_ep;
|
||||
|
||||
long _device_num(const char *session_label)
|
||||
long _device_num(const char *session_label, char *model, char *sn, size_t bufs_len)
|
||||
{
|
||||
long num = -1;
|
||||
|
||||
try {
|
||||
using namespace Genode;
|
||||
Xml_node policy = config()->xml_node().sub_node("policy");
|
||||
|
||||
Xml_node policy = Genode::config()->xml_node().sub_node("policy");
|
||||
for (;; policy = policy.next("policy")) {
|
||||
char label_buf[64];
|
||||
policy.attribute("label").value(label_buf, sizeof(label_buf));
|
||||
|
||||
for (;; policy = policy.next("policy")) {
|
||||
char label_buf[64];
|
||||
policy.attribute("label").value(label_buf, sizeof(label_buf));
|
||||
if (Genode::strcmp(session_label, label_buf))
|
||||
continue;
|
||||
|
||||
if (Genode::strcmp(session_label, label_buf))
|
||||
continue;
|
||||
|
||||
/* read device attribute */
|
||||
/* try read device port number attribute */
|
||||
try {
|
||||
policy.attribute("device").value(&num);
|
||||
break;
|
||||
}
|
||||
} catch (...) {}
|
||||
} catch (...) { }
|
||||
|
||||
/* try read device model and serial number attributes */
|
||||
try {
|
||||
model[0] = sn[0] = 0;
|
||||
policy.attribute("model").value(model, bufs_len);
|
||||
policy.attribute("serial").value(sn, bufs_len);
|
||||
} catch (...) { }
|
||||
break;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
@ -96,12 +101,16 @@ class Block::Root_multiple_clients : public Root_component< ::Session_component>
|
||||
/* TODO: build quota check */
|
||||
|
||||
/* Search for configured device */
|
||||
char label_buf[64];
|
||||
char label_buf[64], model_buf[64], sn_buf[64];
|
||||
Genode::Arg_string::find_arg(args,
|
||||
"label").string(label_buf,
|
||||
sizeof(label_buf),
|
||||
"<unlabeled>");
|
||||
long num = _device_num(label_buf);
|
||||
long num = _device_num(label_buf, model_buf, sn_buf, sizeof(model_buf));
|
||||
/* prefer model/serial routing */
|
||||
if ((model_buf[0] != 0) && (sn_buf[0] != 0))
|
||||
num = Ahci_driver::device_number(model_buf, sn_buf);
|
||||
|
||||
if (num < 0) {
|
||||
PERR("No confguration found for client: %s", label_buf);
|
||||
throw Root::Invalid_args();
|
||||
|
Loading…
Reference in New Issue
Block a user