ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/serial.cpp
Revision: 1.1
Committed: 2002-02-04T16:58:13Z (22 years, 9 months ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * serial.cpp - Serial device driver
3     *
4     * SheepShaver (C) 1997-2002 Marc Hellwig and Christian Bauer
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sysdeps.h"
22     #include "main.h"
23     #include "macos_util.h"
24     #include "serial.h"
25     #include "serial_defs.h"
26    
27     #define DEBUG 0
28     #include "debug.h"
29    
30    
31     // Global variables
32     SERDPort *the_serd_port[2];
33    
34     // Function pointers from imported functions
35     typedef int16 (*iocommandiscomplete_ptr)(uint32, int16);
36     static iocommandiscomplete_ptr IOCommandIsComplete;
37    
38    
39     /*
40     * Empty function (AIn/BIn Open/Close)
41     */
42    
43     int16 SerialNothing(uint32 pb, uint32 dce)
44     {
45     return noErr;
46     }
47    
48    
49     /*
50     * Driver Open() routine (output side only)
51     */
52    
53     int16 SerialOpen(uint32 pb, uint32 dce)
54     {
55     D(bug("SerialOpen pb %08lx, dce %08lx\n", pb, dce));
56    
57     // Get IOCommandIsComplete function
58     IOCommandIsComplete = (iocommandiscomplete_ptr)FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete");
59     D(bug("IOCommandIsComplete TVECT at %08lx\n", (uint32)IOCommandIsComplete));
60     if (IOCommandIsComplete == NULL) {
61     printf("FATAL: SerialOpen(): Can't find IOCommandIsComplete()\n");
62     return openErr;
63     }
64    
65     // Do nothing if port is already open
66     SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1];
67     if (the_port->is_open)
68     return noErr;
69    
70     // Init variables
71     the_port->read_pending = the_port->write_pending = false;
72     the_port->read_done = the_port->write_done = false;
73     the_port->cum_errors = 0;
74    
75     // Open port
76     int16 res = the_port->open(ReadMacInt16(0x1fc + ((-(int16)ReadMacInt16(dce + dCtlRefNum)-6) & 2)));
77     if (res)
78     return res;
79    
80     // Allocate Deferred Task structures
81     uint32 input_dt = the_port->input_dt = (uint32)the_port->dt_store;
82     uint32 output_dt = the_port->output_dt = (uint32)the_port->dt_store + SIZEOF_serdt;
83     D(bug(" input_dt %08lx, output_dt %08lx\n", input_dt, output_dt));
84    
85     WriteMacInt16(input_dt + qType, dtQType);
86     WriteMacInt32(input_dt + dtAddr, input_dt + serdtCode);
87     WriteMacInt32(input_dt + dtParam, input_dt + serdtResult);
88     // Deferred function for signalling that Prime is complete (pointer to mydtResult in a1)
89     WriteMacInt16(input_dt + serdtCode, 0x2019); // move.l (a1)+,d0 (result)
90     WriteMacInt16(input_dt + serdtCode + 2, 0x2251); // move.l (a1),a1 (dce)
91     WriteMacInt32(input_dt + serdtCode + 4, 0x207808fc); // move.l JIODone,a0
92     WriteMacInt16(input_dt + serdtCode + 8, 0x4ed0); // jmp (a0)
93    
94     WriteMacInt16(output_dt + qType, dtQType);
95     WriteMacInt32(output_dt + dtAddr, output_dt + serdtCode);
96     WriteMacInt32(output_dt + dtParam, output_dt + serdtResult);
97     // Deferred function for signalling that Prime is complete (pointer to mydtResult in a1)
98     WriteMacInt16(output_dt + serdtCode, 0x2019); // move.l (a1)+,d0 (result)
99     WriteMacInt16(output_dt + serdtCode + 2, 0x2251); // move.l (a1),a1 (dce)
100     WriteMacInt32(output_dt + serdtCode + 4, 0x207808fc); // move.l JIODone,a0
101     WriteMacInt16(output_dt + serdtCode + 8, 0x4ed0); // jmp (a0)
102    
103     the_port->is_open = true;
104     return noErr;
105     }
106    
107    
108     /*
109     * Driver Prime() routines
110     */
111    
112     int16 SerialPrimeIn(uint32 pb, uint32 dce)
113     {
114     D(bug("SerialPrimeIn pb %08lx, dce %08lx\n", pb, dce));
115     int16 res;
116    
117     SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1];
118     if (!the_port->is_open)
119     res = notOpenErr;
120     else {
121     if (the_port->read_pending) {
122     printf("FATAL: SerialPrimeIn() called while request is pending\n");
123     res = readErr;
124     } else
125     res = the_port->prime_in(pb, dce);
126     }
127    
128     if (ReadMacInt16(pb + ioTrap) & 0x0200)
129     if (res > 0) {
130     WriteMacInt16(pb + ioResult, 0);
131     return 0; // Command in progress
132     } else {
133     WriteMacInt16(pb + ioResult, res);
134     return res;
135     }
136     else
137     if (res > 0)
138     return 0; // Command in progress
139     else {
140     IOCommandIsComplete(pb, res);
141     return res;
142     }
143     }
144    
145     int16 SerialPrimeOut(uint32 pb, uint32 dce)
146     {
147     D(bug("SerialPrimeOut pb %08lx, dce %08lx\n", pb, dce));
148     int16 res;
149    
150     SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1];
151     if (!the_port->is_open)
152     res = notOpenErr;
153     else {
154     if (the_port->write_pending) {
155     printf("FATAL: SerialPrimeOut() called while request is pending\n");
156     res = writErr;
157     } else
158     res = the_port->prime_out(pb, dce);
159     }
160    
161     if (ReadMacInt16(pb + ioTrap) & 0x0200)
162     if (res > 0) {
163     WriteMacInt16(pb + ioResult, 0);
164     return 0; // Command in progress
165     } else {
166     WriteMacInt16(pb + ioResult, res);
167     return res;
168     }
169     else
170     if (res > 0)
171     return 0; // Command in progress
172     else {
173     IOCommandIsComplete(pb, res);
174     return res;
175     }
176     }
177    
178    
179     /*
180     * Driver Control() routine
181     */
182    
183     int16 SerialControl(uint32 pb, uint32 dce)
184     {
185     uint16 code = ReadMacInt16(pb + csCode);
186     D(bug("SerialControl %d, pb %08lx, dce %08lx\n", code, pb, dce));
187     int16 res;
188    
189     SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1];
190     if (!the_port->is_open)
191     res = notOpenErr;
192     else {
193     switch (code) {
194     case kSERDSetPollWrite:
195     res = noErr;
196     break;
197     default:
198     res = the_port->control(pb, dce, code);
199     break;
200     }
201     }
202    
203     if (code == 1)
204     return res;
205     else if (ReadMacInt16(pb + ioTrap) & 0x0200) {
206     WriteMacInt16(pb + ioResult, res);
207     return res;
208     } else {
209     IOCommandIsComplete(pb, res);
210     return res;
211     }
212     }
213    
214    
215     /*
216     * Driver Status() routine
217     */
218    
219     int16 SerialStatus(uint32 pb, uint32 dce)
220     {
221     uint16 code = ReadMacInt16(pb + csCode);
222     D(bug("SerialStatus %d, pb %08lx, dce %08lx\n", code, pb, dce));
223     int16 res;
224    
225     SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1];
226     if (!the_port->is_open)
227     res = notOpenErr;
228     else {
229     switch (code) {
230     case kSERDVersion:
231     WriteMacInt8(pb + csParam, 9); // Second-generation SerialDMA driver
232     res = noErr;
233     break;
234    
235     case 0x8000:
236     WriteMacInt8(pb + csParam, 9); // Second-generation SerialDMA driver
237     WriteMacInt16(pb + csParam + 4, 0x1997); // Date of serial driver
238     WriteMacInt16(pb + csParam + 6, 0x0616);
239     res = noErr;
240     break;
241    
242     default:
243     res = the_port->status(pb, dce, code);
244     break;
245     }
246     }
247    
248     if (ReadMacInt16(pb + ioTrap) & 0x0200) {
249     WriteMacInt16(pb + ioResult, res);
250     return res;
251     } else {
252     IOCommandIsComplete(pb, res);
253     return res;
254     }
255     }
256    
257    
258     /*
259     * Driver Close() routine
260     */
261    
262     int16 SerialClose(uint32 pb, uint32 dce)
263     {
264     D(bug("SerialClose pb %08lx, dce %08lx\n", pb, dce));
265    
266     // Close port if open
267     SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1];
268     if (the_port->is_open) {
269     int16 res = the_port->close();
270     the_port->is_open = false;
271     return res;
272     } else
273     return noErr;
274     }
275    
276    
277     /*
278     * Serial interrupt - Prime command completed, activate deferred tasks to call IODone
279     */
280    
281     void SerialInterrupt(void)
282     {
283     D(bug("SerialIRQ\n"));
284    
285     // Port 0
286     if (the_serd_port[0]->is_open) {
287     if (the_serd_port[0]->read_pending && the_serd_port[0]->read_done) {
288     Enqueue(the_serd_port[0]->input_dt, 0xd92);
289     the_serd_port[0]->read_pending = the_serd_port[0]->read_done = false;
290     }
291     if (the_serd_port[0]->write_pending && the_serd_port[0]->write_done) {
292     Enqueue(the_serd_port[0]->output_dt, 0xd92);
293     the_serd_port[0]->write_pending = the_serd_port[0]->write_done = false;
294     }
295     }
296    
297     // Port 1
298     if (the_serd_port[1]->is_open) {
299     if (the_serd_port[1]->read_pending && the_serd_port[1]->read_done) {
300     Enqueue(the_serd_port[1]->input_dt, 0xd92);
301     the_serd_port[1]->read_pending = the_serd_port[1]->read_done = false;
302     }
303     if (the_serd_port[1]->write_pending && the_serd_port[1]->write_done) {
304     Enqueue(the_serd_port[1]->output_dt, 0xd92);
305     the_serd_port[1]->write_pending = the_serd_port[1]->write_done = false;
306     }
307     }
308     }