Changeset 517
- Timestamp:
- Jul 16, 2010, 6:13:04 AM (15 years ago)
- Location:
- GPL/branches/uniaud32-2.1.x
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
GPL/branches/uniaud32-2.1.x/alsa-kernel/pci/hda/hda_intel.c
r514 r517 2799 2799 { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, 2800 2800 /* NVIDIA MCP */ 2801 #if 1 /* DAZ kludge for NVidia until PCI_ANY_ID is fixed */2802 { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA },2803 { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA },2804 { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA },2805 { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA },2806 { PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA },2807 { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },2808 { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },2809 { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },2810 { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },2811 { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },2812 { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },2813 { PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA },2814 { PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA },2815 { PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA },2816 { PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA },2817 { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },2818 { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },2819 { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },2820 { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA },2821 { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA },2822 { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA },2823 { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },2824 #else2825 2801 { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), 2826 2802 .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, 2827 2803 .class_mask = 0xffffff, 2828 2804 .driver_data = AZX_DRIVER_NVIDIA }, 2829 #endif2830 2805 /* Teradici */ 2831 2806 { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, -
GPL/branches/uniaud32-2.1.x/lib32/ossidc.cpp
r516 r517 104 104 OSSRET OSS32_Initialize(void) 105 105 { 106 short sI ;106 short sI, iTmp; 107 107 108 108 fStrategyInit = TRUE; … … 145 145 if (cardcalls[sI].cinitcall == NULL) continue; 146 146 if (*cardcalls[sI].cinitcall == NULL) continue; 147 if ((*cardcalls[sI].cinitcall)() == 0) fnCardExitCall[nrCardsDetected] = *cardcalls[sI].cexitcall; 147 iTmp = (*cardcalls[sI].cinitcall)(); 148 if (iTmp <= 0) continue; 149 while (iTmp) { 150 fnCardExitCall[nrCardsDetected++] = *cardcalls[sI].cexitcall; 151 iTmp--; 152 if (nrCardsDetected >= OSS32_MAX_AUDIOCARDS) break; 153 } 148 154 if (nrCardsDetected >= OSS32_MAX_AUDIOCARDS) break; 149 155 } -
GPL/branches/uniaud32-2.1.x/lib32/pci.c
r516 r517 47 47 struct pci_bus pci_busses[MAX_PCI_BUSSES] = {0}; 48 48 49 BOOL 49 BOOL fSuspended = FALSE; 50 50 extern int nrCardsDetected; 51 51 52 52 53 #define PCI_CONFIG_ENABLE 54 #define PCI_CONFIG_ADDRESS 55 #define PCI_CONFIG_DATA 53 #define PCI_CONFIG_ENABLE 0x80000000 54 #define PCI_CONFIG_ADDRESS 0xCF8 55 #define PCI_CONFIG_DATA 0xCFC 56 56 57 57 #ifdef ACPI … … 61 61 //****************************************************************************** 62 62 #define CONFIG_CMD(dev, where) \ 63 63 (PCI_CONFIG_ENABLE | (dev->bus->number<<16) | (dev->devfn<<8) | (where & ~3)) 64 64 //****************************************************************************** 65 65 int pci_read_config_byte(struct pci_dev *dev, int where, u8 *value) 66 66 { 67 68 69 67 outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS); 68 *value = inb(PCI_CONFIG_DATA + (where&3)); 69 return PCIBIOS_SUCCESSFUL; 70 70 } 71 71 //****************************************************************************** … … 73 73 int pci_read_config_word(struct pci_dev *dev, int where, u16 *value) 74 74 { 75 76 77 75 outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS); 76 *value = inw(PCI_CONFIG_DATA + (where&2)); 77 return PCIBIOS_SUCCESSFUL; 78 78 } 79 79 //****************************************************************************** … … 81 81 int pci_read_config_dword(struct pci_dev *dev, int where, u32 *value) 82 82 { 83 84 85 83 outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS); 84 *value = inl(PCI_CONFIG_DATA); 85 return PCIBIOS_SUCCESSFUL; 86 86 } 87 87 //****************************************************************************** … … 89 89 int pci_write_config_byte(struct pci_dev *dev, int where, u8 value) 90 90 { 91 92 93 91 outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS); 92 outb(value, PCI_CONFIG_DATA + (where&3)); 93 return PCIBIOS_SUCCESSFUL; 94 94 } 95 95 //****************************************************************************** … … 97 97 int pci_write_config_word(struct pci_dev *dev, int where, u16 value) 98 98 { 99 100 101 99 outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS); 100 outw(value, PCI_CONFIG_DATA + (where&2)); 101 return PCIBIOS_SUCCESSFUL; 102 102 } 103 103 //****************************************************************************** … … 105 105 int pci_write_config_dword(struct pci_dev *dev, int where, u32 value) 106 106 { 107 108 109 107 outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS); 108 outl(value, PCI_CONFIG_DATA); 109 return PCIBIOS_SUCCESSFUL; 110 110 } 111 111 //****************************************************************************** … … 113 113 int pcidev_prepare(struct pci_dev *dev) 114 114 { 115 116 115 dprintf(("pcidev_prepare %x not implemented", dev)); 116 return 1; //todo: correct return value?? 117 117 } 118 118 //****************************************************************************** … … 120 120 int pcidev_activate(struct pci_dev *dev) 121 121 { 122 123 122 dprintf(("pcidev_activate %x not implemented", dev)); 123 return 1; //todo: correct return value?? 124 124 } 125 125 //****************************************************************************** … … 127 127 int pcidev_deactivate(struct pci_dev *dev) 128 128 { 129 130 129 dprintf(("pcidev_deactivate %x not implemented", dev)); 130 return 1; //todo: correct return value?? 131 131 } 132 132 … … 138 138 struct SaveIRQForSlot 139 139 { 140 141 142 143 140 ULONG ulSlotNo; 141 BYTE LowIRQ; 142 BYTE HighIRQ; 143 BYTE Pin; 144 144 }; 145 145 extern struct SaveIRQForSlot sISRHigh[]; 146 extern int 146 extern int SaveIRQCounter; 147 147 #endif 148 148 149 static int pci_query_device(unsigned int vendor, unsigned int device, 150 struct pci_dev near *pcidev, int idx)151 { 152 int resNo, addr, found = 0;153 u32 devNr, busNr, funcNr, detectedId, pciId, cfgaddrreg, temp, temp2;149 //Find the next matching PCI device starting with the device specified by pcidev 150 static ULONG pci_query_device(const struct pci_device_id *id_table, struct pci_dev near *pcidev, ULONG ulLast) 151 { 152 int resNo, addr; 153 u32 devNr, busNr, funcNr, detectedId, cfgaddrreg, temp, temp2; 154 154 #ifdef ACPI 155 APIRETrc;156 ULONGtemp1,temp3; //PS++155 APIRET rc; 156 ULONG temp1,temp3; //PS++ 157 157 #endif 158 u8 headerType; 159 160 pciId = (device << 16) | vendor; 161 162 cfgaddrreg = inl(PCI_CONFIG_ADDRESS); 163 for(busNr=0;busNr<MAX_PCI_BUSSES;busNr++) //BusNumber<255 164 { 165 for(devNr=0;devNr<32;devNr++) 166 { 167 for(funcNr=0;funcNr<8;funcNr++) 168 { 169 headerType = 0; 170 temp = PCI_CONFIG_ENABLE | (busNr<<16) | (devNr<<11) | (funcNr<<8); 171 outl(temp, PCI_CONFIG_ADDRESS); 172 detectedId = inl(PCI_CONFIG_DATA); 173 if( detectedId != 0xffffffff ) 174 { 175 outl(temp | (PCI_HEADER_TYPE & ~3), PCI_CONFIG_ADDRESS); 176 headerType = inb(PCI_CONFIG_DATA + (PCI_HEADER_TYPE & 3)); 177 } 178 // printk("det: %x (%x), need: %x\n", detectedId, headerType, pciId); 179 180 if( detectedId == pciId && 181 (headerType & 0x7f) == PCI_HEADER_TYPE_NORMAL ) 182 { 183 if( found++ == idx ) 184 { 185 memset((void near *)pcidev, 0, sizeof(struct pci_dev)); 186 187 pcidev->vendor = vendor; 188 pcidev->device = device; 189 pcidev->bus = &pci_busses[busNr]; 190 pcidev->bus->number = busNr; 191 pcidev->devfn = (devNr << 3) | funcNr; 192 pcidev->hdr_type = headerType & 0x7f; 193 194 pcidev->prepare = pcidev_prepare; 195 pcidev->activate = pcidev_activate; 196 pcidev->deactivate = pcidev_deactivate; 197 pcidev->active = 1; 198 pcidev->ro = 0; 199 pcidev->sibling = NULL; 200 pcidev->next = NULL; 201 pcidev->dma_mask = 0xFFFFFFFF; 202 203 // Subsystem ID 204 pci_read_config_word(pcidev, PCI_SUBSYSTEM_VENDOR_ID, 205 &pcidev->subsystem_vendor); 206 pci_read_config_word(pcidev, PCI_SUBSYSTEM_ID, 207 &pcidev->subsystem_device); 208 209 // I/O and MEM 210 resNo = 0; 211 for( addr = PCI_BASE_ADDRESS_0; addr <= PCI_BASE_ADDRESS_5; addr += 4 ) 212 { 213 pci_read_config_dword(pcidev, addr, &temp); 214 if( temp != 0 && temp != 0xffffffff ) 215 { 216 pci_write_config_dword(pcidev, addr, 0xffffffff); 217 pci_read_config_dword(pcidev, addr, &temp2); 218 pci_write_config_dword(pcidev, addr, temp); 219 220 if( temp & PCI_BASE_ADDRESS_SPACE_IO ) 221 { 222 pcidev->resource[resNo].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; 223 pcidev->resource[resNo].start = temp & PCI_BASE_ADDRESS_IO_MASK; 224 pcidev->resource[resNo].end = pcidev->resource[resNo].start + 225 ~(temp2 & PCI_BASE_ADDRESS_IO_MASK) + 1; 226 } 227 else 228 { 229 pcidev->resource[resNo].flags = IORESOURCE_MEM | IORESOURCE_MEM_WRITEABLE; 230 pcidev->resource[resNo].start = temp & PCI_BASE_ADDRESS_MEM_MASK; 231 pcidev->resource[resNo].end = pcidev->resource[resNo].start + 232 ~(temp2 & PCI_BASE_ADDRESS_MEM_MASK) + 1; 233 } 234 235 resNo++; 236 237 } 238 } 239 240 // IRQ and PIN 241 pci_read_config_dword(pcidev, PCI_INTERRUPT_LINE, &temp); 158 u8 headerType; 159 160 busNr = (ulLast >> 8) & 0x1f; 161 devNr = PCI_SLOT(ulLast); 162 funcNr = PCI_FUNC(ulLast); 163 if (ulLast) funcNr++; 164 165 cfgaddrreg = inl(PCI_CONFIG_ADDRESS); 166 for(;busNr<MAX_PCI_BUSSES;busNr++) { //BusNumber<255 167 for(;devNr<32;devNr++) { 168 for(;funcNr<8;funcNr++) { 169 headerType = 0; 170 temp = PCI_CONFIG_ENABLE | (busNr<<16) | (devNr<<11) | (funcNr<<8); 171 outl(temp, PCI_CONFIG_ADDRESS); 172 detectedId = inl(PCI_CONFIG_DATA); 173 174 if ( detectedId == 0xffffffff ) { 175 if ( funcNr == 0 ) break; /* if func 0 isn't there, the others aren't either */ 176 continue; 177 } 178 179 outl(temp + PCI_CLASS_REVISION, PCI_CONFIG_ADDRESS); 180 temp2 = inl(PCI_CONFIG_DATA) >> 8; /* get class */ 181 182 //dprintf(("det=%x(%x) %x need=%x%x %x", detectedId, headerType, temp2, id_table->device&0xffff, id_table->vendor, id_table->class)); 183 184 if ( id_table->class ) { 185 if ( (temp2 & id_table->class_mask) != id_table->class ) continue; 186 } else { 187 if ( (id_table->device == PCI_ANY_ID) && ((temp2 >> 8) != PCI_CLASS_MULTIMEDIA_AUDIO) ) continue; 188 } 189 190 if (id_table->vendor != (detectedId & 0xffff)) continue; 191 if ( (id_table->device != PCI_ANY_ID) && (id_table->device != (detectedId >> 16)) ) continue; 192 193 outl(temp | (PCI_HEADER_TYPE & ~3), PCI_CONFIG_ADDRESS); 194 headerType = inb(PCI_CONFIG_DATA + (PCI_HEADER_TYPE & 3)); 195 196 if ( (headerType & 0x7f) != PCI_HEADER_TYPE_NORMAL ) continue; 197 198 memset((void near *)pcidev, 0, sizeof(struct pci_dev)); 199 200 pcidev->vendor = detectedId & 0xffff; 201 pcidev->device = detectedId >> 16; 202 pcidev->bus = &pci_busses[busNr]; 203 pcidev->bus->number = busNr; 204 pcidev->devfn = PCI_DEVFN(devNr, funcNr); 205 pcidev->hdr_type = headerType & 0x7f; 206 207 pcidev->prepare = pcidev_prepare; 208 pcidev->activate = pcidev_activate; 209 pcidev->deactivate = pcidev_deactivate; 210 pcidev->active = 1; 211 pcidev->ro = 0; 212 pcidev->sibling = NULL; 213 pcidev->next = NULL; 214 pcidev->dma_mask = 0xFFFFFFFF; 215 216 // Subsystem ID 217 pci_read_config_word(pcidev, PCI_SUBSYSTEM_VENDOR_ID, &pcidev->subsystem_vendor); 218 pci_read_config_word(pcidev, PCI_SUBSYSTEM_ID, &pcidev->subsystem_device); 219 220 // I/O and MEM 221 resNo = 0; 222 for( addr = PCI_BASE_ADDRESS_0; addr <= PCI_BASE_ADDRESS_5; addr += 4 ) { 223 pci_read_config_dword(pcidev, addr, &temp); 224 if( temp != 0 && temp != 0xffffffff ) { 225 pci_write_config_dword(pcidev, addr, 0xffffffff); 226 pci_read_config_dword(pcidev, addr, &temp2); 227 pci_write_config_dword(pcidev, addr, temp); 228 229 if( temp & PCI_BASE_ADDRESS_SPACE_IO ) { 230 pcidev->resource[resNo].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; 231 pcidev->resource[resNo].start = temp & PCI_BASE_ADDRESS_IO_MASK; 232 pcidev->resource[resNo].end = pcidev->resource[resNo].start + 233 ~(temp2 & PCI_BASE_ADDRESS_IO_MASK) + 1; 234 } 235 else 236 { 237 pcidev->resource[resNo].flags = IORESOURCE_MEM | IORESOURCE_MEM_WRITEABLE; 238 pcidev->resource[resNo].start = temp & PCI_BASE_ADDRESS_MEM_MASK; 239 pcidev->resource[resNo].end = pcidev->resource[resNo].start + 240 ~(temp2 & PCI_BASE_ADDRESS_MEM_MASK) + 1; 241 } 242 243 resNo++; 244 245 } 246 } 247 248 // IRQ and PIN 249 pci_read_config_dword(pcidev, PCI_INTERRUPT_LINE, &temp); 242 250 #ifdef ACPI 243 sISRHigh[SaveIRQCounter].Pin = (temp >> 8) & 0xf; 244 temp2 = temp3 = 0; 245 rc = ACPIFindPCIDevice( (ULONG)busNr, // Bus 246 (ULONG)devNr, // Dev 247 (ULONG)(pcidev->devfn >> 8) & 7, // Function 248 &temp1, // PIC IRQ 249 &temp3, // APIC IRQ 250 NULL, // ACPI handle to finding device 251 "Uniaud32"); // Name for acpi log 252 if (!rc) 253 { 254 // Check APIC IRQ, if we have /SMP /APIC, must be set 255 if (temp1) 256 temp = (temp & (~0xff)) | (temp1 & 0xff); 257 // Check PIC IRQ 258 else if (temp3) 259 temp = (temp & (~0xff)) | (temp3 & 0xff); 260 dprintf(("pci_query_device: IRQs ACPI PIC%d APIC%d", temp1, temp3)); 261 sISRHigh[SaveIRQCounter].LowIRQ = temp1; 262 sISRHigh[SaveIRQCounter].HighIRQ = temp3; 263 } 251 sISRHigh[SaveIRQCounter].Pin = (temp >> 8) & 0xf; 252 temp2 = temp3 = 0; 253 rc = ACPIFindPCIDevice( (ULONG)busNr, // Bus 254 (ULONG)devNr, // Dev 255 (ULONG)(pcidev->devfn >> 8) & 7, // Function 256 &temp1, // PIC IRQ 257 &temp3, // APIC IRQ 258 NULL, // ACPI handle to finding device 259 "Uniaud32"); // Name for acpi log 260 if (!rc) { 261 // Check APIC IRQ, if we have /SMP /APIC, must be set 262 if (temp1) temp = (temp & (~0xff)) | (temp1 & 0xff); 263 // Check PIC IRQ 264 else if (temp3) temp = (temp & (~0xff)) | (temp3 & 0xff); 265 dprintf(("pci_query_device: IRQs ACPI PIC%d APIC%d", temp1, temp3)); 266 sISRHigh[SaveIRQCounter].LowIRQ = temp1; 267 sISRHigh[SaveIRQCounter].HighIRQ = temp3; 268 } 264 269 #endif /* ACPI */ 265 if( (u8)temp && (u8)temp != 0xff ) 266 { 267 pcidev->irq_resource[0].flags = IORESOURCE_IRQ; 268 pcidev->irq_resource[0].start = 269 pcidev->irq_resource[0].end = temp & 0xffff; 270 pcidev->irq = (u8)temp; 271 } 272 273 return 1; 274 } 275 } 276 277 // don't need to check more, if function 0 not present or single 278 if( funcNr == 0 && !(headerType & 0x80) ) break; 279 } 280 } 281 } 282 outl(cfgaddrreg, PCI_CONFIG_ADDRESS); 283 return 0; 284 285 } 286 287 //****************************************************************************** 288 //****************************************************************************** 270 if( (u8)temp && (u8)temp != 0xff ) { 271 pcidev->irq_resource[0].flags = IORESOURCE_IRQ; 272 pcidev->irq_resource[0].start = pcidev->irq_resource[0].end = temp & 0xffff; 273 pcidev->irq = (u8)temp; 274 } 275 276 return (0x8000 | (busNr << 8) | PCI_DEVFN(devNr, funcNr)); 277 } /* for funcNr */ 278 funcNr = 0; 279 } /* for devNr */ 280 devNr = 0; 281 } 282 outl(cfgaddrreg, PCI_CONFIG_ADDRESS); 283 return 0; 284 } 285 286 //****************************************************************************** 287 //****************************************************************************** 288 // Called from: 289 //if from==NULL search pci bus 290 //if from!=NULL only search already found devices starting with from 289 291 struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from) 290 292 { 291 int i, idx; 292 293 if((int)from < 8) { 294 idx = (int)from; // dirty hack 295 // return 0; 296 } else 297 idx = 0; 298 299 for(i=0;i<MAX_PCI_DEVICES;i++) 300 { 301 if(pci_devices[i].devfn == 0) 302 { 303 if( pci_query_device(vendor, device, (struct pci_dev near *)&pci_devices[i], idx) ) 304 return &pci_devices[i]; 305 else 306 break; 307 } 308 } 309 310 return NULL; 293 int i; 294 struct pci_device_id id_table; 295 296 for(i=0;i<MAX_PCI_DEVICES;i++) { 297 if ( pci_devices[i].devfn && (pci_devices[i].vendor == vendor) && (pci_devices[i].device == device) ) return &pci_devices[i]; 298 } 299 300 for(i=0;i<MAX_PCI_DEVICES;i++) { 301 if(pci_devices[i].devfn == 0) { 302 memset(&id_table, 0, sizeof(id_table)); 303 id_table.vendor = vendor; 304 id_table.device = device; 305 if( pci_query_device(&id_table, (struct pci_dev near *)&pci_devices[i], 0) ) return &pci_devices[i]; 306 else break; 307 } 308 } 309 310 return NULL; 311 311 } 312 312 //****************************************************************************** 313 313 //****************************************************************************** 314 314 struct resource * __request_region(struct resource *a, unsigned long start, 315 316 { 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 resource->name= name;336 337 resource->end= start + n; // - 1;338 339 340 341 342 343 344 345 346 315 unsigned long n, const char *name) 316 { 317 struct resource *resource; 318 319 if(a->flags & IORESOURCE_MEM) { 320 if(RMRequestMem(/*hResMgr,*/ start, n) == FALSE) { 321 printk("RMRequestIO failed for io %x, length %x\n", start, n); 322 return NULL; 323 } 324 } 325 else if(a->flags & IORESOURCE_IO) { 326 if(RMRequestIO(/*hResMgr,*/ start, n) == FALSE) { 327 printk("RMRequestIO failed for io %x, length %x\n", start, n); 328 return NULL; 329 } 330 } 331 332 resource = kmalloc(sizeof(struct resource), GFP_KERNEL); 333 if (resource == NULL) 334 return NULL; 335 resource->name = name; 336 resource->start = start; 337 resource->end = start + n; // - 1; 338 resource->flags = a->flags; 339 resource->parent = 340 resource->child = NULL; 341 342 // insert in list 343 resource->sibling = a->sibling; 344 a->sibling = resource; 345 346 return resource; 347 347 } 348 348 //****************************************************************************** 349 349 //****************************************************************************** 350 350 void __release_region(struct resource *a, 351 352 { 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 351 unsigned long start, unsigned long n) 352 { 353 struct resource *resource; 354 struct resource **ppres = &a->sibling; 355 unsigned long end = start + n; // - 1; 356 357 while( *ppres ) 358 { 359 resource = *ppres; 360 361 if( resource->start == start && resource->end == end ) 362 { 363 // remove from list 364 *ppres = resource->sibling; 365 kfree(resource); 366 return; 367 } 368 369 ppres = &resource->sibling; 370 } 371 371 } 372 372 //****************************************************************************** … … 374 374 int pci_get_flags (struct pci_dev *dev, int n_base) 375 375 { 376 377 378 379 380 376 if(n_base >= DEVICE_COUNT_RESOURCE || !dev->resource[n_base].flags) { 377 DebugInt3(); 378 return 0; 379 } 380 return dev->resource[n_base].flags; 381 381 } 382 382 //****************************************************************************** … … 384 384 int pcibios_present(void) 385 385 { 386 387 386 printk("pcibios_present -> pretend BIOS present\n"); 387 return 1; 388 388 } 389 389 //****************************************************************************** … … 391 391 struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn) 392 392 { 393 394 395 393 printk("pci_find_slot %d %x not implemented!!\n", bus, devfn); 394 DebugInt3(); 395 return NULL; 396 396 } 397 397 //****************************************************************************** … … 399 399 int pci_dma_supported(struct pci_dev *dev, unsigned long mask) 400 400 { 401 402 401 printk("pci_dma_supported: return TRUE\n"); 402 return 1; 403 403 } 404 404 //****************************************************************************** … … 406 406 int pci_find_capability(struct pci_dev *dev, int cap) 407 407 { 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 408 u16 status; 409 u8 pos, id; 410 int ttl = 48; 411 412 pci_read_config_word(dev, PCI_STATUS, &status); 413 if (!(status & PCI_STATUS_CAP_LIST)) 414 return 0; 415 pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos); 416 while (ttl-- && pos >= 0x40) { 417 pos &= ~3; 418 pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id); 419 if (id == 0xff) 420 break; 421 if (id == cap) 422 return pos; 423 pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos); 424 } 425 return 0; 426 426 } 427 427 //****************************************************************************** 428 428 /* 429 * 430 * 431 * 429 * Set power management state of a device. For transitions from state D3 430 * it isn't as straightforward as one could assume since many devices forget 431 * their configuration space during wakeup. Returns old power state. 432 432 */ 433 433 //****************************************************************************** 434 434 int pci_set_power_state(struct pci_dev *dev, int new_state) 435 435 { 436 437 438 u8pci_latency, pci_cacheline;439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 436 u32 base[5], romaddr; 437 u16 pci_command, pwr_command; 438 u8 pci_latency, pci_cacheline; 439 int i, old_state; 440 int pm = pci_find_capability(dev, PCI_CAP_ID_PM); 441 442 if (!pm) 443 return 0; 444 pci_read_config_word(dev, pm + PCI_PM_CTRL, &pwr_command); 445 old_state = pwr_command & PCI_PM_CTRL_STATE_MASK; 446 if (old_state == new_state) 447 return old_state; 448 if (old_state == 3) { 449 pci_read_config_word(dev, PCI_COMMAND, &pci_command); 450 pci_write_config_word(dev, PCI_COMMAND, pci_command & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)); 451 for (i = 0; i < 5; i++) 452 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, &base[i]); 453 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &romaddr); 454 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); 455 pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_cacheline); 456 pci_write_config_word(dev, pm + PCI_PM_CTRL, new_state); 457 for (i = 0; i < 5; i++) 458 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, base[i]); 459 pci_write_config_dword(dev, PCI_ROM_ADDRESS, romaddr); 460 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); 461 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cacheline); 462 pci_write_config_byte(dev, PCI_LATENCY_TIMER, pci_latency); 463 pci_write_config_word(dev, PCI_COMMAND, pci_command); 464 } else 465 pci_write_config_word(dev, pm + PCI_PM_CTRL, (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | new_state); 466 return old_state; 467 467 } 468 468 //****************************************************************************** 469 469 /* 470 * 471 * 472 * 470 * Initialize device before it's used by a driver. Ask low-level code 471 * to enable I/O and memory. Wake up the device if it was suspended. 472 * Beware, this function can fail. 473 473 */ 474 474 //****************************************************************************** 475 475 int pci_enable_device(struct pci_dev *dev) 476 476 { 477 478 479 480 481 482 483 484 477 u16 pci_command; 478 479 printk("pci_enable_device %x\n", dev); 480 481 pci_read_config_word(dev, PCI_COMMAND, &pci_command); 482 pci_write_config_word(dev, PCI_COMMAND, pci_command | (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)); 483 pci_set_power_state(dev, 0); 484 return 0; 485 485 } 486 486 //****************************************************************************** … … 488 488 int pci_register_driver(struct pci_driver *driver) 489 489 { 490 int i, j, dev_num; 491 struct pci_dev *pcidev; 492 493 for( i = 0; driver->id_table[i].vendor; i++) 494 { 495 dev_num = 0; 496 while( (pcidev = pci_find_device(driver->id_table[i].vendor, 497 driver->id_table[i].device, 498 (struct pci_dev *)dev_num)) != NULL ) 499 { 500 RMInit(); 501 if( driver->probe) { 502 printk("found: %x, id: %x idx %i\n",driver->id_table[i].vendor, driver->id_table[i].device, dev_num); 503 504 if(driver->probe(pcidev, &driver->id_table[i]) == 0) { 505 pcidev->pcidriver = (void *)driver; 506 pcidev->current_state = 4; 507 508 // create adapter 509 RMDone((driver->id_table[i].device << 16) | driver->id_table[i].vendor); 510 nrCardsDetected++; 511 } 512 else pcidev->devfn = 0; 513 } 514 515 RMDone(0); 516 517 dev_num++; 518 519 } 520 } 521 if (nrCardsDetected >=1) 522 return 1; 523 524 return 0; 490 int iTableIx, iNumCards, iTmp; 491 ULONG ulLast; 492 struct pci_dev *pcidev; 493 494 if (!driver->probe) return 0; 495 496 iNumCards = 0; 497 ulLast = 0; 498 pcidev=&pci_devices[0]; 499 500 for( iTableIx = 0; driver->id_table[iTableIx].vendor; iTableIx++) { 501 502 if (pcidev->devfn) { /* find an empty slot */ 503 for (iTmp=0; iTmp<MAX_PCI_DEVICES; iTmp++) { 504 if (pci_devices[iTmp].devfn == 0) break; 505 } 506 if (iTmp >= MAX_PCI_DEVICES) break; 507 pcidev=&pci_devices[iTmp]; 508 } 509 510 511 while( (ulLast = pci_query_device(&driver->id_table[iTableIx], pcidev, ulLast)) ) { 512 RMInit(); 513 dprintf(("pci_register_driver: found=%x:%x searching for %x:%x\n", 514 pcidev->vendor, pcidev->device, driver->id_table[iTableIx].vendor, driver->id_table[iTableIx].device)); 515 516 if(driver->probe(pcidev, &driver->id_table[iTableIx]) == 0) { 517 pcidev->pcidriver = (void *)driver; 518 pcidev->current_state = 4; 519 520 // create adapter 521 RMDone((pcidev->device << 16) | pcidev->vendor); 522 iNumCards++; 523 } else pcidev->devfn = 0; 524 525 RMDone(0); 526 } 527 } 528 529 return iNumCards; 525 530 } 526 531 //****************************************************************************** … … 528 533 int pci_module_init(struct pci_driver *drv) 529 534 { 530 int res = pci_register_driver(drv); 531 if (res < 0) 532 return res; 533 if (res == 0) 534 return -ENODEV; 535 return 0; 535 int res = pci_register_driver(drv); 536 if (res == 0) return -ENODEV; 537 return res; 536 538 } 537 539 //****************************************************************************** … … 539 541 int pci_unregister_driver(struct pci_driver *driver) 540 542 { 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 543 struct pci_dev *pcidev; 544 int i = 0, j; 545 546 while(driver->id_table[i].vendor) 547 { 548 for(j=0;j<MAX_PCI_DEVICES;j++) 549 { 550 if(pci_devices[j].vendor == driver->id_table[i].vendor && 551 pci_devices[j].device == driver->id_table[i].device) 552 { 553 if(driver->remove) { 554 driver->remove(&pci_devices[j]); 555 } 556 } 557 } 558 i++; 559 } 560 return 0; 559 561 } 560 562 //****************************************************************************** … … 562 564 void pci_set_master(struct pci_dev *dev) 563 565 { 564 565 566 567 568 569 570 571 572 566 u16 cmd; 567 568 pci_read_config_word(dev, PCI_COMMAND, &cmd); 569 if (! (cmd & PCI_COMMAND_MASTER)) { 570 dprintf(("pci_set_master %x", dev)); 571 cmd |= PCI_COMMAND_MASTER; 572 pci_write_config_word(dev, PCI_COMMAND, cmd); 573 } 574 return; 573 575 } 574 576 //****************************************************************************** … … 577 579 struct pm_dev *pm_register(pm_dev_t type, unsigned long id, pm_callback callback) 578 580 { 579 580 581 581 dprintf(("pm_register STUB")); 582 DebugInt3(); 583 return NULL; 582 584 } 583 585 //****************************************************************************** … … 586 588 void pm_unregister(struct pm_dev *dev) 587 589 { 588 590 dprintf(("pm_unregister STUB")); 589 591 } 590 592 //****************************************************************************** … … 592 594 int __compat_get_order(unsigned long size) 593 595 { 594 595 596 597 598 599 600 601 602 596 int order; 597 598 size = (size-1) >> (PAGE_SHIFT-1); 599 order = -1; 600 do { 601 size >>= 1; 602 order++; 603 } while (size); 604 return order; 603 605 } 604 606 //****************************************************************************** 605 607 //****************************************************************************** 606 608 void *pci_alloc_consistent(struct pci_dev *hwdev, 607 608 { 609 610 611 609 long size, dma_addr_t *dma_handle) 610 { 611 void *ret = NULL; 612 int gfp = GFP_ATOMIC; 613 int order; 612 614 #ifdef DEBUG 613 615 dprintf(("pci_alloc_consistent %d mask %x", size, (hwdev) ? hwdev->dma_mask : 0)); 614 616 #endif 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 617 if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) { 618 //try not to exhaust low memory (< 16mb) so allocate from the high region first 619 //if that doesn't satisfy the dma mask requirement, then get it from the low 620 //regino anyway 621 if(hwdev->dma_mask > 0x00ffffff) { 622 order = __compat_get_order(size); 623 ret = (void *)__get_free_pages(gfp|GFP_DMAHIGHMEM, order); 624 *dma_handle = virt_to_bus(ret); 625 if(*dma_handle > hwdev->dma_mask) { 626 free_pages((unsigned long)ret, __compat_get_order(size)); 627 //be sure and allocate below 16 mb 628 gfp |= GFP_DMA; 629 ret = NULL; 630 } 631 } 632 else { //must always allocate below 16 mb 633 gfp |= GFP_DMA; 634 } 635 } 636 if(ret == NULL) { 637 ret = (void *)__get_free_pages(gfp, __compat_get_order(size)); 638 } 639 640 if (ret != NULL) { 641 memset(ret, 0, size); 642 *dma_handle = virt_to_bus(ret); 643 } 644 return ret; 643 645 } 644 646 //****************************************************************************** 645 647 //****************************************************************************** 646 648 void pci_free_consistent(struct pci_dev *hwdev, long size, 647 648 { 649 649 void *vaddr, dma_addr_t dma_handle) 650 { 651 free_pages((unsigned long)vaddr, __compat_get_order(size)); 650 652 } 651 653 //****************************************************************************** … … 653 655 void pci_set_driver_data (struct pci_dev *dev, void *driver_data) 654 656 { 655 656 657 if (dev) 658 dev->driver_data = driver_data; 657 659 } 658 660 //****************************************************************************** … … 660 662 void *pci_get_driver_data (struct pci_dev *dev) 661 663 { 662 663 664 664 if (dev) 665 return dev->driver_data; 666 return 0; 665 667 } 666 668 //****************************************************************************** … … 668 670 unsigned long pci_get_dma_mask (struct pci_dev *dev) 669 671 { 670 671 672 672 if (dev) 673 return dev->dma_mask; 674 return 0; 673 675 } 674 676 //****************************************************************************** … … 676 678 int release_resource(struct resource *newres) 677 679 { 678 680 return 0; 679 681 } 680 682 … … 683 685 int pci_set_latency_time(struct pci_dev *dev, int latency) 684 686 { 685 686 687 pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); 688 return 0; 687 689 } 688 690 … … 699 701 int pci_orig_save_state(struct pci_dev *dev, u32 *buffer) 700 702 { 701 702 703 704 705 706 707 703 int i; 704 if (buffer) { 705 /* XXX: 100% dword access ok here? */ 706 for (i = 0; i < 16; i++) 707 pci_read_config_dword(dev, i * 4,&buffer[i]); 708 } 709 return 0; 708 710 } 709 711 … … 717 719 pci_orig_restore_state(struct pci_dev *dev, u32 *buffer) 718 720 { 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 721 int i; 722 723 if (buffer) { 724 for (i = 0; i < 16; i++) 725 pci_write_config_dword(dev,i * 4, buffer[i]); 726 } 727 /* 728 * otherwise, write the context information we know from bootup. 729 * This works around a problem where warm-booting from Windows 730 * combined with a D3(hot)->D0 transition causes PCI config 731 * header data to be forgotten. 732 */ 733 else { 734 for (i = 0; i < 6; i ++) 735 pci_write_config_dword(dev, 736 PCI_BASE_ADDRESS_0 + (i * 4), 737 dev->resource[i].start); 738 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); 739 } 740 return 0; 739 741 } 740 742 741 743 struct saved_config_tbl { 742 743 744 struct pci_dev *pci; 745 u32 config[16]; 744 746 }; 745 747 static struct saved_config_tbl saved_tbl[16]; … … 747 749 int pci_save_state(struct pci_dev *pci) 748 750 { 749 750 751 752 753 754 755 756 757 758 759 751 int i; 752 /* FIXME: mutex needed for race? */ 753 for (i = 0; i < ARRAY_SIZE(saved_tbl); i++) { 754 if (! saved_tbl[i].pci) { 755 saved_tbl[i].pci = pci; 756 pci_orig_save_state(pci, saved_tbl[i].config); 757 return 1; 758 } 759 } 760 printk(KERN_DEBUG "snd: no pci config space found!\n"); 761 return 0; 760 762 } 761 763 762 764 int pci_restore_state(struct pci_dev *pci) 763 765 { 764 765 766 767 768 769 770 771 772 773 774 766 int i; 767 /* FIXME: mutex needed for race? */ 768 for (i = 0; i < ARRAY_SIZE(saved_tbl); i++) { 769 if (saved_tbl[i].pci == pci) { 770 saved_tbl[i].pci = NULL; 771 pci_orig_restore_state(pci, saved_tbl[i].config); 772 return 0; 773 } 774 } 775 printk(KERN_DEBUG "snd: no saved pci config!\n"); 776 return 1; 775 777 } 776 778 777 779 void pci_disable_device(struct pci_dev *dev) 778 780 { 779 780 781 782 783 784 785 781 u16 pci_command; 782 783 pci_read_config_word(dev, PCI_COMMAND, &pci_command); 784 if (pci_command & PCI_COMMAND_MASTER) { 785 pci_command &= ~PCI_COMMAND_MASTER; 786 pci_write_config_word(dev, PCI_COMMAND, pci_command); 787 } 786 788 } 787 789 788 790 int pci_request_region(struct pci_dev *pdev, int bar, char *res_name) 789 791 { 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 792 int flags; 793 794 if (pci_resource_len(pdev, bar) == 0) 795 return 0; 796 flags = pci_get_flags(pdev, bar); 797 if (flags & IORESOURCE_IO) { 798 if (check_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar))) 799 goto err_out; 800 request_region(pci_resource_start(pdev, bar), 801 pci_resource_len(pdev, bar), res_name); 802 } 803 else if (flags & IORESOURCE_MEM) { 804 if (check_mem_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar))) 805 goto err_out; 806 request_mem_region(pci_resource_start(pdev, bar), 807 pci_resource_len(pdev, bar), res_name); 808 } 809 810 return 0; 809 811 810 812 err_out: 811 812 813 814 815 816 813 printk(KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n", 814 flags & IORESOURCE_IO ? "I/O" : "mem", 815 bar + 1, /* PCI BAR # */ 816 pci_resource_len(pdev, bar), pci_resource_start(pdev, bar), 817 res_name); 818 return -EBUSY; 817 819 } 818 820 819 821 void pci_release_region(struct pci_dev *pdev, int bar) 820 822 { 821 822 823 824 825 826 827 828 829 830 831 832 833 823 int flags; 824 825 if (pci_resource_len(pdev, bar) == 0) 826 return; 827 flags = pci_get_flags(pdev, bar); 828 if (flags & IORESOURCE_IO) { 829 release_region(pci_resource_start(pdev, bar), 830 pci_resource_len(pdev, bar)); 831 } 832 else if (flags & IORESOURCE_MEM) { 833 release_mem_region(pci_resource_start(pdev, bar), 834 pci_resource_len(pdev, bar)); 835 } 834 836 } 835 837 836 838 int pci_request_regions(struct pci_dev *pdev, char *res_name) 837 839 { 838 839 840 841 842 843 844 845 846 847 840 int i; 841 842 for (i = 0; i < 6; i++) 843 if (pci_request_region(pdev, i, res_name)) 844 goto err; 845 return 0; 846 err: 847 while (--i >= 0) 848 pci_release_region(pdev, i); 849 return -EBUSY; 848 850 } 849 851 850 852 void pci_release_regions(struct pci_dev *pdev) 851 853 { 852 853 854 854 int i; 855 for (i = 0; i < 6; i++) 856 pci_release_region(pdev, i); 855 857 } 856 858 857 859 const struct pci_device_id * pci_match_device(const struct pci_device_id *ids, struct pci_dev *dev) 858 860 { 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 861 u16 subsystem_vendor, subsystem_device; 862 863 pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); 864 pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &subsystem_device); 865 866 while (ids->vendor || ids->subvendor || ids->class_mask) { 867 if ((ids->vendor == PCI_ANY_ID || ids->vendor == dev->vendor) && 868 (ids->device == PCI_ANY_ID || ids->device == dev->device) && 869 (ids->subvendor == PCI_ANY_ID || ids->subvendor == subsystem_vendor) && 870 (ids->subdevice == PCI_ANY_ID || ids->subdevice == subsystem_device) && 871 !((ids->class ^ dev->_class) & ids->class_mask)) 872 return ids; 873 ids++; 874 } 875 return NULL; 874 876 } 875 877 876 878 int snd_pci_dev_present(const struct pci_device_id *ids) 877 879 { 878 879 880 881 882 883 880 while (ids->vendor || ids->subvendor) { 881 if (pci_find_device(ids->vendor, ids->subvendor, NULL)) 882 return 1; 883 ids++; 884 } 885 return 0; 884 886 } 885 887 886 888 struct pci_driver_mapping { 887 888 889 890 891 889 struct pci_dev *dev; 890 struct pci_driver *drv; 891 unsigned long dma_mask; 892 void *driver_data; 893 u32 saved_config[16]; 892 894 }; 893 895 … … 898 900 static struct pci_driver_mapping *get_pci_driver_mapping(struct pci_dev *dev) 899 901 { 900 901 902 903 904 905 902 int i; 903 904 for (i = 0; i < PCI_MAX_MAPPINGS; i++) 905 if (drvmap[i].dev == dev) 906 return &drvmap[i]; 907 return NULL; 906 908 } 907 909 908 910 struct pci_driver *snd_pci_compat_get_pci_driver(struct pci_dev *dev) 909 911 { 910 911 912 913 912 struct pci_driver_mapping *map = get_pci_driver_mapping(dev); 913 if (map) 914 return map->drv; 915 return NULL; 914 916 } 915 917 #if 0 916 918 void * pci_get_drvdata (struct pci_dev *dev) 917 919 { 918 919 920 921 920 struct pci_driver_mapping *map = get_pci_driver_mapping(dev); 921 if (map) 922 return map->driver_data; 923 return NULL; 922 924 } 923 925 … … 925 927 void pci_set_drvdata (struct pci_dev *dev, void *driver_data) 926 928 { 927 928 929 929 struct pci_driver_mapping *map = get_pci_driver_mapping(dev); 930 if (map) 931 map->driver_data = driver_data; 930 932 } 931 933 #endif … … 936 938 OSSRET OSS32_APMResume() 937 939 { 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 940 int i; 941 struct pci_driver *driver; 942 943 dprintf(("OSS32_APMResume")); 944 945 fSuspended = FALSE; 946 947 for(i=0;i<MAX_PCI_DEVICES;i++) 948 { 949 if(pci_devices[i].devfn) 950 { 951 driver = pci_devices[i].pcidriver; 952 if(driver && driver->resume) { 953 driver->resume(&pci_devices[i]); 954 } 955 } 956 } 957 958 return OSSERR_SUCCESS; 957 959 } 958 960 //****************************************************************************** … … 960 962 OSSRET OSS32_APMSuspend() 961 963 { 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 } 982 964 int i; 965 struct pci_driver *driver; 966 967 dprintf(("OSS32_APMSuspend")); 968 969 fSuspended = TRUE; 970 971 for(i=0;i<MAX_PCI_DEVICES;i++) 972 { 973 if(pci_devices[i].devfn) 974 { 975 driver = pci_devices[i].pcidriver; 976 if(driver && driver->suspend) { 977 driver->suspend(&pci_devices[i], SNDRV_CTL_POWER_D3cold); 978 } 979 } 980 } 981 982 return OSSERR_SUCCESS; 983 } 984 -
GPL/branches/uniaud32-2.1.x/uniaud.inc
r516 r517 13 13 # ex RC3 GA FIXPACK2 beta_47 14 14 # Comment out to avoid a fixpack line in bldlevel 15 FIXPACK = BETA SVNr51 615 FIXPACK = BETA SVNr517 16 16 17 17 # ALSA BUILD VERSION
Note:
See TracChangeset
for help on using the changeset viewer.