diff mbox series

[5/6] FMS: Add the SCSI Get Configuration command.

Message ID 20210626211820.107310-6-i.kononenko@yadro.com
State New
Headers show
Series None | expand

Commit Message

i.kononenko June 26, 2021, 9:18 p.m. UTC
The SCSI Get Configuration command is required to obtain information
about a CD/DVD/BL device (MMC-6, 6.5 GET CONFIGURATION Command).

The aforementioned ability will be expected by several multimedia
consumers, such as OS MS Windows, OS ESXi, etc., for selecting the
appropriate FS driver.

End-user-impact: The FMS devices consumers can now retrieve their
                 capabilities.
                 FMS supports the ISO-13346(UDF) multimedia file systems

Signed-off-by: Igor Kononenko <i.kononenko@yadro.com>
---
 drivers/ata/libata-zpodd.c                   |   8 +-
 drivers/usb/gadget/function/f_mass_storage.c | 222 +++++
 include/scsi/scsi_proto.h                    |   1 +
 include/uapi/linux/cdrom.h                   | 844 ++++++++++++++++++-
 4 files changed, 1041 insertions(+), 34 deletions(-)

Comments

kernel test robot June 27, 2021, 12:44 a.m. UTC | #1
Hi Igor,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on scsi/for-next linus/master balbi-usb/testing/next v5.13-rc7 next-20210625]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Igor-Kononenko/usb-gadget-mass-storage-Improve-the-signature-of-SCSI-handler-function/20210627-061851
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
config: powerpc-randconfig-r035-20210627 (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/db2ec6f1e52293817f380a4875e01c36a4195c19
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Igor-Kononenko/usb-gadget-mass-storage-Improve-the-signature-of-SCSI-handler-function/20210627-061851
        git checkout db2ec6f1e52293817f380a4875e01c36a4195c19
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=powerpc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from include/linux/printk.h:7,
                    from include/linux/kernel.h:17,
                    from include/asm-generic/bug.h:20,
                    from arch/powerpc/include/asm/bug.h:109,
                    from include/linux/bug.h:5,
                    from arch/powerpc/include/asm/mmu.h:147,
                    from arch/powerpc/include/asm/paca.h:18,
                    from arch/powerpc/include/asm/current.h:13,
                    from include/linux/sched.h:12,
                    from include/linux/blkdev.h:5,
                    from drivers/usb/gadget/function/f_mass_storage.c:201:
   drivers/usb/gadget/function/f_mass_storage.c: In function 'cdr_guess_medium_type':
>> include/linux/kern_levels.h:5:18: warning: format '%u' expects argument of type 'unsigned int', but argument 4 has type 'size_t' {aka 'long unsigned int'} [-Wformat=]
       5 | #define KERN_SOH "\001"  /* ASCII Start Of Header */
         |                  ^~~~~~
   include/linux/kern_levels.h:15:20: note: in expansion of macro 'KERN_SOH'
      15 | #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
         |                    ^~~~~~~~
   include/linux/printk.h:427:9: note: in expansion of macro 'KERN_DEBUG'
     427 |  printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
         |         ^~~~~~~~~~
   drivers/usb/gadget/function/storage_common.h:24:4: note: in expansion of macro 'pr_debug'
      24 |    func("%s/%s: " fmt, *(lun)->name_pfx,  \
         |    ^~~~
   drivers/usb/gadget/function/storage_common.h:30:34: note: in expansion of macro '_LMSG'
      30 | #define LDBG(lun, fmt, args...)  _LMSG(pr_debug, lun, fmt, ## args)
         |                                  ^~~~~
   drivers/usb/gadget/function/f_mass_storage.c:1964:2: note: in expansion of macro 'LDBG'
    1964 |  LDBG(curlun,
         |  ^~~~
   drivers/usb/gadget/function/f_mass_storage.c:1965:27: note: format string is defined here
    1965 |       "Disc layout size (%u) exceeds all known media types, assuming BD - ROM !\n",
         |                          ~^
         |                           |
         |                           unsigned int
         |                          %lu
   In file included from include/linux/printk.h:7,
                    from include/linux/kernel.h:17,
                    from include/asm-generic/bug.h:20,
                    from arch/powerpc/include/asm/bug.h:109,
                    from include/linux/bug.h:5,
                    from arch/powerpc/include/asm/mmu.h:147,
                    from arch/powerpc/include/asm/paca.h:18,
                    from arch/powerpc/include/asm/current.h:13,
                    from include/linux/sched.h:12,
                    from include/linux/blkdev.h:5,
                    from drivers/usb/gadget/function/f_mass_storage.c:201:
   include/linux/kern_levels.h:5:18: warning: format '%u' expects argument of type 'unsigned int', but argument 3 has type 'size_t' {aka 'long unsigned int'} [-Wformat=]
       5 | #define KERN_SOH "\001"  /* ASCII Start Of Header */
         |                  ^~~~~~
   include/linux/kern_levels.h:15:20: note: in expansion of macro 'KERN_SOH'
      15 | #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
         |                    ^~~~~~~~
   include/linux/printk.h:427:9: note: in expansion of macro 'KERN_DEBUG'
     427 |  printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
         |         ^~~~~~~~~~
   drivers/usb/gadget/function/storage_common.h:27:4: note: in expansion of macro 'pr_debug'
      27 |    func("%s: " fmt, (lun)->name, ## args);  \
         |    ^~~~
   drivers/usb/gadget/function/storage_common.h:30:34: note: in expansion of macro '_LMSG'
      30 | #define LDBG(lun, fmt, args...)  _LMSG(pr_debug, lun, fmt, ## args)
         |                                  ^~~~~
   drivers/usb/gadget/function/f_mass_storage.c:1964:2: note: in expansion of macro 'LDBG'
    1964 |  LDBG(curlun,
         |  ^~~~
   drivers/usb/gadget/function/f_mass_storage.c:1965:27: note: format string is defined here
    1965 |       "Disc layout size (%u) exceeds all known media types, assuming BD - ROM !\n",
         |                          ~^
         |                           |
         |                           unsigned int
         |                          %lu
   drivers/usb/gadget/function/f_mass_storage.c: At top level:
   drivers/usb/gadget/function/f_mass_storage.c:311:23: warning: initialized field overwritten [-Woverride-init]
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2231:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2231 |  { CDB_REG_CHECKER_BLK(READ_6, 6, CDB_SIZE_FIELD_4, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: note: (near initialization for 'cdb_checker_table[6].do_check_command')
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2231:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2231 |  { CDB_REG_CHECKER_BLK(READ_6, 6, CDB_SIZE_FIELD_4, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: warning: initialized field overwritten [-Woverride-init]
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2233:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2233 |  { CDB_REG_CHECKER_BLK(READ_10, 10, CDB_SIZE_FIELD_7, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: note: (near initialization for 'cdb_checker_table[7].do_check_command')
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2233:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2233 |  { CDB_REG_CHECKER_BLK(READ_10, 10, CDB_SIZE_FIELD_7, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: warning: initialized field overwritten [-Woverride-init]
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2235:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2235 |  { CDB_REG_CHECKER_BLK(READ_12, 12, CDB_SIZE_FIELD_6, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: note: (near initialization for 'cdb_checker_table[8].do_check_command')
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2235:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2235 |  { CDB_REG_CHECKER_BLK(READ_12, 12, CDB_SIZE_FIELD_6, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: warning: initialized field overwritten [-Woverride-init]
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2259:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2259 |  { CDB_REG_CHECKER_BLK(VERIFY, 10, CDB_NO_SIZE_FIELD, DATA_DIR_NONE,
--
   drivers/usb/gadget/function/f_mass_storage.c: In function 'invalidate_sub':
   drivers/usb/gadget/function/f_mass_storage.c:1166:16: warning: variable 'rc' set but not used [-Wunused-but-set-variable]
    1166 |  unsigned long rc;
         |                ^~
   In file included from include/linux/kernel.h:17,
                    from include/asm-generic/bug.h:20,
                    from arch/powerpc/include/asm/bug.h:109,
                    from include/linux/bug.h:5,
                    from arch/powerpc/include/asm/mmu.h:147,
                    from arch/powerpc/include/asm/paca.h:18,
                    from arch/powerpc/include/asm/current.h:13,
                    from include/linux/sched.h:12,
                    from include/linux/blkdev.h:5,
                    from drivers/usb/gadget/function/f_mass_storage.c:201:
   drivers/usb/gadget/function/f_mass_storage.c: In function 'cdr_guess_medium_type':
>> include/linux/kern_levels.h:5:18: warning: format '%u' expects argument of type 'unsigned int', but argument 4 has type 'size_t' {aka 'long unsigned int'} [-Wformat=]
       5 | #define KERN_SOH "\001"  /* ASCII Start Of Header */
         |                  ^~~~~~
   include/linux/printk.h:140:10: note: in definition of macro 'no_printk'
     140 |   printk(fmt, ##__VA_ARGS__);  \
         |          ^~~
   include/linux/kern_levels.h:15:20: note: in expansion of macro 'KERN_SOH'
      15 | #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
         |                    ^~~~~~~~
   include/linux/printk.h:430:12: note: in expansion of macro 'KERN_DEBUG'
     430 |  no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
         |            ^~~~~~~~~~
   drivers/usb/gadget/function/storage_common.h:24:4: note: in expansion of macro 'pr_debug'
      24 |    func("%s/%s: " fmt, *(lun)->name_pfx,  \
         |    ^~~~
   drivers/usb/gadget/function/storage_common.h:30:34: note: in expansion of macro '_LMSG'
      30 | #define LDBG(lun, fmt, args...)  _LMSG(pr_debug, lun, fmt, ## args)
         |                                  ^~~~~
   drivers/usb/gadget/function/f_mass_storage.c:1964:2: note: in expansion of macro 'LDBG'
    1964 |  LDBG(curlun,
         |  ^~~~
   drivers/usb/gadget/function/f_mass_storage.c:1965:27: note: format string is defined here
    1965 |       "Disc layout size (%u) exceeds all known media types, assuming BD - ROM !\n",
         |                          ~^
         |                           |
         |                           unsigned int
         |                          %lu
   In file included from include/linux/kernel.h:17,
                    from include/asm-generic/bug.h:20,
                    from arch/powerpc/include/asm/bug.h:109,
                    from include/linux/bug.h:5,
                    from arch/powerpc/include/asm/mmu.h:147,
                    from arch/powerpc/include/asm/paca.h:18,
                    from arch/powerpc/include/asm/current.h:13,
                    from include/linux/sched.h:12,
                    from include/linux/blkdev.h:5,
                    from drivers/usb/gadget/function/f_mass_storage.c:201:
   include/linux/kern_levels.h:5:18: warning: format '%u' expects argument of type 'unsigned int', but argument 3 has type 'size_t' {aka 'long unsigned int'} [-Wformat=]
       5 | #define KERN_SOH "\001"  /* ASCII Start Of Header */
         |                  ^~~~~~
   include/linux/printk.h:140:10: note: in definition of macro 'no_printk'
     140 |   printk(fmt, ##__VA_ARGS__);  \
         |          ^~~
   include/linux/kern_levels.h:15:20: note: in expansion of macro 'KERN_SOH'
      15 | #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
         |                    ^~~~~~~~
   include/linux/printk.h:430:12: note: in expansion of macro 'KERN_DEBUG'
     430 |  no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
         |            ^~~~~~~~~~
   drivers/usb/gadget/function/storage_common.h:27:4: note: in expansion of macro 'pr_debug'
      27 |    func("%s: " fmt, (lun)->name, ## args);  \
         |    ^~~~
   drivers/usb/gadget/function/storage_common.h:30:34: note: in expansion of macro '_LMSG'
      30 | #define LDBG(lun, fmt, args...)  _LMSG(pr_debug, lun, fmt, ## args)
         |                                  ^~~~~
   drivers/usb/gadget/function/f_mass_storage.c:1964:2: note: in expansion of macro 'LDBG'
    1964 |  LDBG(curlun,
         |  ^~~~
   drivers/usb/gadget/function/f_mass_storage.c:1965:27: note: format string is defined here
    1965 |       "Disc layout size (%u) exceeds all known media types, assuming BD - ROM !\n",
         |                          ~^
         |                           |
         |                           unsigned int
         |                          %lu
   drivers/usb/gadget/function/f_mass_storage.c: At top level:
   drivers/usb/gadget/function/f_mass_storage.c:311:23: warning: initialized field overwritten [-Woverride-init]
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2231:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2231 |  { CDB_REG_CHECKER_BLK(READ_6, 6, CDB_SIZE_FIELD_4, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: note: (near initialization for 'cdb_checker_table[6].do_check_command')
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2231:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2231 |  { CDB_REG_CHECKER_BLK(READ_6, 6, CDB_SIZE_FIELD_4, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: warning: initialized field overwritten [-Woverride-init]
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2233:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2233 |  { CDB_REG_CHECKER_BLK(READ_10, 10, CDB_SIZE_FIELD_7, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: note: (near initialization for 'cdb_checker_table[7].do_check_command')
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2233:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2233 |  { CDB_REG_CHECKER_BLK(READ_10, 10, CDB_SIZE_FIELD_7, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: warning: initialized field overwritten [-Woverride-init]
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2235:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2235 |  { CDB_REG_CHECKER_BLK(READ_12, 12, CDB_SIZE_FIELD_6, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~
   drivers/usb/gadget/function/f_mass_storage.c:311:23: note: (near initialization for 'cdb_checker_table[8].do_check_command')
     311 |   .do_check_command = &check_command_size_in_blocks
         |                       ^
   drivers/usb/gadget/function/f_mass_storage.c:2235:4: note: in expansion of macro 'CDB_REG_CHECKER_BLK'
    2235 |  { CDB_REG_CHECKER_BLK(READ_12, 12, CDB_SIZE_FIELD_6, DATA_DIR_TO_HOST,
         |    ^~~~~~~~~~~~~~~~~~~


vim +5 include/linux/kern_levels.h

314ba3520e513a Joe Perches 2012-07-30  4  
04d2c8c83d0e3a Joe Perches 2012-07-30 @5  #define KERN_SOH	"\001"		/* ASCII Start Of Header */
04d2c8c83d0e3a Joe Perches 2012-07-30  6  #define KERN_SOH_ASCII	'\001'
04d2c8c83d0e3a Joe Perches 2012-07-30  7  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot June 27, 2021, 4:42 a.m. UTC | #2
Hi Igor,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on scsi/for-next linus/master balbi-usb/testing/next v5.13-rc7 next-20210625]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Igor-Kononenko/usb-gadget-mass-storage-Improve-the-signature-of-SCSI-handler-function/20210627-061851
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
config: i386-randconfig-s002-20210627 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/db2ec6f1e52293817f380a4875e01c36a4195c19
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Igor-Kononenko/usb-gadget-mass-storage-Improve-the-signature-of-SCSI-handler-function/20210627-061851
        git checkout db2ec6f1e52293817f380a4875e01c36a4195c19
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash drivers/usb/gadget/function/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> drivers/usb/gadget/function/f_mass_storage.c:1988:57: sparse: sparse: restricted __be16 degrades to integer
>> drivers/usb/gadget/function/f_mass_storage.c:2060:30: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] data_len @@     got restricted __be32 [usertype] @@
   drivers/usb/gadget/function/f_mass_storage.c:2060:30: sparse:     expected unsigned int [usertype] data_len
   drivers/usb/gadget/function/f_mass_storage.c:2060:30: sparse:     got restricted __be32 [usertype]
>> drivers/usb/gadget/function/f_mass_storage.c:2062:17: sparse: sparse: cast from restricted __be16
>> drivers/usb/gadget/function/f_mass_storage.c:2061:34: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned short [usertype] curr_profile @@     got restricted __be16 [usertype] @@
   drivers/usb/gadget/function/f_mass_storage.c:2061:34: sparse:     expected unsigned short [usertype] curr_profile
   drivers/usb/gadget/function/f_mass_storage.c:2061:34: sparse:     got restricted __be16 [usertype]
   drivers/usb/gadget/function/f_mass_storage.c:2231:11: sparse: sparse: Initializer entry defined twice
   drivers/usb/gadget/function/f_mass_storage.c:2231:11: sparse:   also defined here
   drivers/usb/gadget/function/f_mass_storage.c:2233:11: sparse: sparse: Initializer entry defined twice
   drivers/usb/gadget/function/f_mass_storage.c:2233:11: sparse:   also defined here
   drivers/usb/gadget/function/f_mass_storage.c:2235:11: sparse: sparse: Initializer entry defined twice
   drivers/usb/gadget/function/f_mass_storage.c:2235:11: sparse:   also defined here
   drivers/usb/gadget/function/f_mass_storage.c:2259:11: sparse: sparse: Initializer entry defined twice
   drivers/usb/gadget/function/f_mass_storage.c:2259:11: sparse:   also defined here
   drivers/usb/gadget/function/f_mass_storage.c:2261:11: sparse: sparse: Initializer entry defined twice
   drivers/usb/gadget/function/f_mass_storage.c:2261:11: sparse:   also defined here
   drivers/usb/gadget/function/f_mass_storage.c:2263:11: sparse: sparse: Initializer entry defined twice
   drivers/usb/gadget/function/f_mass_storage.c:2263:11: sparse:   also defined here
   drivers/usb/gadget/function/f_mass_storage.c:2265:11: sparse: sparse: Initializer entry defined twice
   drivers/usb/gadget/function/f_mass_storage.c:2265:11: sparse:   also defined here
   drivers/usb/gadget/function/f_mass_storage.c: note: in included file (through include/linux/rcuwait.h, include/linux/percpu-rwsem.h, include/linux/fs.h, ...):
   include/linux/sched/signal.h:285:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   include/linux/sched/signal.h:285:28: sparse:     expected struct spinlock [usertype] *lock
   include/linux/sched/signal.h:285:28: sparse:     got struct spinlock [noderef] __rcu *
   include/linux/sched/signal.h:287:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   include/linux/sched/signal.h:287:30: sparse:     expected struct spinlock [usertype] *lock
   include/linux/sched/signal.h:287:30: sparse:     got struct spinlock [noderef] __rcu *

vim +1988 drivers/usb/gadget/function/f_mass_storage.c

  1969	
  1970	/* Adjust current profile which depended on an inserted medium */
  1971	static inline void cdf_populate_profile_list(struct fsg_common *common,
  1972						     struct cdr_features **feature)
  1973	{
  1974		__be16 current_media_type = cdr_guess_medium_type(common);
  1975		struct mmc_profile *profiles =
  1976			(*feature)->feature.profile_list.profiles;
  1977		int i;
  1978	
  1979		/* copy profile list to the response buffer */
  1980		memcpy(profiles, cdf_supported_profiles,
  1981		       sizeof(cdf_supported_profiles));
  1982		for (i = 0; i < CDF_PROFILES_COUNT; ++i) {
  1983			/*
  1984			 * Reset the current profile bit,
  1985			 * because it might be set from the previous one
  1986			 */
  1987			profiles[i].current_p = 0;
> 1988			if (be16_to_cpu(profiles[i].profile) == current_media_type) {
  1989				DBG(common, "Fill current profile: curr=(%04Xh)\n",
  1990				    be16_to_cpu(profiles[i].profile));
  1991				profiles[i].current_p = 1;
  1992			}
  1993		}
  1994	}
  1995	
  1996	static int do_get_configuration(struct fsg_common *common,
  1997					struct fsg_buffhd *bh)
  1998	{
  1999		struct fsg_lun *curlun = common->curlun;
  2000		int i;
  2001		struct cdb_get_configuration *cdb =
  2002			(struct cdb_get_configuration *)common->cmnd;
  2003		size_t buffer_size = sizeof(struct feature_header);
  2004		size_t generic_desc_size = sizeof(struct cdb_ft_generic);
  2005		struct feature_header *ret_header = (struct feature_header *)bh->buf;
  2006		u8 *ret_data = ((u8 *)ret_header) + buffer_size;
  2007	
  2008		LDBG(curlun, "Requesting features from 0x%04X, with RT flag 0x%02X\n",
  2009		     be16_to_cpu(cdb->sfn), cdb->rt);
  2010	
  2011		if (!common->curlun || !common->curlun->cdrom)
  2012			return -EINVAL;
  2013	
  2014		/* Go over *all* features, and copy them according to RT value */
  2015		for (i = 0; i < ARRAY_SIZE(features_table); ++i) {
  2016			struct cdb_ft_generic *generic =
  2017				(struct cdb_ft_generic *)&features_table[i];
  2018			struct cdr_features *feature = &features_table[i];
  2019	
  2020			if (feature->populate != NULL)
  2021				feature->populate(common, &feature);
  2022	
  2023			// a) RT is 0x00 and feature's code >= SFN
  2024			// b) RT is 0x01, feature's code >= SFN and feature has 'current' bit set
  2025			// c) RT is 0x02 and feature's code == SFN
  2026	
  2027			if (be16_to_cpu(generic->code) >= be16_to_cpu(cdb->sfn)) {
  2028				if ((cdb->rt == CDR_CFG_RT_FULL) ||
  2029				    (cdb->rt == CDR_CFG_RT_CURRENT &&
  2030				     generic->vpc.cur) ||
  2031				    (cdb->rt == CDR_CFG_RT_SPECIFIED_SFN &&
  2032				     be16_to_cpu(generic->code) ==
  2033					     be16_to_cpu(cdb->sfn))) {
  2034					LDBG(curlun, "Copying feature 0x%04X\n",
  2035					     be16_to_cpu(generic->code));
  2036	
  2037					memset(ret_data, 0,
  2038					       (generic->length + generic_desc_size));
  2039					/* Copy feature */
  2040					memcpy(ret_data, feature,
  2041					       (generic->length + generic_desc_size));
  2042					buffer_size +=
  2043						(generic->length + generic_desc_size);
  2044					ret_data +=
  2045						(generic->length + generic_desc_size);
  2046	
  2047					/* Break the loop if RT is CDR_CFG_RT_SPECIFIED_SFN */
  2048					if (cdb->rt == CDR_CFG_RT_SPECIFIED_SFN) {
  2049						LDBG(curlun,
  2050						     "Got the feature we wanted (0x%04X), breaking the loop\n",
  2051						     be16_to_cpu(cdb->sfn));
  2052						break;
  2053					}
  2054				}
  2055			}
  2056		}
  2057	
  2058		memset(ret_header, 0, sizeof(struct feature_header));
  2059		/* Header */
> 2060		ret_header->data_len = cpu_to_be32(buffer_size - generic_desc_size);
> 2061		ret_header->curr_profile =
> 2062			cpu_to_be16(cdr_guess_medium_type(common));
  2063	
  2064		dump_msg(common, "feature header", (u8 *)ret_header,
  2065			 sizeof(struct feature_header));
  2066	
  2067		dump_msg(common, "features table", (u8 *)bh->buf, buffer_size);
  2068	
  2069		common->data_size_to_handle = buffer_size;
  2070		return 0;
  2071	}
  2072	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Christoph Hellwig June 28, 2021, 9:53 a.m. UTC | #3
What is FMS?  And why do only patches 5 and 6 show up on the list?
And why does this mix changes to the SCSI layer, libata, usb-gadget and
the CDROM UAPI in a single patch?
diff mbox series

Patch

diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index eefda51f97d3..e49ff795a506 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -54,7 +54,7 @@  static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev)
 {
 	char *buf;
 	unsigned int ret;
-	struct rm_feature_desc *desc;
+	struct cdf_removable_medium *desc;
 	struct ata_taskfile tf;
 	static const char cdb[ATAPI_CDB_LEN] = {  GPCMD_GET_CONFIGURATION,
 			2,      /* only 1 feature descriptor requested */
@@ -82,15 +82,15 @@  static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev)
 		return ODD_MECH_TYPE_UNSUPPORTED;
 	}
 
-	if (be16_to_cpu(desc->feature_code) != 3) {
+	if (be16_to_cpu(desc->code) != 3) {
 		kfree(buf);
 		return ODD_MECH_TYPE_UNSUPPORTED;
 	}
 
-	if (desc->mech_type == 0 && desc->load == 0 && desc->eject == 1) {
+	if (desc->mechanism == 0 && desc->load == 0 && desc->eject == 1) {
 		kfree(buf);
 		return ODD_MECH_TYPE_SLOT;
-	} else if (desc->mech_type == 1 && desc->load == 0 &&
+	} else if (desc->mechanism == 1 && desc->load == 0 &&
 		   desc->eject == 1) {
 		kfree(buf);
 		return ODD_MECH_TYPE_DRAWER;
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 4865937799aa..7e736e5594f9 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -366,6 +366,87 @@  struct cdb_handler {
 	/* SCSI command ASCII name */
 	char *name;
 };
+/*-------------------------------------------------------------------------*/
+
+#define CDF_PROFILES_COUNT (ARRAY_SIZE(cdf_supported_profiles))
+
+/* List of supported profiles */
+static struct mmc_profile cdf_supported_profiles[] = {
+	{ .profile = cpu_to_be16(MMC_PROFILE_BD_ROM) },
+	{ .profile = cpu_to_be16(MMC_PROFILE_DVD_ROM) },
+	{ .profile = cpu_to_be16(MMC_PROFILE_CD_ROM) },
+};
+
+struct cdf_profile_list_custom {
+	struct cdf_profile_list header;
+	/* We support several profiles, whose indices are declared in the
+	 * enum above
+	 */
+	struct mmc_profile profiles[CDF_PROFILES_COUNT];
+} __packed;
+
+/**
+ * Type to allocate of all supported features
+ * @param populate - callback to fill the specified feature data which
+ * is depended by medium
+ */
+struct cdr_features;
+struct cdr_features {
+	union {
+		struct cdf_profile_list_custom profile_list;
+		struct cdf_core core;
+		struct cdf_morphing morphing;
+		struct cdf_removable_medium removable;
+		struct cdf_random_readable random_readable;
+		struct cdf_multi_read multi_read;
+		struct cdf_cd_read cd_read;
+		struct cdf_dvd_read dvd_read;
+		struct cdf_rt_streaming rt_streaming;
+	} __packed feature;
+	void (*populate)(struct fsg_common *common,
+			 struct cdr_features **features);
+};
+
+/**
+ * @brief Adjust the Profile List members of actual data which is depended
+ * on the inserted medium image
+ *
+ * @param common - the FSG instance
+ * @param feature - a list of profile descriptors which to be configured
+ */
+static void cdf_populate_profile_list(struct fsg_common *common,
+				      struct cdr_features **feature);
+
+#define CDF_SET_VPC(v, p, c) .vpc = { .ver = (v), .per = (p), .cur = (c) }
+
+#define CDF_FT_SIZE(member)                                                    \
+	((sizeof(((struct cdr_features *)0)->feature.member)) -                \
+	 sizeof(struct cdb_ft_generic))
+
+#define CDR_FT_ITEM(item, c, ...)                                              \
+	CDR_FT_ITEM_S(item, c, CDF_FT_SIZE(item), __VA_ARGS__)
+
+#define CDR_FT_ITEM_S(item, c, s, ...)                                         \
+	.feature.item = { .code = cpu_to_be16(c), .length = (s), __VA_ARGS__ }
+
+static struct cdr_features features_table[] = {
+	{ CDR_FT_ITEM_S(profile_list.header, CDF_PROFILE_LIST_CODE,
+			CDF_FT_SIZE(profile_list), CDF_SET_VPC(0, 1, 1)),
+	  .populate = &cdf_populate_profile_list },
+	{ CDR_FT_ITEM(core, CDF_CORE, CDF_SET_VPC(2, 1, 1), .dbevent = 1,
+		      .interface = cpu_to_be32(CF_PIS_USB)) },
+	{ CDR_FT_ITEM(morphing, CDF_MORPHING_CODE, CDF_SET_VPC(1, 1, 1),
+		      .ocevent = 1) },
+	{ CDR_FT_ITEM(removable, CDF_REMOVEBLE_MEDIA, CDF_SET_VPC(2, 1, 1),
+		      .mechanism = CDF_LMT__TRAY_TYPE, .eject = 1, .lock = 1) },
+	{ CDR_FT_ITEM(random_readable, CDF_RANDOM_READ, CDF_SET_VPC(0, 0, 1),
+		      .block_size = cpu_to_be32(CD_FRAMESIZE),
+		      .blocking = cpu_to_be16(0x10), .pp = 1) },
+	{ CDR_FT_ITEM(dvd_read, CDF_DVD_READ, CDF_SET_VPC(2, 1, 1),
+		      .multi110 = 1, .dualr = 1) },
+	{ CDR_FT_ITEM(rt_streaming, CDF_REAL_TIME_STREAM, CDF_SET_VPC(5, 0, 1),
+		      .rbcb = 1, .scs = 1, .mp2a = 1, .wspd = 1, .sw = 1) },
+};
 
 /*------------------------------------------------------------------------*/
 
@@ -1851,6 +1932,143 @@  static void send_status(struct fsg_common *common)
 	return;
 }
 
+/**
+ * Attempts to guess medium type by looking at the length of the disc layout.
+ */
+static inline __be16 cdr_guess_medium_type(struct fsg_common *common)
+{
+	struct fsg_lun *curlun = common->curlun;
+	size_t length = curlun->num_sectors;
+
+	if (length <= CD_MAX_FRAMES) {
+		LDBG(curlun, "Disc layout size implies CD-ROM image\n");
+		return MMC_PROFILE_CD_ROM;
+	} else if (length <= CD_DVD_MAX_FRAMES) {
+		LDBG(curlun,
+		     "Disc layout size implies single-layer DVD-ROM image\n");
+		return MMC_PROFILE_DVD_ROM;
+	} else if (length <= CD_DVDDL_MAX_FRAMES) {
+		LDBG(curlun,
+		     "Disc layout size implies dual-layer DVD-ROM image\n");
+		return MMC_PROFILE_DVD_ROM;
+	} else if (length <= CD_BD_MAX_FRAMES) {
+		LDBG(curlun,
+		     "Disc layout size implies single-layer BD-ROM image\n");
+		return MMC_PROFILE_BD_ROM;
+	} else if (length <= CD_BDDL_MAX_FRAMES) {
+		LDBG(curlun,
+		     "Disc layout size implies dual-layer BD-ROM image\n");
+		return MMC_PROFILE_BD_ROM;
+	}
+
+	LDBG(curlun,
+	     "Disc layout size (%u) exceeds all known media types, assuming BD - ROM !\n",
+	     length);
+	return MMC_PROFILE_BD_ROM;
+}
+
+/* Adjust current profile which depended on an inserted medium */
+static inline void cdf_populate_profile_list(struct fsg_common *common,
+					     struct cdr_features **feature)
+{
+	__be16 current_media_type = cdr_guess_medium_type(common);
+	struct mmc_profile *profiles =
+		(*feature)->feature.profile_list.profiles;
+	int i;
+
+	/* copy profile list to the response buffer */
+	memcpy(profiles, cdf_supported_profiles,
+	       sizeof(cdf_supported_profiles));
+	for (i = 0; i < CDF_PROFILES_COUNT; ++i) {
+		/*
+		 * Reset the current profile bit,
+		 * because it might be set from the previous one
+		 */
+		profiles[i].current_p = 0;
+		if (be16_to_cpu(profiles[i].profile) == current_media_type) {
+			DBG(common, "Fill current profile: curr=(%04Xh)\n",
+			    be16_to_cpu(profiles[i].profile));
+			profiles[i].current_p = 1;
+		}
+	}
+}
+
+static int do_get_configuration(struct fsg_common *common,
+				struct fsg_buffhd *bh)
+{
+	struct fsg_lun *curlun = common->curlun;
+	int i;
+	struct cdb_get_configuration *cdb =
+		(struct cdb_get_configuration *)common->cmnd;
+	size_t buffer_size = sizeof(struct feature_header);
+	size_t generic_desc_size = sizeof(struct cdb_ft_generic);
+	struct feature_header *ret_header = (struct feature_header *)bh->buf;
+	u8 *ret_data = ((u8 *)ret_header) + buffer_size;
+
+	LDBG(curlun, "Requesting features from 0x%04X, with RT flag 0x%02X\n",
+	     be16_to_cpu(cdb->sfn), cdb->rt);
+
+	if (!common->curlun || !common->curlun->cdrom)
+		return -EINVAL;
+
+	/* Go over *all* features, and copy them according to RT value */
+	for (i = 0; i < ARRAY_SIZE(features_table); ++i) {
+		struct cdb_ft_generic *generic =
+			(struct cdb_ft_generic *)&features_table[i];
+		struct cdr_features *feature = &features_table[i];
+
+		if (feature->populate != NULL)
+			feature->populate(common, &feature);
+
+		// a) RT is 0x00 and feature's code >= SFN
+		// b) RT is 0x01, feature's code >= SFN and feature has 'current' bit set
+		// c) RT is 0x02 and feature's code == SFN
+
+		if (be16_to_cpu(generic->code) >= be16_to_cpu(cdb->sfn)) {
+			if ((cdb->rt == CDR_CFG_RT_FULL) ||
+			    (cdb->rt == CDR_CFG_RT_CURRENT &&
+			     generic->vpc.cur) ||
+			    (cdb->rt == CDR_CFG_RT_SPECIFIED_SFN &&
+			     be16_to_cpu(generic->code) ==
+				     be16_to_cpu(cdb->sfn))) {
+				LDBG(curlun, "Copying feature 0x%04X\n",
+				     be16_to_cpu(generic->code));
+
+				memset(ret_data, 0,
+				       (generic->length + generic_desc_size));
+				/* Copy feature */
+				memcpy(ret_data, feature,
+				       (generic->length + generic_desc_size));
+				buffer_size +=
+					(generic->length + generic_desc_size);
+				ret_data +=
+					(generic->length + generic_desc_size);
+
+				/* Break the loop if RT is CDR_CFG_RT_SPECIFIED_SFN */
+				if (cdb->rt == CDR_CFG_RT_SPECIFIED_SFN) {
+					LDBG(curlun,
+					     "Got the feature we wanted (0x%04X), breaking the loop\n",
+					     be16_to_cpu(cdb->sfn));
+					break;
+				}
+			}
+		}
+	}
+
+	memset(ret_header, 0, sizeof(struct feature_header));
+	/* Header */
+	ret_header->data_len = cpu_to_be32(buffer_size - generic_desc_size);
+	ret_header->curr_profile =
+		cpu_to_be16(cdr_guess_medium_type(common));
+
+	dump_msg(common, "feature header", (u8 *)ret_header,
+		 sizeof(struct feature_header));
+
+	dump_msg(common, "features table", (u8 *)bh->buf, buffer_size);
+
+	common->data_size_to_handle = buffer_size;
+	return 0;
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -2035,6 +2253,9 @@  static struct cdb_command_check cdb_checker_table[] = {
 	{ CDB_REG_CHECKER(TEST_UNIT_READY, 6, CDB_NO_SIZE_FIELD, DATA_DIR_NONE,
 			  0x0000, MEDIUM_REQUIRED) },
 
+	{ CDB_REG_NO_CHECKER(GET_CONFIGURATION, CDB_SIZE_FIELD_7,
+			     DATA_DIR_TO_HOST, MEDIUM_REQUIRED) },
+
 	{ CDB_REG_CHECKER_BLK(VERIFY, 10, CDB_NO_SIZE_FIELD, DATA_DIR_NONE,
 			      0x0000, MEDIUM_REQUIRED) },
 	{ CDB_REG_CHECKER_BLK(WRITE_6, 6, CDB_SIZE_FIELD_4, DATA_DIR_FROM_HOST,
@@ -2065,6 +2286,7 @@  static struct cdb_handler cdb_handlers_table[] = {
 	{ CDB_REG_HANDLER(SYNCHRONIZE_CACHE, &do_synchronize_cache) },
 	{ CDB_REG_HANDLER(TEST_UNIT_READY, NULL) },
 
+	{ CDB_REG_HANDLER_BUFFHD(GET_CONFIGURATION, &do_get_configuration) },
 	/*
 	 * Although optional, this command is used by MS-Windows.  We
 	 * support a minimal version: BytChk must be 0.
diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index c36860111932..6b2a8ee1f0a3 100644
--- a/include/scsi/scsi_proto.h
+++ b/include/scsi/scsi_proto.h
@@ -73,6 +73,7 @@ 
 #define UNMAP		      0x42
 #define READ_TOC              0x43
 #define READ_HEADER           0x44
+#define GET_CONFIGURATION     0x46
 #define GET_EVENT_STATUS_NOTIFICATION 0x4a
 #define LOG_SELECT            0x4c
 #define LOG_SENSE             0x4d
diff --git a/include/uapi/linux/cdrom.h b/include/uapi/linux/cdrom.h
index 1d7b4333c3aa..442693fdc059 100644
--- a/include/uapi/linux/cdrom.h
+++ b/include/uapi/linux/cdrom.h
@@ -349,6 +349,12 @@  struct cdrom_generic_command
 /* most drives don't deliver everything: */
 #define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/
 #define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/
+/* total frames on the specific medium-disk format */
+#define CD_MAX_FRAMES			(CD_MINS * CD_SECS * CD_FRAMES)
+#define CD_DVD_MAX_FRAMES		(2295104)
+#define CD_DVDDL_MAX_FRAMES	(4173824)
+#define CD_BD_MAX_FRAMES		(12219392)
+#define CD_BDDL_MAX_FRAMES		(24438784)
 
 #define CD_XA_HEAD        (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */
 #define CD_XA_TAIL        (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */
@@ -896,12 +902,173 @@  typedef struct {
 	__be32 last_rec_address;
 } track_information;
 
+/* CDB Get Configuration command */
+
+/**
+ * The Drive shall return the Feature Header and all Feature Descriptors supported by the
+ * Drive without regard to currency
+ */
+#define CDR_CFG_RT_FULL 0x00
+/**
+ * The Drive shall return the Feature Header and only those Feature Descriptors in which
+ * the Current bit is set to one.
+ */
+#define CDR_CFG_RT_CURRENT 0x01
+/**
+ * The Feature Header and the Feature Descriptor identified by Starting Feature Number
+ * shall be returned. If the Drive does not support the specified feature, only the Feature
+ * Header shall be returned.
+ */
+#define CDR_CFG_RT_SPECIFIED_SFN 0x02
+#define CDR_CFG_RT_RESERVED 0x03
+
+/**
+ * @brief GET CONFIGURATION Command
+ * The GET CONFIGURATION command provides a Host with information about Drive capabilities;
+ * both current and potential.
+ *
+ * @note The command shall not return a CHECK CONDITION Status due to a pending
+ * UNIT ATTENTION Condition.
+ */
+struct cdb_get_configuration {
+	__u8 code;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved1 : 6;
+	/* The RT field identifies the type of data to be returned by the Drive */
+	__u8 rt : 2;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 rt : 2;
+	__u8 reserved1 : 6;
+#endif
+	/**
+	 * The Starting Feature Number field indicates the first Feature number to be returned.
+	 * All supported Feature numbers higher than the Starting Feature Number shall be
+	 * returned.
+	 */
+	__be16 sfn;
+	__u8 reserved2[3];
+	/**
+	 * The Allocation Length field specifies the maximum length in bytes of the
+	 * Get Configuration response data. An Allocation Length field of zero indicates that no
+	 * data shall be transferred
+	 */
+	__be16 length;
+	__u8 control;
+
+} __packed;
+
+/* Features */
+
+/* Feature and Profile Descriptors*/
+
+/**
+ * @brief The Version, Persisten and Current byte.
+ * This structure is required for many CDB features.
+ */
+struct cdb_ft_vpc_byte {
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved1 : 2;
+	/**
+	 * The Version field is reserved and shall be set to zero unless otherwise specified
+	 * within the Feature Description
+	 */
+	__u8 ver : 4;
+	/**
+	 * The Persistent bit, when set to zero, shall indicate that this Feature may change
+	 * its current status.
+	 * When set to one, shall indicate that this Feature is always active.
+	 * The Drive shall not set this bit to one if the Current bit is, or may become, zero.
+	 */
+	__u8 per : 1;
+	/**
+	 * The Current bit, when set to zero, indicates that this Feature is not currently
+	 * active and that the Feature Dependent Data may not be valid.
+	 * When set to one, this Feature is currently active and the Feature Dependent Data is
+	 * valid.
+	 */
+	__u8 cur : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 cur : 1;
+	__u8 per : 1;
+	__u8 ver : 4;
+	__u8 reserved1 : 2;
+#endif
+} __packed;
+
+/**
+ * @brief Feature Descriptor generic
+ * A Feature Descriptor shall describe each Feature supported by a Drive. All
+ * Feature descriptors shall be a multiple of four bytes
+ */
+struct cdb_ft_generic {
+	/**
+	 * The Feature Code field shall identify a Feature supported by the Drive
+	 */
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	/**
+	 * The Additional Length field indicates the number of Feature specific
+	 * bytes that follow this header. This field shall be an integral multiple
+	 * of 4
+	 */
+	__u8 length;
+} __packed;
+
+/* Profile list */
+#define MMC_PROFILE_NONE 0x0000
+#define MMC_PROFILE_CD_ROM 0x0008
+#define MMC_PROFILE_CD_R 0x0009
+#define MMC_PROFILE_CD_RW 0x000A
+#define MMC_PROFILE_DVD_ROM 0x0010
+#define MMC_PROFILE_DVD_R_SR 0x0011
+#define MMC_PROFILE_DVD_RAM 0x0012
+#define MMC_PROFILE_DVD_RW_RO 0x0013
+#define MMC_PROFILE_DVD_RW_SR 0x0014
+#define MMC_PROFILE_DVD_R_DL_SR 0x0015
+#define MMC_PROFILE_DVD_R_DL_JR 0x0016
+#define MMC_PROFILE_DVD_RW_DL 0x0017
+#define MMC_PROFILE_DVD_DDR 0x0018
+#define MMC_PROFILE_DVD_PLUS_RW 0x001A
+#define MMC_PROFILE_DVD_PLUS_R 0x001B
+#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A
+#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B
+#define MMC_PROFILE_BD_ROM 0x0040
+#define MMC_PROFILE_BD_R_SRM 0x0041
+#define MMC_PROFILE_BD_R_RRM 0x0042
+#define MMC_PROFILE_BD_RE 0x0043
+#define MMC_PROFILE_HDDVD_ROM 0x0050
+#define MMC_PROFILE_HDDVD_R 0x0051
+#define MMC_PROFILE_HDDVD_RAM 0x0052
+#define MMC_PROFILE_HDDVD_RW 0x0053
+#define MMC_PROFILE_HDDVD_R_DL 0x0058
+#define MMC_PROFILE_HDDVD_RW_DL 0x005A
+#define MMC_PROFILE_INVALID 0xFFFF
+
+/**
+ * @brief The CDB Feature Header
+ * Response data consists of a header field and zero or more variable length
+ * Feature descriptors
+ */
 struct feature_header {
+	/**
+	 * The Data Length field indicates the amount of data available given a
+	 * sufficient allocation length following this field.
+	 * This length shall not be truncated due to an insufficient Allocation
+	 * Length
+	 */
 	__u32 data_len;
 	__u8 reserved1;
 	__u8 reserved2;
+	/**
+	 * The Current Profile field shall identify one of the profiles from the
+	 * Profile List Feature. If there are no Profiles currently active, this
+	 * field shall contain zero.
+	 */
 	__u16 curr_profile;
-};
+} __packed;
 
 struct mode_page_header {
 	__be16 mode_data_length;
@@ -912,41 +1079,658 @@  struct mode_page_header {
 	__be16 desc_length;
 };
 
-/* removable medium feature descriptor */
-struct rm_feature_desc {
-	__be16 feature_code;
+/**
+ * @brief Profile descriptors are returned in the order of preferred
+ * operation – most desirable to least desirable. e.g., a DVD-ROM
+ * that is also able to read a CD-ROM should list the DVD-ROM
+ * Profile first and the CD-ROM Profile second.
+ */
+struct mmc_profile {
+	/* The Profile Number identifies a Profile */
+	__be16 profile;
+
 #if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 reserved1:2;
-	__u8 feature_version:4;
-	__u8 persistent:1;
-	__u8 curr:1;
+	__u8 reserved1 : 7;
+	/**
+	 * The current_p bit, when set to one, shall indicate that this
+	 * Profile is currently active.
+	 */
+	__u8 current_p : 1;
 #elif defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 curr:1;
-	__u8 persistent:1;
-	__u8 feature_version:4;
-	__u8 reserved1:2;
-#endif
-	__u8 add_len;
-#if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 mech_type:3;
-	__u8 load:1;
-	__u8 eject:1;
-	__u8 pvnt_jmpr:1;
-	__u8 dbml:1;
-	__u8 lock:1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8 lock:1;
-	__u8 dbml:1;
-	__u8 pvnt_jmpr:1;
-	__u8 eject:1;
-	__u8 load:1;
-	__u8 mech_type:3;
+	__u8 current_p : 1;
+	__u8 reserved1 : 7;
 #endif
+
 	__u8 reserved2;
-	__u8 reserved3;
-	__u8 reserved4;
+} __packed;
+
+/**
+ * @brief Profile List Feature (0000h)
+ *
+ * This Feature identifies Profiles supported by the Drive.
+ * Profiles are defined as collections of Features and provide a method
+ * to quickly determine the Drive’s type.
+ */
+struct cdf_profile_list {
+	/* The Feature Code */
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+	/**
+	 * The Additional Length field shall be set
+	 * to ((number of Profile Descriptors) * 4).
+	 */
+	__u8 length;
+} __packed;
+
+/**
+ * @brief The core feature: phisycal interface standards
+ */
+enum cdf_cf_pis {
+	CF_PIS_UNSPECIFIED = 0x00000000U,
+	CF_PIS_SCSI_FAMILY,
+	CF_PIS_ATAPI,
+	CF_PIS_IEEE_1394_1995,
+	CF_PIS_IEEE_1394A,
+	CF_PIS_FIBRE_CHANNEL,
+	CF_PIS_IEEE_1394_B,
+	CF_PIS_USB,
+	CF_PIS_RESERVED,
+	CF_PIS_DEF_INCITS = 0x00010000U,
+	CF_PIS_DEF_SFF = 0x00020000U,
+	CF_PIS_DEF_IEEE = 0x00030000U,
+	CF_PIS_DEF_RESERVED = 0x00040000U
 };
 
+/**
+ * @brief Core Feature (0001h)
+ * This Feature identifies a Drive that supports functionality common
+ * to all devices.
+ */
+struct cdf_core {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	/* The Additional Length field shall be set to 8. */
+	__u8 length;
+	/**
+	 * The Physical Interface Standard field shall be set to a value
+	 * selected from @enum cdf_cf_pis
+	 * It is possible that more than one physical interface exists
+	 * between the Host and Drive, e.g., an IEEE1394 Host connecting
+	 * to an ATAPI bridge to an ATAPI Drive. The Drive may not be aware
+	 * of interfaces beyond the ATAPI.
+	 */
+	__be32 interface;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2 : 6;
+	/**
+	 * The INQ2 bit permits the Drive to indicate support for certain
+	 * features of the INQUIRY command. If INQ2 is set to one, the
+	 * Drive shall support validation of EVPD, Page Code, and the
+	 * 16-bit Allocation Length fields
+	 */
+	__u8 inq2 : 1;
+	/**
+	 * DBE (Device Busy Event) shall be set to one.
+	 */
+	__u8 dbevent : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 dbevent : 1;
+	__u8 inq2 : 1;
+	__u8 reserved2 : 6;
+#endif
+
+	__u8 reserved3[3];
+} __packed;
+
+/**
+ * @brief Morphing Feature (0002h)
+ * This Feature identifies the ability of the Drive to notify
+ * A Host about operational changes and accept Host requests to
+ * prevent operational changes.
+ */
+struct cdf_morphing {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2 : 6;
+	__u8 ocevent : 1;
+	__u8 async : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 async : 1;
+	__u8 ocevent : 1;
+	__u8 reserved2 : 6;
+#endif
+
+	__u8 reserved3[3];
+} __packed;
+
+/**
+ * @brief Removable Medium: Loading Mechanism Types
+ */
+enum cdf_removable_media_lmt {
+	CDF_LMT__CADDY_SLOT_TYPE,
+	CDF_LMT__TRAY_TYPE,
+	CDF_LMT__POP_UP_TYPE,
+	CDF_LMT__RESERVED1,
+	CDF_LMT__EMBEDDED_INDIVIDUALLY,
+	CDF_LMT__EMBEDDED_MAGAZINE,
+	CDF_LMT__RESERVED2,
+};
+
+/**
+ * @brief Removable Medium Feature (0003h)
+ *
+ * This Feature identifies a Drive that has a medium that is removable.
+ * Media shall be considered removable if it is possible to remove it
+ * from the loaded position, i.e., a single mechanism changer, even if
+ * the media is captive to the changer.
+ *
+ * The Drive shall generate Events for media changes.
+ * Event Notification Class 4 (Media Events) shall be supported. This
+ * includes reporting user requests to load/eject the medium.
+ */
+struct cdf_removable_medium {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+	/* The Additional Length field shall be set to 4. */
+	__u8 length;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	/**
+	 * The Loading Mechanism Type field shall be set according to
+	 * @enum cdf_removable_media_lmt
+	 */
+	__u8 mechanism : 3;
+	/**
+	 * If the Load bit is set to zero, the Drive is unable to load
+	 * the medium or cartridge via the START STOP UNIT command with
+	 * the LoEj bit set to one, e.g. the tray type loading mechanism
+	 * that is found in many portable PCs.
+	 * If the Load bit is set to one, the Drive is able to load the
+	 * medium or cartridge.
+	 */
+	__u8 load : 1;
+	/**
+	 * The Eject bit, when set to zero, indicates that the device is
+	 * unable to eject the medium or magazine via the normal START STOP UNIT
+	 * command with the LoEj bit set.
+	 * When set to one, indicates that the device is able to eject
+	 * the medium or magazine.
+	 */
+	__u8 eject : 1;
+	/**
+	 * The Pvnt Jmpr bit, when set to zero, shall indicate that the
+	 * Prevent Jumper is present.
+	 * When set to one, the Prevent Jumper is not present.
+	 * The Pvnt Jmpr bit shall not change state, even if the physical
+	 * jumper is added or removed during operation.
+	 */
+	__u8 prvnt_jmp : 1;
+	__u8 reserved2 : 1;
+	/**
+	 * If Lock is set to zero, there is no locking mechanism for locking
+	 * the medium into the Drive. If Lock is set to one, the Drive is
+	 * capable of locking the media into the Drive.
+	 */
+	__u8 lock : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 lock : 1;
+	__u8 reserved2 : 1;
+	__u8 prvnt_jmp : 1;
+	__u8 eject : 1;
+	__u8 load : 1;
+	__u8 mechanism : 3;
+#endif
+
+	__u8 reserved3[3];
+} __packed;
+
+/**
+ * @brief Random Readable Feature (0010h)
+ *
+ * This Feature identifies a Drive that is able to read data from logical
+ * blocks referenced by Logical Block Addresses, but not requiring that
+ * either the addresses or the read sequences occur in any particular order.
+ */
+struct cdf_random_readable {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+	/* The Additional Length field shall be set to 8. */
+	__u8 length;
+	/**
+	 * The Logical Block Size shall be set to the number of bytes per
+	 * logical block.
+	 */
+	__be32 block_size;
+	/**
+	 * The Blocking field shall indicate the number of logical blocks per
+	 * device readable unit.
+	 * If there is more than one Blocking on the medium possible,
+	 * the Blocking field shall be set to zero.
+	 */
+	__be16 blocking;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2 : 7;
+	/**
+	 * The PP (Page Present) bit, when set to zero, shall indicate that
+	 * the Read/Write Error Recovery mode page may not be present.
+	 * When set to one, shall indicate that the Read/Write Error Recovery
+	 * mode page is present.
+	 */
+	__u8 pp : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 pp : 1;
+	__u8 reserved2 : 7;
+#endif
+
+	__u8 reserved3;
+} __packed;
+
+/*
+ * Multi-read Feature (001Dh)
+ * The Drive shall conform to the OSTA Multi-Read
+ * specification 1.00, with the exception of CD Play
+ * capability (the CD Audio Feature is not required).
+ */
+struct cdf_multi_read {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+} __packed;
+
+/*
+ * CD Read Feature (001Eh)
+ * This Feature identifies a Drive that is able to read
+ * CD specific information from the media and is able
+ * to read user data from all types of CD sectors.
+ */
+struct cdf_cd_read {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+#if defined(__BIG_ENDIAN_BITFIELD)
+
+	/*
+	 * If DAP is set to one, the READ CD and READ CD MSF
+	 * commands support the DAP bit in bit 1, byte 1
+	 * of the CDB.
+	 */
+	__u8 dap : 1;
+	__u8 reserved2 : 5;
+
+	/*
+	 * The C2 Flags, when set to one, indicates the Drive
+	 * supports the C2 Error Pointers.
+	 * When set to zero the Drive does not support
+	 * C2 Error Pointers.
+	 */
+	__u8 c2flags : 1;
+	/*
+	 * The CD-Text bit, when set to one, indicates the Drive
+	 * supports Format Code 5h of the READ TOC/PMA/ATIP
+	 * command.
+	 * When set to zero, CD-Text is not supported.
+	 */
+	__u8 cdtext : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 cdtext : 1;
+	__u8 c2flags : 1;
+	__u8 reserved2 : 5;
+	__u8 dap : 1;
+#endif
+
+	__u8 reserved3[3];
+} __packed;
+
+/*
+ * DVD Read Feature (001Fh)
+ * This Feature identifies a Drive that is able to read DVD
+ * specific information from the media.
+ */
+struct cdf_dvd_read {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2 : 7;
+	/*
+	 * If MULTI110 is set to one, the Drive shall
+	 * be compliant with the DVD Multi Drive Read-only
+	 * specifications as defined in [DVD-Ref8].
+	 */
+	__u8 multi110 : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 multi110 : 1;
+	__u8 reserved2 : 7;
+#endif
+	__u8 reserved3;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved4 : 6;
+	/*
+	 * If the DVD-RW Dual Layer (Dual-RW) bit is set to one,
+	 * the Drive is able to read DVD-RW DL media that has the
+	 * Complete state.
+	 * If the Dual-RW bit is set to zero, the Drive is unable
+	 * to read the DVD-RW DL media.
+	 */
+	__u8 dualrw : 1;
+	/*
+	 * If the DVD-R Dual Layer (Dual-R) bit is set to one,
+	 * the Drive shall support reading all recording modes
+	 * (i.e., Sequential recording and Layer Jump recording modes)
+	 * of DVD-R DL discs.
+	 * The Drive shall support Remapping on DVD-R DL discs.
+	 */
+	__u8 dualr : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 dualr : 1;
+	__u8 dualrw : 1;
+	__u8 reserved4 : 6;
+#endif
+
+	__u8 reserved5;
+} __packed;
+
+/**
+ * @brief DVD+R Feature (002Bh)
+ * The presence of the DVD+R Feature indicates that the Drive is
+ * capable of reading a recorded DVD+R disc that is written according
+ * to [DVD+Ref1].
+ * Specifically, this includes the capability of reading DCBs.
+ */
+struct cdf_dvd_plus_r {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2 : 7;
+	/**
+	 * If the Write bit is set to one, then the Drive is also capable
+	 * of writing DVD+R discs according to [DVD+Ref1].
+	 */
+	__u8 write : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 write : 1;
+	__u8 reserved2 : 7;
+#endif
+
+	__u8 reserved3[3];
+} __packed;
+
+/**
+ * @brief CD Track at Once Feature (002Dh)
+ * This Feature identifies a Drive that is able to write data to
+ * a CD track.
+ */
+struct cdf_cd_track_at_once {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2 : 1;
+	/**
+	 * The BUF bit, if set to 1, shall indicate that the Drive
+	 * is capable of zero loss linking.
+	 */
+	__u8 buf : 1;
+	__u8 reserved1 : 1;
+	/**
+	 * The R-W Raw bit, if set to 1, shall indicate that the Drive
+	 * supports writing R-W Sub code in the Raw mode.
+	 * The R-W Sub-code bit shall be set if this bit is set.
+	 */
+	__u8 rw_raw : 1;
+	/**
+	 * The R-W Pack bit, if set to 1, shall indicate that the Drive
+	 * supports writing R-W Sub code in the Packed mode.
+	 * The R-W Sub-code bit shall be set if this bit is set.
+	 */
+	__u8 rw_pack : 1;
+	/**
+	 * The Test Write bit indicates that the Drive is able to
+	 * perform test writes.
+	 */
+	__u8 test_write : 1;
+	/**
+	 * The CD-RW bit indicates support for overwriting a Track at
+	 * Once track with another.
+	 */
+	__u8 cd_rw : 1;
+	/**
+	 * The R-W Sub-code bit indicates that the Drive is able to
+	 * record the R-W Sub-channels with user supplied data.
+	 */
+	__u8 rw_subcode : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 rw_subcode : 1;
+	__u8 cd_rw : 1;
+	__u8 test_write : 1;
+	__u8 rw_pack : 1;
+	__u8 rw_raw : 1;
+	__u8 reserved3 : 1;
+	__u8 buf : 1;
+	__u8 reserved2 : 1;
+#endif
+
+	__u8 reserved4;
+	/**
+	 * The data type references to the
+	 * "Incremental Streaming Writable Feature"
+	 */
+	__be16 data_type_supported;
+} __packed;
+
+/**
+ * @brief BD Read Feature (0040h)
+ * This Feature identifies a Drive that is able to read control
+ * structures and user data from the BD disc.
+ */
+struct cdf_bd_read {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+
+	__u8 reserved2[4];
+	/**
+	 * If the Version K bit (K = 0...15) of the Class M (M = 0...3)
+	 * bit map is set to zero, the Drive claims no read capabilities
+	 * for BD-R(E)(ROM) discs of Class M and Version K.
+	 * If the Version K bit of Class M is set to one, the Drive is
+	 * able to read BD-RE discs of class M and Version K.
+	 *
+	 */
+
+	/* Class M (M = 0..3) BD-RE Read Support */
+	__be16 class0_bdre_read_support;
+	__be16 class1_bdre_read_support;
+	__be16 class2_bdre_read_support;
+	__be16 class3_bdre_read_support;
+	/* Class M (M = 0..3) BD-R Read Support */
+	__be16 class0_bdr_read_support;
+	__be16 class1_bdr_read_support;
+	__be16 class2_bdr_read_support;
+	__be16 class3_bdr_read_support;
+	/* Class M (M = 0..3) BD-ROM Read Support */
+	__be16 class0_bdrom_read_support;
+	__be16 class1_bdrom_read_support;
+	__be16 class2_bdrom_read_support;
+	__be16 class3_bdrom_read_support;
+} __packed;
+
+/**
+ * @brief Power Management Feature (0100h)
+ * This Feature identifies a Drive that is able to perform Host and
+ * Drive directed power management.
+ */
+struct cdf_power_mgmt {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+} __packed;
+
+/**
+ * @brief Real Time Streaming Feature (0107h)
+ * This Feature identifies a Drive that is able to perform reading
+ * and writing within Host specified (and Drive verified) performance
+ * ranges. This Feature also indicates whether the Drive supports the
+ * Stream playback operation.
+ */
+struct cdf_rt_streaming {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	__u8 length;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2 : 3;
+	/**
+	 * The Read Buffer Capacity Block (RBCB) bit indicates that the
+	 * Drive supports the READ_BUFFER_CAPACITY command and its Block
+	 * bit.
+	 */
+	__u8 rbcb : 1;
+	/**
+	 * The Set CD Speed (SCS) bit of one indicates that the Drive
+	 * supports the SET_CD_SPEED command. Otherwise, the Drive does not
+	 * support the SET_CD_SPEED command.
+	 */
+	__u8 scs : 1;
+	/**
+	 * The mode page 2A (MP2A) bit of one indicates that the MM
+	 * Capabilities & Mechanical Status mode page (2Ah) with the Drive
+	 * Write Speed Performance Descriptor Blocks is supported.
+	 * Otherwise, the MM Capabilities & Mechanical Status mode
+	 * page (2Ah), with the Drive Write Speed Performance Descriptor
+	 * Blocks are not supported by the Drive.
+	 */
+	__u8 mp2a : 1;
+	/**
+	 * A Write Speed Performance Descriptor (WSPD) bit of one indicates
+	 * that the Drive supports the Write Speed (Type field = 03h) data
+	 * of GET PERFORMANCE command and the WRC field of SET STREAMING
+	 * command. This bit shall be set to one, if Drive supports writing
+	 * speed selection.
+	 */
+	__u8 wspd : 1;
+	/**
+	 * A Stream Writing (SW) bit of one indicates that the Drive
+	 * supports the Stream recording operation. A SW bit of zero
+	 * indicates that the Drive may not support the Stream recording
+	 * operation.
+	 */
+	__u8 sw : 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 sw : 1;
+	__u8 wspd : 1;
+	__u8 mp2a : 1;
+	__u8 scs : 1;
+	__u8 rbcb : 1;
+	__u8 reserved2 : 3;
+#endif
+
+	__u8 reserved3[3];
+} __packed;
+
+/**
+ * @brief Disc Control Blocks (DCBs) Feature (010Ah)
+ *
+ * This Feature identifies a Drive that is able to read and/or write
+ * DCBs from or to the media.
+ */
+struct cdf_dcbs {
+	__be16 code;
+
+	struct cdb_ft_vpc_byte vpc;
+
+	/**
+	 * The Additional Length field shall be set to N * 4, where n is
+	 * the number of Supported DCB entries. The Supported DCB entry
+	 * n fields shall each contain the Content Descriptor of a
+	 * supported DCB.
+	 * Entries shall be sorted in ascending order.
+	 */
+	__u8 length;
+
+	/**
+	 * Non supported read and/or write the DCBs blocks.
+	 */
+	__be32 supported_dcb_entry[0];
+};
+
+/*
+ * feature codes list
+ */
+
+/* A list of all Profiles supported by the Drive*/
+#define CDF_PROFILE_LIST_CODE 0x0000
+/* Mandatory behavior for all devices */
+#define CDF_CORE 0x0001
+
+#define CDF_MORPHING_CODE 0x0002
+/* The medium may be removed from the device */
+#define CDF_REMOVEBLE_MEDIA 0x0003
+#define CDF_RANDOM_READ 0x0010
+/* The Drive is able to read all CD media types; based on OSTA MultiRead */
+#define CDF_MULTI_READ 0x001D
+/* The ability to read CD specific structures */
+#define CDF_CD_READ 0x001E
+/* The ability to read DVD specific structures*/
+#define CDF_DVD_READ 0x001F
+/* Write support for randomly addressed writes */
+#define CDF_RWRT 0x0020
+/* Write support for sequential recording */
+#define CDF_INC_STREAM_WR 0x0021
+/* Hardware Defect Management */
+#define CDF_HWDM 0x0024
+/* The ability to recognize and read and optionally write MRW formatted media */
+#define CDF_MRW 0x0028
+/* The ability to read DVD+R recorded media formats */
+#define CDF_DVD_R 0x002B
+/* Ability to write CD with Track at Once recording */
+#define CDF_CD_TRACK_ONCE 0x002D
+/* The ability to read control structures and user data from a BD disc */
+#define CDF_BD_READ 0x0040
+/* The ability to write control structures and user data to certain BD discs */
+#define CDF_BD_WRITE 0x0041
+/* Host and device directed power management */
+#define CDF_POWER_MGMT 0x0100
+/* Ability to perform DVD CSS/CPPM authentication and RPC */
+#define CDF_DVD_CSS 0x0106
+/* Ability to read and write using Host requested performance parameters */
+#define CDF_REAL_TIME_STREAM 0x0107
+/* The ability to read and/or write DCBs*/
+#define CDF_DCBS 0x010A
+
 /**
  * The READ TOC/PMA/ATIP format field values
  */