1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Björn Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #include "dir.h" /* for release_dirs() */
27 #include "file.h" /* for release_files() */
31 /* Partition table entry layout:
32 -----------------------
41 8-11: starting sector (LBA)
42 12-15: nr of sectors in partition
45 #define BYTES2INT32(array,pos) \
46 ((long)array[pos] | ((long)array[pos+1] << 8 ) | \
47 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
49 static const unsigned char fat_partition_types
[] = {
50 0x0b, 0x1b, /* FAT32 + hidden variant */
51 0x0c, 0x1c, /* FAT32 (LBA) + hidden variant */
52 #ifdef HAVE_FAT16SUPPORT
53 0x04, 0x14, /* FAT16 <= 32MB + hidden variant */
54 0x06, 0x16, /* FAT16 > 32MB + hidden variant */
55 0x0e, 0x1e, /* FAT16 (LBA) + hidden variant */
59 static struct partinfo part
[NUM_DRIVES
*4]; /* space for 4 partitions on 2 drives */
60 static int vol_drive
[NUM_VOLUMES
]; /* mounted to which drive (-1 if none) */
61 static struct mutex disk_mutex
;
63 #ifdef MAX_LOG_SECTOR_SIZE
64 static int disk_sector_multiplier
[NUM_DRIVES
] = {[0 ... NUM_DRIVES
-1] = 1};
66 int disk_get_sector_multiplier(IF_MD_NONVOID(int drive
))
68 #ifdef HAVE_MULTIDRIVE
69 return disk_sector_multiplier
[drive
];
71 return disk_sector_multiplier
[0];
76 struct partinfo
* disk_init(IF_MD_NONVOID(int drive
))
79 #ifdef HAVE_MULTIDRIVE
80 /* For each drive, start at a different position, in order not to destroy
81 the first entry of drive 0.
82 That one is needed to calculate config sector position. */
83 struct partinfo
* pinfo
= &part
[drive
*4];
84 if ((size_t)drive
>= sizeof(part
)/sizeof(*part
)/4)
85 return NULL
; /* out of space in table */
87 struct partinfo
* pinfo
= part
;
92 unsigned char* sector
= fat_get_sector_buffer();
93 storage_read_sectors(IF_MD2(drive
,) 0,1, sector
);
94 /* check that the boot sector is initialized */
95 if ( (sector
[510] != 0x55) ||
96 (sector
[511] != 0xaa)) {
97 fat_release_sector_buffer();
98 DEBUGF("Bad boot sector signature\n");
102 /* parse partitions */
103 for ( i
=0; i
<4; i
++ ) {
104 unsigned char* ptr
= sector
+ 0x1be + 16*i
;
105 pinfo
[i
].type
= ptr
[4];
106 pinfo
[i
].start
= BYTES2INT32(ptr
, 8);
107 pinfo
[i
].size
= BYTES2INT32(ptr
, 12);
109 DEBUGF("Part%d: Type %02x, start: %08lx size: %08lx\n",
110 i
,pinfo
[i
].type
,pinfo
[i
].start
,pinfo
[i
].size
);
113 if ( pinfo
[i
].type
== 5 ) {
114 /* not handled yet */
117 fat_release_sector_buffer();
121 struct partinfo
* disk_partinfo(int partition
)
123 return &part
[partition
];
126 void disk_init_subsystem(void)
128 mutex_init(&disk_mutex
);
131 int disk_mount_all(void)
137 mutex_lock(&disk_mutex
);
140 fat_init(); /* reset all mounted partitions */
141 for (i
=0; i
<NUM_VOLUMES
; i
++)
142 vol_drive
[i
] = -1; /* mark all as unassigned */
144 #ifndef HAVE_MULTIDRIVE
145 mounted
= disk_mount(0);
147 for(i
=0;i
<NUM_DRIVES
;i
++)
150 if (storage_present(i
))
152 mounted
+= disk_mount(i
);
157 mutex_unlock(&disk_mutex
);
162 static int get_free_volume(void)
165 for (i
=0; i
<NUM_VOLUMES
; i
++)
167 if (vol_drive
[i
] == -1) /* unassigned? */
171 return -1; /* none found */
174 int disk_mount(int drive
)
176 int mounted
= 0; /* reset partition-on-drive flag */
178 struct partinfo
* pinfo
;
181 mutex_lock(&disk_mutex
);
184 volume
= get_free_volume();
185 pinfo
= disk_init(IF_MD(drive
));
186 #ifdef MAX_LOG_SECTOR_SIZE
187 disk_sector_multiplier
[drive
] = 1;
193 mutex_unlock(&disk_mutex
);
197 #if defined(TOSHIBA_GIGABEAT_S)
198 int i
= 1; /* For the Gigabeat S, we mount the second partition */
202 for (; volume
!= -1 && i
<4 && mounted
<NUM_VOLUMES_PER_DRIVE
; i
++)
204 if (memchr(fat_partition_types
, pinfo
[i
].type
,
205 sizeof(fat_partition_types
)) == NULL
)
206 continue; /* not an accepted partition type */
208 #ifdef MAX_LOG_SECTOR_SIZE
211 for (j
= 1; j
<= (MAX_LOG_SECTOR_SIZE
/SECTOR_SIZE
); j
<<= 1)
213 if (!fat_mount(IF_MV2(volume
,) IF_MD2(drive
,) pinfo
[i
].start
* j
))
218 vol_drive
[volume
] = drive
; /* remember the drive for this volume */
219 volume
= get_free_volume(); /* prepare next entry */
220 disk_sector_multiplier
[drive
] = j
;
225 if (!fat_mount(IF_MV2(volume
,) IF_MD2(drive
,) pinfo
[i
].start
))
228 vol_drive
[volume
] = drive
; /* remember the drive for this volume */
229 volume
= get_free_volume(); /* prepare next entry */
234 if (mounted
== 0 && volume
!= -1) /* none of the 4 entries worked? */
235 { /* try "superfloppy" mode */
236 DEBUGF("No partition found, trying to mount sector 0.\n");
237 if (!fat_mount(IF_MV2(volume
,) IF_MD2(drive
,) 0))
239 #ifdef MAX_LOG_SECTOR_SIZE
240 disk_sector_multiplier
[drive
] = fat_get_bytes_per_sector(IF_MV(volume
))/SECTOR_SIZE
;
243 vol_drive
[volume
] = drive
; /* remember the drive for this volume */
247 mutex_unlock(&disk_mutex
);
252 int disk_unmount(int drive
)
257 mutex_lock(&disk_mutex
);
259 for (i
=0; i
<NUM_VOLUMES
; i
++)
261 if (vol_drive
[i
] == drive
)
262 { /* force releasing resources */
263 vol_drive
[i
] = -1; /* mark unused */
267 fat_unmount(i
, false);
271 mutex_unlock(&disk_mutex
);
277 int disk_unmount_all(void)
279 #ifndef HAVE_MULTIDRIVE
280 return disk_unmount(0);
281 #else /* HAVE_MULTIDRIVE */
284 for (i
= 0; i
< NUM_DRIVES
; i
++)
287 if (storage_present(i
))
289 unmounted
+= disk_unmount(i
);
293 #endif /* HAVE_MULTIDRIVE */