/[gxemul]/trunk/src/devices/dev_sgi_ip32.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_sgi_ip32.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 12 by dpavlin, Mon Oct 8 16:18:38 2007 UTC revision 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_sgi_ip32.c,v 1.29 2005/08/13 08:25:48 debug Exp $   *  $Id: dev_sgi_ip32.c,v 1.34 2005/10/27 14:01:14 debug Exp $
29   *     *  
30   *  SGI IP32 devices.   *  SGI IP32 devices.
31   *   *
# Line 110  int dev_crime_access(struct cpu *cpu, st Line 110  int dev_crime_access(struct cpu *cpu, st
110          uint64_t relative_addr, unsigned char *data, size_t len,          uint64_t relative_addr, unsigned char *data, size_t len,
111          int writeflag, void *extra)          int writeflag, void *extra)
112  {  {
         int i;  
113          struct crime_data *d = extra;          struct crime_data *d = extra;
114          uint64_t idata;          uint64_t idata = 0;
115            int i;
116    
117          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
118                    idata = memory_readmax64(cpu, data, len);
119    
120          /*          /*
121           *  Set crime version/revision:           *  Set crime version/revision:
122           *           *
123           *  This might not be the most elegant or correct solution,           *  This might not be the most elegant or correct solution, but it
124           *  but it seems that the IP32 PROM likes 0x11 for machines           *  seems that the IP32 PROM likes 0x11 for machines without graphics,
125           *  without graphics, and 0xa1 for machines with graphics.           *  and 0xa1 for machines with graphics.
          *  
          *  NetBSD 2.0 complains about "unknown" crime for 0x11,  
          *  but I guess that's something one has to live with.  
126           *           *
127           *  (TODO?)           *  NetBSD 2.0 complains about "unknown" crime for 0x11, but I guess
128             *  that's something one has to live with.  (TODO?)
129           */           */
130          d->reg[4] = 0x00; d->reg[5] = 0x00; d->reg[6] = 0x00;          d->reg[4] = 0x00; d->reg[5] = 0x00; d->reg[6] = 0x00;
131          d->reg[7] = d->use_fb? 0xa1 : 0x11;          d->reg[7] = d->use_fb? 0xa1 : 0x11;
# Line 344  int dev_macepci_access(struct cpu *cpu, Line 343  int dev_macepci_access(struct cpu *cpu,
343          uint64_t idata = 0, odata=0;          uint64_t idata = 0, odata=0;
344          int regnr, res = 1;          int regnr, res = 1;
345    
346          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
347                    idata = memory_readmax64(cpu, data, len);
348    
349          regnr = relative_addr / sizeof(uint32_t);          regnr = relative_addr / sizeof(uint32_t);
350    
351          /*  Read from/write to the macepci:  */          /*  Read from/write to the macepci:  */
# Line 775  int dev_sgi_mec_access(struct cpu *cpu, Line 776  int dev_sgi_mec_access(struct cpu *cpu,
776          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
777          int regnr;          int regnr;
778    
779          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
780                    idata = memory_readmax64(cpu, data, len);
781    
782          regnr = relative_addr / sizeof(uint64_t);          regnr = relative_addr / sizeof(uint64_t);
783    
784          /*  Treat most registers as read/write, by default.  */          /*  Treat most registers as read/write, by default.  */
# Line 1037  void dev_sgi_ust_init(struct memory *mem Line 1040  void dev_sgi_ust_init(struct memory *mem
1040   *  memory. Used by (at least) the SGI O2 PROM.   *  memory. Used by (at least) the SGI O2 PROM.
1041   *   *
1042   *  Actually, it seems to be used for graphics output as well. (?)   *  Actually, it seems to be used for graphics output as well. (?)
1043   *  TODO: Run the O2's prom and try to figure out what it really does.   *  The O2's PROM uses it to output graphics.
1044   */   */
1045  /*  #define debug fatal  */  /*  #define debug fatal  */
1046    /*  #define MTE_DEBUG  */
1047  #define ZERO_CHUNK_LEN          4096  #define ZERO_CHUNK_LEN          4096
1048    
1049  struct sgi_mte_data {  struct sgi_mte_data {
1050          uint64_t        reg[DEV_SGI_MTE_LENGTH / sizeof(uint64_t)];          uint32_t        reg[DEV_SGI_MTE_LENGTH / sizeof(uint32_t)];
1051  };  };
1052    
1053  /*  /*
# Line 1060  int dev_sgi_mte_access(struct cpu *cpu, Line 1064  int dev_sgi_mte_access(struct cpu *cpu,
1064          int regnr;          int regnr;
1065    
1066          idata = memory_readmax64(cpu, data, len);          idata = memory_readmax64(cpu, data, len);
1067          regnr = relative_addr / sizeof(uint64_t);          regnr = relative_addr / sizeof(uint32_t);
1068    
1069            /*
1070             *  Treat all registers as read/write, by default.  Sometimes these
1071             *  are accessed as 32-bit words, sometimes as 64-bit words.
1072             */
1073            if (len != 4) {
1074                    if (writeflag == MEM_WRITE) {
1075                            d->reg[regnr] = idata >> 32;
1076                            d->reg[regnr+1] = idata;
1077                    } else
1078                            odata = ((uint64_t)d->reg[regnr] << 32) +
1079                                d->reg[regnr+1];
1080            }
1081    
         /*  Treat all registers as read/write, by default.  */  
1082          if (writeflag == MEM_WRITE)          if (writeflag == MEM_WRITE)
1083                  d->reg[regnr] = idata;                  d->reg[regnr] = idata;
1084          else          else
1085                  odata = d->reg[regnr];                  odata = d->reg[regnr];
1086    
1087    #ifdef MTE_DEBUG
1088            if (writeflag == MEM_WRITE && relative_addr >= 0x2000 &&
1089                relative_addr < 0x3000)
1090                    fatal("[ MTE: 0x%08x: 0x%016llx ]\n", (int)relative_addr,
1091                        (long long)idata);
1092    #endif
1093    
1094          /*          /*
1095           *  I've not found any docs about this 'mte' device at all, so this is           *  I've not found any docs about this 'mte' device at all, so this is
1096           *  just a guess. The mte seems to be used for copying and zeroing           *  just a guess. The mte seems to be used for copying and zeroing
1097           *  chunks of memory.           *  chunks of memory.
1098           *           *
1099           *  [ sgi_mte: unimplemented write to address 0x3030, data=0x00000000003da000 ]  <-- first address           *   write to 0x3030, data=0x00000000003da000 ]  <-- first address
1100           *  [ sgi_mte: unimplemented write to address 0x3038, data=0x00000000003f9fff ]  <-- last address           *   write to 0x3038, data=0x00000000003f9fff ]  <-- last address
1101           *  [ sgi_mte: unimplemented write to address 0x3018, data=0x0000000000000000 ]  <-- what to fill?           *   write to 0x3018, data=0x0000000000000000 ]  <-- what to fill?
1102           *  [ sgi_mte: unimplemented write to address 0x3008, data=0x00000000ffffffff ]  <-- ?           *   write to 0x3008, data=0x00000000ffffffff ]  <-- ?
1103           *  [ sgi_mte: unimplemented write to address 0x3800, data=0x0000000000000011 ]  <-- operation (0x11 = zerofill)           *   write to 0x3800, data=0x0000000000000011 ]  <-- operation
1104             *                                                   (0x11 = zerofill)
1105           *           *
1106           *  [ sgi_mte: unimplemented write to address 0x1700, data=0x80001ea080001ea1 ]  <-- also containing the address to fill (?)           *   write to 0x1700, data=0x80001ea080001ea1  <-- also containing the
1107           *  [ sgi_mte: unimplemented write to address 0x1708, data=0x80001ea280001ea3 ]           *   write to 0x1708, data=0x80001ea280001ea3      address to fill (?)
1108           *  [ sgi_mte: unimplemented write to address 0x1710, data=0x80001ea480001ea5 ]           *   write to 0x1710, data=0x80001ea480001ea5
1109           *  ...           *  ...
1110           *  [ sgi_mte: unimplemented write to address 0x1770, data=0x80001e9c80001e9d ]           *   write to 0x1770, data=0x80001e9c80001e9d
1111           *  [ sgi_mte: unimplemented write to address 0x1778, data=0x80001e9e80001e9f ]           *   write to 0x1778, data=0x80001e9e80001e9f
1112           */           */
1113          switch (relative_addr) {          switch (relative_addr) {
1114    
# Line 1115  int dev_sgi_mte_access(struct cpu *cpu, Line 1139  int dev_sgi_mte_access(struct cpu *cpu,
1139          case 0x1778:          case 0x1778:
1140                  break;                  break;
1141    
1142  #if 1          /*  Graphics stuff? No warning:  */
1143  case 0x2074:          case 0x2018:
1144  {          case 0x2060:
1145  /*  This seems to have to do with graphical output:          case 0x2070:
1146      0x000000000xxx0yyy  where x is usually 0..1279 and y is 0..1023?  */          case 0x2074:
1147  /*  Gaaah...  */          case 0x20c0:
1148          int x = (idata >> 16) & 0xfff;          case 0x20c4:
1149          int y = idata & 0xfff;          case 0x20d0:
1150          int addr;          case 0x21b0:
1151  unsigned char buf[3];          case 0x21b8:
1152          printf("x = %i, y = %i\n", x, y);                  break;
1153  buf[0] = buf[1] = buf[2] = random() | 0x80;  
1154  addr = (x/2 + (y/2)*640) * 3;          /*  Perform graphics operation:  */
1155  if (x < 640 && y < 480)          case 0x21f8:
1156  cpu->memory_rw(cpu, cpu->mem, 0x38000000 + addr,                  {
1157   buf, 3, MEM_WRITE, NO_EXCEPTIONS | PHYSICAL);                          uint32_t op = d->reg[0x2060 / sizeof(uint32_t)];
1158                            uint32_t color = d->reg[0x20d0 / sizeof(uint32_t)]&255;
1159                            uint32_t x1 = (d->reg[0x2070 / sizeof(uint32_t)]
1160                                >> 16) & 0xfff;
1161                            uint32_t y1 = d->reg[0x2070 / sizeof(uint32_t)]& 0xfff;
1162                            uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)]
1163                                >> 16) & 0xfff;
1164                            uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff;
1165                            int y;
1166    
1167                            op >>= 24;
1168    
1169                            switch (op) {
1170                            case 1: /*  Unknown. Used after drawing bitmaps?  */
1171                                    break;
1172                            case 3: /*  Fill:  */
1173                                    if (x2 < x1) {
1174                                            int tmp = x1; x1 = x2; x2 = tmp;
1175                                    }
1176                                    if (y2 < y1) {
1177                                            int tmp = y1; y1 = y2; y2 = tmp;
1178                                    }
1179                                    for (y=y1; y<=y2; y++) {
1180                                            unsigned char buf[1280];
1181                                            int length = x2-x1+1;
1182                                            int addr = (x1 + y*1280);
1183                                            if (length < 1)
1184                                                    length = 1;
1185                                            memset(buf, color, length);
1186                                            if (x1 < 1280 && y < 1024)
1187                                                    cpu->memory_rw(cpu, cpu->mem,
1188                                                        0x38000000 + addr, buf,
1189                                                        length, MEM_WRITE,
1190                                                        NO_EXCEPTIONS | PHYSICAL);
1191                                    }
1192                                    break;
1193    
1194                            default:fatal("\n--- MTE OP %i color 0x%02x: %i,%i - "
1195                                        "%i,%i\n\n", op, color, x1,y1, x2,y2);
1196                            }
1197                    }
1198                    break;
1199    
1200            case 0x29f0:
1201                    /*  Pixel output:  */
1202                    {
1203                            uint32_t data = d->reg[0x20c4 / sizeof(uint32_t)];
1204                            uint32_t color = d->reg[0x20d0 / sizeof(uint32_t)]&255;
1205                            uint32_t x1 = (d->reg[0x2070 / sizeof(uint32_t)]
1206                                >> 16) & 0xfff;
1207                            uint32_t y1 = d->reg[0x2070 / sizeof(uint32_t)]& 0xfff;
1208                            uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)]
1209                                >> 16) & 0xfff;
1210                            uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff;
1211                            int x,y;
1212                            if (x2 < x1) {
1213                                    int tmp = x1; x1 = x2; x2 = tmp;
1214                            }
1215                            if (y2 < y1) {
1216                                    int tmp = y1; y1 = y2; y2 = tmp;
1217                            }
1218                            if (x2-x1 <= 15)
1219                                    data <<= 16;
1220                            x=x1; y=y1;
1221                            while (x <= x2 && y <= y2) {
1222                                    unsigned char buf = color;
1223                                    int addr = x + y*1280;
1224                                    int bit_set = data & 0x80000000UL;
1225                                    data <<= 1;
1226                                    if (x < 1280 && y < 1024 && bit_set)
1227                                            cpu->memory_rw(cpu, cpu->mem,
1228                                                0x38000000 + addr, &buf,1,MEM_WRITE,
1229                                                NO_EXCEPTIONS | PHYSICAL);
1230                                    x++;
1231                                    if (x > x2) {
1232                                            x = x1;
1233                                            y++;
1234                                    }
1235                            }
1236                    }
1237                    break;
1238    
 }  
 break;  
 #endif  
1239    
1240          /*  Operations:  */          /*  Operations:  */
1241          case 0x3800:          case 0x3800:
1242                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
1243                          switch (idata) {                          switch (idata) {
1244                          case 0x11:              /*  zerofill  */                          case 0x11:              /*  zerofill  */
1245                                  first_addr = d->reg[0x3030 / sizeof(uint64_t)];                                  first_addr = d->reg[0x3030 / sizeof(uint32_t)];
1246                                  last_addr  = d->reg[0x3038 / sizeof(uint64_t)];                                  last_addr  = d->reg[0x3038 / sizeof(uint32_t)];
1247                                  zerobuflen = last_addr - first_addr + 1;                                  zerobuflen = last_addr - first_addr + 1;
1248                                  debug("[ sgi_mte: zerofill: first = 0x%016llx, last = 0x%016llx, length = 0x%llx ]\n",                                  debug("[ sgi_mte: zerofill: first = 0x%016llx,"
1249                                      (long long)first_addr, (long long)last_addr, (long long)zerobuflen);                                      " last = 0x%016llx, length = 0x%llx ]\n",
1250                                        (long long)first_addr, (long long)
1251                                        last_addr, (long long)zerobuflen);
1252    
1253                                  /*  TODO:  is there a better way to implement this?  */                                  /*  TODO:  is there a better way to
1254                                               implement this?  */
1255                                  memset(zerobuf, 0, sizeof(zerobuf));                                  memset(zerobuf, 0, sizeof(zerobuf));
1256                                  fill_addr = first_addr;                                  fill_addr = first_addr;
1257                                  while (zerobuflen != 0) {                                  while (zerobuflen != 0) {
# Line 1164  break; Line 1268  break;
1268    
1269                                  break;                                  break;
1270                          default:                          default:
1271                                  fatal("[ sgi_mte: UNKNOWN operation 0x%x ]\n", idata);                                  fatal("[ sgi_mte: UNKNOWN operation "
1272                                        "0x%x ]\n", idata);
1273                          }                          }
1274                  }                  }
1275                  break;                  break;
1276          default:          default:
1277                  if (writeflag == MEM_WRITE)                  if (writeflag == MEM_WRITE)
1278                          debug("[ sgi_mte: unimplemented write to address 0x%llx, data=0x%016llx ]\n", (long long)relative_addr, (long long)idata);                          debug("[ sgi_mte: unimplemented write to "
1279                                "address 0x%llx, data=0x%016llx ]\n",
1280                                (long long)relative_addr, (long long)idata);
1281                  else                  else
1282                          debug("[ sgi_mte: unimplemented read from address 0x%llx ]\n", (long long)relative_addr);                          debug("[ sgi_mte: unimplemented read from address"
1283                                " 0x%llx ]\n", (long long)relative_addr);
1284          }          }
1285    
1286          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)

Legend:
Removed from v.12  
changed lines
  Added in v.18

  ViewVC Help
Powered by ViewVC 1.1.26