ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/serial.cpp
Revision: 1.1
Committed: 1999-10-03T14:16:25Z (25 years, 2 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     * Basilisk II (C) 1997-1999 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     /*
22     * SEE ALSO
23     * Inside Macintosh: Devices, chapter 7 "Serial Driver"
24     * Technote HW 04: "Break/CTS Device Driver Event Structure"
25     * Technote 1018: "Understanding the SerialDMA Driver"
26     */
27    
28     #include <stdio.h>
29    
30     #include "sysdeps.h"
31     #include "cpu_emulation.h"
32     #include "main.h"
33     #include "macos_util.h"
34     #include "serial.h"
35     #include "serial_defs.h"
36    
37     #include "emul_op.h"
38    
39     #define DEBUG 0
40     #include "debug.h"
41    
42    
43     // Global variables
44     SERDPort *the_serd_port[2];
45    
46    
47     /*
48     * Driver Open() routine
49     */
50    
51     int16 SerialOpen(uint32 pb, uint32 dce, int port)
52     {
53     D(bug("SerialOpen port %d, pb %08lx, dce %08lx\n", port, pb, dce));
54    
55     if (port == 0 || port == 2) {
56    
57     // Do nothing for input side
58     return noErr;
59    
60     } else {
61    
62     // Do nothing if port is already open
63     SERDPort *the_port = the_serd_port[port >> 1];
64     if (the_port->is_open)
65     return noErr;
66    
67     // Init variables
68     the_port->read_pending = the_port->write_pending = false;
69     the_port->read_done = the_port->write_done = false;
70     the_port->cum_errors = 0;
71    
72     // Open port
73     int16 res = the_port->Open(ReadMacInt16(0x1fc + (port & 2)));
74     if (res)
75     return res;
76    
77     // Allocate Deferred Task structures
78     M68kRegisters r;
79     r.d[0] = SIZEOF_serdt * 2;
80     Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
81     if (r.a[0] == 0) {
82     the_port->Close();
83     return openErr;
84     }
85     uint32 input_dt = the_port->input_dt = r.a[0];
86     uint32 output_dt = the_port->output_dt = r.a[0] + SIZEOF_serdt;
87     D(bug(" input_dt %08lx, output_dt %08lx\n", input_dt, output_dt));
88    
89     WriteMacInt16(input_dt + qType, dtQType);
90     WriteMacInt32(input_dt + dtAddr, input_dt + serdtCode);
91     WriteMacInt32(input_dt + dtParam, input_dt + serdtResult);
92     // Deferred function for signalling that Prime is complete (pointer to mydtResult in a1)
93     WriteMacInt16(input_dt + serdtCode, 0x2019); // move.l (a1)+,d0 (result)
94     WriteMacInt16(input_dt + serdtCode + 2, 0x2251); // move.l (a1),a1 (dce)
95     WriteMacInt32(input_dt + serdtCode + 4, 0x207808fc); // move.l JIODone,a0
96     WriteMacInt16(input_dt + serdtCode + 8, 0x4ed0); // jmp (a0)
97    
98     WriteMacInt16(output_dt + qType, dtQType);
99     WriteMacInt32(output_dt + dtAddr, output_dt + serdtCode);
100     WriteMacInt32(output_dt + dtParam, output_dt + serdtResult);
101     // Deferred function for signalling that Prime is complete (pointer to mydtResult in a1)
102     WriteMacInt16(output_dt + serdtCode, 0x2019); // move.l (a1)+,d0 (result)
103     WriteMacInt16(output_dt + serdtCode + 2, 0x2251); // move.l (a1),a1 (dce)
104     WriteMacInt32(output_dt + serdtCode + 4, 0x207808fc); // move.l JIODone,a0
105     WriteMacInt16(output_dt + serdtCode + 8, 0x4ed0); // jmp (a0)
106    
107     the_port->is_open = true;
108     return noErr;
109     }
110     }
111    
112    
113     /*
114     * Driver Prime() routine
115     */
116    
117     int16 SerialPrime(uint32 pb, uint32 dce, int port)
118     {
119     D(bug("SerialPrime port %d, pb %08lx, dce %08lx\n", port, pb, dce));
120    
121     // Error if port is not open
122     SERDPort *the_port = the_serd_port[port >> 1];
123     if (!the_port->is_open)
124     return notOpenErr;
125    
126     if (port == 0 || port == 2) {
127     if (the_port->read_pending) {
128     printf("FATAL: SerialPrimeIn() called while request is pending\n");
129     return readErr;
130     } else
131     return the_port->PrimeIn(pb, dce);
132     } else {
133     if (the_port->write_pending) {
134     printf("FATAL: SerialPrimeOut() called while request is pending\n");
135     return readErr;
136     } else
137     return the_port->PrimeOut(pb, dce);
138     }
139     }
140    
141    
142     /*
143     * Driver Control() routine
144     */
145    
146     int16 SerialControl(uint32 pb, uint32 dce, int port)
147     {
148     uint16 code = ReadMacInt16(pb + csCode);
149     D(bug("SerialControl %d, port %d, pb %08lx, dce %08lx\n", code, port, pb, dce));
150    
151     // Error if port is not open
152     SERDPort *the_port = the_serd_port[port >> 1];
153     if (!the_port->is_open)
154     return notOpenErr;
155    
156     switch (code) {
157     case kSERDSetPollWrite:
158     return noErr;
159    
160     default:
161     return the_port->Control(pb, dce, code);
162     }
163     }
164    
165    
166     /*
167     * Driver Status() routine
168     */
169    
170     int16 SerialStatus(uint32 pb, uint32 dce, int port)
171     {
172     uint16 code = ReadMacInt16(pb + csCode);
173     D(bug("SerialStatus %d, port %d, pb %08lx, dce %08lx\n", code, port, pb, dce));
174    
175     // Error if port is not open
176     SERDPort *the_port = the_serd_port[port >> 1];
177     if (!the_port->is_open)
178     return notOpenErr;
179    
180     switch (code) {
181     case kSERDVersion:
182     WriteMacInt8(pb + csParam, 9); // Second-generation SerialDMA driver
183     return noErr;
184    
185     case 0x8000:
186     WriteMacInt8(pb + csParam, 9); // Second-generation SerialDMA driver
187     WriteMacInt16(pb + csParam + 4, 0x1997); // Date of serial driver
188     WriteMacInt16(pb + csParam + 6, 0x0616);
189     return noErr;
190    
191     default:
192     return the_port->Status(pb, dce, code);
193     }
194     }
195    
196    
197     /*
198     * Driver Close() routine
199     */
200    
201     int16 SerialClose(uint32 pb, uint32 dce, int port)
202     {
203     D(bug("SerialClose port %d, pb %08lx, dce %08lx\n", port, pb, dce));
204    
205     if (port == 0 || port == 2) {
206    
207     // Do nothing for input side
208     return noErr;
209    
210     } else {
211    
212     // Close port if open
213     SERDPort *the_port = the_serd_port[port >> 1];
214     if (the_port->is_open) {
215     int16 res = the_port->Close();
216     M68kRegisters r; // Free Deferred Task structures
217     r.a[0] = the_port->input_dt;
218     Execute68kTrap(0xa01f, &r); // DisposePtr()
219     the_port->is_open = false;
220     return res;
221     } else
222     return noErr;
223     }
224     }
225    
226    
227     /*
228     * Serial interrupt - Prime command completed, activate deferred tasks to call IODone
229     */
230    
231     static void serial_irq(SERDPort *p)
232     {
233     if (p->is_open) {
234     if (p->read_pending && p->read_done) {
235     Enqueue(p->input_dt, 0xd92);
236     p->read_pending = p->read_done = false;
237     }
238     if (p->write_pending && p->write_done) {
239     Enqueue(p->output_dt, 0xd92);
240     p->write_pending = p->write_done = false;
241     }
242     }
243     }
244    
245     void SerialInterrupt(void)
246     {
247     D(bug("SerialIRQ\n"));
248    
249     serial_irq(the_serd_port[0]);
250     serial_irq(the_serd_port[1]);
251     }