Rev 2644 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2644 | clevermous | 1 | ; Callbacks which implement tmpdisk-specific disk functions for tmpdisk.asm. |
2 | |||
3 | ; The first argument of every callback is .userdata = userdata arg of AddDisk. |
||
4 | ; For tmpdisk, .userdata is the disk id, one of 0,...,max_num_disks-1. |
||
5 | |||
6 | DISK_STATUS_OK = 0 ; success |
||
7 | DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable |
||
8 | DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters |
||
9 | DISK_STATUS_NO_MEDIA = 2 ; no media present |
||
10 | DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data |
||
11 | |||
12 | ; The last function that is called for the given disk. The kernel calls it when |
||
13 | ; the kernel has finished all operations with the disk and it is safe to free |
||
14 | ; all driver-specific data identified by 'userdata'. |
||
15 | proc tmpdisk_close |
||
16 | virtual at esp+4 |
||
17 | .userdata dd ? |
||
18 | end virtual |
||
19 | ; Free the memory for disk and zero global variables. |
||
20 | mov edx, [.userdata] |
||
21 | mov [disk_sizes+edx*4], 0 |
||
22 | xor eax, eax |
||
23 | xchg eax, [disk_pointers+edx*4] |
||
5044 | clevermous | 24 | invoke KernelFree, eax |
2644 | clevermous | 25 | retn 4 |
26 | endp |
||
27 | |||
28 | struc DISKMEDIAINFO |
||
29 | { |
||
30 | .flags dd ? |
||
31 | DISK_MEDIA_READONLY = 1 |
||
32 | .sectorsize dd ? |
||
33 | .capacity dq ? |
||
34 | } |
||
35 | virtual at 0 |
||
36 | DISKMEDIAINFO DISKMEDIAINFO |
||
37 | end virtual |
||
38 | |||
39 | ; Returns information about disk media. |
||
40 | proc tmpdisk_querymedia |
||
41 | virtual at esp+4 |
||
42 | .userdata dd ? |
||
43 | .info dd ? |
||
44 | end virtual |
||
45 | ; Media is always present, sector size is always 512 bytes, |
||
46 | ; the size of disk in sectors is stored in a global variable. |
||
47 | mov edx, [.userdata] |
||
48 | mov ecx, [.info] |
||
49 | mov [ecx+DISKMEDIAINFO.flags], 0 |
||
50 | mov [ecx+DISKMEDIAINFO.sectorsize], 512 |
||
51 | mov eax, [disk_sizes+edx*4] |
||
52 | mov dword [ecx+DISKMEDIAINFO.capacity], eax |
||
53 | mov dword [ecx+DISKMEDIAINFO.capacity+4], 0 |
||
54 | ; Return zero as an indicator of success. |
||
55 | xor eax, eax |
||
56 | retn 8 |
||
57 | endp |
||
58 | |||
59 | ; Reads one or more sectors from the device. |
||
60 | tmpdisk_read: |
||
61 | xor edx, edx ; 0 = reading |
||
62 | jmp tmpdisk_readwrite |
||
63 | |||
64 | ; Writes one or more sectors to the device. |
||
65 | tmpdisk_write: |
||
66 | mov dl, 1 ; 1 = writing |
||
67 | ; Fall through to tmpdisk_readwrite. |
||
68 | |||
69 | ; Common procedure for reading and writing. |
||
70 | ; dl = 0 for reading, dl = 1 for writing. |
||
71 | ; Arguments of tmpdisk_read and tmpdisk_write are the same, |
||
72 | ; they continue to be stack arguments of this procedure. |
||
73 | proc tmpdisk_readwrite \ |
||
74 | userdata:dword, \ |
||
75 | buffer:dword, \ |
||
76 | start_sector:qword, \ |
||
77 | numsectors_ptr:dword |
||
78 | ; 1. Save used registers to be stdcall. |
||
79 | push esi edi |
||
80 | mov esi, [userdata] |
||
81 | mov edi, [numsectors_ptr] |
||
82 | ; 1. Determine number of sectors to be transferred. |
||
83 | ; This is either the requested number of sectors or number of sectors |
||
84 | ; up to the disk boundary, depending of what is less. |
||
85 | xor ecx, ecx |
||
86 | ; 1a. Test whether [start_sector] is less than [disk_sizes] for selected disk. |
||
87 | ; If so, calculate number of sectors between [start_sector] and [disk_sizes]. |
||
88 | ; Otherwise, the actual number of sectors is zero. |
||
89 | cmp dword [start_sector+4], ecx |
||
90 | jnz .got_number |
||
91 | mov eax, [disk_sizes+esi*4] |
||
92 | sub eax, dword [start_sector] |
||
93 | jbe .got_number |
||
94 | ; 1b. Get the requested number of sectors. |
||
95 | mov ecx, [edi] |
||
96 | ; 1c. If it is greater than number of sectors calculated in 1a, use the value |
||
97 | ; from 1a. |
||
98 | cmp ecx, eax |
||
99 | jb .got_number |
||
100 | mov ecx, eax |
||
101 | .got_number: |
||
102 | ; 2. Compare the actual number of sectors with requested. If they are |
||
103 | ; equal, set eax (it will be the returned value) to zero. Otherwise, |
||
104 | ; use DISK_STATUS_END_OF_MEDIA. |
||
105 | xor eax, eax |
||
106 | cmp ecx, [edi] |
||
107 | jz @f |
||
108 | mov al, DISK_STATUS_END_OF_MEDIA |
||
109 | @@: |
||
110 | ; 3. Store the actual number of sectors. |
||
111 | mov [edi], ecx |
||
112 | ; 4. Calculate source and destination addresses. |
||
113 | mov edi, dword [start_sector] |
||
114 | shl edi, 9 |
||
115 | add edi, [disk_pointers+esi*4] |
||
116 | mov esi, [buffer] |
||
117 | ; 5. Calculate number of dwords to be transferred. |
||
118 | shl ecx, 9-2 |
||
119 | ; 6. Now esi = [buffer], edi = pointer inside disk. |
||
120 | ; This is normal for write operations; |
||
121 | ; exchange esi and edi for read operations. |
||
122 | test dl, dl |
||
123 | jnz @f |
||
124 | xchg esi, edi |
||
125 | @@: |
||
126 | ; 7. Copy data. |
||
127 | rep movsd |
||
128 | ; 8. Restore used registers to be stdcall and return. |
||
129 | ; The value in eax was calculated in step 2. |
||
130 | pop edi esi |
||
131 | ret |
||
132 | endp |
||
133 | |||
134 | ; The kernel calls this function when initializing cache subsystem for |
||
135 | ; the media. This call allows the driver to adjust the cache size. |
||
136 | proc tmpdisk_adjust_cache_size |
||
137 | virtual at esp+4 |
||
138 | .userdata dd ? |
||
139 | .suggested_size dd ? |
||
140 | end virtual |
||
141 | ; Since tmpdisk does not need cache, just return 0. |
||
142 | xor eax, eax |
||
143 | retn 8 |
||
144 | endp |