Previous 15994 Revisions Next

r7052 Sunday 17th January, 2010 at 12:26:12 UTC by Phill Harvey-Smith
Added scsibus implementation, which emulates the raw SCSI1 / SASI bus
Added preliminary hard disk support to the Nimbus driver
[src/mess]mess.mak
[src/mess/drivers]rmnimbus.c
[src/mess/includes]rmnimbus.h
[src/mess/machine]rmnimbus.c scsibus.c* scsibus.h*

src/mess/includes/rmnimbus.h
r7051r7052
6060WRITE16_HANDLER (nimbus_io_w);
6161
6262/* External int vectors for chained interupts */
63#define EXTERNAL_INT_FDC        0x80
63#define EXTERNAL_INT_DISK       0x80
6464#define EXTERNAL_INT_PC8031     0x8c
6565#define EXTERNAL_INT_Z80SIO     0x9C
6666#define EXTERNAL_INT_MSM5205    0x84
r7051r7052
8181WRITE8_DEVICE_HANDLER( sio_serial_transmit );
8282int sio_serial_receive( const device_config *device, int channel );
8383
84/* Floppy drive interface */
84/* Floppy/Fixed drive interface */
8585
8686#define FDC_TAG                 "wd2793"
8787
8888extern const wd17xx_interface nimbus_wd17xx_interface;
8989
90READ8_HANDLER( nimbus_fdc_r );
91WRITE8_HANDLER( nimbus_fdc_w );
90READ8_HANDLER( nimbus_disk_r );
91WRITE8_HANDLER( nimbus_disk_w );
9292
9393#define NO_DRIVE_SELECTED   0xFF
9494
95/* SASI harddisk interface */
96#define HARDDISK0_TAG           "harddisk0"
97#define SCSIBUS_TAG             "scsibus"
98
99void nimbus_scsi_linechange(const device_config *device, UINT8 line, UINT8 state);
100
101/* Masks for writes to port 0x400 */
102#define FDC_DRIVE0_MASK 0x01
103#define FDC_DRIVE1_MASK 0x02
104#define FDC_DRIVE2_MASK 0x04
105#define FDC_DRIVE3_MASK 0x08
106#define FDC_SIDE_MASK   0x10
107#define FDC_MOTOR_MASKO 0x20
108#define HDC_DRQ_MASK    0x40
109#define FDC_DRQ_MASK    0x80
110#define FDC_DRIVE_MASK  (FDC_DRIVE0_MASK | FDC_DRIVE1_MASK | FDC_DRIVE2_MASK | FDC_DRIVE3_MASK)
111
112#define FDC_SIDE()          ((nimbus_drives.reg400 & FDC_SIDE_MASK) >> 4)
113#define FDC_MOTOR()         ((nimbus_drives.reg400 & FDC_MOTOR_MASKO) >> 5)
114#define FDC_DRIVE()         (driveno(nimbus_drives.reg400 & FDC_DRIVE_MASK))
115#define HDC_DRQ_ENABLED()   ((nimbus_drives.reg400 & HDC_DRQ_MASK) ? 1 : 0)
116#define FDC_DRQ_ENABLED()   ((nimbus_drives.reg400 & FDC_DRQ_MASK) ? 1 : 0)
117
118/* Masks for port 0x410 read*/
119
120#define FDC_READY_MASK  0x01
121#define FDC_INDEX_MASK  0x02
122#define FDC_MOTOR_MASKI 0x04
123#define HDC_MSG_MASK    0x08
124#define HDC_BSY_MASK    0x10
125#define HDC_IO_MASK     0X20
126#define HDC_CD_MASK     0x40
127#define HDC_REQ_MASK    0x80
128
129#define FDC_BITS_410    (FDC_READY_MASK | FDC_INDEX_MASK | FDC_MOTOR_MASKI)
130#define HDC_BITS_410    (HDC_MSG_MASK | HDC_BSY_MASK | HDC_IO_MASK | HDC_CD_MASK | HDC_REQ_MASK)
131#define INV_BITS_410    (HDC_BSY_MASK | HDC_IO_MASK | HDC_CD_MASK | HDC_REQ_MASK)
132
133#define HDC_INT_TRIGGER (HDC_IO_MASK | HDC_CD_MASK | HDC_REQ_MASK)
134
135/* Masks for port 0x410 write*/
136
137#define HDC_RESET_MASK  0x01
138#define HDC_SEL_MASK    0x02
139#define HDC_IRQ_MASK    0x04
140#define HDC_IRQ_ENABLED()   ((nimbus_drives.reg410_out & HDC_IRQ_MASK) ? 1 : 0)
141
142
143#define SCSI_ID_NONE    0x80
144
145
95146/* 8031/8051 Peripheral controler */
96147
97148#define PC8031_RAMSIZE          0X004
r7051r7052
109160
110161/* IO unit */
111162
112#define FDC_INT_ENABLE          0x01
163#define DISK_INT_ENABLE         0x01
113164#define MSM5205_INT_ENABLE      0x04
114165#define PC8031_INT_ENABLE       0x10
115166
src/mess/machine/scsibus.c
r0r7052
1/*
2    SCSIBus.c
3     
4    Implementation of a raw SCSI/SASI bus for machines that don't use a SCSI
5    controler chip such as the RM Nimbus, which implements it as a bunch of 
6    74LS series chips.
7     
8*/
9 
10#include "machine/scsi.h"
11#include "machine/scsibus.h"
12 
13/* LOGLEVEL 0=no logging, 1=just commands and data, 2=everything ! */
14 
15#define LOGLEVEL         0   
16 
17#define LOG(level,...)      if(LOGLEVEL>=level) logerror(__VA_ARGS__)
18 
19typedef struct _scsibus_t scsibus_t;
20struct _scsibus_t
21{
22   SCSIInstance            *devices[8];
23   const SCSIBus_interface *interface;
24 
25    UINT8       linestate;
26   UINT8       last_id;
27    UINT8       command[CMD_BUF_SIZE];
28   UINT8       data[DATA_BUF_SIZE];
29    UINT8       cmd_idx;
30    UINT16      data_idx;
31    int         xfer_count;
32    int         bytes_left;
33   UINT8       phase;
34    UINT8       is_linked;
35     
36    emu_timer   *req_timer;
37    emu_timer   *ack_timer;
38     
39    UINT8       timer_flag;
40     
41    running_machine *machine;
42     
43    UINT8       initialised;
44};
45 
46static void set_scsi_line_now(const device_config *device, UINT8 line, UINT8 state);
47static void set_scsi_line_ack(const device_config *device, UINT8 state);
48static void scsi_in_line_changed(const device_config *device, UINT8 line, UINT8 state);
49static void scsi_out_line_change(const device_config *device, UINT8 line, UINT8 state);
50static void scsi_out_line_change_now(const device_config *device, UINT8 line, UINT8 state);
51static void scsi_out_line_req(const device_config *device, UINT8 state);
52static TIMER_CALLBACK(req_timer_callback);
53static TIMER_CALLBACK(ack_timer_callback);
54static void scsi_change_phase(const device_config *device, UINT8 newphase);
55 
56static const char *const linenames[] = 
57{
58    "select", "busy", "request", "acknoledge", "C/D", "I/O", "message", "reset"
59};
60 
61static const char *const phasenames[] = 
62{
63    "data out", "data in", "command", "status", "none", "none", "message out", "message in", "bus free","select"
64};
65 
66INLINE scsibus_t *get_token(const device_config *device)
67{
68   assert(device->type == SCSIBUS);
69   return (scsibus_t *) device->token;
70}
71 
72static void scsibus_read_data(scsibus_t   *bus)
73{   
74    if(bus->bytes_left >= DATA_BUF_SIZE)
75    {
76        SCSIReadData(bus->devices[bus->last_id], bus->data, DATA_BUF_SIZE);
77         
78        bus->bytes_left-=DATA_BUF_SIZE;
79        bus->data_idx=0;
80   }
81}
82 
83static void scsibus_write_data(scsibus_t   *bus)
84{
85    if(bus->bytes_left >= DATA_BUF_SIZE)
86    {
87        SCSIWriteData(bus->devices[bus->last_id], bus->data, DATA_BUF_SIZE);
88         
89        bus->bytes_left-=DATA_BUF_SIZE;
90        bus->data_idx=0;
91    }
92}
93 
94/* SCSI Bus read/write */
95 
96UINT8 scsi_data_r(const device_config *device)
97{
98    scsibus_t   *bus = get_token(device);
99    UINT8       result = 0;
100     
101    switch (bus->phase)
102    {
103        case SCSI_PHASE_DATAIN : 
104            result=bus->data[bus->data_idx++];
105             
106            // check to see if we have reached the end of the block buffer
107            // and that there is more data to read from the scsi disk
108            if((bus->data_idx==DATA_BUF_SIZE) && (bus->bytes_left>0))
109            {
110                scsibus_read_data(bus);
111            }
112            break;
113             
114        case SCSI_PHASE_STATUS : 
115            result=0;              // no errors for the time being !
116            bus->cmd_idx++;
117            break;
118             
119        case SCSI_PHASE_MESSAGE_IN : 
120            result=0;              // no errors for the time being !
121            bus->cmd_idx++;
122            break;           
123    }
124     
125    LOG(2,"scsi_data_r : phase=%s, data_idx=%d, cmd_idx=%d\n",phasenames[bus->phase],bus->data_idx,bus->cmd_idx);
126    return result;
127}
128 
129void scsi_data_w(const device_config *device, UINT8 data)
130{
131    scsibus_t   *bus = get_token(device);
132 
133    switch (bus->phase)
134    {
135        // Note this assumes we only have one initiator and therefore
136        // only one line active.
137        case SCSI_PHASE_BUS_FREE :
138            bus->last_id=driveno(data);
139            break;
140             
141        case SCSI_PHASE_COMMAND :
142            bus->command[bus->cmd_idx++]=data;
143            break;
144             
145        case SCSI_PHASE_DATAOUT :
146            bus->data[bus->data_idx++]=data;
147             
148            // If the data buffer is full, flush it to the SCSI disk
149            if(bus->data_idx == DATA_BUF_SIZE)
150                scsibus_write_data(bus);
151            break;         
152    }
153}
154 
155/* Get/Set lines */
156 
157UINT8 get_scsi_lines(const device_config *device)
158{
159    scsibus_t   *bus = get_token(device);
160     
161    return bus->linestate;
162}
163 
164UINT8 get_scsi_line(const device_config *device, UINT8 lineno)
165{
166    scsibus_t   *bus = get_token(device);
167    UINT8       result=0;
168     
169    switch (lineno)
170    {
171        case SCSI_LINE_SEL      : result=(bus->linestate & (1<<SCSI_LINE_SEL)) >> SCSI_LINE_SEL;
172        case SCSI_LINE_BSY      : result=(bus->linestate & (1<<SCSI_LINE_BSY)) >> SCSI_LINE_BSY;
173        case SCSI_LINE_REQ      : result=(bus->linestate & (1<<SCSI_LINE_REQ)) >> SCSI_LINE_REQ;
174        case SCSI_LINE_ACK      : result=(bus->linestate & (1<<SCSI_LINE_ACK)) >> SCSI_LINE_ACK;
175        case SCSI_LINE_CD       : result=(bus->linestate & (1<<SCSI_LINE_CD )) >> SCSI_LINE_CD;
176        case SCSI_LINE_IO       : result=(bus->linestate & (1<<SCSI_LINE_IO )) >> SCSI_LINE_IO;
177        case SCSI_LINE_MSG      : result=(bus->linestate & (1<<SCSI_LINE_MSG)) >> SCSI_LINE_MSG;
178        case SCSI_LINE_RESET    : result=(bus->linestate & (1<<SCSI_LINE_RESET)) >> SCSI_LINE_RESET;
179    }
180 
181    LOG(2,"get_scsi_line(%s)=%d\n",linenames[lineno],result);
182 
183    return result;
184}
185 
186void set_scsi_line(const device_config *device, UINT8 line, UINT8 state)
187{
188    scsibus_t   *bus = get_token(device);   
189    UINT8       changed;
190     
191    changed = ((bus->linestate & (1<<line)) != (state << line));
192     
193    LOG(2,"set_scsi_line(%s,%d), changed=%d, linestate=%02X\n",linenames[line],state,changed,bus->linestate);
194     
195    if(changed)
196    {
197        if (line==SCSI_LINE_ACK)
198            set_scsi_line_ack(device,state);
199        else
200            set_scsi_line_now(device,line,state);
201    }
202}
203 
204static void set_scsi_line_now(const device_config *device, UINT8 line, UINT8 state)
205{
206    scsibus_t   *bus = get_token(device);   
207 
208    if(state) 
209        bus->linestate |= (1<<line);
210    else
211        bus->linestate &= ~(1<<line);
212     
213    scsi_in_line_changed(device,line,state);
214}
215 
216void set_scsi_line_ack(const device_config *device, UINT8 state)
217{
218    scsibus_t   *bus = get_token(device);   
219     
220    timer_adjust_oneshot(bus->ack_timer,ATTOTIME_IN_NSEC(ACK_DELAY_NS),state);
221}
222 
223void dump_command_bytes(scsibus_t   *bus)
224{   
225    int byteno;
226     
227    logerror("sending command %0X to ScsiID %d\n",bus->command[0],bus->last_id);
228                         
229    for(byteno=0; byteno<bus->cmd_idx; byteno++)
230    {
231        logerror("%02X ",bus->command[byteno]);
232    }
233    logerror("\n\n");
234}
235 
236static void scsi_in_line_changed(const device_config *device, UINT8 line, UINT8 state)
237{
238    scsibus_t   *bus = get_token(device);   
239    int         newphase;
240 
241    // Reset aborts and returns to bus free
242    if((line==SCSI_LINE_RESET) && (state==0))
243    {   
244        scsi_change_phase(device,SCSI_PHASE_BUS_FREE);
245        bus->cmd_idx=0;
246        bus->data_idx=0;
247        bus->is_linked=0;
248     
249        return;
250    }
251 
252    switch (bus->phase)
253    {
254        case SCSI_PHASE_BUS_FREE :
255            if((line==SCSI_LINE_SEL) && (bus->devices[bus->last_id]!=NULL))
256            {
257                if(state==0)
258                    scsi_out_line_change(device,SCSI_LINE_BSY,0);
259                else
260                    scsi_change_phase(device,SCSI_PHASE_COMMAND);
261            }
262            break;
263             
264        case SCSI_PHASE_COMMAND :
265            if(line==SCSI_LINE_ACK)
266            {
267                if(state)
268                {
269                    // If the command is ready go and execute it
270                    if(bus->cmd_idx==get_scsi_cmd_len(bus->command[0]))
271                    {
272                        dump_command_bytes(bus);
273                        bus->is_linked=bus->command[bus->cmd_idx-1] & 0x01;
274                        SCSISetCommand(bus->devices[bus->last_id], bus->command, bus->cmd_idx);
275                        SCSIExecCommand(bus->devices[bus->last_id], &bus->xfer_count);
276                        SCSIGetPhase(bus->devices[bus->last_id], &newphase);
277                 
278                        scsi_change_phase(device,newphase);
279                 
280                        bus->bytes_left=bus->xfer_count;
281                        bus->data_idx=0;
282                         
283                        if (bus->phase == SCSI_PHASE_DATAIN)
284                            scsibus_read_data(bus);
285                    }
286                    else
287                        scsi_out_line_change(device,SCSI_LINE_REQ,0);
288                }
289                else
290                    scsi_out_line_change(device,SCSI_LINE_REQ,1);
291            }               
292            break;
293 
294        case SCSI_PHASE_DATAIN : 
295            if(line==SCSI_LINE_ACK) 
296            {
297                if(state)
298                {
299                    if((bus->data_idx == DATA_BUF_SIZE-1) && (bus->bytes_left == 0))
300                        scsi_change_phase(device,SCSI_PHASE_STATUS);
301                    else
302                        scsi_out_line_change(device,SCSI_LINE_REQ,0);
303                }
304                else
305                    scsi_out_line_change(device,SCSI_LINE_REQ,1);
306            }
307            break;
308             
309        case SCSI_PHASE_DATAOUT : 
310            if(line==SCSI_LINE_ACK) 
311            {
312                if(state)
313                {
314                    if((bus->data_idx == 0) && (bus->bytes_left == 0))
315                        scsi_change_phase(device,SCSI_PHASE_STATUS);
316                    else
317                        scsi_out_line_change(device,SCSI_LINE_REQ,0);
318                }
319                else
320                    scsi_out_line_change(device,SCSI_LINE_REQ,1);
321            }
322            break;
323             
324        case SCSI_PHASE_STATUS : 
325            if(line==SCSI_LINE_ACK) 
326            {
327                if(state)
328                {
329                    if(bus->cmd_idx > 0)
330                    {
331                        scsi_change_phase(device,SCSI_PHASE_MESSAGE_IN);
332                    }
333                    else
334                        scsi_out_line_change(device,SCSI_LINE_REQ,0);
335                }
336                else
337                    scsi_out_line_change(device,SCSI_LINE_REQ,1);
338            }
339            break;
340             
341        case SCSI_PHASE_MESSAGE_IN : 
342            if(line==SCSI_LINE_ACK) 
343            {
344                if(state)
345                {
346                    if(bus->cmd_idx > 0)
347                    {
348                        if(bus->is_linked)
349                            scsi_change_phase(device,SCSI_PHASE_COMMAND);
350                        else
351                            scsi_change_phase(device,SCSI_PHASE_BUS_FREE);
352                    }
353                    else
354                        scsi_out_line_change(device,SCSI_LINE_REQ,0);
355                }
356                else
357                    scsi_out_line_change(device,SCSI_LINE_REQ,1);
358            }
359            break;
360    }
361}
362 
363static void scsi_out_line_change(const device_config *device, UINT8 line, UINT8 state)
364{
365    if(line==SCSI_LINE_REQ)
366        scsi_out_line_req(device,state);
367    else
368        scsi_out_line_change_now(device,line,state);
369}
370 
371static void scsi_out_line_change_now(const device_config *device, UINT8 line, UINT8 state)
372{     
373    scsibus_t   *bus = get_token(device);   
374 
375    if(state)
376        bus->linestate |= (1<<line);
377    else
378        bus->linestate &= ~(1<<line);
379         
380    LOG(2,"scsi_out_line_change(%s,%d)\n",linenames[line],state);
381         
382    if(bus->interface->line_change_cb!=NULL)
383        bus->interface->line_change_cb(device,line,state);
384}
385 
386static void scsi_out_line_req(const device_config *device, UINT8 state)
387{
388    scsibus_t   *bus = get_token(device);   
389     
390    timer_adjust_oneshot(bus->req_timer,ATTOTIME_IN_NSEC(REQ_DELAY_NS),state);
391}
392 
393 
394static TIMER_CALLBACK(req_timer_callback)
395{
396    scsi_out_line_change_now(ptr, SCSI_LINE_REQ, param);
397}
398 
399static TIMER_CALLBACK(ack_timer_callback)
400{
401    set_scsi_line_now(ptr, SCSI_LINE_ACK, param);
402}
403 
404 
405UINT8 get_scsi_phase(const device_config *device)
406{
407    scsibus_t   *bus = get_token(device);   
408 
409    return bus->phase;
410}
411 
412 
413static void scsi_change_phase(const device_config *device, UINT8 newphase)
414{
415    scsibus_t   *bus = get_token(device);   
416 
417    LOG(1,"scsi_change_phase() from=%s, to=%s\n",phasenames[bus->phase],phasenames[newphase]);
418 
419    bus->phase=newphase;
420    bus->cmd_idx=0;
421    bus->data_idx=0;
422     
423    switch(bus->phase)
424    {
425        case SCSI_PHASE_BUS_FREE :
426            scsi_out_line_change(device,SCSI_LINE_CD,1);
427            scsi_out_line_change(device,SCSI_LINE_IO,1);
428            scsi_out_line_change(device,SCSI_LINE_MSG,1);
429            scsi_out_line_change(device,SCSI_LINE_REQ,1);
430            scsi_out_line_change(device,SCSI_LINE_BSY,1);
431            break;     
432 
433        case SCSI_PHASE_COMMAND :
434            scsi_out_line_change(device,SCSI_LINE_CD,0);
435            scsi_out_line_change(device,SCSI_LINE_IO,1);
436            scsi_out_line_change(device,SCSI_LINE_MSG,1);
437            scsi_out_line_change(device,SCSI_LINE_REQ,0);
438            break;     
439             
440        case SCSI_PHASE_DATAOUT :
441            scsi_out_line_change(device,SCSI_LINE_CD,1);
442            scsi_out_line_change(device,SCSI_LINE_IO,1);
443            scsi_out_line_change(device,SCSI_LINE_MSG,1);
444            scsi_out_line_change(device,SCSI_LINE_REQ,0);
445            break;     
446             
447        case SCSI_PHASE_DATAIN :
448            scsi_out_line_change(device,SCSI_LINE_CD,1);
449            scsi_out_line_change(device,SCSI_LINE_IO,0);
450            scsi_out_line_change(device,SCSI_LINE_MSG,1);
451            scsi_out_line_change(device,SCSI_LINE_REQ,0);
452            break;     
453             
454        case SCSI_PHASE_STATUS : 
455            scsi_out_line_change(device,SCSI_LINE_CD,0);
456            scsi_out_line_change(device,SCSI_LINE_IO,0);
457            scsi_out_line_change(device,SCSI_LINE_MSG,1);
458            scsi_out_line_change(device,SCSI_LINE_REQ,0);
459            break;     
460 
461        case SCSI_PHASE_MESSAGE_OUT : 
462            scsi_out_line_change(device,SCSI_LINE_CD,0);
463            scsi_out_line_change(device,SCSI_LINE_IO,1);
464            scsi_out_line_change(device,SCSI_LINE_MSG,0);
465            scsi_out_line_change(device,SCSI_LINE_REQ,0);           
466            break;     
467 
468        case SCSI_PHASE_MESSAGE_IN : 
469            scsi_out_line_change(device,SCSI_LINE_CD,0);
470            scsi_out_line_change(device,SCSI_LINE_IO,0);
471            scsi_out_line_change(device,SCSI_LINE_MSG,0);
472            scsi_out_line_change(device,SCSI_LINE_REQ,0);           
473            break;     
474    }
475}
476 
477UINT8 driveno(UINT8  drivesel)
478{
479    switch (drivesel)
480    {
481        case 0x01   : return 0;
482        case 0x02   : return 1;
483        case 0x04   : return 2;
484        case 0x08   : return 3;
485        case 0x10   : return 4;
486        case 0x20   : return 5;
487        case 0x40   : return 6;
488        case 0x80   : return 7;
489        default : return 0;
490    }
491}
492 
493// get the length of a SCSI command based on it's command byte type
494int get_scsi_cmd_len(int cbyte)
495{
496   int group;
497 
498   group = (cbyte>>5) & 7;
499 
500   if (group == 0) return 6;
501   if (group == 1 || group == 2) return 10;
502   if (group == 5) return 12;
503 
504   fatalerror("scsibus: Unknown SCSI command group %d\n", group);
505 
506   return 6;
507}
508 
509void init_scsibus(const device_config *device)
510{
511    scsibus_t               *bus = get_token(device);
512    const SCSIConfigTable   *scsidevs = bus->interface->scsidevs;
513   int                     devno;
514 
515    if(!bus->initialised)
516    {
517        // try to open the devices
518        for (devno = 0; devno < scsidevs->devs_present; devno++)
519        {
520            logerror("init_scsibus devno=%d \n",devno);
521            SCSIAllocInstance( device->machine, scsidevs->devices[devno].scsiClass, &bus->devices[scsidevs->devices[devno].scsiID], scsidevs->devices[devno].diskregion );
522        }
523         
524        bus->initialised=1;
525    }
526 }
527 
528static DEVICE_START( scsibus )
529{
530    scsibus_t               *bus = get_token(device);
531     
532   assert(device->static_config != NULL);
533    bus->interface = device->static_config;
534     
535   memset(bus->devices, 0, sizeof(bus->devices));
536     
537    // Flag not initialised
538    bus->initialised=0;
539     
540    // All lines start high - inactive
541    bus->linestate=0xFF; 
542 
543    // Start with bus free
544    bus->phase=SCSI_PHASE_BUS_FREE;
545     
546    // Setup req/ack timers 
547    bus->req_timer=timer_alloc(device->machine, req_timer_callback, (void *)device);
548    bus->ack_timer=timer_alloc(device->machine, ack_timer_callback, (void *)device);
549     
550    //timer_adjust_periodic(bus->reqack_timer, attotime_zero, 0, ATTOTIME_IN_MSEC(1));
551     
552    bus->machine=device->machine;
553}
554 
555static DEVICE_STOP( scsibus )
556{
557    scsibus_t               *bus = get_token(device);
558    int                     devno;
559     
560   for (devno = 0; devno < bus->interface->scsidevs->devs_present; devno++)
561   {
562        SCSIDeleteInstance( bus->devices[devno] );
563    }
564}
565 
566static DEVICE_RESET( scsibus )
567{
568}
569 
570DEVICE_GET_INFO( scsibus ) 
571{
572   switch ( state ) 
573    {
574      /* --- the following bits of info are returned as 64-bit signed integers --- */
575      case DEVINFO_INT_TOKEN_BYTES:         info->i = sizeof(scsibus_t);            break;
576      case DEVINFO_INT_INLINE_CONFIG_BYTES:   info->i = 0;                        break;
577      case DEVINFO_INT_CLASS:                info->i = DEVICE_CLASS_PERIPHERAL;         break;
578 
579      /* --- the following bits of info are returned as pointers to data or functions --- */
580      case DEVINFO_FCT_START:                info->start = DEVICE_START_NAME(scsibus);   break;
581      case DEVINFO_FCT_STOP:                info->stop  = DEVICE_STOP_NAME(scsibus);    break;
582      case DEVINFO_FCT_RESET:                info->reset = DEVICE_RESET_NAME(scsibus);   break;
583 
584      /* --- the following bits of info are returned as NULL-terminated strings --- */
585      case DEVINFO_STR_NAME:                strcpy(info->s, "SCSI bus");               break;
586      case DEVINFO_STR_FAMILY:             strcpy(info->s, "SCSI");                   break;
587      case DEVINFO_STR_VERSION:             strcpy(info->s, "1.0");                   break;
588      case DEVINFO_STR_SOURCE_FILE:         strcpy(info->s, __FILE__);                   break;
589      case DEVINFO_STR_CREDITS:             strcpy(info->s, "Copyright the MAME and MESS Teams"); break;
590   }
591}
src/mess/machine/scsibus.h
r0r7052
1/*
2    SCSIBus.h
3     
4    Implementation of a raw SCSI/SASI bus for machines that don't use a SCSI
5    controler chip such as the RM Nimbus, which implements it as a bunch of 
6    74LS series chips.
7     
8*/
9 
10#ifndef _SCSIBUS_H_
11#define _SCSIBUS_H_
12 
13#include "machine/scsidev.h"
14#include "devcb.h"
15#include "driver.h"
16 
17/***************************************************************************
18    MACROS
19***************************************************************************/
20 
21#define SCSIBUS      DEVICE_GET_INFO_NAME(scsibus)
22 
23#define MDRV_SCSIBUS_ADD(_tag, _intrf) \
24   MDRV_DEVICE_ADD(_tag, SCSIBUS, 0) \
25   MDRV_DEVICE_CONFIG(_intrf)
26     
27     
28/***************************************************************************
29    CONSTANTS
30***************************************************************************/
31 
32#define SCSI_LINE_SEL   0
33#define SCSI_LINE_BSY   1
34#define SCSI_LINE_REQ   2
35#define SCSI_LINE_ACK   3
36#define SCSI_LINE_CD    4
37#define SCSI_LINE_IO    5
38#define SCSI_LINE_MSG   6
39#define SCSI_LINE_RESET 7
40 
41// Perhaps thse should be in scsi.h ?
42#define SCSI_PHASE_BUS_FREE 8
43#define SCSI_PHASE_SELECT   9   
44 
45#define REQ_DELAY_NS    90
46#define ACK_DELAY_NS    90
47 
48#define CMD_BUF_SIZE    32
49#define DATA_BUF_SIZE   512
50 
51 
52/***************************************************************************
53    INTERFACE
54***************************************************************************/
55 
56typedef struct _SCSIBus_interface SCSIBus_interface;
57struct _SCSIBus_interface
58{
59    const SCSIConfigTable *scsidevs;      /* SCSI devices */
60    void (*line_change_cb)(const device_config *device, UINT8 line, UINT8 state);     
61};
62 
63/* SCSI Bus read/write */
64 
65UINT8 scsi_data_r(const device_config *device);
66void scsi_data_w(const device_config *device, UINT8 data);
67 
68/* Get/Set lines */
69 
70UINT8 get_scsi_lines(const device_config *device);
71UINT8 get_scsi_line(const device_config *device, UINT8 lineno);
72void set_scsi_line(const device_config *device, UINT8 line, UINT8 state);
73 
74/* Get current bus phase */
75 
76UINT8 get_scsi_phase(const device_config *device);
77 
78/* utility functions */
79 
80/* get a drive's number from it's select line */
81UINT8 driveno(UINT8  drivesel);
82 
83/* get the number of bytes for a scsi command */
84int get_scsi_cmd_len(int cbyte);
85 
86/* Initialisation at machine reset time */
87void init_scsibus(const device_config *device);
88 
89/* ----- device interface ----- */
90 
91#define SCSIBUS DEVICE_GET_INFO_NAME(scsibus)
92DEVICE_GET_INFO( scsibus );
93 
94#endif
src/mess/machine/rmnimbus.c
r7051r7052
2121#include "machine/pic8259.h"
2222#include "machine/pit8253.h"
2323#include "machine/msm8251.h"
24#include "machine/scsi.h"
25#include "machine/scsibus.h"
2426#include "machine/z80sio.h"
2527#include "sound/ay8910.h"
2628#include "sound/msm5205.h"
r7051r7052
3840#define LOG_INTERRUPTS_EXT  1
3941#define LOG_TIMER           0
4042#define LOG_OPTIMIZATION    0
41#define LOG_DMA             
43#define LOG_DMA             1
4244#define CPU_RESUME_TRIGGER   7123
4345#define LOG_KEYBOARD        0
4446#define LOG_SIO             0
45#define LOG_DISK            0
47#define LOG_DISK_FDD        0
48#define LOG_DISK_HDD        1
49#define LOG_DISK            1
4650#define LOG_PC8031          0
47#define LOG_PC8031_186      1
51#define LOG_PC8031_186     
4852#define LOG_PC8031_PORT     0
49#define LOG_IOU             1
50#define LOG_SOUND           1
53#define LOG_IOU             0
54#define LOG_SOUND           0
5155
5256/* 80186 internal stuff */
5357struct mem_state
r7051r7052
140144   {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
141145};
142146
143static struct _nimbus_fdc
147
148// Static data related to Floppy and SCSI hard disks
149static struct _nimbus_drives
144150{
145    UINT8 drq_enabled;
146    UINT8 irq_enabled;
147    UINT8 diskno;
148    UINT8 motor_on;
149} nimbus_fdc;
151    UINT8           reg400;
152    UINT8           reg410_in;
153    UINT8           reg410_out;
154    UINT8           reg418;
150155
156    UINT8           drq_ff;
157} nimbus_drives;
151158
159
160static const SCSIConfigTable SCSI_dev_table =
161{
162   1,                                      /* 1 SCSI device */
163   {
164      { SCSI_ID_0, HARDDISK0_TAG, SCSI_DEVICE_HARDDISK },
165   }
166};
167
152168/* 8031 Peripheral controler */
153169
154170UINT8 pcregs[PC8031_RAMSIZE];
r7051r7052
177193static void decode_dssi_f_plonk_char(const device_config *device,UINT16  ds, UINT16 si);
178194
179195static void fdc_reset(void);
196static void generate_disk_int(running_machine *machine);
197static void hdc_reset(running_machine *machine);
198static void hdc_ctrl_write(running_machine *machine, UINT8 data);
199static void hdc_post_rw(running_machine *machine);
200static void hdc_drq(running_machine *machine);
180201
181202static void keyboard_reset(void);
182203static TIMER_CALLBACK(keyscan_callback);
r7051r7052
318339            }
319340         }
320341
321        //logerror("Checking external ints\n");
322      /* check external interrupts */
342        /* check external interrupts */
323343      for (IntNo = 0; IntNo < 4; IntNo++)
324344         if ((i186.intr.ext[IntNo] & 0x0F) == Priority)
325345         {
r7051r7052
646666   int which = param;
647667   struct dma_state *d = &i186.dma[which];
648668
649   /* force an update and see if we're really done */
650   //stream_update(dma_stream, 0);
651
652669   /* complete the status update */
653670   d->control &= ~0x0002;
654671   d->source += d->count;
r7051r7052
700717      /* otherwise, set a timer */
701718      else
702719      {
703//          int count = d->count;
704
705         /* adjust for redline racer */
706            // int dacnum = (d->dest & 0x3f) / 2;
707
708720         if (LOG_DMA) logerror("Initiated DMA %d - count = %04X, source = %04X, dest = %04X\n", which, d->count, d->source, d->dest);
709721
710722         d->finished = 0;
711/*          timer_adjust_oneshot(d->finish_timer,
712         ATTOTIME_IN_HZ(dac[dacnum].frequency) * (double)count, which);*/
713723      }
714724   }
715725
r7051r7052
974984      case 0x68:
975985         if (LOG_PORTS) logerror("%05X:read 80186 DMA%d lower source address\n", cpu_get_pc(space->cpu), (offset - 0x60) / 8);
976986         which = (offset - 0x60) / 8;
977//          stream_update(dma_stream, 0);
978987         return i186.dma[which].source;
979988
980989      case 0x61:
981990      case 0x69:
982991         if (LOG_PORTS) logerror("%05X:read 80186 DMA%d upper source address\n", cpu_get_pc(space->cpu), (offset - 0x61) / 8);
983992         which = (offset - 0x61) / 8;
984//          stream_update(dma_stream, 0);
985993         return i186.dma[which].source >> 16;
986994
987995      case 0x62:
988996      case 0x6a:
989997         if (LOG_PORTS) logerror("%05X:read 80186 DMA%d lower dest address\n", cpu_get_pc(space->cpu), (offset - 0x62) / 8);
990998         which = (offset - 0x62) / 8;
991//          stream_update(dma_stream, 0);
992999         return i186.dma[which].dest;
9931000
9941001      case 0x63:
9951002      case 0x6b:
9961003         if (LOG_PORTS) logerror("%05X:read 80186 DMA%d upper dest address\n", cpu_get_pc(space->cpu), (offset - 0x63) / 8);
9971004         which = (offset - 0x63) / 8;
998//          stream_update(dma_stream, 0);
9991005         return i186.dma[which].dest >> 16;
10001006
10011007      case 0x64:
10021008      case 0x6c:
10031009         if (LOG_PORTS) logerror("%05X:read 80186 DMA%d transfer count\n", cpu_get_pc(space->cpu), (offset - 0x64) / 8);
10041010         which = (offset - 0x64) / 8;
1005//          stream_update(dma_stream, 0);
10061011         return i186.dma[which].count;
10071012
10081013      case 0x65:
10091014      case 0x6d:
10101015         if (LOG_PORTS) logerror("%05X:read 80186 DMA%d control\n", cpu_get_pc(space->cpu), (offset - 0x65) / 8);
10111016         which = (offset - 0x65) / 8;
1012//          stream_update(dma_stream, 0);
10131017         return i186.dma[which].control;
10141018
10151019      default:
r7051r7052
11711175         if (LOG_PORTS) logerror("%05X:80186 middle P chip select = %04X\n", cpu_get_pc(space->cpu), data16);
11721176         i186.mem.middle_size = data16 | 0x8038;
11731177
1174         temp = (i186.mem.peripheral & 0xffc0) << 4;
1175         if (i186.mem.middle_size & 0x0040)
1176         {
1177//              install_mem_read_handler(2, temp, temp + 0x2ff, peripheral_r);
1178//              install_mem_write_handler(2, temp, temp + 0x2ff, peripheral_w);
1179         }
1180         else
1181         {
1182            temp &= 0xffff;
1183//              install_port_read_handler(2, temp, temp + 0x2ff, peripheral_r);
1184//              install_port_write_handler(2, temp, temp + 0x2ff, peripheral_w);
1185         }
1186
11871178         /* we need to do this at a time when the I86 context is swapped in */
11881179         /* this register is generally set once at startup and never again, so it's a good */
11891180         /* time to set it up */
r7051r7052
11941185      case 0x68:
11951186         if (LOG_PORTS) logerror("%05X:80186 DMA%d lower source address = %04X\n", cpu_get_pc(space->cpu), (offset - 0x60) / 8, data16);
11961187         which = (offset - 0x60) / 8;
1197//          stream_update(dma_stream, 0);
11981188         i186.dma[which].source = (i186.dma[which].source & ~0x0ffff) | (data16 & 0x0ffff);
11991189         break;
12001190
r7051r7052
12021192      case 0x69:
12031193         if (LOG_PORTS) logerror("%05X:80186 DMA%d upper source address = %04X\n", cpu_get_pc(space->cpu), (offset - 0x61) / 8, data16);
12041194         which = (offset - 0x61) / 8;
1205//          stream_update(dma_stream, 0);
12061195         i186.dma[which].source = (i186.dma[which].source & ~0xf0000) | ((data16 << 16) & 0xf0000);
12071196         break;
12081197
r7051r7052
12101199      case 0x6a:
12111200         if (LOG_PORTS) logerror("%05X:80186 DMA%d lower dest address = %04X\n", cpu_get_pc(space->cpu), (offset - 0x62) / 8, data16);
12121201         which = (offset - 0x62) / 8;
1213//          stream_update(dma_stream, 0);
12141202         i186.dma[which].dest = (i186.dma[which].dest & ~0x0ffff) | (data16 & 0x0ffff);
12151203         break;
12161204
r7051r7052
12181206      case 0x6b:
12191207         if (LOG_PORTS) logerror("%05X:80186 DMA%d upper dest address = %04X\n", cpu_get_pc(space->cpu), (offset - 0x63) / 8, data16);
12201208         which = (offset - 0x63) / 8;
1221//          stream_update(dma_stream, 0);
12221209         i186.dma[which].dest = (i186.dma[which].dest & ~0xf0000) | ((data16 << 16) & 0xf0000);
12231210         break;
12241211
r7051r7052
12261213      case 0x6c:
12271214         if (LOG_PORTS) logerror("%05X:80186 DMA%d transfer count = %04X\n", cpu_get_pc(space->cpu), (offset - 0x64) / 8, data16);
12281215         which = (offset - 0x64) / 8;
1229//          stream_update(dma_stream, 0);
12301216         i186.dma[which].count = data16;
12311217         break;
12321218
r7051r7052
12341220      case 0x6d:
12351221         if (LOG_PORTS) logerror("%05X:80186 DMA%d control = %04X\n", cpu_get_pc(space->cpu), (offset - 0x65) / 8, data16);
12361222         which = (offset - 0x65) / 8;
1237//          stream_update(dma_stream, 0);
12381223         update_dma_control(space->machine, which, data16);
12391224         break;
12401225
r7051r7052
12561241            memory_install_read16_handler(cputag_get_address_space(space->machine, MAINCPU_TAG, ADDRESS_SPACE_IO), temp, temp + 0xff, 0, 0, i186_internal_port_r);
12571242            memory_install_write16_handler(cputag_get_address_space(space->machine, MAINCPU_TAG, ADDRESS_SPACE_IO), temp, temp + 0xff, 0, 0, i186_internal_port_w);
12581243         }
1259/*          popmessage("Sound CPU reset");*/
12601244         break;
12611245
12621246      default:
r7051r7052
12711255   nimbus_cpu_reset(machine);
12721256    iou_reset();
12731257    fdc_reset();
1258    hdc_reset(machine);
12741259    keyboard_reset();
12751260    pc8031_reset();
12761261    sound_reset(machine);
r7051r7052
19731958
19741959static void fdc_reset(void)
19751960{
1976    nimbus_fdc.irq_enabled=0;
1977    nimbus_fdc.drq_enabled=0;
1978    nimbus_fdc.diskno=0;
1979    nimbus_fdc.motor_on=0;
1961    nimbus_drives.reg400=0;
1962    nimbus_drives.reg410_in=0;
1963    nimbus_drives.reg410_out=0;
19801964}
19811965
1982static WRITE_LINE_DEVICE_HANDLER( nimbus_fdc_intrq_w )
1966static void generate_disk_int(running_machine *machine)
19831967{
19841968    if(LOG_DISK)
1985        logerror("nimbus_fdc_intrq_w(%d)\n", state);
1969        logerror("nimbus_drives_intrq\n");
19861970
1987    if(state && (iou_reg092 & FDC_INT_ENABLE))
1971    if(iou_reg092 & DISK_INT_ENABLE)
19881972    {
1989        external_int(device->machine,0,EXTERNAL_INT_FDC);
1973        external_int(machine,0,EXTERNAL_INT_DISK);
19901974    }
19911975}
19921976
1977static WRITE_LINE_DEVICE_HANDLER( nimbus_fdc_intrq_w )
1978{
1979    if (state)
1980        generate_disk_int(device->machine);
1981}
1982
19931983static WRITE_LINE_DEVICE_HANDLER( nimbus_fdc_drq_w )
19941984{
19951985
19961986    if(LOG_DISK)
1997        logerror("nimbus_fdc_drq_w(%d)\n", state);
1987        logerror("nimbus_drives_drq_w(%d)\n", state);
19981988   
1999    if(state && nimbus_fdc.drq_enabled)
1989    if(state && FDC_DRQ_ENABLED())
20001990        drq_callback(device->machine,1);
20011991}
20021992
2003READ8_HANDLER( nimbus_fdc_r )
1993/*
1994    0x410 read bits
1995 
1996    0   Ready from floppy
1997    1   Index pulse from floppy
1998    2   Motor on from floppy
1999    3   MSG from HDD
2000    4   !BSY from HDD
2001    5   !I/O from HDD
2002    6   !C/D
2003    7   !REQ from HDD
2004*/
2005
2006READ8_HANDLER( nimbus_disk_r )
20042007{
20052008      int result = 0;
20062009   const device_config *fdc = devtag_get_device(space->machine, FDC_TAG);
2010    const device_config *hdc = devtag_get_device(space->machine, SCSIBUS_TAG);
2011   
20072012    int pc=cpu_get_pc(space->cpu);
2008    const device_config *drive = devtag_get_device(space->machine, nimbus_wd17xx_interface.floppy_drive_tags[nimbus_fdc.diskno]);
2013    const device_config *drive = devtag_get_device(space->machine, nimbus_wd17xx_interface.floppy_drive_tags[FDC_DRIVE()]);
20092014   
20102015    switch(offset*2)
20112016   {
20122017      case 0x08 :
20132018         result = wd17xx_status_r(fdc, 0);
2014         if (LOG_DISK) logerror("Disk status=%2.2X\n",result);
2019         if (LOG_DISK_FDD) logerror("Disk status=%2.2X\n",result);
20152020         break;
20162021      case 0x0A :
20172022         result = wd17xx_track_r(fdc, 0);
r7051r7052
20232028         result = wd17xx_data_r(fdc, 0);
20242029         break;
20252030        case 0x10 :
2026            result = (nimbus_fdc.motor_on                                    ? 0x04 : 0x00) |
2027                     (floppy_drive_get_flag_state(drive, FLOPPY_DRIVE_INDEX) ? 0x00 : 0x02) |
2028                     (floppy_drive_get_flag_state(drive, FLOPPY_DRIVE_READY) ? 0x01 : 0x00);     
2031            nimbus_drives.reg410_in &= ~FDC_BITS_410;
2032            nimbus_drives.reg410_in |= (FDC_MOTOR() ? FDC_MOTOR_MASKI : 0x00);
2033            nimbus_drives.reg410_in |= (floppy_drive_get_flag_state(drive, FLOPPY_DRIVE_INDEX) ? 0x00 : FDC_INDEX_MASK);
2034            nimbus_drives.reg410_in |= (floppy_drive_get_flag_state(drive, FLOPPY_DRIVE_READY) ? FDC_READY_MASK : 0x00);     
2035           
2036            // Flip inverted bits
2037            result=nimbus_drives.reg410_in ^ INV_BITS_410;
20292038            break;
2039        case 0x18 :
2040            result = scsi_data_r(hdc);
2041            hdc_post_rw(space->machine);
20302042      default:
20312043         break;
20322044   }
20332045
2034    if(LOG_DISK)
2046    if(LOG_DISK_FDD)
20352047        logerror("Nimbus FDCR at pc=%08X from %04X data=%02X\n",pc,(offset*2)+0x400,result);
20362048
2049    if((LOG_DISK_HDD) && ((offset*2)>=0x10))
2050        logerror("Nimbus HDCR at pc=%08X from %04X data=%02X\n",pc,(offset*2)+0x400,result);
2051   
2052
20372053   return result;
20382054}
20392055
2040WRITE8_HANDLER( nimbus_fdc_w )
2056/*
2057    0x400 write bits
2058   
2059    0   drive 0 select
2060    1   drive 1 select
2061    2   drive 2 select
2062    3   drive 3 select
2063    4   side select
2064    5   fdc motor on
2065    6   hdc drq enabled
2066    7   fdc drq enabled
2067   
2068    0x410 write bits
2069   
2070    0   SCSI reset
2071    1   SCSI SEL
2072    2   SCSI IRQ Enable
2073*/
2074
2075WRITE8_HANDLER( nimbus_disk_w )
20412076{
20422077   const device_config *fdc = devtag_get_device(space->machine, FDC_TAG);
2043    int pc=cpu_get_pc(space->cpu);
2078    const device_config *hdc = devtag_get_device(space->machine, SCSIBUS_TAG);
2079    int                 pc=cpu_get_pc(space->cpu);
2080    UINT8               reg400_old = nimbus_drives.reg400;
2081   
2082    if(LOG_DISK_FDD)
2083        logerror("Nimbus FDCW at %05X write of %02X to %04X\n",pc,data,(offset*2)+0x400);
20442084
2045    if(LOG_DISK)
2046        logerror("Nimbus FDCW at %08X write of %02X to %04X\n",pc,data,(offset*2)+0x400);
2085    if((LOG_DISK_HDD) && (((offset*2)>=0x10) || (offset==0)))
2086        logerror("Nimbus HDCW at %05X write of %02X to %04X\n",pc,data,(offset*2)+0x400);
20472087
20482088    switch(offset*2)
20492089   {
20502090        case 0x00 :
2051            switch (data & 0x0F)
2052            {
2053                case 0x01 : nimbus_fdc.diskno=0; break;
2054                case 0x02 : nimbus_fdc.diskno=1; break;
2055                case 0x04 : nimbus_fdc.diskno=2; break;
2056                case 0x08 : nimbus_fdc.diskno=3; break; 
2057                //default : nimbus_fdc.diskno=NO_DRIVE_SELECTED; break; // no drive selected
2058            }
2059            if (nimbus_fdc.diskno!=NO_DRIVE_SELECTED)
2060            {
2061                wd17xx_set_drive(fdc, nimbus_fdc.diskno);
2062                wd17xx_set_side(fdc, (data & 0x10) ? 1 : 0);
2063            }
2064            nimbus_fdc.motor_on=(data & 0x20);
2065            nimbus_fdc.drq_enabled=(data & 0x80);
2066            nimbus_fdc.irq_enabled=1;
2091            nimbus_drives.reg400=data;
2092         
2093            wd17xx_set_drive(fdc,FDC_DRIVE());
2094            wd17xx_set_side(fdc, FDC_SIDE());
20672095           
20682096            // Nimbus FDC is hard wired for double density
20692097            wd17xx_set_density(fdc, DEN_MFM_LO);
2070         break;
2098
2099            //logerror("nimbus_drives.reg400=%02X, data=%02X, drq_ff=%d\n",reg400_old,data,nimbus_drives.drq_ff);
2100
2101            // if we enable hdc drq with a pending condition, act on it
2102            if((data & HDC_DRQ_MASK) && (~reg400_old & HDC_DRQ_MASK))
2103                hdc_drq(space->machine);
2104
2105            break;
20712106      case 0x08 :
20722107         wd17xx_command_w(fdc, 0, data);
20732108         break;
r7051r7052
20802115      case 0x0E :
20812116         wd17xx_data_w(fdc, 0, data);
20822117         break;
2118        case 0x10 :
2119            hdc_ctrl_write(space->machine,data);
2120            break;
2121   
2122        case 0x18 :
2123            scsi_data_w(hdc, data);
2124            hdc_post_rw(space->machine);
2125            break;
20832126   }
20842127}
20852128
2129static void hdc_reset(running_machine *machine)
2130{
2131    const device_config *hdc = devtag_get_device(machine, SCSIBUS_TAG);
2132
2133    init_scsibus(hdc);
2134
2135    nimbus_drives.reg410_in=0;
2136    nimbus_drives.reg410_in |= (get_scsi_line(hdc,SCSI_LINE_REQ) ? HDC_REQ_MASK : 0);
2137    nimbus_drives.reg410_in |= (get_scsi_line(hdc,SCSI_LINE_CD)  ? HDC_CD_MASK  : 0);
2138    nimbus_drives.reg410_in |= (get_scsi_line(hdc,SCSI_LINE_IO)  ? HDC_IO_MASK  : 0);
2139    nimbus_drives.reg410_in |= (get_scsi_line(hdc,SCSI_LINE_BSY) ? HDC_BSY_MASK : 0);
2140    nimbus_drives.reg410_in |= (get_scsi_line(hdc,SCSI_LINE_MSG) ? HDC_MSG_MASK : 0);
2141   
2142    nimbus_drives.drq_ff=0;
2143}
2144
2145static void hdc_ctrl_write(running_machine *machine, UINT8 data)
2146{
2147   const device_config *hdc = devtag_get_device(machine, SCSIBUS_TAG);
2148   
2149    // If we enable the HDC interupt, and an interrupt is pending, go deal with it.
2150    if(((data & HDC_IRQ_MASK) && (~nimbus_drives.reg410_out & HDC_IRQ_MASK)) &&
2151       ((~nimbus_drives.reg410_in & HDC_INT_TRIGGER)==HDC_INT_TRIGGER))
2152        generate_disk_int(machine);
2153           
2154    nimbus_drives.reg410_out=data;
2155
2156    set_scsi_line(hdc, SCSI_LINE_RESET, (data & HDC_RESET_MASK) ? 0 : 1);
2157    set_scsi_line(hdc, SCSI_LINE_SEL, (data & HDC_SEL_MASK) ? 0 : 1);
2158}
2159
2160static void hdc_post_rw(running_machine *machine)
2161{
2162    const device_config *hdc = devtag_get_device(machine, SCSIBUS_TAG);
2163   
2164    if((nimbus_drives.reg410_in & HDC_REQ_MASK)==0)
2165        set_scsi_line(hdc,SCSI_LINE_ACK,0);
2166}
2167
2168static void hdc_drq(running_machine *machine)
2169{
2170    if(HDC_DRQ_ENABLED() && nimbus_drives.drq_ff)
2171    {
2172        drq_callback(machine,1);
2173        nimbus_drives.drq_ff=0;
2174    }
2175}
2176
2177void nimbus_scsi_linechange(const device_config *device, UINT8 line, UINT8 state)
2178{
2179    UINT8   mask = 0;
2180   
2181    switch (line)
2182    {
2183        case SCSI_LINE_REQ   : mask=HDC_REQ_MASK; break;
2184        case SCSI_LINE_CD    : mask=HDC_CD_MASK; break;
2185        case SCSI_LINE_IO    : mask=HDC_IO_MASK; break;
2186        case SCSI_LINE_BSY   : mask=HDC_BSY_MASK; break;
2187        case SCSI_LINE_MSG   : mask=HDC_MSG_MASK; break;
2188    }
2189   
2190    if(state)
2191        nimbus_drives.reg410_in|=mask;
2192    else
2193        nimbus_drives.reg410_in&=~mask;
2194
2195   
2196    if(line==SCSI_LINE_REQ)
2197    {
2198    //logerror("nimbus_scsi_linechange(%02X,%d), ~nimbus_drives.reg410_in=%02X, mask=%02X, (~reg410 & mask)=%02X, int_enabled=%d, int_enabled=%d\n",
2199    //         line,state,~nimbus_drives.reg410_in,HDC_INT_TRIGGER,(~nimbus_drives.reg410_in & HDC_INT_TRIGGER),HDC_IRQ_ENABLED(),HDC_DRQ_ENABLED());
2200        if (state==0)
2201        {
2202            if(HDC_IRQ_ENABLED() && ((~nimbus_drives.reg410_in & HDC_INT_TRIGGER)==HDC_INT_TRIGGER))
2203                generate_disk_int(device->machine);
2204   
2205            if((nimbus_drives.reg410_in & HDC_CD_MASK)==HDC_CD_MASK)
2206            {   
2207                nimbus_drives.drq_ff=1;
2208                hdc_drq(device->machine);
2209            }
2210        }
2211        else
2212            set_scsi_line(device,SCSI_LINE_ACK,1);
2213    }
2214}
2215
20862216/* 8031/8051 Peripheral controler 80186 side */
20872217
20882218#define REG_0C2_INIT        1
r7051r7052
21362266    if(LOG_PC8031_186)
21372267        logerror("Nimbus PCIOR %08X read of %04X returns %02X reg0C2_ptr=%02X\n",pc,(offset*2)+0xC0,result,reg0C2_ptr);
21382268   
2139    dump_pcregs();
2269    if(LOG_PC8031_186)
2270        dump_pcregs();
21402271   
21412272    return result;
21422273}
src/mess/mess.mak
r7051r7052
470470   $(MESS_MACHINE)/pcf8593.o   \
471471   $(MESS_MACHINE)/rp5c01a.o   \
472472   $(MESS_MACHINE)/rp5c15.o   \
473    $(MESS_MACHINE)/scsibus.o   \
473474   $(MESS_MACHINE)/serial.o   \
474475   $(MESS_MACHINE)/smartmed.o   \
475476   $(MESS_MACHINE)/smc92x4.o   \
src/mess/drivers/rmnimbus.c
r7051r7052
1212#include "cpu/i86/i86.h"
1313#include "cpu/mcs51/mcs51.h"
1414#include "devices/flopdrv.h"
15#include "devices/harddriv.h"
1516#include "devices/messram.h"
1617#include "formats/flopimg.h"
1718#include "formats/pc_dsk.h"
1819#include "includes/rmnimbus.h"
1920#include "machine/er59256.h"
21#include "machine/scsi.h"
22#include "machine/scsibus.h"
2023#include "machine/z80sio.h"
2124#include "sound/ay8910.h"
2225#include "sound/msm5205.h"
r7051r7052
7578   MSM5205_S48_4B      /* 8 kHz */
7679};
7780
81static const SCSIConfigTable nimbus_scsi_dev_table =
82{
83   1,                                      /* 1 SCSI device */
84   {
85      { SCSI_ID_0, HARDDISK0_TAG, SCSI_DEVICE_HARDDISK },
86   }
87};
7888
89
90static const SCSIBus_interface scsibus_config =
91{
92    &nimbus_scsi_dev_table,
93    &nimbus_scsi_linechange
94};
95
7996static ADDRESS_MAP_START(nimbus_mem, ADDRESS_SPACE_PROGRAM, 16)
8097    AM_RANGE( 0x00000, 0xEFFFF ) AM_RAM
8198    AM_RANGE( 0xF0000, 0xFFFFF ) AM_ROM
r7051r7052
88105    AM_RANGE( 0X00c0, 0X00cf) AM_READWRITE8( pc8031_r, pc8031_w, 0x00FF)
89106    AM_RANGE( 0X00e0, 0X00ef) AM_READWRITE8( sound_ay8910_r, sound_ay8910_w, 0x00FF)
90107    AM_RANGE( 0X00f0, 0X00f7) AM_DEVREADWRITE8( Z80SIO_TAG, sio_r, sio_w, 0x00FF)
91    AM_RANGE( 0x0400, 0x041f) AM_READWRITE8( nimbus_fdc_r, nimbus_fdc_w, 0x00FF)
108    AM_RANGE( 0x0400, 0x041f) AM_READWRITE8( nimbus_disk_r, nimbus_disk_w, 0x00FF)
92109   AM_RANGE( 0xff00, 0xffff) AM_READWRITE( i186_internal_port_r, i186_internal_port_w)/* CPU 80186         */
93110ADDRESS_MAP_END
94111
r7051r7052
269286    MDRV_VIDEO_RESET(nimbus)
270287
271288
289    /* Backing storage */
272290   MDRV_WD2793_ADD(FDC_TAG, nimbus_wd17xx_interface )
273291   MDRV_FLOPPY_4_DRIVES_ADD(nimbus_floppy_config)
274292   
293    MDRV_HARDDISK_ADD(HARDDISK0_TAG)
294    MDRV_SCSIBUS_ADD(SCSIBUS_TAG, scsibus_config)
295   
275296    MDRV_RAM_ADD("messram")
276297   MDRV_RAM_DEFAULT_SIZE("512K")
277298   MDRV_RAM_EXTRA_OPTIONS("1024K,1536K")

Previous 15994 Revisions Next


© 1998-2018 The MESS Team