diff -uprN -X dontdiff linux-2.6.12/drivers/usb/storage/Kconfig linux/drivers/usb/storage/Kconfig --- linux-2.6.12/drivers/usb/storage/Kconfig 2005-06-17 15:48:29.000000000 -0400 +++ linux/drivers/usb/storage/Kconfig 2005-08-18 18:22:54.000000000 -0400 @@ -111,3 +111,9 @@ config USB_STORAGE_JUMPSHOT Say Y here to include additional code to support the Lexar Jumpshot USB CompactFlash reader. +config USB_STORAGE_KARMA + bool "Rio Karma MP3 player (EXPERIMENTAL)" + depends on USB_STORAGE && EXPERIMENTAL + help + Say Y here to include additional code to support the Rio Karma + digital music player as a mass storage device. diff -uprN -X dontdiff linux-2.6.12/drivers/usb/storage/Makefile linux/drivers/usb/storage/Makefile --- linux-2.6.12/drivers/usb/storage/Makefile 2005-06-17 15:48:29.000000000 -0400 +++ linux/drivers/usb/storage/Makefile 2005-08-18 18:22:54.000000000 -0400 @@ -18,6 +18,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DPC usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o +usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += rio_karma.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o $(usb-storage-obj-y) diff -uprN -X dontdiff linux-2.6.12/drivers/usb/storage/rio_karma.c linux/drivers/usb/storage/rio_karma.c --- linux-2.6.12/drivers/usb/storage/rio_karma.c 1969-12-31 19:00:00.000000000 -0500 +++ linux/drivers/usb/storage/rio_karma.c 2005-08-30 23:50:31.000000000 -0400 @@ -0,0 +1,105 @@ +/* USB driver for DNNA Rio Karma + * + * Rio Karma driver v0.1.1 + * (C) 2005 Bob Copeland (email@bobcopeland.com) + * + * The Karma is a mass storage device, although it requires some + * initialization code to get in that mode. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include "rio_karma.h" +#include "usb.h" +#include "transport.h" +#include "debug.h" + +#define RIOP_INIT "RIOP\x00\x01\x08" +#define CMD_LEN 40 +#define RECV_LEN 0x200 + +/* Initialize the karma and get it into mass storage mode. + * + * The initialization begins by sending RIOP\x00\x01\x08\x00... which + * the device will ack with a 512 byte packet with the high four bits + * set and everything else null. + * + * Next, we send RIOP\x80\x00\x08\x00. Each time, a 512 byte response + * must be read, but we must loop until byte 5 in the response is 0x08, + * indicating success. */ +int rio_karma_init(struct us_data *us) +{ + int result, partial; + static char init_cmd[] = RIOP_INIT; + char *cmd, *recv, *buf; + unsigned long timeout = jiffies + 2 * HZ; /* give it a few seconds */ + + if (!(buf = kmalloc(CMD_LEN + RECV_LEN, GFP_KERNEL | __GFP_DMA))) + goto init_failed; + + cmd = buf; + recv = buf + CMD_LEN; + + us->max_lun = 0; + + US_DEBUGP("Initializing Karma...\n"); + + memcpy(cmd, init_cmd, sizeof(init_cmd)); + memset(&cmd[sizeof(init_cmd)], 0, CMD_LEN - sizeof(init_cmd)); + + result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, cmd, + CMD_LEN, &partial); + if (result != USB_STOR_XFER_GOOD) + goto init_failed; + + result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, + recv, RECV_LEN, &partial); + if (result != USB_STOR_XFER_GOOD) + goto init_failed; + + cmd[4] = 0x80; + cmd[5] = 0; + for (;;) { + US_DEBUGP("Sending init command\n"); + result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, + cmd, CMD_LEN, &partial); + if (result != USB_STOR_XFER_GOOD) + goto init_failed; + + result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, + recv, RECV_LEN, &partial); + if (result != USB_STOR_XFER_GOOD) + goto init_failed; + + if (recv[5] == 0x08) + break; + if (time_after(jiffies, timeout)) + goto init_failed; + msleep(10); + } + US_DEBUGP("Karma initialized.\n"); + kfree(buf); + return 0; + +init_failed: + kfree(buf); + US_DEBUGP("Could not initialize karma.\n"); + return USB_STOR_TRANSPORT_FAILED; +} + diff -uprN -X dontdiff linux-2.6.12/drivers/usb/storage/rio_karma.h linux/drivers/usb/storage/rio_karma.h --- linux-2.6.12/drivers/usb/storage/rio_karma.h 1969-12-31 19:00:00.000000000 -0500 +++ linux/drivers/usb/storage/rio_karma.h 2005-08-18 19:16:57.000000000 -0400 @@ -0,0 +1,31 @@ +/* Header file for USB driver for DNNA Rio Karma + * + * Rio Karma driver v0.1.1 + * + * (C) 2005 Bob Copeland (email@bobcopeland.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _RIO_KARMA_H +#define _RIO_KARMA_H + +#include +#include "usb.h" + +int rio_karma_init(struct us_data *); + +#endif diff -uprN -X dontdiff linux-2.6.12/drivers/usb/storage/unusual_devs.h linux/drivers/usb/storage/unusual_devs.h --- linux-2.6.12/drivers/usb/storage/unusual_devs.h 2005-06-17 15:48:29.000000000 -0400 +++ linux/drivers/usb/storage/unusual_devs.h 2005-08-30 23:57:51.000000000 -0400 @@ -96,6 +96,14 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), #endif +#ifdef CONFIG_USB_STORAGE_KARMA +UNUSUAL_DEV( 0x045a, 0x5210, 0x0000, 0x9999, + "Rio", + "Rio Karma", + US_SC_SCSI, US_PR_BULK, rio_karma_init, + US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN ), +#endif + /* Patch submitted by Philipp Friedrich */ UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, "Kyocera", @@ -1039,3 +1047,4 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x US_SC_SCSI, US_PR_SDDR55, NULL, US_FL_SINGLE_LUN), #endif + diff -uprN -X dontdiff linux-2.6.12/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c --- linux-2.6.12/drivers/usb/storage/usb.c 2005-06-17 15:48:29.000000000 -0400 +++ linux/drivers/usb/storage/usb.c 2005-08-18 18:22:54.000000000 -0400 @@ -90,6 +90,9 @@ #ifdef CONFIG_USB_STORAGE_JUMPSHOT #include "jumpshot.h" #endif +#ifdef CONFIG_USB_STORAGE_KARMA +#include "rio_karma.h" +#endif /* Some informational data */ diff -uprN -X dontdiff linux-2.6.12/fs/Kconfig linux/fs/Kconfig --- linux-2.6.12/fs/Kconfig 2005-06-17 15:48:29.000000000 -0400 +++ linux/fs/Kconfig 2005-09-03 00:26:07.000000000 -0400 @@ -1699,6 +1699,11 @@ config CODA_FS_OLD_API For most cases you probably want to say N. +config OMFS_FS + tristate "OMFS (Rio Karma)" + help + Say 'Y' to get support for the RIO Karma fs. + config AFS_FS # for fs/nls/Config.in tristate "Andrew File System support (AFS) (Experimental)" diff -uprN -X dontdiff linux-2.6.12/fs/Makefile linux/fs/Makefile --- linux-2.6.12/fs/Makefile 2005-06-17 15:48:29.000000000 -0400 +++ linux/fs/Makefile 2005-09-03 00:41:26.000000000 -0400 @@ -94,4 +94,5 @@ obj-$(CONFIG_AFS_FS) += afs/ obj-$(CONFIG_BEFS_FS) += befs/ obj-$(CONFIG_HOSTFS) += hostfs/ obj-$(CONFIG_HPPFS) += hppfs/ +obj-$(CONFIG_OMFS_FS) += omfs/ obj-$(CONFIG_DEBUG_FS) += debugfs/ diff -uprN -X dontdiff linux-2.6.12/fs/omfs/Makefile linux/fs/omfs/Makefile --- linux-2.6.12/fs/omfs/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ linux/fs/omfs/Makefile 2005-09-12 21:25:58.000000000 -0400 @@ -0,0 +1,8 @@ +# +# Makefile for OMFS filesystem. +# + + +obj-$(CONFIG_OMFS_FS) += omfs.o + +omfs-objs := inode.o diff -uprN -X dontdiff linux-2.6.12/fs/omfs/inode.c linux/fs/omfs/inode.c --- linux-2.6.12/fs/omfs/inode.c 1969-12-31 19:00:00.000000000 -0500 +++ linux/fs/omfs/inode.c 2005-09-12 23:57:17.000000000 -0400 @@ -0,0 +1,440 @@ +/* + * fs/omfs/inode.c + * OMFS (as used by RIO Karma) inode operations. + * Copyright (C) 2005 Bob Copeland + */ + +#include +#include +#include +#include +#include +#include "omfs.h" + +MODULE_AUTHOR("Bob Copeland "); +MODULE_DESCRIPTION("OMFS (ReplayTV/Karma) Filesystem for Linux"); +MODULE_LICENSE("GPL"); + +#define OMFS_DIR 'D' +#define OMFS_FILE 'F' +#define OMFS_NAMELEN 256 +#define ERRPTR(foo) 0 + +static void omfs_read_inode(struct inode *inode); +static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir); +static struct super_block *omfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data); +static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd); +static int omfs_readpage(struct file *file, struct page *page); + +struct omfs_super_block { + char fill1[256]; + u32 fill2; + u32 root_block; + u64 num_blocks; + u32 magic; + u32 blocksize; + u32 mirrors; + u32 sys_blocksize; +}; + +struct omfs_header { + u32 fill1; + u32 self; + u32 body_size; + u16 crc; + char fill2[5]; + u8 check_xor; + u32 fill3; +}; + +struct omfs_root_block { + struct omfs_header head; + u64 fill3; + u64 num_blocks; + u32 fill4; + u32 root_dir; + u64 fill5; + u32 blocksize; + u32 clustersize; + u64 mirrors; + char name[OMFS_NAMELEN]; +}; + +struct omfs_inode { + struct omfs_header head; + u32 fill1; + u32 parent; + u32 fill2; + u32 sibling; + u64 ctime; + char fill3[35]; + char type; + u32 fill4; + char fill5[64]; + char name[OMFS_NAMELEN]; + u64 size; + // 198 bytes of nonsense. +}; + +struct omfs_extent { + u32 fill1; + u32 next; + u32 extent_count; + u32 fill2; + u32 fill3; + u32 cluster; + u32 fill4; + u32 blocks; +}; + +static inline sector_t logical_to_sector(sector_t in) +{ + return in << 4; +} + +static struct file_operations omfs_file_operations = { + .llseek = generic_file_llseek, + .read = generic_file_read, + .write = generic_file_write, + .mmap = generic_file_mmap, + .sendfile = generic_file_sendfile, +}; + +static struct address_space_operations omfs_aops = { + .readpage = omfs_readpage, +}; + +static struct inode_operations omfs_dir_inops = { + .lookup = omfs_lookup, +}; + +static struct file_operations omfs_dir_operations = { + .read = generic_read_dir, + .readdir = omfs_readdir, +}; + +static struct super_operations omfs_sops = { + .read_inode = omfs_read_inode, +}; + +/**** directory stuff ****/ + +static struct buffer_head *omfs_find_entry(struct inode *dir, + const char *name, int namelen) +{ + struct buffer_head *bh, *bh2; + struct omfs_inode *oi; + + // get the bh for this inode (should be cached w/?) + // read bh+1 up to i_size. make this cleaner like bfs? + int block = 1 + logical_to_sector(dir->i_ino); + loff_t offset = 0x200; // FIXME + + while (offset < dir->i_size) { + int i = 0; + + bh = sb_bread(dir->i_sb, block++); + if (!bh) + goto out; + + for (i = 0; i < dir->i_sb->s_blocksize && offset < dir->i_size; + i += 8, offset += 8) { + u64 cluster = be64_to_cpu(*((u64 *) & bh->b_data[i])); + if (cluster != ~0) { + bh2 = + sb_bread(dir->i_sb, + logical_to_sector(cluster)); + if (!bh2) + goto out; + + oi = (struct omfs_inode *)bh2->b_data; + if (strncmp(oi->name, name, namelen) == 0) { + brelse(bh); + return bh2; + } + brelse(bh2); + } + } + brelse(bh); + } + out: + return 0; +} + +static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +{ + struct buffer_head *bh; + struct inode *inode = NULL; + + if (dentry->d_name.len > OMFS_NAMELEN) + return ERRPTR(-ENAMETOOLONG); + + printk(KERN_DEBUG "looked up %s\n", dentry->d_name.name); + + bh = omfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); + if (bh) { + struct omfs_inode *oi = (struct omfs_inode *)bh->b_data; + ino_t ino = be32_to_cpu(oi->head.self); + brelse(bh); + inode = iget(dir->i_sb, ino); + if (!inode) { + unlock_kernel(); + return ERR_PTR(-EINVAL); //FIXME Acc + } + } + d_add(dentry, inode); + return NULL; +} + +static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir) +{ + struct inode *dir = filp->f_dentry->d_inode; + struct buffer_head *bh, *bh2; + struct omfs_inode *oi; + int ret = 0; + + printk(KERN_DEBUG "in readdir %lu\n", dir->i_ino); + + loff_t offset = filp->f_pos; + + // add locking + while (offset < dir->i_size) { + unsigned int block = 1 + (offset >> 9); // FIXME (blocksize bits??) + unsigned int bl_ofs = offset & (dir->i_sb->s_blocksize - 1); + + bh = sb_bread(dir->i_sb, block + logical_to_sector(dir->i_ino)); + if (!bh) { + ret = -EINVAL; + goto out; + } + do { + unsigned char d_type = DT_DIR; + u64 cluster = + be64_to_cpu(*((u64 *) & bh->b_data[bl_ofs])); + if (cluster != ~0) { + bh2 = + sb_bread(dir->i_sb, + logical_to_sector(cluster)); + if (!bh2) { + ret = -EINVAL; + goto out; + } + + oi = (struct omfs_inode *)bh2->b_data; + if (oi->type == OMFS_DIR) + d_type = DT_DIR; + else + d_type = DT_REG; + + filldir(dirent, oi->name, + strnlen(oi->name, OMFS_NAMELEN), + filp->f_pos, cluster, d_type); + printk(KERN_DEBUG "omfs: added file %s\n", + oi->name); + brelse(bh2); + } + bl_ofs += 8; + offset += 8; + filp->f_pos += 8; + + } while (offset < dir->i_size && + bl_ofs < dir->i_sb->s_blocksize); + brelse(bh); + } + out: + return ret; +} + +/**** file stuff ****/ + +static int omfs_get_block(struct inode *inode, sector_t block, + struct buffer_head *bh_result, int create) +{ + struct buffer_head *bh; + sector_t start, next; + struct omfs_extent *oe; + if (create) + return -EIO; + + if (block < 0) // || > stuff + return -EIO; + + /* wants block 0.. N of a given file. we have to count + * the blocks in clusters and total clusters in an extent + * to find the right extent. we have to search the extents + * in order. + */ + sector_t logical = block >> 4; // logic = block/16 (8192->512) + sector_t phys_ofs = block & 15; // = block % 16 + + // FIXME store this stuff ? + bh = sb_bread(inode->i_sb, logical_to_sector(inode->i_ino)); + if (!bh) + return -EIO; + + oe = (struct omfs_extent *)(&bh->b_data[0x1d0]); + + // skip to the right extent + start = 0; + for (;;) { + u32 *eptr = &oe->cluster; + int count = be32_to_cpu(oe->extent_count); + while (count-- > 0) { + sector_t cluster = be32_to_cpu(*eptr); + /* size is size in 8192-blocks */ + int size = be32_to_cpu(*eptr + 2); + + if (logical >= start && logical < start + size) { + map_bh(bh_result, inode->i_sb, + ((cluster + logical) << 4) + phys_ofs); + return 0; + } + start += size; + eptr += 6; + } + next = be32_to_cpu(oe->next); + brelse(bh); + + if (next == ~0) + break; + + bh = sb_bread(inode->i_sb, logical_to_sector(oe->next)); + if (!bh) + return -EIO; + oe = (struct omfs_extent *)(&bh->b_data[0x40]); + } + return 0; +} + +static int omfs_readpage(struct file *file, struct page *page) +{ + return block_read_full_page(page, omfs_get_block); +} + +/**** inode stuff ****/ + +static void omfs_read_inode(struct inode *inode) +{ + struct omfs_inode *oi; + struct buffer_head *bh; + unsigned int block; + ino_t ino = inode->i_ino; + + printk(KERN_DEBUG "omfs: Reading inode: %lx\n", ino); + + // check against num_blocks + block = logical_to_sector(ino); + bh = sb_bread(inode->i_sb, block); + if (!bh) { + make_bad_inode(inode); + return; + } + + oi = (struct omfs_inode *)bh->b_data; + + // check self + if (ino != be32_to_cpu(oi->head.self)) { + make_bad_inode(inode); + return; + } + + inode->i_uid = 0; + inode->i_gid = 0; + + if (oi->type == OMFS_DIR) { + inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; + inode->i_mode |= S_IFDIR; + inode->i_op = &omfs_dir_inops; + inode->i_fop = &omfs_dir_operations; + inode->i_size = (loff_t) be32_to_cpu(oi->head.body_size) + + sizeof(struct omfs_header); + } else if (oi->type == OMFS_FILE) { + inode->i_mode = S_IFREG | S_IRUGO; + inode->i_mapping->a_ops = &omfs_aops; + inode->i_fop = &omfs_file_operations; + inode->i_size = (loff_t) be64_to_cpu(oi->size); + } +} + +/**** super stuff ****/ + +static int omfs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct buffer_head *bh, *bh2; + struct omfs_super_block *omfs_sb; + struct omfs_root_block *omfs_rb; + struct inode *root; + + sb->s_flags |= MS_RDONLY; + sb->s_maxbytes = 0xffffffff; + + sb_set_blocksize(sb, 0x200); + + if (!(bh = sb_bread(sb, 0))) + goto out; + + omfs_sb = (struct omfs_super_block *)bh->b_data; + if (be32_to_cpu(omfs_sb->magic) != OMFS_MAGIC) { + if (!silent) + printk(KERN_ERR "omfs: Invalid superblock (%x)\n", + omfs_sb->magic); + goto out; + } + sb->s_magic = OMFS_MAGIC; + + sector_t start = logical_to_sector(be32_to_cpu(omfs_sb->root_block)); + if (!(bh2 = sb_bread(sb, start))) + goto out; + + omfs_rb = (struct omfs_root_block *)bh2->b_data; + printk(KERN_DEBUG "omfs: volume: %s\n", omfs_rb->name); + + sb->s_op = &omfs_sops; + root = iget(sb, be32_to_cpu(omfs_rb->root_dir)); + sb->s_root = d_alloc_root(root); + if (!sb->s_root) { + iput(root); + goto out; + } + + brelse(bh); + brelse(bh2); + return 0; + + out: + // fixup brelses + return -EINVAL; +} + +static struct super_block *omfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, omfs_fill_super); +} + +static struct file_system_type omfs_fs_type = { + .owner = THIS_MODULE, + .name = "omfs", + .get_sb = omfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, +}; + +static int __init init_omfs_fs(void) +{ + register_filesystem(&omfs_fs_type); + return 0; +} + +static void __exit exit_omfs_fs(void) +{ + unregister_filesystem(&omfs_fs_type); +} + +module_init(init_omfs_fs); +module_exit(exit_omfs_fs); diff -uprN -X dontdiff linux-2.6.12/fs/omfs/omfs.h linux/fs/omfs/omfs.h --- linux-2.6.12/fs/omfs/omfs.h 1969-12-31 19:00:00.000000000 -0500 +++ linux/fs/omfs/omfs.h 2005-09-02 08:05:59.000000000 -0400 @@ -0,0 +1,6 @@ +#ifndef _OMFS_H +#define _OMFS_H + +#define OMFS_MAGIC 0xC2993D87 + +#endif diff -uprN -X dontdiff linux-2.6.12/fs/partitions/Kconfig linux/fs/partitions/Kconfig --- linux-2.6.12/fs/partitions/Kconfig 2005-06-17 15:48:29.000000000 -0400 +++ linux/fs/partitions/Kconfig 2005-08-30 18:58:53.000000000 -0400 @@ -225,4 +225,11 @@ config EFI_PARTITION were partitioned using EFI GPT. Presently only useful on the IA-64 platform. +config KARMA_PARTITION + bool "Karma Partition support" + depends on PARTITION_ADVANCED + help + Say Y here if you would like to mount the Rio Karma MP3 player, + as it uses a proprietary partition table. + # define_bool CONFIG_ACORN_PARTITION_CUMANA y diff -uprN -X dontdiff linux-2.6.12/fs/partitions/Makefile linux/fs/partitions/Makefile --- linux-2.6.12/fs/partitions/Makefile 2005-06-17 15:48:29.000000000 -0400 +++ linux/fs/partitions/Makefile 2005-08-30 18:58:58.000000000 -0400 @@ -18,3 +18,4 @@ obj-$(CONFIG_ULTRIX_PARTITION) += ultrix obj-$(CONFIG_IBM_PARTITION) += ibm.o obj-$(CONFIG_EFI_PARTITION) += efi.o obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o +obj-$(CONFIG_KARMA_PARTITION) += karma.o diff -uprN -X dontdiff linux-2.6.12/fs/partitions/check.c linux/fs/partitions/check.c --- linux-2.6.12/fs/partitions/check.c 2005-06-17 15:48:29.000000000 -0400 +++ linux/fs/partitions/check.c 2005-08-30 18:59:38.000000000 -0400 @@ -35,6 +35,7 @@ #include "ibm.h" #include "ultrix.h" #include "efi.h" +#include "karma.h" #ifdef CONFIG_BLK_DEV_MD extern void md_autodetect_dev(dev_t dev); @@ -106,6 +107,9 @@ static int (*check_part[])(struct parsed #ifdef CONFIG_IBM_PARTITION ibm_partition, #endif +#ifdef CONFIG_KARMA_PARTITION + karma_partition, +#endif NULL }; diff -uprN -X dontdiff linux-2.6.12/fs/partitions/karma.c linux/fs/partitions/karma.c --- linux-2.6.12/fs/partitions/karma.c 1969-12-31 19:00:00.000000000 -0500 +++ linux/fs/partitions/karma.c 2005-08-30 18:58:35.000000000 -0400 @@ -0,0 +1,58 @@ +/* + * fs/partitions/karma.c + * Rio Karma partition info. + * + * Copyright (C) 2005 Bob Copeland, based on ofs.c + */ + +#include "check.h" +#include "karma.h" + +int karma_partition(struct parsed_partitions *state, struct block_device *bdev) +{ + int i; + int slot = 1; + Sector sect; + unsigned char *data; + struct disklabel { + u8 reserved[270]; + struct d_partition { + __le32 res; + u8 fstype; + u8 res2[3]; + __le32 offset; + __le32 size; + } partitions[2]; + u8 blank[208]; + __le16 magic; + } __attribute__((packed)) *label; + struct d_partition *p; + + data = read_dev_sector(bdev, 0, §); + if (!data) + return -1; + + label = (struct disklabel *) data; + if (le16_to_cpu(label->magic) != KARMA_LABEL_MAGIC) { + put_dev_sector(sect); + return 0; + } + + p = label->partitions; + for (i = 0 ; i < 2; i++, p++) { + if (slot == state->limit) + break; + + if (p->fstype == 0x4d && + le32_to_cpu(p->size)) { + put_partition(state, slot, + le32_to_cpu(p->offset), + le32_to_cpu(p->size)); + } + slot++; + } + printk("\n"); + put_dev_sector(sect); + return 1; +} + diff -uprN -X dontdiff linux-2.6.12/fs/partitions/karma.h linux/fs/partitions/karma.h --- linux-2.6.12/fs/partitions/karma.h 1969-12-31 19:00:00.000000000 -0500 +++ linux/fs/partitions/karma.h 2005-08-30 18:58:35.000000000 -0400 @@ -0,0 +1,8 @@ +/* + * fs/partitions/karma.h + */ + +#define KARMA_LABEL_MAGIC 0xAB56 + +int karma_partition(struct parsed_partitions *state, struct block_device *bdev); +