Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
46 theseven 1
/***************************************************************************
2
 *             __________               __   ___.
3
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7
 *                     \/            \/     \/    \/            \/
8
 * $Id: disk.c 26629 2010-06-06 13:28:13Z gevaerts $
9
 *
10
 * Copyright (C) 2002 by Björn Stenberg
11
 *
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.
16
 *
17
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18
 * KIND, either express or implied.
19
 *
20
 ****************************************************************************/
49 theseven 21
#include "global.h"
22
#include "thread.h"
46 theseven 23
#include <stdio.h>
24
#include "storage.h"
25
#include "debug.h"
26
#include "fat.h"
27
#ifdef HAVE_HOTSWAP
28
#include "dir.h" /* for release_dirs() */
29
#include "file.h" /* for release_files() */
30
#endif
31
#include "disk.h"
32
#include <string.h>
33
 
34
/* Partition table entry layout:
35
   -----------------------
36
   0: 0x80 - active
37
   1: starting head
38
   2: starting sector
39
   3: starting cylinder
40
   4: partition type
41
   5: end head
42
   6: end sector
43
   7: end cylinder
44
   8-11: starting sector (LBA)
45
   12-15: nr of sectors in partition
46
*/
47
 
48
#define BYTES2INT32(array,pos)                  \
49
    ((long)array[pos] | ((long)array[pos+1] << 8 ) |        \
50
     ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
51
 
52
static const unsigned char fat_partition_types[] = {
53
    0x0b, 0x1b, /* FAT32 + hidden variant */
54
    0x0c, 0x1c, /* FAT32 (LBA) + hidden variant */
55
#ifdef HAVE_FAT16SUPPORT
56
    0x04, 0x14, /* FAT16 <= 32MB + hidden variant */
57
    0x06, 0x16, /* FAT16  > 32MB + hidden variant */
58
    0x0e, 0x1e, /* FAT16 (LBA) + hidden variant */
59
#endif
60
};
61
 
62
static struct partinfo part[NUM_DRIVES*4]; /* space for 4 partitions on 2 drives */
63
static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */
64
static struct mutex disk_mutex;
65
 
66
struct partinfo* disk_init(IF_MD_NONVOID(int drive))
67
{
68
    int i;
69
    unsigned char sector[SECTOR_SIZE];
70
#ifdef HAVE_MULTIDRIVE
47 farthen 71
    /* For each drive, start at a different position, in order not to destroy
72
       the first entry of drive 0.
46 theseven 73
       That one is needed to calculate config sector position. */
74
    struct partinfo* pinfo = &part[drive*4];
75
    if ((size_t)drive >= sizeof(part)/sizeof(*part)/4)
76
        return NULL; /* out of space in table */
77
#else
78
    struct partinfo* pinfo = part;
79
    const int drive = 0;
80
    (void)drive;
81
#endif
82
 
83
    storage_read_sectors(IF_MD2(drive,) 0,1, sector);
84
    /* check that the boot sector is initialized */
85
    if ( (sector[510] != 0x55) ||
86
         (sector[511] != 0xaa)) {
50 theseven 87
        DEBUGF("Bad boot sector signature");
46 theseven 88
        return NULL;
89
    }
90
 
91
    /* parse partitions */
92
    for ( i=0; i<4; i++ ) {
93
        unsigned char* ptr = sector + 0x1be + 16*i;
94
        pinfo[i].type  = ptr[4];
95
        pinfo[i].start = BYTES2INT32(ptr, 8);
96
        pinfo[i].size  = BYTES2INT32(ptr, 12);
97
 
50 theseven 98
        DEBUGF("Part%d: Type %02x, start: %08lx size: %08lx",
46 theseven 99
               i,pinfo[i].type,pinfo[i].start,pinfo[i].size);
100
 
101
        /* extended? */
102
        if ( pinfo[i].type == 5 ) {
103
            /* not handled yet */
104
        }
105
    }
106
    return pinfo;
107
}
108
 
109
struct partinfo* disk_partinfo(int partition)
110
{
111
    return &part[partition];
112
}
113
 
114
void disk_init_subsystem(void)
115
{
116
   mutex_init(&disk_mutex);
117
}
118
 
119
int disk_mount_all(void)
120
{
121
    int mounted=0;
122
    int i;
123
 
124
#ifdef HAVE_HOTSWAP
125
    mutex_lock(&disk_mutex);
126
#endif
127
 
128
    fat_init(); /* reset all mounted partitions */
129
    for (i=0; i<NUM_VOLUMES; i++)
130
        vol_drive[i] = -1; /* mark all as unassigned */
131
 
132
#ifndef HAVE_MULTIDRIVE
133
    mounted = disk_mount(0);
134
#else
135
    for(i=0;i<NUM_DRIVES;i++)
136
    {
137
#ifdef HAVE_HOTSWAP
138
        if (storage_present(i))
139
#endif
140
            mounted += disk_mount(i); 
141
    }
142
#endif
143
 
144
#ifdef HAVE_HOTSWAP
145
    mutex_unlock(&disk_mutex);
146
#endif
147
    return mounted;
148
}
149
 
150
static int get_free_volume(void)
151
{
152
    int i;
153
    for (i=0; i<NUM_VOLUMES; i++)
154
    {
155
        if (vol_drive[i] == -1) /* unassigned? */
156
            return i;
157
    }
158
 
159
    return -1; /* none found */
160
}
161
 
162
int disk_mount(int drive)
163
{
164
    int i;
165
    int mounted = 0; /* reset partition-on-drive flag */
166
    int volume;
167
    struct partinfo* pinfo;
168
 
169
#ifdef HAVE_HOTSWAP
170
    mutex_lock(&disk_mutex);
171
#endif
172
 
173
    volume = get_free_volume();
174
    pinfo = disk_init(IF_MD(drive));
175
 
176
    if (pinfo == NULL)
177
    {
178
#ifdef HAVE_HOTSWAP
179
        mutex_unlock(&disk_mutex);
180
#endif
181
        return 0;
182
    }
183
    for (i = 0; volume != -1 && i<4 && mounted<NUM_VOLUMES_PER_DRIVE; i++)
184
    {
185
        if (memchr(fat_partition_types, pinfo[i].type,
186
                   sizeof(fat_partition_types)) == NULL)
187
            continue;  /* not an accepted partition type */
188
 
189
        if (!fat_mount(IF_MV2(volume,) IF_MD2(drive,) pinfo[i].start))
190
        {
191
            mounted++;
192
            vol_drive[volume] = drive; /* remember the drive for this volume */
193
            volume = get_free_volume(); /* prepare next entry */
194
        }
195
    }
196
 
197
    if (mounted == 0 && volume != -1) /* none of the 4 entries worked? */
198
    {   /* try "superfloppy" mode */
50 theseven 199
        DEBUGF("No partition found, trying to mount sector 0.");
46 theseven 200
        if (!fat_mount(IF_MV2(volume,) IF_MD2(drive,) 0))
201
        {
202
            mounted = 1;
203
            vol_drive[volume] = drive; /* remember the drive for this volume */
204
        }
205
    }
206
#ifdef HAVE_HOTSWAP
207
    mutex_unlock(&disk_mutex);
208
#endif
209
    return mounted;
210
}
211
 
212
#ifdef HAVE_HOTSWAP
213
int disk_unmount(int drive)
214
{
215
    int unmounted = 0;
216
    int i;
217
    mutex_lock(&disk_mutex);
218
    for (i=0; i<NUM_VOLUMES; i++)
219
    {
220
        if (vol_drive[i] == drive)
221
        {   /* force releasing resources */
222
            vol_drive[i] = -1; /* mark unused */
223
            unmounted++;
224
            release_files(i);
225
            release_dirs(i);
226
            fat_unmount(i, false);
227
        }
228
    }
229
    mutex_unlock(&disk_mutex);
230
 
231
    return unmounted;
232
}
233
#endif /* #ifdef HAVE_HOTSWAP */