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