Modules/FDDv2 - VFS interface almost done, Caching added
[tpg/acess2.git] / Modules / Storage / FDDv2 / main.c
1 /*
2  * Acess2 82077AA FDC
3  * - By John Hodge (thePowersGang)
4  *
5  * fdc.c
6  * - Core file
7  */
8 #include <acess.h>
9 #include <modules.h>
10 #include <fs_devfs.h>
11 #include "common.h"
12 #include <api_drv_disk.h>
13
14 // === CONSTANTS ===
15 #define FDD_VERSION     VER2(1,10)
16
17 // === STRUCTURES ===
18
19 // === PROTOTYPES ===
20  int    FDD_Install(char **Arguments);
21  int    FDD_RegisterFS(void);
22 // --- VFS
23 char    *FDD_ReadDir(tVFS_Node *Node, int pos);
24 tVFS_Node       *FDD_FindDir(tVFS_Node *dirNode, const char *Name);
25  int    FDD_IOCtl(tVFS_Node *Node, int ID, void *Data);
26 Uint64  FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);
27
28 // === GLOBALS ===
29 MODULE_DEFINE(0, FDD_VERSION, Storage_FDDv2, FDD_Install, NULL, "x86_ISADMA", NULL);
30 tDrive  gaFDD_Disks[MAX_DISKS];
31 tVFS_Node       gaFDD_DiskNodes[MAX_DISKS];
32 tDevFS_Driver   gFDD_DriverInfo = {
33         NULL, "fdd",
34         {
35         .Size = -1,
36         .NumACLs = 1,
37         .ACLs = &gVFS_ACL_EveryoneRX,
38         .Flags = VFS_FFLAG_DIRECTORY,
39         .ReadDir = FDD_ReadDir,
40         .FindDir = FDD_FindDir,
41         .IOCtl = FDD_IOCtl
42         }
43         };
44
45 // === CODE ===
46 int FDD_Install(char **Arguments)
47 {
48         // Query CMOS memory
49         {
50                 Uint8   data;
51                 outb(0x70, 0x10);
52                 data = inb(0x71);
53                 
54                 // NOTE: CMOS only reports 2 disks
55                 if( (data & 0xF0) == 0x40 )
56                         gaFDD_Disks[0].bValid = gaFDD_Disks[0].bInserted = 1;
57                 if( (data & 0x0F) == 0x04 )
58                         gaFDD_Disks[1].bValid = gaFDD_Disks[1].bInserted = 1;
59                 
60                 if( gaFDD_Disks[0].bValid == 0 && gaFDD_Disks[1].bValid == 0 )
61                         return MODULE_ERR_NOTNEEDED;
62         }
63         
64         // Initialise controller
65         FDD_SetupIO();
66
67         FDD_RegisterFS();
68
69         return 0;
70 }
71
72 /**
73  * \brief Register the FDD driver with DevFS
74  */
75 int FDD_RegisterFS(void)
76 {
77         gFDD_DriverInfo.RootNode.CTime = gFDD_DriverInfo.RootNode.MTime
78                 = gFDD_DriverInfo.RootNode.ATime = now();
79
80         for( int i = 0; i < MAX_DISKS; i ++ )
81         {
82                 if( !gaFDD_Disks[i].bValid )    continue ;
83         
84                 // Initialise Child Nodes
85                 gaFDD_DiskNodes[i].Inode = i;
86                 gaFDD_DiskNodes[i].Flags = 0;
87                 gaFDD_DiskNodes[i].NumACLs = 0;
88                 gaFDD_DiskNodes[i].Read = FDD_ReadFS;
89                 gaFDD_DiskNodes[i].Write = NULL;//FDD_WriteFS;
90                 gaFDD_DiskNodes[i].Size = 1440*1024;    // TODO: Non 1.44 disks
91         }
92         
93         DevFS_AddDevice( &gFDD_DriverInfo );
94 }
95
96 /**
97  * \brief Get the name of the \a Pos th item in the driver root
98  * \param Node  Root node (unused)
99  * \param Pos   Position
100  * \return Heap string of node name
101  */
102 char *FDD_ReadDir(tVFS_Node *Node, int Pos)
103 {
104         char    ret_tpl[2];
105         if(Pos < 0 || Pos > MAX_DISKS )
106                 return NULL;
107         if(gaFDD_Disks[Pos].bValid)
108                 return VFS_SKIP;
109         
110         ret_tpl[0] = '0' + Pos;
111         ret_tpl[1] = '\0';
112         return strdup(ret_tpl);
113 }
114
115 /**
116  * \brief Get a node by name
117  * \param Node  Root node (unused)
118  * \param Name  Drive name
119  * \return Pointer to node structure
120  */
121 tVFS_Node *FDD_FindDir(tVFS_Node *Node, const char *Name)
122 {
123          int    pos;
124         if( '0' > Name[0] || Name[0] > '9' )    return NULL;
125         if( Name[1] != '\0' )   return NULL;
126         
127         pos = Name[0] - '0';
128         
129         return &gaFDD_DiskNodes[pos];
130 }
131
132 static const char       *casIOCTLS[] = {DRV_IOCTLNAMES,DRV_DISK_IOCTLNAMES,NULL};
133 /**
134  * \brief Driver root IOCtl Handler
135  * \param Node  Root node (unused)
136  * \param ID    IOCtl ID
137  * \param Data  IOCtl specific data pointer
138  */
139 int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data)
140 {
141         switch(ID)
142         {
143         BASE_IOCTLS(DRV_TYPE_DISK, "FDDv2", FDD_VERSION, casIOCTLS);
144         
145         case DISK_IOCTL_GETBLOCKSIZE:   return 512;
146         
147         default:
148                 return -1;
149         }
150 }
151
152 /**
153  * \brief Read from a disk
154  * \param Node  Disk node
155  * \param Offset        Byte offset in disk
156  * \param Length        Number of bytes to read
157  * \param Buffer        Destination buffer
158  * \return Number of bytes read
159  */
160 Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
161 {
162          int    disk = Node->Inode;
163          int    track;
164
165         track = Offset / BYTES_PER_TRACK;
166         
167         if( Offset % BYTES_PER_TRACK )
168         {
169                 
170         }
171 }
172
173 /**
174  * \brief Read from a track
175  */
176 int FDD_int_ReadWriteWithinTrack(int Disk, int Track, int bWrite, size_t Offset, size_t Length, void *Buffer)
177 {
178         if( Offset > BYTES_PER_TRACK || Length > BYTES_PER_TRACK )
179                 return 1;
180         if( Offset + Length > BYTES_PER_TRACK )
181                 return 1;
182         
183         Mutex_Acquire( &gaFDD_Disks[Disk].Mutex );
184
185         // If the cache doesn't exist, create it
186         if( !gaFDD_Disks[Disk].TrackData[Track] )
187         {
188                 gaFDD_Disks[Disk].TrackData[Track] = malloc( BYTES_PER_TRACK );
189                 // Don't bother reading if this is a whole track write
190                 if( !(bWrite && Offset == 0 && Length == BYTES_PER_TRACK) )
191                 {
192                         FDD_int_ReadWriteTrack(Disk, Track, 0, gaFDD_Disks[Disk].TrackData[Track]);
193                 }
194         }
195         
196         // Read/Write
197         if( bWrite )
198         {
199                 // Write to cache then commit cache to disk
200                 char    *dest = gaFDD_Disks[Disk].TrackData[Track];
201                 memcpy( dest + Offset, Buffer, Length );
202                 FDD_int_ReadWriteTrack(Disk, Track, 1, gaFDD_Disks[Disk].TrackData[Track]);
203         }
204         else
205         {
206                 // Read from cache
207                 char    *src = gaFDD_Disks[Disk].TrackData[Track];
208                 memcpy(Buffer, src + Offset, Length);
209         }
210         
211         Mutex_Release( &gaFDD_Disks[Disk].Mutex );
212         
213         return 0;
214 }

UCC git Repository :: git.ucc.asn.au