Hi, Samuel Thibault: > I'm afraid I just can't afford spending time on taking part of the > details. I see that you are understanding each other, so it should be > fine.
So i present my current sketch mainly to Olaf for review and hopefully for intermediate approval. This proposal shall cover RPC definition and architecture impact. There is still some flesh to put on the bones. Especially the userspace part is still riddling to me. I have now dropped both, manual marshalling and function membership in the interface struct device_emulation_ops. (The latter could be re-introduced easily.) (">>>" means that further investigation and sketching is needed.) ----------------------------------------------------------------------- gnumach/include/device/device.defs A new RPC is defined: routine device_transact_cd( in device : device_t; in cmd : ^ array[] of unsigned char; in timeout : unsigned int; in flags : unsigned int; in data_size : unsigned int; in write_data : ^ array[] of unsigned char; out outcome : unsigned int; out read_data : ^ array[] of unsigned char; out sense_bytes : ^ array[] of unsigned char; ); The parameter .timeout is not yet supported by the existing transaction calls in gnumach. But it is so desirable that i would consider to beef up the parameters of these existing calls. (Impact on other parts of gnumach has not yet been explored.) The parameters .flags and .outcome shall be used for behavior control and resulting information about unusual events during the transaction. >>> It has still to be decided which sg_io_hdr aspects will be mapped >>> onto these parameters. ----------------------------------------------------------------------- >>> Where to implement the userspace code ? >>> The userspace function has to pick the supported parameters from >>> Linux struct sg_io_hdr, do the RPC, put the supported result parameters >>> into the struct and set the unsupported ones to default values. ----------------------------------------------------------------------- gnumach/device/ds_routines.c The RPC receiver in the kernel: io_return_t ds_device_transact_cd (device_t dev, unsigned char *cmd, mach_msg_type_number_t cmd_len, unsigned int timeout, unsigned int flags, unsigned int data_size, unsigned char *write_data, mach_msg_type_number_t write_data_len, unsigned int *outcome, unsigned char *read_data, mach_msg_type_number_t read_data_len, unsigned char *sense_bytes, mach_msg_type_number_t sense_bytes_len) { /* Refuse if device is dead or not completely open. */ if (dev == DEVICE_NULL) return D_NO_SUCH_DEVICE; /* Call dispatcher in gnumach/linux/dev/glue/block.c which decides whether SCSI CD, ATAPI CD, or unsuitable device */ return device_transact_cd (dev, cmd, cmd_len, timeout, flags, data_size, write_data, write_data_len, outcome, read_data, read_data_len, sense_bytes, sense_bytes_len); } ----------------------------------------------------------------------- gnumach/linux/dev/glue/block.c io_return_t device_transact_cd (device_t dev, unsigned char *cmd, mach_msg_type_number_t cmd_len, unsigned int timeout, unsigned int flags, unsigned int data_size, unsigned char *write_data, mach_msg_type_number_t write_data_len, unsigned int *outcome, unsigned char *read_data, mach_msg_type_number_t read_data_len, unsigned char *sense_bytes, mach_msg_type_number_t sense_bytes_len) { struct block_data *bd; bd = dev->emul_data; if (scsi_blk_major (MAJOR (bd->dev)) { /* >>> scsi transport by call to scsi.c */; } else if (MAJOR (bd->dev) == IDE0_MAJOR || MAJOR (bd->dev) == IDE1_MAJOR || MAJOR (bd->dev) == IDE2_MAJOR || MAJOR (bd->dev) == IDE3_MAJOR) { /* >>> ide transport by call to ide-cd.c */; } else return D_INVALID_OPERATION; /* >>> bring result into the output parameters */; return D_SUCCESS; } The calls for SCSI and ATAPI may decide to return D_INVALID_OPERATION if the device is not a CD drive. ----------------------------------------------------------------------- gnumach/linux/src/drivers/block/ide.c To obtain (ide_drive_t *) from kdev_t, there exists: /* * get_info_ptr() returns the (ide_drive_t *) for a given device number. * It returns NULL if the given device number does not match any present drives. */ static ide_drive_t *get_info_ptr (kdev_t i_rdev) New function to check whether drive is a IDE ATAPI CDROM device (ide_disk is not ATAPI. ide_tape is not block. I have no clue about them) gnumach/linux/src/drivers/block/ide.h defines ide_media_t value ide_cdrom and ide_media_t ide_drive_t.media static int is_atapi_cd(ide_drive_t *drive) { return (drive->media == ide_cdrom); } >>> Need a glue function which checks this. If appropriate. it sets up >>> this struct which is defined in gnumach/linux/src/drivers/block/ide.h struct packet_command { unsigned char *buffer; int buflen; int stat; struct atapi_request_sense *sense_data; unsigned char c[12]; }; >>> Then it calls the existing ATAPI CD transaction function from: >>> gnumach/linux/src/drivers/block/ide-cd.c: static int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc); >>> and fills its reply parameters. ----------------------------------------------------------------------- gnumach/linux/src/drivers/scsi/scsi.c To obtain Scsi_Device from kdev_t there will be a new function static Scsi_Device *get_scsi_cdrom_device(kdev_t dev) { if (MAJOR(dev) == SCSI_CDROM_MAJOR) return scsi_CDs[MINOR(dev)].device; return NULL; } >>> Need a glue function which checks this. If appropriate. it sets up >>> this struct which is not really defined but only described in a >>> comment in scsi_ioctl_send_command() about its (void *) parameter: /* * The structure that we are passed should look like: * * struct sdata { * unsigned int inlen; * unsigned int outlen; * unsigned char cmd[]; # However many bytes are used for cmd. * unsigned char data[]; * }; >>> Then it calls the existing SCSI transaction function from: >>> gnumach/linux/src/drivers/scsi/scsi.c int scsi_ioctl_send_command(Scsi_Device *dev, void *buffer) >>> and fills its reply parameters. ----------------------------------------------------------------------- Have a nice day :) Thomas